1 /* -*- c-basic-offset: 8 -*-
2    rdesktop: A Remote Desktop Protocol client.
3    RDP order processing
4    Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
5 
6    This program is free software: you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation, either version 3 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "rdesktop.h"
21 #include "orders.h"
22 
23 extern size_t g_next_packet;
24 static RDP_ORDER_STATE g_order_state;
25 extern RDP_VERSION g_rdp_version;
26 
27 /* Read field indicating which parameters are present */
28 static void
rdp_in_present(STREAM s,uint32 * present,uint8 flags,int size)29 rdp_in_present(STREAM s, uint32 * present, uint8 flags, int size)
30 {
31 	uint8 bits;
32 	int i;
33 
34 	if (flags & RDP_ORDER_SMALL)
35 	{
36 		size--;
37 	}
38 
39 	if (flags & RDP_ORDER_TINY)
40 	{
41 		if (size < 2)
42 			size = 0;
43 		else
44 			size -= 2;
45 	}
46 
47 	*present = 0;
48 	for (i = 0; i < size; i++)
49 	{
50 		in_uint8(s, bits);
51 		*present |= bits << (i * 8);
52 	}
53 }
54 
55 /* Read a co-ordinate (16-bit, or 8-bit delta) */
56 static void
rdp_in_coord(STREAM s,sint16 * coord,RD_BOOL delta)57 rdp_in_coord(STREAM s, sint16 * coord, RD_BOOL delta)
58 {
59 	sint8 change;
60 
61 	if (delta)
62 	{
63 		in_uint8(s, change);
64 		*coord += change;
65 	}
66 	else
67 	{
68 		in_uint16_le(s, *coord);
69 	}
70 }
71 
72 /* Parse a delta co-ordinate in polyline/polygon order form */
73 static int
parse_delta(uint8 * buffer,int * offset)74 parse_delta(uint8 * buffer, int *offset)
75 {
76 	int value = buffer[(*offset)++];
77 	int two_byte = value & 0x80;
78 
79 	if (value & 0x40)	/* sign bit */
80 		value |= ~0x3f;
81 	else
82 		value &= 0x3f;
83 
84 	if (two_byte)
85 		value = (value << 8) | buffer[(*offset)++];
86 
87 	return value;
88 }
89 
90 /* Read a colour entry */
91 static void
rdp_in_colour(STREAM s,uint32 * colour)92 rdp_in_colour(STREAM s, uint32 * colour)
93 {
94 	uint32 i;
95 	in_uint8(s, i);
96 	*colour = i;
97 	in_uint8(s, i);
98 	*colour |= i << 8;
99 	in_uint8(s, i);
100 	*colour |= i << 16;
101 }
102 
103 /* Parse bounds information */
104 static void
rdp_parse_bounds(STREAM s,BOUNDS * bounds)105 rdp_parse_bounds(STREAM s, BOUNDS * bounds)
106 {
107 	uint8 present;
108 
109 	in_uint8(s, present);
110 
111 	if (present & 1)
112 		rdp_in_coord(s, &bounds->left, False);
113 	else if (present & 16)
114 		rdp_in_coord(s, &bounds->left, True);
115 
116 	if (present & 2)
117 		rdp_in_coord(s, &bounds->top, False);
118 	else if (present & 32)
119 		rdp_in_coord(s, &bounds->top, True);
120 
121 	if (present & 4)
122 		rdp_in_coord(s, &bounds->right, False);
123 	else if (present & 64)
124 		rdp_in_coord(s, &bounds->right, True);
125 
126 	if (present & 8)
127 		rdp_in_coord(s, &bounds->bottom, False);
128 	else if (present & 128)
129 		rdp_in_coord(s, &bounds->bottom, True);
130 }
131 
132 /* Parse a pen */
133 static void
rdp_parse_pen(STREAM s,PEN * pen,uint32 present)134 rdp_parse_pen(STREAM s, PEN * pen, uint32 present)
135 {
136 	if (present & 1)
137 		in_uint8(s, pen->style);
138 
139 	if (present & 2)
140 		in_uint8(s, pen->width);
141 
142 	if (present & 4)
143 		rdp_in_colour(s, &pen->colour);
144 }
145 
146 static void
setup_brush(BRUSH * out_brush,BRUSH * in_brush)147 setup_brush(BRUSH * out_brush, BRUSH * in_brush)
148 {
149 	BRUSHDATA *brush_data;
150 	uint8 cache_idx;
151 	uint8 colour_code;
152 
153 	memcpy(out_brush, in_brush, sizeof(BRUSH));
154 	if (out_brush->style & 0x80)
155 	{
156 		colour_code = out_brush->style & 0x0f;
157 		cache_idx = out_brush->pattern[0];
158 		brush_data = cache_get_brush_data(colour_code, cache_idx);
159 		if ((brush_data == NULL) || (brush_data->data == NULL))
160 		{
161 			logger(Graphics, Error, "setup_brush(), error getting brush data, style %x",
162 			       out_brush->style);
163 			out_brush->bd = NULL;
164 			memset(out_brush->pattern, 0, 8);
165 		}
166 		else
167 		{
168 			out_brush->bd = brush_data;
169 		}
170 		out_brush->style = 3;
171 	}
172 }
173 
174 /* Parse a brush */
175 static void
rdp_parse_brush(STREAM s,BRUSH * brush,uint32 present)176 rdp_parse_brush(STREAM s, BRUSH * brush, uint32 present)
177 {
178 	if (present & 1)
179 		in_uint8(s, brush->xorigin);
180 
181 	if (present & 2)
182 		in_uint8(s, brush->yorigin);
183 
184 	if (present & 4)
185 		in_uint8(s, brush->style);
186 
187 	if (present & 8)
188 		in_uint8(s, brush->pattern[0]);
189 
190 	if (present & 16)
191 		in_uint8a(s, &brush->pattern[1], 7);
192 }
193 
194 /* Process a destination blt order */
195 static void
process_destblt(STREAM s,DESTBLT_ORDER * os,uint32 present,RD_BOOL delta)196 process_destblt(STREAM s, DESTBLT_ORDER * os, uint32 present, RD_BOOL delta)
197 {
198 	if (present & 0x01)
199 		rdp_in_coord(s, &os->x, delta);
200 
201 	if (present & 0x02)
202 		rdp_in_coord(s, &os->y, delta);
203 
204 	if (present & 0x04)
205 		rdp_in_coord(s, &os->cx, delta);
206 
207 	if (present & 0x08)
208 		rdp_in_coord(s, &os->cy, delta);
209 
210 	if (present & 0x10)
211 		in_uint8(s, os->opcode);
212 
213 	logger(Graphics, Debug, "process_destblt(), op=0x%x, x=%d, y=%d, cx=%d, cy=%d",
214 	       os->opcode, os->x, os->y, os->cx, os->cy);
215 
216 	ui_destblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy);
217 }
218 
219 /* Process a pattern blt order */
220 static void
process_patblt(STREAM s,PATBLT_ORDER * os,uint32 present,RD_BOOL delta)221 process_patblt(STREAM s, PATBLT_ORDER * os, uint32 present, RD_BOOL delta)
222 {
223 	BRUSH brush;
224 
225 	if (present & 0x0001)
226 		rdp_in_coord(s, &os->x, delta);
227 
228 	if (present & 0x0002)
229 		rdp_in_coord(s, &os->y, delta);
230 
231 	if (present & 0x0004)
232 		rdp_in_coord(s, &os->cx, delta);
233 
234 	if (present & 0x0008)
235 		rdp_in_coord(s, &os->cy, delta);
236 
237 	if (present & 0x0010)
238 		in_uint8(s, os->opcode);
239 
240 	if (present & 0x0020)
241 		rdp_in_colour(s, &os->bgcolour);
242 
243 	if (present & 0x0040)
244 		rdp_in_colour(s, &os->fgcolour);
245 
246 	rdp_parse_brush(s, &os->brush, present >> 7);
247 
248 	logger(Graphics, Debug,
249 	       "process_patblt(), op=0x%x, x=%d, y=%d, cx=%d, cy=%d, bs=%d, bg=0x%x, fg=0x%x)",
250 	       os->opcode, os->x, os->y, os->cx, os->cy, os->brush.style, os->bgcolour,
251 	       os->fgcolour);
252 
253 	setup_brush(&brush, &os->brush);
254 
255 	ui_patblt(ROP2_P(os->opcode), os->x, os->y, os->cx, os->cy,
256 		  &brush, os->bgcolour, os->fgcolour);
257 }
258 
259 /* Process a screen blt order */
260 static void
process_screenblt(STREAM s,SCREENBLT_ORDER * os,uint32 present,RD_BOOL delta)261 process_screenblt(STREAM s, SCREENBLT_ORDER * os, uint32 present, RD_BOOL delta)
262 {
263 	if (present & 0x0001)
264 		rdp_in_coord(s, &os->x, delta);
265 
266 	if (present & 0x0002)
267 		rdp_in_coord(s, &os->y, delta);
268 
269 	if (present & 0x0004)
270 		rdp_in_coord(s, &os->cx, delta);
271 
272 	if (present & 0x0008)
273 		rdp_in_coord(s, &os->cy, delta);
274 
275 	if (present & 0x0010)
276 		in_uint8(s, os->opcode);
277 
278 	if (present & 0x0020)
279 		rdp_in_coord(s, &os->srcx, delta);
280 
281 	if (present & 0x0040)
282 		rdp_in_coord(s, &os->srcy, delta);
283 
284 	logger(Graphics, Debug,
285 	       "process_screenblt(), op=0x%x, x=%d, y=%d, cx=%d, cy=%d, srcx=%d, srcy=%d)",
286 	       os->opcode, os->x, os->y, os->cx, os->cy, os->srcx, os->srcy);
287 
288 	ui_screenblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy, os->srcx, os->srcy);
289 }
290 
291 /* Process a line order */
292 static void
process_line(STREAM s,LINE_ORDER * os,uint32 present,RD_BOOL delta)293 process_line(STREAM s, LINE_ORDER * os, uint32 present, RD_BOOL delta)
294 {
295 	if (present & 0x0001)
296 		in_uint16_le(s, os->mixmode);
297 
298 	if (present & 0x0002)
299 		rdp_in_coord(s, &os->startx, delta);
300 
301 	if (present & 0x0004)
302 		rdp_in_coord(s, &os->starty, delta);
303 
304 	if (present & 0x0008)
305 		rdp_in_coord(s, &os->endx, delta);
306 
307 	if (present & 0x0010)
308 		rdp_in_coord(s, &os->endy, delta);
309 
310 	if (present & 0x0020)
311 		rdp_in_colour(s, &os->bgcolour);
312 
313 	if (present & 0x0040)
314 		in_uint8(s, os->opcode);
315 
316 	rdp_parse_pen(s, &os->pen, present >> 7);
317 
318 	logger(Graphics, Debug, "process_line(), op=0x%x, sx=%d, sy=%d, dx=%d, dy=%d, fg=0x%x)",
319 	       os->opcode, os->startx, os->starty, os->endx, os->endy, os->pen.colour);
320 
321 	if (os->opcode < 0x01 || os->opcode > 0x10)
322 	{
323 		logger(Graphics, Error, "process_line(), bad ROP2 0x%x", os->opcode);
324 		return;
325 	}
326 
327 	ui_line(os->opcode - 1, os->startx, os->starty, os->endx, os->endy, &os->pen);
328 }
329 
330 /* Process an opaque rectangle order */
331 static void
process_rect(STREAM s,RECT_ORDER * os,uint32 present,RD_BOOL delta)332 process_rect(STREAM s, RECT_ORDER * os, uint32 present, RD_BOOL delta)
333 {
334 	uint32 i;
335 	if (present & 0x01)
336 		rdp_in_coord(s, &os->x, delta);
337 
338 	if (present & 0x02)
339 		rdp_in_coord(s, &os->y, delta);
340 
341 	if (present & 0x04)
342 		rdp_in_coord(s, &os->cx, delta);
343 
344 	if (present & 0x08)
345 		rdp_in_coord(s, &os->cy, delta);
346 
347 	if (present & 0x10)
348 	{
349 		in_uint8(s, i);
350 		os->colour = (os->colour & 0xffffff00) | i;
351 	}
352 
353 	if (present & 0x20)
354 	{
355 		in_uint8(s, i);
356 		os->colour = (os->colour & 0xffff00ff) | (i << 8);
357 	}
358 
359 	if (present & 0x40)
360 	{
361 		in_uint8(s, i);
362 		os->colour = (os->colour & 0xff00ffff) | (i << 16);
363 	}
364 
365 	logger(Graphics, Debug, "process_rect(), x=%d, y=%d, cx=%d, cy=%d, fg=0x%x",
366 	       os->x, os->y, os->cx, os->cy, os->colour);
367 
368 	ui_rect(os->x, os->y, os->cx, os->cy, os->colour);
369 }
370 
371 /* Process a desktop save order */
372 static void
process_desksave(STREAM s,DESKSAVE_ORDER * os,uint32 present,RD_BOOL delta)373 process_desksave(STREAM s, DESKSAVE_ORDER * os, uint32 present, RD_BOOL delta)
374 {
375 	int width, height;
376 
377 	if (present & 0x01)
378 		in_uint32_le(s, os->offset);
379 
380 	if (present & 0x02)
381 		rdp_in_coord(s, &os->left, delta);
382 
383 	if (present & 0x04)
384 		rdp_in_coord(s, &os->top, delta);
385 
386 	if (present & 0x08)
387 		rdp_in_coord(s, &os->right, delta);
388 
389 	if (present & 0x10)
390 		rdp_in_coord(s, &os->bottom, delta);
391 
392 	if (present & 0x20)
393 		in_uint8(s, os->action);
394 
395 	logger(Graphics, Debug, "process_desksave(), l=%d, t=%d, r=%d, b=%d, off=%d, op=%d",
396 	       os->left, os->top, os->right, os->bottom, os->offset, os->action);
397 
398 	width = os->right - os->left + 1;
399 	height = os->bottom - os->top + 1;
400 
401 	if (os->action == 0)
402 		ui_desktop_save(os->offset, os->left, os->top, width, height);
403 	else
404 		ui_desktop_restore(os->offset, os->left, os->top, width, height);
405 }
406 
407 /* Process a memory blt order */
408 static void
process_memblt(STREAM s,MEMBLT_ORDER * os,uint32 present,RD_BOOL delta)409 process_memblt(STREAM s, MEMBLT_ORDER * os, uint32 present, RD_BOOL delta)
410 {
411 	RD_HBITMAP bitmap;
412 
413 	if (present & 0x0001)
414 	{
415 		in_uint8(s, os->cache_id);
416 		in_uint8(s, os->colour_table);
417 	}
418 
419 	if (present & 0x0002)
420 		rdp_in_coord(s, &os->x, delta);
421 
422 	if (present & 0x0004)
423 		rdp_in_coord(s, &os->y, delta);
424 
425 	if (present & 0x0008)
426 		rdp_in_coord(s, &os->cx, delta);
427 
428 	if (present & 0x0010)
429 		rdp_in_coord(s, &os->cy, delta);
430 
431 	if (present & 0x0020)
432 		in_uint8(s, os->opcode);
433 
434 	if (present & 0x0040)
435 		rdp_in_coord(s, &os->srcx, delta);
436 
437 	if (present & 0x0080)
438 		rdp_in_coord(s, &os->srcy, delta);
439 
440 	if (present & 0x0100)
441 		in_uint16_le(s, os->cache_idx);
442 
443 	logger(Graphics, Debug,
444 	       "process_memblt(), op=0x%x, x=%d, y=%d, cx=%d, cy=%d, id=%d, idx=%d", os->opcode,
445 	       os->x, os->y, os->cx, os->cy, os->cache_id, os->cache_idx);
446 
447 	bitmap = cache_get_bitmap(os->cache_id, os->cache_idx);
448 	if (bitmap == NULL)
449 		return;
450 
451 	ui_memblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy, bitmap, os->srcx, os->srcy);
452 }
453 
454 /* Process a 3-way blt order */
455 static void
process_triblt(STREAM s,TRIBLT_ORDER * os,uint32 present,RD_BOOL delta)456 process_triblt(STREAM s, TRIBLT_ORDER * os, uint32 present, RD_BOOL delta)
457 {
458 	RD_HBITMAP bitmap;
459 	BRUSH brush;
460 
461 	if (present & 0x000001)
462 	{
463 		in_uint8(s, os->cache_id);
464 		in_uint8(s, os->colour_table);
465 	}
466 
467 	if (present & 0x000002)
468 		rdp_in_coord(s, &os->x, delta);
469 
470 	if (present & 0x000004)
471 		rdp_in_coord(s, &os->y, delta);
472 
473 	if (present & 0x000008)
474 		rdp_in_coord(s, &os->cx, delta);
475 
476 	if (present & 0x000010)
477 		rdp_in_coord(s, &os->cy, delta);
478 
479 	if (present & 0x000020)
480 		in_uint8(s, os->opcode);
481 
482 	if (present & 0x000040)
483 		rdp_in_coord(s, &os->srcx, delta);
484 
485 	if (present & 0x000080)
486 		rdp_in_coord(s, &os->srcy, delta);
487 
488 	if (present & 0x000100)
489 		rdp_in_colour(s, &os->bgcolour);
490 
491 	if (present & 0x000200)
492 		rdp_in_colour(s, &os->fgcolour);
493 
494 	rdp_parse_brush(s, &os->brush, present >> 10);
495 
496 	if (present & 0x008000)
497 		in_uint16_le(s, os->cache_idx);
498 
499 	if (present & 0x010000)
500 		in_uint16_le(s, os->unknown);
501 
502 	logger(Graphics, Debug,
503 	       "process_triblt(), op=0x%x, x=%d, y=%d, cx=%d, cy=%d, id=%d, idx=%d, bs=%d, bg=0x%x, fg=0x%x",
504 	       os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id, os->cache_idx,
505 	       os->brush.style, os->bgcolour, os->fgcolour);
506 
507 	bitmap = cache_get_bitmap(os->cache_id, os->cache_idx);
508 	if (bitmap == NULL)
509 		return;
510 
511 	setup_brush(&brush, &os->brush);
512 
513 	ui_triblt(os->opcode, os->x, os->y, os->cx, os->cy,
514 		  bitmap, os->srcx, os->srcy, &brush, os->bgcolour, os->fgcolour);
515 }
516 
517 /* Process a polygon order */
518 static void
process_polygon(STREAM s,POLYGON_ORDER * os,uint32 present,RD_BOOL delta)519 process_polygon(STREAM s, POLYGON_ORDER * os, uint32 present, RD_BOOL delta)
520 {
521 	int index, data, next;
522 	uint8 flags = 0;
523 	RD_POINT *points;
524 
525 	if (present & 0x01)
526 		rdp_in_coord(s, &os->x, delta);
527 
528 	if (present & 0x02)
529 		rdp_in_coord(s, &os->y, delta);
530 
531 	if (present & 0x04)
532 		in_uint8(s, os->opcode);
533 
534 	if (present & 0x08)
535 		in_uint8(s, os->fillmode);
536 
537 	if (present & 0x10)
538 		rdp_in_colour(s, &os->fgcolour);
539 
540 	if (present & 0x20)
541 		in_uint8(s, os->npoints);
542 
543 	if (present & 0x40)
544 	{
545 		in_uint8(s, os->datasize);
546 		in_uint8a(s, os->data, os->datasize);
547 	}
548 
549 	logger(Graphics, Debug,
550 	       "process_polygon(), x=%d, y=%d, op=0x%x, fm=%d, fg=0x%x, n=%d, sz=%d", os->x, os->y,
551 	       os->opcode, os->fillmode, os->fgcolour, os->npoints, os->datasize);
552 
553 	if (os->opcode < 0x01 || os->opcode > 0x10)
554 	{
555 		logger(Graphics, Error, "process_polygon(), bad ROP2 0x%x", os->opcode);
556 		return;
557 	}
558 
559 	points = (RD_POINT *) xmalloc((os->npoints + 1) * sizeof(RD_POINT));
560 	memset(points, 0, (os->npoints + 1) * sizeof(RD_POINT));
561 
562 	points[0].x = os->x;
563 	points[0].y = os->y;
564 
565 	index = 0;
566 	data = ((os->npoints - 1) / 4) + 1;
567 	for (next = 1; (next <= os->npoints) && (next < 256) && (data < os->datasize); next++)
568 	{
569 		if ((next - 1) % 4 == 0)
570 			flags = os->data[index++];
571 
572 		if (~flags & 0x80)
573 			points[next].x = parse_delta(os->data, &data);
574 
575 		if (~flags & 0x40)
576 			points[next].y = parse_delta(os->data, &data);
577 
578 		flags <<= 2;
579 	}
580 
581 	if (next - 1 == os->npoints)
582 		ui_polygon(os->opcode - 1, os->fillmode, points, os->npoints + 1, NULL, 0,
583 			   os->fgcolour);
584 	else
585 		logger(Graphics, Error, "process_polygon(), polygon parse error");
586 
587 	xfree(points);
588 }
589 
590 /* Process a polygon2 order */
591 static void
process_polygon2(STREAM s,POLYGON2_ORDER * os,uint32 present,RD_BOOL delta)592 process_polygon2(STREAM s, POLYGON2_ORDER * os, uint32 present, RD_BOOL delta)
593 {
594 	int index, data, next;
595 	uint8 flags = 0;
596 	RD_POINT *points;
597 	BRUSH brush;
598 
599 	if (present & 0x0001)
600 		rdp_in_coord(s, &os->x, delta);
601 
602 	if (present & 0x0002)
603 		rdp_in_coord(s, &os->y, delta);
604 
605 	if (present & 0x0004)
606 		in_uint8(s, os->opcode);
607 
608 	if (present & 0x0008)
609 		in_uint8(s, os->fillmode);
610 
611 	if (present & 0x0010)
612 		rdp_in_colour(s, &os->bgcolour);
613 
614 	if (present & 0x0020)
615 		rdp_in_colour(s, &os->fgcolour);
616 
617 	rdp_parse_brush(s, &os->brush, present >> 6);
618 
619 	if (present & 0x0800)
620 		in_uint8(s, os->npoints);
621 
622 	if (present & 0x1000)
623 	{
624 		in_uint8(s, os->datasize);
625 		in_uint8a(s, os->data, os->datasize);
626 	}
627 
628 	logger(Graphics, Debug,
629 	       "process_polygon2(), x=%d, y=%d, op=0x%x, fm=%d, bs=%d, bg=0x%x, fg=0x%x, n=%d, sz=%d)",
630 	       os->x, os->y, os->opcode, os->fillmode, os->brush.style, os->bgcolour, os->fgcolour,
631 	       os->npoints, os->datasize);
632 
633 	if (os->opcode < 0x01 || os->opcode > 0x10)
634 	{
635 		logger(Graphics, Error, "process_polygon2(), bad ROP2 0x%x", os->opcode);
636 		return;
637 	}
638 
639 	setup_brush(&brush, &os->brush);
640 
641 	points = (RD_POINT *) xmalloc((os->npoints + 1) * sizeof(RD_POINT));
642 	memset(points, 0, (os->npoints + 1) * sizeof(RD_POINT));
643 
644 	points[0].x = os->x;
645 	points[0].y = os->y;
646 
647 	index = 0;
648 	data = ((os->npoints - 1) / 4) + 1;
649 	for (next = 1; (next <= os->npoints) && (next < 256) && (data < os->datasize); next++)
650 	{
651 		if ((next - 1) % 4 == 0)
652 			flags = os->data[index++];
653 
654 		if (~flags & 0x80)
655 			points[next].x = parse_delta(os->data, &data);
656 
657 		if (~flags & 0x40)
658 			points[next].y = parse_delta(os->data, &data);
659 
660 		flags <<= 2;
661 	}
662 
663 	if (next - 1 == os->npoints)
664 		ui_polygon(os->opcode - 1, os->fillmode, points, os->npoints + 1,
665 			   &brush, os->bgcolour, os->fgcolour);
666 	else
667 		logger(Graphics, Error, "process_polygon2(), polygon parse error");
668 
669 	xfree(points);
670 }
671 
672 /* Process a polyline order */
673 static void
process_polyline(STREAM s,POLYLINE_ORDER * os,uint32 present,RD_BOOL delta)674 process_polyline(STREAM s, POLYLINE_ORDER * os, uint32 present, RD_BOOL delta)
675 {
676 	int index, next, data;
677 	uint8 flags = 0;
678 	PEN pen;
679 	RD_POINT *points;
680 
681 	if (present & 0x01)
682 		rdp_in_coord(s, &os->x, delta);
683 
684 	if (present & 0x02)
685 		rdp_in_coord(s, &os->y, delta);
686 
687 	if (present & 0x04)
688 		in_uint8(s, os->opcode);
689 
690 	if (present & 0x10)
691 		rdp_in_colour(s, &os->fgcolour);
692 
693 	if (present & 0x20)
694 		in_uint8(s, os->lines);
695 
696 	if (present & 0x40)
697 	{
698 		in_uint8(s, os->datasize);
699 		in_uint8a(s, os->data, os->datasize);
700 	}
701 
702 	logger(Graphics, Debug, "process_polyline(), x=%d, y=%d, op=0x%x, fg=0x%x, n=%d, sz=%d)",
703 	       os->x, os->y, os->opcode, os->fgcolour, os->lines, os->datasize);
704 
705 	if (os->opcode < 0x01 || os->opcode > 0x10)
706 	{
707 		logger(Graphics, Error, "process_polyline(), bad ROP2 0x%x", os->opcode);
708 		return;
709 	}
710 
711 	points = (RD_POINT *) xmalloc((os->lines + 1) * sizeof(RD_POINT));
712 	memset(points, 0, (os->lines + 1) * sizeof(RD_POINT));
713 
714 	points[0].x = os->x;
715 	points[0].y = os->y;
716 	pen.style = pen.width = 0;
717 	pen.colour = os->fgcolour;
718 
719 	index = 0;
720 	data = ((os->lines - 1) / 4) + 1;
721 	for (next = 1; (next <= os->lines) && (data < os->datasize); next++)
722 	{
723 		if ((next - 1) % 4 == 0)
724 			flags = os->data[index++];
725 
726 		if (~flags & 0x80)
727 			points[next].x = parse_delta(os->data, &data);
728 
729 		if (~flags & 0x40)
730 			points[next].y = parse_delta(os->data, &data);
731 
732 		flags <<= 2;
733 	}
734 
735 	if (next - 1 == os->lines)
736 		ui_polyline(os->opcode - 1, points, os->lines + 1, &pen);
737 	else
738 		logger(Graphics, Error, "process_polyline(), parse error");
739 
740 	xfree(points);
741 }
742 
743 /* Process an ellipse order */
744 static void
process_ellipse(STREAM s,ELLIPSE_ORDER * os,uint32 present,RD_BOOL delta)745 process_ellipse(STREAM s, ELLIPSE_ORDER * os, uint32 present, RD_BOOL delta)
746 {
747 	if (present & 0x01)
748 		rdp_in_coord(s, &os->left, delta);
749 
750 	if (present & 0x02)
751 		rdp_in_coord(s, &os->top, delta);
752 
753 	if (present & 0x04)
754 		rdp_in_coord(s, &os->right, delta);
755 
756 	if (present & 0x08)
757 		rdp_in_coord(s, &os->bottom, delta);
758 
759 	if (present & 0x10)
760 		in_uint8(s, os->opcode);
761 
762 	if (present & 0x20)
763 		in_uint8(s, os->fillmode);
764 
765 	if (present & 0x40)
766 		rdp_in_colour(s, &os->fgcolour);
767 
768 	logger(Graphics, Debug,
769 	       "process_ellipse(), l=%d, t=%d, r=%d, b=%d, op=0x%x, fm=%d, fg=0x%x", os->left,
770 	       os->top, os->right, os->bottom, os->opcode, os->fillmode, os->fgcolour);
771 
772 	ui_ellipse(os->opcode - 1, os->fillmode, os->left, os->top, os->right - os->left,
773 		   os->bottom - os->top, NULL, 0, os->fgcolour);
774 }
775 
776 /* Process an ellipse2 order */
777 static void
process_ellipse2(STREAM s,ELLIPSE2_ORDER * os,uint32 present,RD_BOOL delta)778 process_ellipse2(STREAM s, ELLIPSE2_ORDER * os, uint32 present, RD_BOOL delta)
779 {
780 	BRUSH brush;
781 
782 	if (present & 0x0001)
783 		rdp_in_coord(s, &os->left, delta);
784 
785 	if (present & 0x0002)
786 		rdp_in_coord(s, &os->top, delta);
787 
788 	if (present & 0x0004)
789 		rdp_in_coord(s, &os->right, delta);
790 
791 	if (present & 0x0008)
792 		rdp_in_coord(s, &os->bottom, delta);
793 
794 	if (present & 0x0010)
795 		in_uint8(s, os->opcode);
796 
797 	if (present & 0x0020)
798 		in_uint8(s, os->fillmode);
799 
800 	if (present & 0x0040)
801 		rdp_in_colour(s, &os->bgcolour);
802 
803 	if (present & 0x0080)
804 		rdp_in_colour(s, &os->fgcolour);
805 
806 	rdp_parse_brush(s, &os->brush, present >> 8);
807 
808 	logger(Graphics, Debug,
809 	       "process_ellipse2(), l=%d, t=%d, r=%d, b=%d, op=0x%x, fm=%d, bs=%d, bg=0x%x, fg=0x%x",
810 	       os->left, os->top, os->right, os->bottom, os->opcode, os->fillmode, os->brush.style,
811 	       os->bgcolour, os->fgcolour);
812 
813 	setup_brush(&brush, &os->brush);
814 
815 	ui_ellipse(os->opcode - 1, os->fillmode, os->left, os->top, os->right - os->left,
816 		   os->bottom - os->top, &brush, os->bgcolour, os->fgcolour);
817 }
818 
819 /* Process a text order */
820 static void
process_text2(STREAM s,TEXT2_ORDER * os,uint32 present,RD_BOOL delta)821 process_text2(STREAM s, TEXT2_ORDER * os, uint32 present, RD_BOOL delta)
822 {
823 	UNUSED(delta);
824 	BRUSH brush;
825 
826 	if (present & 0x000001)
827 		in_uint8(s, os->font);
828 
829 	if (present & 0x000002)
830 		in_uint8(s, os->flags);
831 
832 	if (present & 0x000004)
833 		in_uint8(s, os->opcode);
834 
835 	if (present & 0x000008)
836 		in_uint8(s, os->mixmode);
837 
838 	if (present & 0x000010)
839 		rdp_in_colour(s, &os->fgcolour);
840 
841 	if (present & 0x000020)
842 		rdp_in_colour(s, &os->bgcolour);
843 
844 	if (present & 0x000040)
845 		in_uint16_le(s, os->clipleft);
846 
847 	if (present & 0x000080)
848 		in_uint16_le(s, os->cliptop);
849 
850 	if (present & 0x000100)
851 		in_uint16_le(s, os->clipright);
852 
853 	if (present & 0x000200)
854 		in_uint16_le(s, os->clipbottom);
855 
856 	if (present & 0x000400)
857 		in_uint16_le(s, os->boxleft);
858 
859 	if (present & 0x000800)
860 		in_uint16_le(s, os->boxtop);
861 
862 	if (present & 0x001000)
863 		in_uint16_le(s, os->boxright);
864 
865 	if (present & 0x002000)
866 		in_uint16_le(s, os->boxbottom);
867 
868 	rdp_parse_brush(s, &os->brush, present >> 14);
869 
870 	if (present & 0x080000)
871 		in_uint16_le(s, os->x);
872 
873 	if (present & 0x100000)
874 		in_uint16_le(s, os->y);
875 
876 	if (present & 0x200000)
877 	{
878 		in_uint8(s, os->length);
879 		in_uint8a(s, os->text, os->length);
880 	}
881 
882 	logger(Graphics, Debug,
883 	       "process_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",
884 	       os->x, os->y, os->clipleft, os->cliptop, os->clipright, os->clipbottom, os->boxleft,
885 	       os->boxtop, os->boxright, os->boxbottom, os->brush.style, os->bgcolour, os->fgcolour,
886 	       os->font, os->flags, os->opcode, os->mixmode, os->length);
887 
888 	setup_brush(&brush, &os->brush);
889 
890 	ui_draw_text(os->font, os->flags, os->opcode - 1, os->mixmode, os->x, os->y,
891 		     os->clipleft, os->cliptop, os->clipright - os->clipleft,
892 		     os->clipbottom - os->cliptop, os->boxleft, os->boxtop,
893 		     os->boxright - os->boxleft, os->boxbottom - os->boxtop,
894 		     &brush, os->bgcolour, os->fgcolour, os->text, os->length);
895 }
896 
897 /* Process a raw bitmap cache order */
898 static void
process_raw_bmpcache(STREAM s)899 process_raw_bmpcache(STREAM s)
900 {
901 	RD_HBITMAP bitmap;
902 	uint16 cache_idx, bufsize;
903 	uint8 cache_id, width, height, bpp, Bpp;
904 	uint8 *data, *inverted;
905 	int y;
906 
907 	in_uint8(s, cache_id);
908 	in_uint8s(s, 1);	/* pad */
909 	in_uint8(s, width);
910 	in_uint8(s, height);
911 	in_uint8(s, bpp);
912 	Bpp = (bpp + 7) / 8;
913 	in_uint16_le(s, bufsize);
914 	in_uint16_le(s, cache_idx);
915 	in_uint8p(s, data, bufsize);
916 
917 	logger(Graphics, Debug, "process_raw_bpmcache(), cx=%d, cy=%d, id=%d, idx=%d", width,
918 	       height, cache_id, cache_idx);
919 	inverted = (uint8 *) xmalloc(width * height * Bpp);
920 	for (y = 0; y < height; y++)
921 	{
922 		memcpy(&inverted[(height - y - 1) * (width * Bpp)], &data[y * (width * Bpp)],
923 		       width * Bpp);
924 	}
925 
926 	bitmap = ui_create_bitmap(width, height, inverted);
927 	xfree(inverted);
928 	cache_put_bitmap(cache_id, cache_idx, bitmap);
929 }
930 
931 /* Process a bitmap cache order */
932 static void
process_bmpcache(STREAM s)933 process_bmpcache(STREAM s)
934 {
935 	RD_HBITMAP bitmap;
936 	uint16 cache_idx, size;
937 	uint8 cache_id, width, height, bpp, Bpp;
938 	uint8 *data, *bmpdata;
939 	uint16 bufsize, pad2, row_size, final_size;
940 	uint8 pad1;
941 
942 	pad2 = row_size = final_size = 0xffff;	/* Shut the compiler up */
943 
944 	in_uint8(s, cache_id);
945 	in_uint8(s, pad1);	/* pad */
946 	in_uint8(s, width);
947 	in_uint8(s, height);
948 	in_uint8(s, bpp);
949 	Bpp = (bpp + 7) / 8;
950 	in_uint16_le(s, bufsize);	/* bufsize */
951 	in_uint16_le(s, cache_idx);
952 
953 	if (g_rdp_version >= RDP_V5)
954 	{
955 		size = bufsize;
956 	}
957 	else
958 	{
959 
960 		/* Begin compressedBitmapData */
961 		in_uint16_le(s, pad2);	/* pad */
962 		in_uint16_le(s, size);
963 		/*      in_uint8s(s, 4);  *//* row_size, final_size */
964 		in_uint16_le(s, row_size);
965 		in_uint16_le(s, final_size);
966 
967 	}
968 	in_uint8p(s, data, size);
969 	logger(Graphics, Debug,
970 	       "process_bmpcache(), cx=%d, cy=%d, id=%d, idx=%d, bpp=%d, size=%d, pad1=%d, bufsize=%d, pad2=%d, rs=%d, fs=%d",
971 	       width, height, cache_id, cache_idx, bpp, size, pad1, bufsize, pad2, row_size,
972 	       final_size);
973 
974 	bmpdata = (uint8 *) xmalloc(width * height * Bpp);
975 
976 	if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
977 	{
978 		bitmap = ui_create_bitmap(width, height, bmpdata);
979 		cache_put_bitmap(cache_id, cache_idx, bitmap);
980 	}
981 	else
982 	{
983 		logger(Graphics, Error, "process_bmpcache(), Failed to decompress bitmap data");
984 	}
985 
986 	xfree(bmpdata);
987 }
988 
989 /* Process a bitmap cache v2 order */
990 static void
process_bmpcache2(STREAM s,uint16 flags,RD_BOOL compressed)991 process_bmpcache2(STREAM s, uint16 flags, RD_BOOL compressed)
992 {
993 	RD_HBITMAP bitmap;
994 	int y;
995 	uint8 cache_id, cache_idx_low, width, height, Bpp;
996 	uint16 cache_idx, bufsize;
997 	uint8 *data, *bmpdata, *bitmap_id;
998 
999 	bitmap_id = NULL;	/* prevent compiler warning */
1000 	cache_id = flags & ID_MASK;
1001 	Bpp = ((flags & MODE_MASK) >> MODE_SHIFT) - 2;
1002 
1003 	if (flags & PERSIST)
1004 	{
1005 		in_uint8p(s, bitmap_id, 8);
1006 	}
1007 
1008 	if (flags & SQUARE)
1009 	{
1010 		in_uint8(s, width);
1011 		height = width;
1012 	}
1013 	else
1014 	{
1015 		in_uint8(s, width);
1016 		in_uint8(s, height);
1017 	}
1018 
1019 	in_uint16_be(s, bufsize);
1020 	bufsize &= BUFSIZE_MASK;
1021 	in_uint8(s, cache_idx);
1022 
1023 	if (cache_idx & LONG_FORMAT)
1024 	{
1025 		in_uint8(s, cache_idx_low);
1026 		cache_idx = ((cache_idx ^ LONG_FORMAT) << 8) + cache_idx_low;
1027 	}
1028 
1029 	in_uint8p(s, data, bufsize);
1030 
1031 	logger(Graphics, Debug,
1032 	       "process_bmpcache2(), compr=%d, flags=%x, cx=%d, cy=%d, id=%d, idx=%d, Bpp=%d, bs=%d",
1033 	       compressed, flags, width, height, cache_id, cache_idx, Bpp, bufsize);
1034 
1035 	bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1036 
1037 	if (compressed)
1038 	{
1039 		if (!bitmap_decompress(bmpdata, width, height, data, bufsize, Bpp))
1040 		{
1041 			logger(Graphics, Error,
1042 			       "process_bmpcache2(), failed to decompress bitmap data");
1043 			xfree(bmpdata);
1044 			return;
1045 		}
1046 	}
1047 	else
1048 	{
1049 		for (y = 0; y < height; y++)
1050 			memcpy(&bmpdata[(height - y - 1) * (width * Bpp)],
1051 			       &data[y * (width * Bpp)], width * Bpp);
1052 	}
1053 
1054 	bitmap = ui_create_bitmap(width, height, bmpdata);
1055 
1056 	if (bitmap)
1057 	{
1058 		cache_put_bitmap(cache_id, cache_idx, bitmap);
1059 		if (flags & PERSIST)
1060 			pstcache_save_bitmap(cache_id, cache_idx, bitmap_id, width, height,
1061 					     width * height * Bpp, bmpdata);
1062 	}
1063 	else
1064 	{
1065 		logger(Graphics, Error, "process_bmpcache2(), ui_create_bitmap(), failed");
1066 	}
1067 
1068 	xfree(bmpdata);
1069 }
1070 
1071 /* Process a colourmap cache order */
1072 static void
process_colcache(STREAM s)1073 process_colcache(STREAM s)
1074 {
1075 	COLOURENTRY *entry;
1076 	COLOURMAP map;
1077 	RD_HCOLOURMAP hmap;
1078 	uint8 cache_id;
1079 	int i;
1080 
1081 	in_uint8(s, cache_id);
1082 	in_uint16_le(s, map.ncolours);
1083 
1084 	map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
1085 
1086 	for (i = 0; i < map.ncolours; i++)
1087 	{
1088 		entry = &map.colours[i];
1089 		in_uint8(s, entry->blue);
1090 		in_uint8(s, entry->green);
1091 		in_uint8(s, entry->red);
1092 		in_uint8s(s, 1);	/* pad */
1093 	}
1094 
1095 	logger(Graphics, Debug, "process_colcache(), id=%d, n=%d", cache_id, map.ncolours);
1096 
1097 	hmap = ui_create_colourmap(&map);
1098 
1099 	if (cache_id)
1100 		ui_set_colourmap(hmap);
1101 
1102 	xfree(map.colours);
1103 }
1104 
1105 /* Process a font cache order */
1106 static void
process_fontcache(STREAM s)1107 process_fontcache(STREAM s)
1108 {
1109 	RD_HGLYPH bitmap;
1110 	uint8 font, nglyphs;
1111 	uint16 character, offset, baseline, width, height;
1112 	int i, datasize;
1113 	uint8 *data;
1114 
1115 	in_uint8(s, font);
1116 	in_uint8(s, nglyphs);
1117 
1118 	logger(Graphics, Debug, "process_fontcache(), font=%d, n=%d", font, nglyphs);
1119 
1120 	for (i = 0; i < nglyphs; i++)
1121 	{
1122 		in_uint16_le(s, character);
1123 		in_uint16_le(s, offset);
1124 		in_uint16_le(s, baseline);
1125 		in_uint16_le(s, width);
1126 		in_uint16_le(s, height);
1127 
1128 		datasize = (height * ((width + 7) / 8) + 3) & ~3;
1129 		in_uint8p(s, data, datasize);
1130 
1131 		bitmap = ui_create_glyph(width, height, data);
1132 		cache_put_font(font, character, offset, baseline, width, height, bitmap);
1133 	}
1134 }
1135 
1136 static void
process_compressed_8x8_brush_data(uint8 * in,uint8 * out,int Bpp)1137 process_compressed_8x8_brush_data(uint8 * in, uint8 * out, int Bpp)
1138 {
1139 	int x, y, pal_index, in_index, shift, do2, i;
1140 	uint8 *pal;
1141 
1142 	in_index = 0;
1143 	pal = in + 16;
1144 	/* read it bottom up */
1145 	for (y = 7; y >= 0; y--)
1146 	{
1147 		/* 2 bytes per row */
1148 		x = 0;
1149 		for (do2 = 0; do2 < 2; do2++)
1150 		{
1151 			/* 4 pixels per byte */
1152 			shift = 6;
1153 			while (shift >= 0)
1154 			{
1155 				pal_index = (in[in_index] >> shift) & 3;
1156 				/* size of palette entries depends on Bpp */
1157 				for (i = 0; i < Bpp; i++)
1158 				{
1159 					out[(y * 8 + x) * Bpp + i] = pal[pal_index * Bpp + i];
1160 				}
1161 				x++;
1162 				shift -= 2;
1163 			}
1164 			in_index++;
1165 		}
1166 	}
1167 }
1168 
1169 /* Process a brush cache order */
1170 static void
process_brushcache(STREAM s,uint16 flags)1171 process_brushcache(STREAM s, uint16 flags)
1172 {
1173 	UNUSED(flags);
1174 	BRUSHDATA brush_data;
1175 	uint8 cache_idx, colour_code, width, height, size, type;
1176 	uint8 *comp_brush;
1177 	int index;
1178 	int Bpp;
1179 
1180 	in_uint8(s, cache_idx);
1181 	in_uint8(s, colour_code);
1182 	in_uint8(s, width);
1183 	in_uint8(s, height);
1184 	in_uint8(s, type);	/* type, 0x8x = cached */
1185 	in_uint8(s, size);
1186 
1187 	logger(Graphics, Debug, "process_brushcache(), idx=%d, wd=%d, ht=%d, type=0x%x sz=%d",
1188 	       cache_idx, width, height, type, size);
1189 
1190 	if ((width == 8) && (height == 8))
1191 	{
1192 		if (colour_code == 1)
1193 		{
1194 			brush_data.colour_code = 1;
1195 			brush_data.data_size = 8;
1196 			brush_data.data = xmalloc(8);
1197 			if (size == 8)
1198 			{
1199 				/* read it bottom up */
1200 				for (index = 7; index >= 0; index--)
1201 				{
1202 					in_uint8(s, brush_data.data[index]);
1203 				}
1204 			}
1205 			else
1206 			{
1207 				logger(Graphics, Warning,
1208 				       "process_brushcache(), incompatible brush, colour_code %d size %d",
1209 				       colour_code, size);
1210 			}
1211 			cache_put_brush_data(1, cache_idx, &brush_data);
1212 		}
1213 		else if ((colour_code >= 3) && (colour_code <= 6))
1214 		{
1215 			Bpp = colour_code - 2;
1216 			brush_data.colour_code = colour_code;
1217 			brush_data.data_size = 8 * 8 * Bpp;
1218 			brush_data.data = xmalloc(8 * 8 * Bpp);
1219 			if (size == 16 + 4 * Bpp)
1220 			{
1221 				in_uint8p(s, comp_brush, 16 + 4 * Bpp);
1222 				process_compressed_8x8_brush_data(comp_brush, brush_data.data, Bpp);
1223 			}
1224 			else
1225 			{
1226 				in_uint8a(s, brush_data.data, 8 * 8 * Bpp);
1227 			}
1228 			cache_put_brush_data(colour_code, cache_idx, &brush_data);
1229 		}
1230 		else
1231 		{
1232 			logger(Graphics, Warning,
1233 			       "process_brushcache(), incompatible brush, colour_code %d size %d",
1234 			       colour_code, size);
1235 		}
1236 	}
1237 	else
1238 	{
1239 		logger(Graphics, Warning,
1240 		       "process_brushcache(), incompatible brush, width height %d %d", width,
1241 		       height);
1242 	}
1243 }
1244 
1245 /* Process a secondary order */
1246 static void
process_secondary_order(STREAM s)1247 process_secondary_order(STREAM s)
1248 {
1249 	/* The length isn't calculated correctly by the server.
1250 	 * For very compact orders the length becomes negative
1251 	 * so a signed integer must be used. */
1252 	sint16 length;
1253 	uint16 flags;
1254 	uint8 type;
1255 	size_t next_order;
1256 	struct stream packet = *s;
1257 
1258 	in_uint16_le(s, length);
1259 	in_uint16_le(s, flags);	/* used by bmpcache2 */
1260 	in_uint8(s, type);
1261 
1262 	length += 13;  /* MS-RDPEGDI is ridiculous and says that you need to add 13 to this
1263 			  field to get the total packet length. "For historical reasons". */
1264 	length -= 6;   /* Subtract six bytes of headers and you'll get the size of the remaining
1265 			  order data. */
1266 
1267 	if (!s_check_rem(s, length))
1268 	{
1269 		rdp_protocol_error("next order pointer would overrun stream", &packet);
1270 	}
1271 
1272 	next_order = s_tell(s) + length;
1273 
1274 	switch (type)
1275 	{
1276 		case RDP_ORDER_RAW_BMPCACHE:
1277 			process_raw_bmpcache(s);
1278 			break;
1279 
1280 		case RDP_ORDER_COLCACHE:
1281 			process_colcache(s);
1282 			break;
1283 
1284 		case RDP_ORDER_BMPCACHE:
1285 			process_bmpcache(s);
1286 			break;
1287 
1288 		case RDP_ORDER_FONTCACHE:
1289 			process_fontcache(s);
1290 			break;
1291 
1292 		case RDP_ORDER_RAW_BMPCACHE2:
1293 			process_bmpcache2(s, flags, False);	/* uncompressed */
1294 			break;
1295 
1296 		case RDP_ORDER_BMPCACHE2:
1297 			process_bmpcache2(s, flags, True);	/* compressed */
1298 			break;
1299 
1300 		case RDP_ORDER_BRUSHCACHE:
1301 			process_brushcache(s, flags);
1302 			break;
1303 
1304 		default:
1305 			logger(Graphics, Warning,
1306 			       "process_secondary_order(), unhandled secondary order %d", type);
1307 	}
1308 
1309 	s_seek(s, next_order);
1310 }
1311 
1312 /* Process an order PDU */
1313 void
process_orders(STREAM s,uint16 num_orders)1314 process_orders(STREAM s, uint16 num_orders)
1315 {
1316 	RDP_ORDER_STATE *os = &g_order_state;
1317 	uint32 present;
1318 	uint8 order_flags;
1319 	int size, processed = 0;
1320 	RD_BOOL delta;
1321 
1322 	while (processed < num_orders)
1323 	{
1324 		in_uint8(s, order_flags);
1325 
1326 		if (!(order_flags & RDP_ORDER_STANDARD))
1327 		{
1328 			logger(Graphics, Error, "process_orders(), order parsing failed");
1329 			break;
1330 		}
1331 
1332 		if (order_flags & RDP_ORDER_SECONDARY)
1333 		{
1334 			process_secondary_order(s);
1335 		}
1336 		else
1337 		{
1338 			if (order_flags & RDP_ORDER_CHANGE)
1339 			{
1340 				in_uint8(s, os->order_type);
1341 			}
1342 
1343 			switch (os->order_type)
1344 			{
1345 				case RDP_ORDER_TRIBLT:
1346 				case RDP_ORDER_TEXT2:
1347 					size = 3;
1348 					break;
1349 
1350 				case RDP_ORDER_PATBLT:
1351 				case RDP_ORDER_MEMBLT:
1352 				case RDP_ORDER_LINE:
1353 				case RDP_ORDER_POLYGON2:
1354 				case RDP_ORDER_ELLIPSE2:
1355 					size = 2;
1356 					break;
1357 
1358 				default:
1359 					size = 1;
1360 			}
1361 
1362 			rdp_in_present(s, &present, order_flags, size);
1363 
1364 			if (order_flags & RDP_ORDER_BOUNDS)
1365 			{
1366 				if (!(order_flags & RDP_ORDER_LASTBOUNDS))
1367 					rdp_parse_bounds(s, &os->bounds);
1368 
1369 				ui_set_clip(os->bounds.left,
1370 					    os->bounds.top,
1371 					    os->bounds.right -
1372 					    os->bounds.left + 1,
1373 					    os->bounds.bottom - os->bounds.top + 1);
1374 			}
1375 
1376 			delta = order_flags & RDP_ORDER_DELTA;
1377 
1378 			switch (os->order_type)
1379 			{
1380 				case RDP_ORDER_DESTBLT:
1381 					process_destblt(s, &os->destblt, present, delta);
1382 					break;
1383 
1384 				case RDP_ORDER_PATBLT:
1385 					process_patblt(s, &os->patblt, present, delta);
1386 					break;
1387 
1388 				case RDP_ORDER_SCREENBLT:
1389 					process_screenblt(s, &os->screenblt, present, delta);
1390 					break;
1391 
1392 				case RDP_ORDER_LINE:
1393 					process_line(s, &os->line, present, delta);
1394 					break;
1395 
1396 				case RDP_ORDER_RECT:
1397 					process_rect(s, &os->rect, present, delta);
1398 					break;
1399 
1400 				case RDP_ORDER_DESKSAVE:
1401 					process_desksave(s, &os->desksave, present, delta);
1402 					break;
1403 
1404 				case RDP_ORDER_MEMBLT:
1405 					process_memblt(s, &os->memblt, present, delta);
1406 					break;
1407 
1408 				case RDP_ORDER_TRIBLT:
1409 					process_triblt(s, &os->triblt, present, delta);
1410 					break;
1411 
1412 				case RDP_ORDER_POLYGON:
1413 					process_polygon(s, &os->polygon, present, delta);
1414 					break;
1415 
1416 				case RDP_ORDER_POLYGON2:
1417 					process_polygon2(s, &os->polygon2, present, delta);
1418 					break;
1419 
1420 				case RDP_ORDER_POLYLINE:
1421 					process_polyline(s, &os->polyline, present, delta);
1422 					break;
1423 
1424 				case RDP_ORDER_ELLIPSE:
1425 					process_ellipse(s, &os->ellipse, present, delta);
1426 					break;
1427 
1428 				case RDP_ORDER_ELLIPSE2:
1429 					process_ellipse2(s, &os->ellipse2, present, delta);
1430 					break;
1431 
1432 				case RDP_ORDER_TEXT2:
1433 					process_text2(s, &os->text2, present, delta);
1434 					break;
1435 
1436 				default:
1437 					logger(Graphics, Warning,
1438 					       "process_orders(), unhandled order type %d",
1439 					       os->order_type);
1440 					return;
1441 			}
1442 
1443 			if (order_flags & RDP_ORDER_BOUNDS)
1444 				ui_reset_clip();
1445 		}
1446 
1447 		processed++;
1448 	}
1449 #if 0
1450 	/* not true when RDP_COMPRESSION is set */
1451 	if (s_tell(s) != g_next_packet)
1452 		logger(Graphics, Error, "process_orders(), %d bytes remaining",
1453 		       (int) (g_next_packet - s_tell(s)));
1454 #endif
1455 
1456 }
1457 
1458 /* Reset order state */
1459 void
reset_order_state(void)1460 reset_order_state(void)
1461 {
1462 	memset(&g_order_state, 0, sizeof(g_order_state));
1463 	g_order_state.order_type = RDP_ORDER_PATBLT;
1464 }
1465