1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
4 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
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.
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, see <http://www.gnu.org/licenses/>.
23 extern uint8
*g_next_packet
;
24 static RDP_ORDER_STATE g_order_state
;
25 extern RDP_VERSION g_rdp_version
;
27 /* Read field indicating which parameters are present */
29 rdp_in_present(STREAM s
, uint32
* present
, uint8 flags
, int size
)
34 if (flags
& RDP_ORDER_SMALL
)
39 if (flags
& RDP_ORDER_TINY
)
48 for (i
= 0; i
< size
; i
++)
51 *present
|= bits
<< (i
* 8);
55 /* Read a co-ordinate (16-bit, or 8-bit delta) */
57 rdp_in_coord(STREAM s
, sint16
* coord
, RD_BOOL delta
)
68 in_uint16_le(s
, *coord
);
72 /* Parse a delta co-ordinate in polyline/polygon order form */
74 parse_delta(uint8
* buffer
, int *offset
)
76 int value
= buffer
[(*offset
)++];
77 int two_byte
= value
& 0x80;
79 if (value
& 0x40) /* sign bit */
85 value
= (value
<< 8) | buffer
[(*offset
)++];
90 /* Read a colour entry */
92 rdp_in_colour(STREAM s
, uint32
* colour
)
103 /* Parse bounds information */
105 rdp_parse_bounds(STREAM s
, BOUNDS
* bounds
)
109 in_uint8(s
, present
);
112 rdp_in_coord(s
, &bounds
->left
, False
);
113 else if (present
& 16)
114 rdp_in_coord(s
, &bounds
->left
, True
);
117 rdp_in_coord(s
, &bounds
->top
, False
);
118 else if (present
& 32)
119 rdp_in_coord(s
, &bounds
->top
, True
);
122 rdp_in_coord(s
, &bounds
->right
, False
);
123 else if (present
& 64)
124 rdp_in_coord(s
, &bounds
->right
, True
);
127 rdp_in_coord(s
, &bounds
->bottom
, False
);
128 else if (present
& 128)
129 rdp_in_coord(s
, &bounds
->bottom
, True
);
136 rdp_parse_pen(STREAM s
, PEN
* pen
, uint32 present
)
139 in_uint8(s
, pen
->style
);
142 in_uint8(s
, pen
->width
);
145 rdp_in_colour(s
, &pen
->colour
);
151 setup_brush(BRUSH
* out_brush
, BRUSH
* in_brush
)
153 BRUSHDATA
*brush_data
;
157 memcpy(out_brush
, in_brush
, sizeof(BRUSH
));
158 if (out_brush
->style
& 0x80)
160 colour_code
= out_brush
->style
& 0x0f;
161 cache_idx
= out_brush
->pattern
[0];
162 brush_data
= cache_get_brush_data(colour_code
, cache_idx
);
163 if ((brush_data
== NULL
) || (brush_data
->data
== NULL
))
165 error("error getting brush data, style %x\n", out_brush
->style
);
166 out_brush
->bd
= NULL
;
167 memset(out_brush
->pattern
, 0, 8);
171 out_brush
->bd
= brush_data
;
173 out_brush
->style
= 3;
179 rdp_parse_brush(STREAM s
, BRUSH
* brush
, uint32 present
)
182 in_uint8(s
, brush
->xorigin
);
185 in_uint8(s
, brush
->yorigin
);
188 in_uint8(s
, brush
->style
);
191 in_uint8(s
, brush
->pattern
[0]);
194 in_uint8a(s
, &brush
->pattern
[1], 7);
199 /* Process a destination blt order */
201 process_destblt(STREAM s
, DESTBLT_ORDER
* os
, uint32 present
, RD_BOOL delta
)
204 rdp_in_coord(s
, &os
->x
, delta
);
207 rdp_in_coord(s
, &os
->y
, delta
);
210 rdp_in_coord(s
, &os
->cx
, delta
);
213 rdp_in_coord(s
, &os
->cy
, delta
);
216 in_uint8(s
, os
->opcode
);
218 DEBUG(("DESTBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d)\n",
219 os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
));
221 ui_destblt(ROP2_S(os
->opcode
), os
->x
, os
->y
, os
->cx
, os
->cy
);
224 /* Process a pattern blt order */
226 process_patblt(STREAM s
, PATBLT_ORDER
* os
, uint32 present
, RD_BOOL delta
)
230 if (present
& 0x0001)
231 rdp_in_coord(s
, &os
->x
, delta
);
233 if (present
& 0x0002)
234 rdp_in_coord(s
, &os
->y
, delta
);
236 if (present
& 0x0004)
237 rdp_in_coord(s
, &os
->cx
, delta
);
239 if (present
& 0x0008)
240 rdp_in_coord(s
, &os
->cy
, delta
);
242 if (present
& 0x0010)
243 in_uint8(s
, os
->opcode
);
245 if (present
& 0x0020)
246 rdp_in_colour(s
, &os
->bgcolour
);
248 if (present
& 0x0040)
249 rdp_in_colour(s
, &os
->fgcolour
);
251 rdp_parse_brush(s
, &os
->brush
, present
>> 7);
253 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
,
254 os
->y
, os
->cx
, os
->cy
, os
->brush
.style
, os
->bgcolour
, os
->fgcolour
));
256 setup_brush(&brush
, &os
->brush
);
258 ui_patblt(ROP2_P(os
->opcode
), os
->x
, os
->y
, os
->cx
, os
->cy
,
259 &brush
, os
->bgcolour
, os
->fgcolour
);
262 /* Process a screen blt order */
264 process_screenblt(STREAM s
, SCREENBLT_ORDER
* os
, uint32 present
, RD_BOOL delta
)
266 if (present
& 0x0001)
267 rdp_in_coord(s
, &os
->x
, delta
);
269 if (present
& 0x0002)
270 rdp_in_coord(s
, &os
->y
, delta
);
272 if (present
& 0x0004)
273 rdp_in_coord(s
, &os
->cx
, delta
);
275 if (present
& 0x0008)
276 rdp_in_coord(s
, &os
->cy
, delta
);
278 if (present
& 0x0010)
279 in_uint8(s
, os
->opcode
);
281 if (present
& 0x0020)
282 rdp_in_coord(s
, &os
->srcx
, delta
);
284 if (present
& 0x0040)
285 rdp_in_coord(s
, &os
->srcy
, delta
);
287 DEBUG(("SCREENBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,srcx=%d,srcy=%d)\n",
288 os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
, os
->srcx
, os
->srcy
));
290 ui_screenblt(ROP2_S(os
->opcode
), os
->x
, os
->y
, os
->cx
, os
->cy
, os
->srcx
, os
->srcy
);
293 /* Process a line order */
295 process_line(STREAM s
, LINE_ORDER
* os
, uint32 present
, RD_BOOL delta
)
297 if (present
& 0x0001)
298 in_uint16_le(s
, os
->mixmode
);
300 if (present
& 0x0002)
301 rdp_in_coord(s
, &os
->startx
, delta
);
303 if (present
& 0x0004)
304 rdp_in_coord(s
, &os
->starty
, delta
);
306 if (present
& 0x0008)
307 rdp_in_coord(s
, &os
->endx
, delta
);
309 if (present
& 0x0010)
310 rdp_in_coord(s
, &os
->endy
, delta
);
312 if (present
& 0x0020)
313 rdp_in_colour(s
, &os
->bgcolour
);
315 if (present
& 0x0040)
316 in_uint8(s
, os
->opcode
);
318 rdp_parse_pen(s
, &os
->pen
, present
>> 7);
320 DEBUG(("LINE(op=0x%x,sx=%d,sy=%d,dx=%d,dy=%d,fg=0x%x)\n",
321 os
->opcode
, os
->startx
, os
->starty
, os
->endx
, os
->endy
, os
->pen
.colour
));
323 if (os
->opcode
< 0x01 || os
->opcode
> 0x10)
325 error("bad ROP2 0x%x\n", os
->opcode
);
329 ui_line(os
->opcode
- 1, os
->startx
, os
->starty
, os
->endx
, os
->endy
, &os
->pen
);
332 /* Process an opaque rectangle order */
334 process_rect(STREAM s
, RECT_ORDER
* os
, uint32 present
, RD_BOOL delta
)
338 rdp_in_coord(s
, &os
->x
, delta
);
341 rdp_in_coord(s
, &os
->y
, delta
);
344 rdp_in_coord(s
, &os
->cx
, delta
);
347 rdp_in_coord(s
, &os
->cy
, delta
);
352 os
->colour
= (os
->colour
& 0xffffff00) | i
;
358 os
->colour
= (os
->colour
& 0xffff00ff) | (i
<< 8);
364 os
->colour
= (os
->colour
& 0xff00ffff) | (i
<< 16);
367 DEBUG(("RECT(x=%d,y=%d,cx=%d,cy=%d,fg=0x%x)\n", os
->x
, os
->y
, os
->cx
, os
->cy
, os
->colour
));
369 ui_rect(os
->x
, os
->y
, os
->cx
, os
->cy
, os
->colour
);
372 /* Process a desktop save order */
374 process_desksave(STREAM s
, DESKSAVE_ORDER
* os
, uint32 present
, RD_BOOL delta
)
379 in_uint32_le(s
, os
->offset
);
382 rdp_in_coord(s
, &os
->left
, delta
);
385 rdp_in_coord(s
, &os
->top
, delta
);
388 rdp_in_coord(s
, &os
->right
, delta
);
391 rdp_in_coord(s
, &os
->bottom
, delta
);
394 in_uint8(s
, os
->action
);
396 DEBUG(("DESKSAVE(l=%d,t=%d,r=%d,b=%d,off=%d,op=%d)\n",
397 os
->left
, os
->top
, os
->right
, os
->bottom
, os
->offset
, os
->action
));
399 width
= os
->right
- os
->left
+ 1;
400 height
= os
->bottom
- os
->top
+ 1;
403 ui_desktop_save(os
->offset
, os
->left
, os
->top
, width
, height
);
405 ui_desktop_restore(os
->offset
, os
->left
, os
->top
, width
, height
);
408 /* Process a memory blt order */
410 process_memblt(STREAM s
, MEMBLT_ORDER
* os
, uint32 present
, RD_BOOL delta
)
414 if (present
& 0x0001)
416 in_uint8(s
, os
->cache_id
);
417 in_uint8(s
, os
->colour_table
);
420 if (present
& 0x0002)
421 rdp_in_coord(s
, &os
->x
, delta
);
423 if (present
& 0x0004)
424 rdp_in_coord(s
, &os
->y
, delta
);
426 if (present
& 0x0008)
427 rdp_in_coord(s
, &os
->cx
, delta
);
429 if (present
& 0x0010)
430 rdp_in_coord(s
, &os
->cy
, delta
);
432 if (present
& 0x0020)
433 in_uint8(s
, os
->opcode
);
435 if (present
& 0x0040)
436 rdp_in_coord(s
, &os
->srcx
, delta
);
438 if (present
& 0x0080)
439 rdp_in_coord(s
, &os
->srcy
, delta
);
441 if (present
& 0x0100)
442 in_uint16_le(s
, os
->cache_idx
);
444 DEBUG(("MEMBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d)\n",
445 os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
, os
->cache_id
, os
->cache_idx
));
447 bitmap
= cache_get_bitmap(os
->cache_id
, os
->cache_idx
);
451 ui_memblt(ROP2_S(os
->opcode
), os
->x
, os
->y
, os
->cx
, os
->cy
, bitmap
, os
->srcx
, os
->srcy
);
454 /* Process a 3-way blt order */
456 process_triblt(STREAM s
, TRIBLT_ORDER
* os
, uint32 present
, RD_BOOL delta
)
461 if (present
& 0x000001)
463 in_uint8(s
, os
->cache_id
);
464 in_uint8(s
, os
->colour_table
);
467 if (present
& 0x000002)
468 rdp_in_coord(s
, &os
->x
, delta
);
470 if (present
& 0x000004)
471 rdp_in_coord(s
, &os
->y
, delta
);
473 if (present
& 0x000008)
474 rdp_in_coord(s
, &os
->cx
, delta
);
476 if (present
& 0x000010)
477 rdp_in_coord(s
, &os
->cy
, delta
);
479 if (present
& 0x000020)
480 in_uint8(s
, os
->opcode
);
482 if (present
& 0x000040)
483 rdp_in_coord(s
, &os
->srcx
, delta
);
485 if (present
& 0x000080)
486 rdp_in_coord(s
, &os
->srcy
, delta
);
488 if (present
& 0x000100)
489 rdp_in_colour(s
, &os
->bgcolour
);
491 if (present
& 0x000200)
492 rdp_in_colour(s
, &os
->fgcolour
);
494 rdp_parse_brush(s
, &os
->brush
, present
>> 10);
496 if (present
& 0x008000)
497 in_uint16_le(s
, os
->cache_idx
);
499 if (present
& 0x010000)
500 in_uint16_le(s
, os
->unknown
);
502 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",
503 os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
, os
->cache_id
, os
->cache_idx
,
504 os
->brush
.style
, os
->bgcolour
, os
->fgcolour
));
506 bitmap
= cache_get_bitmap(os
->cache_id
, os
->cache_idx
);
510 setup_brush(&brush
, &os
->brush
);
512 ui_triblt(os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
,
513 bitmap
, os
->srcx
, os
->srcy
, &brush
, os
->bgcolour
, os
->fgcolour
);
516 /* Process a polygon order */
518 process_polygon(STREAM s
, POLYGON_ORDER
* os
, uint32 present
, RD_BOOL delta
)
520 int index
, data
, next
;
525 rdp_in_coord(s
, &os
->x
, delta
);
528 rdp_in_coord(s
, &os
->y
, delta
);
531 in_uint8(s
, os
->opcode
);
534 in_uint8(s
, os
->fillmode
);
537 rdp_in_colour(s
, &os
->fgcolour
);
540 in_uint8(s
, os
->npoints
);
544 in_uint8(s
, os
->datasize
);
545 in_uint8a(s
, os
->data
, os
->datasize
);
548 DEBUG(("POLYGON(x=%d,y=%d,op=0x%x,fm=%d,fg=0x%x,n=%d,sz=%d)\n",
549 os
->x
, os
->y
, os
->opcode
, os
->fillmode
, os
->fgcolour
, os
->npoints
, os
->datasize
));
553 for (index
= 0; index
< os
->datasize
; index
++)
554 DEBUG(("%02x ", os
->data
[index
]));
558 if (os
->opcode
< 0x01 || os
->opcode
> 0x10)
560 error("bad ROP2 0x%x\n", os
->opcode
);
564 points
= (RD_POINT
*) xmalloc((os
->npoints
+ 1) * sizeof(RD_POINT
));
565 memset(points
, 0, (os
->npoints
+ 1) * sizeof(RD_POINT
));
571 data
= ((os
->npoints
- 1) / 4) + 1;
572 for (next
= 1; (next
<= os
->npoints
) && (next
< 256) && (data
< os
->datasize
); next
++)
574 if ((next
- 1) % 4 == 0)
575 flags
= os
->data
[index
++];
578 points
[next
].x
= parse_delta(os
->data
, &data
);
581 points
[next
].y
= parse_delta(os
->data
, &data
);
586 if (next
- 1 == os
->npoints
)
587 ui_polygon(os
->opcode
- 1, os
->fillmode
, points
, os
->npoints
+ 1, NULL
, 0,
590 error("polygon parse error\n");
595 /* Process a polygon2 order */
597 process_polygon2(STREAM s
, POLYGON2_ORDER
* os
, uint32 present
, RD_BOOL delta
)
599 int index
, data
, next
;
604 if (present
& 0x0001)
605 rdp_in_coord(s
, &os
->x
, delta
);
607 if (present
& 0x0002)
608 rdp_in_coord(s
, &os
->y
, delta
);
610 if (present
& 0x0004)
611 in_uint8(s
, os
->opcode
);
613 if (present
& 0x0008)
614 in_uint8(s
, os
->fillmode
);
616 if (present
& 0x0010)
617 rdp_in_colour(s
, &os
->bgcolour
);
619 if (present
& 0x0020)
620 rdp_in_colour(s
, &os
->fgcolour
);
622 rdp_parse_brush(s
, &os
->brush
, present
>> 6);
624 if (present
& 0x0800)
625 in_uint8(s
, os
->npoints
);
627 if (present
& 0x1000)
629 in_uint8(s
, os
->datasize
);
630 in_uint8a(s
, os
->data
, os
->datasize
);
633 DEBUG(("POLYGON2(x=%d,y=%d,op=0x%x,fm=%d,bs=%d,bg=0x%x,fg=0x%x,n=%d,sz=%d)\n",
634 os
->x
, os
->y
, os
->opcode
, os
->fillmode
, os
->brush
.style
, os
->bgcolour
, os
->fgcolour
,
635 os
->npoints
, os
->datasize
));
639 for (index
= 0; index
< os
->datasize
; index
++)
640 DEBUG(("%02x ", os
->data
[index
]));
644 if (os
->opcode
< 0x01 || os
->opcode
> 0x10)
646 error("bad ROP2 0x%x\n", os
->opcode
);
650 setup_brush(&brush
, &os
->brush
);
652 points
= (RD_POINT
*) xmalloc((os
->npoints
+ 1) * sizeof(RD_POINT
));
653 memset(points
, 0, (os
->npoints
+ 1) * sizeof(RD_POINT
));
659 data
= ((os
->npoints
- 1) / 4) + 1;
660 for (next
= 1; (next
<= os
->npoints
) && (next
< 256) && (data
< os
->datasize
); next
++)
662 if ((next
- 1) % 4 == 0)
663 flags
= os
->data
[index
++];
666 points
[next
].x
= parse_delta(os
->data
, &data
);
669 points
[next
].y
= parse_delta(os
->data
, &data
);
674 if (next
- 1 == os
->npoints
)
675 ui_polygon(os
->opcode
- 1, os
->fillmode
, points
, os
->npoints
+ 1,
676 &brush
, os
->bgcolour
, os
->fgcolour
);
678 error("polygon2 parse error\n");
683 /* Process a polyline order */
685 process_polyline(STREAM s
, POLYLINE_ORDER
* os
, uint32 present
, RD_BOOL delta
)
687 int index
, next
, data
;
693 rdp_in_coord(s
, &os
->x
, delta
);
696 rdp_in_coord(s
, &os
->y
, delta
);
699 in_uint8(s
, os
->opcode
);
702 rdp_in_colour(s
, &os
->fgcolour
);
705 in_uint8(s
, os
->lines
);
709 in_uint8(s
, os
->datasize
);
710 in_uint8a(s
, os
->data
, os
->datasize
);
713 DEBUG(("POLYLINE(x=%d,y=%d,op=0x%x,fg=0x%x,n=%d,sz=%d)\n",
714 os
->x
, os
->y
, os
->opcode
, os
->fgcolour
, os
->lines
, os
->datasize
));
718 for (index
= 0; index
< os
->datasize
; index
++)
719 DEBUG(("%02x ", os
->data
[index
]));
723 if (os
->opcode
< 0x01 || os
->opcode
> 0x10)
725 error("bad ROP2 0x%x\n", os
->opcode
);
729 points
= (RD_POINT
*) xmalloc((os
->lines
+ 1) * sizeof(RD_POINT
));
730 memset(points
, 0, (os
->lines
+ 1) * sizeof(RD_POINT
));
734 pen
.style
= pen
.width
= 0;
735 pen
.colour
= os
->fgcolour
;
738 data
= ((os
->lines
- 1) / 4) + 1;
739 for (next
= 1; (next
<= os
->lines
) && (data
< os
->datasize
); next
++)
741 if ((next
- 1) % 4 == 0)
742 flags
= os
->data
[index
++];
745 points
[next
].x
= parse_delta(os
->data
, &data
);
748 points
[next
].y
= parse_delta(os
->data
, &data
);
753 if (next
- 1 == os
->lines
)
754 ui_polyline(os
->opcode
- 1, points
, os
->lines
+ 1, &pen
);
756 error("polyline parse error\n");
761 /* Process an ellipse order */
763 process_ellipse(STREAM s
, ELLIPSE_ORDER
* os
, uint32 present
, RD_BOOL delta
)
766 rdp_in_coord(s
, &os
->left
, delta
);
769 rdp_in_coord(s
, &os
->top
, delta
);
772 rdp_in_coord(s
, &os
->right
, delta
);
775 rdp_in_coord(s
, &os
->bottom
, delta
);
778 in_uint8(s
, os
->opcode
);
781 in_uint8(s
, os
->fillmode
);
784 rdp_in_colour(s
, &os
->fgcolour
);
786 DEBUG(("ELLIPSE(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,fg=0x%x)\n", os
->left
, os
->top
,
787 os
->right
, os
->bottom
, os
->opcode
, os
->fillmode
, os
->fgcolour
));
789 ui_ellipse(os
->opcode
- 1, os
->fillmode
, os
->left
, os
->top
, os
->right
- os
->left
,
790 os
->bottom
- os
->top
, NULL
, 0, os
->fgcolour
);
793 /* Process an ellipse2 order */
795 process_ellipse2(STREAM s
, ELLIPSE2_ORDER
* os
, uint32 present
, RD_BOOL delta
)
799 if (present
& 0x0001)
800 rdp_in_coord(s
, &os
->left
, delta
);
802 if (present
& 0x0002)
803 rdp_in_coord(s
, &os
->top
, delta
);
805 if (present
& 0x0004)
806 rdp_in_coord(s
, &os
->right
, delta
);
808 if (present
& 0x0008)
809 rdp_in_coord(s
, &os
->bottom
, delta
);
811 if (present
& 0x0010)
812 in_uint8(s
, os
->opcode
);
814 if (present
& 0x0020)
815 in_uint8(s
, os
->fillmode
);
817 if (present
& 0x0040)
818 rdp_in_colour(s
, &os
->bgcolour
);
820 if (present
& 0x0080)
821 rdp_in_colour(s
, &os
->fgcolour
);
823 rdp_parse_brush(s
, &os
->brush
, present
>> 8);
825 DEBUG(("ELLIPSE2(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,bs=%d,bg=0x%x,fg=0x%x)\n",
826 os
->left
, os
->top
, os
->right
, os
->bottom
, os
->opcode
, os
->fillmode
, os
->brush
.style
,
827 os
->bgcolour
, os
->fgcolour
));
829 setup_brush(&brush
, &os
->brush
);
831 ui_ellipse(os
->opcode
- 1, os
->fillmode
, os
->left
, os
->top
, os
->right
- os
->left
,
832 os
->bottom
- os
->top
, &brush
, os
->bgcolour
, os
->fgcolour
);
835 /* Process a text order */
837 process_text2(STREAM s
, TEXT2_ORDER
* os
, uint32 present
, RD_BOOL delta
)
842 if (present
& 0x000001)
843 in_uint8(s
, os
->font
);
845 if (present
& 0x000002)
846 in_uint8(s
, os
->flags
);
848 if (present
& 0x000004)
849 in_uint8(s
, os
->opcode
);
851 if (present
& 0x000008)
852 in_uint8(s
, os
->mixmode
);
854 if (present
& 0x000010)
855 rdp_in_colour(s
, &os
->fgcolour
);
857 if (present
& 0x000020)
858 rdp_in_colour(s
, &os
->bgcolour
);
860 if (present
& 0x000040)
861 in_uint16_le(s
, os
->clipleft
);
863 if (present
& 0x000080)
864 in_uint16_le(s
, os
->cliptop
);
866 if (present
& 0x000100)
867 in_uint16_le(s
, os
->clipright
);
869 if (present
& 0x000200)
870 in_uint16_le(s
, os
->clipbottom
);
872 if (present
& 0x000400)
873 in_uint16_le(s
, os
->boxleft
);
875 if (present
& 0x000800)
876 in_uint16_le(s
, os
->boxtop
);
878 if (present
& 0x001000)
879 in_uint16_le(s
, os
->boxright
);
881 if (present
& 0x002000)
882 in_uint16_le(s
, os
->boxbottom
);
884 rdp_parse_brush(s
, &os
->brush
, present
>> 14);
886 if (present
& 0x080000)
887 in_uint16_le(s
, os
->x
);
889 if (present
& 0x100000)
890 in_uint16_le(s
, os
->y
);
892 if (present
& 0x200000)
894 in_uint8(s
, os
->length
);
895 in_uint8a(s
, os
->text
, os
->length
);
898 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
));
902 for (i
= 0; i
< os
->length
; i
++)
903 DEBUG(("%02x ", os
->text
[i
]));
907 setup_brush(&brush
, &os
->brush
);
909 ui_draw_text(os
->font
, os
->flags
, os
->opcode
- 1, os
->mixmode
, os
->x
, os
->y
,
910 os
->clipleft
, os
->cliptop
, os
->clipright
- os
->clipleft
,
911 os
->clipbottom
- os
->cliptop
, os
->boxleft
, os
->boxtop
,
912 os
->boxright
- os
->boxleft
, os
->boxbottom
- os
->boxtop
,
913 &brush
, os
->bgcolour
, os
->fgcolour
, os
->text
, os
->length
);
916 /* Process a raw bitmap cache order */
918 process_raw_bmpcache(STREAM s
)
921 uint16 cache_idx
, bufsize
;
922 uint8 cache_id
, width
, height
, bpp
, Bpp
;
923 uint8
*data
, *inverted
;
926 in_uint8(s
, cache_id
);
927 in_uint8s(s
, 1); /* pad */
932 in_uint16_le(s
, bufsize
);
933 in_uint16_le(s
, cache_idx
);
934 in_uint8p(s
, data
, bufsize
);
936 DEBUG(("RAW_BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n", width
, height
, cache_id
, cache_idx
));
937 inverted
= (uint8
*) xmalloc(width
* height
* Bpp
);
938 for (y
= 0; y
< height
; y
++)
940 memcpy(&inverted
[(height
- y
- 1) * (width
* Bpp
)], &data
[y
* (width
* Bpp
)],
944 bitmap
= ui_create_bitmap(width
, height
, inverted
);
946 cache_put_bitmap(cache_id
, cache_idx
, bitmap
);
949 /* Process a bitmap cache order */
951 process_bmpcache(STREAM s
)
954 uint16 cache_idx
, size
;
955 uint8 cache_id
, width
, height
, bpp
, Bpp
;
956 uint8
*data
, *bmpdata
;
957 uint16 bufsize
, pad2
, row_size
, final_size
;
960 pad2
= row_size
= final_size
= 0xffff; /* Shut the compiler up */
962 in_uint8(s
, cache_id
);
963 in_uint8(s
, pad1
); /* pad */
968 in_uint16_le(s
, bufsize
); /* bufsize */
969 in_uint16_le(s
, cache_idx
);
971 if (g_rdp_version
>= RDP_V5
)
978 /* Begin compressedBitmapData */
979 in_uint16_le(s
, pad2
); /* pad */
980 in_uint16_le(s
, size
);
981 /* in_uint8s(s, 4); *//* row_size, final_size */
982 in_uint16_le(s
, row_size
);
983 in_uint16_le(s
, final_size
);
986 in_uint8p(s
, data
, size
);
988 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
));
990 bmpdata
= (uint8
*) xmalloc(width
* height
* Bpp
);
992 if (bitmap_decompress(bmpdata
, width
, height
, data
, size
, Bpp
))
994 bitmap
= ui_create_bitmap(width
, height
, bmpdata
);
995 cache_put_bitmap(cache_id
, cache_idx
, bitmap
);
999 DEBUG(("Failed to decompress bitmap data\n"));
1001 if (pad1
|| pad2
) {}
1006 /* Process a bitmap cache v2 order */
1008 process_bmpcache2(STREAM s
, uint16 flags
, RD_BOOL compressed
)
1012 uint8 cache_id
, cache_idx_low
, width
, height
, Bpp
;
1013 uint16 cache_idx
, bufsize
;
1014 uint8
*data
, *bmpdata
, *bitmap_id
;
1016 bitmap_id
= NULL
; /* prevent compiler warning */
1017 cache_id
= flags
& ID_MASK
;
1018 Bpp
= ((flags
& MODE_MASK
) >> MODE_SHIFT
) - 2;
1020 if (flags
& PERSIST
)
1022 in_uint8p(s
, bitmap_id
, 8);
1033 in_uint8(s
, height
);
1036 in_uint16_be(s
, bufsize
);
1037 bufsize
&= BUFSIZE_MASK
;
1038 in_uint8(s
, cache_idx
);
1040 if (cache_idx
& LONG_FORMAT
)
1042 in_uint8(s
, cache_idx_low
);
1043 cache_idx
= ((cache_idx
^ LONG_FORMAT
) << 8) + cache_idx_low
;
1046 in_uint8p(s
, data
, bufsize
);
1048 DEBUG(("BMPCACHE2(compr=%d,flags=%x,cx=%d,cy=%d,id=%d,idx=%d,Bpp=%d,bs=%d)\n",
1049 compressed
, flags
, width
, height
, cache_id
, cache_idx
, Bpp
, bufsize
));
1051 bmpdata
= (uint8
*) xmalloc(width
* height
* Bpp
);
1055 if (!bitmap_decompress(bmpdata
, width
, height
, data
, bufsize
, Bpp
))
1057 DEBUG(("Failed to decompress bitmap data\n"));
1064 for (y
= 0; y
< height
; y
++)
1065 memcpy(&bmpdata
[(height
- y
- 1) * (width
* Bpp
)],
1066 &data
[y
* (width
* Bpp
)], width
* Bpp
);
1069 bitmap
= ui_create_bitmap(width
, height
, bmpdata
);
1073 cache_put_bitmap(cache_id
, cache_idx
, bitmap
);
1074 if (flags
& PERSIST
)
1075 pstcache_save_bitmap(cache_id
, cache_idx
, bitmap_id
, width
, height
,
1076 width
* height
* Bpp
, bmpdata
);
1080 DEBUG(("process_bmpcache2: ui_create_bitmap failed\n"));
1086 /* Process a colourmap cache order */
1088 process_colcache(STREAM s
)
1096 in_uint8(s
, cache_id
);
1097 in_uint16_le(s
, map
.ncolours
);
1099 map
.colours
= (COLOURENTRY
*) xmalloc(sizeof(COLOURENTRY
) * map
.ncolours
);
1101 for (i
= 0; i
< map
.ncolours
; i
++)
1103 entry
= &map
.colours
[i
];
1104 in_uint8(s
, entry
->blue
);
1105 in_uint8(s
, entry
->green
);
1106 in_uint8(s
, entry
->red
);
1107 in_uint8s(s
, 1); /* pad */
1110 DEBUG(("COLCACHE(id=%d,n=%d)\n", cache_id
, map
.ncolours
));
1112 hmap
= ui_create_colourmap(&map
);
1115 ui_set_colourmap(hmap
);
1120 /* Process a font cache order */
1122 process_fontcache(STREAM s
)
1125 uint8 font
, nglyphs
;
1126 uint16 character
, offset
, baseline
, width
, height
;
1131 in_uint8(s
, nglyphs
);
1133 DEBUG(("FONTCACHE(font=%d,n=%d)\n", font
, nglyphs
));
1135 for (i
= 0; i
< nglyphs
; i
++)
1137 in_uint16_le(s
, character
);
1138 in_uint16_le(s
, offset
);
1139 in_uint16_le(s
, baseline
);
1140 in_uint16_le(s
, width
);
1141 in_uint16_le(s
, height
);
1143 datasize
= (height
* ((width
+ 7) / 8) + 3) & ~3;
1144 in_uint8p(s
, data
, datasize
);
1146 bitmap
= ui_create_glyph(width
, height
, data
);
1147 cache_put_font(font
, character
, offset
, baseline
, width
, height
, bitmap
);
1152 process_compressed_8x8_brush_data(uint8
* in
, uint8
* out
, int Bpp
)
1154 int x
, y
, pal_index
, in_index
, shift
, do2
, i
;
1159 /* read it bottom up */
1160 for (y
= 7; y
>= 0; y
--)
1162 /* 2 bytes per row */
1164 for (do2
= 0; do2
< 2; do2
++)
1166 /* 4 pixels per byte */
1170 pal_index
= (in
[in_index
] >> shift
) & 3;
1171 /* size of palette entries depends on Bpp */
1172 for (i
= 0; i
< Bpp
; i
++)
1174 out
[(y
* 8 + x
) * Bpp
+ i
] = pal
[pal_index
* Bpp
+ i
];
1184 /* Process a brush cache order */
1186 process_brushcache(STREAM s
, uint16 flags
)
1188 BRUSHDATA brush_data
;
1189 uint8 cache_idx
, colour_code
, width
, height
, size
, type
;
1194 in_uint8(s
, cache_idx
);
1195 in_uint8(s
, colour_code
);
1197 in_uint8(s
, height
);
1198 in_uint8(s
, type
); /* type, 0x8x = cached */
1201 DEBUG(("BRUSHCACHE(idx=%d,wd=%d,ht=%d,sz=%d)\n", cache_idx
, width
, height
, size
));
1203 if ((width
== 8) && (height
== 8))
1205 if (colour_code
== 1)
1207 brush_data
.colour_code
= 1;
1208 brush_data
.data_size
= 8;
1209 brush_data
.data
= xmalloc(8);
1212 /* read it bottom up */
1213 for (index
= 7; index
>= 0; index
--)
1215 in_uint8(s
, brush_data
.data
[index
]);
1220 warning("incompatible brush, colour_code %d size %d\n", colour_code
,
1223 cache_put_brush_data(1, cache_idx
, &brush_data
);
1225 else if ((colour_code
>= 3) && (colour_code
<= 6))
1227 Bpp
= colour_code
- 2;
1228 brush_data
.colour_code
= colour_code
;
1229 brush_data
.data_size
= 8 * 8 * Bpp
;
1230 brush_data
.data
= xmalloc(8 * 8 * Bpp
);
1231 if (size
== 16 + 4 * Bpp
)
1233 in_uint8p(s
, comp_brush
, 16 + 4 * Bpp
);
1234 process_compressed_8x8_brush_data(comp_brush
, brush_data
.data
, Bpp
);
1238 in_uint8a(s
, brush_data
.data
, 8 * 8 * Bpp
);
1240 cache_put_brush_data(colour_code
, cache_idx
, &brush_data
);
1244 warning("incompatible brush, colour_code %d size %d\n", colour_code
, size
);
1249 warning("incompatible brush, width height %d %d\n", width
, height
);
1254 /* Process a secondary order */
1256 process_secondary_order(STREAM s
)
1258 /* The length isn't calculated correctly by the server.
1259 * For very compact orders the length becomes negative
1260 * so a signed integer must be used. */
1266 in_uint16_le(s
, length
);
1267 in_uint16_le(s
, flags
); /* used by bmpcache2 */
1270 next_order
= s
->p
+ (sint16
) length
+ 7;
1274 case RDP_ORDER_RAW_BMPCACHE
:
1275 process_raw_bmpcache(s
);
1278 case RDP_ORDER_COLCACHE
:
1279 process_colcache(s
);
1282 case RDP_ORDER_BMPCACHE
:
1283 process_bmpcache(s
);
1286 case RDP_ORDER_FONTCACHE
:
1287 process_fontcache(s
);
1290 case RDP_ORDER_RAW_BMPCACHE2
:
1291 process_bmpcache2(s
, flags
, False
); /* uncompressed */
1294 case RDP_ORDER_BMPCACHE2
:
1295 process_bmpcache2(s
, flags
, True
); /* compressed */
1298 case RDP_ORDER_BRUSHCACHE
:
1299 process_brushcache(s
, flags
);
1303 unimpl("secondary order %d\n", type
);
1309 /* Process an order PDU */
1311 process_orders(STREAM s
, uint16 num_orders
)
1313 RDP_ORDER_STATE
*os
= &g_order_state
;
1316 int size
, processed
= 0;
1319 while (processed
< num_orders
)
1321 in_uint8(s
, order_flags
);
1323 if (!(order_flags
& RDP_ORDER_STANDARD
))
1325 error("order parsing failed\n");
1329 if (order_flags
& RDP_ORDER_SECONDARY
)
1331 process_secondary_order(s
);
1335 if (order_flags
& RDP_ORDER_CHANGE
)
1337 in_uint8(s
, os
->order_type
);
1340 switch (os
->order_type
)
1342 case RDP_ORDER_TRIBLT
:
1343 case RDP_ORDER_TEXT2
:
1347 case RDP_ORDER_PATBLT
:
1348 case RDP_ORDER_MEMBLT
:
1349 case RDP_ORDER_LINE
:
1350 case RDP_ORDER_POLYGON2
:
1351 case RDP_ORDER_ELLIPSE2
:
1359 rdp_in_present(s
, &present
, order_flags
, size
);
1361 if (order_flags
& RDP_ORDER_BOUNDS
)
1363 if (!(order_flags
& RDP_ORDER_LASTBOUNDS
))
1364 rdp_parse_bounds(s
, &os
->bounds
);
1366 ui_set_clip(os
->bounds
.left
,
1369 os
->bounds
.left
+ 1,
1370 os
->bounds
.bottom
- os
->bounds
.top
+ 1);
1373 delta
= order_flags
& RDP_ORDER_DELTA
;
1375 switch (os
->order_type
)
1377 case RDP_ORDER_DESTBLT
:
1378 process_destblt(s
, &os
->destblt
, present
, delta
);
1381 case RDP_ORDER_PATBLT
:
1382 process_patblt(s
, &os
->patblt
, present
, delta
);
1385 case RDP_ORDER_SCREENBLT
:
1386 process_screenblt(s
, &os
->screenblt
, present
, delta
);
1389 case RDP_ORDER_LINE
:
1390 process_line(s
, &os
->line
, present
, delta
);
1393 case RDP_ORDER_RECT
:
1394 process_rect(s
, &os
->rect
, present
, delta
);
1397 case RDP_ORDER_DESKSAVE
:
1398 process_desksave(s
, &os
->desksave
, present
, delta
);
1401 case RDP_ORDER_MEMBLT
:
1402 process_memblt(s
, &os
->memblt
, present
, delta
);
1405 case RDP_ORDER_TRIBLT
:
1406 process_triblt(s
, &os
->triblt
, present
, delta
);
1409 case RDP_ORDER_POLYGON
:
1410 process_polygon(s
, &os
->polygon
, present
, delta
);
1413 case RDP_ORDER_POLYGON2
:
1414 process_polygon2(s
, &os
->polygon2
, present
, delta
);
1417 case RDP_ORDER_POLYLINE
:
1418 process_polyline(s
, &os
->polyline
, present
, delta
);
1421 case RDP_ORDER_ELLIPSE
:
1422 process_ellipse(s
, &os
->ellipse
, present
, delta
);
1425 case RDP_ORDER_ELLIPSE2
:
1426 process_ellipse2(s
, &os
->ellipse2
, present
, delta
);
1429 case RDP_ORDER_TEXT2
:
1430 process_text2(s
, &os
->text2
, present
, delta
);
1434 unimpl("order %d\n", os
->order_type
);
1438 if (order_flags
& RDP_ORDER_BOUNDS
)
1445 /* not true when RDP_COMPRESSION is set */
1446 if (s
->p
!= g_next_packet
)
1447 error("%d bytes remaining\n", (int) (g_next_packet
- s
->p
));
1452 /* Reset order state */
1454 reset_order_state(void)
1456 memset(&g_order_state
, 0, sizeof(g_order_state
));
1457 g_order_state
.order_type
= RDP_ORDER_PATBLT
;