1 /**
2  * FreeRDP: A Remote Desktop Protocol Implementation
3  * Drawing Orders
4  *
5  * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  * Copyright 2016 Armin Novak <armin.novak@thincast.com>
7  * Copyright 2016 Thincast Technologies GmbH
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *     http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #include "window.h"
27 
28 #include <winpr/wtypes.h>
29 #include <winpr/crt.h>
30 
31 #include <freerdp/api.h>
32 #include <freerdp/log.h>
33 #include <freerdp/graphics.h>
34 #include <freerdp/codec/bitmap.h>
35 #include <freerdp/gdi/gdi.h>
36 
37 #include "orders.h"
38 
39 #include "../cache/glyph.h"
40 #include "../cache/bitmap.h"
41 #include "../cache/brush.h"
42 #include "../cache/cache.h"
43 
44 #define TAG FREERDP_TAG("core.orders")
45 
get_primary_drawing_order_field_bytes(UINT32 orderType,BOOL * pValid)46 BYTE get_primary_drawing_order_field_bytes(UINT32 orderType, BOOL* pValid)
47 {
48 	if (pValid)
49 		*pValid = TRUE;
50 	switch (orderType)
51 	{
52 		case 0:
53 			return DSTBLT_ORDER_FIELD_BYTES;
54 		case 1:
55 			return PATBLT_ORDER_FIELD_BYTES;
56 		case 2:
57 			return SCRBLT_ORDER_FIELD_BYTES;
58 		case 3:
59 			return 0;
60 		case 4:
61 			return 0;
62 		case 5:
63 			return 0;
64 		case 6:
65 			return 0;
66 		case 7:
67 			return DRAW_NINE_GRID_ORDER_FIELD_BYTES;
68 		case 8:
69 			return MULTI_DRAW_NINE_GRID_ORDER_FIELD_BYTES;
70 		case 9:
71 			return LINE_TO_ORDER_FIELD_BYTES;
72 		case 10:
73 			return OPAQUE_RECT_ORDER_FIELD_BYTES;
74 		case 11:
75 			return SAVE_BITMAP_ORDER_FIELD_BYTES;
76 		case 12:
77 			return 0;
78 		case 13:
79 			return MEMBLT_ORDER_FIELD_BYTES;
80 		case 14:
81 			return MEM3BLT_ORDER_FIELD_BYTES;
82 		case 15:
83 			return MULTI_DSTBLT_ORDER_FIELD_BYTES;
84 		case 16:
85 			return MULTI_PATBLT_ORDER_FIELD_BYTES;
86 		case 17:
87 			return MULTI_SCRBLT_ORDER_FIELD_BYTES;
88 		case 18:
89 			return MULTI_OPAQUE_RECT_ORDER_FIELD_BYTES;
90 		case 19:
91 			return FAST_INDEX_ORDER_FIELD_BYTES;
92 		case 20:
93 			return POLYGON_SC_ORDER_FIELD_BYTES;
94 		case 21:
95 			return POLYGON_CB_ORDER_FIELD_BYTES;
96 		case 22:
97 			return POLYLINE_ORDER_FIELD_BYTES;
98 		case 23:
99 			return 0;
100 		case 24:
101 			return FAST_GLYPH_ORDER_FIELD_BYTES;
102 		case 25:
103 			return ELLIPSE_SC_ORDER_FIELD_BYTES;
104 		case 26:
105 			return ELLIPSE_CB_ORDER_FIELD_BYTES;
106 		case 27:
107 			return GLYPH_INDEX_ORDER_FIELD_BYTES;
108 		default:
109 			if (pValid)
110 				*pValid = FALSE;
111 			WLog_WARN(TAG, "Invalid orderType 0x%08X received", orderType);
112 			return 0;
113 	}
114 }
115 
get_cbr2_bpp(UINT32 bpp,BOOL * pValid)116 static BYTE get_cbr2_bpp(UINT32 bpp, BOOL* pValid)
117 {
118 	if (pValid)
119 		*pValid = TRUE;
120 	switch (bpp)
121 	{
122 		case 3:
123 			return 8;
124 		case 4:
125 			return 16;
126 		case 5:
127 			return 24;
128 		case 6:
129 			return 32;
130 		default:
131 			WLog_WARN(TAG, "Invalid bpp %" PRIu32, bpp);
132 			if (pValid)
133 				*pValid = FALSE;
134 			return 0;
135 	}
136 }
137 
get_bmf_bpp(UINT32 bmf,BOOL * pValid)138 static BYTE get_bmf_bpp(UINT32 bmf, BOOL* pValid)
139 {
140 	if (pValid)
141 		*pValid = TRUE;
142 	/* Mask out highest bit */
143 	switch (bmf & (~CACHED_BRUSH))
144 	{
145 		case 1:
146 			return 1;
147 		case 3:
148 			return 8;
149 		case 4:
150 			return 16;
151 		case 5:
152 			return 24;
153 		case 6:
154 			return 32;
155 		default:
156 			WLog_WARN(TAG, "Invalid bmf %" PRIu32, bmf);
157 			if (pValid)
158 				*pValid = FALSE;
159 			return 0;
160 	}
161 }
get_bpp_bmf(UINT32 bpp,BOOL * pValid)162 static BYTE get_bpp_bmf(UINT32 bpp, BOOL* pValid)
163 {
164 	if (pValid)
165 		*pValid = TRUE;
166 	switch (bpp)
167 	{
168 		case 1:
169 			return 1;
170 		case 8:
171 			return 3;
172 		case 16:
173 			return 4;
174 		case 24:
175 			return 5;
176 		case 32:
177 			return 6;
178 		default:
179 			WLog_WARN(TAG, "Invalid color depth %" PRIu32, bpp);
180 			if (pValid)
181 				*pValid = FALSE;
182 			return 0;
183 	}
184 }
185 
check_order_activated(wLog * log,rdpSettings * settings,const char * orderName,BOOL condition,const char * extendedMessage)186 static BOOL check_order_activated(wLog* log, rdpSettings* settings, const char* orderName,
187                                   BOOL condition, const char* extendedMessage)
188 {
189 	if (!condition)
190 	{
191 		if (settings->AllowUnanouncedOrdersFromServer)
192 		{
193 			WLog_Print(log, WLOG_WARN,
194 			           "%s - SERVER BUG: The support for this feature was not announced!",
195 			           orderName);
196 			if (extendedMessage)
197 				WLog_Print(log, WLOG_WARN, "%s", extendedMessage);
198 			return TRUE;
199 		}
200 		else
201 		{
202 			WLog_Print(log, WLOG_ERROR,
203 			           "%s - SERVER BUG: The support for this feature was not announced! Use "
204 			           "/relax-order-checks to ignore",
205 			           orderName);
206 			if (extendedMessage)
207 				WLog_Print(log, WLOG_WARN, "%s", extendedMessage);
208 			return FALSE;
209 		}
210 	}
211 
212 	return TRUE;
213 }
214 
check_alt_order_supported(wLog * log,rdpSettings * settings,BYTE orderType,const char * orderName)215 static BOOL check_alt_order_supported(wLog* log, rdpSettings* settings, BYTE orderType,
216                                       const char* orderName)
217 {
218 	const char* extendedMessage = NULL;
219 	BOOL condition = FALSE;
220 
221 	switch (orderType)
222 	{
223 		case ORDER_TYPE_CREATE_OFFSCREEN_BITMAP:
224 		case ORDER_TYPE_SWITCH_SURFACE:
225 			condition = settings->OffscreenSupportLevel != 0;
226 			extendedMessage = "Adding +offscreen-cache might mitigate";
227 			break;
228 
229 		case ORDER_TYPE_CREATE_NINE_GRID_BITMAP:
230 			condition = settings->DrawNineGridEnabled;
231 			break;
232 
233 		case ORDER_TYPE_FRAME_MARKER:
234 			condition = settings->FrameMarkerCommandEnabled;
235 			break;
236 
237 		case ORDER_TYPE_GDIPLUS_FIRST:
238 		case ORDER_TYPE_GDIPLUS_NEXT:
239 		case ORDER_TYPE_GDIPLUS_END:
240 		case ORDER_TYPE_GDIPLUS_CACHE_FIRST:
241 		case ORDER_TYPE_GDIPLUS_CACHE_NEXT:
242 		case ORDER_TYPE_GDIPLUS_CACHE_END:
243 			condition = settings->DrawGdiPlusCacheEnabled;
244 			break;
245 
246 		case ORDER_TYPE_WINDOW:
247 			condition = settings->RemoteWndSupportLevel != WINDOW_LEVEL_NOT_SUPPORTED;
248 			break;
249 
250 		case ORDER_TYPE_STREAM_BITMAP_FIRST:
251 		case ORDER_TYPE_STREAM_BITMAP_NEXT:
252 		case ORDER_TYPE_COMPDESK_FIRST:
253 			condition = TRUE;
254 			break;
255 
256 		default:
257 			WLog_Print(log, WLOG_WARN, "%s - Alternate Secondary Drawing Order UNKNOWN", orderName);
258 			condition = FALSE;
259 			break;
260 	}
261 
262 	return check_order_activated(log, settings, orderName, condition, extendedMessage);
263 }
264 
check_secondary_order_supported(wLog * log,rdpSettings * settings,BYTE orderType,const char * orderName)265 static BOOL check_secondary_order_supported(wLog* log, rdpSettings* settings, BYTE orderType,
266                                             const char* orderName)
267 {
268 	const char* extendedMessage = NULL;
269 	BOOL condition = FALSE;
270 
271 	switch (orderType)
272 	{
273 		case ORDER_TYPE_BITMAP_UNCOMPRESSED:
274 		case ORDER_TYPE_CACHE_BITMAP_COMPRESSED:
275 			condition = settings->BitmapCacheEnabled;
276 			extendedMessage = "Adding +bitmap-cache might mitigate";
277 			break;
278 
279 		case ORDER_TYPE_BITMAP_UNCOMPRESSED_V2:
280 		case ORDER_TYPE_BITMAP_COMPRESSED_V2:
281 			condition = settings->BitmapCacheEnabled;
282 			extendedMessage = "Adding +bitmap-cache might mitigate";
283 			break;
284 
285 		case ORDER_TYPE_BITMAP_COMPRESSED_V3:
286 			condition = settings->BitmapCacheV3Enabled;
287 			extendedMessage = "Adding +bitmap-cache might mitigate";
288 			break;
289 
290 		case ORDER_TYPE_CACHE_COLOR_TABLE:
291 			condition = (settings->OrderSupport[NEG_MEMBLT_INDEX] ||
292 			             settings->OrderSupport[NEG_MEM3BLT_INDEX]);
293 			break;
294 
295 		case ORDER_TYPE_CACHE_GLYPH:
296 		{
297 			switch (settings->GlyphSupportLevel)
298 			{
299 				case GLYPH_SUPPORT_PARTIAL:
300 				case GLYPH_SUPPORT_FULL:
301 				case GLYPH_SUPPORT_ENCODE:
302 					condition = TRUE;
303 					break;
304 
305 				case GLYPH_SUPPORT_NONE:
306 				default:
307 					condition = FALSE;
308 					break;
309 			}
310 		}
311 		break;
312 
313 		case ORDER_TYPE_CACHE_BRUSH:
314 			condition = TRUE;
315 			break;
316 
317 		default:
318 			WLog_Print(log, WLOG_WARN, "SECONDARY ORDER %s not supported", orderName);
319 			break;
320 	}
321 
322 	return check_order_activated(log, settings, orderName, condition, extendedMessage);
323 }
324 
check_primary_order_supported(wLog * log,rdpSettings * settings,UINT32 orderType,const char * orderName)325 static BOOL check_primary_order_supported(wLog* log, rdpSettings* settings, UINT32 orderType,
326                                           const char* orderName)
327 {
328 	const char* extendedMessage = NULL;
329 	BOOL condition = FALSE;
330 
331 	switch (orderType)
332 	{
333 		case ORDER_TYPE_DSTBLT:
334 			condition = settings->OrderSupport[NEG_DSTBLT_INDEX];
335 			break;
336 
337 		case ORDER_TYPE_SCRBLT:
338 			condition = settings->OrderSupport[NEG_SCRBLT_INDEX];
339 			break;
340 
341 		case ORDER_TYPE_DRAW_NINE_GRID:
342 			condition = settings->OrderSupport[NEG_DRAWNINEGRID_INDEX];
343 			break;
344 
345 		case ORDER_TYPE_MULTI_DRAW_NINE_GRID:
346 			condition = settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX];
347 			break;
348 
349 		case ORDER_TYPE_LINE_TO:
350 			condition = settings->OrderSupport[NEG_LINETO_INDEX];
351 			break;
352 
353 		/* [MS-RDPEGDI] 2.2.2.2.1.1.2.5 OpaqueRect (OPAQUERECT_ORDER)
354 		 * suggests that PatBlt and OpaqueRect imply each other. */
355 		case ORDER_TYPE_PATBLT:
356 		case ORDER_TYPE_OPAQUE_RECT:
357 			condition = settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] ||
358 			            settings->OrderSupport[NEG_PATBLT_INDEX];
359 			break;
360 
361 		case ORDER_TYPE_SAVE_BITMAP:
362 			condition = settings->OrderSupport[NEG_SAVEBITMAP_INDEX];
363 			break;
364 
365 		case ORDER_TYPE_MEMBLT:
366 			condition = settings->OrderSupport[NEG_MEMBLT_INDEX];
367 			break;
368 
369 		case ORDER_TYPE_MEM3BLT:
370 			condition = settings->OrderSupport[NEG_MEM3BLT_INDEX];
371 			break;
372 
373 		case ORDER_TYPE_MULTI_DSTBLT:
374 			condition = settings->OrderSupport[NEG_MULTIDSTBLT_INDEX];
375 			break;
376 
377 		case ORDER_TYPE_MULTI_PATBLT:
378 			condition = settings->OrderSupport[NEG_MULTIPATBLT_INDEX];
379 			break;
380 
381 		case ORDER_TYPE_MULTI_SCRBLT:
382 			condition = settings->OrderSupport[NEG_MULTIDSTBLT_INDEX];
383 			break;
384 
385 		case ORDER_TYPE_MULTI_OPAQUE_RECT:
386 			condition = settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX];
387 			break;
388 
389 		case ORDER_TYPE_FAST_INDEX:
390 			condition = settings->OrderSupport[NEG_FAST_INDEX_INDEX];
391 			break;
392 
393 		case ORDER_TYPE_POLYGON_SC:
394 			condition = settings->OrderSupport[NEG_POLYGON_SC_INDEX];
395 			break;
396 
397 		case ORDER_TYPE_POLYGON_CB:
398 			condition = settings->OrderSupport[NEG_POLYGON_CB_INDEX];
399 			break;
400 
401 		case ORDER_TYPE_POLYLINE:
402 			condition = settings->OrderSupport[NEG_POLYLINE_INDEX];
403 			break;
404 
405 		case ORDER_TYPE_FAST_GLYPH:
406 			condition = settings->OrderSupport[NEG_FAST_GLYPH_INDEX];
407 			break;
408 
409 		case ORDER_TYPE_ELLIPSE_SC:
410 			condition = settings->OrderSupport[NEG_ELLIPSE_SC_INDEX];
411 			break;
412 
413 		case ORDER_TYPE_ELLIPSE_CB:
414 			condition = settings->OrderSupport[NEG_ELLIPSE_CB_INDEX];
415 			break;
416 
417 		case ORDER_TYPE_GLYPH_INDEX:
418 			condition = settings->OrderSupport[NEG_GLYPH_INDEX_INDEX];
419 			break;
420 
421 		default:
422 			WLog_Print(log, WLOG_WARN, "%s Primary Drawing Order not supported", orderName);
423 			break;
424 	}
425 
426 	return check_order_activated(log, settings, orderName, condition, extendedMessage);
427 }
428 
primary_order_string(UINT32 orderType)429 static const char* primary_order_string(UINT32 orderType)
430 {
431 	const char* orders[] = { "[0x%02" PRIx8 "] DstBlt",
432 		                     "[0x%02" PRIx8 "] PatBlt",
433 		                     "[0x%02" PRIx8 "] ScrBlt",
434 		                     "[0x%02" PRIx8 "] UNUSED",
435 		                     "[0x%02" PRIx8 "] UNUSED",
436 		                     "[0x%02" PRIx8 "] UNUSED",
437 		                     "[0x%02" PRIx8 "] UNUSED",
438 		                     "[0x%02" PRIx8 "] DrawNineGrid",
439 		                     "[0x%02" PRIx8 "] MultiDrawNineGrid",
440 		                     "[0x%02" PRIx8 "] LineTo",
441 		                     "[0x%02" PRIx8 "] OpaqueRect",
442 		                     "[0x%02" PRIx8 "] SaveBitmap",
443 		                     "[0x%02" PRIx8 "] UNUSED",
444 		                     "[0x%02" PRIx8 "] MemBlt",
445 		                     "[0x%02" PRIx8 "] Mem3Blt",
446 		                     "[0x%02" PRIx8 "] MultiDstBlt",
447 		                     "[0x%02" PRIx8 "] MultiPatBlt",
448 		                     "[0x%02" PRIx8 "] MultiScrBlt",
449 		                     "[0x%02" PRIx8 "] MultiOpaqueRect",
450 		                     "[0x%02" PRIx8 "] FastIndex",
451 		                     "[0x%02" PRIx8 "] PolygonSC",
452 		                     "[0x%02" PRIx8 "] PolygonCB",
453 		                     "[0x%02" PRIx8 "] Polyline",
454 		                     "[0x%02" PRIx8 "] UNUSED",
455 		                     "[0x%02" PRIx8 "] FastGlyph",
456 		                     "[0x%02" PRIx8 "] EllipseSC",
457 		                     "[0x%02" PRIx8 "] EllipseCB",
458 		                     "[0x%02" PRIx8 "] GlyphIndex" };
459 	const char* fmt = "[0x%02" PRIx8 "] UNKNOWN";
460 	static char buffer[64] = { 0 };
461 
462 	if (orderType < ARRAYSIZE(orders))
463 		fmt = orders[orderType];
464 
465 	sprintf_s(buffer, ARRAYSIZE(buffer), fmt, orderType);
466 	return buffer;
467 }
secondary_order_string(UINT32 orderType)468 static const char* secondary_order_string(UINT32 orderType)
469 {
470 	const char* orders[] = { "[0x%02" PRIx8 "] Cache Bitmap",
471 		                     "[0x%02" PRIx8 "] Cache Color Table",
472 		                     "[0x%02" PRIx8 "] Cache Bitmap (Compressed)",
473 		                     "[0x%02" PRIx8 "] Cache Glyph",
474 		                     "[0x%02" PRIx8 "] Cache Bitmap V2",
475 		                     "[0x%02" PRIx8 "] Cache Bitmap V2 (Compressed)",
476 		                     "[0x%02" PRIx8 "] UNUSED",
477 		                     "[0x%02" PRIx8 "] Cache Brush",
478 		                     "[0x%02" PRIx8 "] Cache Bitmap V3" };
479 	const char* fmt = "[0x%02" PRIx8 "] UNKNOWN";
480 	static char buffer[64] = { 0 };
481 
482 	if (orderType < ARRAYSIZE(orders))
483 		fmt = orders[orderType];
484 
485 	sprintf_s(buffer, ARRAYSIZE(buffer), fmt, orderType);
486 	return buffer;
487 }
altsec_order_string(BYTE orderType)488 static const char* altsec_order_string(BYTE orderType)
489 {
490 	const char* orders[] = {
491 		"[0x%02" PRIx8 "] Switch Surface",         "[0x%02" PRIx8 "] Create Offscreen Bitmap",
492 		"[0x%02" PRIx8 "] Stream Bitmap First",    "[0x%02" PRIx8 "] Stream Bitmap Next",
493 		"[0x%02" PRIx8 "] Create NineGrid Bitmap", "[0x%02" PRIx8 "] Draw GDI+ First",
494 		"[0x%02" PRIx8 "] Draw GDI+ Next",         "[0x%02" PRIx8 "] Draw GDI+ End",
495 		"[0x%02" PRIx8 "] Draw GDI+ Cache First",  "[0x%02" PRIx8 "] Draw GDI+ Cache Next",
496 		"[0x%02" PRIx8 "] Draw GDI+ Cache End",    "[0x%02" PRIx8 "] Windowing",
497 		"[0x%02" PRIx8 "] Desktop Composition",    "[0x%02" PRIx8 "] Frame Marker"
498 	};
499 	const char* fmt = "[0x%02" PRIx8 "] UNKNOWN";
500 	static char buffer[64] = { 0 };
501 
502 	if (orderType < ARRAYSIZE(orders))
503 		fmt = orders[orderType];
504 
505 	sprintf_s(buffer, ARRAYSIZE(buffer), fmt, orderType);
506 	return buffer;
507 }
508 
update_read_coord(wStream * s,INT32 * coord,BOOL delta)509 static INLINE BOOL update_read_coord(wStream* s, INT32* coord, BOOL delta)
510 {
511 	INT8 lsi8;
512 	INT16 lsi16;
513 
514 	if (delta)
515 	{
516 		if (Stream_GetRemainingLength(s) < 1)
517 			return FALSE;
518 
519 		Stream_Read_INT8(s, lsi8);
520 		*coord += lsi8;
521 	}
522 	else
523 	{
524 		if (Stream_GetRemainingLength(s) < 2)
525 			return FALSE;
526 
527 		Stream_Read_INT16(s, lsi16);
528 		*coord = lsi16;
529 	}
530 
531 	return TRUE;
532 }
update_write_coord(wStream * s,INT32 coord)533 static INLINE BOOL update_write_coord(wStream* s, INT32 coord)
534 {
535 	Stream_Write_UINT16(s, coord);
536 	return TRUE;
537 }
update_read_color(wStream * s,UINT32 * color)538 static INLINE BOOL update_read_color(wStream* s, UINT32* color)
539 {
540 	BYTE byte;
541 
542 	if (Stream_GetRemainingLength(s) < 3)
543 		return FALSE;
544 
545 	*color = 0;
546 	Stream_Read_UINT8(s, byte);
547 	*color = (UINT32)byte;
548 	Stream_Read_UINT8(s, byte);
549 	*color |= ((UINT32)byte << 8) & 0xFF00;
550 	Stream_Read_UINT8(s, byte);
551 	*color |= ((UINT32)byte << 16) & 0xFF0000;
552 	return TRUE;
553 }
update_write_color(wStream * s,UINT32 color)554 static INLINE BOOL update_write_color(wStream* s, UINT32 color)
555 {
556 	BYTE byte;
557 	byte = (color & 0xFF);
558 	Stream_Write_UINT8(s, byte);
559 	byte = ((color >> 8) & 0xFF);
560 	Stream_Write_UINT8(s, byte);
561 	byte = ((color >> 16) & 0xFF);
562 	Stream_Write_UINT8(s, byte);
563 	return TRUE;
564 }
update_read_colorref(wStream * s,UINT32 * color)565 static INLINE BOOL update_read_colorref(wStream* s, UINT32* color)
566 {
567 	BYTE byte;
568 
569 	if (Stream_GetRemainingLength(s) < 4)
570 		return FALSE;
571 
572 	*color = 0;
573 	Stream_Read_UINT8(s, byte);
574 	*color = byte;
575 	Stream_Read_UINT8(s, byte);
576 	*color |= ((UINT32)byte << 8);
577 	Stream_Read_UINT8(s, byte);
578 	*color |= ((UINT32)byte << 16);
579 	Stream_Seek_UINT8(s);
580 	return TRUE;
581 }
update_read_color_quad(wStream * s,UINT32 * color)582 static INLINE BOOL update_read_color_quad(wStream* s, UINT32* color)
583 {
584 	return update_read_colorref(s, color);
585 }
update_write_color_quad(wStream * s,UINT32 color)586 static INLINE void update_write_color_quad(wStream* s, UINT32 color)
587 {
588 	BYTE byte;
589 	byte = (color >> 16) & 0xFF;
590 	Stream_Write_UINT8(s, byte);
591 	byte = (color >> 8) & 0xFF;
592 	Stream_Write_UINT8(s, byte);
593 	byte = color & 0xFF;
594 	Stream_Write_UINT8(s, byte);
595 }
update_read_2byte_unsigned(wStream * s,UINT32 * value)596 static INLINE BOOL update_read_2byte_unsigned(wStream* s, UINT32* value)
597 {
598 	BYTE byte;
599 
600 	if (Stream_GetRemainingLength(s) < 1)
601 		return FALSE;
602 
603 	Stream_Read_UINT8(s, byte);
604 
605 	if (byte & 0x80)
606 	{
607 		if (Stream_GetRemainingLength(s) < 1)
608 			return FALSE;
609 
610 		*value = (byte & 0x7F) << 8;
611 		Stream_Read_UINT8(s, byte);
612 		*value |= byte;
613 	}
614 	else
615 	{
616 		*value = (byte & 0x7F);
617 	}
618 
619 	return TRUE;
620 }
update_write_2byte_unsigned(wStream * s,UINT32 value)621 static INLINE BOOL update_write_2byte_unsigned(wStream* s, UINT32 value)
622 {
623 	BYTE byte;
624 
625 	if (value > 0x7FFF)
626 		return FALSE;
627 
628 	if (value >= 0x7F)
629 	{
630 		byte = ((value & 0x7F00) >> 8);
631 		Stream_Write_UINT8(s, byte | 0x80);
632 		byte = (value & 0xFF);
633 		Stream_Write_UINT8(s, byte);
634 	}
635 	else
636 	{
637 		byte = (value & 0x7F);
638 		Stream_Write_UINT8(s, byte);
639 	}
640 
641 	return TRUE;
642 }
update_read_2byte_signed(wStream * s,INT32 * value)643 static INLINE BOOL update_read_2byte_signed(wStream* s, INT32* value)
644 {
645 	BYTE byte;
646 	BOOL negative;
647 
648 	if (Stream_GetRemainingLength(s) < 1)
649 		return FALSE;
650 
651 	Stream_Read_UINT8(s, byte);
652 	negative = (byte & 0x40) ? TRUE : FALSE;
653 	*value = (byte & 0x3F);
654 
655 	if (byte & 0x80)
656 	{
657 		if (Stream_GetRemainingLength(s) < 1)
658 			return FALSE;
659 
660 		Stream_Read_UINT8(s, byte);
661 		*value = (*value << 8) | byte;
662 	}
663 
664 	if (negative)
665 		*value *= -1;
666 
667 	return TRUE;
668 }
update_write_2byte_signed(wStream * s,INT32 value)669 static INLINE BOOL update_write_2byte_signed(wStream* s, INT32 value)
670 {
671 	BYTE byte;
672 	BOOL negative = FALSE;
673 
674 	if (value < 0)
675 	{
676 		negative = TRUE;
677 		value *= -1;
678 	}
679 
680 	if (value > 0x3FFF)
681 		return FALSE;
682 
683 	if (value >= 0x3F)
684 	{
685 		byte = ((value & 0x3F00) >> 8);
686 
687 		if (negative)
688 			byte |= 0x40;
689 
690 		Stream_Write_UINT8(s, byte | 0x80);
691 		byte = (value & 0xFF);
692 		Stream_Write_UINT8(s, byte);
693 	}
694 	else
695 	{
696 		byte = (value & 0x3F);
697 
698 		if (negative)
699 			byte |= 0x40;
700 
701 		Stream_Write_UINT8(s, byte);
702 	}
703 
704 	return TRUE;
705 }
update_read_4byte_unsigned(wStream * s,UINT32 * value)706 static INLINE BOOL update_read_4byte_unsigned(wStream* s, UINT32* value)
707 {
708 	BYTE byte;
709 	BYTE count;
710 
711 	if (Stream_GetRemainingLength(s) < 1)
712 		return FALSE;
713 
714 	Stream_Read_UINT8(s, byte);
715 	count = (byte & 0xC0) >> 6;
716 
717 	if (Stream_GetRemainingLength(s) < count)
718 		return FALSE;
719 
720 	switch (count)
721 	{
722 		case 0:
723 			*value = (byte & 0x3F);
724 			break;
725 
726 		case 1:
727 			*value = (byte & 0x3F) << 8;
728 			Stream_Read_UINT8(s, byte);
729 			*value |= byte;
730 			break;
731 
732 		case 2:
733 			*value = (byte & 0x3F) << 16;
734 			Stream_Read_UINT8(s, byte);
735 			*value |= (byte << 8);
736 			Stream_Read_UINT8(s, byte);
737 			*value |= byte;
738 			break;
739 
740 		case 3:
741 			*value = (byte & 0x3F) << 24;
742 			Stream_Read_UINT8(s, byte);
743 			*value |= (byte << 16);
744 			Stream_Read_UINT8(s, byte);
745 			*value |= (byte << 8);
746 			Stream_Read_UINT8(s, byte);
747 			*value |= byte;
748 			break;
749 
750 		default:
751 			break;
752 	}
753 
754 	return TRUE;
755 }
update_write_4byte_unsigned(wStream * s,UINT32 value)756 static INLINE BOOL update_write_4byte_unsigned(wStream* s, UINT32 value)
757 {
758 	BYTE byte;
759 
760 	if (value <= 0x3F)
761 	{
762 		Stream_Write_UINT8(s, value);
763 	}
764 	else if (value <= 0x3FFF)
765 	{
766 		byte = (value >> 8) & 0x3F;
767 		Stream_Write_UINT8(s, byte | 0x40);
768 		byte = (value & 0xFF);
769 		Stream_Write_UINT8(s, byte);
770 	}
771 	else if (value <= 0x3FFFFF)
772 	{
773 		byte = (value >> 16) & 0x3F;
774 		Stream_Write_UINT8(s, byte | 0x80);
775 		byte = (value >> 8) & 0xFF;
776 		Stream_Write_UINT8(s, byte);
777 		byte = (value & 0xFF);
778 		Stream_Write_UINT8(s, byte);
779 	}
780 	else if (value <= 0x3FFFFFFF)
781 	{
782 		byte = (value >> 24) & 0x3F;
783 		Stream_Write_UINT8(s, byte | 0xC0);
784 		byte = (value >> 16) & 0xFF;
785 		Stream_Write_UINT8(s, byte);
786 		byte = (value >> 8) & 0xFF;
787 		Stream_Write_UINT8(s, byte);
788 		byte = (value & 0xFF);
789 		Stream_Write_UINT8(s, byte);
790 	}
791 	else
792 		return FALSE;
793 
794 	return TRUE;
795 }
update_read_delta(wStream * s,INT32 * value)796 static INLINE BOOL update_read_delta(wStream* s, INT32* value)
797 {
798 	BYTE byte;
799 
800 	if (Stream_GetRemainingLength(s) < 1)
801 	{
802 		WLog_ERR(TAG, "Stream_GetRemainingLength(s) < 1");
803 		return FALSE;
804 	}
805 
806 	Stream_Read_UINT8(s, byte);
807 
808 	if (byte & 0x40)
809 		*value = (byte | ~0x3F);
810 	else
811 		*value = (byte & 0x3F);
812 
813 	if (byte & 0x80)
814 	{
815 		if (Stream_GetRemainingLength(s) < 1)
816 		{
817 			WLog_ERR(TAG, "Stream_GetRemainingLength(s) < 1");
818 			return FALSE;
819 		}
820 
821 		Stream_Read_UINT8(s, byte);
822 		*value = (*value << 8) | byte;
823 	}
824 
825 	return TRUE;
826 }
827 #if 0
828 static INLINE void update_read_glyph_delta(wStream* s, UINT16* value)
829 {
830 	BYTE byte;
831 	Stream_Read_UINT8(s, byte);
832 
833 	if (byte == 0x80)
834 		Stream_Read_UINT16(s, *value);
835 	else
836 		*value = (byte & 0x3F);
837 }
838 static INLINE void update_seek_glyph_delta(wStream* s)
839 {
840 	BYTE byte;
841 	Stream_Read_UINT8(s, byte);
842 
843 	if (byte & 0x80)
844 		Stream_Seek_UINT8(s);
845 }
846 #endif
update_read_brush(wStream * s,rdpBrush * brush,BYTE fieldFlags)847 static INLINE BOOL update_read_brush(wStream* s, rdpBrush* brush, BYTE fieldFlags)
848 {
849 	if (fieldFlags & ORDER_FIELD_01)
850 	{
851 		if (Stream_GetRemainingLength(s) < 1)
852 			return FALSE;
853 
854 		Stream_Read_UINT8(s, brush->x);
855 	}
856 
857 	if (fieldFlags & ORDER_FIELD_02)
858 	{
859 		if (Stream_GetRemainingLength(s) < 1)
860 			return FALSE;
861 
862 		Stream_Read_UINT8(s, brush->y);
863 	}
864 
865 	if (fieldFlags & ORDER_FIELD_03)
866 	{
867 		if (Stream_GetRemainingLength(s) < 1)
868 			return FALSE;
869 
870 		Stream_Read_UINT8(s, brush->style);
871 	}
872 
873 	if (fieldFlags & ORDER_FIELD_04)
874 	{
875 		if (Stream_GetRemainingLength(s) < 1)
876 			return FALSE;
877 
878 		Stream_Read_UINT8(s, brush->hatch);
879 	}
880 
881 	if (brush->style & CACHED_BRUSH)
882 	{
883 		BOOL rc;
884 		brush->index = brush->hatch;
885 		brush->bpp = get_bmf_bpp(brush->style, &rc);
886 		if (!rc)
887 			return FALSE;
888 		if (brush->bpp == 0)
889 			brush->bpp = 1;
890 	}
891 
892 	if (fieldFlags & ORDER_FIELD_05)
893 	{
894 		if (Stream_GetRemainingLength(s) < 7)
895 			return FALSE;
896 
897 		brush->data = (BYTE*)brush->p8x8;
898 		Stream_Read_UINT8(s, brush->data[7]);
899 		Stream_Read_UINT8(s, brush->data[6]);
900 		Stream_Read_UINT8(s, brush->data[5]);
901 		Stream_Read_UINT8(s, brush->data[4]);
902 		Stream_Read_UINT8(s, brush->data[3]);
903 		Stream_Read_UINT8(s, brush->data[2]);
904 		Stream_Read_UINT8(s, brush->data[1]);
905 		brush->data[0] = brush->hatch;
906 	}
907 
908 	return TRUE;
909 }
update_write_brush(wStream * s,rdpBrush * brush,BYTE fieldFlags)910 static INLINE BOOL update_write_brush(wStream* s, rdpBrush* brush, BYTE fieldFlags)
911 {
912 	if (fieldFlags & ORDER_FIELD_01)
913 	{
914 		Stream_Write_UINT8(s, brush->x);
915 	}
916 
917 	if (fieldFlags & ORDER_FIELD_02)
918 	{
919 		Stream_Write_UINT8(s, brush->y);
920 	}
921 
922 	if (fieldFlags & ORDER_FIELD_03)
923 	{
924 		Stream_Write_UINT8(s, brush->style);
925 	}
926 
927 	if (brush->style & CACHED_BRUSH)
928 	{
929 		BOOL rc;
930 		brush->hatch = brush->index;
931 		brush->bpp = get_bmf_bpp(brush->style, &rc);
932 		if (!rc)
933 			return FALSE;
934 		if (brush->bpp == 0)
935 			brush->bpp = 1;
936 	}
937 
938 	if (fieldFlags & ORDER_FIELD_04)
939 	{
940 		Stream_Write_UINT8(s, brush->hatch);
941 	}
942 
943 	if (fieldFlags & ORDER_FIELD_05)
944 	{
945 		brush->data = (BYTE*)brush->p8x8;
946 		Stream_Write_UINT8(s, brush->data[7]);
947 		Stream_Write_UINT8(s, brush->data[6]);
948 		Stream_Write_UINT8(s, brush->data[5]);
949 		Stream_Write_UINT8(s, brush->data[4]);
950 		Stream_Write_UINT8(s, brush->data[3]);
951 		Stream_Write_UINT8(s, brush->data[2]);
952 		Stream_Write_UINT8(s, brush->data[1]);
953 		brush->data[0] = brush->hatch;
954 	}
955 
956 	return TRUE;
957 }
update_read_delta_rects(wStream * s,DELTA_RECT * rectangles,UINT32 * nr)958 static INLINE BOOL update_read_delta_rects(wStream* s, DELTA_RECT* rectangles, UINT32* nr)
959 {
960 	UINT32 number = *nr;
961 	UINT32 i;
962 	BYTE flags = 0;
963 	BYTE* zeroBits;
964 	UINT32 zeroBitsSize;
965 
966 	if (number > 45)
967 	{
968 		WLog_WARN(TAG, "Invalid number of delta rectangles %" PRIu32, number);
969 		return FALSE;
970 	}
971 
972 	zeroBitsSize = ((number + 1) / 2);
973 
974 	if (Stream_GetRemainingLength(s) < zeroBitsSize)
975 		return FALSE;
976 
977 	Stream_GetPointer(s, zeroBits);
978 	Stream_Seek(s, zeroBitsSize);
979 	ZeroMemory(rectangles, sizeof(DELTA_RECT) * number);
980 
981 	for (i = 0; i < number; i++)
982 	{
983 		if (i % 2 == 0)
984 			flags = zeroBits[i / 2];
985 
986 		if ((~flags & 0x80) && !update_read_delta(s, &rectangles[i].left))
987 			return FALSE;
988 
989 		if ((~flags & 0x40) && !update_read_delta(s, &rectangles[i].top))
990 			return FALSE;
991 
992 		if (~flags & 0x20)
993 		{
994 			if (!update_read_delta(s, &rectangles[i].width))
995 				return FALSE;
996 		}
997 		else if (i > 0)
998 			rectangles[i].width = rectangles[i - 1].width;
999 		else
1000 			rectangles[i].width = 0;
1001 
1002 		if (~flags & 0x10)
1003 		{
1004 			if (!update_read_delta(s, &rectangles[i].height))
1005 				return FALSE;
1006 		}
1007 		else if (i > 0)
1008 			rectangles[i].height = rectangles[i - 1].height;
1009 		else
1010 			rectangles[i].height = 0;
1011 
1012 		if (i > 0)
1013 		{
1014 			rectangles[i].left += rectangles[i - 1].left;
1015 			rectangles[i].top += rectangles[i - 1].top;
1016 		}
1017 
1018 		flags <<= 4;
1019 	}
1020 
1021 	return TRUE;
1022 }
update_read_delta_points(wStream * s,DELTA_POINT * points,int number,INT16 x,INT16 y)1023 static INLINE BOOL update_read_delta_points(wStream* s, DELTA_POINT* points, int number, INT16 x,
1024                                             INT16 y)
1025 {
1026 	int i;
1027 	BYTE flags = 0;
1028 	BYTE* zeroBits;
1029 	UINT32 zeroBitsSize;
1030 	zeroBitsSize = ((number + 3) / 4);
1031 
1032 	if (Stream_GetRemainingLength(s) < zeroBitsSize)
1033 	{
1034 		WLog_ERR(TAG, "Stream_GetRemainingLength(s) < %" PRIu32 "", zeroBitsSize);
1035 		return FALSE;
1036 	}
1037 
1038 	Stream_GetPointer(s, zeroBits);
1039 	Stream_Seek(s, zeroBitsSize);
1040 	ZeroMemory(points, sizeof(DELTA_POINT) * number);
1041 
1042 	for (i = 0; i < number; i++)
1043 	{
1044 		if (i % 4 == 0)
1045 			flags = zeroBits[i / 4];
1046 
1047 		if ((~flags & 0x80) && !update_read_delta(s, &points[i].x))
1048 		{
1049 			WLog_ERR(TAG, "update_read_delta(x) failed");
1050 			return FALSE;
1051 		}
1052 
1053 		if ((~flags & 0x40) && !update_read_delta(s, &points[i].y))
1054 		{
1055 			WLog_ERR(TAG, "update_read_delta(y) failed");
1056 			return FALSE;
1057 		}
1058 
1059 		flags <<= 2;
1060 	}
1061 
1062 	return TRUE;
1063 }
1064 
order_field_flag_is_set(const ORDER_INFO * orderInfo,BYTE number)1065 static BOOL order_field_flag_is_set(const ORDER_INFO* orderInfo, BYTE number)
1066 {
1067 	const UINT32 mask = (1UL << ((UINT32)number - 1UL));
1068 	const BOOL set = (orderInfo->fieldFlags & mask) != 0;
1069 	return set;
1070 }
1071 
read_order_field_byte(const ORDER_INFO * orderInfo,wStream * s,BYTE number,UINT32 * target,BOOL optional)1072 static INLINE BOOL read_order_field_byte(const ORDER_INFO* orderInfo, wStream* s, BYTE number,
1073                                          UINT32* target, BOOL optional)
1074 {
1075 	if (!order_field_flag_is_set(orderInfo, number))
1076 		return TRUE;
1077 	if (Stream_GetRemainingLength(s) < 1)
1078 		return FALSE;
1079 	Stream_Read_UINT8(s, *target);
1080 	return TRUE;
1081 }
1082 
read_order_field_2bytes(const ORDER_INFO * orderInfo,wStream * s,BYTE number,UINT32 * target1,UINT32 * target2,BOOL optional)1083 static INLINE BOOL read_order_field_2bytes(const ORDER_INFO* orderInfo, wStream* s, BYTE number,
1084                                            UINT32* target1, UINT32* target2, BOOL optional)
1085 {
1086 	if (!order_field_flag_is_set(orderInfo, number))
1087 		return TRUE;
1088 	if (Stream_GetRemainingLength(s) < 2)
1089 		return FALSE;
1090 	Stream_Read_UINT8(s, *target1);
1091 	Stream_Read_UINT8(s, *target2);
1092 	return TRUE;
1093 }
1094 
read_order_field_uint16(const ORDER_INFO * orderInfo,wStream * s,BYTE number,UINT32 * target,BOOL optional)1095 static INLINE BOOL read_order_field_uint16(const ORDER_INFO* orderInfo, wStream* s, BYTE number,
1096                                            UINT32* target, BOOL optional)
1097 {
1098 	if (!order_field_flag_is_set(orderInfo, number))
1099 		return TRUE;
1100 
1101 	if (Stream_GetRemainingLength(s) < 2)
1102 		return FALSE;
1103 
1104 	Stream_Read_UINT16(s, *target);
1105 	return TRUE;
1106 }
1107 
read_order_field_int16(const ORDER_INFO * orderInfo,wStream * s,BYTE number,INT32 * target,BOOL optional)1108 static INLINE BOOL read_order_field_int16(const ORDER_INFO* orderInfo, wStream* s, BYTE number,
1109                                           INT32* target, BOOL optional)
1110 {
1111 	if (!order_field_flag_is_set(orderInfo, number))
1112 		return TRUE;
1113 
1114 	if (Stream_GetRemainingLength(s) < 2)
1115 		return FALSE;
1116 
1117 	Stream_Read_INT16(s, *target);
1118 	return TRUE;
1119 }
1120 
read_order_field_uint32(const ORDER_INFO * orderInfo,wStream * s,BYTE number,UINT32 * target,BOOL optional)1121 static INLINE BOOL read_order_field_uint32(const ORDER_INFO* orderInfo, wStream* s, BYTE number,
1122                                            UINT32* target, BOOL optional)
1123 {
1124 	if (!order_field_flag_is_set(orderInfo, number))
1125 		return TRUE;
1126 	if (Stream_GetRemainingLength(s) < 4)
1127 		return FALSE;
1128 
1129 	Stream_Read_UINT32(s, *target);
1130 	return TRUE;
1131 }
1132 
read_order_field_coord(const ORDER_INFO * orderInfo,wStream * s,UINT32 NO,INT32 * TARGET,BOOL optional)1133 static INLINE BOOL read_order_field_coord(const ORDER_INFO* orderInfo, wStream* s, UINT32 NO,
1134                                           INT32* TARGET, BOOL optional)
1135 {
1136 	if (!TARGET || !orderInfo)
1137 		return FALSE;
1138 	if (!order_field_flag_is_set(orderInfo, NO))
1139 		return TRUE;
1140 
1141 	return update_read_coord(s, TARGET, orderInfo->deltaCoordinates);
1142 }
1143 
read_order_field_color(const ORDER_INFO * orderInfo,wStream * s,UINT32 NO,UINT32 * TARGET,BOOL optional)1144 static INLINE BOOL read_order_field_color(const ORDER_INFO* orderInfo, wStream* s, UINT32 NO,
1145                                           UINT32* TARGET, BOOL optional)
1146 {
1147 	if (!TARGET || !orderInfo)
1148 		return FALSE;
1149 	if (!order_field_flag_is_set(orderInfo, NO))
1150 		return TRUE;
1151 
1152 	if (!update_read_color(s, TARGET))
1153 		return FALSE;
1154 
1155 	return TRUE;
1156 }
FIELD_SKIP_BUFFER16(wStream * s,UINT32 TARGET_LEN)1157 static INLINE BOOL FIELD_SKIP_BUFFER16(wStream* s, UINT32 TARGET_LEN)
1158 {
1159 	if (Stream_GetRemainingLength(s) < 2)
1160 		return FALSE;
1161 
1162 	Stream_Read_UINT16(s, TARGET_LEN);
1163 
1164 	if (!Stream_SafeSeek(s, TARGET_LEN))
1165 	{
1166 		WLog_ERR(TAG, "error skipping %" PRIu32 " bytes", TARGET_LEN);
1167 		return FALSE;
1168 	}
1169 
1170 	return TRUE;
1171 }
1172 /* Primary Drawing Orders */
update_read_dstblt_order(wStream * s,const ORDER_INFO * orderInfo,DSTBLT_ORDER * dstblt)1173 static BOOL update_read_dstblt_order(wStream* s, const ORDER_INFO* orderInfo, DSTBLT_ORDER* dstblt)
1174 {
1175 	if (read_order_field_coord(orderInfo, s, 1, &dstblt->nLeftRect, FALSE) &&
1176 	    read_order_field_coord(orderInfo, s, 2, &dstblt->nTopRect, FALSE) &&
1177 	    read_order_field_coord(orderInfo, s, 3, &dstblt->nWidth, FALSE) &&
1178 	    read_order_field_coord(orderInfo, s, 4, &dstblt->nHeight, FALSE) &&
1179 	    read_order_field_byte(orderInfo, s, 5, &dstblt->bRop, TRUE))
1180 		return TRUE;
1181 	return FALSE;
1182 }
update_approximate_dstblt_order(ORDER_INFO * orderInfo,const DSTBLT_ORDER * dstblt)1183 int update_approximate_dstblt_order(ORDER_INFO* orderInfo, const DSTBLT_ORDER* dstblt)
1184 {
1185 	return 32;
1186 }
update_write_dstblt_order(wStream * s,ORDER_INFO * orderInfo,const DSTBLT_ORDER * dstblt)1187 BOOL update_write_dstblt_order(wStream* s, ORDER_INFO* orderInfo, const DSTBLT_ORDER* dstblt)
1188 {
1189 	if (!Stream_EnsureRemainingCapacity(s, update_approximate_dstblt_order(orderInfo, dstblt)))
1190 		return FALSE;
1191 
1192 	orderInfo->fieldFlags = 0;
1193 	orderInfo->fieldFlags |= ORDER_FIELD_01;
1194 	update_write_coord(s, dstblt->nLeftRect);
1195 	orderInfo->fieldFlags |= ORDER_FIELD_02;
1196 	update_write_coord(s, dstblt->nTopRect);
1197 	orderInfo->fieldFlags |= ORDER_FIELD_03;
1198 	update_write_coord(s, dstblt->nWidth);
1199 	orderInfo->fieldFlags |= ORDER_FIELD_04;
1200 	update_write_coord(s, dstblt->nHeight);
1201 	orderInfo->fieldFlags |= ORDER_FIELD_05;
1202 	Stream_Write_UINT8(s, dstblt->bRop);
1203 	return TRUE;
1204 }
update_read_patblt_order(wStream * s,const ORDER_INFO * orderInfo,PATBLT_ORDER * patblt)1205 static BOOL update_read_patblt_order(wStream* s, const ORDER_INFO* orderInfo, PATBLT_ORDER* patblt)
1206 {
1207 	if (read_order_field_coord(orderInfo, s, 1, &patblt->nLeftRect, FALSE) &&
1208 	    read_order_field_coord(orderInfo, s, 2, &patblt->nTopRect, FALSE) &&
1209 	    read_order_field_coord(orderInfo, s, 3, &patblt->nWidth, FALSE) &&
1210 	    read_order_field_coord(orderInfo, s, 4, &patblt->nHeight, FALSE) &&
1211 	    read_order_field_byte(orderInfo, s, 5, &patblt->bRop, TRUE) &&
1212 	    read_order_field_color(orderInfo, s, 6, &patblt->backColor, TRUE) &&
1213 	    read_order_field_color(orderInfo, s, 7, &patblt->foreColor, TRUE) &&
1214 	    update_read_brush(s, &patblt->brush, orderInfo->fieldFlags >> 7))
1215 		return TRUE;
1216 	return FALSE;
1217 }
update_approximate_patblt_order(ORDER_INFO * orderInfo,PATBLT_ORDER * patblt)1218 int update_approximate_patblt_order(ORDER_INFO* orderInfo, PATBLT_ORDER* patblt)
1219 {
1220 	return 32;
1221 }
update_write_patblt_order(wStream * s,ORDER_INFO * orderInfo,PATBLT_ORDER * patblt)1222 BOOL update_write_patblt_order(wStream* s, ORDER_INFO* orderInfo, PATBLT_ORDER* patblt)
1223 {
1224 	if (!Stream_EnsureRemainingCapacity(s, update_approximate_patblt_order(orderInfo, patblt)))
1225 		return FALSE;
1226 
1227 	orderInfo->fieldFlags = 0;
1228 	orderInfo->fieldFlags |= ORDER_FIELD_01;
1229 	update_write_coord(s, patblt->nLeftRect);
1230 	orderInfo->fieldFlags |= ORDER_FIELD_02;
1231 	update_write_coord(s, patblt->nTopRect);
1232 	orderInfo->fieldFlags |= ORDER_FIELD_03;
1233 	update_write_coord(s, patblt->nWidth);
1234 	orderInfo->fieldFlags |= ORDER_FIELD_04;
1235 	update_write_coord(s, patblt->nHeight);
1236 	orderInfo->fieldFlags |= ORDER_FIELD_05;
1237 	Stream_Write_UINT8(s, patblt->bRop);
1238 	orderInfo->fieldFlags |= ORDER_FIELD_06;
1239 	update_write_color(s, patblt->backColor);
1240 	orderInfo->fieldFlags |= ORDER_FIELD_07;
1241 	update_write_color(s, patblt->foreColor);
1242 	orderInfo->fieldFlags |= ORDER_FIELD_08;
1243 	orderInfo->fieldFlags |= ORDER_FIELD_09;
1244 	orderInfo->fieldFlags |= ORDER_FIELD_10;
1245 	orderInfo->fieldFlags |= ORDER_FIELD_11;
1246 	orderInfo->fieldFlags |= ORDER_FIELD_12;
1247 	update_write_brush(s, &patblt->brush, orderInfo->fieldFlags >> 7);
1248 	return TRUE;
1249 }
update_read_scrblt_order(wStream * s,const ORDER_INFO * orderInfo,SCRBLT_ORDER * scrblt)1250 static BOOL update_read_scrblt_order(wStream* s, const ORDER_INFO* orderInfo, SCRBLT_ORDER* scrblt)
1251 {
1252 	if (read_order_field_coord(orderInfo, s, 1, &scrblt->nLeftRect, FALSE) &&
1253 	    read_order_field_coord(orderInfo, s, 2, &scrblt->nTopRect, FALSE) &&
1254 	    read_order_field_coord(orderInfo, s, 3, &scrblt->nWidth, FALSE) &&
1255 	    read_order_field_coord(orderInfo, s, 4, &scrblt->nHeight, FALSE) &&
1256 	    read_order_field_byte(orderInfo, s, 5, &scrblt->bRop, TRUE) &&
1257 	    read_order_field_coord(orderInfo, s, 6, &scrblt->nXSrc, FALSE) &&
1258 	    read_order_field_coord(orderInfo, s, 7, &scrblt->nYSrc, FALSE))
1259 		return TRUE;
1260 	return FALSE;
1261 }
update_approximate_scrblt_order(ORDER_INFO * orderInfo,const SCRBLT_ORDER * scrblt)1262 int update_approximate_scrblt_order(ORDER_INFO* orderInfo, const SCRBLT_ORDER* scrblt)
1263 {
1264 	return 32;
1265 }
update_write_scrblt_order(wStream * s,ORDER_INFO * orderInfo,const SCRBLT_ORDER * scrblt)1266 BOOL update_write_scrblt_order(wStream* s, ORDER_INFO* orderInfo, const SCRBLT_ORDER* scrblt)
1267 {
1268 	if (!Stream_EnsureRemainingCapacity(s, update_approximate_scrblt_order(orderInfo, scrblt)))
1269 		return FALSE;
1270 
1271 	orderInfo->fieldFlags = 0;
1272 	orderInfo->fieldFlags |= ORDER_FIELD_01;
1273 	update_write_coord(s, scrblt->nLeftRect);
1274 	orderInfo->fieldFlags |= ORDER_FIELD_02;
1275 	update_write_coord(s, scrblt->nTopRect);
1276 	orderInfo->fieldFlags |= ORDER_FIELD_03;
1277 	update_write_coord(s, scrblt->nWidth);
1278 	orderInfo->fieldFlags |= ORDER_FIELD_04;
1279 	update_write_coord(s, scrblt->nHeight);
1280 	orderInfo->fieldFlags |= ORDER_FIELD_05;
1281 	Stream_Write_UINT8(s, scrblt->bRop);
1282 	orderInfo->fieldFlags |= ORDER_FIELD_06;
1283 	update_write_coord(s, scrblt->nXSrc);
1284 	orderInfo->fieldFlags |= ORDER_FIELD_07;
1285 	update_write_coord(s, scrblt->nYSrc);
1286 	return TRUE;
1287 }
update_read_opaque_rect_order(wStream * s,const ORDER_INFO * orderInfo,OPAQUE_RECT_ORDER * opaque_rect)1288 static BOOL update_read_opaque_rect_order(wStream* s, const ORDER_INFO* orderInfo,
1289                                           OPAQUE_RECT_ORDER* opaque_rect)
1290 {
1291 	BYTE byte;
1292 	if (!read_order_field_coord(orderInfo, s, 1, &opaque_rect->nLeftRect, FALSE) ||
1293 	    !read_order_field_coord(orderInfo, s, 2, &opaque_rect->nTopRect, FALSE) ||
1294 	    !read_order_field_coord(orderInfo, s, 3, &opaque_rect->nWidth, FALSE) ||
1295 	    !read_order_field_coord(orderInfo, s, 4, &opaque_rect->nHeight, FALSE))
1296 		return FALSE;
1297 
1298 	if ((orderInfo->fieldFlags & ORDER_FIELD_05) != 0)
1299 	{
1300 		if (Stream_GetRemainingLength(s) < 1)
1301 			return FALSE;
1302 
1303 		Stream_Read_UINT8(s, byte);
1304 		opaque_rect->color = (opaque_rect->color & 0x00FFFF00) | ((UINT32)byte);
1305 	}
1306 
1307 	if ((orderInfo->fieldFlags & ORDER_FIELD_06) != 0)
1308 	{
1309 		if (Stream_GetRemainingLength(s) < 1)
1310 			return FALSE;
1311 
1312 		Stream_Read_UINT8(s, byte);
1313 		opaque_rect->color = (opaque_rect->color & 0x00FF00FF) | ((UINT32)byte << 8);
1314 	}
1315 
1316 	if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0)
1317 	{
1318 		if (Stream_GetRemainingLength(s) < 1)
1319 			return FALSE;
1320 
1321 		Stream_Read_UINT8(s, byte);
1322 		opaque_rect->color = (opaque_rect->color & 0x0000FFFF) | ((UINT32)byte << 16);
1323 	}
1324 
1325 	return TRUE;
1326 }
update_approximate_opaque_rect_order(ORDER_INFO * orderInfo,const OPAQUE_RECT_ORDER * opaque_rect)1327 int update_approximate_opaque_rect_order(ORDER_INFO* orderInfo,
1328                                          const OPAQUE_RECT_ORDER* opaque_rect)
1329 {
1330 	return 32;
1331 }
update_write_opaque_rect_order(wStream * s,ORDER_INFO * orderInfo,const OPAQUE_RECT_ORDER * opaque_rect)1332 BOOL update_write_opaque_rect_order(wStream* s, ORDER_INFO* orderInfo,
1333                                     const OPAQUE_RECT_ORDER* opaque_rect)
1334 {
1335 	BYTE byte;
1336 	int inf = update_approximate_opaque_rect_order(orderInfo, opaque_rect);
1337 
1338 	if (!Stream_EnsureRemainingCapacity(s, inf))
1339 		return FALSE;
1340 
1341 	// TODO: Color format conversion
1342 	orderInfo->fieldFlags = 0;
1343 	orderInfo->fieldFlags |= ORDER_FIELD_01;
1344 	update_write_coord(s, opaque_rect->nLeftRect);
1345 	orderInfo->fieldFlags |= ORDER_FIELD_02;
1346 	update_write_coord(s, opaque_rect->nTopRect);
1347 	orderInfo->fieldFlags |= ORDER_FIELD_03;
1348 	update_write_coord(s, opaque_rect->nWidth);
1349 	orderInfo->fieldFlags |= ORDER_FIELD_04;
1350 	update_write_coord(s, opaque_rect->nHeight);
1351 	orderInfo->fieldFlags |= ORDER_FIELD_05;
1352 	byte = opaque_rect->color & 0x000000FF;
1353 	Stream_Write_UINT8(s, byte);
1354 	orderInfo->fieldFlags |= ORDER_FIELD_06;
1355 	byte = (opaque_rect->color & 0x0000FF00) >> 8;
1356 	Stream_Write_UINT8(s, byte);
1357 	orderInfo->fieldFlags |= ORDER_FIELD_07;
1358 	byte = (opaque_rect->color & 0x00FF0000) >> 16;
1359 	Stream_Write_UINT8(s, byte);
1360 	return TRUE;
1361 }
update_read_draw_nine_grid_order(wStream * s,const ORDER_INFO * orderInfo,DRAW_NINE_GRID_ORDER * draw_nine_grid)1362 static BOOL update_read_draw_nine_grid_order(wStream* s, const ORDER_INFO* orderInfo,
1363                                              DRAW_NINE_GRID_ORDER* draw_nine_grid)
1364 {
1365 	if (read_order_field_coord(orderInfo, s, 1, &draw_nine_grid->srcLeft, FALSE) &&
1366 	    read_order_field_coord(orderInfo, s, 2, &draw_nine_grid->srcTop, FALSE) &&
1367 	    read_order_field_coord(orderInfo, s, 3, &draw_nine_grid->srcRight, FALSE) &&
1368 	    read_order_field_coord(orderInfo, s, 4, &draw_nine_grid->srcBottom, FALSE) &&
1369 	    read_order_field_uint16(orderInfo, s, 5, &draw_nine_grid->bitmapId, FALSE))
1370 		return TRUE;
1371 	return FALSE;
1372 }
update_read_multi_dstblt_order(wStream * s,const ORDER_INFO * orderInfo,MULTI_DSTBLT_ORDER * multi_dstblt)1373 static BOOL update_read_multi_dstblt_order(wStream* s, const ORDER_INFO* orderInfo,
1374                                            MULTI_DSTBLT_ORDER* multi_dstblt)
1375 {
1376 	if (!read_order_field_coord(orderInfo, s, 1, &multi_dstblt->nLeftRect, FALSE) ||
1377 	    !read_order_field_coord(orderInfo, s, 2, &multi_dstblt->nTopRect, FALSE) ||
1378 	    !read_order_field_coord(orderInfo, s, 3, &multi_dstblt->nWidth, FALSE) ||
1379 	    !read_order_field_coord(orderInfo, s, 4, &multi_dstblt->nHeight, FALSE) ||
1380 	    !read_order_field_byte(orderInfo, s, 5, &multi_dstblt->bRop, TRUE) ||
1381 	    !read_order_field_byte(orderInfo, s, 6, &multi_dstblt->numRectangles, TRUE))
1382 		return FALSE;
1383 
1384 	if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0)
1385 	{
1386 		if (Stream_GetRemainingLength(s) < 2)
1387 			return FALSE;
1388 
1389 		Stream_Read_UINT16(s, multi_dstblt->cbData);
1390 		return update_read_delta_rects(s, multi_dstblt->rectangles, &multi_dstblt->numRectangles);
1391 	}
1392 
1393 	return TRUE;
1394 }
update_read_multi_patblt_order(wStream * s,const ORDER_INFO * orderInfo,MULTI_PATBLT_ORDER * multi_patblt)1395 static BOOL update_read_multi_patblt_order(wStream* s, const ORDER_INFO* orderInfo,
1396                                            MULTI_PATBLT_ORDER* multi_patblt)
1397 {
1398 	if (!read_order_field_coord(orderInfo, s, 1, &multi_patblt->nLeftRect, FALSE) ||
1399 	    !read_order_field_coord(orderInfo, s, 2, &multi_patblt->nTopRect, FALSE) ||
1400 	    !read_order_field_coord(orderInfo, s, 3, &multi_patblt->nWidth, FALSE) ||
1401 	    !read_order_field_coord(orderInfo, s, 4, &multi_patblt->nHeight, FALSE) ||
1402 	    !read_order_field_byte(orderInfo, s, 5, &multi_patblt->bRop, TRUE) ||
1403 	    !read_order_field_color(orderInfo, s, 6, &multi_patblt->backColor, TRUE) ||
1404 	    !read_order_field_color(orderInfo, s, 7, &multi_patblt->foreColor, TRUE))
1405 		return FALSE;
1406 
1407 	if (!update_read_brush(s, &multi_patblt->brush, orderInfo->fieldFlags >> 7))
1408 		return FALSE;
1409 
1410 	if (!read_order_field_byte(orderInfo, s, 13, &multi_patblt->numRectangles, TRUE))
1411 		return FALSE;
1412 
1413 	if ((orderInfo->fieldFlags & ORDER_FIELD_14) != 0)
1414 	{
1415 		if (Stream_GetRemainingLength(s) < 2)
1416 			return FALSE;
1417 
1418 		Stream_Read_UINT16(s, multi_patblt->cbData);
1419 
1420 		if (!update_read_delta_rects(s, multi_patblt->rectangles, &multi_patblt->numRectangles))
1421 			return FALSE;
1422 	}
1423 
1424 	return TRUE;
1425 }
update_read_multi_scrblt_order(wStream * s,const ORDER_INFO * orderInfo,MULTI_SCRBLT_ORDER * multi_scrblt)1426 static BOOL update_read_multi_scrblt_order(wStream* s, const ORDER_INFO* orderInfo,
1427                                            MULTI_SCRBLT_ORDER* multi_scrblt)
1428 {
1429 	if (!read_order_field_coord(orderInfo, s, 1, &multi_scrblt->nLeftRect, FALSE) ||
1430 	    !read_order_field_coord(orderInfo, s, 2, &multi_scrblt->nTopRect, FALSE) ||
1431 	    !read_order_field_coord(orderInfo, s, 3, &multi_scrblt->nWidth, FALSE) ||
1432 	    !read_order_field_coord(orderInfo, s, 4, &multi_scrblt->nHeight, FALSE) ||
1433 	    !read_order_field_byte(orderInfo, s, 5, &multi_scrblt->bRop, TRUE) ||
1434 	    !read_order_field_coord(orderInfo, s, 6, &multi_scrblt->nXSrc, FALSE) ||
1435 	    !read_order_field_coord(orderInfo, s, 7, &multi_scrblt->nYSrc, FALSE) ||
1436 	    !read_order_field_byte(orderInfo, s, 8, &multi_scrblt->numRectangles, TRUE))
1437 		return FALSE;
1438 
1439 	if ((orderInfo->fieldFlags & ORDER_FIELD_09) != 0)
1440 	{
1441 		if (Stream_GetRemainingLength(s) < 2)
1442 			return FALSE;
1443 
1444 		Stream_Read_UINT16(s, multi_scrblt->cbData);
1445 		return update_read_delta_rects(s, multi_scrblt->rectangles, &multi_scrblt->numRectangles);
1446 	}
1447 
1448 	return TRUE;
1449 }
update_read_multi_opaque_rect_order(wStream * s,const ORDER_INFO * orderInfo,MULTI_OPAQUE_RECT_ORDER * multi_opaque_rect)1450 static BOOL update_read_multi_opaque_rect_order(wStream* s, const ORDER_INFO* orderInfo,
1451                                                 MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect)
1452 {
1453 	BYTE byte;
1454 	if (!read_order_field_coord(orderInfo, s, 1, &multi_opaque_rect->nLeftRect, FALSE) ||
1455 	    !read_order_field_coord(orderInfo, s, 2, &multi_opaque_rect->nTopRect, FALSE) ||
1456 	    !read_order_field_coord(orderInfo, s, 3, &multi_opaque_rect->nWidth, FALSE) ||
1457 	    !read_order_field_coord(orderInfo, s, 4, &multi_opaque_rect->nHeight, FALSE))
1458 		return FALSE;
1459 
1460 	if ((orderInfo->fieldFlags & ORDER_FIELD_05) != 0)
1461 	{
1462 		if (Stream_GetRemainingLength(s) < 1)
1463 			return FALSE;
1464 
1465 		Stream_Read_UINT8(s, byte);
1466 		multi_opaque_rect->color = (multi_opaque_rect->color & 0x00FFFF00) | ((UINT32)byte);
1467 	}
1468 
1469 	if ((orderInfo->fieldFlags & ORDER_FIELD_06) != 0)
1470 	{
1471 		if (Stream_GetRemainingLength(s) < 1)
1472 			return FALSE;
1473 
1474 		Stream_Read_UINT8(s, byte);
1475 		multi_opaque_rect->color = (multi_opaque_rect->color & 0x00FF00FF) | ((UINT32)byte << 8);
1476 	}
1477 
1478 	if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0)
1479 	{
1480 		if (Stream_GetRemainingLength(s) < 1)
1481 			return FALSE;
1482 
1483 		Stream_Read_UINT8(s, byte);
1484 		multi_opaque_rect->color = (multi_opaque_rect->color & 0x0000FFFF) | ((UINT32)byte << 16);
1485 	}
1486 
1487 	if (!read_order_field_byte(orderInfo, s, 8, &multi_opaque_rect->numRectangles, TRUE))
1488 		return FALSE;
1489 
1490 	if ((orderInfo->fieldFlags & ORDER_FIELD_09) != 0)
1491 	{
1492 		if (Stream_GetRemainingLength(s) < 2)
1493 			return FALSE;
1494 
1495 		Stream_Read_UINT16(s, multi_opaque_rect->cbData);
1496 		return update_read_delta_rects(s, multi_opaque_rect->rectangles,
1497 		                               &multi_opaque_rect->numRectangles);
1498 	}
1499 
1500 	return TRUE;
1501 }
update_read_multi_draw_nine_grid_order(wStream * s,const ORDER_INFO * orderInfo,MULTI_DRAW_NINE_GRID_ORDER * multi_draw_nine_grid)1502 static BOOL update_read_multi_draw_nine_grid_order(wStream* s, const ORDER_INFO* orderInfo,
1503                                                    MULTI_DRAW_NINE_GRID_ORDER* multi_draw_nine_grid)
1504 {
1505 	if (!read_order_field_coord(orderInfo, s, 1, &multi_draw_nine_grid->srcLeft, FALSE) ||
1506 	    !read_order_field_coord(orderInfo, s, 2, &multi_draw_nine_grid->srcTop, FALSE) ||
1507 	    !read_order_field_coord(orderInfo, s, 3, &multi_draw_nine_grid->srcRight, FALSE) ||
1508 	    !read_order_field_coord(orderInfo, s, 4, &multi_draw_nine_grid->srcBottom, FALSE) ||
1509 	    !read_order_field_uint16(orderInfo, s, 5, &multi_draw_nine_grid->bitmapId, TRUE) ||
1510 	    !read_order_field_byte(orderInfo, s, 6, &multi_draw_nine_grid->nDeltaEntries, TRUE))
1511 		return FALSE;
1512 
1513 	if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0)
1514 	{
1515 		if (Stream_GetRemainingLength(s) < 2)
1516 			return FALSE;
1517 
1518 		Stream_Read_UINT16(s, multi_draw_nine_grid->cbData);
1519 		return update_read_delta_rects(s, multi_draw_nine_grid->rectangles,
1520 		                               &multi_draw_nine_grid->nDeltaEntries);
1521 	}
1522 
1523 	return TRUE;
1524 }
update_read_line_to_order(wStream * s,const ORDER_INFO * orderInfo,LINE_TO_ORDER * line_to)1525 static BOOL update_read_line_to_order(wStream* s, const ORDER_INFO* orderInfo,
1526                                       LINE_TO_ORDER* line_to)
1527 {
1528 	if (read_order_field_uint16(orderInfo, s, 1, &line_to->backMode, TRUE) &&
1529 	    read_order_field_coord(orderInfo, s, 2, &line_to->nXStart, FALSE) &&
1530 	    read_order_field_coord(orderInfo, s, 3, &line_to->nYStart, FALSE) &&
1531 	    read_order_field_coord(orderInfo, s, 4, &line_to->nXEnd, FALSE) &&
1532 	    read_order_field_coord(orderInfo, s, 5, &line_to->nYEnd, FALSE) &&
1533 	    read_order_field_color(orderInfo, s, 6, &line_to->backColor, TRUE) &&
1534 	    read_order_field_byte(orderInfo, s, 7, &line_to->bRop2, TRUE) &&
1535 	    read_order_field_byte(orderInfo, s, 8, &line_to->penStyle, TRUE) &&
1536 	    read_order_field_byte(orderInfo, s, 9, &line_to->penWidth, TRUE) &&
1537 	    read_order_field_color(orderInfo, s, 10, &line_to->penColor, TRUE))
1538 		return TRUE;
1539 	return FALSE;
1540 }
update_approximate_line_to_order(ORDER_INFO * orderInfo,const LINE_TO_ORDER * line_to)1541 int update_approximate_line_to_order(ORDER_INFO* orderInfo, const LINE_TO_ORDER* line_to)
1542 {
1543 	return 32;
1544 }
update_write_line_to_order(wStream * s,ORDER_INFO * orderInfo,const LINE_TO_ORDER * line_to)1545 BOOL update_write_line_to_order(wStream* s, ORDER_INFO* orderInfo, const LINE_TO_ORDER* line_to)
1546 {
1547 	if (!Stream_EnsureRemainingCapacity(s, update_approximate_line_to_order(orderInfo, line_to)))
1548 		return FALSE;
1549 
1550 	orderInfo->fieldFlags = 0;
1551 	orderInfo->fieldFlags |= ORDER_FIELD_01;
1552 	Stream_Write_UINT16(s, line_to->backMode);
1553 	orderInfo->fieldFlags |= ORDER_FIELD_02;
1554 	update_write_coord(s, line_to->nXStart);
1555 	orderInfo->fieldFlags |= ORDER_FIELD_03;
1556 	update_write_coord(s, line_to->nYStart);
1557 	orderInfo->fieldFlags |= ORDER_FIELD_04;
1558 	update_write_coord(s, line_to->nXEnd);
1559 	orderInfo->fieldFlags |= ORDER_FIELD_05;
1560 	update_write_coord(s, line_to->nYEnd);
1561 	orderInfo->fieldFlags |= ORDER_FIELD_06;
1562 	update_write_color(s, line_to->backColor);
1563 	orderInfo->fieldFlags |= ORDER_FIELD_07;
1564 	Stream_Write_UINT8(s, line_to->bRop2);
1565 	orderInfo->fieldFlags |= ORDER_FIELD_08;
1566 	Stream_Write_UINT8(s, line_to->penStyle);
1567 	orderInfo->fieldFlags |= ORDER_FIELD_09;
1568 	Stream_Write_UINT8(s, line_to->penWidth);
1569 	orderInfo->fieldFlags |= ORDER_FIELD_10;
1570 	update_write_color(s, line_to->penColor);
1571 	return TRUE;
1572 }
update_read_polyline_order(wStream * s,const ORDER_INFO * orderInfo,POLYLINE_ORDER * polyline)1573 static BOOL update_read_polyline_order(wStream* s, const ORDER_INFO* orderInfo,
1574                                        POLYLINE_ORDER* polyline)
1575 {
1576 	UINT32 word;
1577 	UINT32 new_num = polyline->numDeltaEntries;
1578 	if (!read_order_field_coord(orderInfo, s, 1, &polyline->xStart, FALSE) ||
1579 	    !read_order_field_coord(orderInfo, s, 2, &polyline->yStart, FALSE) ||
1580 	    !read_order_field_byte(orderInfo, s, 3, &polyline->bRop2, TRUE) ||
1581 	    !read_order_field_uint16(orderInfo, s, 4, &word, TRUE) ||
1582 	    !read_order_field_color(orderInfo, s, 5, &polyline->penColor, TRUE) ||
1583 	    !read_order_field_byte(orderInfo, s, 6, &new_num, TRUE))
1584 		return FALSE;
1585 
1586 	if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0)
1587 	{
1588 		DELTA_POINT* new_points;
1589 
1590 		if (new_num == 0)
1591 			return FALSE;
1592 
1593 		if (Stream_GetRemainingLength(s) < 1)
1594 		{
1595 			WLog_ERR(TAG, "Stream_GetRemainingLength(s) < 1");
1596 			return FALSE;
1597 		}
1598 
1599 		Stream_Read_UINT8(s, polyline->cbData);
1600 		new_points = (DELTA_POINT*)realloc(polyline->points, sizeof(DELTA_POINT) * new_num);
1601 
1602 		if (!new_points)
1603 		{
1604 			WLog_ERR(TAG, "realloc(%" PRIu32 ") failed", new_num);
1605 			return FALSE;
1606 		}
1607 
1608 		polyline->points = new_points;
1609 		polyline->numDeltaEntries = new_num;
1610 		return update_read_delta_points(s, polyline->points, polyline->numDeltaEntries,
1611 		                                polyline->xStart, polyline->yStart);
1612 	}
1613 
1614 	return TRUE;
1615 }
update_read_memblt_order(wStream * s,const ORDER_INFO * orderInfo,MEMBLT_ORDER * memblt)1616 static BOOL update_read_memblt_order(wStream* s, const ORDER_INFO* orderInfo, MEMBLT_ORDER* memblt)
1617 {
1618 	if (!s || !orderInfo || !memblt)
1619 		return FALSE;
1620 
1621 	if (!read_order_field_uint16(orderInfo, s, 1, &memblt->cacheId, TRUE) ||
1622 	    !read_order_field_coord(orderInfo, s, 2, &memblt->nLeftRect, FALSE) ||
1623 	    !read_order_field_coord(orderInfo, s, 3, &memblt->nTopRect, FALSE) ||
1624 	    !read_order_field_coord(orderInfo, s, 4, &memblt->nWidth, FALSE) ||
1625 	    !read_order_field_coord(orderInfo, s, 5, &memblt->nHeight, FALSE) ||
1626 	    !read_order_field_byte(orderInfo, s, 6, &memblt->bRop, TRUE) ||
1627 	    !read_order_field_coord(orderInfo, s, 7, &memblt->nXSrc, FALSE) ||
1628 	    !read_order_field_coord(orderInfo, s, 8, &memblt->nYSrc, FALSE) ||
1629 	    !read_order_field_uint16(orderInfo, s, 9, &memblt->cacheIndex, TRUE))
1630 		return FALSE;
1631 	memblt->colorIndex = (memblt->cacheId >> 8);
1632 	memblt->cacheId = (memblt->cacheId & 0xFF);
1633 	memblt->bitmap = NULL;
1634 	return TRUE;
1635 }
update_approximate_memblt_order(ORDER_INFO * orderInfo,const MEMBLT_ORDER * memblt)1636 int update_approximate_memblt_order(ORDER_INFO* orderInfo, const MEMBLT_ORDER* memblt)
1637 {
1638 	return 64;
1639 }
update_write_memblt_order(wStream * s,ORDER_INFO * orderInfo,const MEMBLT_ORDER * memblt)1640 BOOL update_write_memblt_order(wStream* s, ORDER_INFO* orderInfo, const MEMBLT_ORDER* memblt)
1641 {
1642 	UINT16 cacheId;
1643 
1644 	if (!Stream_EnsureRemainingCapacity(s, update_approximate_memblt_order(orderInfo, memblt)))
1645 		return FALSE;
1646 
1647 	cacheId = (memblt->cacheId & 0xFF) | ((memblt->colorIndex & 0xFF) << 8);
1648 	orderInfo->fieldFlags |= ORDER_FIELD_01;
1649 	Stream_Write_UINT16(s, cacheId);
1650 	orderInfo->fieldFlags |= ORDER_FIELD_02;
1651 	update_write_coord(s, memblt->nLeftRect);
1652 	orderInfo->fieldFlags |= ORDER_FIELD_03;
1653 	update_write_coord(s, memblt->nTopRect);
1654 	orderInfo->fieldFlags |= ORDER_FIELD_04;
1655 	update_write_coord(s, memblt->nWidth);
1656 	orderInfo->fieldFlags |= ORDER_FIELD_05;
1657 	update_write_coord(s, memblt->nHeight);
1658 	orderInfo->fieldFlags |= ORDER_FIELD_06;
1659 	Stream_Write_UINT8(s, memblt->bRop);
1660 	orderInfo->fieldFlags |= ORDER_FIELD_07;
1661 	update_write_coord(s, memblt->nXSrc);
1662 	orderInfo->fieldFlags |= ORDER_FIELD_08;
1663 	update_write_coord(s, memblt->nYSrc);
1664 	orderInfo->fieldFlags |= ORDER_FIELD_09;
1665 	Stream_Write_UINT16(s, memblt->cacheIndex);
1666 	return TRUE;
1667 }
update_read_mem3blt_order(wStream * s,const ORDER_INFO * orderInfo,MEM3BLT_ORDER * mem3blt)1668 static BOOL update_read_mem3blt_order(wStream* s, const ORDER_INFO* orderInfo,
1669                                       MEM3BLT_ORDER* mem3blt)
1670 {
1671 	if (!read_order_field_uint16(orderInfo, s, 1, &mem3blt->cacheId, TRUE) ||
1672 	    !read_order_field_coord(orderInfo, s, 2, &mem3blt->nLeftRect, FALSE) ||
1673 	    !read_order_field_coord(orderInfo, s, 3, &mem3blt->nTopRect, FALSE) ||
1674 	    !read_order_field_coord(orderInfo, s, 4, &mem3blt->nWidth, FALSE) ||
1675 	    !read_order_field_coord(orderInfo, s, 5, &mem3blt->nHeight, FALSE) ||
1676 	    !read_order_field_byte(orderInfo, s, 6, &mem3blt->bRop, TRUE) ||
1677 	    !read_order_field_coord(orderInfo, s, 7, &mem3blt->nXSrc, FALSE) ||
1678 	    !read_order_field_coord(orderInfo, s, 8, &mem3blt->nYSrc, FALSE) ||
1679 	    !read_order_field_color(orderInfo, s, 9, &mem3blt->backColor, TRUE) ||
1680 	    !read_order_field_color(orderInfo, s, 10, &mem3blt->foreColor, TRUE))
1681 		return FALSE;
1682 
1683 	if (!update_read_brush(s, &mem3blt->brush, orderInfo->fieldFlags >> 10) ||
1684 	    !read_order_field_uint16(orderInfo, s, 16, &mem3blt->cacheIndex, TRUE))
1685 		return FALSE;
1686 	mem3blt->colorIndex = (mem3blt->cacheId >> 8);
1687 	mem3blt->cacheId = (mem3blt->cacheId & 0xFF);
1688 	mem3blt->bitmap = NULL;
1689 	return TRUE;
1690 }
update_read_save_bitmap_order(wStream * s,const ORDER_INFO * orderInfo,SAVE_BITMAP_ORDER * save_bitmap)1691 static BOOL update_read_save_bitmap_order(wStream* s, const ORDER_INFO* orderInfo,
1692                                           SAVE_BITMAP_ORDER* save_bitmap)
1693 {
1694 	if (read_order_field_uint32(orderInfo, s, 1, &save_bitmap->savedBitmapPosition, TRUE) &&
1695 	    read_order_field_coord(orderInfo, s, 2, &save_bitmap->nLeftRect, FALSE) &&
1696 	    read_order_field_coord(orderInfo, s, 3, &save_bitmap->nTopRect, FALSE) &&
1697 	    read_order_field_coord(orderInfo, s, 4, &save_bitmap->nRightRect, FALSE) &&
1698 	    read_order_field_coord(orderInfo, s, 5, &save_bitmap->nBottomRect, FALSE) &&
1699 	    read_order_field_byte(orderInfo, s, 6, &save_bitmap->operation, TRUE))
1700 		return TRUE;
1701 	return FALSE;
1702 }
update_read_glyph_index_order(wStream * s,const ORDER_INFO * orderInfo,GLYPH_INDEX_ORDER * glyph_index)1703 static BOOL update_read_glyph_index_order(wStream* s, const ORDER_INFO* orderInfo,
1704                                           GLYPH_INDEX_ORDER* glyph_index)
1705 {
1706 	if (!read_order_field_byte(orderInfo, s, 1, &glyph_index->cacheId, TRUE) ||
1707 	    !read_order_field_byte(orderInfo, s, 2, &glyph_index->flAccel, TRUE) ||
1708 	    !read_order_field_byte(orderInfo, s, 3, &glyph_index->ulCharInc, TRUE) ||
1709 	    !read_order_field_byte(orderInfo, s, 4, &glyph_index->fOpRedundant, TRUE) ||
1710 	    !read_order_field_color(orderInfo, s, 5, &glyph_index->backColor, TRUE) ||
1711 	    !read_order_field_color(orderInfo, s, 6, &glyph_index->foreColor, TRUE) ||
1712 	    !read_order_field_int16(orderInfo, s, 7, &glyph_index->bkLeft, TRUE) ||
1713 	    !read_order_field_int16(orderInfo, s, 8, &glyph_index->bkTop, TRUE) ||
1714 	    !read_order_field_int16(orderInfo, s, 9, &glyph_index->bkRight, TRUE) ||
1715 	    !read_order_field_int16(orderInfo, s, 10, &glyph_index->bkBottom, TRUE) ||
1716 	    !read_order_field_int16(orderInfo, s, 11, &glyph_index->opLeft, TRUE) ||
1717 	    !read_order_field_int16(orderInfo, s, 12, &glyph_index->opTop, TRUE) ||
1718 	    !read_order_field_int16(orderInfo, s, 13, &glyph_index->opRight, TRUE) ||
1719 	    !read_order_field_int16(orderInfo, s, 14, &glyph_index->opBottom, TRUE) ||
1720 	    !update_read_brush(s, &glyph_index->brush, orderInfo->fieldFlags >> 14) ||
1721 	    !read_order_field_int16(orderInfo, s, 20, &glyph_index->x, TRUE) ||
1722 	    !read_order_field_int16(orderInfo, s, 21, &glyph_index->y, TRUE))
1723 		return FALSE;
1724 
1725 	if ((orderInfo->fieldFlags & ORDER_FIELD_22) != 0)
1726 	{
1727 		if (Stream_GetRemainingLength(s) < 1)
1728 			return FALSE;
1729 
1730 		Stream_Read_UINT8(s, glyph_index->cbData);
1731 
1732 		if (Stream_GetRemainingLength(s) < glyph_index->cbData)
1733 			return FALSE;
1734 
1735 		CopyMemory(glyph_index->data, Stream_Pointer(s), glyph_index->cbData);
1736 		Stream_Seek(s, glyph_index->cbData);
1737 	}
1738 
1739 	return TRUE;
1740 }
update_approximate_glyph_index_order(ORDER_INFO * orderInfo,const GLYPH_INDEX_ORDER * glyph_index)1741 int update_approximate_glyph_index_order(ORDER_INFO* orderInfo,
1742                                          const GLYPH_INDEX_ORDER* glyph_index)
1743 {
1744 	return 64;
1745 }
update_write_glyph_index_order(wStream * s,ORDER_INFO * orderInfo,GLYPH_INDEX_ORDER * glyph_index)1746 BOOL update_write_glyph_index_order(wStream* s, ORDER_INFO* orderInfo,
1747                                     GLYPH_INDEX_ORDER* glyph_index)
1748 {
1749 	int inf = update_approximate_glyph_index_order(orderInfo, glyph_index);
1750 
1751 	if (!Stream_EnsureRemainingCapacity(s, inf))
1752 		return FALSE;
1753 
1754 	orderInfo->fieldFlags = 0;
1755 	orderInfo->fieldFlags |= ORDER_FIELD_01;
1756 	Stream_Write_UINT8(s, glyph_index->cacheId);
1757 	orderInfo->fieldFlags |= ORDER_FIELD_02;
1758 	Stream_Write_UINT8(s, glyph_index->flAccel);
1759 	orderInfo->fieldFlags |= ORDER_FIELD_03;
1760 	Stream_Write_UINT8(s, glyph_index->ulCharInc);
1761 	orderInfo->fieldFlags |= ORDER_FIELD_04;
1762 	Stream_Write_UINT8(s, glyph_index->fOpRedundant);
1763 	orderInfo->fieldFlags |= ORDER_FIELD_05;
1764 	update_write_color(s, glyph_index->backColor);
1765 	orderInfo->fieldFlags |= ORDER_FIELD_06;
1766 	update_write_color(s, glyph_index->foreColor);
1767 	orderInfo->fieldFlags |= ORDER_FIELD_07;
1768 	Stream_Write_UINT16(s, glyph_index->bkLeft);
1769 	orderInfo->fieldFlags |= ORDER_FIELD_08;
1770 	Stream_Write_UINT16(s, glyph_index->bkTop);
1771 	orderInfo->fieldFlags |= ORDER_FIELD_09;
1772 	Stream_Write_UINT16(s, glyph_index->bkRight);
1773 	orderInfo->fieldFlags |= ORDER_FIELD_10;
1774 	Stream_Write_UINT16(s, glyph_index->bkBottom);
1775 	orderInfo->fieldFlags |= ORDER_FIELD_11;
1776 	Stream_Write_UINT16(s, glyph_index->opLeft);
1777 	orderInfo->fieldFlags |= ORDER_FIELD_12;
1778 	Stream_Write_UINT16(s, glyph_index->opTop);
1779 	orderInfo->fieldFlags |= ORDER_FIELD_13;
1780 	Stream_Write_UINT16(s, glyph_index->opRight);
1781 	orderInfo->fieldFlags |= ORDER_FIELD_14;
1782 	Stream_Write_UINT16(s, glyph_index->opBottom);
1783 	orderInfo->fieldFlags |= ORDER_FIELD_15;
1784 	orderInfo->fieldFlags |= ORDER_FIELD_16;
1785 	orderInfo->fieldFlags |= ORDER_FIELD_17;
1786 	orderInfo->fieldFlags |= ORDER_FIELD_18;
1787 	orderInfo->fieldFlags |= ORDER_FIELD_19;
1788 	update_write_brush(s, &glyph_index->brush, orderInfo->fieldFlags >> 14);
1789 	orderInfo->fieldFlags |= ORDER_FIELD_20;
1790 	Stream_Write_UINT16(s, glyph_index->x);
1791 	orderInfo->fieldFlags |= ORDER_FIELD_21;
1792 	Stream_Write_UINT16(s, glyph_index->y);
1793 	orderInfo->fieldFlags |= ORDER_FIELD_22;
1794 	Stream_Write_UINT8(s, glyph_index->cbData);
1795 	Stream_Write(s, glyph_index->data, glyph_index->cbData);
1796 	return TRUE;
1797 }
update_read_fast_index_order(wStream * s,const ORDER_INFO * orderInfo,FAST_INDEX_ORDER * fast_index)1798 static BOOL update_read_fast_index_order(wStream* s, const ORDER_INFO* orderInfo,
1799                                          FAST_INDEX_ORDER* fast_index)
1800 {
1801 	if (!read_order_field_byte(orderInfo, s, 1, &fast_index->cacheId, TRUE) ||
1802 	    !read_order_field_2bytes(orderInfo, s, 2, &fast_index->ulCharInc, &fast_index->flAccel,
1803 	                             TRUE) ||
1804 	    !read_order_field_color(orderInfo, s, 3, &fast_index->backColor, TRUE) ||
1805 	    !read_order_field_color(orderInfo, s, 4, &fast_index->foreColor, TRUE) ||
1806 	    !read_order_field_coord(orderInfo, s, 5, &fast_index->bkLeft, FALSE) ||
1807 	    !read_order_field_coord(orderInfo, s, 6, &fast_index->bkTop, FALSE) ||
1808 	    !read_order_field_coord(orderInfo, s, 7, &fast_index->bkRight, FALSE) ||
1809 	    !read_order_field_coord(orderInfo, s, 8, &fast_index->bkBottom, FALSE) ||
1810 	    !read_order_field_coord(orderInfo, s, 9, &fast_index->opLeft, FALSE) ||
1811 	    !read_order_field_coord(orderInfo, s, 10, &fast_index->opTop, FALSE) ||
1812 	    !read_order_field_coord(orderInfo, s, 11, &fast_index->opRight, FALSE) ||
1813 	    !read_order_field_coord(orderInfo, s, 12, &fast_index->opBottom, FALSE) ||
1814 	    !read_order_field_coord(orderInfo, s, 13, &fast_index->x, FALSE) ||
1815 	    !read_order_field_coord(orderInfo, s, 14, &fast_index->y, FALSE))
1816 		return FALSE;
1817 
1818 	if ((orderInfo->fieldFlags & ORDER_FIELD_15) != 0)
1819 	{
1820 		if (Stream_GetRemainingLength(s) < 1)
1821 			return FALSE;
1822 
1823 		Stream_Read_UINT8(s, fast_index->cbData);
1824 
1825 		if (Stream_GetRemainingLength(s) < fast_index->cbData)
1826 			return FALSE;
1827 
1828 		CopyMemory(fast_index->data, Stream_Pointer(s), fast_index->cbData);
1829 		Stream_Seek(s, fast_index->cbData);
1830 	}
1831 
1832 	return TRUE;
1833 }
update_read_fast_glyph_order(wStream * s,const ORDER_INFO * orderInfo,FAST_GLYPH_ORDER * fastGlyph)1834 static BOOL update_read_fast_glyph_order(wStream* s, const ORDER_INFO* orderInfo,
1835                                          FAST_GLYPH_ORDER* fastGlyph)
1836 {
1837 	GLYPH_DATA_V2* glyph = &fastGlyph->glyphData;
1838 	if (!read_order_field_byte(orderInfo, s, 1, &fastGlyph->cacheId, TRUE))
1839 		return FALSE;
1840 	if (fastGlyph->cacheId > 9)
1841 		return FALSE;
1842 	if (!read_order_field_2bytes(orderInfo, s, 2, &fastGlyph->ulCharInc, &fastGlyph->flAccel,
1843 	                             TRUE) ||
1844 	    !read_order_field_color(orderInfo, s, 3, &fastGlyph->backColor, TRUE) ||
1845 	    !read_order_field_color(orderInfo, s, 4, &fastGlyph->foreColor, TRUE) ||
1846 	    !read_order_field_coord(orderInfo, s, 5, &fastGlyph->bkLeft, FALSE) ||
1847 	    !read_order_field_coord(orderInfo, s, 6, &fastGlyph->bkTop, FALSE) ||
1848 	    !read_order_field_coord(orderInfo, s, 7, &fastGlyph->bkRight, FALSE) ||
1849 	    !read_order_field_coord(orderInfo, s, 8, &fastGlyph->bkBottom, FALSE) ||
1850 	    !read_order_field_coord(orderInfo, s, 9, &fastGlyph->opLeft, FALSE) ||
1851 	    !read_order_field_coord(orderInfo, s, 10, &fastGlyph->opTop, FALSE) ||
1852 	    !read_order_field_coord(orderInfo, s, 11, &fastGlyph->opRight, FALSE) ||
1853 	    !read_order_field_coord(orderInfo, s, 12, &fastGlyph->opBottom, FALSE) ||
1854 	    !read_order_field_coord(orderInfo, s, 13, &fastGlyph->x, FALSE) ||
1855 	    !read_order_field_coord(orderInfo, s, 14, &fastGlyph->y, FALSE))
1856 		return FALSE;
1857 
1858 	if ((orderInfo->fieldFlags & ORDER_FIELD_15) != 0)
1859 	{
1860 		const BYTE* src;
1861 		wStream sub;
1862 		if (Stream_GetRemainingLength(s) < 1)
1863 			return FALSE;
1864 
1865 		Stream_Read_UINT8(s, fastGlyph->cbData);
1866 
1867 		src = Stream_Pointer(s);
1868 		if (!Stream_SafeSeek(s, fastGlyph->cbData) || (fastGlyph->cbData == 0))
1869 			return FALSE;
1870 
1871 		CopyMemory(fastGlyph->data, src, fastGlyph->cbData);
1872 		Stream_StaticInit(&sub, fastGlyph->data, fastGlyph->cbData);
1873 
1874 		Stream_Read_UINT8(&sub, glyph->cacheIndex);
1875 
1876 		if (fastGlyph->cbData > 1)
1877 		{
1878 			if (!update_read_2byte_signed(&sub, &glyph->x) ||
1879 			    !update_read_2byte_signed(&sub, &glyph->y) ||
1880 			    !update_read_2byte_unsigned(&sub, &glyph->cx) ||
1881 			    !update_read_2byte_unsigned(&sub, &glyph->cy))
1882 				return FALSE;
1883 
1884 			if ((glyph->cx == 0) || (glyph->cy == 0))
1885 			{
1886 				WLog_ERR(TAG, "GLYPH_DATA_V2::cx=%" PRIu32 ", GLYPH_DATA_V2::cy=%" PRIu32,
1887 				         glyph->cx, glyph->cy);
1888 				return FALSE;
1889 			}
1890 
1891 			glyph->cb = Stream_GetRemainingLength(&sub);
1892 			if (glyph->cb > 0)
1893 			{
1894 				BYTE* new_aj = (BYTE*)realloc(glyph->aj, glyph->cb);
1895 
1896 				if (!new_aj)
1897 					return FALSE;
1898 
1899 				glyph->aj = new_aj;
1900 				Stream_Read(&sub, glyph->aj, glyph->cb);
1901 			}
1902 			else
1903 			{
1904 				free(glyph->aj);
1905 				glyph->aj = NULL;
1906 			}
1907 		}
1908 	}
1909 
1910 	return TRUE;
1911 }
update_read_polygon_sc_order(wStream * s,const ORDER_INFO * orderInfo,POLYGON_SC_ORDER * polygon_sc)1912 static BOOL update_read_polygon_sc_order(wStream* s, const ORDER_INFO* orderInfo,
1913                                          POLYGON_SC_ORDER* polygon_sc)
1914 {
1915 	UINT32 num = polygon_sc->numPoints;
1916 	if (!read_order_field_coord(orderInfo, s, 1, &polygon_sc->xStart, FALSE) ||
1917 	    !read_order_field_coord(orderInfo, s, 2, &polygon_sc->yStart, FALSE) ||
1918 	    !read_order_field_byte(orderInfo, s, 3, &polygon_sc->bRop2, TRUE) ||
1919 	    !read_order_field_byte(orderInfo, s, 4, &polygon_sc->fillMode, TRUE) ||
1920 	    !read_order_field_color(orderInfo, s, 5, &polygon_sc->brushColor, TRUE) ||
1921 	    !read_order_field_byte(orderInfo, s, 6, &num, TRUE))
1922 		return FALSE;
1923 
1924 	if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0)
1925 	{
1926 		DELTA_POINT* newpoints;
1927 
1928 		if (num == 0)
1929 			return FALSE;
1930 
1931 		if (Stream_GetRemainingLength(s) < 1)
1932 			return FALSE;
1933 
1934 		Stream_Read_UINT8(s, polygon_sc->cbData);
1935 		newpoints = (DELTA_POINT*)realloc(polygon_sc->points, sizeof(DELTA_POINT) * num);
1936 
1937 		if (!newpoints)
1938 			return FALSE;
1939 
1940 		polygon_sc->points = newpoints;
1941 		polygon_sc->numPoints = num;
1942 		return update_read_delta_points(s, polygon_sc->points, polygon_sc->numPoints,
1943 		                                polygon_sc->xStart, polygon_sc->yStart);
1944 	}
1945 
1946 	return TRUE;
1947 }
update_read_polygon_cb_order(wStream * s,const ORDER_INFO * orderInfo,POLYGON_CB_ORDER * polygon_cb)1948 static BOOL update_read_polygon_cb_order(wStream* s, const ORDER_INFO* orderInfo,
1949                                          POLYGON_CB_ORDER* polygon_cb)
1950 {
1951 	UINT32 num = polygon_cb->numPoints;
1952 	if (!read_order_field_coord(orderInfo, s, 1, &polygon_cb->xStart, FALSE) ||
1953 	    !read_order_field_coord(orderInfo, s, 2, &polygon_cb->yStart, FALSE) ||
1954 	    !read_order_field_byte(orderInfo, s, 3, &polygon_cb->bRop2, TRUE) ||
1955 	    !read_order_field_byte(orderInfo, s, 4, &polygon_cb->fillMode, TRUE) ||
1956 	    !read_order_field_color(orderInfo, s, 5, &polygon_cb->backColor, TRUE) ||
1957 	    !read_order_field_color(orderInfo, s, 6, &polygon_cb->foreColor, TRUE))
1958 		return FALSE;
1959 
1960 	if (!update_read_brush(s, &polygon_cb->brush, orderInfo->fieldFlags >> 6))
1961 		return FALSE;
1962 
1963 	if (!read_order_field_byte(orderInfo, s, 12, &num, TRUE))
1964 		return FALSE;
1965 
1966 	if ((orderInfo->fieldFlags & ORDER_FIELD_13) != 0)
1967 	{
1968 		DELTA_POINT* newpoints;
1969 
1970 		if (num == 0)
1971 			return FALSE;
1972 
1973 		if (Stream_GetRemainingLength(s) < 1)
1974 			return FALSE;
1975 
1976 		Stream_Read_UINT8(s, polygon_cb->cbData);
1977 		newpoints = (DELTA_POINT*)realloc(polygon_cb->points, sizeof(DELTA_POINT) * num);
1978 
1979 		if (!newpoints)
1980 			return FALSE;
1981 
1982 		polygon_cb->points = newpoints;
1983 		polygon_cb->numPoints = num;
1984 
1985 		if (!update_read_delta_points(s, polygon_cb->points, polygon_cb->numPoints,
1986 		                              polygon_cb->xStart, polygon_cb->yStart))
1987 			return FALSE;
1988 	}
1989 
1990 	polygon_cb->backMode = (polygon_cb->bRop2 & 0x80) ? BACKMODE_TRANSPARENT : BACKMODE_OPAQUE;
1991 	polygon_cb->bRop2 = (polygon_cb->bRop2 & 0x1F);
1992 	return TRUE;
1993 }
update_read_ellipse_sc_order(wStream * s,const ORDER_INFO * orderInfo,ELLIPSE_SC_ORDER * ellipse_sc)1994 static BOOL update_read_ellipse_sc_order(wStream* s, const ORDER_INFO* orderInfo,
1995                                          ELLIPSE_SC_ORDER* ellipse_sc)
1996 {
1997 	if (read_order_field_coord(orderInfo, s, 1, &ellipse_sc->leftRect, FALSE) &&
1998 	    read_order_field_coord(orderInfo, s, 2, &ellipse_sc->topRect, FALSE) &&
1999 	    read_order_field_coord(orderInfo, s, 3, &ellipse_sc->rightRect, FALSE) &&
2000 	    read_order_field_coord(orderInfo, s, 4, &ellipse_sc->bottomRect, FALSE) &&
2001 	    read_order_field_byte(orderInfo, s, 5, &ellipse_sc->bRop2, TRUE) &&
2002 	    read_order_field_byte(orderInfo, s, 6, &ellipse_sc->fillMode, TRUE) &&
2003 	    read_order_field_color(orderInfo, s, 7, &ellipse_sc->color, TRUE))
2004 		return TRUE;
2005 	return FALSE;
2006 }
update_read_ellipse_cb_order(wStream * s,const ORDER_INFO * orderInfo,ELLIPSE_CB_ORDER * ellipse_cb)2007 static BOOL update_read_ellipse_cb_order(wStream* s, const ORDER_INFO* orderInfo,
2008                                          ELLIPSE_CB_ORDER* ellipse_cb)
2009 {
2010 	if (read_order_field_coord(orderInfo, s, 1, &ellipse_cb->leftRect, FALSE) &&
2011 	    read_order_field_coord(orderInfo, s, 2, &ellipse_cb->topRect, FALSE) &&
2012 	    read_order_field_coord(orderInfo, s, 3, &ellipse_cb->rightRect, FALSE) &&
2013 	    read_order_field_coord(orderInfo, s, 4, &ellipse_cb->bottomRect, FALSE) &&
2014 	    read_order_field_byte(orderInfo, s, 5, &ellipse_cb->bRop2, TRUE) &&
2015 	    read_order_field_byte(orderInfo, s, 6, &ellipse_cb->fillMode, TRUE) &&
2016 	    read_order_field_color(orderInfo, s, 7, &ellipse_cb->backColor, TRUE) &&
2017 	    read_order_field_color(orderInfo, s, 8, &ellipse_cb->foreColor, TRUE) &&
2018 	    update_read_brush(s, &ellipse_cb->brush, orderInfo->fieldFlags >> 8))
2019 		return TRUE;
2020 	return FALSE;
2021 }
2022 /* Secondary Drawing Orders */
update_read_cache_bitmap_order(rdpUpdate * update,wStream * s,BOOL compressed,UINT16 flags)2023 static CACHE_BITMAP_ORDER* update_read_cache_bitmap_order(rdpUpdate* update, wStream* s,
2024                                                           BOOL compressed, UINT16 flags)
2025 {
2026 	CACHE_BITMAP_ORDER* cache_bitmap;
2027 
2028 	if (!update || !s)
2029 		return NULL;
2030 
2031 	cache_bitmap = calloc(1, sizeof(CACHE_BITMAP_ORDER));
2032 
2033 	if (!cache_bitmap)
2034 		goto fail;
2035 
2036 	if (Stream_GetRemainingLength(s) < 9)
2037 		goto fail;
2038 
2039 	Stream_Read_UINT8(s, cache_bitmap->cacheId);      /* cacheId (1 byte) */
2040 	Stream_Seek_UINT8(s);                             /* pad1Octet (1 byte) */
2041 	Stream_Read_UINT8(s, cache_bitmap->bitmapWidth);  /* bitmapWidth (1 byte) */
2042 	Stream_Read_UINT8(s, cache_bitmap->bitmapHeight); /* bitmapHeight (1 byte) */
2043 	Stream_Read_UINT8(s, cache_bitmap->bitmapBpp);    /* bitmapBpp (1 byte) */
2044 
2045 	if ((cache_bitmap->bitmapBpp < 1) || (cache_bitmap->bitmapBpp > 32))
2046 	{
2047 		WLog_Print(update->log, WLOG_ERROR, "invalid bitmap bpp %" PRIu32 "",
2048 		           cache_bitmap->bitmapBpp);
2049 		goto fail;
2050 	}
2051 
2052 	Stream_Read_UINT16(s, cache_bitmap->bitmapLength); /* bitmapLength (2 bytes) */
2053 	Stream_Read_UINT16(s, cache_bitmap->cacheIndex);   /* cacheIndex (2 bytes) */
2054 
2055 	if (compressed)
2056 	{
2057 		if ((flags & NO_BITMAP_COMPRESSION_HDR) == 0)
2058 		{
2059 			BYTE* bitmapComprHdr = (BYTE*)&(cache_bitmap->bitmapComprHdr);
2060 
2061 			if (Stream_GetRemainingLength(s) < 8)
2062 				goto fail;
2063 
2064 			Stream_Read(s, bitmapComprHdr, 8); /* bitmapComprHdr (8 bytes) */
2065 			cache_bitmap->bitmapLength -= 8;
2066 		}
2067 	}
2068 
2069 	if (cache_bitmap->bitmapLength == 0)
2070 		goto fail;
2071 
2072 	if (Stream_GetRemainingLength(s) < cache_bitmap->bitmapLength)
2073 		goto fail;
2074 
2075 	cache_bitmap->bitmapDataStream = malloc(cache_bitmap->bitmapLength);
2076 
2077 	if (!cache_bitmap->bitmapDataStream)
2078 		goto fail;
2079 
2080 	Stream_Read(s, cache_bitmap->bitmapDataStream, cache_bitmap->bitmapLength);
2081 	cache_bitmap->compressed = compressed;
2082 	return cache_bitmap;
2083 fail:
2084 	free_cache_bitmap_order(update->context, cache_bitmap);
2085 	return NULL;
2086 }
update_approximate_cache_bitmap_order(const CACHE_BITMAP_ORDER * cache_bitmap,BOOL compressed,UINT16 * flags)2087 int update_approximate_cache_bitmap_order(const CACHE_BITMAP_ORDER* cache_bitmap, BOOL compressed,
2088                                           UINT16* flags)
2089 {
2090 	return 64 + cache_bitmap->bitmapLength;
2091 }
update_write_cache_bitmap_order(wStream * s,const CACHE_BITMAP_ORDER * cache_bitmap,BOOL compressed,UINT16 * flags)2092 BOOL update_write_cache_bitmap_order(wStream* s, const CACHE_BITMAP_ORDER* cache_bitmap,
2093                                      BOOL compressed, UINT16* flags)
2094 {
2095 	UINT32 bitmapLength = cache_bitmap->bitmapLength;
2096 	int inf = update_approximate_cache_bitmap_order(cache_bitmap, compressed, flags);
2097 
2098 	if (!Stream_EnsureRemainingCapacity(s, inf))
2099 		return FALSE;
2100 
2101 	*flags = NO_BITMAP_COMPRESSION_HDR;
2102 
2103 	if ((*flags & NO_BITMAP_COMPRESSION_HDR) == 0)
2104 		bitmapLength += 8;
2105 
2106 	Stream_Write_UINT8(s, cache_bitmap->cacheId);      /* cacheId (1 byte) */
2107 	Stream_Write_UINT8(s, 0);                          /* pad1Octet (1 byte) */
2108 	Stream_Write_UINT8(s, cache_bitmap->bitmapWidth);  /* bitmapWidth (1 byte) */
2109 	Stream_Write_UINT8(s, cache_bitmap->bitmapHeight); /* bitmapHeight (1 byte) */
2110 	Stream_Write_UINT8(s, cache_bitmap->bitmapBpp);    /* bitmapBpp (1 byte) */
2111 	Stream_Write_UINT16(s, bitmapLength);              /* bitmapLength (2 bytes) */
2112 	Stream_Write_UINT16(s, cache_bitmap->cacheIndex);  /* cacheIndex (2 bytes) */
2113 
2114 	if (compressed)
2115 	{
2116 		if ((*flags & NO_BITMAP_COMPRESSION_HDR) == 0)
2117 		{
2118 			BYTE* bitmapComprHdr = (BYTE*)&(cache_bitmap->bitmapComprHdr);
2119 			Stream_Write(s, bitmapComprHdr, 8); /* bitmapComprHdr (8 bytes) */
2120 			bitmapLength -= 8;
2121 		}
2122 
2123 		Stream_Write(s, cache_bitmap->bitmapDataStream, bitmapLength);
2124 	}
2125 	else
2126 	{
2127 		Stream_Write(s, cache_bitmap->bitmapDataStream, bitmapLength);
2128 	}
2129 
2130 	return TRUE;
2131 }
update_read_cache_bitmap_v2_order(rdpUpdate * update,wStream * s,BOOL compressed,UINT16 flags)2132 static CACHE_BITMAP_V2_ORDER* update_read_cache_bitmap_v2_order(rdpUpdate* update, wStream* s,
2133                                                                 BOOL compressed, UINT16 flags)
2134 {
2135 	BOOL rc;
2136 	BYTE bitsPerPixelId;
2137 	CACHE_BITMAP_V2_ORDER* cache_bitmap_v2;
2138 
2139 	if (!update || !s)
2140 		return NULL;
2141 
2142 	cache_bitmap_v2 = calloc(1, sizeof(CACHE_BITMAP_V2_ORDER));
2143 
2144 	if (!cache_bitmap_v2)
2145 		goto fail;
2146 
2147 	cache_bitmap_v2->cacheId = flags & 0x0003;
2148 	cache_bitmap_v2->flags = (flags & 0xFF80) >> 7;
2149 	bitsPerPixelId = (flags & 0x0078) >> 3;
2150 	cache_bitmap_v2->bitmapBpp = get_cbr2_bpp(bitsPerPixelId, &rc);
2151 	if (!rc)
2152 		goto fail;
2153 
2154 	if (cache_bitmap_v2->flags & CBR2_PERSISTENT_KEY_PRESENT)
2155 	{
2156 		if (Stream_GetRemainingLength(s) < 8)
2157 			goto fail;
2158 
2159 		Stream_Read_UINT32(s, cache_bitmap_v2->key1); /* key1 (4 bytes) */
2160 		Stream_Read_UINT32(s, cache_bitmap_v2->key2); /* key2 (4 bytes) */
2161 	}
2162 
2163 	if (cache_bitmap_v2->flags & CBR2_HEIGHT_SAME_AS_WIDTH)
2164 	{
2165 		if (!update_read_2byte_unsigned(s, &cache_bitmap_v2->bitmapWidth)) /* bitmapWidth */
2166 			goto fail;
2167 
2168 		cache_bitmap_v2->bitmapHeight = cache_bitmap_v2->bitmapWidth;
2169 	}
2170 	else
2171 	{
2172 		if (!update_read_2byte_unsigned(s, &cache_bitmap_v2->bitmapWidth) || /* bitmapWidth */
2173 		    !update_read_2byte_unsigned(s, &cache_bitmap_v2->bitmapHeight))  /* bitmapHeight */
2174 			goto fail;
2175 	}
2176 
2177 	if (!update_read_4byte_unsigned(s, &cache_bitmap_v2->bitmapLength) || /* bitmapLength */
2178 	    !update_read_2byte_unsigned(s, &cache_bitmap_v2->cacheIndex))     /* cacheIndex */
2179 		goto fail;
2180 
2181 	if (cache_bitmap_v2->flags & CBR2_DO_NOT_CACHE)
2182 		cache_bitmap_v2->cacheIndex = BITMAP_CACHE_WAITING_LIST_INDEX;
2183 
2184 	if (compressed)
2185 	{
2186 		if (!(cache_bitmap_v2->flags & CBR2_NO_BITMAP_COMPRESSION_HDR))
2187 		{
2188 			if (Stream_GetRemainingLength(s) < 8)
2189 				goto fail;
2190 
2191 			Stream_Read_UINT16(
2192 			    s, cache_bitmap_v2->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */
2193 			Stream_Read_UINT16(
2194 			    s, cache_bitmap_v2->cbCompMainBodySize);         /* cbCompMainBodySize (2 bytes) */
2195 			Stream_Read_UINT16(s, cache_bitmap_v2->cbScanWidth); /* cbScanWidth (2 bytes) */
2196 			Stream_Read_UINT16(
2197 			    s, cache_bitmap_v2->cbUncompressedSize); /* cbUncompressedSize (2 bytes) */
2198 			cache_bitmap_v2->bitmapLength = cache_bitmap_v2->cbCompMainBodySize;
2199 		}
2200 	}
2201 
2202 	if (cache_bitmap_v2->bitmapLength == 0)
2203 		goto fail;
2204 
2205 	if (Stream_GetRemainingLength(s) < cache_bitmap_v2->bitmapLength)
2206 		goto fail;
2207 
2208 	if (cache_bitmap_v2->bitmapLength == 0)
2209 		goto fail;
2210 
2211 	cache_bitmap_v2->bitmapDataStream = malloc(cache_bitmap_v2->bitmapLength);
2212 
2213 	if (!cache_bitmap_v2->bitmapDataStream)
2214 		goto fail;
2215 
2216 	Stream_Read(s, cache_bitmap_v2->bitmapDataStream, cache_bitmap_v2->bitmapLength);
2217 	cache_bitmap_v2->compressed = compressed;
2218 	return cache_bitmap_v2;
2219 fail:
2220 	free_cache_bitmap_v2_order(update->context, cache_bitmap_v2);
2221 	return NULL;
2222 }
update_approximate_cache_bitmap_v2_order(CACHE_BITMAP_V2_ORDER * cache_bitmap_v2,BOOL compressed,UINT16 * flags)2223 int update_approximate_cache_bitmap_v2_order(CACHE_BITMAP_V2_ORDER* cache_bitmap_v2,
2224                                              BOOL compressed, UINT16* flags)
2225 {
2226 	return 64 + cache_bitmap_v2->bitmapLength;
2227 }
update_write_cache_bitmap_v2_order(wStream * s,CACHE_BITMAP_V2_ORDER * cache_bitmap_v2,BOOL compressed,UINT16 * flags)2228 BOOL update_write_cache_bitmap_v2_order(wStream* s, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2,
2229                                         BOOL compressed, UINT16* flags)
2230 {
2231 	BOOL rc;
2232 	BYTE bitsPerPixelId;
2233 
2234 	if (!Stream_EnsureRemainingCapacity(
2235 	        s, update_approximate_cache_bitmap_v2_order(cache_bitmap_v2, compressed, flags)))
2236 		return FALSE;
2237 
2238 	bitsPerPixelId = get_bpp_bmf(cache_bitmap_v2->bitmapBpp, &rc);
2239 	if (!rc)
2240 		return FALSE;
2241 	*flags = (cache_bitmap_v2->cacheId & 0x0003) | (bitsPerPixelId << 3) |
2242 	         ((cache_bitmap_v2->flags << 7) & 0xFF80);
2243 
2244 	if (cache_bitmap_v2->flags & CBR2_PERSISTENT_KEY_PRESENT)
2245 	{
2246 		Stream_Write_UINT32(s, cache_bitmap_v2->key1); /* key1 (4 bytes) */
2247 		Stream_Write_UINT32(s, cache_bitmap_v2->key2); /* key2 (4 bytes) */
2248 	}
2249 
2250 	if (cache_bitmap_v2->flags & CBR2_HEIGHT_SAME_AS_WIDTH)
2251 	{
2252 		if (!update_write_2byte_unsigned(s, cache_bitmap_v2->bitmapWidth)) /* bitmapWidth */
2253 			return FALSE;
2254 	}
2255 	else
2256 	{
2257 		if (!update_write_2byte_unsigned(s, cache_bitmap_v2->bitmapWidth) || /* bitmapWidth */
2258 		    !update_write_2byte_unsigned(s, cache_bitmap_v2->bitmapHeight))  /* bitmapHeight */
2259 			return FALSE;
2260 	}
2261 
2262 	if (cache_bitmap_v2->flags & CBR2_DO_NOT_CACHE)
2263 		cache_bitmap_v2->cacheIndex = BITMAP_CACHE_WAITING_LIST_INDEX;
2264 
2265 	if (!update_write_4byte_unsigned(s, cache_bitmap_v2->bitmapLength) || /* bitmapLength */
2266 	    !update_write_2byte_unsigned(s, cache_bitmap_v2->cacheIndex))     /* cacheIndex */
2267 		return FALSE;
2268 
2269 	if (compressed)
2270 	{
2271 		if (!(cache_bitmap_v2->flags & CBR2_NO_BITMAP_COMPRESSION_HDR))
2272 		{
2273 			Stream_Write_UINT16(
2274 			    s, cache_bitmap_v2->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */
2275 			Stream_Write_UINT16(
2276 			    s, cache_bitmap_v2->cbCompMainBodySize);          /* cbCompMainBodySize (2 bytes) */
2277 			Stream_Write_UINT16(s, cache_bitmap_v2->cbScanWidth); /* cbScanWidth (2 bytes) */
2278 			Stream_Write_UINT16(
2279 			    s, cache_bitmap_v2->cbUncompressedSize); /* cbUncompressedSize (2 bytes) */
2280 			cache_bitmap_v2->bitmapLength = cache_bitmap_v2->cbCompMainBodySize;
2281 		}
2282 
2283 		if (!Stream_EnsureRemainingCapacity(s, cache_bitmap_v2->bitmapLength))
2284 			return FALSE;
2285 
2286 		Stream_Write(s, cache_bitmap_v2->bitmapDataStream, cache_bitmap_v2->bitmapLength);
2287 	}
2288 	else
2289 	{
2290 		if (!Stream_EnsureRemainingCapacity(s, cache_bitmap_v2->bitmapLength))
2291 			return FALSE;
2292 
2293 		Stream_Write(s, cache_bitmap_v2->bitmapDataStream, cache_bitmap_v2->bitmapLength);
2294 	}
2295 
2296 	cache_bitmap_v2->compressed = compressed;
2297 	return TRUE;
2298 }
update_read_cache_bitmap_v3_order(rdpUpdate * update,wStream * s,UINT16 flags)2299 static CACHE_BITMAP_V3_ORDER* update_read_cache_bitmap_v3_order(rdpUpdate* update, wStream* s,
2300                                                                 UINT16 flags)
2301 {
2302 	BOOL rc;
2303 	BYTE bitsPerPixelId;
2304 	BITMAP_DATA_EX* bitmapData;
2305 	UINT32 new_len;
2306 	BYTE* new_data;
2307 	CACHE_BITMAP_V3_ORDER* cache_bitmap_v3;
2308 
2309 	if (!update || !s)
2310 		return NULL;
2311 
2312 	cache_bitmap_v3 = calloc(1, sizeof(CACHE_BITMAP_V3_ORDER));
2313 
2314 	if (!cache_bitmap_v3)
2315 		goto fail;
2316 
2317 	cache_bitmap_v3->cacheId = flags & 0x00000003;
2318 	cache_bitmap_v3->flags = (flags & 0x0000FF80) >> 7;
2319 	bitsPerPixelId = (flags & 0x00000078) >> 3;
2320 	cache_bitmap_v3->bpp = get_cbr2_bpp(bitsPerPixelId, &rc);
2321 	if (!rc)
2322 		goto fail;
2323 
2324 	if (Stream_GetRemainingLength(s) < 21)
2325 		goto fail;
2326 
2327 	Stream_Read_UINT16(s, cache_bitmap_v3->cacheIndex); /* cacheIndex (2 bytes) */
2328 	Stream_Read_UINT32(s, cache_bitmap_v3->key1);       /* key1 (4 bytes) */
2329 	Stream_Read_UINT32(s, cache_bitmap_v3->key2);       /* key2 (4 bytes) */
2330 	bitmapData = &cache_bitmap_v3->bitmapData;
2331 	Stream_Read_UINT8(s, bitmapData->bpp);
2332 
2333 	if ((bitmapData->bpp < 1) || (bitmapData->bpp > 32))
2334 	{
2335 		WLog_Print(update->log, WLOG_ERROR, "invalid bpp value %" PRIu32 "", bitmapData->bpp);
2336 		goto fail;
2337 	}
2338 
2339 	Stream_Seek_UINT8(s);                      /* reserved1 (1 byte) */
2340 	Stream_Seek_UINT8(s);                      /* reserved2 (1 byte) */
2341 	Stream_Read_UINT8(s, bitmapData->codecID); /* codecID (1 byte) */
2342 	Stream_Read_UINT16(s, bitmapData->width);  /* width (2 bytes) */
2343 	Stream_Read_UINT16(s, bitmapData->height); /* height (2 bytes) */
2344 	Stream_Read_UINT32(s, new_len);            /* length (4 bytes) */
2345 
2346 	if ((new_len == 0) || (Stream_GetRemainingLength(s) < new_len))
2347 		goto fail;
2348 
2349 	new_data = (BYTE*)realloc(bitmapData->data, new_len);
2350 
2351 	if (!new_data)
2352 		goto fail;
2353 
2354 	bitmapData->data = new_data;
2355 	bitmapData->length = new_len;
2356 	Stream_Read(s, bitmapData->data, bitmapData->length);
2357 	return cache_bitmap_v3;
2358 fail:
2359 	free_cache_bitmap_v3_order(update->context, cache_bitmap_v3);
2360 	return NULL;
2361 }
update_approximate_cache_bitmap_v3_order(CACHE_BITMAP_V3_ORDER * cache_bitmap_v3,UINT16 * flags)2362 int update_approximate_cache_bitmap_v3_order(CACHE_BITMAP_V3_ORDER* cache_bitmap_v3, UINT16* flags)
2363 {
2364 	BITMAP_DATA_EX* bitmapData = &cache_bitmap_v3->bitmapData;
2365 	return 64 + bitmapData->length;
2366 }
update_write_cache_bitmap_v3_order(wStream * s,CACHE_BITMAP_V3_ORDER * cache_bitmap_v3,UINT16 * flags)2367 BOOL update_write_cache_bitmap_v3_order(wStream* s, CACHE_BITMAP_V3_ORDER* cache_bitmap_v3,
2368                                         UINT16* flags)
2369 {
2370 	BOOL rc;
2371 	BYTE bitsPerPixelId;
2372 	BITMAP_DATA_EX* bitmapData;
2373 
2374 	if (!Stream_EnsureRemainingCapacity(
2375 	        s, update_approximate_cache_bitmap_v3_order(cache_bitmap_v3, flags)))
2376 		return FALSE;
2377 
2378 	bitmapData = &cache_bitmap_v3->bitmapData;
2379 	bitsPerPixelId = get_bpp_bmf(cache_bitmap_v3->bpp, &rc);
2380 	if (!rc)
2381 		return FALSE;
2382 	*flags = (cache_bitmap_v3->cacheId & 0x00000003) |
2383 	         ((cache_bitmap_v3->flags << 7) & 0x0000FF80) | ((bitsPerPixelId << 3) & 0x00000078);
2384 	Stream_Write_UINT16(s, cache_bitmap_v3->cacheIndex); /* cacheIndex (2 bytes) */
2385 	Stream_Write_UINT32(s, cache_bitmap_v3->key1);       /* key1 (4 bytes) */
2386 	Stream_Write_UINT32(s, cache_bitmap_v3->key2);       /* key2 (4 bytes) */
2387 	Stream_Write_UINT8(s, bitmapData->bpp);
2388 	Stream_Write_UINT8(s, 0);                   /* reserved1 (1 byte) */
2389 	Stream_Write_UINT8(s, 0);                   /* reserved2 (1 byte) */
2390 	Stream_Write_UINT8(s, bitmapData->codecID); /* codecID (1 byte) */
2391 	Stream_Write_UINT16(s, bitmapData->width);  /* width (2 bytes) */
2392 	Stream_Write_UINT16(s, bitmapData->height); /* height (2 bytes) */
2393 	Stream_Write_UINT32(s, bitmapData->length); /* length (4 bytes) */
2394 	Stream_Write(s, bitmapData->data, bitmapData->length);
2395 	return TRUE;
2396 }
update_read_cache_color_table_order(rdpUpdate * update,wStream * s,UINT16 flags)2397 static CACHE_COLOR_TABLE_ORDER* update_read_cache_color_table_order(rdpUpdate* update, wStream* s,
2398                                                                     UINT16 flags)
2399 {
2400 	int i;
2401 	UINT32* colorTable;
2402 	CACHE_COLOR_TABLE_ORDER* cache_color_table = calloc(1, sizeof(CACHE_COLOR_TABLE_ORDER));
2403 
2404 	if (!cache_color_table)
2405 		goto fail;
2406 
2407 	if (Stream_GetRemainingLength(s) < 3)
2408 		goto fail;
2409 
2410 	Stream_Read_UINT8(s, cache_color_table->cacheIndex);    /* cacheIndex (1 byte) */
2411 	Stream_Read_UINT16(s, cache_color_table->numberColors); /* numberColors (2 bytes) */
2412 
2413 	if (cache_color_table->numberColors != 256)
2414 	{
2415 		/* This field MUST be set to 256 */
2416 		goto fail;
2417 	}
2418 
2419 	if (Stream_GetRemainingLength(s) < cache_color_table->numberColors * 4)
2420 		goto fail;
2421 
2422 	colorTable = (UINT32*)&cache_color_table->colorTable;
2423 
2424 	for (i = 0; i < (int)cache_color_table->numberColors; i++)
2425 		update_read_color_quad(s, &colorTable[i]);
2426 
2427 	return cache_color_table;
2428 fail:
2429 	free_cache_color_table_order(update->context, cache_color_table);
2430 	return NULL;
2431 }
update_approximate_cache_color_table_order(const CACHE_COLOR_TABLE_ORDER * cache_color_table,UINT16 * flags)2432 int update_approximate_cache_color_table_order(const CACHE_COLOR_TABLE_ORDER* cache_color_table,
2433                                                UINT16* flags)
2434 {
2435 	return 16 + (256 * 4);
2436 }
update_write_cache_color_table_order(wStream * s,const CACHE_COLOR_TABLE_ORDER * cache_color_table,UINT16 * flags)2437 BOOL update_write_cache_color_table_order(wStream* s,
2438                                           const CACHE_COLOR_TABLE_ORDER* cache_color_table,
2439                                           UINT16* flags)
2440 {
2441 	int i, inf;
2442 	UINT32* colorTable;
2443 
2444 	if (cache_color_table->numberColors != 256)
2445 		return FALSE;
2446 
2447 	inf = update_approximate_cache_color_table_order(cache_color_table, flags);
2448 
2449 	if (!Stream_EnsureRemainingCapacity(s, inf))
2450 		return FALSE;
2451 
2452 	Stream_Write_UINT8(s, cache_color_table->cacheIndex);    /* cacheIndex (1 byte) */
2453 	Stream_Write_UINT16(s, cache_color_table->numberColors); /* numberColors (2 bytes) */
2454 	colorTable = (UINT32*)&cache_color_table->colorTable;
2455 
2456 	for (i = 0; i < (int)cache_color_table->numberColors; i++)
2457 	{
2458 		update_write_color_quad(s, colorTable[i]);
2459 	}
2460 
2461 	return TRUE;
2462 }
update_read_cache_glyph_order(rdpUpdate * update,wStream * s,UINT16 flags)2463 static CACHE_GLYPH_ORDER* update_read_cache_glyph_order(rdpUpdate* update, wStream* s, UINT16 flags)
2464 {
2465 	UINT32 i;
2466 	CACHE_GLYPH_ORDER* cache_glyph_order = calloc(1, sizeof(CACHE_GLYPH_ORDER));
2467 
2468 	if (!cache_glyph_order || !update || !s)
2469 		goto fail;
2470 
2471 	if (Stream_GetRemainingLength(s) < 2)
2472 		goto fail;
2473 
2474 	Stream_Read_UINT8(s, cache_glyph_order->cacheId); /* cacheId (1 byte) */
2475 	Stream_Read_UINT8(s, cache_glyph_order->cGlyphs); /* cGlyphs (1 byte) */
2476 
2477 	for (i = 0; i < cache_glyph_order->cGlyphs; i++)
2478 	{
2479 		GLYPH_DATA* glyph = &cache_glyph_order->glyphData[i];
2480 
2481 		if (Stream_GetRemainingLength(s) < 10)
2482 			goto fail;
2483 
2484 		Stream_Read_UINT16(s, glyph->cacheIndex);
2485 		Stream_Read_INT16(s, glyph->x);
2486 		Stream_Read_INT16(s, glyph->y);
2487 		Stream_Read_UINT16(s, glyph->cx);
2488 		Stream_Read_UINT16(s, glyph->cy);
2489 		glyph->cb = ((glyph->cx + 7) / 8) * glyph->cy;
2490 		glyph->cb += ((glyph->cb % 4) > 0) ? 4 - (glyph->cb % 4) : 0;
2491 
2492 		if (Stream_GetRemainingLength(s) < glyph->cb)
2493 			goto fail;
2494 
2495 		glyph->aj = (BYTE*)malloc(glyph->cb);
2496 
2497 		if (!glyph->aj)
2498 			goto fail;
2499 
2500 		Stream_Read(s, glyph->aj, glyph->cb);
2501 	}
2502 
2503 	if ((flags & CG_GLYPH_UNICODE_PRESENT) && (cache_glyph_order->cGlyphs > 0))
2504 	{
2505 		cache_glyph_order->unicodeCharacters = calloc(cache_glyph_order->cGlyphs, sizeof(WCHAR));
2506 
2507 		if (!cache_glyph_order->unicodeCharacters)
2508 			goto fail;
2509 
2510 		if (Stream_GetRemainingLength(s) < sizeof(WCHAR) * cache_glyph_order->cGlyphs)
2511 			goto fail;
2512 
2513 		Stream_Read_UTF16_String(s, cache_glyph_order->unicodeCharacters,
2514 		                         cache_glyph_order->cGlyphs);
2515 	}
2516 
2517 	return cache_glyph_order;
2518 fail:
2519 	free_cache_glyph_order(update->context, cache_glyph_order);
2520 	return NULL;
2521 }
update_approximate_cache_glyph_order(const CACHE_GLYPH_ORDER * cache_glyph,UINT16 * flags)2522 int update_approximate_cache_glyph_order(const CACHE_GLYPH_ORDER* cache_glyph, UINT16* flags)
2523 {
2524 	return 2 + cache_glyph->cGlyphs * 32;
2525 }
update_write_cache_glyph_order(wStream * s,const CACHE_GLYPH_ORDER * cache_glyph,UINT16 * flags)2526 BOOL update_write_cache_glyph_order(wStream* s, const CACHE_GLYPH_ORDER* cache_glyph, UINT16* flags)
2527 {
2528 	int i, inf;
2529 	INT16 lsi16;
2530 	const GLYPH_DATA* glyph;
2531 	inf = update_approximate_cache_glyph_order(cache_glyph, flags);
2532 
2533 	if (!Stream_EnsureRemainingCapacity(s, inf))
2534 		return FALSE;
2535 
2536 	Stream_Write_UINT8(s, cache_glyph->cacheId); /* cacheId (1 byte) */
2537 	Stream_Write_UINT8(s, cache_glyph->cGlyphs); /* cGlyphs (1 byte) */
2538 
2539 	for (i = 0; i < (int)cache_glyph->cGlyphs; i++)
2540 	{
2541 		UINT32 cb;
2542 		glyph = &cache_glyph->glyphData[i];
2543 		Stream_Write_UINT16(s, glyph->cacheIndex); /* cacheIndex (2 bytes) */
2544 		lsi16 = glyph->x;
2545 		Stream_Write_UINT16(s, lsi16); /* x (2 bytes) */
2546 		lsi16 = glyph->y;
2547 		Stream_Write_UINT16(s, lsi16);     /* y (2 bytes) */
2548 		Stream_Write_UINT16(s, glyph->cx); /* cx (2 bytes) */
2549 		Stream_Write_UINT16(s, glyph->cy); /* cy (2 bytes) */
2550 		cb = ((glyph->cx + 7) / 8) * glyph->cy;
2551 		cb += ((cb % 4) > 0) ? 4 - (cb % 4) : 0;
2552 		Stream_Write(s, glyph->aj, cb);
2553 	}
2554 
2555 	if (*flags & CG_GLYPH_UNICODE_PRESENT)
2556 	{
2557 		Stream_Zero(s, cache_glyph->cGlyphs * 2);
2558 	}
2559 
2560 	return TRUE;
2561 }
update_read_cache_glyph_v2_order(rdpUpdate * update,wStream * s,UINT16 flags)2562 static CACHE_GLYPH_V2_ORDER* update_read_cache_glyph_v2_order(rdpUpdate* update, wStream* s,
2563                                                               UINT16 flags)
2564 {
2565 	UINT32 i;
2566 	CACHE_GLYPH_V2_ORDER* cache_glyph_v2 = calloc(1, sizeof(CACHE_GLYPH_V2_ORDER));
2567 
2568 	if (!cache_glyph_v2)
2569 		goto fail;
2570 
2571 	cache_glyph_v2->cacheId = (flags & 0x000F);
2572 	cache_glyph_v2->flags = (flags & 0x00F0) >> 4;
2573 	cache_glyph_v2->cGlyphs = (flags & 0xFF00) >> 8;
2574 
2575 	for (i = 0; i < cache_glyph_v2->cGlyphs; i++)
2576 	{
2577 		GLYPH_DATA_V2* glyph = &cache_glyph_v2->glyphData[i];
2578 
2579 		if (Stream_GetRemainingLength(s) < 1)
2580 			goto fail;
2581 
2582 		Stream_Read_UINT8(s, glyph->cacheIndex);
2583 
2584 		if (!update_read_2byte_signed(s, &glyph->x) || !update_read_2byte_signed(s, &glyph->y) ||
2585 		    !update_read_2byte_unsigned(s, &glyph->cx) ||
2586 		    !update_read_2byte_unsigned(s, &glyph->cy))
2587 		{
2588 			goto fail;
2589 		}
2590 
2591 		glyph->cb = ((glyph->cx + 7) / 8) * glyph->cy;
2592 		glyph->cb += ((glyph->cb % 4) > 0) ? 4 - (glyph->cb % 4) : 0;
2593 
2594 		if (Stream_GetRemainingLength(s) < glyph->cb)
2595 			goto fail;
2596 
2597 		glyph->aj = (BYTE*)malloc(glyph->cb);
2598 
2599 		if (!glyph->aj)
2600 			goto fail;
2601 
2602 		Stream_Read(s, glyph->aj, glyph->cb);
2603 	}
2604 
2605 	if ((flags & CG_GLYPH_UNICODE_PRESENT) && (cache_glyph_v2->cGlyphs > 0))
2606 	{
2607 		cache_glyph_v2->unicodeCharacters = calloc(cache_glyph_v2->cGlyphs, sizeof(WCHAR));
2608 
2609 		if (!cache_glyph_v2->unicodeCharacters)
2610 			goto fail;
2611 
2612 		if (Stream_GetRemainingLength(s) < sizeof(WCHAR) * cache_glyph_v2->cGlyphs)
2613 			goto fail;
2614 
2615 		Stream_Read_UTF16_String(s, cache_glyph_v2->unicodeCharacters, cache_glyph_v2->cGlyphs);
2616 	}
2617 
2618 	return cache_glyph_v2;
2619 fail:
2620 	free_cache_glyph_v2_order(update->context, cache_glyph_v2);
2621 	return NULL;
2622 }
update_approximate_cache_glyph_v2_order(const CACHE_GLYPH_V2_ORDER * cache_glyph_v2,UINT16 * flags)2623 int update_approximate_cache_glyph_v2_order(const CACHE_GLYPH_V2_ORDER* cache_glyph_v2,
2624                                             UINT16* flags)
2625 {
2626 	return 8 + cache_glyph_v2->cGlyphs * 32;
2627 }
update_write_cache_glyph_v2_order(wStream * s,const CACHE_GLYPH_V2_ORDER * cache_glyph_v2,UINT16 * flags)2628 BOOL update_write_cache_glyph_v2_order(wStream* s, const CACHE_GLYPH_V2_ORDER* cache_glyph_v2,
2629                                        UINT16* flags)
2630 {
2631 	UINT32 i, inf;
2632 	inf = update_approximate_cache_glyph_v2_order(cache_glyph_v2, flags);
2633 
2634 	if (!Stream_EnsureRemainingCapacity(s, inf))
2635 		return FALSE;
2636 
2637 	*flags = (cache_glyph_v2->cacheId & 0x000F) | ((cache_glyph_v2->flags & 0x000F) << 4) |
2638 	         ((cache_glyph_v2->cGlyphs & 0x00FF) << 8);
2639 
2640 	for (i = 0; i < cache_glyph_v2->cGlyphs; i++)
2641 	{
2642 		UINT32 cb;
2643 		const GLYPH_DATA_V2* glyph = &cache_glyph_v2->glyphData[i];
2644 		Stream_Write_UINT8(s, glyph->cacheIndex);
2645 
2646 		if (!update_write_2byte_signed(s, glyph->x) || !update_write_2byte_signed(s, glyph->y) ||
2647 		    !update_write_2byte_unsigned(s, glyph->cx) ||
2648 		    !update_write_2byte_unsigned(s, glyph->cy))
2649 		{
2650 			return FALSE;
2651 		}
2652 
2653 		cb = ((glyph->cx + 7) / 8) * glyph->cy;
2654 		cb += ((cb % 4) > 0) ? 4 - (cb % 4) : 0;
2655 		Stream_Write(s, glyph->aj, cb);
2656 	}
2657 
2658 	if (*flags & CG_GLYPH_UNICODE_PRESENT)
2659 	{
2660 		Stream_Zero(s, cache_glyph_v2->cGlyphs * 2);
2661 	}
2662 
2663 	return TRUE;
2664 }
update_decompress_brush(wStream * s,BYTE * output,size_t outSize,BYTE bpp)2665 static BOOL update_decompress_brush(wStream* s, BYTE* output, size_t outSize, BYTE bpp)
2666 {
2667 	size_t x, k;
2668 	INT8 y;
2669 	BYTE byte = 0;
2670 	const BYTE* palette = Stream_Pointer(s) + 16;
2671 	const size_t bytesPerPixel = ((bpp + 1) / 8);
2672 
2673 	if (Stream_GetRemainingLength(s) < 16 + bytesPerPixel * 4)
2674 		return FALSE;
2675 
2676 	for (y = 7; y >= 0; y--)
2677 	{
2678 		for (x = 0; x < 8; x++)
2679 		{
2680 			UINT32 index;
2681 			if ((x % 4) == 0)
2682 				Stream_Read_UINT8(s, byte);
2683 
2684 			index = ((byte >> ((3 - (x % 4)) * 2)) & 0x03);
2685 
2686 			for (k = 0; k < bytesPerPixel; k++)
2687 			{
2688 				const size_t dstIndex = ((y * 8 + x) * bytesPerPixel) + k;
2689 				const size_t srcIndex = (index * bytesPerPixel) + k;
2690 				if (dstIndex >= outSize)
2691 					return FALSE;
2692 				output[dstIndex] = palette[srcIndex];
2693 			}
2694 		}
2695 	}
2696 
2697 	return TRUE;
2698 }
update_compress_brush(wStream * s,const BYTE * input,BYTE bpp)2699 static BOOL update_compress_brush(wStream* s, const BYTE* input, BYTE bpp)
2700 {
2701 	return FALSE;
2702 }
update_read_cache_brush_order(rdpUpdate * update,wStream * s,UINT16 flags)2703 static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStream* s, UINT16 flags)
2704 {
2705 	int i;
2706 	BOOL rc;
2707 	BYTE iBitmapFormat;
2708 	BOOL compressed = FALSE;
2709 	CACHE_BRUSH_ORDER* cache_brush = calloc(1, sizeof(CACHE_BRUSH_ORDER));
2710 
2711 	if (!cache_brush)
2712 		goto fail;
2713 
2714 	if (Stream_GetRemainingLength(s) < 6)
2715 		goto fail;
2716 
2717 	Stream_Read_UINT8(s, cache_brush->index); /* cacheEntry (1 byte) */
2718 	Stream_Read_UINT8(s, iBitmapFormat);      /* iBitmapFormat (1 byte) */
2719 
2720 	cache_brush->bpp = get_bmf_bpp(iBitmapFormat, &rc);
2721 	if (!rc)
2722 		goto fail;
2723 
2724 	Stream_Read_UINT8(s, cache_brush->cx);     /* cx (1 byte) */
2725 	Stream_Read_UINT8(s, cache_brush->cy);     /* cy (1 byte) */
2726 	/* according to  Section 2.2.2.2.1.2.7 errata the windows implementation sets this filed is set
2727 	 * to 0x00 */
2728 	Stream_Read_UINT8(s, cache_brush->style);  /* style (1 byte) */
2729 	Stream_Read_UINT8(s, cache_brush->length); /* iBytes (1 byte) */
2730 
2731 	if ((cache_brush->cx == 8) && (cache_brush->cy == 8))
2732 	{
2733 		if (cache_brush->bpp == 1)
2734 		{
2735 			if (cache_brush->length != 8)
2736 			{
2737 				WLog_Print(update->log, WLOG_ERROR, "incompatible 1bpp brush of length:%" PRIu32 "",
2738 				           cache_brush->length);
2739 				goto fail;
2740 			}
2741 
2742 			if (Stream_GetRemainingLength(s) < 8)
2743 				goto fail;
2744 
2745 			/* rows are encoded in reverse order */
2746 			for (i = 7; i >= 0; i--)
2747 				Stream_Read_UINT8(s, cache_brush->data[i]);
2748 		}
2749 		else
2750 		{
2751 			if ((iBitmapFormat == BMF_8BPP) && (cache_brush->length == 20))
2752 				compressed = TRUE;
2753 			else if ((iBitmapFormat == BMF_16BPP) && (cache_brush->length == 24))
2754 				compressed = TRUE;
2755 			else if ((iBitmapFormat == BMF_24BPP) && (cache_brush->length == 28))
2756 				compressed = TRUE;
2757 			else if ((iBitmapFormat == BMF_32BPP) && (cache_brush->length == 32))
2758 				compressed = TRUE;
2759 
2760 			if (compressed != FALSE)
2761 			{
2762 				/* compressed brush */
2763 				if (!update_decompress_brush(s, cache_brush->data, sizeof(cache_brush->data),
2764 				                             cache_brush->bpp))
2765 					goto fail;
2766 			}
2767 			else
2768 			{
2769 				/* uncompressed brush */
2770 				UINT32 scanline = (cache_brush->bpp / 8) * 8;
2771 
2772 				if (Stream_GetRemainingLength(s) < scanline * 8)
2773 					goto fail;
2774 
2775 				for (i = 7; i >= 0; i--)
2776 				{
2777 					Stream_Read(s, &cache_brush->data[i * scanline], scanline);
2778 				}
2779 			}
2780 		}
2781 	}
2782 
2783 	return cache_brush;
2784 fail:
2785 	free_cache_brush_order(update->context, cache_brush);
2786 	return NULL;
2787 }
update_approximate_cache_brush_order(const CACHE_BRUSH_ORDER * cache_brush,UINT16 * flags)2788 int update_approximate_cache_brush_order(const CACHE_BRUSH_ORDER* cache_brush, UINT16* flags)
2789 {
2790 	return 64;
2791 }
update_write_cache_brush_order(wStream * s,const CACHE_BRUSH_ORDER * cache_brush,UINT16 * flags)2792 BOOL update_write_cache_brush_order(wStream* s, const CACHE_BRUSH_ORDER* cache_brush, UINT16* flags)
2793 {
2794 	int i;
2795 	BYTE iBitmapFormat;
2796 	BOOL rc;
2797 	BOOL compressed = FALSE;
2798 
2799 	if (!Stream_EnsureRemainingCapacity(s,
2800 	                                    update_approximate_cache_brush_order(cache_brush, flags)))
2801 		return FALSE;
2802 
2803 	iBitmapFormat = get_bpp_bmf(cache_brush->bpp, &rc);
2804 	if (!rc)
2805 		return FALSE;
2806 	Stream_Write_UINT8(s, cache_brush->index);  /* cacheEntry (1 byte) */
2807 	Stream_Write_UINT8(s, iBitmapFormat);       /* iBitmapFormat (1 byte) */
2808 	Stream_Write_UINT8(s, cache_brush->cx);     /* cx (1 byte) */
2809 	Stream_Write_UINT8(s, cache_brush->cy);     /* cy (1 byte) */
2810 	Stream_Write_UINT8(s, cache_brush->style);  /* style (1 byte) */
2811 	Stream_Write_UINT8(s, cache_brush->length); /* iBytes (1 byte) */
2812 
2813 	if ((cache_brush->cx == 8) && (cache_brush->cy == 8))
2814 	{
2815 		if (cache_brush->bpp == 1)
2816 		{
2817 			if (cache_brush->length != 8)
2818 			{
2819 				WLog_ERR(TAG, "incompatible 1bpp brush of length:%" PRIu32 "", cache_brush->length);
2820 				return FALSE;
2821 			}
2822 
2823 			for (i = 7; i >= 0; i--)
2824 			{
2825 				Stream_Write_UINT8(s, cache_brush->data[i]);
2826 			}
2827 		}
2828 		else
2829 		{
2830 			if ((iBitmapFormat == BMF_8BPP) && (cache_brush->length == 20))
2831 				compressed = TRUE;
2832 			else if ((iBitmapFormat == BMF_16BPP) && (cache_brush->length == 24))
2833 				compressed = TRUE;
2834 			else if ((iBitmapFormat == BMF_32BPP) && (cache_brush->length == 32))
2835 				compressed = TRUE;
2836 
2837 			if (compressed != FALSE)
2838 			{
2839 				/* compressed brush */
2840 				if (!update_compress_brush(s, cache_brush->data, cache_brush->bpp))
2841 					return FALSE;
2842 			}
2843 			else
2844 			{
2845 				/* uncompressed brush */
2846 				int scanline = (cache_brush->bpp / 8) * 8;
2847 
2848 				for (i = 7; i >= 0; i--)
2849 				{
2850 					Stream_Write(s, &cache_brush->data[i * scanline], scanline);
2851 				}
2852 			}
2853 		}
2854 	}
2855 
2856 	return TRUE;
2857 }
2858 /* Alternate Secondary Drawing Orders */
2859 static BOOL
update_read_create_offscreen_bitmap_order(wStream * s,CREATE_OFFSCREEN_BITMAP_ORDER * create_offscreen_bitmap)2860 update_read_create_offscreen_bitmap_order(wStream* s,
2861                                           CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap)
2862 {
2863 	UINT16 flags;
2864 	BOOL deleteListPresent;
2865 	OFFSCREEN_DELETE_LIST* deleteList;
2866 
2867 	if (Stream_GetRemainingLength(s) < 6)
2868 		return FALSE;
2869 
2870 	Stream_Read_UINT16(s, flags); /* flags (2 bytes) */
2871 	create_offscreen_bitmap->id = flags & 0x7FFF;
2872 	deleteListPresent = (flags & 0x8000) ? TRUE : FALSE;
2873 	Stream_Read_UINT16(s, create_offscreen_bitmap->cx); /* cx (2 bytes) */
2874 	Stream_Read_UINT16(s, create_offscreen_bitmap->cy); /* cy (2 bytes) */
2875 	deleteList = &(create_offscreen_bitmap->deleteList);
2876 
2877 	if ((create_offscreen_bitmap->cx == 0) || (create_offscreen_bitmap->cy == 0))
2878 	{
2879 		WLog_ERR(TAG, "Invalid OFFSCREEN_DELETE_LIST: cx=%" PRIu16 ", cy=%" PRIu16,
2880 		         create_offscreen_bitmap->cx, create_offscreen_bitmap->cy);
2881 		return FALSE;
2882 	}
2883 
2884 	if (deleteListPresent)
2885 	{
2886 		UINT32 i;
2887 
2888 		if (Stream_GetRemainingLength(s) < 2)
2889 			return FALSE;
2890 
2891 		Stream_Read_UINT16(s, deleteList->cIndices);
2892 
2893 		if (deleteList->cIndices > deleteList->sIndices)
2894 		{
2895 			UINT16* new_indices;
2896 			new_indices = (UINT16*)realloc(deleteList->indices, deleteList->cIndices * 2);
2897 
2898 			if (!new_indices)
2899 				return FALSE;
2900 
2901 			deleteList->sIndices = deleteList->cIndices;
2902 			deleteList->indices = new_indices;
2903 		}
2904 
2905 		if (Stream_GetRemainingLength(s) < 2 * deleteList->cIndices)
2906 			return FALSE;
2907 
2908 		for (i = 0; i < deleteList->cIndices; i++)
2909 		{
2910 			Stream_Read_UINT16(s, deleteList->indices[i]);
2911 		}
2912 	}
2913 	else
2914 	{
2915 		deleteList->cIndices = 0;
2916 	}
2917 
2918 	return TRUE;
2919 }
update_approximate_create_offscreen_bitmap_order(const CREATE_OFFSCREEN_BITMAP_ORDER * create_offscreen_bitmap)2920 int update_approximate_create_offscreen_bitmap_order(
2921     const CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap)
2922 {
2923 	const OFFSCREEN_DELETE_LIST* deleteList = &(create_offscreen_bitmap->deleteList);
2924 	return 32 + deleteList->cIndices * 2;
2925 }
update_write_create_offscreen_bitmap_order(wStream * s,const CREATE_OFFSCREEN_BITMAP_ORDER * create_offscreen_bitmap)2926 BOOL update_write_create_offscreen_bitmap_order(
2927     wStream* s, const CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap)
2928 {
2929 	UINT16 flags;
2930 	BOOL deleteListPresent;
2931 	const OFFSCREEN_DELETE_LIST* deleteList;
2932 
2933 	if (!Stream_EnsureRemainingCapacity(
2934 	        s, update_approximate_create_offscreen_bitmap_order(create_offscreen_bitmap)))
2935 		return FALSE;
2936 
2937 	deleteList = &(create_offscreen_bitmap->deleteList);
2938 	flags = create_offscreen_bitmap->id & 0x7FFF;
2939 	deleteListPresent = (deleteList->cIndices > 0) ? TRUE : FALSE;
2940 
2941 	if (deleteListPresent)
2942 		flags |= 0x8000;
2943 
2944 	Stream_Write_UINT16(s, flags);                       /* flags (2 bytes) */
2945 	Stream_Write_UINT16(s, create_offscreen_bitmap->cx); /* cx (2 bytes) */
2946 	Stream_Write_UINT16(s, create_offscreen_bitmap->cy); /* cy (2 bytes) */
2947 
2948 	if (deleteListPresent)
2949 	{
2950 		int i;
2951 		Stream_Write_UINT16(s, deleteList->cIndices);
2952 
2953 		for (i = 0; i < (int)deleteList->cIndices; i++)
2954 		{
2955 			Stream_Write_UINT16(s, deleteList->indices[i]);
2956 		}
2957 	}
2958 
2959 	return TRUE;
2960 }
update_read_switch_surface_order(wStream * s,SWITCH_SURFACE_ORDER * switch_surface)2961 static BOOL update_read_switch_surface_order(wStream* s, SWITCH_SURFACE_ORDER* switch_surface)
2962 {
2963 	if (Stream_GetRemainingLength(s) < 2)
2964 		return FALSE;
2965 
2966 	Stream_Read_UINT16(s, switch_surface->bitmapId); /* bitmapId (2 bytes) */
2967 	return TRUE;
2968 }
update_approximate_switch_surface_order(const SWITCH_SURFACE_ORDER * switch_surface)2969 int update_approximate_switch_surface_order(const SWITCH_SURFACE_ORDER* switch_surface)
2970 {
2971 	return 2;
2972 }
update_write_switch_surface_order(wStream * s,const SWITCH_SURFACE_ORDER * switch_surface)2973 BOOL update_write_switch_surface_order(wStream* s, const SWITCH_SURFACE_ORDER* switch_surface)
2974 {
2975 	int inf = update_approximate_switch_surface_order(switch_surface);
2976 
2977 	if (!Stream_EnsureRemainingCapacity(s, inf))
2978 		return FALSE;
2979 
2980 	Stream_Write_UINT16(s, switch_surface->bitmapId); /* bitmapId (2 bytes) */
2981 	return TRUE;
2982 }
2983 static BOOL
update_read_create_nine_grid_bitmap_order(wStream * s,CREATE_NINE_GRID_BITMAP_ORDER * create_nine_grid_bitmap)2984 update_read_create_nine_grid_bitmap_order(wStream* s,
2985                                           CREATE_NINE_GRID_BITMAP_ORDER* create_nine_grid_bitmap)
2986 {
2987 	NINE_GRID_BITMAP_INFO* nineGridInfo;
2988 
2989 	if (Stream_GetRemainingLength(s) < 19)
2990 		return FALSE;
2991 
2992 	Stream_Read_UINT8(s, create_nine_grid_bitmap->bitmapBpp); /* bitmapBpp (1 byte) */
2993 
2994 	if ((create_nine_grid_bitmap->bitmapBpp < 1) || (create_nine_grid_bitmap->bitmapBpp > 32))
2995 	{
2996 		WLog_ERR(TAG, "invalid bpp value %" PRIu32 "", create_nine_grid_bitmap->bitmapBpp);
2997 		return FALSE;
2998 	}
2999 
3000 	Stream_Read_UINT16(s, create_nine_grid_bitmap->bitmapId); /* bitmapId (2 bytes) */
3001 	nineGridInfo = &(create_nine_grid_bitmap->nineGridInfo);
3002 	Stream_Read_UINT32(s, nineGridInfo->flFlags);          /* flFlags (4 bytes) */
3003 	Stream_Read_UINT16(s, nineGridInfo->ulLeftWidth);      /* ulLeftWidth (2 bytes) */
3004 	Stream_Read_UINT16(s, nineGridInfo->ulRightWidth);     /* ulRightWidth (2 bytes) */
3005 	Stream_Read_UINT16(s, nineGridInfo->ulTopHeight);      /* ulTopHeight (2 bytes) */
3006 	Stream_Read_UINT16(s, nineGridInfo->ulBottomHeight);   /* ulBottomHeight (2 bytes) */
3007 	update_read_colorref(s, &nineGridInfo->crTransparent); /* crTransparent (4 bytes) */
3008 	return TRUE;
3009 }
update_read_frame_marker_order(wStream * s,FRAME_MARKER_ORDER * frame_marker)3010 static BOOL update_read_frame_marker_order(wStream* s, FRAME_MARKER_ORDER* frame_marker)
3011 {
3012 	if (Stream_GetRemainingLength(s) < 4)
3013 		return FALSE;
3014 
3015 	Stream_Read_UINT32(s, frame_marker->action); /* action (4 bytes) */
3016 	return TRUE;
3017 }
update_read_stream_bitmap_first_order(wStream * s,STREAM_BITMAP_FIRST_ORDER * stream_bitmap_first)3018 static BOOL update_read_stream_bitmap_first_order(wStream* s,
3019                                                   STREAM_BITMAP_FIRST_ORDER* stream_bitmap_first)
3020 {
3021 	if (Stream_GetRemainingLength(s) < 10) // 8 + 2 at least
3022 		return FALSE;
3023 
3024 	Stream_Read_UINT8(s, stream_bitmap_first->bitmapFlags); /* bitmapFlags (1 byte) */
3025 	Stream_Read_UINT8(s, stream_bitmap_first->bitmapBpp);   /* bitmapBpp (1 byte) */
3026 
3027 	if ((stream_bitmap_first->bitmapBpp < 1) || (stream_bitmap_first->bitmapBpp > 32))
3028 	{
3029 		WLog_ERR(TAG, "invalid bpp value %" PRIu32 "", stream_bitmap_first->bitmapBpp);
3030 		return FALSE;
3031 	}
3032 
3033 	Stream_Read_UINT16(s, stream_bitmap_first->bitmapType);   /* bitmapType (2 bytes) */
3034 	Stream_Read_UINT16(s, stream_bitmap_first->bitmapWidth);  /* bitmapWidth (2 bytes) */
3035 	Stream_Read_UINT16(s, stream_bitmap_first->bitmapHeight); /* bitmapHeigth (2 bytes) */
3036 
3037 	if (stream_bitmap_first->bitmapFlags & STREAM_BITMAP_V2)
3038 	{
3039 		if (Stream_GetRemainingLength(s) < 4)
3040 			return FALSE;
3041 
3042 		Stream_Read_UINT32(s, stream_bitmap_first->bitmapSize); /* bitmapSize (4 bytes) */
3043 	}
3044 	else
3045 	{
3046 		if (Stream_GetRemainingLength(s) < 2)
3047 			return FALSE;
3048 
3049 		Stream_Read_UINT16(s, stream_bitmap_first->bitmapSize); /* bitmapSize (2 bytes) */
3050 	}
3051 
3052 	FIELD_SKIP_BUFFER16(
3053 	    s, stream_bitmap_first->bitmapBlockSize); /* bitmapBlockSize(2 bytes) + bitmapBlock */
3054 	return TRUE;
3055 }
update_read_stream_bitmap_next_order(wStream * s,STREAM_BITMAP_NEXT_ORDER * stream_bitmap_next)3056 static BOOL update_read_stream_bitmap_next_order(wStream* s,
3057                                                  STREAM_BITMAP_NEXT_ORDER* stream_bitmap_next)
3058 {
3059 	if (Stream_GetRemainingLength(s) < 5)
3060 		return FALSE;
3061 
3062 	Stream_Read_UINT8(s, stream_bitmap_next->bitmapFlags); /* bitmapFlags (1 byte) */
3063 	Stream_Read_UINT16(s, stream_bitmap_next->bitmapType); /* bitmapType (2 bytes) */
3064 	FIELD_SKIP_BUFFER16(
3065 	    s, stream_bitmap_next->bitmapBlockSize); /* bitmapBlockSize(2 bytes) + bitmapBlock */
3066 	return TRUE;
3067 }
update_read_draw_gdiplus_first_order(wStream * s,DRAW_GDIPLUS_FIRST_ORDER * draw_gdiplus_first)3068 static BOOL update_read_draw_gdiplus_first_order(wStream* s,
3069                                                  DRAW_GDIPLUS_FIRST_ORDER* draw_gdiplus_first)
3070 {
3071 	if (Stream_GetRemainingLength(s) < 11)
3072 		return FALSE;
3073 
3074 	Stream_Seek_UINT8(s);                                      /* pad1Octet (1 byte) */
3075 	Stream_Read_UINT16(s, draw_gdiplus_first->cbSize);         /* cbSize (2 bytes) */
3076 	Stream_Read_UINT32(s, draw_gdiplus_first->cbTotalSize);    /* cbTotalSize (4 bytes) */
3077 	Stream_Read_UINT32(s, draw_gdiplus_first->cbTotalEmfSize); /* cbTotalEmfSize (4 bytes) */
3078 	return Stream_SafeSeek(s, draw_gdiplus_first->cbSize);     /* emfRecords */
3079 }
update_read_draw_gdiplus_next_order(wStream * s,DRAW_GDIPLUS_NEXT_ORDER * draw_gdiplus_next)3080 static BOOL update_read_draw_gdiplus_next_order(wStream* s,
3081                                                 DRAW_GDIPLUS_NEXT_ORDER* draw_gdiplus_next)
3082 {
3083 	if (Stream_GetRemainingLength(s) < 3)
3084 		return FALSE;
3085 
3086 	Stream_Seek_UINT8(s);                              /* pad1Octet (1 byte) */
3087 	FIELD_SKIP_BUFFER16(s, draw_gdiplus_next->cbSize); /* cbSize(2 bytes) + emfRecords */
3088 	return TRUE;
3089 }
update_read_draw_gdiplus_end_order(wStream * s,DRAW_GDIPLUS_END_ORDER * draw_gdiplus_end)3090 static BOOL update_read_draw_gdiplus_end_order(wStream* s, DRAW_GDIPLUS_END_ORDER* draw_gdiplus_end)
3091 {
3092 	if (Stream_GetRemainingLength(s) < 11)
3093 		return FALSE;
3094 
3095 	Stream_Seek_UINT8(s);                                    /* pad1Octet (1 byte) */
3096 	Stream_Read_UINT16(s, draw_gdiplus_end->cbSize);         /* cbSize (2 bytes) */
3097 	Stream_Read_UINT32(s, draw_gdiplus_end->cbTotalSize);    /* cbTotalSize (4 bytes) */
3098 	Stream_Read_UINT32(s, draw_gdiplus_end->cbTotalEmfSize); /* cbTotalEmfSize (4 bytes) */
3099 	return Stream_SafeSeek(s, draw_gdiplus_end->cbSize);     /* emfRecords */
3100 }
3101 static BOOL
update_read_draw_gdiplus_cache_first_order(wStream * s,DRAW_GDIPLUS_CACHE_FIRST_ORDER * draw_gdiplus_cache_first)3102 update_read_draw_gdiplus_cache_first_order(wStream* s,
3103                                            DRAW_GDIPLUS_CACHE_FIRST_ORDER* draw_gdiplus_cache_first)
3104 {
3105 	if (Stream_GetRemainingLength(s) < 11)
3106 		return FALSE;
3107 
3108 	Stream_Read_UINT8(s, draw_gdiplus_cache_first->flags);        /* flags (1 byte) */
3109 	Stream_Read_UINT16(s, draw_gdiplus_cache_first->cacheType);   /* cacheType (2 bytes) */
3110 	Stream_Read_UINT16(s, draw_gdiplus_cache_first->cacheIndex);  /* cacheIndex (2 bytes) */
3111 	Stream_Read_UINT16(s, draw_gdiplus_cache_first->cbSize);      /* cbSize (2 bytes) */
3112 	Stream_Read_UINT32(s, draw_gdiplus_cache_first->cbTotalSize); /* cbTotalSize (4 bytes) */
3113 	return Stream_SafeSeek(s, draw_gdiplus_cache_first->cbSize);  /* emfRecords */
3114 }
3115 static BOOL
update_read_draw_gdiplus_cache_next_order(wStream * s,DRAW_GDIPLUS_CACHE_NEXT_ORDER * draw_gdiplus_cache_next)3116 update_read_draw_gdiplus_cache_next_order(wStream* s,
3117                                           DRAW_GDIPLUS_CACHE_NEXT_ORDER* draw_gdiplus_cache_next)
3118 {
3119 	if (Stream_GetRemainingLength(s) < 7)
3120 		return FALSE;
3121 
3122 	Stream_Read_UINT8(s, draw_gdiplus_cache_next->flags);       /* flags (1 byte) */
3123 	Stream_Read_UINT16(s, draw_gdiplus_cache_next->cacheType);  /* cacheType (2 bytes) */
3124 	Stream_Read_UINT16(s, draw_gdiplus_cache_next->cacheIndex); /* cacheIndex (2 bytes) */
3125 	FIELD_SKIP_BUFFER16(s, draw_gdiplus_cache_next->cbSize);    /* cbSize(2 bytes) + emfRecords */
3126 	return TRUE;
3127 }
3128 static BOOL
update_read_draw_gdiplus_cache_end_order(wStream * s,DRAW_GDIPLUS_CACHE_END_ORDER * draw_gdiplus_cache_end)3129 update_read_draw_gdiplus_cache_end_order(wStream* s,
3130                                          DRAW_GDIPLUS_CACHE_END_ORDER* draw_gdiplus_cache_end)
3131 {
3132 	if (Stream_GetRemainingLength(s) < 11)
3133 		return FALSE;
3134 
3135 	Stream_Read_UINT8(s, draw_gdiplus_cache_end->flags);        /* flags (1 byte) */
3136 	Stream_Read_UINT16(s, draw_gdiplus_cache_end->cacheType);   /* cacheType (2 bytes) */
3137 	Stream_Read_UINT16(s, draw_gdiplus_cache_end->cacheIndex);  /* cacheIndex (2 bytes) */
3138 	Stream_Read_UINT16(s, draw_gdiplus_cache_end->cbSize);      /* cbSize (2 bytes) */
3139 	Stream_Read_UINT32(s, draw_gdiplus_cache_end->cbTotalSize); /* cbTotalSize (4 bytes) */
3140 	return Stream_SafeSeek(s, draw_gdiplus_cache_end->cbSize);  /* emfRecords */
3141 }
update_read_field_flags(wStream * s,UINT32 * fieldFlags,BYTE flags,BYTE fieldBytes)3142 static BOOL update_read_field_flags(wStream* s, UINT32* fieldFlags, BYTE flags, BYTE fieldBytes)
3143 {
3144 	int i;
3145 	BYTE byte;
3146 
3147 	if (flags & ORDER_ZERO_FIELD_BYTE_BIT0)
3148 		fieldBytes--;
3149 
3150 	if (flags & ORDER_ZERO_FIELD_BYTE_BIT1)
3151 	{
3152 		if (fieldBytes > 1)
3153 			fieldBytes -= 2;
3154 		else
3155 			fieldBytes = 0;
3156 	}
3157 
3158 	if (Stream_GetRemainingLength(s) < fieldBytes)
3159 		return FALSE;
3160 
3161 	*fieldFlags = 0;
3162 
3163 	for (i = 0; i < fieldBytes; i++)
3164 	{
3165 		Stream_Read_UINT8(s, byte);
3166 		*fieldFlags |= byte << (i * 8);
3167 	}
3168 
3169 	return TRUE;
3170 }
update_write_field_flags(wStream * s,UINT32 fieldFlags,BYTE flags,BYTE fieldBytes)3171 BOOL update_write_field_flags(wStream* s, UINT32 fieldFlags, BYTE flags, BYTE fieldBytes)
3172 {
3173 	BYTE byte;
3174 
3175 	if (fieldBytes == 1)
3176 	{
3177 		byte = fieldFlags & 0xFF;
3178 		Stream_Write_UINT8(s, byte);
3179 	}
3180 	else if (fieldBytes == 2)
3181 	{
3182 		byte = fieldFlags & 0xFF;
3183 		Stream_Write_UINT8(s, byte);
3184 		byte = (fieldFlags >> 8) & 0xFF;
3185 		Stream_Write_UINT8(s, byte);
3186 	}
3187 	else if (fieldBytes == 3)
3188 	{
3189 		byte = fieldFlags & 0xFF;
3190 		Stream_Write_UINT8(s, byte);
3191 		byte = (fieldFlags >> 8) & 0xFF;
3192 		Stream_Write_UINT8(s, byte);
3193 		byte = (fieldFlags >> 16) & 0xFF;
3194 		Stream_Write_UINT8(s, byte);
3195 	}
3196 	else
3197 	{
3198 		return FALSE;
3199 	}
3200 
3201 	return TRUE;
3202 }
update_read_bounds(wStream * s,rdpBounds * bounds)3203 static BOOL update_read_bounds(wStream* s, rdpBounds* bounds)
3204 {
3205 	BYTE flags;
3206 
3207 	if (Stream_GetRemainingLength(s) < 1)
3208 		return FALSE;
3209 
3210 	Stream_Read_UINT8(s, flags); /* field flags */
3211 
3212 	if (flags & BOUND_LEFT)
3213 	{
3214 		if (!update_read_coord(s, &bounds->left, FALSE))
3215 			return FALSE;
3216 	}
3217 	else if (flags & BOUND_DELTA_LEFT)
3218 	{
3219 		if (!update_read_coord(s, &bounds->left, TRUE))
3220 			return FALSE;
3221 	}
3222 
3223 	if (flags & BOUND_TOP)
3224 	{
3225 		if (!update_read_coord(s, &bounds->top, FALSE))
3226 			return FALSE;
3227 	}
3228 	else if (flags & BOUND_DELTA_TOP)
3229 	{
3230 		if (!update_read_coord(s, &bounds->top, TRUE))
3231 			return FALSE;
3232 	}
3233 
3234 	if (flags & BOUND_RIGHT)
3235 	{
3236 		if (!update_read_coord(s, &bounds->right, FALSE))
3237 			return FALSE;
3238 	}
3239 	else if (flags & BOUND_DELTA_RIGHT)
3240 	{
3241 		if (!update_read_coord(s, &bounds->right, TRUE))
3242 			return FALSE;
3243 	}
3244 
3245 	if (flags & BOUND_BOTTOM)
3246 	{
3247 		if (!update_read_coord(s, &bounds->bottom, FALSE))
3248 			return FALSE;
3249 	}
3250 	else if (flags & BOUND_DELTA_BOTTOM)
3251 	{
3252 		if (!update_read_coord(s, &bounds->bottom, TRUE))
3253 			return FALSE;
3254 	}
3255 
3256 	return TRUE;
3257 }
update_write_bounds(wStream * s,ORDER_INFO * orderInfo)3258 BOOL update_write_bounds(wStream* s, ORDER_INFO* orderInfo)
3259 {
3260 	if (!(orderInfo->controlFlags & ORDER_BOUNDS))
3261 		return TRUE;
3262 
3263 	if (orderInfo->controlFlags & ORDER_ZERO_BOUNDS_DELTAS)
3264 		return TRUE;
3265 
3266 	Stream_Write_UINT8(s, orderInfo->boundsFlags); /* field flags */
3267 
3268 	if (orderInfo->boundsFlags & BOUND_LEFT)
3269 	{
3270 		if (!update_write_coord(s, orderInfo->bounds.left))
3271 			return FALSE;
3272 	}
3273 	else if (orderInfo->boundsFlags & BOUND_DELTA_LEFT)
3274 	{
3275 	}
3276 
3277 	if (orderInfo->boundsFlags & BOUND_TOP)
3278 	{
3279 		if (!update_write_coord(s, orderInfo->bounds.top))
3280 			return FALSE;
3281 	}
3282 	else if (orderInfo->boundsFlags & BOUND_DELTA_TOP)
3283 	{
3284 	}
3285 
3286 	if (orderInfo->boundsFlags & BOUND_RIGHT)
3287 	{
3288 		if (!update_write_coord(s, orderInfo->bounds.right))
3289 			return FALSE;
3290 	}
3291 	else if (orderInfo->boundsFlags & BOUND_DELTA_RIGHT)
3292 	{
3293 	}
3294 
3295 	if (orderInfo->boundsFlags & BOUND_BOTTOM)
3296 	{
3297 		if (!update_write_coord(s, orderInfo->bounds.bottom))
3298 			return FALSE;
3299 	}
3300 	else if (orderInfo->boundsFlags & BOUND_DELTA_BOTTOM)
3301 	{
3302 	}
3303 
3304 	return TRUE;
3305 }
3306 
read_primary_order(wLog * log,const char * orderName,wStream * s,const ORDER_INFO * orderInfo,rdpPrimaryUpdate * primary)3307 static BOOL read_primary_order(wLog* log, const char* orderName, wStream* s,
3308                                const ORDER_INFO* orderInfo, rdpPrimaryUpdate* primary)
3309 {
3310 	BOOL rc = FALSE;
3311 
3312 	if (!s || !orderInfo || !primary || !orderName)
3313 		return FALSE;
3314 
3315 	switch (orderInfo->orderType)
3316 	{
3317 		case ORDER_TYPE_DSTBLT:
3318 			rc = update_read_dstblt_order(s, orderInfo, &(primary->dstblt));
3319 			break;
3320 
3321 		case ORDER_TYPE_PATBLT:
3322 			rc = update_read_patblt_order(s, orderInfo, &(primary->patblt));
3323 			break;
3324 
3325 		case ORDER_TYPE_SCRBLT:
3326 			rc = update_read_scrblt_order(s, orderInfo, &(primary->scrblt));
3327 			break;
3328 
3329 		case ORDER_TYPE_OPAQUE_RECT:
3330 			rc = update_read_opaque_rect_order(s, orderInfo, &(primary->opaque_rect));
3331 			break;
3332 
3333 		case ORDER_TYPE_DRAW_NINE_GRID:
3334 			rc = update_read_draw_nine_grid_order(s, orderInfo, &(primary->draw_nine_grid));
3335 			break;
3336 
3337 		case ORDER_TYPE_MULTI_DSTBLT:
3338 			rc = update_read_multi_dstblt_order(s, orderInfo, &(primary->multi_dstblt));
3339 			break;
3340 
3341 		case ORDER_TYPE_MULTI_PATBLT:
3342 			rc = update_read_multi_patblt_order(s, orderInfo, &(primary->multi_patblt));
3343 			break;
3344 
3345 		case ORDER_TYPE_MULTI_SCRBLT:
3346 			rc = update_read_multi_scrblt_order(s, orderInfo, &(primary->multi_scrblt));
3347 			break;
3348 
3349 		case ORDER_TYPE_MULTI_OPAQUE_RECT:
3350 			rc = update_read_multi_opaque_rect_order(s, orderInfo, &(primary->multi_opaque_rect));
3351 			break;
3352 
3353 		case ORDER_TYPE_MULTI_DRAW_NINE_GRID:
3354 			rc = update_read_multi_draw_nine_grid_order(s, orderInfo,
3355 			                                            &(primary->multi_draw_nine_grid));
3356 			break;
3357 
3358 		case ORDER_TYPE_LINE_TO:
3359 			rc = update_read_line_to_order(s, orderInfo, &(primary->line_to));
3360 			break;
3361 
3362 		case ORDER_TYPE_POLYLINE:
3363 			rc = update_read_polyline_order(s, orderInfo, &(primary->polyline));
3364 			break;
3365 
3366 		case ORDER_TYPE_MEMBLT:
3367 			rc = update_read_memblt_order(s, orderInfo, &(primary->memblt));
3368 			break;
3369 
3370 		case ORDER_TYPE_MEM3BLT:
3371 			rc = update_read_mem3blt_order(s, orderInfo, &(primary->mem3blt));
3372 			break;
3373 
3374 		case ORDER_TYPE_SAVE_BITMAP:
3375 			rc = update_read_save_bitmap_order(s, orderInfo, &(primary->save_bitmap));
3376 			break;
3377 
3378 		case ORDER_TYPE_GLYPH_INDEX:
3379 			rc = update_read_glyph_index_order(s, orderInfo, &(primary->glyph_index));
3380 			break;
3381 
3382 		case ORDER_TYPE_FAST_INDEX:
3383 			rc = update_read_fast_index_order(s, orderInfo, &(primary->fast_index));
3384 			break;
3385 
3386 		case ORDER_TYPE_FAST_GLYPH:
3387 			rc = update_read_fast_glyph_order(s, orderInfo, &(primary->fast_glyph));
3388 			break;
3389 
3390 		case ORDER_TYPE_POLYGON_SC:
3391 			rc = update_read_polygon_sc_order(s, orderInfo, &(primary->polygon_sc));
3392 			break;
3393 
3394 		case ORDER_TYPE_POLYGON_CB:
3395 			rc = update_read_polygon_cb_order(s, orderInfo, &(primary->polygon_cb));
3396 			break;
3397 
3398 		case ORDER_TYPE_ELLIPSE_SC:
3399 			rc = update_read_ellipse_sc_order(s, orderInfo, &(primary->ellipse_sc));
3400 			break;
3401 
3402 		case ORDER_TYPE_ELLIPSE_CB:
3403 			rc = update_read_ellipse_cb_order(s, orderInfo, &(primary->ellipse_cb));
3404 			break;
3405 
3406 		default:
3407 			WLog_Print(log, WLOG_WARN, "Primary Drawing Order %s not supported, ignoring",
3408 			           orderName);
3409 			rc = TRUE;
3410 			break;
3411 	}
3412 
3413 	if (!rc)
3414 	{
3415 		WLog_Print(log, WLOG_ERROR, "%s - update_read_dstblt_order() failed", orderName);
3416 		return FALSE;
3417 	}
3418 
3419 	return TRUE;
3420 }
3421 
update_recv_primary_order(rdpUpdate * update,wStream * s,BYTE flags)3422 static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags)
3423 {
3424 	BYTE field;
3425 	BOOL rc = FALSE;
3426 	rdpContext* context = update->context;
3427 	rdpPrimaryUpdate* primary = update->primary;
3428 	ORDER_INFO* orderInfo = &(primary->order_info);
3429 	rdpSettings* settings = context->settings;
3430 	const char* orderName;
3431 
3432 	if (flags & ORDER_TYPE_CHANGE)
3433 	{
3434 		if (Stream_GetRemainingLength(s) < 1)
3435 		{
3436 			WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) < 1");
3437 			return FALSE;
3438 		}
3439 
3440 		Stream_Read_UINT8(s, orderInfo->orderType); /* orderType (1 byte) */
3441 	}
3442 
3443 	orderName = primary_order_string(orderInfo->orderType);
3444 	WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3445 
3446 	if (!check_primary_order_supported(update->log, settings, orderInfo->orderType, orderName))
3447 		return FALSE;
3448 
3449 	field = get_primary_drawing_order_field_bytes(orderInfo->orderType, &rc);
3450 	if (!rc)
3451 		return FALSE;
3452 
3453 	if (!update_read_field_flags(s, &(orderInfo->fieldFlags), flags, field))
3454 	{
3455 		WLog_Print(update->log, WLOG_ERROR, "update_read_field_flags() failed");
3456 		return FALSE;
3457 	}
3458 
3459 	if (flags & ORDER_BOUNDS)
3460 	{
3461 		if (!(flags & ORDER_ZERO_BOUNDS_DELTAS))
3462 		{
3463 			if (!update_read_bounds(s, &orderInfo->bounds))
3464 			{
3465 				WLog_Print(update->log, WLOG_ERROR, "update_read_bounds() failed");
3466 				return FALSE;
3467 			}
3468 		}
3469 
3470 		rc = IFCALLRESULT(FALSE, update->SetBounds, context, &orderInfo->bounds);
3471 
3472 		if (!rc)
3473 			return FALSE;
3474 	}
3475 
3476 	orderInfo->deltaCoordinates = (flags & ORDER_DELTA_COORDINATES) ? TRUE : FALSE;
3477 
3478 	if (!read_primary_order(update->log, orderName, s, orderInfo, primary))
3479 		return FALSE;
3480 
3481 	rc = IFCALLRESULT(TRUE, primary->OrderInfo, context, orderInfo, orderName);
3482 	if (!rc)
3483 		return FALSE;
3484 
3485 	switch (orderInfo->orderType)
3486 	{
3487 		case ORDER_TYPE_DSTBLT:
3488 		{
3489 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3490 			           orderName, gdi_rop3_code_string(primary->dstblt.bRop),
3491 			           gdi_rop3_code(primary->dstblt.bRop));
3492 			rc = IFCALLRESULT(FALSE, primary->DstBlt, context, &primary->dstblt);
3493 		}
3494 		break;
3495 
3496 		case ORDER_TYPE_PATBLT:
3497 		{
3498 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3499 			           orderName, gdi_rop3_code_string(primary->patblt.bRop),
3500 			           gdi_rop3_code(primary->patblt.bRop));
3501 			rc = IFCALLRESULT(FALSE, primary->PatBlt, context, &primary->patblt);
3502 		}
3503 		break;
3504 
3505 		case ORDER_TYPE_SCRBLT:
3506 		{
3507 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3508 			           orderName, gdi_rop3_code_string(primary->scrblt.bRop),
3509 			           gdi_rop3_code(primary->scrblt.bRop));
3510 			rc = IFCALLRESULT(FALSE, primary->ScrBlt, context, &primary->scrblt);
3511 		}
3512 		break;
3513 
3514 		case ORDER_TYPE_OPAQUE_RECT:
3515 		{
3516 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3517 			rc = IFCALLRESULT(FALSE, primary->OpaqueRect, context, &primary->opaque_rect);
3518 		}
3519 		break;
3520 
3521 		case ORDER_TYPE_DRAW_NINE_GRID:
3522 		{
3523 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3524 			rc = IFCALLRESULT(FALSE, primary->DrawNineGrid, context, &primary->draw_nine_grid);
3525 		}
3526 		break;
3527 
3528 		case ORDER_TYPE_MULTI_DSTBLT:
3529 		{
3530 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3531 			           orderName, gdi_rop3_code_string(primary->multi_dstblt.bRop),
3532 			           gdi_rop3_code(primary->multi_dstblt.bRop));
3533 			rc = IFCALLRESULT(FALSE, primary->MultiDstBlt, context, &primary->multi_dstblt);
3534 		}
3535 		break;
3536 
3537 		case ORDER_TYPE_MULTI_PATBLT:
3538 		{
3539 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3540 			           orderName, gdi_rop3_code_string(primary->multi_patblt.bRop),
3541 			           gdi_rop3_code(primary->multi_patblt.bRop));
3542 			rc = IFCALLRESULT(FALSE, primary->MultiPatBlt, context, &primary->multi_patblt);
3543 		}
3544 		break;
3545 
3546 		case ORDER_TYPE_MULTI_SCRBLT:
3547 		{
3548 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3549 			           orderName, gdi_rop3_code_string(primary->multi_scrblt.bRop),
3550 			           gdi_rop3_code(primary->multi_scrblt.bRop));
3551 			rc = IFCALLRESULT(FALSE, primary->MultiScrBlt, context, &primary->multi_scrblt);
3552 		}
3553 		break;
3554 
3555 		case ORDER_TYPE_MULTI_OPAQUE_RECT:
3556 		{
3557 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3558 			rc =
3559 			    IFCALLRESULT(FALSE, primary->MultiOpaqueRect, context, &primary->multi_opaque_rect);
3560 		}
3561 		break;
3562 
3563 		case ORDER_TYPE_MULTI_DRAW_NINE_GRID:
3564 		{
3565 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3566 			rc = IFCALLRESULT(FALSE, primary->MultiDrawNineGrid, context,
3567 			                  &primary->multi_draw_nine_grid);
3568 		}
3569 		break;
3570 
3571 		case ORDER_TYPE_LINE_TO:
3572 		{
3573 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3574 			rc = IFCALLRESULT(FALSE, primary->LineTo, context, &primary->line_to);
3575 		}
3576 		break;
3577 
3578 		case ORDER_TYPE_POLYLINE:
3579 		{
3580 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3581 			rc = IFCALLRESULT(FALSE, primary->Polyline, context, &primary->polyline);
3582 		}
3583 		break;
3584 
3585 		case ORDER_TYPE_MEMBLT:
3586 		{
3587 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3588 			           orderName, gdi_rop3_code_string(primary->memblt.bRop),
3589 			           gdi_rop3_code(primary->memblt.bRop));
3590 			rc = IFCALLRESULT(FALSE, primary->MemBlt, context, &primary->memblt);
3591 		}
3592 		break;
3593 
3594 		case ORDER_TYPE_MEM3BLT:
3595 		{
3596 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3597 			           orderName, gdi_rop3_code_string(primary->mem3blt.bRop),
3598 			           gdi_rop3_code(primary->mem3blt.bRop));
3599 			rc = IFCALLRESULT(FALSE, primary->Mem3Blt, context, &primary->mem3blt);
3600 		}
3601 		break;
3602 
3603 		case ORDER_TYPE_SAVE_BITMAP:
3604 		{
3605 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3606 			rc = IFCALLRESULT(FALSE, primary->SaveBitmap, context, &primary->save_bitmap);
3607 		}
3608 		break;
3609 
3610 		case ORDER_TYPE_GLYPH_INDEX:
3611 		{
3612 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3613 			rc = IFCALLRESULT(FALSE, primary->GlyphIndex, context, &primary->glyph_index);
3614 		}
3615 		break;
3616 
3617 		case ORDER_TYPE_FAST_INDEX:
3618 		{
3619 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3620 			rc = IFCALLRESULT(FALSE, primary->FastIndex, context, &primary->fast_index);
3621 		}
3622 		break;
3623 
3624 		case ORDER_TYPE_FAST_GLYPH:
3625 		{
3626 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3627 			rc = IFCALLRESULT(FALSE, primary->FastGlyph, context, &primary->fast_glyph);
3628 		}
3629 		break;
3630 
3631 		case ORDER_TYPE_POLYGON_SC:
3632 		{
3633 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3634 			rc = IFCALLRESULT(FALSE, primary->PolygonSC, context, &primary->polygon_sc);
3635 		}
3636 		break;
3637 
3638 		case ORDER_TYPE_POLYGON_CB:
3639 		{
3640 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3641 			rc = IFCALLRESULT(FALSE, primary->PolygonCB, context, &primary->polygon_cb);
3642 		}
3643 		break;
3644 
3645 		case ORDER_TYPE_ELLIPSE_SC:
3646 		{
3647 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3648 			rc = IFCALLRESULT(FALSE, primary->EllipseSC, context, &primary->ellipse_sc);
3649 		}
3650 		break;
3651 
3652 		case ORDER_TYPE_ELLIPSE_CB:
3653 		{
3654 			WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3655 			rc = IFCALLRESULT(FALSE, primary->EllipseCB, context, &primary->ellipse_cb);
3656 		}
3657 		break;
3658 
3659 		default:
3660 			WLog_Print(update->log, WLOG_WARN, "Primary Drawing Order %s not supported", orderName);
3661 			break;
3662 	}
3663 
3664 	if (!rc)
3665 	{
3666 		WLog_Print(update->log, WLOG_WARN, "Primary Drawing Order %s failed", orderName);
3667 		return FALSE;
3668 	}
3669 
3670 	if (flags & ORDER_BOUNDS)
3671 	{
3672 		rc = IFCALLRESULT(FALSE, update->SetBounds, context, NULL);
3673 	}
3674 
3675 	return rc;
3676 }
3677 
update_recv_secondary_order(rdpUpdate * update,wStream * s,BYTE flags)3678 static BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s, BYTE flags)
3679 {
3680 	BOOL rc = FALSE;
3681 	size_t start, end, pos, diff;
3682 	BYTE orderType;
3683 	UINT16 extraFlags;
3684 	UINT16 orderLength;
3685 	rdpContext* context = update->context;
3686 	rdpSettings* settings = context->settings;
3687 	rdpSecondaryUpdate* secondary = update->secondary;
3688 	const char* name;
3689 
3690 	if (Stream_GetRemainingLength(s) < 5)
3691 	{
3692 		WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) < 5");
3693 		return FALSE;
3694 	}
3695 
3696 	Stream_Read_UINT16(s, orderLength); /* orderLength (2 bytes) */
3697 	Stream_Read_UINT16(s, extraFlags);  /* extraFlags (2 bytes) */
3698 	Stream_Read_UINT8(s, orderType);    /* orderType (1 byte) */
3699 
3700 	start = Stream_GetPosition(s);
3701 	name = secondary_order_string(orderType);
3702 	WLog_Print(update->log, WLOG_DEBUG, "Secondary Drawing Order %s", name);
3703 	rc = IFCALLRESULT(TRUE, secondary->CacheOrderInfo, context, orderLength, extraFlags, orderType,
3704 	                  name);
3705 	if (!rc)
3706 		return FALSE;
3707 
3708 	/*
3709 	 * According to [MS-RDPEGDI] 2.2.2.2.1.2.1.1 the order length must be increased by 13 bytes
3710 	 * including the header. As we already read the header 7 left
3711 	 */
3712 	if (Stream_GetRemainingLength(s) < orderLength + 7U)
3713 	{
3714 		WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) %" PRIuz " < %" PRIu16,
3715 		           Stream_GetRemainingLength(s), orderLength + 7);
3716 		return FALSE;
3717 	}
3718 
3719 	if (!check_secondary_order_supported(update->log, settings, orderType, name))
3720 		return FALSE;
3721 
3722 	switch (orderType)
3723 	{
3724 		case ORDER_TYPE_BITMAP_UNCOMPRESSED:
3725 		case ORDER_TYPE_CACHE_BITMAP_COMPRESSED:
3726 		{
3727 			const BOOL compressed = (orderType == ORDER_TYPE_CACHE_BITMAP_COMPRESSED);
3728 			CACHE_BITMAP_ORDER* order =
3729 			    update_read_cache_bitmap_order(update, s, compressed, extraFlags);
3730 
3731 			if (order)
3732 			{
3733 				rc = IFCALLRESULT(FALSE, secondary->CacheBitmap, context, order);
3734 				free_cache_bitmap_order(context, order);
3735 			}
3736 		}
3737 		break;
3738 
3739 		case ORDER_TYPE_BITMAP_UNCOMPRESSED_V2:
3740 		case ORDER_TYPE_BITMAP_COMPRESSED_V2:
3741 		{
3742 			const BOOL compressed = (orderType == ORDER_TYPE_BITMAP_COMPRESSED_V2);
3743 			CACHE_BITMAP_V2_ORDER* order =
3744 			    update_read_cache_bitmap_v2_order(update, s, compressed, extraFlags);
3745 
3746 			if (order)
3747 			{
3748 				rc = IFCALLRESULT(FALSE, secondary->CacheBitmapV2, context, order);
3749 				free_cache_bitmap_v2_order(context, order);
3750 			}
3751 		}
3752 		break;
3753 
3754 		case ORDER_TYPE_BITMAP_COMPRESSED_V3:
3755 		{
3756 			CACHE_BITMAP_V3_ORDER* order = update_read_cache_bitmap_v3_order(update, s, extraFlags);
3757 
3758 			if (order)
3759 			{
3760 				rc = IFCALLRESULT(FALSE, secondary->CacheBitmapV3, context, order);
3761 				free_cache_bitmap_v3_order(context, order);
3762 			}
3763 		}
3764 		break;
3765 
3766 		case ORDER_TYPE_CACHE_COLOR_TABLE:
3767 		{
3768 			CACHE_COLOR_TABLE_ORDER* order =
3769 			    update_read_cache_color_table_order(update, s, extraFlags);
3770 
3771 			if (order)
3772 			{
3773 				rc = IFCALLRESULT(FALSE, secondary->CacheColorTable, context, order);
3774 				free_cache_color_table_order(context, order);
3775 			}
3776 		}
3777 		break;
3778 
3779 		case ORDER_TYPE_CACHE_GLYPH:
3780 		{
3781 			switch (settings->GlyphSupportLevel)
3782 			{
3783 				case GLYPH_SUPPORT_PARTIAL:
3784 				case GLYPH_SUPPORT_FULL:
3785 				{
3786 					CACHE_GLYPH_ORDER* order = update_read_cache_glyph_order(update, s, extraFlags);
3787 
3788 					if (order)
3789 					{
3790 						rc = IFCALLRESULT(FALSE, secondary->CacheGlyph, context, order);
3791 						free_cache_glyph_order(context, order);
3792 					}
3793 				}
3794 				break;
3795 
3796 				case GLYPH_SUPPORT_ENCODE:
3797 				{
3798 					CACHE_GLYPH_V2_ORDER* order =
3799 					    update_read_cache_glyph_v2_order(update, s, extraFlags);
3800 
3801 					if (order)
3802 					{
3803 						rc = IFCALLRESULT(FALSE, secondary->CacheGlyphV2, context, order);
3804 						free_cache_glyph_v2_order(context, order);
3805 					}
3806 				}
3807 				break;
3808 
3809 				case GLYPH_SUPPORT_NONE:
3810 				default:
3811 					break;
3812 			}
3813 		}
3814 		break;
3815 
3816 		case ORDER_TYPE_CACHE_BRUSH:
3817 			/* [MS-RDPEGDI] 2.2.2.2.1.2.7 Cache Brush (CACHE_BRUSH_ORDER) */
3818 			{
3819 				CACHE_BRUSH_ORDER* order = update_read_cache_brush_order(update, s, extraFlags);
3820 
3821 				if (order)
3822 				{
3823 					rc = IFCALLRESULT(FALSE, secondary->CacheBrush, context, order);
3824 					free_cache_brush_order(context, order);
3825 				}
3826 			}
3827 			break;
3828 
3829 		default:
3830 			WLog_Print(update->log, WLOG_WARN, "SECONDARY ORDER %s not supported", name);
3831 			break;
3832 	}
3833 
3834 	if (!rc)
3835 	{
3836 		WLog_Print(update->log, WLOG_ERROR, "SECONDARY ORDER %s failed", name);
3837 	}
3838 
3839 	end = start + orderLength + 7;
3840 	pos = Stream_GetPosition(s);
3841 	if (pos > end)
3842 	{
3843 		WLog_Print(update->log, WLOG_WARN, "SECONDARY_ORDER %s: read %" PRIuz "bytes too much",
3844 		           name, pos - end);
3845 		return FALSE;
3846 	}
3847 	diff = end - pos;
3848 	if (diff > 0)
3849 	{
3850 		WLog_Print(update->log, WLOG_DEBUG,
3851 		           "SECONDARY_ORDER %s: read %" PRIuz "bytes short, skipping", name, diff);
3852 		if (!Stream_SafeSeek(s, diff))
3853 			return FALSE;
3854 	}
3855 	return rc;
3856 }
3857 
read_altsec_order(wStream * s,BYTE orderType,rdpAltSecUpdate * altsec)3858 static BOOL read_altsec_order(wStream* s, BYTE orderType, rdpAltSecUpdate* altsec)
3859 {
3860 	BOOL rc = FALSE;
3861 
3862 	switch (orderType)
3863 	{
3864 		case ORDER_TYPE_CREATE_OFFSCREEN_BITMAP:
3865 			rc = update_read_create_offscreen_bitmap_order(s, &(altsec->create_offscreen_bitmap));
3866 			break;
3867 
3868 		case ORDER_TYPE_SWITCH_SURFACE:
3869 			rc = update_read_switch_surface_order(s, &(altsec->switch_surface));
3870 			break;
3871 
3872 		case ORDER_TYPE_CREATE_NINE_GRID_BITMAP:
3873 			rc = update_read_create_nine_grid_bitmap_order(s, &(altsec->create_nine_grid_bitmap));
3874 			break;
3875 
3876 		case ORDER_TYPE_FRAME_MARKER:
3877 			rc = update_read_frame_marker_order(s, &(altsec->frame_marker));
3878 			break;
3879 
3880 		case ORDER_TYPE_STREAM_BITMAP_FIRST:
3881 			rc = update_read_stream_bitmap_first_order(s, &(altsec->stream_bitmap_first));
3882 			break;
3883 
3884 		case ORDER_TYPE_STREAM_BITMAP_NEXT:
3885 			rc = update_read_stream_bitmap_next_order(s, &(altsec->stream_bitmap_next));
3886 			break;
3887 
3888 		case ORDER_TYPE_GDIPLUS_FIRST:
3889 			rc = update_read_draw_gdiplus_first_order(s, &(altsec->draw_gdiplus_first));
3890 			break;
3891 
3892 		case ORDER_TYPE_GDIPLUS_NEXT:
3893 			rc = update_read_draw_gdiplus_next_order(s, &(altsec->draw_gdiplus_next));
3894 			break;
3895 
3896 		case ORDER_TYPE_GDIPLUS_END:
3897 			rc = update_read_draw_gdiplus_end_order(s, &(altsec->draw_gdiplus_end));
3898 			break;
3899 
3900 		case ORDER_TYPE_GDIPLUS_CACHE_FIRST:
3901 			rc = update_read_draw_gdiplus_cache_first_order(s, &(altsec->draw_gdiplus_cache_first));
3902 			break;
3903 
3904 		case ORDER_TYPE_GDIPLUS_CACHE_NEXT:
3905 			rc = update_read_draw_gdiplus_cache_next_order(s, &(altsec->draw_gdiplus_cache_next));
3906 			break;
3907 
3908 		case ORDER_TYPE_GDIPLUS_CACHE_END:
3909 			rc = update_read_draw_gdiplus_cache_end_order(s, &(altsec->draw_gdiplus_cache_end));
3910 			break;
3911 
3912 		case ORDER_TYPE_WINDOW:
3913 			/* This order is handled elsewhere. */
3914 			rc = TRUE;
3915 			break;
3916 
3917 		case ORDER_TYPE_COMPDESK_FIRST:
3918 			rc = TRUE;
3919 			break;
3920 
3921 		default:
3922 			break;
3923 	}
3924 
3925 	return rc;
3926 }
3927 
update_recv_altsec_order(rdpUpdate * update,wStream * s,BYTE flags)3928 static BOOL update_recv_altsec_order(rdpUpdate* update, wStream* s, BYTE flags)
3929 {
3930 	BYTE orderType = flags >>= 2; /* orderType is in higher 6 bits of flags field */
3931 	BOOL rc = FALSE;
3932 	rdpContext* context = update->context;
3933 	rdpSettings* settings = context->settings;
3934 	rdpAltSecUpdate* altsec = update->altsec;
3935 	const char* orderName = altsec_order_string(orderType);
3936 	WLog_Print(update->log, WLOG_DEBUG, "Alternate Secondary Drawing Order %s", orderName);
3937 
3938 	rc = IFCALLRESULT(TRUE, altsec->DrawOrderInfo, context, orderType, orderName);
3939 	if (!rc)
3940 		return FALSE;
3941 
3942 	if (!check_alt_order_supported(update->log, settings, orderType, orderName))
3943 		return FALSE;
3944 
3945 	if (!read_altsec_order(s, orderType, altsec))
3946 		return FALSE;
3947 
3948 	switch (orderType)
3949 	{
3950 		case ORDER_TYPE_CREATE_OFFSCREEN_BITMAP:
3951 			IFCALLRET(altsec->CreateOffscreenBitmap, rc, context,
3952 			          &(altsec->create_offscreen_bitmap));
3953 			break;
3954 
3955 		case ORDER_TYPE_SWITCH_SURFACE:
3956 			IFCALLRET(altsec->SwitchSurface, rc, context, &(altsec->switch_surface));
3957 			break;
3958 
3959 		case ORDER_TYPE_CREATE_NINE_GRID_BITMAP:
3960 			IFCALLRET(altsec->CreateNineGridBitmap, rc, context,
3961 			          &(altsec->create_nine_grid_bitmap));
3962 			break;
3963 
3964 		case ORDER_TYPE_FRAME_MARKER:
3965 			IFCALLRET(altsec->FrameMarker, rc, context, &(altsec->frame_marker));
3966 			break;
3967 
3968 		case ORDER_TYPE_STREAM_BITMAP_FIRST:
3969 			IFCALLRET(altsec->StreamBitmapFirst, rc, context, &(altsec->stream_bitmap_first));
3970 			break;
3971 
3972 		case ORDER_TYPE_STREAM_BITMAP_NEXT:
3973 			IFCALLRET(altsec->StreamBitmapNext, rc, context, &(altsec->stream_bitmap_next));
3974 			break;
3975 
3976 		case ORDER_TYPE_GDIPLUS_FIRST:
3977 			IFCALLRET(altsec->DrawGdiPlusFirst, rc, context, &(altsec->draw_gdiplus_first));
3978 			break;
3979 
3980 		case ORDER_TYPE_GDIPLUS_NEXT:
3981 			IFCALLRET(altsec->DrawGdiPlusNext, rc, context, &(altsec->draw_gdiplus_next));
3982 			break;
3983 
3984 		case ORDER_TYPE_GDIPLUS_END:
3985 			IFCALLRET(altsec->DrawGdiPlusEnd, rc, context, &(altsec->draw_gdiplus_end));
3986 			break;
3987 
3988 		case ORDER_TYPE_GDIPLUS_CACHE_FIRST:
3989 			IFCALLRET(altsec->DrawGdiPlusCacheFirst, rc, context,
3990 			          &(altsec->draw_gdiplus_cache_first));
3991 			break;
3992 
3993 		case ORDER_TYPE_GDIPLUS_CACHE_NEXT:
3994 			IFCALLRET(altsec->DrawGdiPlusCacheNext, rc, context,
3995 			          &(altsec->draw_gdiplus_cache_next));
3996 			break;
3997 
3998 		case ORDER_TYPE_GDIPLUS_CACHE_END:
3999 			IFCALLRET(altsec->DrawGdiPlusCacheEnd, rc, context, &(altsec->draw_gdiplus_cache_end));
4000 			break;
4001 
4002 		case ORDER_TYPE_WINDOW:
4003 			rc = update_recv_altsec_window_order(update, s);
4004 			break;
4005 
4006 		case ORDER_TYPE_COMPDESK_FIRST:
4007 			rc = TRUE;
4008 			break;
4009 
4010 		default:
4011 			break;
4012 	}
4013 
4014 	if (!rc)
4015 	{
4016 		WLog_Print(update->log, WLOG_WARN, "Alternate Secondary Drawing Order %s failed",
4017 		           orderName);
4018 	}
4019 
4020 	return rc;
4021 }
update_recv_order(rdpUpdate * update,wStream * s)4022 BOOL update_recv_order(rdpUpdate* update, wStream* s)
4023 {
4024 	BOOL rc;
4025 	BYTE controlFlags;
4026 
4027 	if (Stream_GetRemainingLength(s) < 1)
4028 	{
4029 		WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) < 1");
4030 		return FALSE;
4031 	}
4032 
4033 	Stream_Read_UINT8(s, controlFlags); /* controlFlags (1 byte) */
4034 
4035 	if (!(controlFlags & ORDER_STANDARD))
4036 		rc = update_recv_altsec_order(update, s, controlFlags);
4037 	else if (controlFlags & ORDER_SECONDARY)
4038 		rc = update_recv_secondary_order(update, s, controlFlags);
4039 	else
4040 		rc = update_recv_primary_order(update, s, controlFlags);
4041 
4042 	if (!rc)
4043 		WLog_Print(update->log, WLOG_ERROR, "order flags %02" PRIx8 " failed", controlFlags);
4044 
4045 	return rc;
4046 }
4047