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 along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 extern uint8
*g_next_packet
;
26 static RDP_ORDER_STATE g_order_state
;
27 extern BOOL g_use_rdp5
;
29 /* Read field indicating which parameters are present */
31 rdp_in_present(STREAM s
, uint32
* present
, uint8 flags
, int size
)
36 if (flags
& RDP_ORDER_SMALL
)
41 if (flags
& RDP_ORDER_TINY
)
50 for (i
= 0; i
< size
; i
++)
53 *present
|= bits
<< (i
* 8);
57 /* Read a co-ordinate (16-bit, or 8-bit delta) */
59 rdp_in_coord(STREAM s
, sint16
* coord
, BOOL delta
)
70 in_uint16_le(s
, *coord
);
74 /* Parse a delta co-ordinate in polyline/polygon order form */
76 parse_delta(uint8
* buffer
, int *offset
)
78 int value
= buffer
[(*offset
)++];
79 int two_byte
= value
& 0x80;
81 if (value
& 0x40) /* sign bit */
87 value
= (value
<< 8) | buffer
[(*offset
)++];
92 /* Read a colour entry */
94 rdp_in_colour(STREAM s
, uint32
* colour
)
105 /* Parse bounds information */
107 rdp_parse_bounds(STREAM s
, BOUNDS
* bounds
)
111 in_uint8(s
, present
);
114 rdp_in_coord(s
, &bounds
->left
, False
);
115 else if (present
& 16)
116 rdp_in_coord(s
, &bounds
->left
, True
);
119 rdp_in_coord(s
, &bounds
->top
, False
);
120 else if (present
& 32)
121 rdp_in_coord(s
, &bounds
->top
, True
);
124 rdp_in_coord(s
, &bounds
->right
, False
);
125 else if (present
& 64)
126 rdp_in_coord(s
, &bounds
->right
, True
);
129 rdp_in_coord(s
, &bounds
->bottom
, False
);
130 else if (present
& 128)
131 rdp_in_coord(s
, &bounds
->bottom
, True
);
138 rdp_parse_pen(STREAM s
, PEN
* pen
, uint32 present
)
141 in_uint8(s
, pen
->style
);
144 in_uint8(s
, pen
->width
);
147 rdp_in_colour(s
, &pen
->colour
);
154 rdp_parse_brush(STREAM s
, BRUSH
* brush
, uint32 present
)
157 in_uint8(s
, brush
->xorigin
);
160 in_uint8(s
, brush
->yorigin
);
163 in_uint8(s
, brush
->style
);
166 in_uint8(s
, brush
->pattern
[0]);
169 in_uint8a(s
, &brush
->pattern
[1], 7);
174 /* Process a destination blt order */
176 process_destblt(STREAM s
, DESTBLT_ORDER
* os
, uint32 present
, BOOL delta
)
179 rdp_in_coord(s
, &os
->x
, delta
);
182 rdp_in_coord(s
, &os
->y
, delta
);
185 rdp_in_coord(s
, &os
->cx
, delta
);
188 rdp_in_coord(s
, &os
->cy
, delta
);
191 in_uint8(s
, os
->opcode
);
193 DEBUG(("DESTBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d)\n",
194 os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
));
196 ui_destblt(ROP2_S(os
->opcode
), os
->x
, os
->y
, os
->cx
, os
->cy
);
199 /* Process a pattern blt order */
201 process_patblt(STREAM s
, PATBLT_ORDER
* os
, uint32 present
, BOOL delta
)
203 if (present
& 0x0001)
204 rdp_in_coord(s
, &os
->x
, delta
);
206 if (present
& 0x0002)
207 rdp_in_coord(s
, &os
->y
, delta
);
209 if (present
& 0x0004)
210 rdp_in_coord(s
, &os
->cx
, delta
);
212 if (present
& 0x0008)
213 rdp_in_coord(s
, &os
->cy
, delta
);
215 if (present
& 0x0010)
216 in_uint8(s
, os
->opcode
);
218 if (present
& 0x0020)
219 rdp_in_colour(s
, &os
->bgcolour
);
221 if (present
& 0x0040)
222 rdp_in_colour(s
, &os
->fgcolour
);
224 rdp_parse_brush(s
, &os
->brush
, present
>> 7);
226 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
,
227 os
->y
, os
->cx
, os
->cy
, os
->brush
.style
, os
->bgcolour
, os
->fgcolour
));
229 ui_patblt(ROP2_P(os
->opcode
), os
->x
, os
->y
, os
->cx
, os
->cy
,
230 &os
->brush
, os
->bgcolour
, os
->fgcolour
);
233 /* Process a screen blt order */
235 process_screenblt(STREAM s
, SCREENBLT_ORDER
* os
, uint32 present
, BOOL delta
)
237 if (present
& 0x0001)
238 rdp_in_coord(s
, &os
->x
, delta
);
240 if (present
& 0x0002)
241 rdp_in_coord(s
, &os
->y
, delta
);
243 if (present
& 0x0004)
244 rdp_in_coord(s
, &os
->cx
, delta
);
246 if (present
& 0x0008)
247 rdp_in_coord(s
, &os
->cy
, delta
);
249 if (present
& 0x0010)
250 in_uint8(s
, os
->opcode
);
252 if (present
& 0x0020)
253 rdp_in_coord(s
, &os
->srcx
, delta
);
255 if (present
& 0x0040)
256 rdp_in_coord(s
, &os
->srcy
, delta
);
258 DEBUG(("SCREENBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,srcx=%d,srcy=%d)\n",
259 os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
, os
->srcx
, os
->srcy
));
261 ui_screenblt(ROP2_S(os
->opcode
), os
->x
, os
->y
, os
->cx
, os
->cy
, os
->srcx
, os
->srcy
);
264 /* Process a line order */
266 process_line(STREAM s
, LINE_ORDER
* os
, uint32 present
, BOOL delta
)
268 if (present
& 0x0001)
269 in_uint16_le(s
, os
->mixmode
);
271 if (present
& 0x0002)
272 rdp_in_coord(s
, &os
->startx
, delta
);
274 if (present
& 0x0004)
275 rdp_in_coord(s
, &os
->starty
, delta
);
277 if (present
& 0x0008)
278 rdp_in_coord(s
, &os
->endx
, delta
);
280 if (present
& 0x0010)
281 rdp_in_coord(s
, &os
->endy
, delta
);
283 if (present
& 0x0020)
284 rdp_in_colour(s
, &os
->bgcolour
);
286 if (present
& 0x0040)
287 in_uint8(s
, os
->opcode
);
289 rdp_parse_pen(s
, &os
->pen
, present
>> 7);
291 DEBUG(("LINE(op=0x%x,sx=%d,sy=%d,dx=%d,dy=%d,fg=0x%x)\n",
292 os
->opcode
, os
->startx
, os
->starty
, os
->endx
, os
->endy
, os
->pen
.colour
));
294 if (os
->opcode
< 0x01 || os
->opcode
> 0x10)
296 error("bad ROP2 0x%x\n", os
->opcode
);
300 ui_line(ROP_MINUS_1(os
->opcode
), os
->startx
, os
->starty
, os
->endx
, os
->endy
, &os
->pen
);
303 /* Process an opaque rectangle order */
305 process_rect(STREAM s
, RECT_ORDER
* os
, uint32 present
, BOOL delta
)
309 rdp_in_coord(s
, &os
->x
, delta
);
312 rdp_in_coord(s
, &os
->y
, delta
);
315 rdp_in_coord(s
, &os
->cx
, delta
);
318 rdp_in_coord(s
, &os
->cy
, delta
);
323 os
->colour
= (os
->colour
& 0xffffff00) | i
;
329 os
->colour
= (os
->colour
& 0xffff00ff) | (i
<< 8);
335 os
->colour
= (os
->colour
& 0xff00ffff) | (i
<< 16);
338 DEBUG(("RECT(x=%d,y=%d,cx=%d,cy=%d,fg=0x%x)\n", os
->x
, os
->y
, os
->cx
, os
->cy
, os
->colour
));
340 ui_rect(os
->x
, os
->y
, os
->cx
, os
->cy
, os
->colour
);
343 /* Process a desktop save order */
345 process_desksave(STREAM s
, DESKSAVE_ORDER
* os
, uint32 present
, BOOL delta
)
350 in_uint32_le(s
, os
->offset
);
353 rdp_in_coord(s
, &os
->left
, delta
);
356 rdp_in_coord(s
, &os
->top
, delta
);
359 rdp_in_coord(s
, &os
->right
, delta
);
362 rdp_in_coord(s
, &os
->bottom
, delta
);
365 in_uint8(s
, os
->action
);
367 DEBUG(("DESKSAVE(l=%d,t=%d,r=%d,b=%d,off=%d,op=%d)\n",
368 os
->left
, os
->top
, os
->right
, os
->bottom
, os
->offset
, os
->action
));
370 width
= os
->right
- os
->left
+ 1;
371 height
= os
->bottom
- os
->top
+ 1;
374 ui_desktop_save(os
->offset
, os
->left
, os
->top
, width
, height
);
376 ui_desktop_restore(os
->offset
, os
->left
, os
->top
, width
, height
);
379 /* Process a memory blt order */
381 process_memblt(STREAM s
, MEMBLT_ORDER
* os
, uint32 present
, BOOL delta
)
385 if (present
& 0x0001)
387 in_uint8(s
, os
->cache_id
);
388 in_uint8(s
, os
->colour_table
);
391 if (present
& 0x0002)
392 rdp_in_coord(s
, &os
->x
, delta
);
394 if (present
& 0x0004)
395 rdp_in_coord(s
, &os
->y
, delta
);
397 if (present
& 0x0008)
398 rdp_in_coord(s
, &os
->cx
, delta
);
400 if (present
& 0x0010)
401 rdp_in_coord(s
, &os
->cy
, delta
);
403 if (present
& 0x0020)
404 in_uint8(s
, os
->opcode
);
406 if (present
& 0x0040)
407 rdp_in_coord(s
, &os
->srcx
, delta
);
409 if (present
& 0x0080)
410 rdp_in_coord(s
, &os
->srcy
, delta
);
412 if (present
& 0x0100)
413 in_uint16_le(s
, os
->cache_idx
);
415 DEBUG(("MEMBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d)\n",
416 os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
, os
->cache_id
, os
->cache_idx
));
418 bitmap
= cache_get_bitmap(os
->cache_id
, os
->cache_idx
);
422 ui_memblt(ROP2_S(os
->opcode
), os
->x
, os
->y
, os
->cx
, os
->cy
, bitmap
, os
->srcx
, os
->srcy
);
425 /* Process a 3-way blt order */
427 process_triblt(STREAM s
, TRIBLT_ORDER
* os
, uint32 present
, BOOL delta
)
431 if (present
& 0x000001)
433 in_uint8(s
, os
->cache_id
);
434 in_uint8(s
, os
->colour_table
);
437 if (present
& 0x000002)
438 rdp_in_coord(s
, &os
->x
, delta
);
440 if (present
& 0x000004)
441 rdp_in_coord(s
, &os
->y
, delta
);
443 if (present
& 0x000008)
444 rdp_in_coord(s
, &os
->cx
, delta
);
446 if (present
& 0x000010)
447 rdp_in_coord(s
, &os
->cy
, delta
);
449 if (present
& 0x000020)
450 in_uint8(s
, os
->opcode
);
452 if (present
& 0x000040)
453 rdp_in_coord(s
, &os
->srcx
, delta
);
455 if (present
& 0x000080)
456 rdp_in_coord(s
, &os
->srcy
, delta
);
458 if (present
& 0x000100)
459 rdp_in_colour(s
, &os
->bgcolour
);
461 if (present
& 0x000200)
462 rdp_in_colour(s
, &os
->fgcolour
);
464 rdp_parse_brush(s
, &os
->brush
, present
>> 10);
466 if (present
& 0x008000)
467 in_uint16_le(s
, os
->cache_idx
);
469 if (present
& 0x010000)
470 in_uint16_le(s
, os
->unknown
);
472 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",
473 os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
, os
->cache_id
, os
->cache_idx
,
474 os
->brush
.style
, os
->bgcolour
, os
->fgcolour
));
476 bitmap
= cache_get_bitmap(os
->cache_id
, os
->cache_idx
);
480 ui_triblt(os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
,
481 bitmap
, os
->srcx
, os
->srcy
, &os
->brush
, os
->bgcolour
, os
->fgcolour
);
484 /* Process a polygon order */
486 process_polygon(STREAM s
, POLYGON_ORDER
* os
, uint32 present
, BOOL delta
)
488 int index
, data
, next
;
493 rdp_in_coord(s
, &os
->x
, delta
);
496 rdp_in_coord(s
, &os
->y
, delta
);
499 in_uint8(s
, os
->opcode
);
502 in_uint8(s
, os
->fillmode
);
505 rdp_in_colour(s
, &os
->fgcolour
);
508 in_uint8(s
, os
->npoints
);
512 in_uint8(s
, os
->datasize
);
513 in_uint8a(s
, os
->data
, os
->datasize
);
516 DEBUG(("POLYGON(x=%d,y=%d,op=0x%x,fm=%d,fg=0x%x,n=%d,sz=%d)\n",
517 os
->x
, os
->y
, os
->opcode
, os
->fillmode
, os
->fgcolour
, os
->npoints
, os
->datasize
));
521 for (index
= 0; index
< os
->datasize
; index
++)
522 DEBUG(("%02x ", os
->data
[index
]));
526 if (os
->opcode
< 0x01 || os
->opcode
> 0x10)
528 error("bad ROP2 0x%x\n", os
->opcode
);
532 points
= (POINT
*) xmalloc((os
->npoints
+ 1) * sizeof(POINT
));
533 memset(points
, 0, (os
->npoints
+ 1) * sizeof(POINT
));
539 data
= ((os
->npoints
- 1) / 4) + 1;
540 for (next
= 1; (next
<= os
->npoints
) && (next
< 256) && (data
< os
->datasize
); next
++)
542 if ((next
- 1) % 4 == 0)
543 flags
= os
->data
[index
++];
546 points
[next
].x
= parse_delta(os
->data
, &data
);
549 points
[next
].y
= parse_delta(os
->data
, &data
);
554 if (next
- 1 == os
->npoints
)
555 ui_polygon(ROP_MINUS_1(os
->opcode
), os
->fillmode
, points
, os
->npoints
+ 1, NULL
, 0,
558 error("polygon parse error\n");
563 /* Process a polygon2 order */
565 process_polygon2(STREAM s
, POLYGON2_ORDER
* os
, uint32 present
, BOOL delta
)
567 int index
, data
, next
;
571 if (present
& 0x0001)
572 rdp_in_coord(s
, &os
->x
, delta
);
574 if (present
& 0x0002)
575 rdp_in_coord(s
, &os
->y
, delta
);
577 if (present
& 0x0004)
578 in_uint8(s
, os
->opcode
);
580 if (present
& 0x0008)
581 in_uint8(s
, os
->fillmode
);
583 if (present
& 0x0010)
584 rdp_in_colour(s
, &os
->bgcolour
);
586 if (present
& 0x0020)
587 rdp_in_colour(s
, &os
->fgcolour
);
589 rdp_parse_brush(s
, &os
->brush
, present
>> 6);
591 if (present
& 0x0800)
592 in_uint8(s
, os
->npoints
);
594 if (present
& 0x1000)
596 in_uint8(s
, os
->datasize
);
597 in_uint8a(s
, os
->data
, os
->datasize
);
600 DEBUG(("POLYGON2(x=%d,y=%d,op=0x%x,fm=%d,bs=%d,bg=0x%x,fg=0x%x,n=%d,sz=%d)\n",
601 os
->x
, os
->y
, os
->opcode
, os
->fillmode
, os
->brush
.style
, os
->bgcolour
, os
->fgcolour
,
602 os
->npoints
, os
->datasize
));
606 for (index
= 0; index
< os
->datasize
; index
++)
607 DEBUG(("%02x ", os
->data
[index
]));
611 if (os
->opcode
< 0x01 || os
->opcode
> 0x10)
613 error("bad ROP2 0x%x\n", os
->opcode
);
617 points
= (POINT
*) xmalloc((os
->npoints
+ 1) * sizeof(POINT
));
618 memset(points
, 0, (os
->npoints
+ 1) * sizeof(POINT
));
624 data
= ((os
->npoints
- 1) / 4) + 1;
625 for (next
= 1; (next
<= os
->npoints
) && (next
< 256) && (data
< os
->datasize
); next
++)
627 if ((next
- 1) % 4 == 0)
628 flags
= os
->data
[index
++];
631 points
[next
].x
= parse_delta(os
->data
, &data
);
634 points
[next
].y
= parse_delta(os
->data
, &data
);
639 if (next
- 1 == os
->npoints
)
640 ui_polygon(ROP_MINUS_1(os
->opcode
), os
->fillmode
, points
, os
->npoints
+ 1,
641 &os
->brush
, os
->bgcolour
, os
->fgcolour
);
643 error("polygon2 parse error\n");
648 /* Process a polyline order */
650 process_polyline(STREAM s
, POLYLINE_ORDER
* os
, uint32 present
, BOOL delta
)
652 int index
, next
, data
;
658 rdp_in_coord(s
, &os
->x
, delta
);
661 rdp_in_coord(s
, &os
->y
, delta
);
664 in_uint8(s
, os
->opcode
);
667 rdp_in_colour(s
, &os
->fgcolour
);
670 in_uint8(s
, os
->lines
);
674 in_uint8(s
, os
->datasize
);
675 in_uint8a(s
, os
->data
, os
->datasize
);
678 DEBUG(("POLYLINE(x=%d,y=%d,op=0x%x,fg=0x%x,n=%d,sz=%d)\n",
679 os
->x
, os
->y
, os
->opcode
, os
->fgcolour
, os
->lines
, os
->datasize
));
683 for (index
= 0; index
< os
->datasize
; index
++)
684 DEBUG(("%02x ", os
->data
[index
]));
688 if (os
->opcode
< 0x01 || os
->opcode
> 0x10)
690 error("bad ROP2 0x%x\n", os
->opcode
);
694 points
= (POINT
*) xmalloc((os
->lines
+ 1) * sizeof(POINT
));
695 memset(points
, 0, (os
->lines
+ 1) * sizeof(POINT
));
699 pen
.style
= pen
.width
= 0;
700 pen
.colour
= os
->fgcolour
;
703 data
= ((os
->lines
- 1) / 4) + 1;
704 for (next
= 1; (next
<= os
->lines
) && (data
< os
->datasize
); next
++)
706 if ((next
- 1) % 4 == 0)
707 flags
= os
->data
[index
++];
710 points
[next
].x
= parse_delta(os
->data
, &data
);
713 points
[next
].y
= parse_delta(os
->data
, &data
);
718 if (next
- 1 == os
->lines
)
719 ui_polyline(ROP_MINUS_1(os
->opcode
), points
, os
->lines
+ 1, &pen
);
721 error("polyline parse error\n");
726 /* Process an ellipse order */
728 process_ellipse(STREAM s
, ELLIPSE_ORDER
* os
, uint32 present
, BOOL delta
)
731 rdp_in_coord(s
, &os
->left
, delta
);
734 rdp_in_coord(s
, &os
->top
, delta
);
737 rdp_in_coord(s
, &os
->right
, delta
);
740 rdp_in_coord(s
, &os
->bottom
, delta
);
743 in_uint8(s
, os
->opcode
);
746 in_uint8(s
, os
->fillmode
);
749 rdp_in_colour(s
, &os
->fgcolour
);
751 DEBUG(("ELLIPSE(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,fg=0x%x)\n", os
->left
, os
->top
,
752 os
->right
, os
->bottom
, os
->opcode
, os
->fillmode
, os
->fgcolour
));
754 ui_ellipse(ROP_MINUS_1(os
->opcode
), os
->fillmode
, os
->left
, os
->top
, os
->right
- os
->left
,
755 os
->bottom
- os
->top
, NULL
, 0, os
->fgcolour
);
758 /* Process an ellipse2 order */
760 process_ellipse2(STREAM s
, ELLIPSE2_ORDER
* os
, uint32 present
, BOOL delta
)
762 if (present
& 0x0001)
763 rdp_in_coord(s
, &os
->left
, delta
);
765 if (present
& 0x0002)
766 rdp_in_coord(s
, &os
->top
, delta
);
768 if (present
& 0x0004)
769 rdp_in_coord(s
, &os
->right
, delta
);
771 if (present
& 0x0008)
772 rdp_in_coord(s
, &os
->bottom
, delta
);
774 if (present
& 0x0010)
775 in_uint8(s
, os
->opcode
);
777 if (present
& 0x0020)
778 in_uint8(s
, os
->fillmode
);
780 if (present
& 0x0040)
781 rdp_in_colour(s
, &os
->bgcolour
);
783 if (present
& 0x0080)
784 rdp_in_colour(s
, &os
->fgcolour
);
786 rdp_parse_brush(s
, &os
->brush
, present
>> 8);
788 DEBUG(("ELLIPSE2(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,bs=%d,bg=0x%x,fg=0x%x)\n",
789 os
->left
, os
->top
, os
->right
, os
->bottom
, os
->opcode
, os
->fillmode
, os
->brush
.style
,
790 os
->bgcolour
, os
->fgcolour
));
792 ui_ellipse(ROP_MINUS_1(os
->opcode
), os
->fillmode
, os
->left
, os
->top
, os
->right
- os
->left
,
793 os
->bottom
- os
->top
, &os
->brush
, os
->bgcolour
, os
->fgcolour
);
796 /* Process a text order */
798 process_text2(STREAM s
, TEXT2_ORDER
* os
, uint32 present
, BOOL delta
)
802 if (present
& 0x000001)
803 in_uint8(s
, os
->font
);
805 if (present
& 0x000002)
806 in_uint8(s
, os
->flags
);
808 if (present
& 0x000004)
809 in_uint8(s
, os
->opcode
);
811 if (present
& 0x000008)
812 in_uint8(s
, os
->mixmode
);
814 if (present
& 0x000010)
815 rdp_in_colour(s
, &os
->fgcolour
);
817 if (present
& 0x000020)
818 rdp_in_colour(s
, &os
->bgcolour
);
820 if (present
& 0x000040)
821 in_uint16_le(s
, os
->clipleft
);
823 if (present
& 0x000080)
824 in_uint16_le(s
, os
->cliptop
);
826 if (present
& 0x000100)
827 in_uint16_le(s
, os
->clipright
);
829 if (present
& 0x000200)
830 in_uint16_le(s
, os
->clipbottom
);
832 if (present
& 0x000400)
833 in_uint16_le(s
, os
->boxleft
);
835 if (present
& 0x000800)
836 in_uint16_le(s
, os
->boxtop
);
838 if (present
& 0x001000)
839 in_uint16_le(s
, os
->boxright
);
841 if (present
& 0x002000)
842 in_uint16_le(s
, os
->boxbottom
);
844 rdp_parse_brush(s
, &os
->brush
, present
>> 14);
846 if (present
& 0x080000)
847 in_uint16_le(s
, os
->x
);
849 if (present
& 0x100000)
850 in_uint16_le(s
, os
->y
);
852 if (present
& 0x200000)
854 in_uint8(s
, os
->length
);
855 in_uint8a(s
, os
->text
, os
->length
);
858 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
));
862 for (i
= 0; i
< os
->length
; i
++)
863 DEBUG(("%02x ", os
->text
[i
]));
867 ui_draw_text(os
->font
, os
->flags
, ROP_MINUS_1(os
->opcode
), os
->mixmode
, os
->x
, os
->y
,
868 os
->clipleft
, os
->cliptop
, os
->clipright
- os
->clipleft
,
869 os
->clipbottom
- os
->cliptop
, os
->boxleft
, os
->boxtop
,
870 os
->boxright
- os
->boxleft
, os
->boxbottom
- os
->boxtop
,
871 &os
->brush
, os
->bgcolour
, os
->fgcolour
, os
->text
, os
->length
);
874 /* Process a raw bitmap cache order */
876 process_raw_bmpcache(STREAM s
)
879 uint16 cache_idx
, bufsize
;
880 uint8 cache_id
, width
, height
, bpp
, Bpp
;
881 uint8
*data
, *inverted
;
884 in_uint8(s
, cache_id
);
885 in_uint8s(s
, 1); /* pad */
890 in_uint16_le(s
, bufsize
);
891 in_uint16_le(s
, cache_idx
);
892 in_uint8p(s
, data
, bufsize
);
894 DEBUG(("RAW_BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n", width
, height
, cache_id
, cache_idx
));
895 inverted
= (uint8
*) xmalloc(width
* height
* Bpp
);
896 for (y
= 0; y
< height
; y
++)
898 memcpy(&inverted
[(height
- y
- 1) * (width
* Bpp
)], &data
[y
* (width
* Bpp
)],
902 bitmap
= ui_create_bitmap(width
, height
, inverted
);
904 cache_put_bitmap(cache_id
, cache_idx
, bitmap
);
907 /* Process a bitmap cache order */
909 process_bmpcache(STREAM s
)
912 uint16 cache_idx
, size
;
913 uint8 cache_id
, width
, height
, bpp
, Bpp
;
914 uint8
*data
, *bmpdata
;
915 uint16 bufsize
, pad2
, row_size
, final_size
;
918 pad2
= row_size
= final_size
= 0xffff; /* Shut the compiler up */
920 in_uint8(s
, cache_id
);
921 in_uint8(s
, pad1
); /* pad */
926 in_uint16_le(s
, bufsize
); /* bufsize */
927 in_uint16_le(s
, cache_idx
);
936 /* Begin compressedBitmapData */
937 in_uint16_le(s
, pad2
); /* pad */
938 in_uint16_le(s
, size
);
939 /* in_uint8s(s, 4); *//* row_size, final_size */
940 in_uint16_le(s
, row_size
);
941 in_uint16_le(s
, final_size
);
944 in_uint8p(s
, data
, size
);
946 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 (void)pad1
; (void)pad2
;
949 bmpdata
= (uint8
*) xmalloc(width
* height
* Bpp
);
951 if (bitmap_decompress(bmpdata
, width
, height
, data
, size
, Bpp
))
953 bitmap
= ui_create_bitmap(width
, height
, bmpdata
);
954 cache_put_bitmap(cache_id
, cache_idx
, bitmap
);
958 DEBUG(("Failed to decompress bitmap data\n"));
964 /* Process a bitmap cache v2 order */
966 process_bmpcache2(STREAM s
, uint16 flags
, BOOL compressed
)
970 uint8 cache_id
, cache_idx_low
, width
, height
, Bpp
;
971 uint16 cache_idx
, bufsize
;
972 uint8
*data
, *bmpdata
, *bitmap_id
;
974 bitmap_id
= NULL
; /* prevent compiler warning */
975 cache_id
= flags
& ID_MASK
;
976 Bpp
= ((flags
& MODE_MASK
) >> MODE_SHIFT
) - 2;
980 in_uint8p(s
, bitmap_id
, 8);
994 in_uint16_be(s
, bufsize
);
995 bufsize
&= BUFSIZE_MASK
;
996 in_uint8(s
, cache_idx
);
998 if (cache_idx
& LONG_FORMAT
)
1000 in_uint8(s
, cache_idx_low
);
1001 cache_idx
= ((cache_idx
^ LONG_FORMAT
) << 8) + cache_idx_low
;
1004 in_uint8p(s
, data
, bufsize
);
1006 DEBUG(("BMPCACHE2(compr=%d,flags=%x,cx=%d,cy=%d,id=%d,idx=%d,Bpp=%d,bs=%d)\n",
1007 compressed
, flags
, width
, height
, cache_id
, cache_idx
, Bpp
, bufsize
));
1009 bmpdata
= (uint8
*) xmalloc(width
* height
* Bpp
);
1013 if (!bitmap_decompress(bmpdata
, width
, height
, data
, bufsize
, Bpp
))
1015 DEBUG(("Failed to decompress bitmap data\n"));
1022 for (y
= 0; y
< height
; y
++)
1023 memcpy(&bmpdata
[(height
- y
- 1) * (width
* Bpp
)],
1024 &data
[y
* (width
* Bpp
)], width
* Bpp
);
1027 bitmap
= ui_create_bitmap(width
, height
, bmpdata
);
1031 cache_put_bitmap(cache_id
, cache_idx
, bitmap
);
1032 if (flags
& PERSIST
)
1033 pstcache_save_bitmap(cache_id
, cache_idx
, bitmap_id
, width
, height
,
1034 (uint16
) (width
* height
* Bpp
), bmpdata
);
1038 DEBUG(("process_bmpcache2: ui_create_bitmap failed\n"));
1044 /* Process a colourmap cache order */
1046 process_colcache(STREAM s
)
1054 in_uint8(s
, cache_id
);
1055 in_uint16_le(s
, map
.ncolours
);
1057 map
.colours
= (COLOURENTRY
*) xmalloc(sizeof(COLOURENTRY
) * map
.ncolours
);
1059 for (i
= 0; i
< map
.ncolours
; i
++)
1061 entry
= &map
.colours
[i
];
1062 in_uint8(s
, entry
->blue
);
1063 in_uint8(s
, entry
->green
);
1064 in_uint8(s
, entry
->red
);
1065 in_uint8s(s
, 1); /* pad */
1068 DEBUG(("COLCACHE(id=%d,n=%d)\n", cache_id
, map
.ncolours
));
1070 hmap
= ui_create_colourmap(&map
);
1073 ui_set_colourmap(hmap
);
1078 /* Process a font cache order */
1080 process_fontcache(STREAM s
)
1083 uint8 font
, nglyphs
;
1084 uint16 character
, offset
, baseline
, width
, height
;
1089 in_uint8(s
, nglyphs
);
1091 DEBUG(("FONTCACHE(font=%d,n=%d)\n", font
, nglyphs
));
1093 for (i
= 0; i
< nglyphs
; i
++)
1095 in_uint16_le(s
, character
);
1096 in_uint16_le(s
, offset
);
1097 in_uint16_le(s
, baseline
);
1098 in_uint16_le(s
, width
);
1099 in_uint16_le(s
, height
);
1101 datasize
= (height
* ((width
+ 7) / 8) + 3) & ~3;
1102 in_uint8p(s
, data
, datasize
);
1104 bitmap
= ui_create_glyph(width
, height
, data
);
1105 cache_put_font(font
, character
, offset
, baseline
, width
, height
, bitmap
);
1109 /* Process a secondary order */
1111 process_secondary_order(STREAM s
)
1113 /* The length isn't calculated correctly by the server.
1114 * For very compact orders the length becomes negative
1115 * so a signed integer must be used. */
1121 in_uint16_le(s
, length
);
1122 in_uint16_le(s
, flags
); /* used by bmpcache2 */
1125 next_order
= s
->p
+ (sint16
) length
+ 7;
1129 case RDP_ORDER_RAW_BMPCACHE
:
1130 process_raw_bmpcache(s
);
1133 case RDP_ORDER_COLCACHE
:
1134 process_colcache(s
);
1137 case RDP_ORDER_BMPCACHE
:
1138 process_bmpcache(s
);
1141 case RDP_ORDER_FONTCACHE
:
1142 process_fontcache(s
);
1145 case RDP_ORDER_RAW_BMPCACHE2
:
1146 process_bmpcache2(s
, flags
, False
); /* uncompressed */
1149 case RDP_ORDER_BMPCACHE2
:
1150 process_bmpcache2(s
, flags
, True
); /* compressed */
1154 unimpl("secondary order %d\n", type
);
1160 /* Process an order PDU */
1162 process_orders(STREAM s
, uint16 num_orders
)
1164 RDP_ORDER_STATE
*os
= &g_order_state
;
1167 int size
, processed
= 0;
1170 while (processed
< num_orders
)
1172 in_uint8(s
, order_flags
);
1174 if (!(order_flags
& RDP_ORDER_STANDARD
))
1176 error("order parsing failed\n");
1180 if (order_flags
& RDP_ORDER_SECONDARY
)
1182 process_secondary_order(s
);
1186 if (order_flags
& RDP_ORDER_CHANGE
)
1188 in_uint8(s
, os
->order_type
);
1191 switch (os
->order_type
)
1193 case RDP_ORDER_TRIBLT
:
1194 case RDP_ORDER_TEXT2
:
1198 case RDP_ORDER_PATBLT
:
1199 case RDP_ORDER_MEMBLT
:
1200 case RDP_ORDER_LINE
:
1201 case RDP_ORDER_POLYGON2
:
1202 case RDP_ORDER_ELLIPSE2
:
1210 rdp_in_present(s
, &present
, order_flags
, size
);
1212 if (order_flags
& RDP_ORDER_BOUNDS
)
1214 if (!(order_flags
& RDP_ORDER_LASTBOUNDS
))
1215 rdp_parse_bounds(s
, &os
->bounds
);
1217 ui_set_clip(os
->bounds
.left
,
1220 os
->bounds
.left
+ 1,
1221 os
->bounds
.bottom
- os
->bounds
.top
+ 1);
1224 delta
= order_flags
& RDP_ORDER_DELTA
;
1226 switch (os
->order_type
)
1228 case RDP_ORDER_DESTBLT
:
1229 process_destblt(s
, &os
->destblt
, present
, delta
);
1232 case RDP_ORDER_PATBLT
:
1233 process_patblt(s
, &os
->patblt
, present
, delta
);
1236 case RDP_ORDER_SCREENBLT
:
1237 process_screenblt(s
, &os
->screenblt
, present
, delta
);
1240 case RDP_ORDER_LINE
:
1241 process_line(s
, &os
->line
, present
, delta
);
1244 case RDP_ORDER_RECT
:
1245 process_rect(s
, &os
->rect
, present
, delta
);
1248 case RDP_ORDER_DESKSAVE
:
1249 process_desksave(s
, &os
->desksave
, present
, delta
);
1252 case RDP_ORDER_MEMBLT
:
1253 process_memblt(s
, &os
->memblt
, present
, delta
);
1256 case RDP_ORDER_TRIBLT
:
1257 process_triblt(s
, &os
->triblt
, present
, delta
);
1260 case RDP_ORDER_POLYGON
:
1261 process_polygon(s
, &os
->polygon
, present
, delta
);
1264 case RDP_ORDER_POLYGON2
:
1265 process_polygon2(s
, &os
->polygon2
, present
, delta
);
1268 case RDP_ORDER_POLYLINE
:
1269 process_polyline(s
, &os
->polyline
, present
, delta
);
1272 case RDP_ORDER_ELLIPSE
:
1273 process_ellipse(s
, &os
->ellipse
, present
, delta
);
1276 case RDP_ORDER_ELLIPSE2
:
1277 process_ellipse2(s
, &os
->ellipse2
, present
, delta
);
1280 case RDP_ORDER_TEXT2
:
1281 process_text2(s
, &os
->text2
, present
, delta
);
1285 unimpl("order %d\n", os
->order_type
);
1289 if (order_flags
& RDP_ORDER_BOUNDS
)
1296 /* not true when RDP_COMPRESSION is set */
1297 if (s
->p
!= g_next_packet
)
1298 error("%d bytes remaining\n", (int) (g_next_packet
- s
->p
));
1303 /* Reset order state */
1305 reset_order_state(void)
1307 memset(&g_order_state
, 0, sizeof(g_order_state
));
1308 g_order_state
.order_type
= RDP_ORDER_PATBLT
;