FreeRDP
update.c
1 
22 #include <freerdp/config.h>
23 
24 #include <winpr/crt.h>
25 #include <winpr/print.h>
26 #include <winpr/synch.h>
27 #include <winpr/thread.h>
28 #include <winpr/collections.h>
29 
30 #include "settings.h"
31 #include "update.h"
32 #include "surface.h"
33 #include "message.h"
34 #include "info.h"
35 #include "window.h"
36 
37 #include <freerdp/log.h>
38 #include <freerdp/peer.h>
39 #include <freerdp/codec/bitmap.h>
40 
41 #include "../cache/pointer.h"
42 #include "../cache/palette.h"
43 #include "../cache/bitmap.h"
44 
45 #define TAG FREERDP_TAG("core.update")
46 
47 #define FORCE_ASYNC_UPDATE_OFF
48 
49 static const char* const UPDATE_TYPE_STRINGS[] = { "Orders", "Bitmap", "Palette", "Synchronize" };
50 
51 static const char* update_type_to_string(UINT16 updateType)
52 {
53  if (updateType >= ARRAYSIZE(UPDATE_TYPE_STRINGS))
54  return "UNKNOWN";
55 
56  return UPDATE_TYPE_STRINGS[updateType];
57 }
58 
59 static BOOL update_recv_orders(rdpUpdate* update, wStream* s)
60 {
61  UINT16 numberOrders = 0;
62 
63  WINPR_ASSERT(update);
64 
65  if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
66  return FALSE;
67 
68  Stream_Seek_UINT16(s); /* pad2OctetsA (2 bytes) */
69  Stream_Read_UINT16(s, numberOrders); /* numberOrders (2 bytes) */
70  Stream_Seek_UINT16(s); /* pad2OctetsB (2 bytes) */
71 
72  while (numberOrders > 0)
73  {
74  if (!update_recv_order(update, s))
75  {
76  WLog_ERR(TAG, "update_recv_order() failed");
77  return FALSE;
78  }
79 
80  numberOrders--;
81  }
82 
83  return TRUE;
84 }
85 
86 static BOOL update_read_bitmap_data(rdpUpdate* update, wStream* s, BITMAP_DATA* bitmapData)
87 {
88  WINPR_UNUSED(update);
89  WINPR_ASSERT(bitmapData);
90 
91  if (!Stream_CheckAndLogRequiredLength(TAG, s, 18))
92  return FALSE;
93 
94  Stream_Read_UINT16(s, bitmapData->destLeft);
95  Stream_Read_UINT16(s, bitmapData->destTop);
96  Stream_Read_UINT16(s, bitmapData->destRight);
97  Stream_Read_UINT16(s, bitmapData->destBottom);
98  Stream_Read_UINT16(s, bitmapData->width);
99  Stream_Read_UINT16(s, bitmapData->height);
100  Stream_Read_UINT16(s, bitmapData->bitsPerPixel);
101  Stream_Read_UINT16(s, bitmapData->flags);
102  Stream_Read_UINT16(s, bitmapData->bitmapLength);
103 
104  if ((bitmapData->width == 0) || (bitmapData->height == 0))
105  {
106  WLog_ERR(TAG, "Invalid BITMAP_DATA: width=%" PRIu16 ", height=%" PRIu16, bitmapData->width,
107  bitmapData->height);
108  return FALSE;
109  }
110 
111  if (bitmapData->flags & BITMAP_COMPRESSION)
112  {
113  if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR))
114  {
115  if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
116  return FALSE;
117 
118  Stream_Read_UINT16(s,
119  bitmapData->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */
120  Stream_Read_UINT16(s,
121  bitmapData->cbCompMainBodySize); /* cbCompMainBodySize (2 bytes) */
122  Stream_Read_UINT16(s, bitmapData->cbScanWidth); /* cbScanWidth (2 bytes) */
123  Stream_Read_UINT16(s,
124  bitmapData->cbUncompressedSize); /* cbUncompressedSize (2 bytes) */
125  bitmapData->bitmapLength = bitmapData->cbCompMainBodySize;
126  }
127 
128  bitmapData->compressed = TRUE;
129  }
130  else
131  bitmapData->compressed = FALSE;
132 
133  if (!Stream_CheckAndLogRequiredLength(TAG, s, bitmapData->bitmapLength))
134  return FALSE;
135 
136  if (bitmapData->bitmapLength > 0)
137  {
138  bitmapData->bitmapDataStream = malloc(bitmapData->bitmapLength);
139 
140  if (!bitmapData->bitmapDataStream)
141  return FALSE;
142 
143  memcpy(bitmapData->bitmapDataStream, Stream_ConstPointer(s), bitmapData->bitmapLength);
144  Stream_Seek(s, bitmapData->bitmapLength);
145  }
146 
147  return TRUE;
148 }
149 
150 static BOOL update_write_bitmap_data(rdpUpdate* update_pub, wStream* s, BITMAP_DATA* bitmapData)
151 {
152  rdp_update_internal* update = update_cast(update_pub);
153 
154  WINPR_ASSERT(bitmapData);
155 
156  if (!Stream_EnsureRemainingCapacity(s, 64 + bitmapData->bitmapLength))
157  return FALSE;
158 
159  if (update->common.autoCalculateBitmapData)
160  {
161  bitmapData->flags = 0;
162  bitmapData->cbCompFirstRowSize = 0;
163 
164  if (bitmapData->compressed)
165  bitmapData->flags |= BITMAP_COMPRESSION;
166 
167  if (update->common.context->settings->NoBitmapCompressionHeader)
168  {
169  bitmapData->flags |= NO_BITMAP_COMPRESSION_HDR;
170  bitmapData->cbCompMainBodySize = bitmapData->bitmapLength;
171  }
172  }
173 
174  Stream_Write_UINT16(s, bitmapData->destLeft);
175  Stream_Write_UINT16(s, bitmapData->destTop);
176  Stream_Write_UINT16(s, bitmapData->destRight);
177  Stream_Write_UINT16(s, bitmapData->destBottom);
178  Stream_Write_UINT16(s, bitmapData->width);
179  Stream_Write_UINT16(s, bitmapData->height);
180  Stream_Write_UINT16(s, bitmapData->bitsPerPixel);
181  Stream_Write_UINT16(s, bitmapData->flags);
182  Stream_Write_UINT16(s, bitmapData->bitmapLength);
183 
184  if (bitmapData->flags & BITMAP_COMPRESSION)
185  {
186  if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR))
187  {
188  Stream_Write_UINT16(s,
189  bitmapData->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */
190  Stream_Write_UINT16(s,
191  bitmapData->cbCompMainBodySize); /* cbCompMainBodySize (2 bytes) */
192  Stream_Write_UINT16(s, bitmapData->cbScanWidth); /* cbScanWidth (2 bytes) */
193  Stream_Write_UINT16(s,
194  bitmapData->cbUncompressedSize); /* cbUncompressedSize (2 bytes) */
195  }
196 
197  Stream_Write(s, bitmapData->bitmapDataStream, bitmapData->bitmapLength);
198  }
199  else
200  {
201  Stream_Write(s, bitmapData->bitmapDataStream, bitmapData->bitmapLength);
202  }
203 
204  return TRUE;
205 }
206 
207 BITMAP_UPDATE* update_read_bitmap_update(rdpUpdate* update, wStream* s)
208 {
209  BITMAP_UPDATE* bitmapUpdate = calloc(1, sizeof(BITMAP_UPDATE));
210  rdp_update_internal* up = update_cast(update);
211 
212  if (!bitmapUpdate)
213  goto fail;
214 
215  if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
216  goto fail;
217 
218  Stream_Read_UINT16(s, bitmapUpdate->number); /* numberRectangles (2 bytes) */
219  WLog_Print(up->log, WLOG_TRACE, "BitmapUpdate: %" PRIu32 "", bitmapUpdate->number);
220 
221  bitmapUpdate->rectangles = (BITMAP_DATA*)calloc(bitmapUpdate->number, sizeof(BITMAP_DATA));
222 
223  if (!bitmapUpdate->rectangles)
224  goto fail;
225 
226  /* rectangles */
227  for (UINT32 i = 0; i < bitmapUpdate->number; i++)
228  {
229  if (!update_read_bitmap_data(update, s, &bitmapUpdate->rectangles[i]))
230  goto fail;
231  }
232 
233  return bitmapUpdate;
234 fail:
235  WINPR_PRAGMA_DIAG_PUSH
236  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
237  free_bitmap_update(update->context, bitmapUpdate);
238  WINPR_PRAGMA_DIAG_POP
239  return NULL;
240 }
241 
242 static BOOL update_write_bitmap_update(rdpUpdate* update, wStream* s,
243  const BITMAP_UPDATE* bitmapUpdate)
244 {
245  WINPR_ASSERT(update);
246  WINPR_ASSERT(bitmapUpdate);
247 
248  if (!Stream_EnsureRemainingCapacity(s, 32))
249  return FALSE;
250 
251  Stream_Write_UINT16(s, UPDATE_TYPE_BITMAP); /* updateType */
252  Stream_Write_UINT16(s, bitmapUpdate->number); /* numberRectangles (2 bytes) */
253 
254  /* rectangles */
255  for (UINT32 i = 0; i < bitmapUpdate->number; i++)
256  {
257  if (!update_write_bitmap_data(update, s, &bitmapUpdate->rectangles[i]))
258  return FALSE;
259  }
260 
261  return TRUE;
262 }
263 
264 PALETTE_UPDATE* update_read_palette(rdpUpdate* update, wStream* s)
265 {
266  PALETTE_UPDATE* palette_update = calloc(1, sizeof(PALETTE_UPDATE));
267 
268  if (!palette_update)
269  goto fail;
270 
271  if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
272  goto fail;
273 
274  Stream_Seek_UINT16(s); /* pad2Octets (2 bytes) */
275  Stream_Read_UINT32(s, palette_update->number); /* numberColors (4 bytes), must be set to 256 */
276 
277  if (palette_update->number > 256)
278  palette_update->number = 256;
279 
280  if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, palette_update->number, 3ull))
281  goto fail;
282 
283  /* paletteEntries */
284  for (UINT32 i = 0; i < palette_update->number; i++)
285  {
286  PALETTE_ENTRY* entry = &palette_update->entries[i];
287  Stream_Read_UINT8(s, entry->red);
288  Stream_Read_UINT8(s, entry->green);
289  Stream_Read_UINT8(s, entry->blue);
290  }
291 
292  return palette_update;
293 fail:
294  WINPR_PRAGMA_DIAG_PUSH
295  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
296  free_palette_update(update->context, palette_update);
297  WINPR_PRAGMA_DIAG_POP
298  return NULL;
299 }
300 
301 static BOOL update_read_synchronize(rdpUpdate* update, wStream* s)
302 {
303  WINPR_UNUSED(update);
304  return Stream_SafeSeek(s, 2); /* pad2Octets (2 bytes) */
309 }
310 
311 static BOOL update_read_play_sound(wStream* s, PLAY_SOUND_UPDATE* play_sound)
312 {
313  WINPR_ASSERT(play_sound);
314 
315  if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
316  return FALSE;
317 
318  Stream_Read_UINT32(s, play_sound->duration); /* duration (4 bytes) */
319  Stream_Read_UINT32(s, play_sound->frequency); /* frequency (4 bytes) */
320  return TRUE;
321 }
322 
323 BOOL update_recv_play_sound(rdpUpdate* update, wStream* s)
324 {
325  PLAY_SOUND_UPDATE play_sound = { 0 };
326 
327  WINPR_ASSERT(update);
328 
329  if (!update_read_play_sound(s, &play_sound))
330  return FALSE;
331 
332  return IFCALLRESULT(FALSE, update->PlaySound, update->context, &play_sound);
333 }
334 
335 POINTER_POSITION_UPDATE* update_read_pointer_position(rdpUpdate* update, wStream* s)
336 {
337  POINTER_POSITION_UPDATE* pointer_position = calloc(1, sizeof(POINTER_POSITION_UPDATE));
338 
339  WINPR_ASSERT(update);
340 
341  if (!pointer_position)
342  goto fail;
343 
344  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
345  goto fail;
346 
347  Stream_Read_UINT16(s, pointer_position->xPos); /* xPos (2 bytes) */
348  Stream_Read_UINT16(s, pointer_position->yPos); /* yPos (2 bytes) */
349  return pointer_position;
350 fail:
351  WINPR_PRAGMA_DIAG_PUSH
352  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
353  free_pointer_position_update(update->context, pointer_position);
354  WINPR_PRAGMA_DIAG_POP
355  return NULL;
356 }
357 
358 POINTER_SYSTEM_UPDATE* update_read_pointer_system(rdpUpdate* update, wStream* s)
359 {
360  POINTER_SYSTEM_UPDATE* pointer_system = calloc(1, sizeof(POINTER_SYSTEM_UPDATE));
361 
362  WINPR_ASSERT(update);
363 
364  if (!pointer_system)
365  goto fail;
366 
367  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
368  goto fail;
369 
370  Stream_Read_UINT32(s, pointer_system->type); /* systemPointerType (4 bytes) */
371  return pointer_system;
372 fail:
373  WINPR_PRAGMA_DIAG_PUSH
374  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
375  free_pointer_system_update(update->context, pointer_system);
376  WINPR_PRAGMA_DIAG_POP
377  return NULL;
378 }
379 
380 static BOOL s_update_read_pointer_color(wStream* s, POINTER_COLOR_UPDATE* pointer_color,
381  BYTE xorBpp, UINT32 flags)
382 {
383  BYTE* newMask = NULL;
384  UINT32 scanlineSize = 0;
385  UINT32 max = 32;
386 
387  WINPR_ASSERT(pointer_color);
388 
389  if (flags & LARGE_POINTER_FLAG_96x96)
390  max = 96;
391 
392  if (!pointer_color)
393  goto fail;
394 
395  if (!Stream_CheckAndLogRequiredLength(TAG, s, 14))
396  goto fail;
397 
398  Stream_Read_UINT16(s, pointer_color->cacheIndex); /* cacheIndex (2 bytes) */
399  Stream_Read_UINT16(s, pointer_color->hotSpotX); /* hotSpot.xPos (2 bytes) */
400  Stream_Read_UINT16(s, pointer_color->hotSpotY); /* hotSpot.yPos (2 bytes) */
410  Stream_Read_UINT16(s, pointer_color->width); /* width (2 bytes) */
411  Stream_Read_UINT16(s, pointer_color->height); /* height (2 bytes) */
412 
413  if ((pointer_color->width > max) || (pointer_color->height > max))
414  goto fail;
415 
416  Stream_Read_UINT16(s, pointer_color->lengthAndMask); /* lengthAndMask (2 bytes) */
417  Stream_Read_UINT16(s, pointer_color->lengthXorMask); /* lengthXorMask (2 bytes) */
418 
425  if (pointer_color->hotSpotX >= pointer_color->width)
426  pointer_color->hotSpotX = 0;
427 
428  if (pointer_color->hotSpotY >= pointer_color->height)
429  pointer_color->hotSpotY = 0;
430 
431  if (pointer_color->lengthXorMask > 0)
432  {
444  if (!Stream_CheckAndLogRequiredLength(TAG, s, pointer_color->lengthXorMask))
445  goto fail;
446 
447  scanlineSize = (7 + xorBpp * pointer_color->width) / 8;
448  scanlineSize = ((scanlineSize + 1) / 2) * 2;
449 
450  if (scanlineSize * pointer_color->height != pointer_color->lengthXorMask)
451  {
452  WLog_ERR(TAG,
453  "invalid lengthXorMask: width=%" PRIu32 " height=%" PRIu32 ", %" PRIu32
454  " instead of %" PRIu32 "",
455  pointer_color->width, pointer_color->height, pointer_color->lengthXorMask,
456  scanlineSize * pointer_color->height);
457  goto fail;
458  }
459 
460  newMask = realloc(pointer_color->xorMaskData, pointer_color->lengthXorMask);
461 
462  if (!newMask)
463  goto fail;
464 
465  pointer_color->xorMaskData = newMask;
466  Stream_Read(s, pointer_color->xorMaskData, pointer_color->lengthXorMask);
467  }
468 
469  if (pointer_color->lengthAndMask > 0)
470  {
478  if (!Stream_CheckAndLogRequiredLength(TAG, s, pointer_color->lengthAndMask))
479  goto fail;
480 
481  scanlineSize = ((7 + pointer_color->width) / 8);
482  scanlineSize = ((1 + scanlineSize) / 2) * 2;
483 
484  if (scanlineSize * pointer_color->height != pointer_color->lengthAndMask)
485  {
486  WLog_ERR(TAG, "invalid lengthAndMask: %" PRIu32 " instead of %" PRIu32 "",
487  pointer_color->lengthAndMask, scanlineSize * pointer_color->height);
488  goto fail;
489  }
490 
491  newMask = realloc(pointer_color->andMaskData, pointer_color->lengthAndMask);
492 
493  if (!newMask)
494  goto fail;
495 
496  pointer_color->andMaskData = newMask;
497  Stream_Read(s, pointer_color->andMaskData, pointer_color->lengthAndMask);
498  }
499 
500  if (Stream_GetRemainingLength(s) > 0)
501  Stream_Seek_UINT8(s); /* pad (1 byte) */
502 
503  return TRUE;
504 fail:
505  return FALSE;
506 }
507 
508 POINTER_COLOR_UPDATE* update_read_pointer_color(rdpUpdate* update, wStream* s, BYTE xorBpp)
509 {
510  POINTER_COLOR_UPDATE* pointer_color = calloc(1, sizeof(POINTER_COLOR_UPDATE));
511 
512  WINPR_ASSERT(update);
513 
514  if (!pointer_color)
515  goto fail;
516 
517  if (!s_update_read_pointer_color(s, pointer_color, xorBpp,
518  update->context->settings->LargePointerFlag))
519  goto fail;
520 
521  return pointer_color;
522 fail:
523  WINPR_PRAGMA_DIAG_PUSH
524  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
525  free_pointer_color_update(update->context, pointer_color);
526  WINPR_PRAGMA_DIAG_POP
527  return NULL;
528 }
529 
530 static BOOL s_update_read_pointer_large(wStream* s, POINTER_LARGE_UPDATE* pointer)
531 {
532  BYTE* newMask = NULL;
533  UINT32 scanlineSize = 0;
534 
535  if (!pointer)
536  goto fail;
537 
538  if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
539  goto fail;
540 
541  Stream_Read_UINT16(s, pointer->xorBpp);
542  Stream_Read_UINT16(s, pointer->cacheIndex); /* cacheIndex (2 bytes) */
543  Stream_Read_UINT16(s, pointer->hotSpotX); /* hotSpot.xPos (2 bytes) */
544  Stream_Read_UINT16(s, pointer->hotSpotY); /* hotSpot.yPos (2 bytes) */
545 
546  Stream_Read_UINT16(s, pointer->width); /* width (2 bytes) */
547  Stream_Read_UINT16(s, pointer->height); /* height (2 bytes) */
548 
549  if ((pointer->width > 384) || (pointer->height > 384))
550  goto fail;
551 
552  Stream_Read_UINT32(s, pointer->lengthAndMask); /* lengthAndMask (4 bytes) */
553  Stream_Read_UINT32(s, pointer->lengthXorMask); /* lengthXorMask (4 bytes) */
554 
555  if (pointer->hotSpotX >= pointer->width)
556  pointer->hotSpotX = 0;
557 
558  if (pointer->hotSpotY >= pointer->height)
559  pointer->hotSpotY = 0;
560 
561  if (pointer->lengthXorMask > 0)
562  {
574  if (!Stream_CheckAndLogRequiredLength(TAG, s, pointer->lengthXorMask))
575  goto fail;
576 
577  scanlineSize = (7 + pointer->xorBpp * pointer->width) / 8;
578  scanlineSize = ((scanlineSize + 1) / 2) * 2;
579 
580  if (scanlineSize * pointer->height != pointer->lengthXorMask)
581  {
582  WLog_ERR(TAG,
583  "invalid lengthXorMask: width=%" PRIu32 " height=%" PRIu32 ", %" PRIu32
584  " instead of %" PRIu32 "",
585  pointer->width, pointer->height, pointer->lengthXorMask,
586  scanlineSize * pointer->height);
587  goto fail;
588  }
589 
590  newMask = realloc(pointer->xorMaskData, pointer->lengthXorMask);
591 
592  if (!newMask)
593  goto fail;
594 
595  pointer->xorMaskData = newMask;
596  Stream_Read(s, pointer->xorMaskData, pointer->lengthXorMask);
597  }
598 
599  if (pointer->lengthAndMask > 0)
600  {
608  if (!Stream_CheckAndLogRequiredLength(TAG, s, pointer->lengthAndMask))
609  goto fail;
610 
611  scanlineSize = ((7 + pointer->width) / 8);
612  scanlineSize = ((1 + scanlineSize) / 2) * 2;
613 
614  if (scanlineSize * pointer->height != pointer->lengthAndMask)
615  {
616  WLog_ERR(TAG, "invalid lengthAndMask: %" PRIu32 " instead of %" PRIu32 "",
617  pointer->lengthAndMask, scanlineSize * pointer->height);
618  goto fail;
619  }
620 
621  newMask = realloc(pointer->andMaskData, pointer->lengthAndMask);
622 
623  if (!newMask)
624  goto fail;
625 
626  pointer->andMaskData = newMask;
627  Stream_Read(s, pointer->andMaskData, pointer->lengthAndMask);
628  }
629 
630  if (Stream_GetRemainingLength(s) > 0)
631  Stream_Seek_UINT8(s); /* pad (1 byte) */
632 
633  return TRUE;
634 fail:
635  return FALSE;
636 }
637 
638 POINTER_LARGE_UPDATE* update_read_pointer_large(rdpUpdate* update, wStream* s)
639 {
640  POINTER_LARGE_UPDATE* pointer = calloc(1, sizeof(POINTER_LARGE_UPDATE));
641 
642  WINPR_ASSERT(update);
643 
644  if (!pointer)
645  goto fail;
646 
647  if (!s_update_read_pointer_large(s, pointer))
648  goto fail;
649 
650  return pointer;
651 fail:
652  WINPR_PRAGMA_DIAG_PUSH
653  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
654  free_pointer_large_update(update->context, pointer);
655  WINPR_PRAGMA_DIAG_POP
656  return NULL;
657 }
658 
659 POINTER_NEW_UPDATE* update_read_pointer_new(rdpUpdate* update, wStream* s)
660 {
661  POINTER_NEW_UPDATE* pointer_new = calloc(1, sizeof(POINTER_NEW_UPDATE));
662 
663  WINPR_ASSERT(update);
664 
665  if (!pointer_new)
666  goto fail;
667 
668  if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
669  goto fail;
670 
671  Stream_Read_UINT16(s, pointer_new->xorBpp); /* xorBpp (2 bytes) */
672 
673  if ((pointer_new->xorBpp < 1) || (pointer_new->xorBpp > 32))
674  {
675  WLog_ERR(TAG, "invalid xorBpp %" PRIu32 "", pointer_new->xorBpp);
676  goto fail;
677  }
678 
679  if (!s_update_read_pointer_color(
680  s, &pointer_new->colorPtrAttr, pointer_new->xorBpp,
681  update->context->settings->LargePointerFlag)) /* colorPtrAttr */
682  goto fail;
683 
684  return pointer_new;
685 fail:
686  WINPR_PRAGMA_DIAG_PUSH
687  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
688  free_pointer_new_update(update->context, pointer_new);
689  WINPR_PRAGMA_DIAG_POP
690  return NULL;
691 }
692 
693 POINTER_CACHED_UPDATE* update_read_pointer_cached(rdpUpdate* update, wStream* s)
694 {
695  POINTER_CACHED_UPDATE* pointer = calloc(1, sizeof(POINTER_CACHED_UPDATE));
696 
697  WINPR_ASSERT(update);
698 
699  if (!pointer)
700  goto fail;
701 
702  if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
703  goto fail;
704 
705  Stream_Read_UINT16(s, pointer->cacheIndex); /* cacheIndex (2 bytes) */
706  return pointer;
707 fail:
708  WINPR_PRAGMA_DIAG_PUSH
709  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
710  free_pointer_cached_update(update->context, pointer);
711  WINPR_PRAGMA_DIAG_POP
712  return NULL;
713 }
714 
715 BOOL update_recv_pointer(rdpUpdate* update, wStream* s)
716 {
717  BOOL rc = FALSE;
718  UINT16 messageType = 0;
719 
720  WINPR_ASSERT(update);
721 
722  rdpContext* context = update->context;
723  rdpPointerUpdate* pointer = update->pointer;
724 
725  if (!Stream_CheckAndLogRequiredLength(TAG, s, 2 + 2))
726  return FALSE;
727 
728  Stream_Read_UINT16(s, messageType); /* messageType (2 bytes) */
729  Stream_Seek_UINT16(s); /* pad2Octets (2 bytes) */
730 
731  switch (messageType)
732  {
733  case PTR_MSG_TYPE_POSITION:
734  {
735  POINTER_POSITION_UPDATE* pointer_position = update_read_pointer_position(update, s);
736 
737  if (pointer_position)
738  {
739  rc = IFCALLRESULT(FALSE, pointer->PointerPosition, context, pointer_position);
740  free_pointer_position_update(context, pointer_position);
741  }
742  }
743  break;
744 
745  case PTR_MSG_TYPE_SYSTEM:
746  {
747  POINTER_SYSTEM_UPDATE* pointer_system = update_read_pointer_system(update, s);
748 
749  if (pointer_system)
750  {
751  rc = IFCALLRESULT(FALSE, pointer->PointerSystem, context, pointer_system);
752  free_pointer_system_update(context, pointer_system);
753  }
754  }
755  break;
756 
757  case PTR_MSG_TYPE_COLOR:
758  {
759  POINTER_COLOR_UPDATE* pointer_color = update_read_pointer_color(update, s, 24);
760 
761  if (pointer_color)
762  {
763  rc = IFCALLRESULT(FALSE, pointer->PointerColor, context, pointer_color);
764  free_pointer_color_update(context, pointer_color);
765  }
766  }
767  break;
768 
769  case PTR_MSG_TYPE_POINTER_LARGE:
770  {
771  POINTER_LARGE_UPDATE* pointer_large = update_read_pointer_large(update, s);
772 
773  if (pointer_large)
774  {
775  rc = IFCALLRESULT(FALSE, pointer->PointerLarge, context, pointer_large);
776  free_pointer_large_update(context, pointer_large);
777  }
778  }
779  break;
780 
781  case PTR_MSG_TYPE_POINTER:
782  {
783  POINTER_NEW_UPDATE* pointer_new = update_read_pointer_new(update, s);
784 
785  if (pointer_new)
786  {
787  rc = IFCALLRESULT(FALSE, pointer->PointerNew, context, pointer_new);
788  free_pointer_new_update(context, pointer_new);
789  }
790  }
791  break;
792 
793  case PTR_MSG_TYPE_CACHED:
794  {
795  POINTER_CACHED_UPDATE* pointer_cached = update_read_pointer_cached(update, s);
796 
797  if (pointer_cached)
798  {
799  rc = IFCALLRESULT(FALSE, pointer->PointerCached, context, pointer_cached);
800  free_pointer_cached_update(context, pointer_cached);
801  }
802  }
803  break;
804 
805  default:
806  break;
807  }
808 
809  return rc;
810 }
811 
812 BOOL update_recv(rdpUpdate* update, wStream* s)
813 {
814  BOOL rc = FALSE;
815  UINT16 updateType = 0;
816  rdp_update_internal* up = update_cast(update);
817  rdpContext* context = update->context;
818 
819  WINPR_ASSERT(context);
820 
821  if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
822  return FALSE;
823 
824  Stream_Read_UINT16(s, updateType); /* updateType (2 bytes) */
825  WLog_Print(up->log, WLOG_TRACE, "%s Update Data PDU", update_type_to_string(updateType));
826 
827  if (!update_begin_paint(update))
828  goto fail;
829 
830  switch (updateType)
831  {
832  case UPDATE_TYPE_ORDERS:
833  rc = update_recv_orders(update, s);
834  break;
835 
836  case UPDATE_TYPE_BITMAP:
837  {
838  BITMAP_UPDATE* bitmap_update = update_read_bitmap_update(update, s);
839 
840  if (!bitmap_update)
841  {
842  WLog_ERR(TAG, "UPDATE_TYPE_BITMAP - update_read_bitmap_update() failed");
843  goto fail;
844  }
845 
846  rc = IFCALLRESULT(FALSE, update->BitmapUpdate, context, bitmap_update);
847  free_bitmap_update(context, bitmap_update);
848  }
849  break;
850 
851  case UPDATE_TYPE_PALETTE:
852  {
853  PALETTE_UPDATE* palette_update = update_read_palette(update, s);
854 
855  if (!palette_update)
856  {
857  WLog_ERR(TAG, "UPDATE_TYPE_PALETTE - update_read_palette() failed");
858  goto fail;
859  }
860 
861  rc = IFCALLRESULT(FALSE, update->Palette, context, palette_update);
862  free_palette_update(context, palette_update);
863  }
864  break;
865 
866  case UPDATE_TYPE_SYNCHRONIZE:
867  if (!update_read_synchronize(update, s))
868  goto fail;
869  rc = IFCALLRESULT(TRUE, update->Synchronize, context);
870  break;
871 
872  default:
873  break;
874  }
875 
876 fail:
877 
878  if (!update_end_paint(update))
879  rc = FALSE;
880 
881  if (!rc)
882  {
883  WLog_ERR(TAG, "UPDATE_TYPE %s [%" PRIu16 "] failed", update_type_to_string(updateType),
884  updateType);
885  return FALSE;
886  }
887 
888  return TRUE;
889 }
890 
891 void update_reset_state(rdpUpdate* update)
892 {
893  rdp_update_internal* up = update_cast(update);
894  rdp_primary_update_internal* primary = primary_update_cast(update->primary);
895 
896  WINPR_ASSERT(primary);
897 
898  ZeroMemory(&primary->order_info, sizeof(ORDER_INFO));
899  ZeroMemory(&primary->dstblt, sizeof(DSTBLT_ORDER));
900  ZeroMemory(&primary->patblt, sizeof(PATBLT_ORDER));
901  ZeroMemory(&primary->scrblt, sizeof(SCRBLT_ORDER));
902  ZeroMemory(&primary->opaque_rect, sizeof(OPAQUE_RECT_ORDER));
903  ZeroMemory(&primary->draw_nine_grid, sizeof(DRAW_NINE_GRID_ORDER));
904  ZeroMemory(&primary->multi_dstblt, sizeof(MULTI_DSTBLT_ORDER));
905  ZeroMemory(&primary->multi_patblt, sizeof(MULTI_PATBLT_ORDER));
906  ZeroMemory(&primary->multi_scrblt, sizeof(MULTI_SCRBLT_ORDER));
907  ZeroMemory(&primary->multi_opaque_rect, sizeof(MULTI_OPAQUE_RECT_ORDER));
908  ZeroMemory(&primary->multi_draw_nine_grid, sizeof(MULTI_DRAW_NINE_GRID_ORDER));
909  ZeroMemory(&primary->line_to, sizeof(LINE_TO_ORDER));
910 
911  free(primary->polyline.points);
912  ZeroMemory(&primary->polyline, sizeof(POLYLINE_ORDER));
913 
914  ZeroMemory(&primary->memblt, sizeof(MEMBLT_ORDER));
915  ZeroMemory(&primary->mem3blt, sizeof(MEM3BLT_ORDER));
916  ZeroMemory(&primary->save_bitmap, sizeof(SAVE_BITMAP_ORDER));
917  ZeroMemory(&primary->glyph_index, sizeof(GLYPH_INDEX_ORDER));
918  ZeroMemory(&primary->fast_index, sizeof(FAST_INDEX_ORDER));
919 
920  free(primary->fast_glyph.glyphData.aj);
921  ZeroMemory(&primary->fast_glyph, sizeof(FAST_GLYPH_ORDER));
922 
923  free(primary->polygon_sc.points);
924  ZeroMemory(&primary->polygon_sc, sizeof(POLYGON_SC_ORDER));
925 
926  free(primary->polygon_cb.points);
927  ZeroMemory(&primary->polygon_cb, sizeof(POLYGON_CB_ORDER));
928 
929  ZeroMemory(&primary->ellipse_sc, sizeof(ELLIPSE_SC_ORDER));
930  ZeroMemory(&primary->ellipse_cb, sizeof(ELLIPSE_CB_ORDER));
931  primary->order_info.orderType = ORDER_TYPE_PATBLT;
932 
933  if (!up->initialState)
934  {
935  rdp_altsec_update_internal* altsec = altsec_update_cast(update->altsec);
936  WINPR_ASSERT(altsec);
937 
938  altsec->switch_surface.bitmapId = SCREEN_BITMAP_SURFACE;
939  IFCALL(altsec->common.SwitchSurface, update->context, &(altsec->switch_surface));
940  }
941 }
942 
943 BOOL update_post_connect(rdpUpdate* update)
944 {
945  rdp_update_internal* up = update_cast(update);
946  rdp_altsec_update_internal* altsec = altsec_update_cast(update->altsec);
947 
948  WINPR_ASSERT(update->context);
949  WINPR_ASSERT(update->context->settings);
950  up->asynchronous = update->context->settings->AsyncUpdate;
951 
952  if (up->asynchronous)
953  {
954 #if defined(FORCE_ASYNC_UPDATE_OFF)
955  WLog_WARN(TAG, "AsyncUpdate requested, but forced deactivated");
956  WLog_WARN(TAG, "see https://github.com/FreeRDP/FreeRDP/issues/10153 for details");
957 #else
958  if (!(up->proxy = update_message_proxy_new(update)))
959  return FALSE;
960 #endif
961  }
962 
963  altsec->switch_surface.bitmapId = SCREEN_BITMAP_SURFACE;
964  IFCALL(update->altsec->SwitchSurface, update->context, &(altsec->switch_surface));
965  up->initialState = FALSE;
966  return TRUE;
967 }
968 
969 void update_post_disconnect(rdpUpdate* update)
970 {
971  rdp_update_internal* up = update_cast(update);
972 
973  WINPR_ASSERT(update->context);
974  WINPR_ASSERT(update->context->settings);
975 
976  up->asynchronous = update->context->settings->AsyncUpdate;
977 
978  if (up->asynchronous)
979  {
980 #if !defined(FORCE_ASYNC_UPDATE_OFF)
981  update_message_proxy_free(up->proxy);
982 #endif
983  }
984 
985  up->initialState = TRUE;
986 }
987 
988 static BOOL s_update_begin_paint(rdpContext* context)
989 {
990  wStream* s = NULL;
991  WINPR_ASSERT(context);
992  rdp_update_internal* update = update_cast(context->update);
993 
994  if (update->us)
995  {
996  if (!update_end_paint(&update->common))
997  return FALSE;
998  }
999 
1000  WINPR_ASSERT(context->rdp);
1001  s = fastpath_update_pdu_init_new(context->rdp->fastpath);
1002 
1003  if (!s)
1004  return FALSE;
1005 
1006  Stream_SealLength(s);
1007  Stream_GetLength(s, update->offsetOrders);
1008  Stream_Seek(s, 2); /* numberOrders (2 bytes) */
1009  update->combineUpdates = TRUE;
1010  update->numberOrders = 0;
1011  update->us = s;
1012  return TRUE;
1013 }
1014 
1015 static BOOL s_update_end_paint(rdpContext* context)
1016 {
1017  wStream* s = NULL;
1018  WINPR_ASSERT(context);
1019  rdp_update_internal* update = update_cast(context->update);
1020 
1021  if (!update->us)
1022  return FALSE;
1023 
1024  s = update->us;
1025  Stream_SealLength(s);
1026  Stream_SetPosition(s, update->offsetOrders);
1027  Stream_Write_UINT16(s, update->numberOrders); /* numberOrders (2 bytes) */
1028  Stream_SetPosition(s, Stream_Length(s));
1029 
1030  if (update->numberOrders > 0)
1031  {
1032  WLog_DBG(TAG, "sending %" PRIu16 " orders", update->numberOrders);
1033  fastpath_send_update_pdu(context->rdp->fastpath, FASTPATH_UPDATETYPE_ORDERS, s, FALSE);
1034  }
1035 
1036  update->combineUpdates = FALSE;
1037  update->numberOrders = 0;
1038  update->offsetOrders = 0;
1039  update->us = NULL;
1040  Stream_Free(s, TRUE);
1041  return TRUE;
1042 }
1043 
1044 static void update_flush(rdpContext* context)
1045 {
1046  rdp_update_internal* update = NULL;
1047 
1048  WINPR_ASSERT(context);
1049  update = update_cast(context->update);
1050 
1051  if (update->numberOrders > 0)
1052  {
1053  update_end_paint(&update->common);
1054  update_begin_paint(&update->common);
1055  }
1056 }
1057 
1058 static void update_force_flush(rdpContext* context)
1059 {
1060  update_flush(context);
1061 }
1062 
1063 static BOOL update_check_flush(rdpContext* context, size_t size)
1064 {
1065  WINPR_ASSERT(context);
1066  rdp_update_internal* update = update_cast(context->update);
1067 
1068  wStream* s = update->us;
1069 
1070  if (!update->us)
1071  {
1072  update_begin_paint(&update->common);
1073  return FALSE;
1074  }
1075 
1076  if (Stream_GetPosition(s) + size + 64 >= 0x3FFF)
1077  {
1078  update_flush(context);
1079  return TRUE;
1080  }
1081 
1082  return FALSE;
1083 }
1084 
1085 static BOOL update_set_bounds(rdpContext* context, const rdpBounds* bounds)
1086 {
1087  rdp_update_internal* update = NULL;
1088 
1089  WINPR_ASSERT(context);
1090 
1091  update = update_cast(context->update);
1092 
1093  CopyMemory(&update->previousBounds, &update->currentBounds, sizeof(rdpBounds));
1094 
1095  if (!bounds)
1096  ZeroMemory(&update->currentBounds, sizeof(rdpBounds));
1097  else
1098  CopyMemory(&update->currentBounds, bounds, sizeof(rdpBounds));
1099 
1100  return TRUE;
1101 }
1102 
1103 static BOOL update_bounds_is_null(rdpBounds* bounds)
1104 {
1105  WINPR_ASSERT(bounds);
1106  if ((bounds->left == 0) && (bounds->top == 0) && (bounds->right == 0) && (bounds->bottom == 0))
1107  return TRUE;
1108 
1109  return FALSE;
1110 }
1111 
1112 static BOOL update_bounds_equals(rdpBounds* bounds1, rdpBounds* bounds2)
1113 {
1114  WINPR_ASSERT(bounds1);
1115  WINPR_ASSERT(bounds2);
1116 
1117  if ((bounds1->left == bounds2->left) && (bounds1->top == bounds2->top) &&
1118  (bounds1->right == bounds2->right) && (bounds1->bottom == bounds2->bottom))
1119  return TRUE;
1120 
1121  return FALSE;
1122 }
1123 
1124 static int update_prepare_bounds(rdpContext* context, ORDER_INFO* orderInfo)
1125 {
1126  int length = 0;
1127  rdp_update_internal* update = NULL;
1128 
1129  WINPR_ASSERT(context);
1130  WINPR_ASSERT(orderInfo);
1131 
1132  update = update_cast(context->update);
1133 
1134  orderInfo->boundsFlags = 0;
1135 
1136  if (update_bounds_is_null(&update->currentBounds))
1137  return 0;
1138 
1139  orderInfo->controlFlags |= ORDER_BOUNDS;
1140 
1141  if (update_bounds_equals(&update->previousBounds, &update->currentBounds))
1142  {
1143  orderInfo->controlFlags |= ORDER_ZERO_BOUNDS_DELTAS;
1144  return 0;
1145  }
1146  else
1147  {
1148  length += 1;
1149 
1150  if (update->previousBounds.left != update->currentBounds.left)
1151  {
1152  orderInfo->bounds.left = update->currentBounds.left;
1153  orderInfo->boundsFlags |= BOUND_LEFT;
1154  length += 2;
1155  }
1156 
1157  if (update->previousBounds.top != update->currentBounds.top)
1158  {
1159  orderInfo->bounds.top = update->currentBounds.top;
1160  orderInfo->boundsFlags |= BOUND_TOP;
1161  length += 2;
1162  }
1163 
1164  if (update->previousBounds.right != update->currentBounds.right)
1165  {
1166  orderInfo->bounds.right = update->currentBounds.right;
1167  orderInfo->boundsFlags |= BOUND_RIGHT;
1168  length += 2;
1169  }
1170 
1171  if (update->previousBounds.bottom != update->currentBounds.bottom)
1172  {
1173  orderInfo->bounds.bottom = update->currentBounds.bottom;
1174  orderInfo->boundsFlags |= BOUND_BOTTOM;
1175  length += 2;
1176  }
1177  }
1178 
1179  return length;
1180 }
1181 
1182 static size_t update_prepare_order_info(rdpContext* context, ORDER_INFO* orderInfo,
1183  UINT32 orderType)
1184 {
1185  WINPR_ASSERT(context);
1186  WINPR_ASSERT(orderInfo);
1187 
1188  orderInfo->fieldFlags = 0;
1189  orderInfo->orderType = orderType;
1190  orderInfo->controlFlags = ORDER_STANDARD;
1191  orderInfo->controlFlags |= ORDER_TYPE_CHANGE;
1192  size_t length = 2;
1193  length += get_primary_drawing_order_field_bytes(orderInfo->orderType, NULL);
1194  length += update_prepare_bounds(context, orderInfo);
1195  return length;
1196 }
1197 
1198 static int update_write_order_info(rdpContext* context, wStream* s, ORDER_INFO* orderInfo,
1199  size_t offset)
1200 {
1201  size_t position = 0;
1202 
1203  WINPR_UNUSED(context);
1204  WINPR_ASSERT(orderInfo);
1205 
1206  position = Stream_GetPosition(s);
1207  Stream_SetPosition(s, offset);
1208  Stream_Write_UINT8(s, orderInfo->controlFlags); /* controlFlags (1 byte) */
1209 
1210  if (orderInfo->controlFlags & ORDER_TYPE_CHANGE)
1211  Stream_Write_UINT8(s, orderInfo->orderType); /* orderType (1 byte) */
1212 
1213  if (!update_write_field_flags(
1214  s, orderInfo->fieldFlags, orderInfo->controlFlags,
1215  get_primary_drawing_order_field_bytes(orderInfo->orderType, NULL)))
1216  return -1;
1217  if (!update_write_bounds(s, orderInfo))
1218  return -1;
1219  Stream_SetPosition(s, position);
1220  return 0;
1221 }
1222 
1223 static void update_write_refresh_rect(wStream* s, BYTE count, const RECTANGLE_16* areas)
1224 {
1225  WINPR_ASSERT(s);
1226  WINPR_ASSERT(areas || (count == 0));
1227 
1228  Stream_Write_UINT8(s, count); /* numberOfAreas (1 byte) */
1229  Stream_Seek(s, 3); /* pad3Octets (3 bytes) */
1230 
1231  for (BYTE i = 0; i < count; i++)
1232  {
1233  Stream_Write_UINT16(s, areas[i].left); /* left (2 bytes) */
1234  Stream_Write_UINT16(s, areas[i].top); /* top (2 bytes) */
1235  Stream_Write_UINT16(s, areas[i].right); /* right (2 bytes) */
1236  Stream_Write_UINT16(s, areas[i].bottom); /* bottom (2 bytes) */
1237  }
1238 }
1239 
1240 static BOOL update_send_refresh_rect(rdpContext* context, BYTE count, const RECTANGLE_16* areas)
1241 {
1242  WINPR_ASSERT(context);
1243  rdpRdp* rdp = context->rdp;
1244 
1245  WINPR_ASSERT(rdp->settings);
1246  if (rdp->settings->RefreshRect)
1247  {
1248  wStream* s = rdp_data_pdu_init(rdp);
1249 
1250  if (!s)
1251  return FALSE;
1252 
1253  update_write_refresh_rect(s, count, areas);
1254  return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_REFRESH_RECT, rdp->mcs->userId);
1255  }
1256 
1257  return TRUE;
1258 }
1259 
1260 static void update_write_suppress_output(wStream* s, BYTE allow, const RECTANGLE_16* area)
1261 {
1262  WINPR_ASSERT(s);
1263 
1264  Stream_Write_UINT8(s, allow); /* allowDisplayUpdates (1 byte) */
1265  /* Use zeros for padding (like mstsc) for compatibility with legacy servers */
1266  Stream_Zero(s, 3); /* pad3Octets (3 bytes) */
1267 
1268  if (allow > 0)
1269  {
1270  WINPR_ASSERT(area);
1271  Stream_Write_UINT16(s, area->left); /* left (2 bytes) */
1272  Stream_Write_UINT16(s, area->top); /* top (2 bytes) */
1273  Stream_Write_UINT16(s, area->right); /* right (2 bytes) */
1274  Stream_Write_UINT16(s, area->bottom); /* bottom (2 bytes) */
1275  }
1276 }
1277 
1278 static BOOL update_send_suppress_output(rdpContext* context, BYTE allow, const RECTANGLE_16* area)
1279 {
1280  WINPR_ASSERT(context);
1281  rdpRdp* rdp = context->rdp;
1282 
1283  WINPR_ASSERT(rdp);
1284  WINPR_ASSERT(rdp->settings);
1285  if (rdp->settings->SuppressOutput)
1286  {
1287  wStream* s = rdp_data_pdu_init(rdp);
1288 
1289  if (!s)
1290  return FALSE;
1291 
1292  update_write_suppress_output(s, allow, area);
1293  WINPR_ASSERT(rdp->mcs);
1294  return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SUPPRESS_OUTPUT, rdp->mcs->userId);
1295  }
1296 
1297  return TRUE;
1298 }
1299 
1300 static BOOL update_send_surface_command(rdpContext* context, wStream* s)
1301 {
1302  wStream* update = NULL;
1303  WINPR_ASSERT(context);
1304  rdpRdp* rdp = context->rdp;
1305  BOOL ret = 0;
1306 
1307  WINPR_ASSERT(rdp);
1308  update = fastpath_update_pdu_init(rdp->fastpath);
1309 
1310  if (!update)
1311  return FALSE;
1312 
1313  if (!Stream_EnsureRemainingCapacity(update, Stream_GetPosition(s)))
1314  {
1315  ret = FALSE;
1316  goto out;
1317  }
1318 
1319  Stream_Write(update, Stream_Buffer(s), Stream_GetPosition(s));
1320  ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, update, FALSE);
1321 out:
1322  Stream_Release(update);
1323  return ret;
1324 }
1325 
1326 static BOOL update_send_surface_bits(rdpContext* context,
1327  const SURFACE_BITS_COMMAND* surfaceBitsCommand)
1328 {
1329  wStream* s = NULL;
1330  WINPR_ASSERT(context);
1331  rdpRdp* rdp = context->rdp;
1332  BOOL ret = FALSE;
1333 
1334  WINPR_ASSERT(surfaceBitsCommand);
1335  WINPR_ASSERT(rdp);
1336 
1337  update_force_flush(context);
1338  s = fastpath_update_pdu_init(rdp->fastpath);
1339 
1340  if (!s)
1341  return FALSE;
1342 
1343  if (!update_write_surfcmd_surface_bits(s, surfaceBitsCommand))
1344  goto out_fail;
1345 
1346  if (!fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s,
1347  surfaceBitsCommand->skipCompression))
1348  goto out_fail;
1349 
1350  update_force_flush(context);
1351  ret = TRUE;
1352 out_fail:
1353  Stream_Release(s);
1354  return ret;
1355 }
1356 
1357 static BOOL update_send_surface_frame_marker(rdpContext* context,
1358  const SURFACE_FRAME_MARKER* surfaceFrameMarker)
1359 {
1360  wStream* s = NULL;
1361  WINPR_ASSERT(context);
1362  rdpRdp* rdp = context->rdp;
1363  BOOL ret = FALSE;
1364  update_force_flush(context);
1365 
1366  WINPR_ASSERT(rdp);
1367  s = fastpath_update_pdu_init(rdp->fastpath);
1368 
1369  if (!s)
1370  return FALSE;
1371 
1372  if (!update_write_surfcmd_frame_marker(s, surfaceFrameMarker->frameAction,
1373  surfaceFrameMarker->frameId) ||
1374  !fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s, FALSE))
1375  goto out_fail;
1376 
1377  update_force_flush(context);
1378  ret = TRUE;
1379 out_fail:
1380  Stream_Release(s);
1381  return ret;
1382 }
1383 
1384 static BOOL update_send_surface_frame_bits(rdpContext* context, const SURFACE_BITS_COMMAND* cmd,
1385  BOOL first, BOOL last, UINT32 frameId)
1386 {
1387  wStream* s = NULL;
1388 
1389  WINPR_ASSERT(context);
1390  rdpRdp* rdp = context->rdp;
1391  BOOL ret = FALSE;
1392 
1393  update_force_flush(context);
1394 
1395  WINPR_ASSERT(rdp);
1396  s = fastpath_update_pdu_init(rdp->fastpath);
1397 
1398  if (!s)
1399  return FALSE;
1400 
1401  if (first)
1402  {
1403  if (!update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_BEGIN, frameId))
1404  goto out_fail;
1405  }
1406 
1407  if (!update_write_surfcmd_surface_bits(s, cmd))
1408  goto out_fail;
1409 
1410  if (last)
1411  {
1412  if (!update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_END, frameId))
1413  goto out_fail;
1414  }
1415 
1416  ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s,
1417  cmd->skipCompression);
1418  update_force_flush(context);
1419 out_fail:
1420  Stream_Release(s);
1421  return ret;
1422 }
1423 
1424 static BOOL update_send_frame_acknowledge(rdpContext* context, UINT32 frameId)
1425 {
1426  WINPR_ASSERT(context);
1427  rdpRdp* rdp = context->rdp;
1428 
1429  WINPR_ASSERT(rdp);
1430  WINPR_ASSERT(rdp->settings);
1431  if (rdp->settings->ReceivedCapabilities[CAPSET_TYPE_FRAME_ACKNOWLEDGE])
1432  {
1433  wStream* s = rdp_data_pdu_init(rdp);
1434 
1435  if (!s)
1436  return FALSE;
1437 
1438  Stream_Write_UINT32(s, frameId);
1439  return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FRAME_ACKNOWLEDGE, rdp->mcs->userId);
1440  }
1441 
1442  return TRUE;
1443 }
1444 
1445 static BOOL update_send_synchronize(rdpContext* context)
1446 {
1447  wStream* s = NULL;
1448  WINPR_ASSERT(context);
1449  rdpRdp* rdp = context->rdp;
1450  BOOL ret = 0;
1451 
1452  WINPR_ASSERT(rdp);
1453  s = fastpath_update_pdu_init(rdp->fastpath);
1454 
1455  if (!s)
1456  return FALSE;
1457 
1458  Stream_Zero(s, 2); /* pad2Octets (2 bytes) */
1459  ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SYNCHRONIZE, s, FALSE);
1460  Stream_Release(s);
1461  return ret;
1462 }
1463 
1464 static BOOL update_send_desktop_resize(rdpContext* context)
1465 {
1466  WINPR_ASSERT(context);
1467  return rdp_server_reactivate(context->rdp);
1468 }
1469 
1470 static BOOL update_send_bitmap_update(rdpContext* context, const BITMAP_UPDATE* bitmapUpdate)
1471 {
1472  wStream* s = NULL;
1473  WINPR_ASSERT(context);
1474  rdpRdp* rdp = context->rdp;
1475  rdpUpdate* update = context->update;
1476  BOOL ret = TRUE;
1477 
1478  update_force_flush(context);
1479 
1480  WINPR_ASSERT(rdp);
1481  s = fastpath_update_pdu_init(rdp->fastpath);
1482 
1483  if (!s)
1484  return FALSE;
1485 
1486  if (!update_write_bitmap_update(update, s, bitmapUpdate) ||
1487  !fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_BITMAP, s,
1488  bitmapUpdate->skipCompression))
1489  {
1490  ret = FALSE;
1491  goto out_fail;
1492  }
1493 
1494  update_force_flush(context);
1495 out_fail:
1496  Stream_Release(s);
1497  return ret;
1498 }
1499 
1500 static BOOL update_send_play_sound(rdpContext* context, const PLAY_SOUND_UPDATE* play_sound)
1501 {
1502  wStream* s = NULL;
1503  WINPR_ASSERT(context);
1504  rdpRdp* rdp = context->rdp;
1505 
1506  WINPR_ASSERT(rdp);
1507  WINPR_ASSERT(rdp->settings);
1508  WINPR_ASSERT(play_sound);
1509  if (!rdp->settings->ReceivedCapabilities[CAPSET_TYPE_SOUND])
1510  {
1511  return TRUE;
1512  }
1513 
1514  s = rdp_data_pdu_init(rdp);
1515 
1516  if (!s)
1517  return FALSE;
1518 
1519  Stream_Write_UINT32(s, play_sound->duration);
1520  Stream_Write_UINT32(s, play_sound->frequency);
1521  return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_PLAY_SOUND, rdp->mcs->userId);
1522 }
1523 
1528 static BOOL update_send_dstblt(rdpContext* context, const DSTBLT_ORDER* dstblt)
1529 {
1530  ORDER_INFO orderInfo = { 0 };
1531 
1532  WINPR_ASSERT(context);
1533  WINPR_ASSERT(dstblt);
1534 
1535  rdp_update_internal* update = update_cast(context->update);
1536 
1537  const size_t headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_DSTBLT);
1538  const size_t inf = update_approximate_dstblt_order(&orderInfo, dstblt);
1539  if (!update_check_flush(context, headerLength + inf))
1540  return FALSE;
1541 
1542  wStream* s = update->us;
1543 
1544  if (!s)
1545  return FALSE;
1546 
1547  const size_t offset = Stream_GetPosition(s);
1548 
1549  if (!Stream_EnsureRemainingCapacity(s, headerLength))
1550  return FALSE;
1551 
1552  Stream_Seek(s, headerLength);
1553 
1554  if (!update_write_dstblt_order(s, &orderInfo, dstblt))
1555  return FALSE;
1556 
1557  update_write_order_info(context, s, &orderInfo, offset);
1558  update->numberOrders++;
1559  return TRUE;
1560 }
1561 
1562 static BOOL update_send_patblt(rdpContext* context, PATBLT_ORDER* patblt)
1563 {
1564  size_t offset = 0;
1565  ORDER_INFO orderInfo = { 0 };
1566 
1567  WINPR_ASSERT(context);
1568  WINPR_ASSERT(patblt);
1569  rdp_update_internal* update = update_cast(context->update);
1570 
1571  const size_t headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_PATBLT);
1572  if (!update_check_flush(context,
1573  headerLength + update_approximate_patblt_order(&orderInfo, patblt)))
1574  return FALSE;
1575 
1576  wStream* s = update->us;
1577 
1578  if (!s)
1579  return FALSE;
1580 
1581  offset = Stream_GetPosition(s);
1582 
1583  if (!Stream_EnsureRemainingCapacity(s, headerLength))
1584  return FALSE;
1585 
1586  Stream_Seek(s, headerLength);
1587  update_write_patblt_order(s, &orderInfo, patblt);
1588  update_write_order_info(context, s, &orderInfo, offset);
1589  update->numberOrders++;
1590  return TRUE;
1591 }
1592 
1593 static BOOL update_send_scrblt(rdpContext* context, const SCRBLT_ORDER* scrblt)
1594 {
1595  ORDER_INFO orderInfo = { 0 };
1596 
1597  WINPR_ASSERT(context);
1598  WINPR_ASSERT(scrblt);
1599  rdp_update_internal* update = update_cast(context->update);
1600 
1601  const size_t headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_SCRBLT);
1602  const size_t inf = update_approximate_scrblt_order(&orderInfo, scrblt);
1603  if (!update_check_flush(context, headerLength + inf))
1604  return FALSE;
1605 
1606  wStream* s = update->us;
1607 
1608  if (!s)
1609  return TRUE;
1610 
1611  const size_t offset = Stream_GetPosition(s);
1612 
1613  if (!Stream_EnsureRemainingCapacity(s, headerLength))
1614  return FALSE;
1615 
1616  Stream_Seek(s, headerLength);
1617  update_write_scrblt_order(s, &orderInfo, scrblt);
1618  update_write_order_info(context, s, &orderInfo, offset);
1619  update->numberOrders++;
1620  return TRUE;
1621 }
1622 
1623 static BOOL update_send_opaque_rect(rdpContext* context, const OPAQUE_RECT_ORDER* opaque_rect)
1624 {
1625  size_t offset = 0;
1626  ORDER_INFO orderInfo = { 0 };
1627 
1628  WINPR_ASSERT(context);
1629  WINPR_ASSERT(opaque_rect);
1630  rdp_update_internal* update = update_cast(context->update);
1631 
1632  const size_t headerLength =
1633  update_prepare_order_info(context, &orderInfo, ORDER_TYPE_OPAQUE_RECT);
1634  if (!update_check_flush(
1635  context, headerLength + update_approximate_opaque_rect_order(&orderInfo, opaque_rect)))
1636  return FALSE;
1637 
1638  wStream* s = update->us;
1639 
1640  if (!s)
1641  return FALSE;
1642 
1643  offset = Stream_GetPosition(s);
1644 
1645  if (!Stream_EnsureRemainingCapacity(s, headerLength))
1646  return FALSE;
1647 
1648  Stream_Seek(s, headerLength);
1649  update_write_opaque_rect_order(s, &orderInfo, opaque_rect);
1650  update_write_order_info(context, s, &orderInfo, offset);
1651  update->numberOrders++;
1652  return TRUE;
1653 }
1654 
1655 static BOOL update_send_line_to(rdpContext* context, const LINE_TO_ORDER* line_to)
1656 {
1657  ORDER_INFO orderInfo = { 0 };
1658 
1659  WINPR_ASSERT(context);
1660  WINPR_ASSERT(line_to);
1661  rdp_update_internal* update = update_cast(context->update);
1662  const size_t headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_LINE_TO);
1663  const size_t inf = update_approximate_line_to_order(&orderInfo, line_to);
1664  if (!update_check_flush(context, headerLength + inf))
1665  return FALSE;
1666 
1667  wStream* s = update->us;
1668 
1669  if (!s)
1670  return FALSE;
1671 
1672  const size_t offset = Stream_GetPosition(s);
1673 
1674  if (!Stream_EnsureRemainingCapacity(s, headerLength))
1675  return FALSE;
1676 
1677  Stream_Seek(s, headerLength);
1678  update_write_line_to_order(s, &orderInfo, line_to);
1679  update_write_order_info(context, s, &orderInfo, offset);
1680  update->numberOrders++;
1681  return TRUE;
1682 }
1683 
1684 static BOOL update_send_memblt(rdpContext* context, MEMBLT_ORDER* memblt)
1685 {
1686  size_t offset = 0;
1687  ORDER_INFO orderInfo = { 0 };
1688 
1689  WINPR_ASSERT(context);
1690  WINPR_ASSERT(memblt);
1691  rdp_update_internal* update = update_cast(context->update);
1692  const size_t headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_MEMBLT);
1693  if (!update_check_flush(context,
1694  headerLength + update_approximate_memblt_order(&orderInfo, memblt)))
1695  return FALSE;
1696 
1697  wStream* s = update->us;
1698 
1699  if (!s)
1700  return FALSE;
1701 
1702  offset = Stream_GetPosition(s);
1703 
1704  if (!Stream_EnsureRemainingCapacity(s, headerLength))
1705  return FALSE;
1706 
1707  Stream_Seek(s, headerLength);
1708  update_write_memblt_order(s, &orderInfo, memblt);
1709  update_write_order_info(context, s, &orderInfo, offset);
1710  update->numberOrders++;
1711  return TRUE;
1712 }
1713 
1714 static BOOL update_send_glyph_index(rdpContext* context, GLYPH_INDEX_ORDER* glyph_index)
1715 {
1716  ORDER_INFO orderInfo = { 0 };
1717 
1718  WINPR_ASSERT(context);
1719  WINPR_ASSERT(glyph_index);
1720  rdp_update_internal* update = update_cast(context->update);
1721 
1722  const size_t headerLength =
1723  update_prepare_order_info(context, &orderInfo, ORDER_TYPE_GLYPH_INDEX);
1724  const size_t inf = update_approximate_glyph_index_order(&orderInfo, glyph_index);
1725  if (!update_check_flush(context, headerLength + inf))
1726  return FALSE;
1727 
1728  wStream* s = update->us;
1729 
1730  if (!s)
1731  return FALSE;
1732 
1733  const size_t offset = Stream_GetPosition(s);
1734 
1735  if (!Stream_EnsureRemainingCapacity(s, headerLength))
1736  return FALSE;
1737 
1738  Stream_Seek(s, headerLength);
1739  update_write_glyph_index_order(s, &orderInfo, glyph_index);
1740  update_write_order_info(context, s, &orderInfo, offset);
1741  update->numberOrders++;
1742  return TRUE;
1743 }
1744 
1745 /*
1746  * Secondary Drawing Orders
1747  */
1748 
1749 static BOOL update_send_cache_bitmap(rdpContext* context, const CACHE_BITMAP_ORDER* cache_bitmap)
1750 {
1751  const size_t headerLength = 6;
1752  UINT16 extraFlags = 0;
1753 
1754  WINPR_ASSERT(context);
1755  WINPR_ASSERT(cache_bitmap);
1756  rdp_update_internal* update = update_cast(context->update);
1757 
1758  const BYTE orderType = cache_bitmap->compressed ? ORDER_TYPE_CACHE_BITMAP_COMPRESSED
1759  : ORDER_TYPE_BITMAP_UNCOMPRESSED;
1760  const size_t inf =
1761  update_approximate_cache_bitmap_order(cache_bitmap, cache_bitmap->compressed, &extraFlags);
1762  if (!update_check_flush(context, headerLength + inf))
1763  return FALSE;
1764 
1765  wStream* s = update->us;
1766 
1767  if (!s)
1768  return FALSE;
1769 
1770  const size_t bm = Stream_GetPosition(s);
1771 
1772  if (!Stream_EnsureRemainingCapacity(s, headerLength))
1773  return FALSE;
1774 
1775  Stream_Seek(s, headerLength);
1776 
1777  if (!update_write_cache_bitmap_order(s, cache_bitmap, cache_bitmap->compressed, &extraFlags))
1778  return FALSE;
1779 
1780  const size_t em = Stream_GetPosition(s);
1781  WINPR_ASSERT(em >= bm + 13);
1782  const size_t orderLength = (em - bm) - 13;
1783  WINPR_ASSERT(orderLength <= UINT16_MAX);
1784 
1785  Stream_SetPosition(s, bm);
1786  Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
1787  Stream_Write_UINT16(s, (UINT16)orderLength); /* orderLength (2 bytes) */
1788  Stream_Write_UINT16(s, extraFlags); /* extraFlags (2 bytes) */
1789  Stream_Write_UINT8(s, orderType); /* orderType (1 byte) */
1790  Stream_SetPosition(s, em);
1791  update->numberOrders++;
1792  return TRUE;
1793 }
1794 
1795 static BOOL update_send_cache_bitmap_v2(rdpContext* context, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2)
1796 {
1797  const size_t headerLength = 6;
1798  UINT16 extraFlags = 0;
1799 
1800  WINPR_ASSERT(context);
1801  WINPR_ASSERT(cache_bitmap_v2);
1802  rdp_update_internal* update = update_cast(context->update);
1803 
1804  const BYTE orderType = cache_bitmap_v2->compressed ? ORDER_TYPE_BITMAP_COMPRESSED_V2
1805  : ORDER_TYPE_BITMAP_UNCOMPRESSED_V2;
1806 
1807  if (context->settings->NoBitmapCompressionHeader)
1808  cache_bitmap_v2->flags |= CBR2_NO_BITMAP_COMPRESSION_HDR;
1809 
1810  if (!update_check_flush(
1811  context, headerLength + update_approximate_cache_bitmap_v2_order(
1812  cache_bitmap_v2, cache_bitmap_v2->compressed, &extraFlags)))
1813  return FALSE;
1814 
1815  wStream* s = update->us;
1816 
1817  if (!s)
1818  return FALSE;
1819 
1820  const size_t bm = Stream_GetPosition(s);
1821 
1822  if (!Stream_EnsureRemainingCapacity(s, headerLength))
1823  return FALSE;
1824 
1825  Stream_Seek(s, headerLength);
1826 
1827  if (!update_write_cache_bitmap_v2_order(s, cache_bitmap_v2, cache_bitmap_v2->compressed,
1828  &extraFlags))
1829  return FALSE;
1830 
1831  const size_t em = Stream_GetPosition(s);
1832  WINPR_ASSERT(em >= bm + 13);
1833  const size_t orderLength = (em - bm) - 13;
1834  WINPR_ASSERT(orderLength <= UINT16_MAX);
1835 
1836  Stream_SetPosition(s, bm);
1837  Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
1838  Stream_Write_UINT16(s, (UINT16)orderLength); /* orderLength (2 bytes) */
1839  Stream_Write_UINT16(s, extraFlags); /* extraFlags (2 bytes) */
1840  Stream_Write_UINT8(s, orderType); /* orderType (1 byte) */
1841  Stream_SetPosition(s, em);
1842  update->numberOrders++;
1843  return TRUE;
1844 }
1845 
1846 static BOOL update_send_cache_bitmap_v3(rdpContext* context, CACHE_BITMAP_V3_ORDER* cache_bitmap_v3)
1847 {
1848  const size_t headerLength = 6;
1849  UINT16 extraFlags = 0;
1850 
1851  WINPR_ASSERT(context);
1852  WINPR_ASSERT(cache_bitmap_v3);
1853  rdp_update_internal* update = update_cast(context->update);
1854 
1855  const BYTE orderType = ORDER_TYPE_BITMAP_COMPRESSED_V3;
1856  if (!update_check_flush(context, headerLength + update_approximate_cache_bitmap_v3_order(
1857  cache_bitmap_v3, &extraFlags)))
1858  return FALSE;
1859 
1860  wStream* s = update->us;
1861 
1862  if (!s)
1863  return FALSE;
1864 
1865  const size_t bm = Stream_GetPosition(s);
1866 
1867  if (!Stream_EnsureRemainingCapacity(s, headerLength))
1868  return FALSE;
1869 
1870  Stream_Seek(s, headerLength);
1871 
1872  if (!update_write_cache_bitmap_v3_order(s, cache_bitmap_v3, &extraFlags))
1873  return FALSE;
1874 
1875  const size_t em = Stream_GetPosition(s);
1876  WINPR_ASSERT(em >= bm + 13);
1877  const size_t orderLength = (em - bm) - 13;
1878  WINPR_ASSERT(orderLength <= UINT16_MAX);
1879 
1880  Stream_SetPosition(s, bm);
1881  Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
1882  Stream_Write_UINT16(s, (UINT16)orderLength); /* orderLength (2 bytes) */
1883  Stream_Write_UINT16(s, extraFlags); /* extraFlags (2 bytes) */
1884  Stream_Write_UINT8(s, orderType); /* orderType (1 byte) */
1885  Stream_SetPosition(s, em);
1886  update->numberOrders++;
1887  return TRUE;
1888 }
1889 
1890 static BOOL update_send_cache_color_table(rdpContext* context,
1891  const CACHE_COLOR_TABLE_ORDER* cache_color_table)
1892 {
1893  UINT16 flags = 0;
1894  size_t headerLength = 6;
1895 
1896  WINPR_ASSERT(context);
1897  WINPR_ASSERT(cache_color_table);
1898  rdp_update_internal* update = update_cast(context->update);
1899 
1900  const size_t inf = update_approximate_cache_color_table_order(cache_color_table, &flags);
1901  if (!update_check_flush(context, headerLength + inf))
1902  return FALSE;
1903 
1904  wStream* s = update->us;
1905 
1906  if (!s)
1907  return FALSE;
1908 
1909  const size_t bm = Stream_GetPosition(s);
1910 
1911  if (!Stream_EnsureRemainingCapacity(s, headerLength))
1912  return FALSE;
1913 
1914  Stream_Seek(s, headerLength);
1915 
1916  if (!update_write_cache_color_table_order(s, cache_color_table, &flags))
1917  return FALSE;
1918 
1919  const size_t em = Stream_GetPosition(s);
1920  WINPR_ASSERT(em >= bm + 13);
1921  const size_t orderLength = (em - bm) - 13;
1922  WINPR_ASSERT(orderLength <= UINT16_MAX);
1923  Stream_SetPosition(s, bm);
1924  Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
1925  Stream_Write_UINT16(s, (UINT16)orderLength); /* orderLength (2 bytes) */
1926  Stream_Write_UINT16(s, flags); /* extraFlags (2 bytes) */
1927  Stream_Write_UINT8(s, ORDER_TYPE_CACHE_COLOR_TABLE); /* orderType (1 byte) */
1928  Stream_SetPosition(s, em);
1929  update->numberOrders++;
1930  return TRUE;
1931 }
1932 
1933 static BOOL update_send_cache_glyph(rdpContext* context, const CACHE_GLYPH_ORDER* cache_glyph)
1934 {
1935  UINT16 flags = 0;
1936  const size_t headerLength = 6;
1937 
1938  WINPR_ASSERT(context);
1939  WINPR_ASSERT(cache_glyph);
1940  rdp_update_internal* update = update_cast(context->update);
1941 
1942  const size_t inf = update_approximate_cache_glyph_order(cache_glyph, &flags);
1943  if (!update_check_flush(context, headerLength + inf))
1944  return FALSE;
1945 
1946  wStream* s = update->us;
1947 
1948  if (!s)
1949  return FALSE;
1950 
1951  const size_t bm = Stream_GetPosition(s);
1952 
1953  if (!Stream_EnsureRemainingCapacity(s, headerLength))
1954  return FALSE;
1955 
1956  Stream_Seek(s, headerLength);
1957 
1958  if (!update_write_cache_glyph_order(s, cache_glyph, &flags))
1959  return FALSE;
1960 
1961  const size_t em = Stream_GetPosition(s);
1962  WINPR_ASSERT(em >= bm + 13);
1963  const size_t orderLength = (em - bm) - 13;
1964  WINPR_ASSERT(orderLength <= UINT16_MAX);
1965  Stream_SetPosition(s, bm);
1966  Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
1967  Stream_Write_UINT16(s, (UINT16)orderLength); /* orderLength (2 bytes) */
1968  Stream_Write_UINT16(s, flags); /* extraFlags (2 bytes) */
1969  Stream_Write_UINT8(s, ORDER_TYPE_CACHE_GLYPH); /* orderType (1 byte) */
1970  Stream_SetPosition(s, em);
1971  update->numberOrders++;
1972  return TRUE;
1973 }
1974 
1975 static BOOL update_send_cache_glyph_v2(rdpContext* context,
1976  const CACHE_GLYPH_V2_ORDER* cache_glyph_v2)
1977 {
1978  UINT16 flags = 0;
1979  const size_t headerLength = 6;
1980 
1981  WINPR_ASSERT(context);
1982  WINPR_ASSERT(cache_glyph_v2);
1983  rdp_update_internal* update = update_cast(context->update);
1984 
1985  const size_t inf = update_approximate_cache_glyph_v2_order(cache_glyph_v2, &flags);
1986  if (!update_check_flush(context, headerLength + inf))
1987  return FALSE;
1988 
1989  wStream* s = update->us;
1990 
1991  if (!s)
1992  return FALSE;
1993 
1994  const size_t bm = Stream_GetPosition(s);
1995 
1996  if (!Stream_EnsureRemainingCapacity(s, headerLength))
1997  return FALSE;
1998 
1999  Stream_Seek(s, headerLength);
2000 
2001  if (!update_write_cache_glyph_v2_order(s, cache_glyph_v2, &flags))
2002  return FALSE;
2003 
2004  const size_t em = Stream_GetPosition(s);
2005  WINPR_ASSERT(em >= bm + 13);
2006  const size_t orderLength = (em - bm) - 13;
2007  WINPR_ASSERT(orderLength <= UINT16_MAX);
2008  Stream_SetPosition(s, bm);
2009  Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
2010  Stream_Write_UINT16(s, (UINT16)orderLength); /* orderLength (2 bytes) */
2011  Stream_Write_UINT16(s, flags); /* extraFlags (2 bytes) */
2012  Stream_Write_UINT8(s, ORDER_TYPE_CACHE_GLYPH); /* orderType (1 byte) */
2013  Stream_SetPosition(s, em);
2014  update->numberOrders++;
2015  return TRUE;
2016 }
2017 
2018 static BOOL update_send_cache_brush(rdpContext* context, const CACHE_BRUSH_ORDER* cache_brush)
2019 {
2020  UINT16 flags = 0;
2021  const size_t headerLength = 6;
2022 
2023  WINPR_ASSERT(context);
2024  WINPR_ASSERT(cache_brush);
2025  rdp_update_internal* update = update_cast(context->update);
2026 
2027  const size_t inf = update_approximate_cache_brush_order(cache_brush, &flags);
2028  if (!update_check_flush(context, headerLength + inf))
2029  return FALSE;
2030 
2031  wStream* s = update->us;
2032 
2033  if (!s)
2034  return FALSE;
2035 
2036  const size_t bm = Stream_GetPosition(s);
2037 
2038  if (!Stream_EnsureRemainingCapacity(s, headerLength))
2039  return FALSE;
2040 
2041  Stream_Seek(s, headerLength);
2042 
2043  if (!update_write_cache_brush_order(s, cache_brush, &flags))
2044  return FALSE;
2045 
2046  const size_t em = Stream_GetPosition(s);
2047  if (em <= bm + 13)
2048  return FALSE;
2049 
2050  const size_t orderLength = (em - bm) - 13;
2051  WINPR_ASSERT(orderLength <= UINT16_MAX);
2052  Stream_SetPosition(s, bm);
2053  Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
2054  Stream_Write_UINT16(s, (UINT16)orderLength); /* orderLength (2 bytes) */
2055  Stream_Write_UINT16(s, flags); /* extraFlags (2 bytes) */
2056  Stream_Write_UINT8(s, ORDER_TYPE_CACHE_BRUSH); /* orderType (1 byte) */
2057  Stream_SetPosition(s, em);
2058  update->numberOrders++;
2059  return TRUE;
2060 }
2061 
2066 static BOOL update_send_create_offscreen_bitmap_order(
2067  rdpContext* context, const CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap)
2068 {
2069  WINPR_ASSERT(context);
2070  WINPR_ASSERT(create_offscreen_bitmap);
2071  rdp_update_internal* update = update_cast(context->update);
2072 
2073  const size_t headerLength = 1;
2074  const size_t orderType = ORDER_TYPE_CREATE_OFFSCREEN_BITMAP;
2075  const size_t controlFlags = ORDER_SECONDARY | (orderType << 2);
2076  const size_t inf = update_approximate_create_offscreen_bitmap_order(create_offscreen_bitmap);
2077  if (!update_check_flush(context, headerLength + inf))
2078  return FALSE;
2079 
2080  wStream* s = update->us;
2081 
2082  if (!s)
2083  return FALSE;
2084 
2085  const size_t bm = Stream_GetPosition(s);
2086 
2087  if (!Stream_EnsureRemainingCapacity(s, headerLength))
2088  return FALSE;
2089 
2090  Stream_Seek(s, headerLength);
2091 
2092  if (!update_write_create_offscreen_bitmap_order(s, create_offscreen_bitmap))
2093  return FALSE;
2094 
2095  const size_t em = Stream_GetPosition(s);
2096  Stream_SetPosition(s, bm);
2097  Stream_Write_UINT8(s, controlFlags); /* controlFlags (1 byte) */
2098  Stream_SetPosition(s, em);
2099  update->numberOrders++;
2100  return TRUE;
2101 }
2102 
2103 static BOOL update_send_switch_surface_order(rdpContext* context,
2104  const SWITCH_SURFACE_ORDER* switch_surface)
2105 {
2106  WINPR_ASSERT(context);
2107  WINPR_ASSERT(switch_surface);
2108  rdp_update_internal* update = update_cast(context->update);
2109 
2110  const size_t headerLength = 1;
2111  const size_t orderType = ORDER_TYPE_SWITCH_SURFACE;
2112  const size_t controlFlags = ORDER_SECONDARY | (orderType << 2);
2113  const size_t inf = update_approximate_switch_surface_order(switch_surface);
2114  if (!update_check_flush(context, headerLength + inf))
2115  return FALSE;
2116 
2117  wStream* s = update->us;
2118 
2119  if (!s)
2120  return FALSE;
2121 
2122  const size_t bm = Stream_GetPosition(s);
2123 
2124  if (!Stream_EnsureRemainingCapacity(s, headerLength))
2125  return FALSE;
2126 
2127  Stream_Seek(s, headerLength);
2128 
2129  if (!update_write_switch_surface_order(s, switch_surface))
2130  return FALSE;
2131 
2132  const size_t em = Stream_GetPosition(s);
2133  Stream_SetPosition(s, bm);
2134  Stream_Write_UINT8(s, controlFlags); /* controlFlags (1 byte) */
2135  Stream_SetPosition(s, em);
2136  update->numberOrders++;
2137  return TRUE;
2138 }
2139 
2140 static BOOL update_send_pointer_system(rdpContext* context,
2141  const POINTER_SYSTEM_UPDATE* pointer_system)
2142 {
2143  wStream* s = NULL;
2144  BYTE updateCode = 0;
2145 
2146  WINPR_ASSERT(context);
2147  rdpRdp* rdp = context->rdp;
2148  BOOL ret = 0;
2149 
2150  WINPR_ASSERT(rdp);
2151  s = fastpath_update_pdu_init(rdp->fastpath);
2152 
2153  if (!s)
2154  return FALSE;
2155 
2156  if (pointer_system->type == SYSPTR_NULL)
2157  updateCode = FASTPATH_UPDATETYPE_PTR_NULL;
2158  else
2159  updateCode = FASTPATH_UPDATETYPE_PTR_DEFAULT;
2160 
2161  ret = fastpath_send_update_pdu(rdp->fastpath, updateCode, s, FALSE);
2162  Stream_Release(s);
2163  return ret;
2164 }
2165 
2166 static BOOL update_send_pointer_position(rdpContext* context,
2167  const POINTER_POSITION_UPDATE* pointerPosition)
2168 {
2169  wStream* s = NULL;
2170  WINPR_ASSERT(context);
2171  rdpRdp* rdp = context->rdp;
2172  BOOL ret = FALSE;
2173 
2174  WINPR_ASSERT(rdp);
2175  s = fastpath_update_pdu_init(rdp->fastpath);
2176 
2177  if (!s)
2178  return FALSE;
2179 
2180  if (!Stream_EnsureRemainingCapacity(s, 16))
2181  goto out_fail;
2182 
2183  Stream_Write_UINT16(s, pointerPosition->xPos); /* xPos (2 bytes) */
2184  Stream_Write_UINT16(s, pointerPosition->yPos); /* yPos (2 bytes) */
2185  ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_PTR_POSITION, s, FALSE);
2186 out_fail:
2187  Stream_Release(s);
2188  return ret;
2189 }
2190 
2191 static BOOL update_write_pointer_color(wStream* s, const POINTER_COLOR_UPDATE* pointer_color)
2192 {
2193  WINPR_ASSERT(pointer_color);
2194  if (!Stream_EnsureRemainingCapacity(s, 32 + pointer_color->lengthAndMask +
2195  pointer_color->lengthXorMask))
2196  return FALSE;
2197 
2198  Stream_Write_UINT16(s, pointer_color->cacheIndex);
2199  Stream_Write_UINT16(s, pointer_color->hotSpotX);
2200  Stream_Write_UINT16(s, pointer_color->hotSpotY);
2201  Stream_Write_UINT16(s, pointer_color->width);
2202  Stream_Write_UINT16(s, pointer_color->height);
2203  Stream_Write_UINT16(s, pointer_color->lengthAndMask);
2204  Stream_Write_UINT16(s, pointer_color->lengthXorMask);
2205 
2206  if (pointer_color->lengthXorMask > 0)
2207  Stream_Write(s, pointer_color->xorMaskData, pointer_color->lengthXorMask);
2208 
2209  if (pointer_color->lengthAndMask > 0)
2210  Stream_Write(s, pointer_color->andMaskData, pointer_color->lengthAndMask);
2211 
2212  Stream_Write_UINT8(s, 0); /* pad (1 byte) */
2213  return TRUE;
2214 }
2215 
2216 static BOOL update_send_pointer_color(rdpContext* context,
2217  const POINTER_COLOR_UPDATE* pointer_color)
2218 {
2219  wStream* s = NULL;
2220 
2221  WINPR_ASSERT(context);
2222  rdpRdp* rdp = context->rdp;
2223  BOOL ret = FALSE;
2224 
2225  WINPR_ASSERT(rdp);
2226  WINPR_ASSERT(pointer_color);
2227  s = fastpath_update_pdu_init(rdp->fastpath);
2228 
2229  if (!s)
2230  return FALSE;
2231 
2232  if (!update_write_pointer_color(s, pointer_color))
2233  goto out_fail;
2234 
2235  ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_COLOR, s, FALSE);
2236 out_fail:
2237  Stream_Release(s);
2238  return ret;
2239 }
2240 
2241 static BOOL update_write_pointer_large(wStream* s, const POINTER_LARGE_UPDATE* pointer)
2242 {
2243  WINPR_ASSERT(pointer);
2244 
2245  if (!Stream_EnsureRemainingCapacity(s, 32 + pointer->lengthAndMask + pointer->lengthXorMask))
2246  return FALSE;
2247 
2248  Stream_Write_UINT16(s, pointer->xorBpp);
2249  Stream_Write_UINT16(s, pointer->cacheIndex);
2250  Stream_Write_UINT16(s, pointer->hotSpotX);
2251  Stream_Write_UINT16(s, pointer->hotSpotY);
2252  Stream_Write_UINT16(s, pointer->width);
2253  Stream_Write_UINT16(s, pointer->height);
2254  Stream_Write_UINT32(s, pointer->lengthAndMask);
2255  Stream_Write_UINT32(s, pointer->lengthXorMask);
2256  Stream_Write(s, pointer->xorMaskData, pointer->lengthXorMask);
2257  Stream_Write(s, pointer->andMaskData, pointer->lengthAndMask);
2258  Stream_Write_UINT8(s, 0); /* pad (1 byte) */
2259  return TRUE;
2260 }
2261 
2262 static BOOL update_send_pointer_large(rdpContext* context, const POINTER_LARGE_UPDATE* pointer)
2263 {
2264  wStream* s = NULL;
2265  WINPR_ASSERT(context);
2266  rdpRdp* rdp = context->rdp;
2267  BOOL ret = FALSE;
2268 
2269  WINPR_ASSERT(rdp);
2270  WINPR_ASSERT(pointer);
2271  s = fastpath_update_pdu_init(rdp->fastpath);
2272 
2273  if (!s)
2274  return FALSE;
2275 
2276  if (!update_write_pointer_large(s, pointer))
2277  goto out_fail;
2278 
2279  ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_LARGE_POINTER, s, FALSE);
2280 out_fail:
2281  Stream_Release(s);
2282  return ret;
2283 }
2284 
2285 static BOOL update_send_pointer_new(rdpContext* context, const POINTER_NEW_UPDATE* pointer_new)
2286 {
2287  wStream* s = NULL;
2288 
2289  WINPR_ASSERT(context);
2290  rdpRdp* rdp = context->rdp;
2291  BOOL ret = FALSE;
2292 
2293  WINPR_ASSERT(rdp);
2294  WINPR_ASSERT(pointer_new);
2295  s = fastpath_update_pdu_init(rdp->fastpath);
2296 
2297  if (!s)
2298  return FALSE;
2299 
2300  if (!Stream_EnsureRemainingCapacity(s, 16))
2301  goto out_fail;
2302 
2303  Stream_Write_UINT16(s, pointer_new->xorBpp); /* xorBpp (2 bytes) */
2304  update_write_pointer_color(s, &pointer_new->colorPtrAttr);
2305  ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_POINTER, s, FALSE);
2306 out_fail:
2307  Stream_Release(s);
2308  return ret;
2309 }
2310 
2311 static BOOL update_send_pointer_cached(rdpContext* context,
2312  const POINTER_CACHED_UPDATE* pointer_cached)
2313 {
2314  wStream* s = NULL;
2315 
2316  WINPR_ASSERT(context);
2317  rdpRdp* rdp = context->rdp;
2318  BOOL ret = 0;
2319 
2320  WINPR_ASSERT(rdp);
2321  WINPR_ASSERT(pointer_cached);
2322  s = fastpath_update_pdu_init(rdp->fastpath);
2323 
2324  if (!s)
2325  return FALSE;
2326 
2327  Stream_Write_UINT16(s, pointer_cached->cacheIndex); /* cacheIndex (2 bytes) */
2328  ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_CACHED, s, FALSE);
2329  Stream_Release(s);
2330  return ret;
2331 }
2332 
2333 BOOL update_read_refresh_rect(rdpUpdate* update, wStream* s)
2334 {
2335  BYTE numberOfAreas = 0;
2336  RECTANGLE_16 areas[256] = { 0 };
2337  rdp_update_internal* up = update_cast(update);
2338 
2339  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
2340  return FALSE;
2341 
2342  Stream_Read_UINT8(s, numberOfAreas);
2343  Stream_Seek(s, 3); /* pad3Octects */
2344 
2345  if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, numberOfAreas, 8ull))
2346  return FALSE;
2347 
2348  for (BYTE index = 0; index < numberOfAreas; index++)
2349  {
2350  RECTANGLE_16* area = &areas[index];
2351 
2352  Stream_Read_UINT16(s, area->left);
2353  Stream_Read_UINT16(s, area->top);
2354  Stream_Read_UINT16(s, area->right);
2355  Stream_Read_UINT16(s, area->bottom);
2356  }
2357 
2358  WINPR_ASSERT(update->context);
2359  WINPR_ASSERT(update->context->settings);
2360  if (update->context->settings->RefreshRect)
2361  IFCALL(update->RefreshRect, update->context, numberOfAreas, areas);
2362  else
2363  WLog_Print(up->log, WLOG_WARN, "ignoring refresh rect request from client");
2364 
2365  return TRUE;
2366 }
2367 
2368 BOOL update_read_suppress_output(rdpUpdate* update, wStream* s)
2369 {
2370  rdp_update_internal* up = update_cast(update);
2371  RECTANGLE_16* prect = NULL;
2372  RECTANGLE_16 rect = { 0 };
2373  BYTE allowDisplayUpdates = 0;
2374 
2375  WINPR_ASSERT(up);
2376  WINPR_ASSERT(s);
2377 
2378  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
2379  return FALSE;
2380 
2381  Stream_Read_UINT8(s, allowDisplayUpdates);
2382  Stream_Seek(s, 3); /* pad3Octects */
2383 
2384  if (allowDisplayUpdates > 0)
2385  {
2386  if (!Stream_CheckAndLogRequiredLength(TAG, s, sizeof(RECTANGLE_16)))
2387  return FALSE;
2388 
2389  Stream_Read_UINT16(s, rect.left);
2390  Stream_Read_UINT16(s, rect.top);
2391  Stream_Read_UINT16(s, rect.right);
2392  Stream_Read_UINT16(s, rect.bottom);
2393 
2394  prect = &rect;
2395  }
2396 
2397  WINPR_ASSERT(update->context);
2398  WINPR_ASSERT(update->context->settings);
2399  if (update->context->settings->SuppressOutput)
2400  IFCALL(update->SuppressOutput, update->context, allowDisplayUpdates, prect);
2401  else
2402  WLog_Print(up->log, WLOG_WARN, "ignoring suppress output request from client");
2403 
2404  return TRUE;
2405 }
2406 
2407 static BOOL update_send_set_keyboard_indicators(rdpContext* context, UINT16 led_flags)
2408 {
2409  wStream* s = NULL;
2410 
2411  WINPR_ASSERT(context);
2412  rdpRdp* rdp = context->rdp;
2413  s = rdp_data_pdu_init(rdp);
2414 
2415  if (!s)
2416  return FALSE;
2417 
2418  Stream_Write_UINT16(s, 0); /* unitId should be 0 according to MS-RDPBCGR 2.2.8.2.1.1 */
2419  Stream_Write_UINT16(s, led_flags); /* ledFlags (2 bytes) */
2420 
2421  WINPR_ASSERT(rdp->mcs);
2422  return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS, rdp->mcs->userId);
2423 }
2424 
2425 static BOOL update_send_set_keyboard_ime_status(rdpContext* context, UINT16 imeId, UINT32 imeState,
2426  UINT32 imeConvMode)
2427 {
2428  wStream* s = NULL;
2429 
2430  WINPR_ASSERT(context);
2431  rdpRdp* rdp = context->rdp;
2432  s = rdp_data_pdu_init(rdp);
2433 
2434  if (!s)
2435  return FALSE;
2436 
2437  /* unitId should be 0 according to MS-RDPBCGR 2.2.8.2.2.1 */
2438  Stream_Write_UINT16(s, imeId);
2439  Stream_Write_UINT32(s, imeState);
2440  Stream_Write_UINT32(s, imeConvMode);
2441 
2442  WINPR_ASSERT(rdp->mcs);
2443  return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS, rdp->mcs->userId);
2444 }
2445 
2446 static UINT16 update_calculate_new_or_existing_window(const WINDOW_ORDER_INFO* orderInfo,
2447  const WINDOW_STATE_ORDER* stateOrder)
2448 {
2449  UINT16 orderSize = 11;
2450 
2451  WINPR_ASSERT(orderInfo);
2452  WINPR_ASSERT(stateOrder);
2453 
2454  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OWNER) != 0)
2455  orderSize += 4;
2456 
2457  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_STYLE) != 0)
2458  orderSize += 8;
2459 
2460  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_SHOW) != 0)
2461  orderSize += 1;
2462 
2463  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE) != 0)
2464  orderSize += 2 + stateOrder->titleInfo.length;
2465 
2466  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) != 0)
2467  orderSize += 8;
2468 
2469  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) != 0)
2470  orderSize += 8;
2471 
2472  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_X) != 0)
2473  orderSize += 8;
2474 
2475  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_Y) != 0)
2476  orderSize += 8;
2477 
2478  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT) != 0)
2479  orderSize += 1;
2480 
2481  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT) != 0)
2482  orderSize += 4;
2483 
2484  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) != 0)
2485  orderSize += 8;
2486 
2487  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) != 0)
2488  orderSize += 8;
2489 
2490  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) != 0)
2491  orderSize += 8;
2492 
2493  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) != 0)
2494  orderSize += 2 + stateOrder->numWindowRects * sizeof(RECTANGLE_16);
2495 
2496  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) != 0)
2497  orderSize += 8;
2498 
2499  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) != 0)
2500  orderSize += 2 + stateOrder->numVisibilityRects * sizeof(RECTANGLE_16);
2501 
2502  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OVERLAY_DESCRIPTION) != 0)
2503  orderSize += 2 + stateOrder->OverlayDescription.length;
2504 
2505  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TASKBAR_BUTTON) != 0)
2506  orderSize += 1;
2507 
2508  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ENFORCE_SERVER_ZORDER) != 0)
2509  orderSize += 1;
2510 
2511  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_STATE) != 0)
2512  orderSize += 1;
2513 
2514  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_EDGE) != 0)
2515  orderSize += 1;
2516 
2517  return orderSize;
2518 }
2519 
2520 static BOOL update_send_new_or_existing_window(rdpContext* context,
2521  const WINDOW_ORDER_INFO* orderInfo,
2522  const WINDOW_STATE_ORDER* stateOrder)
2523 {
2524  BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2525  UINT16 orderSize = update_calculate_new_or_existing_window(orderInfo, stateOrder);
2526 
2527  WINPR_ASSERT(context);
2528  WINPR_ASSERT(orderInfo);
2529  WINPR_ASSERT(stateOrder);
2530 
2531  rdp_update_internal* update = update_cast(context->update);
2532 
2533  if (!update_check_flush(context, orderSize))
2534  return FALSE;
2535 
2536  wStream* s = update->us;
2537 
2538  if (!s)
2539  return FALSE;
2540 
2541  if (!Stream_EnsureRemainingCapacity(s, orderSize))
2542  return FALSE;
2543 
2544  Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */
2545  Stream_Write_UINT16(s, orderSize); /* OrderSize (2 bytes) */
2546  Stream_Write_UINT32(s, orderInfo->fieldFlags); /* FieldsPresentFlags (4 bytes) */
2547  Stream_Write_UINT32(s, orderInfo->windowId); /* WindowID (4 bytes) */
2548 
2549  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OWNER) != 0)
2550  Stream_Write_UINT32(s, stateOrder->ownerWindowId);
2551 
2552  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_STYLE) != 0)
2553  {
2554  Stream_Write_UINT32(s, stateOrder->style);
2555  Stream_Write_UINT32(s, stateOrder->extendedStyle);
2556  }
2557 
2558  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_SHOW) != 0)
2559  {
2560  Stream_Write_UINT8(s, stateOrder->showState);
2561  }
2562 
2563  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE) != 0)
2564  {
2565  Stream_Write_UINT16(s, stateOrder->titleInfo.length);
2566  Stream_Write(s, stateOrder->titleInfo.string, stateOrder->titleInfo.length);
2567  }
2568 
2569  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) != 0)
2570  {
2571  Stream_Write_INT32(s, stateOrder->clientOffsetX);
2572  Stream_Write_INT32(s, stateOrder->clientOffsetY);
2573  }
2574 
2575  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) != 0)
2576  {
2577  Stream_Write_UINT32(s, stateOrder->clientAreaWidth);
2578  Stream_Write_UINT32(s, stateOrder->clientAreaHeight);
2579  }
2580 
2581  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_X) != 0)
2582  {
2583  Stream_Write_UINT32(s, stateOrder->resizeMarginLeft);
2584  Stream_Write_UINT32(s, stateOrder->resizeMarginRight);
2585  }
2586 
2587  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_Y) != 0)
2588  {
2589  Stream_Write_UINT32(s, stateOrder->resizeMarginTop);
2590  Stream_Write_UINT32(s, stateOrder->resizeMarginBottom);
2591  }
2592 
2593  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT) != 0)
2594  {
2595  Stream_Write_UINT8(s, stateOrder->RPContent);
2596  }
2597 
2598  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT) != 0)
2599  {
2600  Stream_Write_UINT32(s, stateOrder->rootParentHandle);
2601  }
2602 
2603  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) != 0)
2604  {
2605  Stream_Write_INT32(s, stateOrder->windowOffsetX);
2606  Stream_Write_INT32(s, stateOrder->windowOffsetY);
2607  }
2608 
2609  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) != 0)
2610  {
2611  Stream_Write_INT32(s, stateOrder->windowClientDeltaX);
2612  Stream_Write_INT32(s, stateOrder->windowClientDeltaY);
2613  }
2614 
2615  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) != 0)
2616  {
2617  Stream_Write_UINT32(s, stateOrder->windowWidth);
2618  Stream_Write_UINT32(s, stateOrder->windowHeight);
2619  }
2620 
2621  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) != 0)
2622  {
2623  Stream_Write_UINT16(s, stateOrder->numWindowRects);
2624  Stream_Write(s, stateOrder->windowRects, stateOrder->numWindowRects * sizeof(RECTANGLE_16));
2625  }
2626 
2627  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) != 0)
2628  {
2629  Stream_Write_INT32(s, stateOrder->visibleOffsetX);
2630  Stream_Write_INT32(s, stateOrder->visibleOffsetY);
2631  }
2632 
2633  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) != 0)
2634  {
2635  Stream_Write_UINT16(s, stateOrder->numVisibilityRects);
2636  Stream_Write(s, stateOrder->visibilityRects,
2637  stateOrder->numVisibilityRects * sizeof(RECTANGLE_16));
2638  }
2639 
2640  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OVERLAY_DESCRIPTION) != 0)
2641  {
2642  Stream_Write_UINT16(s, stateOrder->OverlayDescription.length);
2643  Stream_Write(s, stateOrder->OverlayDescription.string,
2644  stateOrder->OverlayDescription.length);
2645  }
2646 
2647  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TASKBAR_BUTTON) != 0)
2648  {
2649  Stream_Write_UINT8(s, stateOrder->TaskbarButton);
2650  }
2651 
2652  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ENFORCE_SERVER_ZORDER) != 0)
2653  {
2654  Stream_Write_UINT8(s, stateOrder->EnforceServerZOrder);
2655  }
2656 
2657  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_STATE) != 0)
2658  {
2659  Stream_Write_UINT8(s, stateOrder->AppBarState);
2660  }
2661 
2662  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_EDGE) != 0)
2663  {
2664  Stream_Write_UINT8(s, stateOrder->AppBarEdge);
2665  }
2666 
2667  update->numberOrders++;
2668  return TRUE;
2669 }
2670 
2671 static BOOL update_send_window_create(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
2672  const WINDOW_STATE_ORDER* stateOrder)
2673 {
2674  return update_send_new_or_existing_window(context, orderInfo, stateOrder);
2675 }
2676 
2677 static BOOL update_send_window_update(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
2678  const WINDOW_STATE_ORDER* stateOrder)
2679 {
2680  return update_send_new_or_existing_window(context, orderInfo, stateOrder);
2681 }
2682 
2683 static UINT16 update_calculate_window_icon_order(const WINDOW_ORDER_INFO* orderInfo,
2684  const WINDOW_ICON_ORDER* iconOrder)
2685 {
2686  UINT16 orderSize = 23;
2687 
2688  WINPR_ASSERT(iconOrder);
2689  ICON_INFO* iconInfo = iconOrder->iconInfo;
2690  WINPR_ASSERT(iconInfo);
2691 
2692  orderSize += iconInfo->cbBitsColor + iconInfo->cbBitsMask;
2693 
2694  if (iconInfo->bpp <= 8)
2695  orderSize += 2 + iconInfo->cbColorTable;
2696 
2697  return orderSize;
2698 }
2699 
2700 static BOOL update_send_window_icon(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
2701  const WINDOW_ICON_ORDER* iconOrder)
2702 {
2703  BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2704 
2705  WINPR_ASSERT(iconOrder);
2706  ICON_INFO* iconInfo = iconOrder->iconInfo;
2707  UINT16 orderSize = update_calculate_window_icon_order(orderInfo, iconOrder);
2708 
2709  WINPR_ASSERT(context);
2710  WINPR_ASSERT(orderInfo);
2711  WINPR_ASSERT(iconInfo);
2712 
2713  rdp_update_internal* update = update_cast(context->update);
2714 
2715  if (!update_check_flush(context, orderSize))
2716  return FALSE;
2717 
2718  wStream* s = update->us;
2719 
2720  if (!s || !iconInfo)
2721  return FALSE;
2722 
2723  if (!Stream_EnsureRemainingCapacity(s, orderSize))
2724  return FALSE;
2725 
2726  /* Write Hdr */
2727  Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */
2728  Stream_Write_UINT16(s, orderSize); /* OrderSize (2 bytes) */
2729  Stream_Write_UINT32(s, orderInfo->fieldFlags); /* FieldsPresentFlags (4 bytes) */
2730  Stream_Write_UINT32(s, orderInfo->windowId); /* WindowID (4 bytes) */
2731  /* Write body */
2732  Stream_Write_UINT16(s, iconInfo->cacheEntry); /* CacheEntry (2 bytes) */
2733  Stream_Write_UINT8(s, iconInfo->cacheId); /* CacheId (1 byte) */
2734  Stream_Write_UINT8(s, iconInfo->bpp); /* Bpp (1 byte) */
2735  Stream_Write_UINT16(s, iconInfo->width); /* Width (2 bytes) */
2736  Stream_Write_UINT16(s, iconInfo->height); /* Height (2 bytes) */
2737 
2738  if (iconInfo->bpp <= 8)
2739  {
2740  Stream_Write_UINT16(s, iconInfo->cbColorTable); /* CbColorTable (2 bytes) */
2741  }
2742 
2743  Stream_Write_UINT16(s, iconInfo->cbBitsMask); /* CbBitsMask (2 bytes) */
2744  Stream_Write_UINT16(s, iconInfo->cbBitsColor); /* CbBitsColor (2 bytes) */
2745  Stream_Write(s, iconInfo->bitsMask, iconInfo->cbBitsMask); /* BitsMask (variable) */
2746 
2747  if (iconInfo->bpp <= 8)
2748  {
2749  Stream_Write(s, iconInfo->colorTable, iconInfo->cbColorTable); /* ColorTable (variable) */
2750  }
2751 
2752  Stream_Write(s, iconInfo->bitsColor, iconInfo->cbBitsColor); /* BitsColor (variable) */
2753 
2754  update->numberOrders++;
2755  return TRUE;
2756 }
2757 
2758 static BOOL update_send_window_cached_icon(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
2759  const WINDOW_CACHED_ICON_ORDER* cachedIconOrder)
2760 {
2761  BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2762  UINT16 orderSize = 14;
2763 
2764  WINPR_ASSERT(cachedIconOrder);
2765  const CACHED_ICON_INFO* cachedIcon = &cachedIconOrder->cachedIcon;
2766 
2767  WINPR_ASSERT(context);
2768  WINPR_ASSERT(orderInfo);
2769  WINPR_ASSERT(cachedIcon);
2770 
2771  rdp_update_internal* update = update_cast(context->update);
2772 
2773  if (!update_check_flush(context, orderSize))
2774  return FALSE;
2775 
2776  wStream* s = update->us;
2777  if (!s)
2778  return FALSE;
2779 
2780  if (!Stream_EnsureRemainingCapacity(s, orderSize))
2781  return FALSE;
2782 
2783  /* Write Hdr */
2784  Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */
2785  Stream_Write_UINT16(s, orderSize); /* OrderSize (2 bytes) */
2786  Stream_Write_UINT32(s, orderInfo->fieldFlags); /* FieldsPresentFlags (4 bytes) */
2787  Stream_Write_UINT32(s, orderInfo->windowId); /* WindowID (4 bytes) */
2788  /* Write body */
2789  Stream_Write_UINT16(s, cachedIcon->cacheEntry); /* CacheEntry (2 bytes) */
2790  Stream_Write_UINT8(s, cachedIcon->cacheId); /* CacheId (1 byte) */
2791  update->numberOrders++;
2792  return TRUE;
2793 }
2794 
2795 static BOOL update_send_window_delete(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo)
2796 {
2797  BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2798  UINT16 orderSize = 11;
2799 
2800  WINPR_ASSERT(context);
2801  WINPR_ASSERT(orderInfo);
2802  rdp_update_internal* update = update_cast(context->update);
2803 
2804  if (!update_check_flush(context, orderSize))
2805  return FALSE;
2806 
2807  wStream* s = update->us;
2808 
2809  if (!s)
2810  return FALSE;
2811 
2812  if (!Stream_EnsureRemainingCapacity(s, orderSize))
2813  return FALSE;
2814 
2815  /* Write Hdr */
2816  Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */
2817  Stream_Write_UINT16(s, orderSize); /* OrderSize (2 bytes) */
2818  Stream_Write_UINT32(s, orderInfo->fieldFlags); /* FieldsPresentFlags (4 bytes) */
2819  Stream_Write_UINT32(s, orderInfo->windowId); /* WindowID (4 bytes) */
2820  update->numberOrders++;
2821  return TRUE;
2822 }
2823 
2824 static UINT16 update_calculate_new_or_existing_notification_icons_order(
2825  const WINDOW_ORDER_INFO* orderInfo, const NOTIFY_ICON_STATE_ORDER* iconStateOrder)
2826 {
2827  UINT16 orderSize = 15;
2828 
2829  WINPR_ASSERT(orderInfo);
2830  WINPR_ASSERT(iconStateOrder);
2831 
2832  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_VERSION) != 0)
2833  orderSize += 4;
2834 
2835  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP) != 0)
2836  {
2837  orderSize += 2 + iconStateOrder->toolTip.length;
2838  }
2839 
2840  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP) != 0)
2841  {
2842  NOTIFY_ICON_INFOTIP infoTip = iconStateOrder->infoTip;
2843  orderSize += 12 + infoTip.text.length + infoTip.title.length;
2844  }
2845 
2846  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_STATE) != 0)
2847  {
2848  orderSize += 4;
2849  }
2850 
2851  if ((orderInfo->fieldFlags & WINDOW_ORDER_ICON) != 0)
2852  {
2853  ICON_INFO iconInfo = iconStateOrder->icon;
2854  orderSize += 12;
2855 
2856  if (iconInfo.bpp <= 8)
2857  orderSize += 2 + iconInfo.cbColorTable;
2858 
2859  orderSize += iconInfo.cbBitsMask + iconInfo.cbBitsColor;
2860  }
2861  else if ((orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON) != 0)
2862  {
2863  orderSize += 3;
2864  }
2865 
2866  return orderSize;
2867 }
2868 
2869 static BOOL
2870 update_send_new_or_existing_notification_icons(rdpContext* context,
2871  const WINDOW_ORDER_INFO* orderInfo,
2872  const NOTIFY_ICON_STATE_ORDER* iconStateOrder)
2873 {
2874  BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2875  BOOL versionFieldPresent = FALSE;
2876  const UINT16 orderSize =
2877  update_calculate_new_or_existing_notification_icons_order(orderInfo, iconStateOrder);
2878 
2879  WINPR_ASSERT(context);
2880  WINPR_ASSERT(orderInfo);
2881  WINPR_ASSERT(iconStateOrder);
2882  rdp_update_internal* update = update_cast(context->update);
2883 
2884  if (!update_check_flush(context, orderSize))
2885  return FALSE;
2886 
2887  wStream* s = update->us;
2888  if (!s)
2889  return FALSE;
2890 
2891  if (!Stream_EnsureRemainingCapacity(s, orderSize))
2892  return FALSE;
2893 
2894  /* Write Hdr */
2895  Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */
2896  Stream_Write_UINT16(s, orderSize); /* OrderSize (2 bytes) */
2897  Stream_Write_UINT32(s, orderInfo->fieldFlags); /* FieldsPresentFlags (4 bytes) */
2898  Stream_Write_UINT32(s, orderInfo->windowId); /* WindowID (4 bytes) */
2899  Stream_Write_UINT32(s, orderInfo->notifyIconId); /* NotifyIconId (4 bytes) */
2900 
2901  /* Write body */
2902  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_VERSION) != 0)
2903  {
2904  versionFieldPresent = TRUE;
2905  Stream_Write_UINT32(s, iconStateOrder->version);
2906  }
2907 
2908  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP) != 0)
2909  {
2910  Stream_Write_UINT16(s, iconStateOrder->toolTip.length);
2911  Stream_Write(s, iconStateOrder->toolTip.string, iconStateOrder->toolTip.length);
2912  }
2913 
2914  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP) != 0)
2915  {
2916  NOTIFY_ICON_INFOTIP infoTip = iconStateOrder->infoTip;
2917 
2918  /* info tip should not be sent when version is 0 */
2919  if (versionFieldPresent && iconStateOrder->version == 0)
2920  return FALSE;
2921 
2922  Stream_Write_UINT32(s, infoTip.timeout); /* Timeout (4 bytes) */
2923  Stream_Write_UINT32(s, infoTip.flags); /* InfoFlags (4 bytes) */
2924  Stream_Write_UINT16(s, infoTip.text.length); /* InfoTipText (variable) */
2925  Stream_Write(s, infoTip.text.string, infoTip.text.length);
2926  Stream_Write_UINT16(s, infoTip.title.length); /* Title (variable) */
2927  Stream_Write(s, infoTip.title.string, infoTip.title.length);
2928  }
2929 
2930  if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_STATE) != 0)
2931  {
2932  /* notify state should not be sent when version is 0 */
2933  if (versionFieldPresent && iconStateOrder->version == 0)
2934  return FALSE;
2935 
2936  Stream_Write_UINT32(s, iconStateOrder->state);
2937  }
2938 
2939  if ((orderInfo->fieldFlags & WINDOW_ORDER_ICON) != 0)
2940  {
2941  ICON_INFO iconInfo = iconStateOrder->icon;
2942  Stream_Write_UINT16(s, iconInfo.cacheEntry); /* CacheEntry (2 bytes) */
2943  Stream_Write_UINT8(s, iconInfo.cacheId); /* CacheId (1 byte) */
2944  Stream_Write_UINT8(s, iconInfo.bpp); /* Bpp (1 byte) */
2945  Stream_Write_UINT16(s, iconInfo.width); /* Width (2 bytes) */
2946  Stream_Write_UINT16(s, iconInfo.height); /* Height (2 bytes) */
2947 
2948  if (iconInfo.bpp <= 8)
2949  {
2950  Stream_Write_UINT16(s, iconInfo.cbColorTable); /* CbColorTable (2 bytes) */
2951  }
2952 
2953  Stream_Write_UINT16(s, iconInfo.cbBitsMask); /* CbBitsMask (2 bytes) */
2954  Stream_Write_UINT16(s, iconInfo.cbBitsColor); /* CbBitsColor (2 bytes) */
2955  Stream_Write(s, iconInfo.bitsMask, iconInfo.cbBitsMask); /* BitsMask (variable) */
2956 
2957  if (iconInfo.bpp <= 8)
2958  {
2959  Stream_Write(s, iconInfo.colorTable, iconInfo.cbColorTable); /* ColorTable (variable) */
2960  }
2961 
2962  Stream_Write(s, iconInfo.bitsColor, iconInfo.cbBitsColor); /* BitsColor (variable) */
2963  }
2964  else if ((orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON) != 0)
2965  {
2966  CACHED_ICON_INFO cachedIcon = iconStateOrder->cachedIcon;
2967  Stream_Write_UINT16(s, cachedIcon.cacheEntry); /* CacheEntry (2 bytes) */
2968  Stream_Write_UINT8(s, cachedIcon.cacheId); /* CacheId (1 byte) */
2969  }
2970 
2971  update->numberOrders++;
2972  return TRUE;
2973 }
2974 
2975 static BOOL update_send_notify_icon_create(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
2976  const NOTIFY_ICON_STATE_ORDER* iconStateOrder)
2977 {
2978  return update_send_new_or_existing_notification_icons(context, orderInfo, iconStateOrder);
2979 }
2980 
2981 static BOOL update_send_notify_icon_update(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
2982  const NOTIFY_ICON_STATE_ORDER* iconStateOrder)
2983 {
2984  return update_send_new_or_existing_notification_icons(context, orderInfo, iconStateOrder);
2985 }
2986 
2987 static BOOL update_send_notify_icon_delete(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo)
2988 {
2989  BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2990  UINT16 orderSize = 15;
2991 
2992  WINPR_ASSERT(context);
2993  WINPR_ASSERT(orderInfo);
2994  rdp_update_internal* update = update_cast(context->update);
2995 
2996  if (!update_check_flush(context, orderSize))
2997  return FALSE;
2998 
2999  wStream* s = update->us;
3000 
3001  if (!s)
3002  return FALSE;
3003 
3004  /* Write Hdr */
3005  Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */
3006  Stream_Write_UINT16(s, orderSize); /* OrderSize (2 bytes) */
3007  Stream_Write_UINT32(s, orderInfo->fieldFlags); /* FieldsPresentFlags (4 bytes) */
3008  Stream_Write_UINT32(s, orderInfo->windowId); /* WindowID (4 bytes) */
3009  Stream_Write_UINT32(s, orderInfo->notifyIconId); /* NotifyIconId (4 bytes) */
3010  update->numberOrders++;
3011  return TRUE;
3012 }
3013 
3014 static UINT16 update_calculate_monitored_desktop(const WINDOW_ORDER_INFO* orderInfo,
3015  const MONITORED_DESKTOP_ORDER* monitoredDesktop)
3016 {
3017  UINT16 orderSize = 7;
3018 
3019  WINPR_ASSERT(orderInfo);
3020  WINPR_ASSERT(monitoredDesktop);
3021 
3022  if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
3023  {
3024  orderSize += 4;
3025  }
3026 
3027  if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
3028  {
3029  orderSize += 1 + (4 * monitoredDesktop->numWindowIds);
3030  }
3031 
3032  return orderSize;
3033 }
3034 
3035 static BOOL update_send_monitored_desktop(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
3036  const MONITORED_DESKTOP_ORDER* monitoredDesktop)
3037 {
3038  BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
3039  UINT16 orderSize = update_calculate_monitored_desktop(orderInfo, monitoredDesktop);
3040 
3041  WINPR_ASSERT(context);
3042  WINPR_ASSERT(orderInfo);
3043  WINPR_ASSERT(monitoredDesktop);
3044 
3045  rdp_update_internal* update = update_cast(context->update);
3046 
3047  if (!update_check_flush(context, orderSize))
3048  return FALSE;
3049 
3050  wStream* s = update->us;
3051 
3052  if (!s)
3053  return FALSE;
3054 
3055  Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */
3056  Stream_Write_UINT16(s, orderSize); /* OrderSize (2 bytes) */
3057  Stream_Write_UINT32(s, orderInfo->fieldFlags); /* FieldsPresentFlags (4 bytes) */
3058 
3059  if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
3060  {
3061  Stream_Write_UINT32(s, monitoredDesktop->activeWindowId); /* activeWindowId (4 bytes) */
3062  }
3063 
3064  if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
3065  {
3066  Stream_Write_UINT8(s, monitoredDesktop->numWindowIds); /* numWindowIds (1 byte) */
3067 
3068  /* windowIds */
3069  for (UINT32 i = 0; i < monitoredDesktop->numWindowIds; i++)
3070  {
3071  Stream_Write_UINT32(s, monitoredDesktop->windowIds[i]);
3072  }
3073  }
3074 
3075  update->numberOrders++;
3076  return TRUE;
3077 }
3078 
3079 static BOOL update_send_non_monitored_desktop(rdpContext* context,
3080  const WINDOW_ORDER_INFO* orderInfo)
3081 {
3082  BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
3083  UINT16 orderSize = 7;
3084 
3085  WINPR_ASSERT(context);
3086  WINPR_ASSERT(orderInfo);
3087  rdp_update_internal* update = update_cast(context->update);
3088 
3089  if (!update_check_flush(context, orderSize))
3090  return FALSE;
3091 
3092  wStream* s = update->us;
3093 
3094  if (!s)
3095  return FALSE;
3096 
3097  Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */
3098  Stream_Write_UINT16(s, orderSize); /* OrderSize (2 bytes) */
3099  Stream_Write_UINT32(s, orderInfo->fieldFlags); /* FieldsPresentFlags (4 bytes) */
3100  update->numberOrders++;
3101  return TRUE;
3102 }
3103 
3104 void update_register_server_callbacks(rdpUpdate* update)
3105 {
3106  WINPR_ASSERT(update);
3107 
3108  update->BeginPaint = s_update_begin_paint;
3109  update->EndPaint = s_update_end_paint;
3110  update->SetBounds = update_set_bounds;
3111  update->Synchronize = update_send_synchronize;
3112  update->DesktopResize = update_send_desktop_resize;
3113  update->BitmapUpdate = update_send_bitmap_update;
3114  update->SurfaceBits = update_send_surface_bits;
3115  update->SurfaceFrameMarker = update_send_surface_frame_marker;
3116  update->SurfaceCommand = update_send_surface_command;
3117  update->SurfaceFrameBits = update_send_surface_frame_bits;
3118  update->PlaySound = update_send_play_sound;
3119  update->SetKeyboardIndicators = update_send_set_keyboard_indicators;
3120  update->SetKeyboardImeStatus = update_send_set_keyboard_ime_status;
3121  update->SaveSessionInfo = rdp_send_save_session_info;
3122  update->ServerStatusInfo = rdp_send_server_status_info;
3123  update->primary->DstBlt = update_send_dstblt;
3124  update->primary->PatBlt = update_send_patblt;
3125  update->primary->ScrBlt = update_send_scrblt;
3126  update->primary->OpaqueRect = update_send_opaque_rect;
3127  update->primary->LineTo = update_send_line_to;
3128  update->primary->MemBlt = update_send_memblt;
3129  update->primary->GlyphIndex = update_send_glyph_index;
3130  update->secondary->CacheBitmap = update_send_cache_bitmap;
3131  update->secondary->CacheBitmapV2 = update_send_cache_bitmap_v2;
3132  update->secondary->CacheBitmapV3 = update_send_cache_bitmap_v3;
3133  update->secondary->CacheColorTable = update_send_cache_color_table;
3134  update->secondary->CacheGlyph = update_send_cache_glyph;
3135  update->secondary->CacheGlyphV2 = update_send_cache_glyph_v2;
3136  update->secondary->CacheBrush = update_send_cache_brush;
3137  update->altsec->CreateOffscreenBitmap = update_send_create_offscreen_bitmap_order;
3138  update->altsec->SwitchSurface = update_send_switch_surface_order;
3139  update->pointer->PointerSystem = update_send_pointer_system;
3140  update->pointer->PointerPosition = update_send_pointer_position;
3141  update->pointer->PointerColor = update_send_pointer_color;
3142  update->pointer->PointerLarge = update_send_pointer_large;
3143  update->pointer->PointerNew = update_send_pointer_new;
3144  update->pointer->PointerCached = update_send_pointer_cached;
3145  update->window->WindowCreate = update_send_window_create;
3146  update->window->WindowUpdate = update_send_window_update;
3147  update->window->WindowIcon = update_send_window_icon;
3148  update->window->WindowCachedIcon = update_send_window_cached_icon;
3149  update->window->WindowDelete = update_send_window_delete;
3150  update->window->NotifyIconCreate = update_send_notify_icon_create;
3151  update->window->NotifyIconUpdate = update_send_notify_icon_update;
3152  update->window->NotifyIconDelete = update_send_notify_icon_delete;
3153  update->window->MonitoredDesktop = update_send_monitored_desktop;
3154  update->window->NonMonitoredDesktop = update_send_non_monitored_desktop;
3155 }
3156 
3157 void update_register_client_callbacks(rdpUpdate* update)
3158 {
3159  WINPR_ASSERT(update);
3160 
3161  update->RefreshRect = update_send_refresh_rect;
3162  update->SuppressOutput = update_send_suppress_output;
3163  update->SurfaceFrameAcknowledge = update_send_frame_acknowledge;
3164 }
3165 
3166 int update_process_messages(rdpUpdate* update)
3167 {
3168  return update_message_queue_process_pending_messages(update);
3169 }
3170 
3171 static void update_free_queued_message(void* obj)
3172 {
3173  wMessage* msg = (wMessage*)obj;
3174  update_message_queue_free_message(msg);
3175 }
3176 
3177 void update_free_window_state(WINDOW_STATE_ORDER* window_state)
3178 {
3179  if (!window_state)
3180  return;
3181 
3182  free(window_state->OverlayDescription.string);
3183  free(window_state->titleInfo.string);
3184  free(window_state->windowRects);
3185  free(window_state->visibilityRects);
3186  memset(window_state, 0, sizeof(WINDOW_STATE_ORDER));
3187 }
3188 
3189 rdpUpdate* update_new(rdpRdp* rdp)
3190 {
3191  const wObject cb = { NULL, NULL, NULL, update_free_queued_message, NULL };
3192 
3193  WINPR_ASSERT(rdp);
3194  WINPR_ASSERT(rdp->context);
3195 
3196  rdp_update_internal* update = (rdp_update_internal*)calloc(1, sizeof(rdp_update_internal));
3197 
3198  if (!update)
3199  return NULL;
3200 
3201  update->common.context = rdp->context;
3202  update->log = WLog_Get("com.freerdp.core.update");
3203  InitializeCriticalSection(&(update->mux));
3204  update->common.pointer = (rdpPointerUpdate*)calloc(1, sizeof(rdpPointerUpdate));
3205 
3206  if (!update->common.pointer)
3207  goto fail;
3208 
3209  rdp_primary_update_internal* primary =
3211 
3212  if (!primary)
3213  goto fail;
3214  update->common.primary = &primary->common;
3215 
3216  rdp_secondary_update_internal* secondary =
3218 
3219  if (!secondary)
3220  goto fail;
3221  update->common.secondary = &secondary->common;
3222 
3223  rdp_altsec_update_internal* altsec =
3225 
3226  if (!altsec)
3227  goto fail;
3228 
3229  update->common.altsec = &altsec->common;
3230  update->common.window = (rdpWindowUpdate*)calloc(1, sizeof(rdpWindowUpdate));
3231 
3232  if (!update->common.window)
3233  goto fail;
3234 
3235  OFFSCREEN_DELETE_LIST* deleteList = &(altsec->create_offscreen_bitmap.deleteList);
3236  deleteList->sIndices = 64;
3237  deleteList->indices = calloc(deleteList->sIndices, 2);
3238 
3239  if (!deleteList->indices)
3240  goto fail;
3241 
3242  deleteList->cIndices = 0;
3243  update->common.SuppressOutput = update_send_suppress_output;
3244  update->initialState = TRUE;
3245  update->common.autoCalculateBitmapData = TRUE;
3246  update->queue = MessageQueue_New(&cb);
3247 
3248  if (!update->queue)
3249  goto fail;
3250 
3251  return &update->common;
3252 fail:
3253  WINPR_PRAGMA_DIAG_PUSH
3254  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
3255  update_free(&update->common);
3256  WINPR_PRAGMA_DIAG_POP
3257  return NULL;
3258 }
3259 
3260 void update_free(rdpUpdate* update)
3261 {
3262  if (update != NULL)
3263  {
3264  rdp_update_internal* up = update_cast(update);
3265  rdp_altsec_update_internal* altsec = altsec_update_cast(update->altsec);
3266  OFFSCREEN_DELETE_LIST* deleteList = &(altsec->create_offscreen_bitmap.deleteList);
3267 
3268  if (deleteList)
3269  free(deleteList->indices);
3270 
3271  free(update->pointer);
3272 
3273  if (update->primary)
3274  {
3275  rdp_primary_update_internal* primary = primary_update_cast(update->primary);
3276 
3277  free(primary->polygon_cb.points);
3278  free(primary->polyline.points);
3279  free(primary->polygon_sc.points);
3280  free(primary->fast_glyph.glyphData.aj);
3281  free(primary);
3282  }
3283 
3284  free(update->secondary);
3285  free(altsec);
3286 
3287  if (update->window)
3288  free(update->window);
3289 
3290  MessageQueue_Free(up->queue);
3291  DeleteCriticalSection(&up->mux);
3292 
3293  if (up->us)
3294  Stream_Free(up->us, TRUE);
3295  free(update);
3296  }
3297 }
3298 
3299 void rdp_update_lock(rdpUpdate* update)
3300 {
3301  rdp_update_internal* up = update_cast(update);
3302  EnterCriticalSection(&up->mux);
3303 }
3304 
3305 void rdp_update_unlock(rdpUpdate* update)
3306 {
3307  rdp_update_internal* up = update_cast(update);
3308  LeaveCriticalSection(&up->mux);
3309 }
3310 
3311 BOOL update_begin_paint(rdpUpdate* update)
3312 {
3313  rdp_update_internal* up = update_cast(update);
3314  WINPR_ASSERT(update);
3315  rdp_update_lock(update);
3316 
3317  up->withinBeginEndPaint = TRUE;
3318 
3319  WINPR_ASSERT(update->context);
3320 
3321  BOOL rc = IFCALLRESULT(TRUE, update->BeginPaint, update->context);
3322  if (!rc)
3323  WLog_WARN(TAG, "BeginPaint call failed");
3324 
3325  /* Reset the invalid regions, we start a new frame here. */
3326  rdpGdi* gdi = update->context->gdi;
3327  if (!gdi)
3328  return rc;
3329 
3330  if (gdi->hdc && gdi->primary && gdi->primary->hdc)
3331  {
3332  HGDI_WND hwnd = gdi->primary->hdc->hwnd;
3333  WINPR_ASSERT(hwnd);
3334  WINPR_ASSERT(hwnd->invalid);
3335 
3336  hwnd->invalid->null = TRUE;
3337  hwnd->ninvalid = 0;
3338  }
3339 
3340  return rc;
3341 }
3342 
3343 BOOL update_end_paint(rdpUpdate* update)
3344 {
3345  BOOL rc = TRUE;
3346 
3347  WINPR_ASSERT(update);
3348  IFCALLRET(update->EndPaint, rc, update->context);
3349  if (!rc)
3350  WLog_WARN(TAG, "EndPaint call failed");
3351 
3352  rdp_update_internal* up = update_cast(update);
3353 
3354  if (!up->withinBeginEndPaint)
3355  return rc;
3356  up->withinBeginEndPaint = FALSE;
3357 
3358  rdp_update_unlock(update);
3359  return rc;
3360 }
Definition: types.h:82
This struct contains function pointer to initialize/free objects.
Definition: collections.h:57