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