Diffstat (limited to 'noncore/net/opierdesktop/orders.cpp') (more/less context) (show whitespace changes)
-rw-r--r-- | noncore/net/opierdesktop/orders.cpp | 940 |
1 files changed, 940 insertions, 0 deletions
diff --git a/noncore/net/opierdesktop/orders.cpp b/noncore/net/opierdesktop/orders.cpp new file mode 100644 index 0000000..194b043 --- a/dev/null +++ b/noncore/net/opierdesktop/orders.cpp | |||
@@ -0,0 +1,940 @@ | |||
1 | /* | ||
2 | rdesktop: A Remote Desktop Protocol client. | ||
3 | RDP order processing | ||
4 | Copyright (C) Matthew Chapman 1999-2002 | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include "rdesktop.h" | ||
22 | #include "orders.h" | ||
23 | |||
24 | extern uint8 *next_packet; | ||
25 | static RDP_ORDER_STATE order_state; | ||
26 | |||
27 | /* Read field indicating which parameters are present */ | ||
28 | static void | ||
29 | rdp_in_present(STREAM s, uint32 * present, uint8 flags, int size) | ||
30 | { | ||
31 | uint8 bits; | ||
32 | int i; | ||
33 | |||
34 | if (flags & RDP_ORDER_SMALL) | ||
35 | { | ||
36 | size--; | ||
37 | } | ||
38 | |||
39 | if (flags & RDP_ORDER_TINY) | ||
40 | { | ||
41 | if (size < 2) | ||
42 | size = 0; | ||
43 | else | ||
44 | size -= 2; | ||
45 | } | ||
46 | |||
47 | *present = 0; | ||
48 | for (i = 0; i < size; i++) | ||
49 | { | ||
50 | in_uint8(s, bits); | ||
51 | *present |= bits << (i * 8); | ||
52 | } | ||
53 | } | ||
54 | |||
55 | /* Read a co-ordinate (16-bit, or 8-bit delta) */ | ||
56 | static void | ||
57 | rdp_in_coord(STREAM s, sint16 * coord, BOOL delta) | ||
58 | { | ||
59 | sint8 change; | ||
60 | |||
61 | if (delta) | ||
62 | { | ||
63 | in_uint8(s, change); | ||
64 | *coord += change; | ||
65 | } | ||
66 | else | ||
67 | { | ||
68 | in_uint16_le(s, *coord); | ||
69 | } | ||
70 | } | ||
71 | |||
72 | /* Read a colour entry */ | ||
73 | static void | ||
74 | rdp_in_colour(STREAM s, uint32 * colour) | ||
75 | { | ||
76 | uint32 i; | ||
77 | in_uint8(s, i); | ||
78 | *colour = i; | ||
79 | in_uint8(s, i); | ||
80 | *colour |= i << 8; | ||
81 | in_uint8(s, i); | ||
82 | *colour |= i << 16; | ||
83 | } | ||
84 | |||
85 | /* Parse bounds information */ | ||
86 | static BOOL | ||
87 | rdp_parse_bounds(STREAM s, BOUNDS * bounds) | ||
88 | { | ||
89 | uint8 present; | ||
90 | |||
91 | in_uint8(s, present); | ||
92 | |||
93 | if (present & 1) | ||
94 | rdp_in_coord(s, &bounds->left, False); | ||
95 | else if (present & 16) | ||
96 | rdp_in_coord(s, &bounds->left, True); | ||
97 | |||
98 | if (present & 2) | ||
99 | rdp_in_coord(s, &bounds->top, False); | ||
100 | else if (present & 32) | ||
101 | rdp_in_coord(s, &bounds->top, True); | ||
102 | |||
103 | if (present & 4) | ||
104 | rdp_in_coord(s, &bounds->right, False); | ||
105 | else if (present & 64) | ||
106 | rdp_in_coord(s, &bounds->right, True); | ||
107 | |||
108 | if (present & 8) | ||
109 | rdp_in_coord(s, &bounds->bottom, False); | ||
110 | else if (present & 128) | ||
111 | rdp_in_coord(s, &bounds->bottom, True); | ||
112 | |||
113 | return s_check(s); | ||
114 | } | ||
115 | |||
116 | /* Parse a pen */ | ||
117 | static BOOL | ||
118 | rdp_parse_pen(STREAM s, PEN * pen, uint32 present) | ||
119 | { | ||
120 | if (present & 1) | ||
121 | in_uint8(s, pen->style); | ||
122 | |||
123 | if (present & 2) | ||
124 | in_uint8(s, pen->width); | ||
125 | |||
126 | if (present & 4) | ||
127 | rdp_in_colour(s, &pen->colour); | ||
128 | |||
129 | return s_check(s); | ||
130 | } | ||
131 | |||
132 | /* Parse a brush */ | ||
133 | static BOOL | ||
134 | rdp_parse_brush(STREAM s, BRUSH * brush, uint32 present) | ||
135 | { | ||
136 | if (present & 1) | ||
137 | in_uint8(s, brush->xorigin); | ||
138 | |||
139 | if (present & 2) | ||
140 | in_uint8(s, brush->yorigin); | ||
141 | |||
142 | if (present & 4) | ||
143 | in_uint8(s, brush->style); | ||
144 | |||
145 | if (present & 8) | ||
146 | in_uint8(s, brush->pattern[0]); | ||
147 | |||
148 | if (present & 16) | ||
149 | in_uint8a(s, &brush->pattern[1], 7); | ||
150 | |||
151 | return s_check(s); | ||
152 | } | ||
153 | |||
154 | /* Process a destination blt order */ | ||
155 | static void | ||
156 | process_destblt(STREAM s, DESTBLT_ORDER * os, uint32 present, BOOL delta) | ||
157 | { | ||
158 | if (present & 0x01) | ||
159 | rdp_in_coord(s, &os->x, delta); | ||
160 | |||
161 | if (present & 0x02) | ||
162 | rdp_in_coord(s, &os->y, delta); | ||
163 | |||
164 | if (present & 0x04) | ||
165 | rdp_in_coord(s, &os->cx, delta); | ||
166 | |||
167 | if (present & 0x08) | ||
168 | rdp_in_coord(s, &os->cy, delta); | ||
169 | |||
170 | if (present & 0x10) | ||
171 | in_uint8(s, os->opcode); | ||
172 | |||
173 | DEBUG(("DESTBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d)\n", | ||
174 | os->opcode, os->x, os->y, os->cx, os->cy)); | ||
175 | |||
176 | ui_destblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy); | ||
177 | } | ||
178 | |||
179 | /* Process a pattern blt order */ | ||
180 | static void | ||
181 | process_patblt(STREAM s, PATBLT_ORDER * os, uint32 present, BOOL delta) | ||
182 | { | ||
183 | if (present & 0x0001) | ||
184 | rdp_in_coord(s, &os->x, delta); | ||
185 | |||
186 | if (present & 0x0002) | ||
187 | rdp_in_coord(s, &os->y, delta); | ||
188 | |||
189 | if (present & 0x0004) | ||
190 | rdp_in_coord(s, &os->cx, delta); | ||
191 | |||
192 | if (present & 0x0008) | ||
193 | rdp_in_coord(s, &os->cy, delta); | ||
194 | |||
195 | if (present & 0x0010) | ||
196 | in_uint8(s, os->opcode); | ||
197 | |||
198 | if (present & 0x0020) | ||
199 | rdp_in_colour(s, &os->bgcolour); | ||
200 | |||
201 | if (present & 0x0040) | ||
202 | rdp_in_colour(s, &os->fgcolour); | ||
203 | |||
204 | rdp_parse_brush(s, &os->brush, present >> 7); | ||
205 | |||
206 | DEBUG(("PATBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,bs=%d,bg=0x%x,fg=0x%x)\n", os->opcode, os->x, | ||
207 | os->y, os->cx, os->cy, os->brush.style, os->bgcolour, os->fgcolour)); | ||
208 | |||
209 | ui_patblt(ROP2_P(os->opcode), os->x, os->y, os->cx, os->cy, | ||
210 | &os->brush, os->bgcolour, os->fgcolour); | ||
211 | } | ||
212 | |||
213 | /* Process a screen blt order */ | ||
214 | static void | ||
215 | process_screenblt(STREAM s, SCREENBLT_ORDER * os, uint32 present, BOOL delta) | ||
216 | { | ||
217 | if (present & 0x0001) | ||
218 | rdp_in_coord(s, &os->x, delta); | ||
219 | |||
220 | if (present & 0x0002) | ||
221 | rdp_in_coord(s, &os->y, delta); | ||
222 | |||
223 | if (present & 0x0004) | ||
224 | rdp_in_coord(s, &os->cx, delta); | ||
225 | |||
226 | if (present & 0x0008) | ||
227 | rdp_in_coord(s, &os->cy, delta); | ||
228 | |||
229 | if (present & 0x0010) | ||
230 | in_uint8(s, os->opcode); | ||
231 | |||
232 | if (present & 0x0020) | ||
233 | rdp_in_coord(s, &os->srcx, delta); | ||
234 | |||
235 | if (present & 0x0040) | ||
236 | rdp_in_coord(s, &os->srcy, delta); | ||
237 | |||
238 | DEBUG(("SCREENBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,srcx=%d,srcy=%d)\n", | ||
239 | os->opcode, os->x, os->y, os->cx, os->cy, os->srcx, os->srcy)); | ||
240 | |||
241 | ui_screenblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy, os->srcx, os->srcy); | ||
242 | } | ||
243 | |||
244 | /* Process a line order */ | ||
245 | static void | ||
246 | process_line(STREAM s, LINE_ORDER * os, uint32 present, BOOL delta) | ||
247 | { | ||
248 | if (present & 0x0001) | ||
249 | in_uint16_le(s, os->mixmode); | ||
250 | |||
251 | if (present & 0x0002) | ||
252 | rdp_in_coord(s, &os->startx, delta); | ||
253 | |||
254 | if (present & 0x0004) | ||
255 | rdp_in_coord(s, &os->starty, delta); | ||
256 | |||
257 | if (present & 0x0008) | ||
258 | rdp_in_coord(s, &os->endx, delta); | ||
259 | |||
260 | if (present & 0x0010) | ||
261 | rdp_in_coord(s, &os->endy, delta); | ||
262 | |||
263 | if (present & 0x0020) | ||
264 | rdp_in_colour(s, &os->bgcolour); | ||
265 | |||
266 | if (present & 0x0040) | ||
267 | in_uint8(s, os->opcode); | ||
268 | |||
269 | rdp_parse_pen(s, &os->pen, present >> 7); | ||
270 | |||
271 | DEBUG(("LINE(op=0x%x,sx=%d,sy=%d,dx=%d,dx=%d,fg=0x%x)\n", | ||
272 | os->opcode, os->startx, os->starty, os->endx, os->endy, os->pen.colour)); | ||
273 | |||
274 | if (os->opcode < 0x01 || os->opcode > 0x10) | ||
275 | { | ||
276 | error("bad ROP2 0x%x\n", os->opcode); | ||
277 | return; | ||
278 | } | ||
279 | |||
280 | ui_line(os->opcode - 1, os->startx, os->starty, os->endx, os->endy, &os->pen); | ||
281 | } | ||
282 | |||
283 | /* Process an opaque rectangle order */ | ||
284 | static void | ||
285 | process_rect(STREAM s, RECT_ORDER * os, uint32 present, BOOL delta) | ||
286 | { | ||
287 | uint32 i; | ||
288 | if (present & 0x01) | ||
289 | rdp_in_coord(s, &os->x, delta); | ||
290 | |||
291 | if (present & 0x02) | ||
292 | rdp_in_coord(s, &os->y, delta); | ||
293 | |||
294 | if (present & 0x04) | ||
295 | rdp_in_coord(s, &os->cx, delta); | ||
296 | |||
297 | if (present & 0x08) | ||
298 | rdp_in_coord(s, &os->cy, delta); | ||
299 | |||
300 | if (present & 0x10) | ||
301 | { | ||
302 | in_uint8(s, i); | ||
303 | os->colour = (os->colour & 0xffffff00) | i; | ||
304 | } | ||
305 | |||
306 | if (present & 0x20) | ||
307 | { | ||
308 | in_uint8(s, i); | ||
309 | os->colour = (os->colour & 0xffff00ff) | (i << 8); | ||
310 | } | ||
311 | |||
312 | if (present & 0x40) | ||
313 | { | ||
314 | in_uint8(s, i); | ||
315 | os->colour = (os->colour & 0xff00ffff) | (i << 16); | ||
316 | } | ||
317 | |||
318 | DEBUG(("RECT(x=%d,y=%d,cx=%d,cy=%d,fg=0x%x)\n", os->x, os->y, os->cx, os->cy, os->colour)); | ||
319 | |||
320 | ui_rect(os->x, os->y, os->cx, os->cy, os->colour); | ||
321 | } | ||
322 | |||
323 | /* Process a desktop save order */ | ||
324 | static void | ||
325 | process_desksave(STREAM s, DESKSAVE_ORDER * os, uint32 present, BOOL delta) | ||
326 | { | ||
327 | int width, height; | ||
328 | |||
329 | if (present & 0x01) | ||
330 | in_uint32_le(s, os->offset); | ||
331 | |||
332 | if (present & 0x02) | ||
333 | rdp_in_coord(s, &os->left, delta); | ||
334 | |||
335 | if (present & 0x04) | ||
336 | rdp_in_coord(s, &os->top, delta); | ||
337 | |||
338 | if (present & 0x08) | ||
339 | rdp_in_coord(s, &os->right, delta); | ||
340 | |||
341 | if (present & 0x10) | ||
342 | rdp_in_coord(s, &os->bottom, delta); | ||
343 | |||
344 | if (present & 0x20) | ||
345 | in_uint8(s, os->action); | ||
346 | |||
347 | DEBUG(("DESKSAVE(l=%d,t=%d,r=%d,b=%d,off=%d,op=%d)\n", | ||
348 | os->left, os->top, os->right, os->bottom, os->offset, os->action)); | ||
349 | |||
350 | width = os->right - os->left + 1; | ||
351 | height = os->bottom - os->top + 1; | ||
352 | |||
353 | if (os->action == 0) | ||
354 | ui_desktop_save(os->offset, os->left, os->top, width, height); | ||
355 | else | ||
356 | ui_desktop_restore(os->offset, os->left, os->top, width, height); | ||
357 | } | ||
358 | |||
359 | /* Process a memory blt order */ | ||
360 | static void | ||
361 | process_memblt(STREAM s, MEMBLT_ORDER * os, uint32 present, BOOL delta) | ||
362 | { | ||
363 | HBITMAP bitmap; | ||
364 | |||
365 | if (present & 0x0001) | ||
366 | { | ||
367 | in_uint8(s, os->cache_id); | ||
368 | in_uint8(s, os->colour_table); | ||
369 | } | ||
370 | |||
371 | if (present & 0x0002) | ||
372 | rdp_in_coord(s, &os->x, delta); | ||
373 | |||
374 | if (present & 0x0004) | ||
375 | rdp_in_coord(s, &os->y, delta); | ||
376 | |||
377 | if (present & 0x0008) | ||
378 | rdp_in_coord(s, &os->cx, delta); | ||
379 | |||
380 | if (present & 0x0010) | ||
381 | rdp_in_coord(s, &os->cy, delta); | ||
382 | |||
383 | if (present & 0x0020) | ||
384 | in_uint8(s, os->opcode); | ||
385 | |||
386 | if (present & 0x0040) | ||
387 | rdp_in_coord(s, &os->srcx, delta); | ||
388 | |||
389 | if (present & 0x0080) | ||
390 | rdp_in_coord(s, &os->srcy, delta); | ||
391 | |||
392 | if (present & 0x0100) | ||
393 | in_uint16_le(s, os->cache_idx); | ||
394 | |||
395 | DEBUG(("MEMBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d)\n", | ||
396 | os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id, os->cache_idx)); | ||
397 | |||
398 | bitmap = cache_get_bitmap(os->cache_id, os->cache_idx); | ||
399 | if (bitmap == NULL) | ||
400 | return; | ||
401 | |||
402 | ui_memblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy, bitmap, os->srcx, os->srcy); | ||
403 | } | ||
404 | |||
405 | /* Process a 3-way blt order */ | ||
406 | static void | ||
407 | process_triblt(STREAM s, TRIBLT_ORDER * os, uint32 present, BOOL delta) | ||
408 | { | ||
409 | HBITMAP bitmap; | ||
410 | |||
411 | if (present & 0x000001) | ||
412 | { | ||
413 | in_uint8(s, os->cache_id); | ||
414 | in_uint8(s, os->colour_table); | ||
415 | } | ||
416 | |||
417 | if (present & 0x000002) | ||
418 | rdp_in_coord(s, &os->x, delta); | ||
419 | |||
420 | if (present & 0x000004) | ||
421 | rdp_in_coord(s, &os->y, delta); | ||
422 | |||
423 | if (present & 0x000008) | ||
424 | rdp_in_coord(s, &os->cx, delta); | ||
425 | |||
426 | if (present & 0x000010) | ||
427 | rdp_in_coord(s, &os->cy, delta); | ||
428 | |||
429 | if (present & 0x000020) | ||
430 | in_uint8(s, os->opcode); | ||
431 | |||
432 | if (present & 0x000040) | ||
433 | rdp_in_coord(s, &os->srcx, delta); | ||
434 | |||
435 | if (present & 0x000080) | ||
436 | rdp_in_coord(s, &os->srcy, delta); | ||
437 | |||
438 | if (present & 0x000100) | ||
439 | rdp_in_colour(s, &os->bgcolour); | ||
440 | |||
441 | if (present & 0x000200) | ||
442 | rdp_in_colour(s, &os->fgcolour); | ||
443 | |||
444 | rdp_parse_brush(s, &os->brush, present >> 10); | ||
445 | |||
446 | if (present & 0x008000) | ||
447 | in_uint16_le(s, os->cache_idx); | ||
448 | |||
449 | if (present & 0x010000) | ||
450 | in_uint16_le(s, os->unknown); | ||
451 | |||
452 | DEBUG(("TRIBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d,bs=%d,bg=0x%x,fg=0x%x)\n", | ||
453 | os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id, os->cache_idx, | ||
454 | os->brush.style, os->bgcolour, os->fgcolour)); | ||
455 | |||
456 | bitmap = cache_get_bitmap(os->cache_id, os->cache_idx); | ||
457 | if (bitmap == NULL) | ||
458 | return; | ||
459 | |||
460 | ui_triblt(os->opcode, os->x, os->y, os->cx, os->cy, | ||
461 | bitmap, os->srcx, os->srcy, &os->brush, os->bgcolour, os->fgcolour); | ||
462 | } | ||
463 | |||
464 | /* Parse a delta co-ordinate in polyline order form */ | ||
465 | static int | ||
466 | parse_delta(uint8 * buffer, int *offset) | ||
467 | { | ||
468 | int value = buffer[(*offset)++]; | ||
469 | int two_byte = value & 0x80; | ||
470 | |||
471 | if (value & 0x40)/* sign bit */ | ||
472 | value |= ~0x3f; | ||
473 | else | ||
474 | value &= 0x3f; | ||
475 | |||
476 | if (two_byte) | ||
477 | value = (value << 8) | buffer[(*offset)++]; | ||
478 | |||
479 | return value; | ||
480 | } | ||
481 | |||
482 | /* Process a polyline order */ | ||
483 | static void | ||
484 | process_polyline(STREAM s, POLYLINE_ORDER * os, uint32 present, BOOL delta) | ||
485 | { | ||
486 | int index, line, data; | ||
487 | int x, y, xfrom, yfrom; | ||
488 | uint8 flags = 0; | ||
489 | PEN pen; | ||
490 | uint8 opcode; | ||
491 | |||
492 | if (present & 0x01) | ||
493 | rdp_in_coord(s, &os->x, delta); | ||
494 | |||
495 | if (present & 0x02) | ||
496 | rdp_in_coord(s, &os->y, delta); | ||
497 | |||
498 | if (present & 0x04) | ||
499 | in_uint8(s, os->opcode); | ||
500 | |||
501 | if (present & 0x10) | ||
502 | rdp_in_colour(s, &os->fgcolour); | ||
503 | |||
504 | if (present & 0x20) | ||
505 | in_uint8(s, os->lines); | ||
506 | |||
507 | if (present & 0x40) | ||
508 | { | ||
509 | in_uint8(s, os->datasize); | ||
510 | in_uint8a(s, os->data, os->datasize); | ||
511 | } | ||
512 | |||
513 | DEBUG(("POLYLINE(x=%d,y=%d,op=0x%x,fg=0x%x,n=%d,sz=%d)\n", | ||
514 | os->x, os->y, os->opcode, os->fgcolour, os->lines, os->datasize)); | ||
515 | |||
516 | DEBUG(("Data: ")); | ||
517 | |||
518 | for (index = 0; index < os->datasize; index++) | ||
519 | DEBUG(("%02x ", os->data[index])); | ||
520 | |||
521 | DEBUG(("\n")); | ||
522 | |||
523 | if (os->opcode < 0x01 || os->opcode > 0x10) | ||
524 | { | ||
525 | error("bad ROP2 0x%x\n", os->opcode); | ||
526 | return; | ||
527 | } | ||
528 | |||
529 | opcode = os->opcode - 1; | ||
530 | x = os->x; | ||
531 | y = os->y; | ||
532 | pen.style = pen.width = 0; | ||
533 | pen.colour = os->fgcolour; | ||
534 | |||
535 | index = 0; | ||
536 | data = ((os->lines - 1) / 4) + 1; | ||
537 | for (line = 0; (line < os->lines) && (data < os->datasize); line++) | ||
538 | { | ||
539 | xfrom = x; | ||
540 | yfrom = y; | ||
541 | |||
542 | if (line % 4 == 0) | ||
543 | flags = os->data[index++]; | ||
544 | |||
545 | if ((flags & 0xc0) == 0) | ||
546 | flags |= 0xc0;/* none = both */ | ||
547 | |||
548 | if (flags & 0x40) | ||
549 | x += parse_delta(os->data, &data); | ||
550 | |||
551 | if (flags & 0x80) | ||
552 | y += parse_delta(os->data, &data); | ||
553 | |||
554 | ui_line(opcode, xfrom, yfrom, x, y, &pen); | ||
555 | |||
556 | flags <<= 2; | ||
557 | } | ||
558 | } | ||
559 | |||
560 | /* Process a text order */ | ||
561 | static void | ||
562 | process_text2(STREAM s, TEXT2_ORDER * os, uint32 present, BOOL delta) | ||
563 | { | ||
564 | int i; | ||
565 | |||
566 | if (present & 0x000001) | ||
567 | in_uint8(s, os->font); | ||
568 | |||
569 | if (present & 0x000002) | ||
570 | in_uint8(s, os->flags); | ||
571 | |||
572 | if (present & 0x000004) | ||
573 | in_uint8(s, os->unknown); | ||
574 | |||
575 | if (present & 0x000008) | ||
576 | in_uint8(s, os->mixmode); | ||
577 | |||
578 | if (present & 0x000010) | ||
579 | rdp_in_colour(s, &os->fgcolour); | ||
580 | |||
581 | if (present & 0x000020) | ||
582 | rdp_in_colour(s, &os->bgcolour); | ||
583 | |||
584 | if (present & 0x000040) | ||
585 | in_uint16_le(s, os->clipleft); | ||
586 | |||
587 | if (present & 0x000080) | ||
588 | in_uint16_le(s, os->cliptop); | ||
589 | |||
590 | if (present & 0x000100) | ||
591 | in_uint16_le(s, os->clipright); | ||
592 | |||
593 | if (present & 0x000200) | ||
594 | in_uint16_le(s, os->clipbottom); | ||
595 | |||
596 | if (present & 0x000400) | ||
597 | in_uint16_le(s, os->boxleft); | ||
598 | |||
599 | if (present & 0x000800) | ||
600 | in_uint16_le(s, os->boxtop); | ||
601 | |||
602 | if (present & 0x001000) | ||
603 | in_uint16_le(s, os->boxright); | ||
604 | |||
605 | if (present & 0x002000) | ||
606 | in_uint16_le(s, os->boxbottom); | ||
607 | |||
608 | if (present & 0x004000) /* fix for connecting to a server that */ | ||
609 | in_uint8s(s, 10); /* was disconnected with mstsc.exe */ | ||
610 | /* 0x008000, 0x020000, and 0x040000 are present too ??? */ | ||
611 | |||
612 | if (present & 0x080000) | ||
613 | in_uint16_le(s, os->x); | ||
614 | |||
615 | if (present & 0x100000) | ||
616 | in_uint16_le(s, os->y); | ||
617 | |||
618 | if (present & 0x200000) | ||
619 | { | ||
620 | in_uint8(s, os->length); | ||
621 | in_uint8a(s, os->text, os->length); | ||
622 | } | ||
623 | |||
624 | DEBUG(("TEXT2(x=%d,y=%d,cl=%d,ct=%d,cr=%d,cb=%d,bl=%d,bt=%d,bb=%d,br=%d,fg=0x%x,bg=0x%x,font=%d,fl=0x%x,mix=%d,unk=0x%x,n=%d)\n", os->x, os->y, os->clipleft, os->cliptop, os->clipright, os->clipbottom, os->boxleft, os->boxtop, os->boxright, os->boxbottom, os->fgcolour, os->bgcolour, os->font, os->flags, os->mixmode, os->unknown, os->length)); | ||
625 | |||
626 | DEBUG(("Text: ")); | ||
627 | |||
628 | for (i = 0; i < os->length; i++) | ||
629 | DEBUG(("%02x ", os->text[i])); | ||
630 | |||
631 | DEBUG(("\n")); | ||
632 | |||
633 | ui_draw_text(os->font, os->flags, os->mixmode, os->x, os->y, | ||
634 | os->clipleft, os->cliptop, | ||
635 | os->clipright - os->clipleft, | ||
636 | os->clipbottom - os->cliptop, | ||
637 | os->boxleft, os->boxtop, | ||
638 | os->boxright - os->boxleft, | ||
639 | os->boxbottom - os->boxtop, os->bgcolour, os->fgcolour, os->text, os->length); | ||
640 | } | ||
641 | |||
642 | /* Process a raw bitmap cache order */ | ||
643 | static void | ||
644 | process_raw_bmpcache(STREAM s) | ||
645 | { | ||
646 | HBITMAP bitmap; | ||
647 | uint16 cache_idx, bufsize; | ||
648 | uint8 cache_id, width, height, bpp, Bpp; | ||
649 | uint8 *data, *inverted; | ||
650 | int y; | ||
651 | |||
652 | in_uint8(s, cache_id); | ||
653 | in_uint8s(s, 1);/* pad */ | ||
654 | in_uint8(s, width); | ||
655 | in_uint8(s, height); | ||
656 | in_uint8(s, bpp); | ||
657 | Bpp = (bpp + 7) / 8; | ||
658 | in_uint16_le(s, bufsize); | ||
659 | in_uint16_le(s, cache_idx); | ||
660 | in_uint8p(s, data, bufsize); | ||
661 | |||
662 | DEBUG(("RAW_BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n", width, height, cache_id, cache_idx)); | ||
663 | inverted = (uint8*)xmalloc(width * height * Bpp); | ||
664 | for (y = 0; y < height; y++) | ||
665 | { | ||
666 | memcpy(&inverted[(height - y - 1) * (width * Bpp)], &data[y * (width * Bpp)], | ||
667 | width * Bpp); | ||
668 | } | ||
669 | |||
670 | bitmap = ui_create_bitmap(width, height, inverted); | ||
671 | xfree(inverted); | ||
672 | cache_put_bitmap(cache_id, cache_idx, bitmap); | ||
673 | } | ||
674 | |||
675 | /* Process a bitmap cache order */ | ||
676 | static void | ||
677 | process_bmpcache(STREAM s) | ||
678 | { | ||
679 | HBITMAP bitmap; | ||
680 | uint16 cache_idx, size; | ||
681 | uint8 cache_id, width, height, bpp, Bpp; | ||
682 | uint8 *data, *bmpdata; | ||
683 | |||
684 | in_uint8(s, cache_id); | ||
685 | in_uint8s(s, 1);/* pad */ | ||
686 | in_uint8(s, width); | ||
687 | in_uint8(s, height); | ||
688 | in_uint8(s, bpp); | ||
689 | Bpp = (bpp + 7) / 8; | ||
690 | in_uint8s(s, 2);/* bufsize */ | ||
691 | in_uint16_le(s, cache_idx); | ||
692 | in_uint8s(s, 2);/* pad */ | ||
693 | in_uint16_le(s, size); | ||
694 | in_uint8s(s, 4);/* row_size, final_size */ | ||
695 | in_uint8p(s, data, size); | ||
696 | DEBUG(("BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n", width, height, cache_id, cache_idx)); | ||
697 | bmpdata = (uint8*)xmalloc(width * height * Bpp); | ||
698 | if (bitmap_decompress(bmpdata, width, height, data, size, Bpp)) | ||
699 | { | ||
700 | bitmap = ui_create_bitmap(width, height, bmpdata); | ||
701 | cache_put_bitmap(cache_id, cache_idx, bitmap); | ||
702 | } | ||
703 | xfree(bmpdata); | ||
704 | } | ||
705 | |||
706 | /* Process a colourmap cache order */ | ||
707 | static void | ||
708 | process_colcache(STREAM s) | ||
709 | { | ||
710 | COLOURENTRY *entry; | ||
711 | COLOURMAP map; | ||
712 | HCOLOURMAP hmap; | ||
713 | uint8 cache_id; | ||
714 | int i; | ||
715 | in_uint8(s, cache_id); | ||
716 | in_uint16_le(s, map.ncolours); | ||
717 | |||
718 | map.colours = (COLOURENTRY*)xmalloc(3 * map.ncolours); | ||
719 | |||
720 | for (i = 0; i < map.ncolours; i++) | ||
721 | { | ||
722 | entry = &map.colours[i]; | ||
723 | in_uint8(s, entry->blue); | ||
724 | in_uint8(s, entry->green); | ||
725 | in_uint8(s, entry->red); | ||
726 | in_uint8s(s, 1);/* pad */ | ||
727 | } | ||
728 | |||
729 | DEBUG(("COLCACHE(id=%d,n=%d)\n", cache_id, map.ncolours)); | ||
730 | |||
731 | hmap = ui_create_colourmap(&map); | ||
732 | ui_set_colourmap(hmap); | ||
733 | |||
734 | xfree(map.colours); | ||
735 | } | ||
736 | |||
737 | /* Process a font cache order */ | ||
738 | static void | ||
739 | process_fontcache(STREAM s) | ||
740 | { | ||
741 | HGLYPH bitmap; | ||
742 | uint8 font, nglyphs; | ||
743 | uint16 character, offset, baseline, width, height; | ||
744 | int i, datasize; | ||
745 | uint8 *data; | ||
746 | |||
747 | in_uint8(s, font); | ||
748 | in_uint8(s, nglyphs); | ||
749 | |||
750 | DEBUG(("FONTCACHE(font=%d,n=%d)\n", font, nglyphs)); | ||
751 | |||
752 | for (i = 0; i < nglyphs; i++) | ||
753 | { | ||
754 | in_uint16_le(s, character); | ||
755 | in_uint16_le(s, offset); | ||
756 | in_uint16_le(s, baseline); | ||
757 | in_uint16_le(s, width); | ||
758 | in_uint16_le(s, height); | ||
759 | |||
760 | datasize = (height * ((width + 7) / 8) + 3) & ~3; | ||
761 | in_uint8p(s, data, datasize); | ||
762 | |||
763 | bitmap = ui_create_glyph(width, height, data); | ||
764 | cache_put_font(font, character, offset, baseline, width, height, bitmap); | ||
765 | } | ||
766 | } | ||
767 | |||
768 | /* Process a secondary order */ | ||
769 | static void | ||
770 | process_secondary_order(STREAM s) | ||
771 | { | ||
772 | uint16 length; | ||
773 | uint8 type; | ||
774 | uint8 *next_order; | ||
775 | |||
776 | in_uint16_le(s, length); | ||
777 | in_uint8s(s, 2);/* flags */ | ||
778 | in_uint8(s, type); | ||
779 | |||
780 | next_order = s->p + length + 7; | ||
781 | |||
782 | switch (type) | ||
783 | { | ||
784 | case RDP_ORDER_RAW_BMPCACHE: | ||
785 | process_raw_bmpcache(s); | ||
786 | break; | ||
787 | |||
788 | case RDP_ORDER_COLCACHE: | ||
789 | process_colcache(s); | ||
790 | break; | ||
791 | |||
792 | case RDP_ORDER_BMPCACHE: | ||
793 | process_bmpcache(s); | ||
794 | break; | ||
795 | |||
796 | case RDP_ORDER_FONTCACHE: | ||
797 | process_fontcache(s); | ||
798 | break; | ||
799 | |||
800 | default: | ||
801 | unimpl("secondary order %d\n", type); | ||
802 | } | ||
803 | |||
804 | s->p = next_order; | ||
805 | } | ||
806 | |||
807 | /* Process an order PDU */ | ||
808 | void | ||
809 | process_orders(STREAM s) | ||
810 | { | ||
811 | RDP_ORDER_STATE *os = &order_state; | ||
812 | uint32 present; | ||
813 | uint16 num_orders; | ||
814 | uint8 order_flags; | ||
815 | int size, processed = 0; | ||
816 | BOOL delta; | ||
817 | |||
818 | in_uint8s(s, 2);/* pad */ | ||
819 | in_uint16_le(s, num_orders); | ||
820 | in_uint8s(s, 2);/* pad */ | ||
821 | |||
822 | while (processed < num_orders) | ||
823 | { | ||
824 | in_uint8(s, order_flags); | ||
825 | |||
826 | if (!(order_flags & RDP_ORDER_STANDARD)) | ||
827 | { | ||
828 | error("order parsing failed\n"); | ||
829 | break; | ||
830 | } | ||
831 | |||
832 | if (order_flags & RDP_ORDER_SECONDARY) | ||
833 | { | ||
834 | process_secondary_order(s); | ||
835 | } | ||
836 | else | ||
837 | { | ||
838 | if (order_flags & RDP_ORDER_CHANGE) | ||
839 | { | ||
840 | in_uint8(s, os->order_type); | ||
841 | } | ||
842 | |||
843 | switch (os->order_type) | ||
844 | { | ||
845 | case RDP_ORDER_TRIBLT: | ||
846 | case RDP_ORDER_TEXT2: | ||
847 | size = 3; | ||
848 | break; | ||
849 | |||
850 | case RDP_ORDER_PATBLT: | ||
851 | case RDP_ORDER_MEMBLT: | ||
852 | case RDP_ORDER_LINE: | ||
853 | size = 2; | ||
854 | break; | ||
855 | |||
856 | default: | ||
857 | size = 1; | ||
858 | } | ||
859 | |||
860 | rdp_in_present(s, &present, order_flags, size); | ||
861 | |||
862 | if (order_flags & RDP_ORDER_BOUNDS) | ||
863 | { | ||
864 | if (!(order_flags & RDP_ORDER_LASTBOUNDS)) | ||
865 | rdp_parse_bounds(s, &os->bounds); | ||
866 | |||
867 | ui_set_clip(os->bounds.left, | ||
868 | os->bounds.top, | ||
869 | os->bounds.right - | ||
870 | os->bounds.left + 1, | ||
871 | os->bounds.bottom - os->bounds.top + 1); | ||
872 | } | ||
873 | |||
874 | delta = order_flags & RDP_ORDER_DELTA; | ||
875 | |||
876 | switch (os->order_type) | ||
877 | { | ||
878 | case RDP_ORDER_DESTBLT: | ||
879 | process_destblt(s, &os->destblt, present, delta); | ||
880 | break; | ||
881 | |||
882 | case RDP_ORDER_PATBLT: | ||
883 | process_patblt(s, &os->patblt, present, delta); | ||
884 | break; | ||
885 | |||
886 | case RDP_ORDER_SCREENBLT: | ||
887 | process_screenblt(s, &os->screenblt, present, delta); | ||
888 | break; | ||
889 | |||
890 | case RDP_ORDER_LINE: | ||
891 | process_line(s, &os->line, present, delta); | ||
892 | break; | ||
893 | |||
894 | case RDP_ORDER_RECT: | ||
895 | process_rect(s, &os->rect, present, delta); | ||
896 | break; | ||
897 | |||
898 | case RDP_ORDER_DESKSAVE: | ||
899 | process_desksave(s, &os->desksave, present, delta); | ||
900 | break; | ||
901 | |||
902 | case RDP_ORDER_MEMBLT: | ||
903 | process_memblt(s, &os->memblt, present, delta); | ||
904 | break; | ||
905 | |||
906 | case RDP_ORDER_TRIBLT: | ||
907 | process_triblt(s, &os->triblt, present, delta); | ||
908 | break; | ||
909 | |||
910 | case RDP_ORDER_POLYLINE: | ||
911 | process_polyline(s, &os->polyline, present, delta); | ||
912 | break; | ||
913 | |||
914 | case RDP_ORDER_TEXT2: | ||
915 | process_text2(s, &os->text2, present, delta); | ||
916 | break; | ||
917 | |||
918 | default: | ||
919 | unimpl("order %d\n", os->order_type); | ||
920 | return; | ||
921 | } | ||
922 | |||
923 | if (order_flags & RDP_ORDER_BOUNDS) | ||
924 | ui_reset_clip(); | ||
925 | } | ||
926 | |||
927 | processed++; | ||
928 | } | ||
929 | |||
930 | if (s->p != next_packet) | ||
931 | error("%d bytes remaining\n", (int) (next_packet - s->p)); | ||
932 | } | ||
933 | |||
934 | /* Reset order state */ | ||
935 | void | ||
936 | reset_order_state(void) | ||
937 | { | ||
938 | memset(&order_state, 0, sizeof(order_state)); | ||
939 | order_state.order_type = RDP_ORDER_PATBLT; | ||
940 | } | ||