Sync up with trunk r61578.
[reactos.git] / base / applications / mstsc / orders.c
1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 RDP order processing
4 Copyright (C) Matthew Chapman 1999-2005
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 along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include "precomp.h"
22
23 #include "orders.h"
24
25 extern uint8 *g_next_packet;
26 static RDP_ORDER_STATE g_order_state;
27 extern BOOL g_use_rdp5;
28
29 /* Read field indicating which parameters are present */
30 static void
31 rdp_in_present(STREAM s, uint32 * present, uint8 flags, int size)
32 {
33 uint8 bits;
34 int i;
35
36 if (flags & RDP_ORDER_SMALL)
37 {
38 size--;
39 }
40
41 if (flags & RDP_ORDER_TINY)
42 {
43 if (size < 2)
44 size = 0;
45 else
46 size -= 2;
47 }
48
49 *present = 0;
50 for (i = 0; i < size; i++)
51 {
52 in_uint8(s, bits);
53 *present |= bits << (i * 8);
54 }
55 }
56
57 /* Read a co-ordinate (16-bit, or 8-bit delta) */
58 static void
59 rdp_in_coord(STREAM s, sint16 * coord, BOOL delta)
60 {
61 sint8 change;
62
63 if (delta)
64 {
65 in_uint8(s, change);
66 *coord += change;
67 }
68 else
69 {
70 in_uint16_le(s, *coord);
71 }
72 }
73
74 /* Parse a delta co-ordinate in polyline/polygon order form */
75 static int
76 parse_delta(uint8 * buffer, int *offset)
77 {
78 int value = buffer[(*offset)++];
79 int two_byte = value & 0x80;
80
81 if (value & 0x40) /* sign bit */
82 value |= ~0x3f;
83 else
84 value &= 0x3f;
85
86 if (two_byte)
87 value = (value << 8) | buffer[(*offset)++];
88
89 return value;
90 }
91
92 /* Read a colour entry */
93 static void
94 rdp_in_colour(STREAM s, uint32 * colour)
95 {
96 uint32 i;
97 in_uint8(s, i);
98 *colour = i;
99 in_uint8(s, i);
100 *colour |= i << 8;
101 in_uint8(s, i);
102 *colour |= i << 16;
103 }
104
105 /* Parse bounds information */
106 static BOOL
107 rdp_parse_bounds(STREAM s, BOUNDS * bounds)
108 {
109 uint8 present;
110
111 in_uint8(s, present);
112
113 if (present & 1)
114 rdp_in_coord(s, &bounds->left, False);
115 else if (present & 16)
116 rdp_in_coord(s, &bounds->left, True);
117
118 if (present & 2)
119 rdp_in_coord(s, &bounds->top, False);
120 else if (present & 32)
121 rdp_in_coord(s, &bounds->top, True);
122
123 if (present & 4)
124 rdp_in_coord(s, &bounds->right, False);
125 else if (present & 64)
126 rdp_in_coord(s, &bounds->right, True);
127
128 if (present & 8)
129 rdp_in_coord(s, &bounds->bottom, False);
130 else if (present & 128)
131 rdp_in_coord(s, &bounds->bottom, True);
132
133 return s_check(s);
134 }
135
136 /* Parse a pen */
137 static BOOL
138 rdp_parse_pen(STREAM s, PEN * pen, uint32 present)
139 {
140 if (present & 1)
141 in_uint8(s, pen->style);
142
143 if (present & 2)
144 in_uint8(s, pen->width);
145
146 if (present & 4)
147 rdp_in_colour(s, &pen->colour);
148
149 return s_check(s);
150 }
151
152 /* Parse a brush */
153 static BOOL
154 rdp_parse_brush(STREAM s, BRUSH * brush, uint32 present)
155 {
156 if (present & 1)
157 in_uint8(s, brush->xorigin);
158
159 if (present & 2)
160 in_uint8(s, brush->yorigin);
161
162 if (present & 4)
163 in_uint8(s, brush->style);
164
165 if (present & 8)
166 in_uint8(s, brush->pattern[0]);
167
168 if (present & 16)
169 in_uint8a(s, &brush->pattern[1], 7);
170
171 return s_check(s);
172 }
173
174 /* Process a destination blt order */
175 static void
176 process_destblt(STREAM s, DESTBLT_ORDER * os, uint32 present, BOOL delta)
177 {
178 if (present & 0x01)
179 rdp_in_coord(s, &os->x, delta);
180
181 if (present & 0x02)
182 rdp_in_coord(s, &os->y, delta);
183
184 if (present & 0x04)
185 rdp_in_coord(s, &os->cx, delta);
186
187 if (present & 0x08)
188 rdp_in_coord(s, &os->cy, delta);
189
190 if (present & 0x10)
191 in_uint8(s, os->opcode);
192
193 DEBUG(("DESTBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d)\n",
194 os->opcode, os->x, os->y, os->cx, os->cy));
195
196 ui_destblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy);
197 }
198
199 /* Process a pattern blt order */
200 static void
201 process_patblt(STREAM s, PATBLT_ORDER * os, uint32 present, BOOL delta)
202 {
203 if (present & 0x0001)
204 rdp_in_coord(s, &os->x, delta);
205
206 if (present & 0x0002)
207 rdp_in_coord(s, &os->y, delta);
208
209 if (present & 0x0004)
210 rdp_in_coord(s, &os->cx, delta);
211
212 if (present & 0x0008)
213 rdp_in_coord(s, &os->cy, delta);
214
215 if (present & 0x0010)
216 in_uint8(s, os->opcode);
217
218 if (present & 0x0020)
219 rdp_in_colour(s, &os->bgcolour);
220
221 if (present & 0x0040)
222 rdp_in_colour(s, &os->fgcolour);
223
224 rdp_parse_brush(s, &os->brush, present >> 7);
225
226 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,
227 os->y, os->cx, os->cy, os->brush.style, os->bgcolour, os->fgcolour));
228
229 ui_patblt(ROP2_P(os->opcode), os->x, os->y, os->cx, os->cy,
230 &os->brush, os->bgcolour, os->fgcolour);
231 }
232
233 /* Process a screen blt order */
234 static void
235 process_screenblt(STREAM s, SCREENBLT_ORDER * os, uint32 present, BOOL delta)
236 {
237 if (present & 0x0001)
238 rdp_in_coord(s, &os->x, delta);
239
240 if (present & 0x0002)
241 rdp_in_coord(s, &os->y, delta);
242
243 if (present & 0x0004)
244 rdp_in_coord(s, &os->cx, delta);
245
246 if (present & 0x0008)
247 rdp_in_coord(s, &os->cy, delta);
248
249 if (present & 0x0010)
250 in_uint8(s, os->opcode);
251
252 if (present & 0x0020)
253 rdp_in_coord(s, &os->srcx, delta);
254
255 if (present & 0x0040)
256 rdp_in_coord(s, &os->srcy, delta);
257
258 DEBUG(("SCREENBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,srcx=%d,srcy=%d)\n",
259 os->opcode, os->x, os->y, os->cx, os->cy, os->srcx, os->srcy));
260
261 ui_screenblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy, os->srcx, os->srcy);
262 }
263
264 /* Process a line order */
265 static void
266 process_line(STREAM s, LINE_ORDER * os, uint32 present, BOOL delta)
267 {
268 if (present & 0x0001)
269 in_uint16_le(s, os->mixmode);
270
271 if (present & 0x0002)
272 rdp_in_coord(s, &os->startx, delta);
273
274 if (present & 0x0004)
275 rdp_in_coord(s, &os->starty, delta);
276
277 if (present & 0x0008)
278 rdp_in_coord(s, &os->endx, delta);
279
280 if (present & 0x0010)
281 rdp_in_coord(s, &os->endy, delta);
282
283 if (present & 0x0020)
284 rdp_in_colour(s, &os->bgcolour);
285
286 if (present & 0x0040)
287 in_uint8(s, os->opcode);
288
289 rdp_parse_pen(s, &os->pen, present >> 7);
290
291 DEBUG(("LINE(op=0x%x,sx=%d,sy=%d,dx=%d,dy=%d,fg=0x%x)\n",
292 os->opcode, os->startx, os->starty, os->endx, os->endy, os->pen.colour));
293
294 if (os->opcode < 0x01 || os->opcode > 0x10)
295 {
296 error("bad ROP2 0x%x\n", os->opcode);
297 return;
298 }
299
300 ui_line(ROP_MINUS_1(os->opcode), os->startx, os->starty, os->endx, os->endy, &os->pen);
301 }
302
303 /* Process an opaque rectangle order */
304 static void
305 process_rect(STREAM s, RECT_ORDER * os, uint32 present, BOOL delta)
306 {
307 uint32 i;
308 if (present & 0x01)
309 rdp_in_coord(s, &os->x, delta);
310
311 if (present & 0x02)
312 rdp_in_coord(s, &os->y, delta);
313
314 if (present & 0x04)
315 rdp_in_coord(s, &os->cx, delta);
316
317 if (present & 0x08)
318 rdp_in_coord(s, &os->cy, delta);
319
320 if (present & 0x10)
321 {
322 in_uint8(s, i);
323 os->colour = (os->colour & 0xffffff00) | i;
324 }
325
326 if (present & 0x20)
327 {
328 in_uint8(s, i);
329 os->colour = (os->colour & 0xffff00ff) | (i << 8);
330 }
331
332 if (present & 0x40)
333 {
334 in_uint8(s, i);
335 os->colour = (os->colour & 0xff00ffff) | (i << 16);
336 }
337
338 DEBUG(("RECT(x=%d,y=%d,cx=%d,cy=%d,fg=0x%x)\n", os->x, os->y, os->cx, os->cy, os->colour));
339
340 ui_rect(os->x, os->y, os->cx, os->cy, os->colour);
341 }
342
343 /* Process a desktop save order */
344 static void
345 process_desksave(STREAM s, DESKSAVE_ORDER * os, uint32 present, BOOL delta)
346 {
347 int width, height;
348
349 if (present & 0x01)
350 in_uint32_le(s, os->offset);
351
352 if (present & 0x02)
353 rdp_in_coord(s, &os->left, delta);
354
355 if (present & 0x04)
356 rdp_in_coord(s, &os->top, delta);
357
358 if (present & 0x08)
359 rdp_in_coord(s, &os->right, delta);
360
361 if (present & 0x10)
362 rdp_in_coord(s, &os->bottom, delta);
363
364 if (present & 0x20)
365 in_uint8(s, os->action);
366
367 DEBUG(("DESKSAVE(l=%d,t=%d,r=%d,b=%d,off=%d,op=%d)\n",
368 os->left, os->top, os->right, os->bottom, os->offset, os->action));
369
370 width = os->right - os->left + 1;
371 height = os->bottom - os->top + 1;
372
373 if (os->action == 0)
374 ui_desktop_save(os->offset, os->left, os->top, width, height);
375 else
376 ui_desktop_restore(os->offset, os->left, os->top, width, height);
377 }
378
379 /* Process a memory blt order */
380 static void
381 process_memblt(STREAM s, MEMBLT_ORDER * os, uint32 present, BOOL delta)
382 {
383 HBITMAP bitmap;
384
385 if (present & 0x0001)
386 {
387 in_uint8(s, os->cache_id);
388 in_uint8(s, os->colour_table);
389 }
390
391 if (present & 0x0002)
392 rdp_in_coord(s, &os->x, delta);
393
394 if (present & 0x0004)
395 rdp_in_coord(s, &os->y, delta);
396
397 if (present & 0x0008)
398 rdp_in_coord(s, &os->cx, delta);
399
400 if (present & 0x0010)
401 rdp_in_coord(s, &os->cy, delta);
402
403 if (present & 0x0020)
404 in_uint8(s, os->opcode);
405
406 if (present & 0x0040)
407 rdp_in_coord(s, &os->srcx, delta);
408
409 if (present & 0x0080)
410 rdp_in_coord(s, &os->srcy, delta);
411
412 if (present & 0x0100)
413 in_uint16_le(s, os->cache_idx);
414
415 DEBUG(("MEMBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d)\n",
416 os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id, os->cache_idx));
417
418 bitmap = cache_get_bitmap(os->cache_id, os->cache_idx);
419 if (bitmap == NULL)
420 return;
421
422 ui_memblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy, bitmap, os->srcx, os->srcy);
423 }
424
425 /* Process a 3-way blt order */
426 static void
427 process_triblt(STREAM s, TRIBLT_ORDER * os, uint32 present, BOOL delta)
428 {
429 HBITMAP bitmap;
430
431 if (present & 0x000001)
432 {
433 in_uint8(s, os->cache_id);
434 in_uint8(s, os->colour_table);
435 }
436
437 if (present & 0x000002)
438 rdp_in_coord(s, &os->x, delta);
439
440 if (present & 0x000004)
441 rdp_in_coord(s, &os->y, delta);
442
443 if (present & 0x000008)
444 rdp_in_coord(s, &os->cx, delta);
445
446 if (present & 0x000010)
447 rdp_in_coord(s, &os->cy, delta);
448
449 if (present & 0x000020)
450 in_uint8(s, os->opcode);
451
452 if (present & 0x000040)
453 rdp_in_coord(s, &os->srcx, delta);
454
455 if (present & 0x000080)
456 rdp_in_coord(s, &os->srcy, delta);
457
458 if (present & 0x000100)
459 rdp_in_colour(s, &os->bgcolour);
460
461 if (present & 0x000200)
462 rdp_in_colour(s, &os->fgcolour);
463
464 rdp_parse_brush(s, &os->brush, present >> 10);
465
466 if (present & 0x008000)
467 in_uint16_le(s, os->cache_idx);
468
469 if (present & 0x010000)
470 in_uint16_le(s, os->unknown);
471
472 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",
473 os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id, os->cache_idx,
474 os->brush.style, os->bgcolour, os->fgcolour));
475
476 bitmap = cache_get_bitmap(os->cache_id, os->cache_idx);
477 if (bitmap == NULL)
478 return;
479
480 ui_triblt(os->opcode, os->x, os->y, os->cx, os->cy,
481 bitmap, os->srcx, os->srcy, &os->brush, os->bgcolour, os->fgcolour);
482 }
483
484 /* Process a polygon order */
485 static void
486 process_polygon(STREAM s, POLYGON_ORDER * os, uint32 present, BOOL delta)
487 {
488 int index, data, next;
489 uint8 flags = 0;
490 POINT *points;
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 & 0x08)
502 in_uint8(s, os->fillmode);
503
504 if (present & 0x10)
505 rdp_in_colour(s, &os->fgcolour);
506
507 if (present & 0x20)
508 in_uint8(s, os->npoints);
509
510 if (present & 0x40)
511 {
512 in_uint8(s, os->datasize);
513 in_uint8a(s, os->data, os->datasize);
514 }
515
516 DEBUG(("POLYGON(x=%d,y=%d,op=0x%x,fm=%d,fg=0x%x,n=%d,sz=%d)\n",
517 os->x, os->y, os->opcode, os->fillmode, os->fgcolour, os->npoints, os->datasize));
518
519 DEBUG(("Data: "));
520
521 for (index = 0; index < os->datasize; index++)
522 DEBUG(("%02x ", os->data[index]));
523
524 DEBUG(("\n"));
525
526 if (os->opcode < 0x01 || os->opcode > 0x10)
527 {
528 error("bad ROP2 0x%x\n", os->opcode);
529 return;
530 }
531
532 points = (POINT *) xmalloc((os->npoints + 1) * sizeof(POINT));
533 memset(points, 0, (os->npoints + 1) * sizeof(POINT));
534
535 points[0].x = os->x;
536 points[0].y = os->y;
537
538 index = 0;
539 data = ((os->npoints - 1) / 4) + 1;
540 for (next = 1; (next <= os->npoints) && (next < 256) && (data < os->datasize); next++)
541 {
542 if ((next - 1) % 4 == 0)
543 flags = os->data[index++];
544
545 if (~flags & 0x80)
546 points[next].x = parse_delta(os->data, &data);
547
548 if (~flags & 0x40)
549 points[next].y = parse_delta(os->data, &data);
550
551 flags <<= 2;
552 }
553
554 if (next - 1 == os->npoints)
555 ui_polygon(ROP_MINUS_1(os->opcode), os->fillmode, points, os->npoints + 1, NULL, 0,
556 os->fgcolour);
557 else
558 error("polygon parse error\n");
559
560 xfree(points);
561 }
562
563 /* Process a polygon2 order */
564 static void
565 process_polygon2(STREAM s, POLYGON2_ORDER * os, uint32 present, BOOL delta)
566 {
567 int index, data, next;
568 uint8 flags = 0;
569 POINT *points;
570
571 if (present & 0x0001)
572 rdp_in_coord(s, &os->x, delta);
573
574 if (present & 0x0002)
575 rdp_in_coord(s, &os->y, delta);
576
577 if (present & 0x0004)
578 in_uint8(s, os->opcode);
579
580 if (present & 0x0008)
581 in_uint8(s, os->fillmode);
582
583 if (present & 0x0010)
584 rdp_in_colour(s, &os->bgcolour);
585
586 if (present & 0x0020)
587 rdp_in_colour(s, &os->fgcolour);
588
589 rdp_parse_brush(s, &os->brush, present >> 6);
590
591 if (present & 0x0800)
592 in_uint8(s, os->npoints);
593
594 if (present & 0x1000)
595 {
596 in_uint8(s, os->datasize);
597 in_uint8a(s, os->data, os->datasize);
598 }
599
600 DEBUG(("POLYGON2(x=%d,y=%d,op=0x%x,fm=%d,bs=%d,bg=0x%x,fg=0x%x,n=%d,sz=%d)\n",
601 os->x, os->y, os->opcode, os->fillmode, os->brush.style, os->bgcolour, os->fgcolour,
602 os->npoints, os->datasize));
603
604 DEBUG(("Data: "));
605
606 for (index = 0; index < os->datasize; index++)
607 DEBUG(("%02x ", os->data[index]));
608
609 DEBUG(("\n"));
610
611 if (os->opcode < 0x01 || os->opcode > 0x10)
612 {
613 error("bad ROP2 0x%x\n", os->opcode);
614 return;
615 }
616
617 points = (POINT *) xmalloc((os->npoints + 1) * sizeof(POINT));
618 memset(points, 0, (os->npoints + 1) * sizeof(POINT));
619
620 points[0].x = os->x;
621 points[0].y = os->y;
622
623 index = 0;
624 data = ((os->npoints - 1) / 4) + 1;
625 for (next = 1; (next <= os->npoints) && (next < 256) && (data < os->datasize); next++)
626 {
627 if ((next - 1) % 4 == 0)
628 flags = os->data[index++];
629
630 if (~flags & 0x80)
631 points[next].x = parse_delta(os->data, &data);
632
633 if (~flags & 0x40)
634 points[next].y = parse_delta(os->data, &data);
635
636 flags <<= 2;
637 }
638
639 if (next - 1 == os->npoints)
640 ui_polygon(ROP_MINUS_1(os->opcode), os->fillmode, points, os->npoints + 1,
641 &os->brush, os->bgcolour, os->fgcolour);
642 else
643 error("polygon2 parse error\n");
644
645 xfree(points);
646 }
647
648 /* Process a polyline order */
649 static void
650 process_polyline(STREAM s, POLYLINE_ORDER * os, uint32 present, BOOL delta)
651 {
652 int index, next, data;
653 uint8 flags = 0;
654 PEN pen;
655 POINT *points;
656
657 if (present & 0x01)
658 rdp_in_coord(s, &os->x, delta);
659
660 if (present & 0x02)
661 rdp_in_coord(s, &os->y, delta);
662
663 if (present & 0x04)
664 in_uint8(s, os->opcode);
665
666 if (present & 0x10)
667 rdp_in_colour(s, &os->fgcolour);
668
669 if (present & 0x20)
670 in_uint8(s, os->lines);
671
672 if (present & 0x40)
673 {
674 in_uint8(s, os->datasize);
675 in_uint8a(s, os->data, os->datasize);
676 }
677
678 DEBUG(("POLYLINE(x=%d,y=%d,op=0x%x,fg=0x%x,n=%d,sz=%d)\n",
679 os->x, os->y, os->opcode, os->fgcolour, os->lines, os->datasize));
680
681 DEBUG(("Data: "));
682
683 for (index = 0; index < os->datasize; index++)
684 DEBUG(("%02x ", os->data[index]));
685
686 DEBUG(("\n"));
687
688 if (os->opcode < 0x01 || os->opcode > 0x10)
689 {
690 error("bad ROP2 0x%x\n", os->opcode);
691 return;
692 }
693
694 points = (POINT *) xmalloc((os->lines + 1) * sizeof(POINT));
695 memset(points, 0, (os->lines + 1) * sizeof(POINT));
696
697 points[0].x = os->x;
698 points[0].y = os->y;
699 pen.style = pen.width = 0;
700 pen.colour = os->fgcolour;
701
702 index = 0;
703 data = ((os->lines - 1) / 4) + 1;
704 for (next = 1; (next <= os->lines) && (data < os->datasize); next++)
705 {
706 if ((next - 1) % 4 == 0)
707 flags = os->data[index++];
708
709 if (~flags & 0x80)
710 points[next].x = parse_delta(os->data, &data);
711
712 if (~flags & 0x40)
713 points[next].y = parse_delta(os->data, &data);
714
715 flags <<= 2;
716 }
717
718 if (next - 1 == os->lines)
719 ui_polyline(ROP_MINUS_1(os->opcode), points, os->lines + 1, &pen);
720 else
721 error("polyline parse error\n");
722
723 xfree(points);
724 }
725
726 /* Process an ellipse order */
727 static void
728 process_ellipse(STREAM s, ELLIPSE_ORDER * os, uint32 present, BOOL delta)
729 {
730 if (present & 0x01)
731 rdp_in_coord(s, &os->left, delta);
732
733 if (present & 0x02)
734 rdp_in_coord(s, &os->top, delta);
735
736 if (present & 0x04)
737 rdp_in_coord(s, &os->right, delta);
738
739 if (present & 0x08)
740 rdp_in_coord(s, &os->bottom, delta);
741
742 if (present & 0x10)
743 in_uint8(s, os->opcode);
744
745 if (present & 0x20)
746 in_uint8(s, os->fillmode);
747
748 if (present & 0x40)
749 rdp_in_colour(s, &os->fgcolour);
750
751 DEBUG(("ELLIPSE(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,fg=0x%x)\n", os->left, os->top,
752 os->right, os->bottom, os->opcode, os->fillmode, os->fgcolour));
753
754 ui_ellipse(ROP_MINUS_1(os->opcode), os->fillmode, os->left, os->top, os->right - os->left,
755 os->bottom - os->top, NULL, 0, os->fgcolour);
756 }
757
758 /* Process an ellipse2 order */
759 static void
760 process_ellipse2(STREAM s, ELLIPSE2_ORDER * os, uint32 present, BOOL delta)
761 {
762 if (present & 0x0001)
763 rdp_in_coord(s, &os->left, delta);
764
765 if (present & 0x0002)
766 rdp_in_coord(s, &os->top, delta);
767
768 if (present & 0x0004)
769 rdp_in_coord(s, &os->right, delta);
770
771 if (present & 0x0008)
772 rdp_in_coord(s, &os->bottom, delta);
773
774 if (present & 0x0010)
775 in_uint8(s, os->opcode);
776
777 if (present & 0x0020)
778 in_uint8(s, os->fillmode);
779
780 if (present & 0x0040)
781 rdp_in_colour(s, &os->bgcolour);
782
783 if (present & 0x0080)
784 rdp_in_colour(s, &os->fgcolour);
785
786 rdp_parse_brush(s, &os->brush, present >> 8);
787
788 DEBUG(("ELLIPSE2(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,bs=%d,bg=0x%x,fg=0x%x)\n",
789 os->left, os->top, os->right, os->bottom, os->opcode, os->fillmode, os->brush.style,
790 os->bgcolour, os->fgcolour));
791
792 ui_ellipse(ROP_MINUS_1(os->opcode), os->fillmode, os->left, os->top, os->right - os->left,
793 os->bottom - os->top, &os->brush, os->bgcolour, os->fgcolour);
794 }
795
796 /* Process a text order */
797 static void
798 process_text2(STREAM s, TEXT2_ORDER * os, uint32 present, BOOL delta)
799 {
800 int i;
801
802 if (present & 0x000001)
803 in_uint8(s, os->font);
804
805 if (present & 0x000002)
806 in_uint8(s, os->flags);
807
808 if (present & 0x000004)
809 in_uint8(s, os->opcode);
810
811 if (present & 0x000008)
812 in_uint8(s, os->mixmode);
813
814 if (present & 0x000010)
815 rdp_in_colour(s, &os->fgcolour);
816
817 if (present & 0x000020)
818 rdp_in_colour(s, &os->bgcolour);
819
820 if (present & 0x000040)
821 in_uint16_le(s, os->clipleft);
822
823 if (present & 0x000080)
824 in_uint16_le(s, os->cliptop);
825
826 if (present & 0x000100)
827 in_uint16_le(s, os->clipright);
828
829 if (present & 0x000200)
830 in_uint16_le(s, os->clipbottom);
831
832 if (present & 0x000400)
833 in_uint16_le(s, os->boxleft);
834
835 if (present & 0x000800)
836 in_uint16_le(s, os->boxtop);
837
838 if (present & 0x001000)
839 in_uint16_le(s, os->boxright);
840
841 if (present & 0x002000)
842 in_uint16_le(s, os->boxbottom);
843
844 rdp_parse_brush(s, &os->brush, present >> 14);
845
846 if (present & 0x080000)
847 in_uint16_le(s, os->x);
848
849 if (present & 0x100000)
850 in_uint16_le(s, os->y);
851
852 if (present & 0x200000)
853 {
854 in_uint8(s, os->length);
855 in_uint8a(s, os->text, os->length);
856 }
857
858 DEBUG(("TEXT2(x=%d,y=%d,cl=%d,ct=%d,cr=%d,cb=%d,bl=%d,bt=%d,br=%d,bb=%d,bs=%d,bg=0x%x,fg=0x%x,font=%d,fl=0x%x,op=0x%x,mix=%d,n=%d)\n", os->x, os->y, os->clipleft, os->cliptop, os->clipright, os->clipbottom, os->boxleft, os->boxtop, os->boxright, os->boxbottom, os->brush.style, os->bgcolour, os->fgcolour, os->font, os->flags, os->opcode, os->mixmode, os->length));
859
860 DEBUG(("Text: "));
861
862 for (i = 0; i < os->length; i++)
863 DEBUG(("%02x ", os->text[i]));
864
865 DEBUG(("\n"));
866
867 ui_draw_text(os->font, os->flags, ROP_MINUS_1(os->opcode), os->mixmode, os->x, os->y,
868 os->clipleft, os->cliptop, os->clipright - os->clipleft,
869 os->clipbottom - os->cliptop, os->boxleft, os->boxtop,
870 os->boxright - os->boxleft, os->boxbottom - os->boxtop,
871 &os->brush, os->bgcolour, os->fgcolour, os->text, os->length);
872 }
873
874 /* Process a raw bitmap cache order */
875 static void
876 process_raw_bmpcache(STREAM s)
877 {
878 HBITMAP bitmap;
879 uint16 cache_idx, bufsize;
880 uint8 cache_id, width, height, bpp, Bpp;
881 uint8 *data, *inverted;
882 int y;
883
884 in_uint8(s, cache_id);
885 in_uint8s(s, 1); /* pad */
886 in_uint8(s, width);
887 in_uint8(s, height);
888 in_uint8(s, bpp);
889 Bpp = (bpp + 7) / 8;
890 in_uint16_le(s, bufsize);
891 in_uint16_le(s, cache_idx);
892 in_uint8p(s, data, bufsize);
893
894 DEBUG(("RAW_BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n", width, height, cache_id, cache_idx));
895 inverted = (uint8 *) xmalloc(width * height * Bpp);
896 for (y = 0; y < height; y++)
897 {
898 memcpy(&inverted[(height - y - 1) * (width * Bpp)], &data[y * (width * Bpp)],
899 width * Bpp);
900 }
901
902 bitmap = ui_create_bitmap(width, height, inverted);
903 xfree(inverted);
904 cache_put_bitmap(cache_id, cache_idx, bitmap);
905 }
906
907 /* Process a bitmap cache order */
908 static void
909 process_bmpcache(STREAM s)
910 {
911 HBITMAP bitmap;
912 uint16 cache_idx, size;
913 uint8 cache_id, width, height, bpp, Bpp;
914 uint8 *data, *bmpdata;
915 uint16 bufsize, pad2, row_size, final_size;
916 uint8 pad1;
917
918 pad2 = row_size = final_size = 0xffff; /* Shut the compiler up */
919
920 in_uint8(s, cache_id);
921 in_uint8(s, pad1); /* pad */
922 in_uint8(s, width);
923 in_uint8(s, height);
924 in_uint8(s, bpp);
925 Bpp = (bpp + 7) / 8;
926 in_uint16_le(s, bufsize); /* bufsize */
927 in_uint16_le(s, cache_idx);
928
929 if (g_use_rdp5)
930 {
931 size = bufsize;
932 }
933 else
934 {
935
936 /* Begin compressedBitmapData */
937 in_uint16_le(s, pad2); /* pad */
938 in_uint16_le(s, size);
939 /* in_uint8s(s, 4); *//* row_size, final_size */
940 in_uint16_le(s, row_size);
941 in_uint16_le(s, final_size);
942
943 }
944 in_uint8p(s, data, size);
945
946 DEBUG(("BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d,bpp=%d,size=%d,pad1=%d,bufsize=%d,pad2=%d,rs=%d,fs=%d)\n", width, height, cache_id, cache_idx, bpp, size, pad1, bufsize, pad2, row_size, final_size));
947 (void)pad1; (void)pad2;
948
949 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
950
951 if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
952 {
953 bitmap = ui_create_bitmap(width, height, bmpdata);
954 cache_put_bitmap(cache_id, cache_idx, bitmap);
955 }
956 else
957 {
958 DEBUG(("Failed to decompress bitmap data\n"));
959 }
960
961 xfree(bmpdata);
962 }
963
964 /* Process a bitmap cache v2 order */
965 static void
966 process_bmpcache2(STREAM s, uint16 flags, BOOL compressed)
967 {
968 HBITMAP bitmap;
969 int y;
970 uint8 cache_id, cache_idx_low, width, height, Bpp;
971 uint16 cache_idx, bufsize;
972 uint8 *data, *bmpdata, *bitmap_id;
973
974 bitmap_id = NULL; /* prevent compiler warning */
975 cache_id = flags & ID_MASK;
976 Bpp = ((flags & MODE_MASK) >> MODE_SHIFT) - 2;
977
978 if (flags & PERSIST)
979 {
980 in_uint8p(s, bitmap_id, 8);
981 }
982
983 if (flags & SQUARE)
984 {
985 in_uint8(s, width);
986 height = width;
987 }
988 else
989 {
990 in_uint8(s, width);
991 in_uint8(s, height);
992 }
993
994 in_uint16_be(s, bufsize);
995 bufsize &= BUFSIZE_MASK;
996 in_uint8(s, cache_idx);
997
998 if (cache_idx & LONG_FORMAT)
999 {
1000 in_uint8(s, cache_idx_low);
1001 cache_idx = ((cache_idx ^ LONG_FORMAT) << 8) + cache_idx_low;
1002 }
1003
1004 in_uint8p(s, data, bufsize);
1005
1006 DEBUG(("BMPCACHE2(compr=%d,flags=%x,cx=%d,cy=%d,id=%d,idx=%d,Bpp=%d,bs=%d)\n",
1007 compressed, flags, width, height, cache_id, cache_idx, Bpp, bufsize));
1008
1009 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1010
1011 if (compressed)
1012 {
1013 if (!bitmap_decompress(bmpdata, width, height, data, bufsize, Bpp))
1014 {
1015 DEBUG(("Failed to decompress bitmap data\n"));
1016 xfree(bmpdata);
1017 return;
1018 }
1019 }
1020 else
1021 {
1022 for (y = 0; y < height; y++)
1023 memcpy(&bmpdata[(height - y - 1) * (width * Bpp)],
1024 &data[y * (width * Bpp)], width * Bpp);
1025 }
1026
1027 bitmap = ui_create_bitmap(width, height, bmpdata);
1028
1029 if (bitmap)
1030 {
1031 cache_put_bitmap(cache_id, cache_idx, bitmap);
1032 if (flags & PERSIST)
1033 pstcache_save_bitmap(cache_id, cache_idx, bitmap_id, width, height,
1034 (uint16) (width * height * Bpp), bmpdata);
1035 }
1036 else
1037 {
1038 DEBUG(("process_bmpcache2: ui_create_bitmap failed\n"));
1039 }
1040
1041 xfree(bmpdata);
1042 }
1043
1044 /* Process a colourmap cache order */
1045 static void
1046 process_colcache(STREAM s)
1047 {
1048 COLOURENTRY *entry;
1049 COLOURMAP map;
1050 RD_HCOLOURMAP hmap;
1051 uint8 cache_id;
1052 int i;
1053
1054 in_uint8(s, cache_id);
1055 in_uint16_le(s, map.ncolours);
1056
1057 map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
1058
1059 for (i = 0; i < map.ncolours; i++)
1060 {
1061 entry = &map.colours[i];
1062 in_uint8(s, entry->blue);
1063 in_uint8(s, entry->green);
1064 in_uint8(s, entry->red);
1065 in_uint8s(s, 1); /* pad */
1066 }
1067
1068 DEBUG(("COLCACHE(id=%d,n=%d)\n", cache_id, map.ncolours));
1069
1070 hmap = ui_create_colourmap(&map);
1071
1072 if (cache_id)
1073 ui_set_colourmap(hmap);
1074
1075 xfree(map.colours);
1076 }
1077
1078 /* Process a font cache order */
1079 static void
1080 process_fontcache(STREAM s)
1081 {
1082 RD_HGLYPH bitmap;
1083 uint8 font, nglyphs;
1084 uint16 character, offset, baseline, width, height;
1085 int i, datasize;
1086 uint8 *data;
1087
1088 in_uint8(s, font);
1089 in_uint8(s, nglyphs);
1090
1091 DEBUG(("FONTCACHE(font=%d,n=%d)\n", font, nglyphs));
1092
1093 for (i = 0; i < nglyphs; i++)
1094 {
1095 in_uint16_le(s, character);
1096 in_uint16_le(s, offset);
1097 in_uint16_le(s, baseline);
1098 in_uint16_le(s, width);
1099 in_uint16_le(s, height);
1100
1101 datasize = (height * ((width + 7) / 8) + 3) & ~3;
1102 in_uint8p(s, data, datasize);
1103
1104 bitmap = ui_create_glyph(width, height, data);
1105 cache_put_font(font, character, offset, baseline, width, height, bitmap);
1106 }
1107 }
1108
1109 /* Process a secondary order */
1110 static void
1111 process_secondary_order(STREAM s)
1112 {
1113 /* The length isn't calculated correctly by the server.
1114 * For very compact orders the length becomes negative
1115 * so a signed integer must be used. */
1116 uint16 length;
1117 uint16 flags;
1118 uint8 type;
1119 uint8 *next_order;
1120
1121 in_uint16_le(s, length);
1122 in_uint16_le(s, flags); /* used by bmpcache2 */
1123 in_uint8(s, type);
1124
1125 next_order = s->p + (sint16) length + 7;
1126
1127 switch (type)
1128 {
1129 case RDP_ORDER_RAW_BMPCACHE:
1130 process_raw_bmpcache(s);
1131 break;
1132
1133 case RDP_ORDER_COLCACHE:
1134 process_colcache(s);
1135 break;
1136
1137 case RDP_ORDER_BMPCACHE:
1138 process_bmpcache(s);
1139 break;
1140
1141 case RDP_ORDER_FONTCACHE:
1142 process_fontcache(s);
1143 break;
1144
1145 case RDP_ORDER_RAW_BMPCACHE2:
1146 process_bmpcache2(s, flags, False); /* uncompressed */
1147 break;
1148
1149 case RDP_ORDER_BMPCACHE2:
1150 process_bmpcache2(s, flags, True); /* compressed */
1151 break;
1152
1153 default:
1154 unimpl("secondary order %d\n", type);
1155 }
1156
1157 s->p = next_order;
1158 }
1159
1160 /* Process an order PDU */
1161 void
1162 process_orders(STREAM s, uint16 num_orders)
1163 {
1164 RDP_ORDER_STATE *os = &g_order_state;
1165 uint32 present;
1166 uint8 order_flags;
1167 int size, processed = 0;
1168 BOOL delta;
1169
1170 while (processed < num_orders)
1171 {
1172 in_uint8(s, order_flags);
1173
1174 if (!(order_flags & RDP_ORDER_STANDARD))
1175 {
1176 error("order parsing failed\n");
1177 break;
1178 }
1179
1180 if (order_flags & RDP_ORDER_SECONDARY)
1181 {
1182 process_secondary_order(s);
1183 }
1184 else
1185 {
1186 if (order_flags & RDP_ORDER_CHANGE)
1187 {
1188 in_uint8(s, os->order_type);
1189 }
1190
1191 switch (os->order_type)
1192 {
1193 case RDP_ORDER_TRIBLT:
1194 case RDP_ORDER_TEXT2:
1195 size = 3;
1196 break;
1197
1198 case RDP_ORDER_PATBLT:
1199 case RDP_ORDER_MEMBLT:
1200 case RDP_ORDER_LINE:
1201 case RDP_ORDER_POLYGON2:
1202 case RDP_ORDER_ELLIPSE2:
1203 size = 2;
1204 break;
1205
1206 default:
1207 size = 1;
1208 }
1209
1210 rdp_in_present(s, &present, order_flags, size);
1211
1212 if (order_flags & RDP_ORDER_BOUNDS)
1213 {
1214 if (!(order_flags & RDP_ORDER_LASTBOUNDS))
1215 rdp_parse_bounds(s, &os->bounds);
1216
1217 ui_set_clip(os->bounds.left,
1218 os->bounds.top,
1219 os->bounds.right -
1220 os->bounds.left + 1,
1221 os->bounds.bottom - os->bounds.top + 1);
1222 }
1223
1224 delta = order_flags & RDP_ORDER_DELTA;
1225
1226 switch (os->order_type)
1227 {
1228 case RDP_ORDER_DESTBLT:
1229 process_destblt(s, &os->destblt, present, delta);
1230 break;
1231
1232 case RDP_ORDER_PATBLT:
1233 process_patblt(s, &os->patblt, present, delta);
1234 break;
1235
1236 case RDP_ORDER_SCREENBLT:
1237 process_screenblt(s, &os->screenblt, present, delta);
1238 break;
1239
1240 case RDP_ORDER_LINE:
1241 process_line(s, &os->line, present, delta);
1242 break;
1243
1244 case RDP_ORDER_RECT:
1245 process_rect(s, &os->rect, present, delta);
1246 break;
1247
1248 case RDP_ORDER_DESKSAVE:
1249 process_desksave(s, &os->desksave, present, delta);
1250 break;
1251
1252 case RDP_ORDER_MEMBLT:
1253 process_memblt(s, &os->memblt, present, delta);
1254 break;
1255
1256 case RDP_ORDER_TRIBLT:
1257 process_triblt(s, &os->triblt, present, delta);
1258 break;
1259
1260 case RDP_ORDER_POLYGON:
1261 process_polygon(s, &os->polygon, present, delta);
1262 break;
1263
1264 case RDP_ORDER_POLYGON2:
1265 process_polygon2(s, &os->polygon2, present, delta);
1266 break;
1267
1268 case RDP_ORDER_POLYLINE:
1269 process_polyline(s, &os->polyline, present, delta);
1270 break;
1271
1272 case RDP_ORDER_ELLIPSE:
1273 process_ellipse(s, &os->ellipse, present, delta);
1274 break;
1275
1276 case RDP_ORDER_ELLIPSE2:
1277 process_ellipse2(s, &os->ellipse2, present, delta);
1278 break;
1279
1280 case RDP_ORDER_TEXT2:
1281 process_text2(s, &os->text2, present, delta);
1282 break;
1283
1284 default:
1285 unimpl("order %d\n", os->order_type);
1286 return;
1287 }
1288
1289 if (order_flags & RDP_ORDER_BOUNDS)
1290 ui_reset_clip();
1291 }
1292
1293 processed++;
1294 }
1295 #if 0
1296 /* not true when RDP_COMPRESSION is set */
1297 if (s->p != g_next_packet)
1298 error("%d bytes remaining\n", (int) (g_next_packet - s->p));
1299 #endif
1300
1301 }
1302
1303 /* Reset order state */
1304 void
1305 reset_order_state(void)
1306 {
1307 memset(&g_order_state, 0, sizeof(g_order_state));
1308 g_order_state.order_type = RDP_ORDER_PATBLT;
1309 }