/[rdesktop]/sourceforge.net/trunk/rdesktop/orders.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /sourceforge.net/trunk/rdesktop/orders.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 813 - (show annotations)
Wed Feb 16 22:28:17 2005 UTC (19 years, 3 months ago) by jdmeijer
File MIME type: text/plain
File size: 23189 byte(s)
Improve parsing of unknown text2 order members

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

  ViewVC Help
Powered by ViewVC 1.1.26