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