1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
4 Copyright (C) Matthew Chapman 1999-2005
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.
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.
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.
24 extern uint8
*g_next_packet
;
25 static RDP_ORDER_STATE g_order_state
;
26 extern BOOL g_use_rdp5
;
28 /* Read field indicating which parameters are present */
30 rdp_in_present(STREAM s
, uint32
* present
, uint8 flags
, int size
)
35 if (flags
& RDP_ORDER_SMALL
)
40 if (flags
& RDP_ORDER_TINY
)
49 for (i
= 0; i
< size
; i
++)
52 *present
|= bits
<< (i
* 8);
56 /* Read a co-ordinate (16-bit, or 8-bit delta) */
58 rdp_in_coord(STREAM s
, sint16
* coord
, BOOL delta
)
69 in_uint16_le(s
, *coord
);
73 /* Parse a delta co-ordinate in polyline/polygon order form */
75 parse_delta(uint8
* buffer
, int *offset
)
77 int value
= buffer
[(*offset
)++];
78 int two_byte
= value
& 0x80;
80 if (value
& 0x40) /* sign bit */
86 value
= (value
<< 8) | buffer
[(*offset
)++];
91 /* Read a colour entry */
93 rdp_in_colour(STREAM s
, uint32
* colour
)
104 /* Parse bounds information */
106 rdp_parse_bounds(STREAM s
, BOUNDS
* bounds
)
110 in_uint8(s
, present
);
113 rdp_in_coord(s
, &bounds
->left
, False
);
114 else if (present
& 16)
115 rdp_in_coord(s
, &bounds
->left
, True
);
118 rdp_in_coord(s
, &bounds
->top
, False
);
119 else if (present
& 32)
120 rdp_in_coord(s
, &bounds
->top
, True
);
123 rdp_in_coord(s
, &bounds
->right
, False
);
124 else if (present
& 64)
125 rdp_in_coord(s
, &bounds
->right
, True
);
128 rdp_in_coord(s
, &bounds
->bottom
, False
);
129 else if (present
& 128)
130 rdp_in_coord(s
, &bounds
->bottom
, True
);
137 rdp_parse_pen(STREAM s
, PEN
* pen
, uint32 present
)
140 in_uint8(s
, pen
->style
);
143 in_uint8(s
, pen
->width
);
146 rdp_in_colour(s
, &pen
->colour
);
153 rdp_parse_brush(STREAM s
, BRUSH
* brush
, uint32 present
)
156 in_uint8(s
, brush
->xorigin
);
159 in_uint8(s
, brush
->yorigin
);
162 in_uint8(s
, brush
->style
);
165 in_uint8(s
, brush
->pattern
[0]);
168 in_uint8a(s
, &brush
->pattern
[1], 7);
173 /* Process a destination blt order */
175 process_destblt(STREAM s
, DESTBLT_ORDER
* os
, uint32 present
, BOOL delta
)
178 rdp_in_coord(s
, &os
->x
, delta
);
181 rdp_in_coord(s
, &os
->y
, delta
);
184 rdp_in_coord(s
, &os
->cx
, delta
);
187 rdp_in_coord(s
, &os
->cy
, delta
);
190 in_uint8(s
, os
->opcode
);
192 DEBUG(("DESTBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d)\n",
193 os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
));
195 ui_destblt(ROP2_S(os
->opcode
), os
->x
, os
->y
, os
->cx
, os
->cy
);
198 /* Process a pattern blt order */
200 process_patblt(STREAM s
, PATBLT_ORDER
* os
, uint32 present
, BOOL delta
)
202 if (present
& 0x0001)
203 rdp_in_coord(s
, &os
->x
, delta
);
205 if (present
& 0x0002)
206 rdp_in_coord(s
, &os
->y
, delta
);
208 if (present
& 0x0004)
209 rdp_in_coord(s
, &os
->cx
, delta
);
211 if (present
& 0x0008)
212 rdp_in_coord(s
, &os
->cy
, delta
);
214 if (present
& 0x0010)
215 in_uint8(s
, os
->opcode
);
217 if (present
& 0x0020)
218 rdp_in_colour(s
, &os
->bgcolour
);
220 if (present
& 0x0040)
221 rdp_in_colour(s
, &os
->fgcolour
);
223 rdp_parse_brush(s
, &os
->brush
, present
>> 7);
225 DEBUG(("PATBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,bs=%d,bg=0x%x,fg=0x%x)\n", os
->opcode
, os
->x
,
226 os
->y
, os
->cx
, os
->cy
, os
->brush
.style
, os
->bgcolour
, os
->fgcolour
));
228 ui_patblt(ROP2_P(os
->opcode
), os
->x
, os
->y
, os
->cx
, os
->cy
,
229 &os
->brush
, os
->bgcolour
, os
->fgcolour
);
232 /* Process a screen blt order */
234 process_screenblt(STREAM s
, SCREENBLT_ORDER
* os
, uint32 present
, BOOL delta
)
236 if (present
& 0x0001)
237 rdp_in_coord(s
, &os
->x
, delta
);
239 if (present
& 0x0002)
240 rdp_in_coord(s
, &os
->y
, delta
);
242 if (present
& 0x0004)
243 rdp_in_coord(s
, &os
->cx
, delta
);
245 if (present
& 0x0008)
246 rdp_in_coord(s
, &os
->cy
, delta
);
248 if (present
& 0x0010)
249 in_uint8(s
, os
->opcode
);
251 if (present
& 0x0020)
252 rdp_in_coord(s
, &os
->srcx
, delta
);
254 if (present
& 0x0040)
255 rdp_in_coord(s
, &os
->srcy
, delta
);
257 DEBUG(("SCREENBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,srcx=%d,srcy=%d)\n",
258 os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
, os
->srcx
, os
->srcy
));
260 ui_screenblt(ROP2_S(os
->opcode
), os
->x
, os
->y
, os
->cx
, os
->cy
, os
->srcx
, os
->srcy
);
263 /* Process a line order */
265 process_line(STREAM s
, LINE_ORDER
* os
, uint32 present
, BOOL delta
)
267 if (present
& 0x0001)
268 in_uint16_le(s
, os
->mixmode
);
270 if (present
& 0x0002)
271 rdp_in_coord(s
, &os
->startx
, delta
);
273 if (present
& 0x0004)
274 rdp_in_coord(s
, &os
->starty
, delta
);
276 if (present
& 0x0008)
277 rdp_in_coord(s
, &os
->endx
, delta
);
279 if (present
& 0x0010)
280 rdp_in_coord(s
, &os
->endy
, delta
);
282 if (present
& 0x0020)
283 rdp_in_colour(s
, &os
->bgcolour
);
285 if (present
& 0x0040)
286 in_uint8(s
, os
->opcode
);
288 rdp_parse_pen(s
, &os
->pen
, present
>> 7);
290 DEBUG(("LINE(op=0x%x,sx=%d,sy=%d,dx=%d,dy=%d,fg=0x%x)\n",
291 os
->opcode
, os
->startx
, os
->starty
, os
->endx
, os
->endy
, os
->pen
.colour
));
293 if (os
->opcode
< 0x01 || os
->opcode
> 0x10)
295 error("bad ROP2 0x%x\n", os
->opcode
);
299 ui_line(ROP_MINUS_1(os
->opcode
), os
->startx
, os
->starty
, os
->endx
, os
->endy
, &os
->pen
);
302 /* Process an opaque rectangle order */
304 process_rect(STREAM s
, RECT_ORDER
* os
, uint32 present
, BOOL delta
)
308 rdp_in_coord(s
, &os
->x
, delta
);
311 rdp_in_coord(s
, &os
->y
, delta
);
314 rdp_in_coord(s
, &os
->cx
, delta
);
317 rdp_in_coord(s
, &os
->cy
, delta
);
322 os
->colour
= (os
->colour
& 0xffffff00) | i
;
328 os
->colour
= (os
->colour
& 0xffff00ff) | (i
<< 8);
334 os
->colour
= (os
->colour
& 0xff00ffff) | (i
<< 16);
337 DEBUG(("RECT(x=%d,y=%d,cx=%d,cy=%d,fg=0x%x)\n", os
->x
, os
->y
, os
->cx
, os
->cy
, os
->colour
));
339 ui_rect(os
->x
, os
->y
, os
->cx
, os
->cy
, os
->colour
);
342 /* Process a desktop save order */
344 process_desksave(STREAM s
, DESKSAVE_ORDER
* os
, uint32 present
, BOOL delta
)
349 in_uint32_le(s
, os
->offset
);
352 rdp_in_coord(s
, &os
->left
, delta
);
355 rdp_in_coord(s
, &os
->top
, delta
);
358 rdp_in_coord(s
, &os
->right
, delta
);
361 rdp_in_coord(s
, &os
->bottom
, delta
);
364 in_uint8(s
, os
->action
);
366 DEBUG(("DESKSAVE(l=%d,t=%d,r=%d,b=%d,off=%d,op=%d)\n",
367 os
->left
, os
->top
, os
->right
, os
->bottom
, os
->offset
, os
->action
));
369 width
= os
->right
- os
->left
+ 1;
370 height
= os
->bottom
- os
->top
+ 1;
373 ui_desktop_save(os
->offset
, os
->left
, os
->top
, width
, height
);
375 ui_desktop_restore(os
->offset
, os
->left
, os
->top
, width
, height
);
378 /* Process a memory blt order */
380 process_memblt(STREAM s
, MEMBLT_ORDER
* os
, uint32 present
, BOOL delta
)
384 if (present
& 0x0001)
386 in_uint8(s
, os
->cache_id
);
387 in_uint8(s
, os
->colour_table
);
390 if (present
& 0x0002)
391 rdp_in_coord(s
, &os
->x
, delta
);
393 if (present
& 0x0004)
394 rdp_in_coord(s
, &os
->y
, delta
);
396 if (present
& 0x0008)
397 rdp_in_coord(s
, &os
->cx
, delta
);
399 if (present
& 0x0010)
400 rdp_in_coord(s
, &os
->cy
, delta
);
402 if (present
& 0x0020)
403 in_uint8(s
, os
->opcode
);
405 if (present
& 0x0040)
406 rdp_in_coord(s
, &os
->srcx
, delta
);
408 if (present
& 0x0080)
409 rdp_in_coord(s
, &os
->srcy
, delta
);
411 if (present
& 0x0100)
412 in_uint16_le(s
, os
->cache_idx
);
414 DEBUG(("MEMBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d)\n",
415 os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
, os
->cache_id
, os
->cache_idx
));
417 bitmap
= cache_get_bitmap(os
->cache_id
, os
->cache_idx
);
421 ui_memblt(ROP2_S(os
->opcode
), os
->x
, os
->y
, os
->cx
, os
->cy
, bitmap
, os
->srcx
, os
->srcy
);
424 /* Process a 3-way blt order */
426 process_triblt(STREAM s
, TRIBLT_ORDER
* os
, uint32 present
, BOOL delta
)
430 if (present
& 0x000001)
432 in_uint8(s
, os
->cache_id
);
433 in_uint8(s
, os
->colour_table
);
436 if (present
& 0x000002)
437 rdp_in_coord(s
, &os
->x
, delta
);
439 if (present
& 0x000004)
440 rdp_in_coord(s
, &os
->y
, delta
);
442 if (present
& 0x000008)
443 rdp_in_coord(s
, &os
->cx
, delta
);
445 if (present
& 0x000010)
446 rdp_in_coord(s
, &os
->cy
, delta
);
448 if (present
& 0x000020)
449 in_uint8(s
, os
->opcode
);
451 if (present
& 0x000040)
452 rdp_in_coord(s
, &os
->srcx
, delta
);
454 if (present
& 0x000080)
455 rdp_in_coord(s
, &os
->srcy
, delta
);
457 if (present
& 0x000100)
458 rdp_in_colour(s
, &os
->bgcolour
);
460 if (present
& 0x000200)
461 rdp_in_colour(s
, &os
->fgcolour
);
463 rdp_parse_brush(s
, &os
->brush
, present
>> 10);
465 if (present
& 0x008000)
466 in_uint16_le(s
, os
->cache_idx
);
468 if (present
& 0x010000)
469 in_uint16_le(s
, os
->unknown
);
471 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",
472 os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
, os
->cache_id
, os
->cache_idx
,
473 os
->brush
.style
, os
->bgcolour
, os
->fgcolour
));
475 bitmap
= cache_get_bitmap(os
->cache_id
, os
->cache_idx
);
479 ui_triblt(os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
,
480 bitmap
, os
->srcx
, os
->srcy
, &os
->brush
, os
->bgcolour
, os
->fgcolour
);
483 /* Process a polygon order */
485 process_polygon(STREAM s
, POLYGON_ORDER
* os
, uint32 present
, BOOL delta
)
487 int index
, data
, next
;
492 rdp_in_coord(s
, &os
->x
, delta
);
495 rdp_in_coord(s
, &os
->y
, delta
);
498 in_uint8(s
, os
->opcode
);
501 in_uint8(s
, os
->fillmode
);
504 rdp_in_colour(s
, &os
->fgcolour
);
507 in_uint8(s
, os
->npoints
);
511 in_uint8(s
, os
->datasize
);
512 in_uint8a(s
, os
->data
, os
->datasize
);
515 DEBUG(("POLYGON(x=%d,y=%d,op=0x%x,fm=%d,fg=0x%x,n=%d,sz=%d)\n",
516 os
->x
, os
->y
, os
->opcode
, os
->fillmode
, os
->fgcolour
, os
->npoints
, os
->datasize
));
520 for (index
= 0; index
< os
->datasize
; index
++)
521 DEBUG(("%02x ", os
->data
[index
]));
525 if (os
->opcode
< 0x01 || os
->opcode
> 0x10)
527 error("bad ROP2 0x%x\n", os
->opcode
);
531 points
= (POINT
*) xmalloc((os
->npoints
+ 1) * sizeof(POINT
));
532 memset(points
, 0, (os
->npoints
+ 1) * sizeof(POINT
));
538 data
= ((os
->npoints
- 1) / 4) + 1;
539 for (next
= 1; (next
<= os
->npoints
) && (next
< 256) && (data
< os
->datasize
); next
++)
541 if ((next
- 1) % 4 == 0)
542 flags
= os
->data
[index
++];
545 points
[next
].x
= parse_delta(os
->data
, &data
);
548 points
[next
].y
= parse_delta(os
->data
, &data
);
553 if (next
- 1 == os
->npoints
)
554 ui_polygon(ROP_MINUS_1(os
->opcode
), os
->fillmode
, points
, os
->npoints
+ 1, NULL
, 0,
557 error("polygon parse error\n");
562 /* Process a polygon2 order */
564 process_polygon2(STREAM s
, POLYGON2_ORDER
* os
, uint32 present
, BOOL delta
)
566 int index
, data
, next
;
570 if (present
& 0x0001)
571 rdp_in_coord(s
, &os
->x
, delta
);
573 if (present
& 0x0002)
574 rdp_in_coord(s
, &os
->y
, delta
);
576 if (present
& 0x0004)
577 in_uint8(s
, os
->opcode
);
579 if (present
& 0x0008)
580 in_uint8(s
, os
->fillmode
);
582 if (present
& 0x0010)
583 rdp_in_colour(s
, &os
->bgcolour
);
585 if (present
& 0x0020)
586 rdp_in_colour(s
, &os
->fgcolour
);
588 rdp_parse_brush(s
, &os
->brush
, present
>> 6);
590 if (present
& 0x0800)
591 in_uint8(s
, os
->npoints
);
593 if (present
& 0x1000)
595 in_uint8(s
, os
->datasize
);
596 in_uint8a(s
, os
->data
, os
->datasize
);
599 DEBUG(("POLYGON2(x=%d,y=%d,op=0x%x,fm=%d,bs=%d,bg=0x%x,fg=0x%x,n=%d,sz=%d)\n",
600 os
->x
, os
->y
, os
->opcode
, os
->fillmode
, os
->brush
.style
, os
->bgcolour
, os
->fgcolour
,
601 os
->npoints
, os
->datasize
));
605 for (index
= 0; index
< os
->datasize
; index
++)
606 DEBUG(("%02x ", os
->data
[index
]));
610 if (os
->opcode
< 0x01 || os
->opcode
> 0x10)
612 error("bad ROP2 0x%x\n", os
->opcode
);
616 points
= (POINT
*) xmalloc((os
->npoints
+ 1) * sizeof(POINT
));
617 memset(points
, 0, (os
->npoints
+ 1) * sizeof(POINT
));
623 data
= ((os
->npoints
- 1) / 4) + 1;
624 for (next
= 1; (next
<= os
->npoints
) && (next
< 256) && (data
< os
->datasize
); next
++)
626 if ((next
- 1) % 4 == 0)
627 flags
= os
->data
[index
++];
630 points
[next
].x
= parse_delta(os
->data
, &data
);
633 points
[next
].y
= parse_delta(os
->data
, &data
);
638 if (next
- 1 == os
->npoints
)
639 ui_polygon(ROP_MINUS_1(os
->opcode
), os
->fillmode
, points
, os
->npoints
+ 1,
640 &os
->brush
, os
->bgcolour
, os
->fgcolour
);
642 error("polygon2 parse error\n");
647 /* Process a polyline order */
649 process_polyline(STREAM s
, POLYLINE_ORDER
* os
, uint32 present
, BOOL delta
)
651 int index
, next
, data
;
657 rdp_in_coord(s
, &os
->x
, delta
);
660 rdp_in_coord(s
, &os
->y
, delta
);
663 in_uint8(s
, os
->opcode
);
666 rdp_in_colour(s
, &os
->fgcolour
);
669 in_uint8(s
, os
->lines
);
673 in_uint8(s
, os
->datasize
);
674 in_uint8a(s
, os
->data
, os
->datasize
);
677 DEBUG(("POLYLINE(x=%d,y=%d,op=0x%x,fg=0x%x,n=%d,sz=%d)\n",
678 os
->x
, os
->y
, os
->opcode
, os
->fgcolour
, os
->lines
, os
->datasize
));
682 for (index
= 0; index
< os
->datasize
; index
++)
683 DEBUG(("%02x ", os
->data
[index
]));
687 if (os
->opcode
< 0x01 || os
->opcode
> 0x10)
689 error("bad ROP2 0x%x\n", os
->opcode
);
693 points
= (POINT
*) xmalloc((os
->lines
+ 1) * sizeof(POINT
));
694 memset(points
, 0, (os
->lines
+ 1) * sizeof(POINT
));
698 pen
.style
= pen
.width
= 0;
699 pen
.colour
= os
->fgcolour
;
702 data
= ((os
->lines
- 1) / 4) + 1;
703 for (next
= 1; (next
<= os
->lines
) && (data
< os
->datasize
); next
++)
705 if ((next
- 1) % 4 == 0)
706 flags
= os
->data
[index
++];
709 points
[next
].x
= parse_delta(os
->data
, &data
);
712 points
[next
].y
= parse_delta(os
->data
, &data
);
717 if (next
- 1 == os
->lines
)
718 ui_polyline(ROP_MINUS_1(os
->opcode
), points
, os
->lines
+ 1, &pen
);
720 error("polyline parse error\n");
725 /* Process an ellipse order */
727 process_ellipse(STREAM s
, ELLIPSE_ORDER
* os
, uint32 present
, BOOL delta
)
730 rdp_in_coord(s
, &os
->left
, delta
);
733 rdp_in_coord(s
, &os
->top
, delta
);
736 rdp_in_coord(s
, &os
->right
, delta
);
739 rdp_in_coord(s
, &os
->bottom
, delta
);
742 in_uint8(s
, os
->opcode
);
745 in_uint8(s
, os
->fillmode
);
748 rdp_in_colour(s
, &os
->fgcolour
);
750 DEBUG(("ELLIPSE(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,fg=0x%x)\n", os
->left
, os
->top
,
751 os
->right
, os
->bottom
, os
->opcode
, os
->fillmode
, os
->fgcolour
));
753 ui_ellipse(ROP_MINUS_1(os
->opcode
), os
->fillmode
, os
->left
, os
->top
, os
->right
- os
->left
,
754 os
->bottom
- os
->top
, NULL
, 0, os
->fgcolour
);
757 /* Process an ellipse2 order */
759 process_ellipse2(STREAM s
, ELLIPSE2_ORDER
* os
, uint32 present
, BOOL delta
)
761 if (present
& 0x0001)
762 rdp_in_coord(s
, &os
->left
, delta
);
764 if (present
& 0x0002)
765 rdp_in_coord(s
, &os
->top
, delta
);
767 if (present
& 0x0004)
768 rdp_in_coord(s
, &os
->right
, delta
);
770 if (present
& 0x0008)
771 rdp_in_coord(s
, &os
->bottom
, delta
);
773 if (present
& 0x0010)
774 in_uint8(s
, os
->opcode
);
776 if (present
& 0x0020)
777 in_uint8(s
, os
->fillmode
);
779 if (present
& 0x0040)
780 rdp_in_colour(s
, &os
->bgcolour
);
782 if (present
& 0x0080)
783 rdp_in_colour(s
, &os
->fgcolour
);
785 rdp_parse_brush(s
, &os
->brush
, present
>> 8);
787 DEBUG(("ELLIPSE2(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,bs=%d,bg=0x%x,fg=0x%x)\n",
788 os
->left
, os
->top
, os
->right
, os
->bottom
, os
->opcode
, os
->fillmode
, os
->brush
.style
,
789 os
->bgcolour
, os
->fgcolour
));
791 ui_ellipse(ROP_MINUS_1(os
->opcode
), os
->fillmode
, os
->left
, os
->top
, os
->right
- os
->left
,
792 os
->bottom
- os
->top
, &os
->brush
, os
->bgcolour
, os
->fgcolour
);
795 /* Process a text order */
797 process_text2(STREAM s
, TEXT2_ORDER
* os
, uint32 present
, BOOL delta
)
801 if (present
& 0x000001)
802 in_uint8(s
, os
->font
);
804 if (present
& 0x000002)
805 in_uint8(s
, os
->flags
);
807 if (present
& 0x000004)
808 in_uint8(s
, os
->opcode
);
810 if (present
& 0x000008)
811 in_uint8(s
, os
->mixmode
);
813 if (present
& 0x000010)
814 rdp_in_colour(s
, &os
->fgcolour
);
816 if (present
& 0x000020)
817 rdp_in_colour(s
, &os
->bgcolour
);
819 if (present
& 0x000040)
820 in_uint16_le(s
, os
->clipleft
);
822 if (present
& 0x000080)
823 in_uint16_le(s
, os
->cliptop
);
825 if (present
& 0x000100)
826 in_uint16_le(s
, os
->clipright
);
828 if (present
& 0x000200)
829 in_uint16_le(s
, os
->clipbottom
);
831 if (present
& 0x000400)
832 in_uint16_le(s
, os
->boxleft
);
834 if (present
& 0x000800)
835 in_uint16_le(s
, os
->boxtop
);
837 if (present
& 0x001000)
838 in_uint16_le(s
, os
->boxright
);
840 if (present
& 0x002000)
841 in_uint16_le(s
, os
->boxbottom
);
843 rdp_parse_brush(s
, &os
->brush
, present
>> 14);
845 if (present
& 0x080000)
846 in_uint16_le(s
, os
->x
);
848 if (present
& 0x100000)
849 in_uint16_le(s
, os
->y
);
851 if (present
& 0x200000)
853 in_uint8(s
, os
->length
);
854 in_uint8a(s
, os
->text
, os
->length
);
857 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
));
861 for (i
= 0; i
< os
->length
; i
++)
862 DEBUG(("%02x ", os
->text
[i
]));
866 ui_draw_text(os
->font
, os
->flags
, ROP_MINUS_1(os
->opcode
), os
->mixmode
, os
->x
, os
->y
,
867 os
->clipleft
, os
->cliptop
, os
->clipright
- os
->clipleft
,
868 os
->clipbottom
- os
->cliptop
, os
->boxleft
, os
->boxtop
,
869 os
->boxright
- os
->boxleft
, os
->boxbottom
- os
->boxtop
,
870 &os
->brush
, os
->bgcolour
, os
->fgcolour
, os
->text
, os
->length
);
873 /* Process a raw bitmap cache order */
875 process_raw_bmpcache(STREAM s
)
878 uint16 cache_idx
, bufsize
;
879 uint8 cache_id
, width
, height
, bpp
, Bpp
;
880 uint8
*data
, *inverted
;
883 in_uint8(s
, cache_id
);
884 in_uint8s(s
, 1); /* pad */
889 in_uint16_le(s
, bufsize
);
890 in_uint16_le(s
, cache_idx
);
891 in_uint8p(s
, data
, bufsize
);
893 DEBUG(("RAW_BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n", width
, height
, cache_id
, cache_idx
));
894 inverted
= (uint8
*) xmalloc(width
* height
* Bpp
);
895 for (y
= 0; y
< height
; y
++)
897 memcpy(&inverted
[(height
- y
- 1) * (width
* Bpp
)], &data
[y
* (width
* Bpp
)],
901 bitmap
= ui_create_bitmap(width
, height
, inverted
);
903 cache_put_bitmap(cache_id
, cache_idx
, bitmap
);
906 /* Process a bitmap cache order */
908 process_bmpcache(STREAM s
)
911 uint16 cache_idx
, size
;
912 uint8 cache_id
, width
, height
, bpp
, Bpp
;
913 uint8
*data
, *bmpdata
;
914 uint16 bufsize
, pad2
, row_size
, final_size
;
917 pad2
= row_size
= final_size
= 0xffff; /* Shut the compiler up */
919 in_uint8(s
, cache_id
);
920 in_uint8(s
, pad1
); /* pad */
925 in_uint16_le(s
, bufsize
); /* bufsize */
926 in_uint16_le(s
, cache_idx
);
935 /* Begin compressedBitmapData */
936 in_uint16_le(s
, pad2
); /* pad */
937 in_uint16_le(s
, size
);
938 /* in_uint8s(s, 4); *//* row_size, final_size */
939 in_uint16_le(s
, row_size
);
940 in_uint16_le(s
, final_size
);
943 in_uint8p(s
, data
, size
);
945 DEBUG(("BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d,bpp=%d,size=%d,pad1=%d,bufsize=%d,pad2=%d,rs=%d,fs=%d)\n", width
, height
, cache_id
, cache_idx
, bpp
, size
, pad1
, bufsize
, pad2
, row_size
, final_size
));
947 bmpdata
= (uint8
*) xmalloc(width
* height
* Bpp
);
949 if (bitmap_decompress(bmpdata
, width
, height
, data
, size
, Bpp
))
951 bitmap
= ui_create_bitmap(width
, height
, bmpdata
);
952 cache_put_bitmap(cache_id
, cache_idx
, bitmap
);
956 DEBUG(("Failed to decompress bitmap data\n"));
962 /* Process a bitmap cache v2 order */
964 process_bmpcache2(STREAM s
, uint16 flags
, BOOL compressed
)
968 uint8 cache_id
, cache_idx_low
, width
, height
, Bpp
;
969 uint16 cache_idx
, bufsize
;
970 uint8
*data
, *bmpdata
, *bitmap_id
;
972 bitmap_id
= NULL
; /* prevent compiler warning */
973 cache_id
= flags
& ID_MASK
;
974 Bpp
= ((flags
& MODE_MASK
) >> MODE_SHIFT
) - 2;
978 in_uint8p(s
, bitmap_id
, 8);
992 in_uint16_be(s
, bufsize
);
993 bufsize
&= BUFSIZE_MASK
;
994 in_uint8(s
, cache_idx
);
996 if (cache_idx
& LONG_FORMAT
)
998 in_uint8(s
, cache_idx_low
);
999 cache_idx
= ((cache_idx
^ LONG_FORMAT
) << 8) + cache_idx_low
;
1002 in_uint8p(s
, data
, bufsize
);
1004 DEBUG(("BMPCACHE2(compr=%d,flags=%x,cx=%d,cy=%d,id=%d,idx=%d,Bpp=%d,bs=%d)\n",
1005 compressed
, flags
, width
, height
, cache_id
, cache_idx
, Bpp
, bufsize
));
1007 bmpdata
= (uint8
*) xmalloc(width
* height
* Bpp
);
1011 if (!bitmap_decompress(bmpdata
, width
, height
, data
, bufsize
, Bpp
))
1013 DEBUG(("Failed to decompress bitmap data\n"));
1020 for (y
= 0; y
< height
; y
++)
1021 memcpy(&bmpdata
[(height
- y
- 1) * (width
* Bpp
)],
1022 &data
[y
* (width
* Bpp
)], width
* Bpp
);
1025 bitmap
= ui_create_bitmap(width
, height
, bmpdata
);
1029 cache_put_bitmap(cache_id
, cache_idx
, bitmap
);
1030 if (flags
& PERSIST
)
1031 pstcache_save_bitmap(cache_id
, cache_idx
, bitmap_id
, width
, height
,
1032 (uint16
) (width
* height
* Bpp
), bmpdata
);
1036 DEBUG(("process_bmpcache2: ui_create_bitmap failed\n"));
1042 /* Process a colourmap cache order */
1044 process_colcache(STREAM s
)
1052 in_uint8(s
, cache_id
);
1053 in_uint16_le(s
, map
.ncolours
);
1055 map
.colours
= (COLOURENTRY
*) xmalloc(sizeof(COLOURENTRY
) * map
.ncolours
);
1057 for (i
= 0; i
< map
.ncolours
; i
++)
1059 entry
= &map
.colours
[i
];
1060 in_uint8(s
, entry
->blue
);
1061 in_uint8(s
, entry
->green
);
1062 in_uint8(s
, entry
->red
);
1063 in_uint8s(s
, 1); /* pad */
1066 DEBUG(("COLCACHE(id=%d,n=%d)\n", cache_id
, map
.ncolours
));
1068 hmap
= ui_create_colourmap(&map
);
1071 ui_set_colourmap(hmap
);
1076 /* Process a font cache order */
1078 process_fontcache(STREAM s
)
1081 uint8 font
, nglyphs
;
1082 uint16 character
, offset
, baseline
, width
, height
;
1087 in_uint8(s
, nglyphs
);
1089 DEBUG(("FONTCACHE(font=%d,n=%d)\n", font
, nglyphs
));
1091 for (i
= 0; i
< nglyphs
; i
++)
1093 in_uint16_le(s
, character
);
1094 in_uint16_le(s
, offset
);
1095 in_uint16_le(s
, baseline
);
1096 in_uint16_le(s
, width
);
1097 in_uint16_le(s
, height
);
1099 datasize
= (height
* ((width
+ 7) / 8) + 3) & ~3;
1100 in_uint8p(s
, data
, datasize
);
1102 bitmap
= ui_create_glyph(width
, height
, data
);
1103 cache_put_font(font
, character
, offset
, baseline
, width
, height
, bitmap
);
1107 /* Process a secondary order */
1109 process_secondary_order(STREAM s
)
1111 /* The length isn't calculated correctly by the server.
1112 * For very compact orders the length becomes negative
1113 * so a signed integer must be used. */
1119 in_uint16_le(s
, length
);
1120 in_uint16_le(s
, flags
); /* used by bmpcache2 */
1123 next_order
= s
->p
+ (sint16
) length
+ 7;
1127 case RDP_ORDER_RAW_BMPCACHE
:
1128 process_raw_bmpcache(s
);
1131 case RDP_ORDER_COLCACHE
:
1132 process_colcache(s
);
1135 case RDP_ORDER_BMPCACHE
:
1136 process_bmpcache(s
);
1139 case RDP_ORDER_FONTCACHE
:
1140 process_fontcache(s
);
1143 case RDP_ORDER_RAW_BMPCACHE2
:
1144 process_bmpcache2(s
, flags
, False
); /* uncompressed */
1147 case RDP_ORDER_BMPCACHE2
:
1148 process_bmpcache2(s
, flags
, True
); /* compressed */
1152 unimpl("secondary order %d\n", type
);
1158 /* Process an order PDU */
1160 process_orders(STREAM s
, uint16 num_orders
)
1162 RDP_ORDER_STATE
*os
= &g_order_state
;
1165 int size
, processed
= 0;
1168 while (processed
< num_orders
)
1170 in_uint8(s
, order_flags
);
1172 if (!(order_flags
& RDP_ORDER_STANDARD
))
1174 error("order parsing failed\n");
1178 if (order_flags
& RDP_ORDER_SECONDARY
)
1180 process_secondary_order(s
);
1184 if (order_flags
& RDP_ORDER_CHANGE
)
1186 in_uint8(s
, os
->order_type
);
1189 switch (os
->order_type
)
1191 case RDP_ORDER_TRIBLT
:
1192 case RDP_ORDER_TEXT2
:
1196 case RDP_ORDER_PATBLT
:
1197 case RDP_ORDER_MEMBLT
:
1198 case RDP_ORDER_LINE
:
1199 case RDP_ORDER_POLYGON2
:
1200 case RDP_ORDER_ELLIPSE2
:
1208 rdp_in_present(s
, &present
, order_flags
, size
);
1210 if (order_flags
& RDP_ORDER_BOUNDS
)
1212 if (!(order_flags
& RDP_ORDER_LASTBOUNDS
))
1213 rdp_parse_bounds(s
, &os
->bounds
);
1215 ui_set_clip(os
->bounds
.left
,
1218 os
->bounds
.left
+ 1,
1219 os
->bounds
.bottom
- os
->bounds
.top
+ 1);
1222 delta
= order_flags
& RDP_ORDER_DELTA
;
1224 switch (os
->order_type
)
1226 case RDP_ORDER_DESTBLT
:
1227 process_destblt(s
, &os
->destblt
, present
, delta
);
1230 case RDP_ORDER_PATBLT
:
1231 process_patblt(s
, &os
->patblt
, present
, delta
);
1234 case RDP_ORDER_SCREENBLT
:
1235 process_screenblt(s
, &os
->screenblt
, present
, delta
);
1238 case RDP_ORDER_LINE
:
1239 process_line(s
, &os
->line
, present
, delta
);
1242 case RDP_ORDER_RECT
:
1243 process_rect(s
, &os
->rect
, present
, delta
);
1246 case RDP_ORDER_DESKSAVE
:
1247 process_desksave(s
, &os
->desksave
, present
, delta
);
1250 case RDP_ORDER_MEMBLT
:
1251 process_memblt(s
, &os
->memblt
, present
, delta
);
1254 case RDP_ORDER_TRIBLT
:
1255 process_triblt(s
, &os
->triblt
, present
, delta
);
1258 case RDP_ORDER_POLYGON
:
1259 process_polygon(s
, &os
->polygon
, present
, delta
);
1262 case RDP_ORDER_POLYGON2
:
1263 process_polygon2(s
, &os
->polygon2
, present
, delta
);
1266 case RDP_ORDER_POLYLINE
:
1267 process_polyline(s
, &os
->polyline
, present
, delta
);
1270 case RDP_ORDER_ELLIPSE
:
1271 process_ellipse(s
, &os
->ellipse
, present
, delta
);
1274 case RDP_ORDER_ELLIPSE2
:
1275 process_ellipse2(s
, &os
->ellipse2
, present
, delta
);
1278 case RDP_ORDER_TEXT2
:
1279 process_text2(s
, &os
->text2
, present
, delta
);
1283 unimpl("order %d\n", os
->order_type
);
1287 if (order_flags
& RDP_ORDER_BOUNDS
)
1294 /* not true when RDP_COMPRESSION is set */
1295 if (s
->p
!= g_next_packet
)
1296 error("%d bytes remaining\n", (int) (g_next_packet
- s
->p
));
1301 /* Reset order state */
1303 reset_order_state(void)
1305 memset(&g_order_state
, 0, sizeof(g_order_state
));
1306 g_order_state
.order_type
= RDP_ORDER_PATBLT
;