VirtualBox

source: vbox/trunk/src/VBox/RDP/client-1.8.4/orders.c@ 82512

Last change on this file since 82512 was 76779, checked in by vboxsync, 6 years ago

RDP: add client-1.8.4.
bugref:9356: Update rdesktop-vrdp to 1.8.4
client-1.8.4 is a Subversion copy of 1.8.3 with the upstream 1.8.3 to 1.8.4
patch applied and a couple of fixes and changes after review, namely:

  • Stopped disabling the new pointer data format for our build, as this is no

longer needed.

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