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