Coverage Report

Created: 2024-05-21 06:32

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