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 /* Read field indicating which parameters are present */
26 rdp_in_present(STREAM s
, uint32
* present
, uint8 flags
, int size
)
31 if (flags
& RDP_ORDER_SMALL
)
36 if (flags
& RDP_ORDER_TINY
)
45 for (i
= 0; i
< size
; i
++)
48 *present
|= bits
<< (i
* 8);
52 /* Read a co-ordinate (16-bit, or 8-bit delta) */
54 rdp_in_coord(STREAM s
, sint16
* coord
, BOOL delta
)
65 in_uint16_le(s
, *coord
);
69 /* Parse a delta co-ordinate in polyline/polygon order form */
71 parse_delta(uint8
* buffer
, int *offset
)
73 int value
= buffer
[(*offset
)++];
74 int two_byte
= value
& 0x80;
76 if (value
& 0x40) /* sign bit */
82 value
= (value
<< 8) | buffer
[(*offset
)++];
87 /* Read a colour entry */
89 rdp_in_colour(STREAM s
, uint32
* colour
)
100 /* Parse bounds information */
102 rdp_parse_bounds(STREAM s
, BOUNDS
* bounds
)
106 in_uint8(s
, present
);
109 rdp_in_coord(s
, &bounds
->left
, False
);
110 else if (present
& 16)
111 rdp_in_coord(s
, &bounds
->left
, True
);
114 rdp_in_coord(s
, &bounds
->top
, False
);
115 else if (present
& 32)
116 rdp_in_coord(s
, &bounds
->top
, True
);
119 rdp_in_coord(s
, &bounds
->right
, False
);
120 else if (present
& 64)
121 rdp_in_coord(s
, &bounds
->right
, True
);
124 rdp_in_coord(s
, &bounds
->bottom
, False
);
125 else if (present
& 128)
126 rdp_in_coord(s
, &bounds
->bottom
, True
);
133 rdp_parse_pen(STREAM s
, PEN
* pen
, uint32 present
)
136 in_uint8(s
, pen
->style
);
139 in_uint8(s
, pen
->width
);
142 rdp_in_colour(s
, &pen
->colour
);
149 rdp_parse_brush(STREAM s
, BRUSH
* brush
, uint32 present
)
152 in_uint8(s
, brush
->xorigin
);
155 in_uint8(s
, brush
->yorigin
);
158 in_uint8(s
, brush
->style
);
161 in_uint8(s
, brush
->pattern
[0]);
164 in_uint8a(s
, &brush
->pattern
[1], 7);
169 /* Process a destination blt order */
171 process_destblt(RDPCLIENT
* This
, STREAM s
, DESTBLT_ORDER
* os
, uint32 present
, BOOL delta
)
174 rdp_in_coord(s
, &os
->x
, delta
);
177 rdp_in_coord(s
, &os
->y
, delta
);
180 rdp_in_coord(s
, &os
->cx
, delta
);
183 rdp_in_coord(s
, &os
->cy
, delta
);
186 in_uint8(s
, os
->opcode
);
188 DEBUG(("DESTBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d)\n",
189 os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
));
192 ui_destblt(This
, ROP2_S(os
->opcode
), os
->x
, os
->y
, os
->cx
, os
->cy
);
194 ui_destblt(This
, os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
);
198 /* Process a pattern blt order */
200 process_patblt(RDPCLIENT
* This
, 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
));
229 ui_patblt(This
, ROP2_P(os
->opcode
), os
->x
, os
->y
, os
->cx
, os
->cy
,
230 &os
->brush
, os
->bgcolour
, os
->fgcolour
);
232 ui_patblt(This
, os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
,
233 &os
->brush
, os
->bgcolour
, os
->fgcolour
);
237 /* Process a screen blt order */
239 process_screenblt(RDPCLIENT
* This
, STREAM s
, SCREENBLT_ORDER
* os
, uint32 present
, BOOL delta
)
241 if (present
& 0x0001)
242 rdp_in_coord(s
, &os
->x
, delta
);
244 if (present
& 0x0002)
245 rdp_in_coord(s
, &os
->y
, delta
);
247 if (present
& 0x0004)
248 rdp_in_coord(s
, &os
->cx
, delta
);
250 if (present
& 0x0008)
251 rdp_in_coord(s
, &os
->cy
, delta
);
253 if (present
& 0x0010)
254 in_uint8(s
, os
->opcode
);
256 if (present
& 0x0020)
257 rdp_in_coord(s
, &os
->srcx
, delta
);
259 if (present
& 0x0040)
260 rdp_in_coord(s
, &os
->srcy
, delta
);
262 DEBUG(("SCREENBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,srcx=%d,srcy=%d)\n",
263 os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
, os
->srcx
, os
->srcy
));
266 ui_screenblt(This
, ROP2_S(os
->opcode
), os
->x
, os
->y
, os
->cx
, os
->cy
, os
->srcx
, os
->srcy
);
268 ui_screenblt(This
, os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
, os
->srcx
, os
->srcy
);
272 /* Process a line order */
274 process_line(RDPCLIENT
* This
, STREAM s
, LINE_ORDER
* os
, uint32 present
, BOOL delta
)
276 if (present
& 0x0001)
277 in_uint16_le(s
, os
->mixmode
);
279 if (present
& 0x0002)
280 rdp_in_coord(s
, &os
->startx
, delta
);
282 if (present
& 0x0004)
283 rdp_in_coord(s
, &os
->starty
, delta
);
285 if (present
& 0x0008)
286 rdp_in_coord(s
, &os
->endx
, delta
);
288 if (present
& 0x0010)
289 rdp_in_coord(s
, &os
->endy
, delta
);
291 if (present
& 0x0020)
292 rdp_in_colour(s
, &os
->bgcolour
);
294 if (present
& 0x0040)
295 in_uint8(s
, os
->opcode
);
297 rdp_parse_pen(s
, &os
->pen
, present
>> 7);
299 DEBUG(("LINE(op=0x%x,sx=%d,sy=%d,dx=%d,dy=%d,fg=0x%x)\n",
300 os
->opcode
, os
->startx
, os
->starty
, os
->endx
, os
->endy
, os
->pen
.colour
));
302 if (os
->opcode
< 0x01 || os
->opcode
> 0x10)
304 error("bad ROP2 0x%x\n", os
->opcode
);
309 ui_line(This
, os
->opcode
- 1, os
->startx
, os
->starty
, os
->endx
, os
->endy
, &os
->pen
);
311 ui_line(This
, os
->opcode
, os
->startx
, os
->starty
, os
->endx
, os
->endy
, &os
->pen
);
315 /* Process an opaque rectangle order */
317 process_rect(RDPCLIENT
* This
, STREAM s
, RECT_ORDER
* os
, uint32 present
, BOOL delta
)
321 rdp_in_coord(s
, &os
->x
, delta
);
324 rdp_in_coord(s
, &os
->y
, delta
);
327 rdp_in_coord(s
, &os
->cx
, delta
);
330 rdp_in_coord(s
, &os
->cy
, delta
);
335 os
->colour
= (os
->colour
& 0xffffff00) | i
;
341 os
->colour
= (os
->colour
& 0xffff00ff) | (i
<< 8);
347 os
->colour
= (os
->colour
& 0xff00ffff) | (i
<< 16);
350 DEBUG(("RECT(x=%d,y=%d,cx=%d,cy=%d,fg=0x%x)\n", os
->x
, os
->y
, os
->cx
, os
->cy
, os
->colour
));
352 ui_rect(This
, os
->x
, os
->y
, os
->cx
, os
->cy
, os
->colour
);
355 /* Process a desktop save order */
357 process_desksave(RDPCLIENT
* This
, STREAM s
, DESKSAVE_ORDER
* os
, uint32 present
, BOOL delta
)
362 in_uint32_le(s
, os
->offset
);
365 rdp_in_coord(s
, &os
->left
, delta
);
368 rdp_in_coord(s
, &os
->top
, delta
);
371 rdp_in_coord(s
, &os
->right
, delta
);
374 rdp_in_coord(s
, &os
->bottom
, delta
);
377 in_uint8(s
, os
->action
);
379 DEBUG(("DESKSAVE(l=%d,t=%d,r=%d,b=%d,off=%d,op=%d)\n",
380 os
->left
, os
->top
, os
->right
, os
->bottom
, os
->offset
, os
->action
));
382 width
= os
->right
- os
->left
+ 1;
383 height
= os
->bottom
- os
->top
+ 1;
386 ui_desktop_save(This
, os
->offset
, os
->left
, os
->top
, width
, height
);
388 ui_desktop_restore(This
, os
->offset
, os
->left
, os
->top
, width
, height
);
391 /* Process a memory blt order */
393 process_memblt(RDPCLIENT
* This
, STREAM s
, MEMBLT_ORDER
* os
, uint32 present
, BOOL delta
)
397 if (present
& 0x0001)
399 in_uint8(s
, os
->cache_id
);
400 in_uint8(s
, os
->colour_table
);
403 if (present
& 0x0002)
404 rdp_in_coord(s
, &os
->x
, delta
);
406 if (present
& 0x0004)
407 rdp_in_coord(s
, &os
->y
, delta
);
409 if (present
& 0x0008)
410 rdp_in_coord(s
, &os
->cx
, delta
);
412 if (present
& 0x0010)
413 rdp_in_coord(s
, &os
->cy
, delta
);
415 if (present
& 0x0020)
416 in_uint8(s
, os
->opcode
);
418 if (present
& 0x0040)
419 rdp_in_coord(s
, &os
->srcx
, delta
);
421 if (present
& 0x0080)
422 rdp_in_coord(s
, &os
->srcy
, delta
);
424 if (present
& 0x0100)
425 in_uint16_le(s
, os
->cache_idx
);
427 DEBUG(("MEMBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d)\n",
428 os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
, os
->cache_id
, os
->cache_idx
));
430 bitmap
= cache_get_bitmap(This
, os
->cache_id
, os
->cache_idx
);
435 ui_memblt(This
, ROP2_S(os
->opcode
), os
->x
, os
->y
, os
->cx
, os
->cy
, bitmap
, os
->srcx
, os
->srcy
);
437 ui_memblt(This
, os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
, bitmap
, os
->srcx
, os
->srcy
);
441 /* Process a 3-way blt order */
443 process_triblt(RDPCLIENT
* This
, STREAM s
, TRIBLT_ORDER
* os
, uint32 present
, BOOL delta
)
447 if (present
& 0x000001)
449 in_uint8(s
, os
->cache_id
);
450 in_uint8(s
, os
->colour_table
);
453 if (present
& 0x000002)
454 rdp_in_coord(s
, &os
->x
, delta
);
456 if (present
& 0x000004)
457 rdp_in_coord(s
, &os
->y
, delta
);
459 if (present
& 0x000008)
460 rdp_in_coord(s
, &os
->cx
, delta
);
462 if (present
& 0x000010)
463 rdp_in_coord(s
, &os
->cy
, delta
);
465 if (present
& 0x000020)
466 in_uint8(s
, os
->opcode
);
468 if (present
& 0x000040)
469 rdp_in_coord(s
, &os
->srcx
, delta
);
471 if (present
& 0x000080)
472 rdp_in_coord(s
, &os
->srcy
, delta
);
474 if (present
& 0x000100)
475 rdp_in_colour(s
, &os
->bgcolour
);
477 if (present
& 0x000200)
478 rdp_in_colour(s
, &os
->fgcolour
);
480 rdp_parse_brush(s
, &os
->brush
, present
>> 10);
482 if (present
& 0x008000)
483 in_uint16_le(s
, os
->cache_idx
);
485 if (present
& 0x010000)
486 in_uint16_le(s
, os
->unknown
);
488 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",
489 os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
, os
->cache_id
, os
->cache_idx
,
490 os
->brush
.style
, os
->bgcolour
, os
->fgcolour
));
492 bitmap
= cache_get_bitmap(This
, os
->cache_id
, os
->cache_idx
);
496 ui_triblt(This
, os
->opcode
, os
->x
, os
->y
, os
->cx
, os
->cy
,
497 bitmap
, os
->srcx
, os
->srcy
, &os
->brush
, os
->bgcolour
, os
->fgcolour
);
500 /* Process a polygon order */
502 process_polygon(RDPCLIENT
* This
, STREAM s
, POLYGON_ORDER
* os
, uint32 present
, BOOL delta
)
504 int index
, data
, next
;
509 rdp_in_coord(s
, &os
->x
, delta
);
512 rdp_in_coord(s
, &os
->y
, delta
);
515 in_uint8(s
, os
->opcode
);
518 in_uint8(s
, os
->fillmode
);
521 rdp_in_colour(s
, &os
->fgcolour
);
524 in_uint8(s
, os
->npoints
);
528 in_uint8(s
, os
->datasize
);
529 in_uint8a(s
, os
->data
, os
->datasize
);
532 DEBUG(("POLYGON(x=%d,y=%d,op=0x%x,fm=%d,fg=0x%x,n=%d,sz=%d)\n",
533 os
->x
, os
->y
, os
->opcode
, os
->fillmode
, os
->fgcolour
, os
->npoints
, os
->datasize
));
537 for (index
= 0; index
< os
->datasize
; index
++)
538 DEBUG(("%02x ", os
->data
[index
]));
542 if (os
->opcode
< 0x01 || os
->opcode
> 0x10)
544 error("bad ROP2 0x%x\n", os
->opcode
);
548 points
= (POINT
*) malloc((os
->npoints
+ 1) * sizeof(POINT
));
553 memset(points
, 0, (os
->npoints
+ 1) * sizeof(POINT
));
559 data
= ((os
->npoints
- 1) / 4) + 1;
560 for (next
= 1; (next
<= os
->npoints
) && (next
< 256) && (data
< os
->datasize
); next
++)
562 if ((next
- 1) % 4 == 0)
563 flags
= os
->data
[index
++];
566 points
[next
].x
= parse_delta(os
->data
, &data
);
569 points
[next
].y
= parse_delta(os
->data
, &data
);
574 if (next
- 1 == os
->npoints
)
576 ui_polygon(This
, os
->opcode
- 1, os
->fillmode
, points
, os
->npoints
+ 1, NULL
, 0,
579 ui_polygon(This
, os
->opcode
, os
->fillmode
, points
, os
->npoints
+ 1, NULL
, 0,
583 error("polygon parse error\n");
588 /* Process a polygon2 order */
590 process_polygon2(RDPCLIENT
* This
, STREAM s
, POLYGON2_ORDER
* os
, uint32 present
, BOOL delta
)
592 int index
, data
, next
;
596 if (present
& 0x0001)
597 rdp_in_coord(s
, &os
->x
, delta
);
599 if (present
& 0x0002)
600 rdp_in_coord(s
, &os
->y
, delta
);
602 if (present
& 0x0004)
603 in_uint8(s
, os
->opcode
);
605 if (present
& 0x0008)
606 in_uint8(s
, os
->fillmode
);
608 if (present
& 0x0010)
609 rdp_in_colour(s
, &os
->bgcolour
);
611 if (present
& 0x0020)
612 rdp_in_colour(s
, &os
->fgcolour
);
614 rdp_parse_brush(s
, &os
->brush
, present
>> 6);
616 if (present
& 0x0800)
617 in_uint8(s
, os
->npoints
);
619 if (present
& 0x1000)
621 in_uint8(s
, os
->datasize
);
622 in_uint8a(s
, os
->data
, os
->datasize
);
625 DEBUG(("POLYGON2(x=%d,y=%d,op=0x%x,fm=%d,bs=%d,bg=0x%x,fg=0x%x,n=%d,sz=%d)\n",
626 os
->x
, os
->y
, os
->opcode
, os
->fillmode
, os
->brush
.style
, os
->bgcolour
, os
->fgcolour
,
627 os
->npoints
, os
->datasize
));
631 for (index
= 0; index
< os
->datasize
; index
++)
632 DEBUG(("%02x ", os
->data
[index
]));
636 if (os
->opcode
< 0x01 || os
->opcode
> 0x10)
638 error("bad ROP2 0x%x\n", os
->opcode
);
642 points
= (POINT
*) malloc((os
->npoints
+ 1) * sizeof(POINT
));
647 memset(points
, 0, (os
->npoints
+ 1) * sizeof(POINT
));
653 data
= ((os
->npoints
- 1) / 4) + 1;
654 for (next
= 1; (next
<= os
->npoints
) && (next
< 256) && (data
< os
->datasize
); next
++)
656 if ((next
- 1) % 4 == 0)
657 flags
= os
->data
[index
++];
660 points
[next
].x
= parse_delta(os
->data
, &data
);
663 points
[next
].y
= parse_delta(os
->data
, &data
);
668 if (next
- 1 == os
->npoints
)
670 ui_polygon(This
, os
->opcode
- 1, os
->fillmode
, points
, os
->npoints
+ 1,
671 &os
->brush
, os
->bgcolour
, os
->fgcolour
);
673 ui_polygon(This
, os
->opcode
, os
->fillmode
, points
, os
->npoints
+ 1,
674 &os
->brush
, os
->bgcolour
, os
->fgcolour
);
677 error("polygon2 parse error\n");
682 /* Process a polyline order */
684 process_polyline(RDPCLIENT
* This
, STREAM s
, POLYLINE_ORDER
* os
, uint32 present
, BOOL delta
)
686 int index
, next
, data
;
692 rdp_in_coord(s
, &os
->x
, delta
);
695 rdp_in_coord(s
, &os
->y
, delta
);
698 in_uint8(s
, os
->opcode
);
701 rdp_in_colour(s
, &os
->fgcolour
);
704 in_uint8(s
, os
->lines
);
708 in_uint8(s
, os
->datasize
);
709 in_uint8a(s
, os
->data
, os
->datasize
);
712 DEBUG(("POLYLINE(x=%d,y=%d,op=0x%x,fg=0x%x,n=%d,sz=%d)\n",
713 os
->x
, os
->y
, os
->opcode
, os
->fgcolour
, os
->lines
, os
->datasize
));
717 for (index
= 0; index
< os
->datasize
; index
++)
718 DEBUG(("%02x ", os
->data
[index
]));
722 if (os
->opcode
< 0x01 || os
->opcode
> 0x10)
724 error("bad ROP2 0x%x\n", os
->opcode
);
728 points
= (POINT
*) malloc((os
->lines
+ 1) * sizeof(POINT
));
733 memset(points
, 0, (os
->lines
+ 1) * sizeof(POINT
));
737 pen
.style
= pen
.width
= 0;
738 pen
.colour
= os
->fgcolour
;
741 data
= ((os
->lines
- 1) / 4) + 1;
742 for (next
= 1; (next
<= os
->lines
) && (data
< os
->datasize
); next
++)
744 if ((next
- 1) % 4 == 0)
745 flags
= os
->data
[index
++];
748 points
[next
].x
= parse_delta(os
->data
, &data
);
751 points
[next
].y
= parse_delta(os
->data
, &data
);
756 if (next
- 1 == os
->lines
)
758 ui_polyline(This
, os
->opcode
- 1, points
, os
->lines
+ 1, &pen
);
760 ui_polyline(This
, os
->opcode
, points
, os
->lines
+ 1, &pen
);
763 error("polyline parse error\n");
768 /* Process an ellipse order */
770 process_ellipse(RDPCLIENT
* This
, STREAM s
, ELLIPSE_ORDER
* os
, uint32 present
, BOOL delta
)
773 rdp_in_coord(s
, &os
->left
, delta
);
776 rdp_in_coord(s
, &os
->top
, delta
);
779 rdp_in_coord(s
, &os
->right
, delta
);
782 rdp_in_coord(s
, &os
->bottom
, delta
);
785 in_uint8(s
, os
->opcode
);
788 in_uint8(s
, os
->fillmode
);
791 rdp_in_colour(s
, &os
->fgcolour
);
793 DEBUG(("ELLIPSE(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,fg=0x%x)\n", os
->left
, os
->top
,
794 os
->right
, os
->bottom
, os
->opcode
, os
->fillmode
, os
->fgcolour
));
797 ui_ellipse(This
, os
->opcode
- 1, os
->fillmode
, os
->left
, os
->top
, os
->right
- os
->left
,
798 os
->bottom
- os
->top
, NULL
, 0, os
->fgcolour
);
800 ui_ellipse(This
, os
->opcode
, os
->fillmode
, os
->left
, os
->top
, os
->right
- os
->left
,
801 os
->bottom
- os
->top
, NULL
, 0, os
->fgcolour
);
805 /* Process an ellipse2 order */
807 process_ellipse2(RDPCLIENT
* This
, STREAM s
, ELLIPSE2_ORDER
* os
, uint32 present
, BOOL delta
)
809 if (present
& 0x0001)
810 rdp_in_coord(s
, &os
->left
, delta
);
812 if (present
& 0x0002)
813 rdp_in_coord(s
, &os
->top
, delta
);
815 if (present
& 0x0004)
816 rdp_in_coord(s
, &os
->right
, delta
);
818 if (present
& 0x0008)
819 rdp_in_coord(s
, &os
->bottom
, delta
);
821 if (present
& 0x0010)
822 in_uint8(s
, os
->opcode
);
824 if (present
& 0x0020)
825 in_uint8(s
, os
->fillmode
);
827 if (present
& 0x0040)
828 rdp_in_colour(s
, &os
->bgcolour
);
830 if (present
& 0x0080)
831 rdp_in_colour(s
, &os
->fgcolour
);
833 rdp_parse_brush(s
, &os
->brush
, present
>> 8);
835 DEBUG(("ELLIPSE2(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,bs=%d,bg=0x%x,fg=0x%x)\n",
836 os
->left
, os
->top
, os
->right
, os
->bottom
, os
->opcode
, os
->fillmode
, os
->brush
.style
,
837 os
->bgcolour
, os
->fgcolour
));
840 ui_ellipse(This
, os
->opcode
- 1, os
->fillmode
, os
->left
, os
->top
, os
->right
- os
->left
,
841 os
->bottom
- os
->top
, &os
->brush
, os
->bgcolour
, os
->fgcolour
);
843 ui_ellipse(This
, os
->opcode
, os
->fillmode
, os
->left
, os
->top
, os
->right
- os
->left
,
844 os
->bottom
- os
->top
, &os
->brush
, os
->bgcolour
, os
->fgcolour
);
848 /* Process a text order */
850 process_text2(RDPCLIENT
* This
, STREAM s
, TEXT2_ORDER
* os
, uint32 present
, BOOL delta
)
854 if (present
& 0x000001)
855 in_uint8(s
, os
->font
);
857 if (present
& 0x000002)
858 in_uint8(s
, os
->flags
);
860 if (present
& 0x000004)
861 in_uint8(s
, os
->opcode
);
863 if (present
& 0x000008)
864 in_uint8(s
, os
->mixmode
);
866 if (present
& 0x000010)
867 rdp_in_colour(s
, &os
->fgcolour
);
869 if (present
& 0x000020)
870 rdp_in_colour(s
, &os
->bgcolour
);
872 if (present
& 0x000040)
873 in_uint16_le(s
, os
->clipleft
);
875 if (present
& 0x000080)
876 in_uint16_le(s
, os
->cliptop
);
878 if (present
& 0x000100)
879 in_uint16_le(s
, os
->clipright
);
881 if (present
& 0x000200)
882 in_uint16_le(s
, os
->clipbottom
);
884 if (present
& 0x000400)
885 in_uint16_le(s
, os
->boxleft
);
887 if (present
& 0x000800)
888 in_uint16_le(s
, os
->boxtop
);
890 if (present
& 0x001000)
891 in_uint16_le(s
, os
->boxright
);
893 if (present
& 0x002000)
894 in_uint16_le(s
, os
->boxbottom
);
896 rdp_parse_brush(s
, &os
->brush
, present
>> 14);
898 if (present
& 0x080000)
899 in_uint16_le(s
, os
->x
);
901 if (present
& 0x100000)
902 in_uint16_le(s
, os
->y
);
904 if (present
& 0x200000)
906 in_uint8(s
, os
->length
);
907 in_uint8a(s
, os
->text
, os
->length
);
910 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
));
914 for (i
= 0; i
< os
->length
; i
++)
915 DEBUG(("%02x ", os
->text
[i
]));
920 ui_draw_text(This
, os
->font
, os
->flags
, os
->opcode
- 1, os
->mixmode
, os
->x
, os
->y
,
921 os
->clipleft
, os
->cliptop
, os
->clipright
- os
->clipleft
,
922 os
->clipbottom
- os
->cliptop
, os
->boxleft
, os
->boxtop
,
923 os
->boxright
- os
->boxleft
, os
->boxbottom
- os
->boxtop
,
924 &os
->brush
, os
->bgcolour
, os
->fgcolour
, os
->text
, os
->length
);
926 ui_draw_text(This
, os
->font
, os
->flags
, os
->opcode
, os
->mixmode
, os
->x
, os
->y
,
927 os
->clipleft
, os
->cliptop
, os
->clipright
- os
->clipleft
,
928 os
->clipbottom
- os
->cliptop
, os
->boxleft
, os
->boxtop
,
929 os
->boxright
- os
->boxleft
, os
->boxbottom
- os
->boxtop
,
930 &os
->brush
, os
->bgcolour
, os
->fgcolour
, os
->text
, os
->length
);
934 /* Process a raw bitmap cache order */
936 process_raw_bmpcache(RDPCLIENT
* This
, STREAM s
)
939 uint16 cache_idx
, bufsize
;
940 uint8 cache_id
, width
, height
, bpp
, Bpp
;
943 in_uint8(s
, cache_id
);
944 in_uint8s(s
, 1); /* pad */
949 in_uint16_le(s
, bufsize
);
950 in_uint16_le(s
, cache_idx
);
951 in_uint8p(s
, data
, bufsize
);
953 DEBUG(("RAW_BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n", width
, height
, cache_id
, cache_idx
));
955 inverted
= (uint8
*) xmalloc(width
* height
* Bpp
);
956 for (y
= 0; y
< height
; y
++)
958 memcpy(&inverted
[(height
- y
- 1) * (width
* Bpp
)], &data
[y
* (width
* Bpp
)],
964 bitmap
= ui_create_bitmap(This
, width
, height
, inverted
);
967 bitmap
= ui_create_bitmap(This
, width
, height
, data
);
970 cache_put_bitmap(This
, cache_id
, cache_idx
, bitmap
);
973 /* Process a bitmap cache order */
975 process_bmpcache(RDPCLIENT
* This
, STREAM s
)
978 uint16 cache_idx
, size
;
979 uint8 cache_id
, width
, height
, bpp
, Bpp
;
980 uint8
*data
, *bmpdata
;
981 uint16 bufsize
, pad2
, row_size
, final_size
;
984 pad2
= row_size
= final_size
= 0xffff; /* Shut the compiler up */
986 in_uint8(s
, cache_id
);
987 in_uint8(s
, pad1
); /* pad */
992 in_uint16_le(s
, bufsize
); /* bufsize */
993 in_uint16_le(s
, cache_idx
);
1002 /* Begin compressedBitmapData */
1003 in_uint16_le(s
, pad2
); /* pad */
1004 in_uint16_le(s
, size
);
1005 /* in_uint8s(s, 4); *//* row_size, final_size */
1006 in_uint16_le(s
, row_size
);
1007 in_uint16_le(s
, final_size
);
1010 in_uint8p(s
, data
, size
);
1012 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
));
1014 bmpdata
= (uint8
*) malloc(width
* height
* Bpp
);
1019 if (bitmap_decompress(bmpdata
, width
, height
, data
, size
, Bpp
))
1021 bitmap
= ui_create_bitmap(This
, width
, height
, bmpdata
);
1022 cache_put_bitmap(This
, cache_id
, cache_idx
, bitmap
);
1026 DEBUG(("Failed to decompress bitmap data\n"));
1032 /* Process a bitmap cache v2 order */
1034 process_bmpcache2(RDPCLIENT
* This
, STREAM s
, uint16 flags
, BOOL compressed
)
1037 uint8 cache_id
, cache_idx_low
, width
, height
, Bpp
;
1038 uint16 cache_idx
, bufsize
;
1039 uint8
*data
, *bmpdata
, *bitmap_id
;
1041 bitmap_id
= NULL
; /* prevent compiler warning */
1042 cache_id
= flags
& ID_MASK
;
1043 Bpp
= ((flags
& MODE_MASK
) >> MODE_SHIFT
) - 2;
1045 if (flags
& PERSIST
)
1047 in_uint8p(s
, bitmap_id
, 8);
1058 in_uint8(s
, height
);
1061 in_uint16_be(s
, bufsize
);
1062 bufsize
&= BUFSIZE_MASK
;
1063 in_uint8(s
, cache_idx
);
1065 if (cache_idx
& LONG_FORMAT
)
1067 in_uint8(s
, cache_idx_low
);
1068 cache_idx
= ((cache_idx
^ LONG_FORMAT
) << 8) + cache_idx_low
;
1071 in_uint8p(s
, data
, bufsize
);
1073 DEBUG(("BMPCACHE2(compr=%d,flags=%x,cx=%d,cy=%d,id=%d,idx=%d,Bpp=%d,bs=%d)\n",
1074 compressed
, flags
, width
, height
, cache_id
, cache_idx
, Bpp
, bufsize
));
1078 bmpdata
= (uint8
*) malloc(width
* height
* Bpp
);
1083 if (!bitmap_decompress(bmpdata
, width
, height
, data
, bufsize
, Bpp
))
1085 DEBUG(("Failed to decompress bitmap data\n"));
1093 for (y
= 0; y
< height
; y
++)
1094 memcpy(&bmpdata
[(height
- y
- 1) * (width
* Bpp
)],
1095 &data
[y
* (width
* Bpp
)], width
* Bpp
);
1101 bitmap
= ui_create_bitmap(This
, width
, height
, bmpdata
);
1105 cache_put_bitmap(This
, cache_id
, cache_idx
, bitmap
);
1106 if (flags
& PERSIST
)
1107 pstcache_save_bitmap(This
, cache_id
, cache_idx
, bitmap_id
, width
, height
,
1108 width
* height
* Bpp
, bmpdata
);
1112 DEBUG(("process_bmpcache2: ui_create_bitmap failed\n"));
1119 /* Process a colourmap cache order */
1121 process_colcache(RDPCLIENT
* This
, STREAM s
)
1129 in_uint8(s
, cache_id
);
1130 in_uint16_le(s
, map
.ncolours
);
1132 map
.colours
= (COLOURENTRY
*) malloc(sizeof(COLOURENTRY
) * map
.ncolours
);
1134 if(map
.colours
== NULL
)
1136 in_uint8s(s
, map
.ncolours
* 4);
1140 for (i
= 0; i
< map
.ncolours
; i
++)
1142 entry
= &map
.colours
[i
];
1143 in_uint8(s
, entry
->blue
);
1144 in_uint8(s
, entry
->green
);
1145 in_uint8(s
, entry
->red
);
1146 in_uint8s(s
, 1); /* pad */
1149 DEBUG(("COLCACHE(id=%d,n=%d)\n", cache_id
, map
.ncolours
));
1151 hmap
= ui_create_colourmap(This
, &map
);
1154 ui_set_colourmap(This
, hmap
);
1159 /* Process a font cache order */
1161 process_fontcache(RDPCLIENT
* This
, STREAM s
)
1164 uint8 font
, nglyphs
;
1165 uint16 character
, offset
, baseline
, width
, height
;
1170 in_uint8(s
, nglyphs
);
1172 DEBUG(("FONTCACHE(font=%d,n=%d)\n", font
, nglyphs
));
1174 for (i
= 0; i
< nglyphs
; i
++)
1176 in_uint16_le(s
, character
);
1177 in_uint16_le(s
, offset
);
1178 in_uint16_le(s
, baseline
);
1179 in_uint16_le(s
, width
);
1180 in_uint16_le(s
, height
);
1182 datasize
= (height
* ((width
+ 7) / 8) + 3) & ~3;
1183 in_uint8p(s
, data
, datasize
);
1185 bitmap
= ui_create_glyph(This
, width
, height
, data
);
1186 cache_put_font(This
, font
, character
, offset
, baseline
, width
, height
, bitmap
);
1190 /* Process a secondary order */
1192 process_secondary_order(RDPCLIENT
* This
, STREAM s
)
1194 /* The length isn't calculated correctly by the server.
1195 * For very compact orders the length becomes negative
1196 * so a signed integer must be used. */
1202 in_uint16_le(s
, length
);
1203 in_uint16_le(s
, flags
); /* used by bmpcache2 */
1206 next_order
= s
->p
+ (sint16
) length
+ 7;
1210 case RDP_ORDER_RAW_BMPCACHE
:
1211 process_raw_bmpcache(This
, s
);
1214 case RDP_ORDER_COLCACHE
:
1215 process_colcache(This
, s
);
1218 case RDP_ORDER_BMPCACHE
:
1219 process_bmpcache(This
, s
);
1222 case RDP_ORDER_FONTCACHE
:
1223 process_fontcache(This
, s
);
1226 case RDP_ORDER_RAW_BMPCACHE2
:
1227 process_bmpcache2(This
, s
, flags
, False
); /* uncompressed */
1230 case RDP_ORDER_BMPCACHE2
:
1231 process_bmpcache2(This
, s
, flags
, True
); /* compressed */
1235 unimpl("secondary order %d\n", type
);
1241 /* Process an order PDU */
1243 process_orders(RDPCLIENT
* This
, STREAM s
, uint16 num_orders
)
1245 RDP_ORDER_STATE
*os
= &This
->orders
.order_state
;
1248 int size
, processed
= 0;
1251 while (processed
< num_orders
)
1253 in_uint8(s
, order_flags
);
1255 if (!(order_flags
& RDP_ORDER_STANDARD
))
1257 error("order parsing failed\n");
1261 if (order_flags
& RDP_ORDER_SECONDARY
)
1263 process_secondary_order(This
, s
);
1267 if (order_flags
& RDP_ORDER_CHANGE
)
1269 in_uint8(s
, os
->order_type
);
1272 switch (os
->order_type
)
1274 case RDP_ORDER_TRIBLT
:
1275 case RDP_ORDER_TEXT2
:
1279 case RDP_ORDER_PATBLT
:
1280 case RDP_ORDER_MEMBLT
:
1281 case RDP_ORDER_LINE
:
1282 case RDP_ORDER_POLYGON2
:
1283 case RDP_ORDER_ELLIPSE2
:
1291 rdp_in_present(s
, &present
, order_flags
, size
);
1293 if (order_flags
& RDP_ORDER_BOUNDS
)
1295 if (!(order_flags
& RDP_ORDER_LASTBOUNDS
))
1296 rdp_parse_bounds(s
, &os
->bounds
);
1298 ui_set_clip(This
, os
->bounds
.left
,
1301 os
->bounds
.left
+ 1,
1302 os
->bounds
.bottom
- os
->bounds
.top
+ 1);
1305 delta
= order_flags
& RDP_ORDER_DELTA
;
1307 switch (os
->order_type
)
1309 case RDP_ORDER_DESTBLT
:
1310 process_destblt(This
, s
, &os
->destblt
, present
, delta
);
1313 case RDP_ORDER_PATBLT
:
1314 process_patblt(This
, s
, &os
->patblt
, present
, delta
);
1317 case RDP_ORDER_SCREENBLT
:
1318 process_screenblt(This
, s
, &os
->screenblt
, present
, delta
);
1321 case RDP_ORDER_LINE
:
1322 process_line(This
, s
, &os
->line
, present
, delta
);
1325 case RDP_ORDER_RECT
:
1326 process_rect(This
, s
, &os
->rect
, present
, delta
);
1329 case RDP_ORDER_DESKSAVE
:
1330 process_desksave(This
, s
, &os
->desksave
, present
, delta
);
1333 case RDP_ORDER_MEMBLT
:
1334 process_memblt(This
, s
, &os
->memblt
, present
, delta
);
1337 case RDP_ORDER_TRIBLT
:
1338 process_triblt(This
, s
, &os
->triblt
, present
, delta
);
1341 case RDP_ORDER_POLYGON
:
1342 process_polygon(This
, s
, &os
->polygon
, present
, delta
);
1345 case RDP_ORDER_POLYGON2
:
1346 process_polygon2(This
, s
, &os
->polygon2
, present
, delta
);
1349 case RDP_ORDER_POLYLINE
:
1350 process_polyline(This
, s
, &os
->polyline
, present
, delta
);
1353 case RDP_ORDER_ELLIPSE
:
1354 process_ellipse(This
, s
, &os
->ellipse
, present
, delta
);
1357 case RDP_ORDER_ELLIPSE2
:
1358 process_ellipse2(This
, s
, &os
->ellipse2
, present
, delta
);
1361 case RDP_ORDER_TEXT2
:
1362 process_text2(This
, s
, &os
->text2
, present
, delta
);
1366 unimpl("order %d\n", os
->order_type
);
1370 if (order_flags
& RDP_ORDER_BOUNDS
)
1371 ui_reset_clip(This
);
1377 /* not true when RDP_COMPRESSION is set */
1378 if (s
->p
!= This
->next_packet
)
1379 error("%d bytes remaining\n", (int) (This
->next_packet
- s
->p
));
1384 /* Reset order state */
1386 reset_order_state(RDPCLIENT
* This
)
1388 memset(&This
->orders
.order_state
, 0, sizeof(This
->orders
.order_state
));
1389 This
->orders
.order_state
.order_type
= RDP_ORDER_PATBLT
;