VirtualBox

source: vbox/trunk/src/VBox/RDP/client/orders.c@ 14833

Last change on this file since 14833 was 11982, checked in by vboxsync, 16 years ago

All: license header changes for 2.0 (OSE headers, add Sun GPL/LGPL disclaimer)

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette