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