22#include <freerdp/config.h>
25#include <winpr/print.h>
26#include <winpr/synch.h>
27#include <winpr/thread.h>
28#include <winpr/collections.h>
29#include <winpr/assert.h>
30#include <winpr/cast.h>
39#include <freerdp/log.h>
40#include <freerdp/peer.h>
41#include <freerdp/codec/bitmap.h>
43#include "../cache/pointer.h"
44#include "../cache/palette.h"
45#include "../cache/bitmap.h"
47#define TAG FREERDP_TAG("core.update")
49#define FORCE_ASYNC_UPDATE_OFF
51#define RDP_STATS_COUNT sizeof(rdp_stats) / sizeof(uint64_t)
54static INIT_ONCE stats_names_once = INIT_ONCE_STATIC_INIT;
55static char stats_names[RDP_STATS_COUNT][bufferlen];
58static BOOL CALLBACK stats_names_generate(WINPR_ATTR_UNUSED
PINIT_ONCE InitOnce,
59 WINPR_ATTR_UNUSED PVOID Parameter,
60 WINPR_ATTR_UNUSED PVOID* Context)
62 for (
size_t index = 0; index < RDP_STATS_COUNT; index++)
64 char* buffer = stats_names[index];
66 const rdp_stats stats = WINPR_C_ARRAY_INIT;
67 size_t limit = ARRAYSIZE(stats.primary);
71 char obuffer[64] = WINPR_C_ARRAY_INIT;
72 const char* str = primary_order_string(WINPR_ASSERTING_INT_CAST(UINT32, index), obuffer,
76 (void)_snprintf(buffer, bufferlen,
"RDP_STATS_ORDER_PRIMARY %s", str);
77 WINPR_ASSERT(strnlen(buffer, 2) > 0);
82 limit += ARRAYSIZE(stats.secondary);
85 char obuffer[64] = WINPR_C_ARRAY_INIT;
86 const char* str = secondary_order_string(
87 WINPR_ASSERTING_INT_CAST(UINT32, index - offset), obuffer,
sizeof(obuffer));
90 (void)_snprintf(buffer, bufferlen,
"RDP_STATS_ORDER_SECONDARY %s", str);
91 WINPR_ASSERT(strnlen(buffer, 2) > 0);
96 limit += ARRAYSIZE(stats.altsec);
99 char obuffer[64] = WINPR_C_ARRAY_INIT;
100 const char* str = altsec_order_string(WINPR_ASSERTING_INT_CAST(BYTE, index - offset),
101 obuffer,
sizeof(obuffer));
104 (void)_snprintf(buffer, bufferlen,
"RDP_STATS_ORDER_ALTSEC %s", str);
105 WINPR_ASSERT(strnlen(buffer, 2) > 0);
110 limit += ARRAYSIZE(stats.base);
115 (void)_snprintf(buffer, bufferlen, "%s", #x); \
118 switch (index - offset)
120 EVCASE(RDP_STATS_SURFACE_BITS);
121 EVCASE(RDP_STATS_SURFACE_BITS_NSC);
122 EVCASE(RDP_STATS_SURFACE_BITS_RFX);
123 EVCASE(RDP_STATS_SURFACE_BITS_RFX_IMAGE);
124 EVCASE(RDP_STATS_SURFACE_BITS_NONE);
125 EVCASE(RDP_STATS_SURFACE_BITS_UNKNOWN);
126 EVCASE(RDP_STATS_BEGIN_PAINT);
127 EVCASE(RDP_STATS_END_PAINT);
128 EVCASE(RDP_STATS_SET_BOUNDS);
129 EVCASE(RDP_STATS_SYNC);
130 EVCASE(RDP_STATS_RESIZE);
131 EVCASE(RDP_STATS_BITMAP_UPDATE);
132 EVCASE(RDP_STATS_PALETTE);
133 EVCASE(RDP_STATS_REFRESH_RECT);
134 EVCASE(RDP_STATS_SUPPRESS_OUTPUT);
135 EVCASE(RDP_STATS_SURFACE_COMMAND);
136 EVCASE(RDP_STATS_SURFACE_FRAME_MARKER);
137 EVCASE(RDP_STATS_SURFACE_FRAME_ACK);
138 EVCASE(RDP_STATS_POINTER_SYSTEM);
139 EVCASE(RDP_STATS_POINTER_DEFAULT);
140 EVCASE(RDP_STATS_POINTER_POSITION);
141 EVCASE(RDP_STATS_POINTER_COLOR);
142 EVCASE(RDP_STATS_POINTER_CACHED);
143 EVCASE(RDP_STATS_POINTER_NEW);
144 EVCASE(RDP_STATS_POINTER_LARGE);
146 (void)_snprintf(buffer, bufferlen,
"RDP_STATS_UNUSED");
152 (
void)_snprintf(buffer, bufferlen,
"RDP_STATS_UNUSED");
157static const char*
const UPDATE_TYPE_STRINGS[] = {
"Orders",
"Bitmap",
"Palette",
"Synchronize" };
160static const char* update_type_to_string(UINT16 updateType)
162 if (updateType >= ARRAYSIZE(UPDATE_TYPE_STRINGS))
165 return UPDATE_TYPE_STRINGS[updateType];
169static BOOL update_recv_orders(rdpUpdate* update,
wStream* s)
171 UINT16 numberOrders = 0;
173 WINPR_ASSERT(update);
175 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
178 Stream_Seek_UINT16(s);
179 Stream_Read_UINT16(s, numberOrders);
180 Stream_Seek_UINT16(s);
182 while (numberOrders > 0)
184 if (!update_recv_order(update, s))
186 WLog_ERR(TAG,
"update_recv_order() failed");
197static BOOL update_read_bitmap_data(rdpUpdate* update,
wStream* s,
BITMAP_DATA* bitmapData)
199 WINPR_UNUSED(update);
200 WINPR_ASSERT(bitmapData);
202 if (!Stream_CheckAndLogRequiredLength(TAG, s, 18))
205 Stream_Read_UINT16(s, bitmapData->destLeft);
206 Stream_Read_UINT16(s, bitmapData->destTop);
207 Stream_Read_UINT16(s, bitmapData->destRight);
208 Stream_Read_UINT16(s, bitmapData->destBottom);
209 Stream_Read_UINT16(s, bitmapData->width);
210 Stream_Read_UINT16(s, bitmapData->height);
211 Stream_Read_UINT16(s, bitmapData->bitsPerPixel);
212 Stream_Read_UINT16(s, bitmapData->flags);
213 Stream_Read_UINT16(s, bitmapData->bitmapLength);
215 if ((bitmapData->width == 0) || (bitmapData->height == 0))
217 WLog_ERR(TAG,
"Invalid BITMAP_DATA: width=%" PRIu16
", height=%" PRIu16, bitmapData->width,
221 if (bitmapData->destLeft > bitmapData->destRight)
223 WLog_ERR(TAG,
"Invalid BITMAP_DATA: left=%" PRIu16
" > right=%" PRIu16,
224 bitmapData->destLeft, bitmapData->destRight);
227 if (bitmapData->destTop > bitmapData->destBottom)
229 WLog_ERR(TAG,
"Invalid BITMAP_DATA: top=%" PRIu16
" > bottom=%" PRIu16, bitmapData->destTop,
230 bitmapData->destBottom);
237 const UINT32 w = 1u + bitmapData->destRight - bitmapData->destLeft;
238 if (w > bitmapData->width)
240 WLog_ERR(TAG,
"Invalid BITMAP_DATA: width=%" PRIu16
" < right - left + 1=%" PRIu32,
241 bitmapData->width, w);
245 const UINT32 h = 1u + bitmapData->destBottom - bitmapData->destTop;
246 if (h > bitmapData->height)
248 WLog_ERR(TAG,
"Invalid BITMAP_DATA: height=%" PRIu16
" < bottom - top + 1=%" PRIu32,
249 bitmapData->height, h);
253 if (bitmapData->flags & BITMAP_COMPRESSION)
255 if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR))
257 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
260 Stream_Read_UINT16(s,
261 bitmapData->cbCompFirstRowSize);
262 Stream_Read_UINT16(s,
263 bitmapData->cbCompMainBodySize);
264 Stream_Read_UINT16(s, bitmapData->cbScanWidth);
265 Stream_Read_UINT16(s,
266 bitmapData->cbUncompressedSize);
267 bitmapData->bitmapLength = bitmapData->cbCompMainBodySize;
270 bitmapData->compressed = TRUE;
273 bitmapData->compressed = FALSE;
275 if (!Stream_CheckAndLogRequiredLength(TAG, s, bitmapData->bitmapLength))
278 if (bitmapData->bitmapLength > 0)
280 bitmapData->bitmapDataStream = malloc(bitmapData->bitmapLength);
282 if (!bitmapData->bitmapDataStream)
285 memcpy(bitmapData->bitmapDataStream, Stream_ConstPointer(s), bitmapData->bitmapLength);
286 Stream_Seek(s, bitmapData->bitmapLength);
295 WINPR_ASSERT(bitmapData);
296 if (!Stream_EnsureRemainingCapacity(s, 18))
298 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->destLeft));
299 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->destTop));
300 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->destRight));
301 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->destBottom));
302 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->width));
303 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->height));
304 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->bitsPerPixel));
305 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->flags));
306 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->bitmapLength));
311static BOOL update_write_bitmap_data_no_comp_header(
const BITMAP_DATA* bitmapData,
wStream* s)
313 WINPR_ASSERT(bitmapData);
314 if (!Stream_EnsureRemainingCapacity(s, 8))
318 s, WINPR_ASSERTING_INT_CAST(
319 uint16_t, bitmapData->cbCompFirstRowSize));
321 s, WINPR_ASSERTING_INT_CAST(
322 uint16_t, bitmapData->cbCompMainBodySize));
324 s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->cbScanWidth));
326 s, WINPR_ASSERTING_INT_CAST(
327 uint16_t, bitmapData->cbUncompressedSize));
332static BOOL update_write_bitmap_data(rdpUpdate* update_pub,
wStream* s,
BITMAP_DATA* bitmapData)
336 WINPR_ASSERT(bitmapData);
338 if (!Stream_EnsureRemainingCapacity(s, 64ull + bitmapData->bitmapLength))
341 if (update->common.autoCalculateBitmapData)
343 bitmapData->flags = 0;
344 bitmapData->cbCompFirstRowSize = 0;
346 if (bitmapData->compressed)
347 bitmapData->flags |= BITMAP_COMPRESSION;
349 if (update->common.context->settings->NoBitmapCompressionHeader)
351 bitmapData->flags |= NO_BITMAP_COMPRESSION_HDR;
352 bitmapData->cbCompMainBodySize = bitmapData->bitmapLength;
356 if (!update_write_bitmap_data_header(bitmapData, s))
359 if (bitmapData->flags & BITMAP_COMPRESSION)
361 if ((bitmapData->flags & NO_BITMAP_COMPRESSION_HDR) == 0)
363 if (!update_write_bitmap_data_no_comp_header(bitmapData, s))
368 if (!Stream_EnsureRemainingCapacity(s, bitmapData->bitmapLength))
370 Stream_Write(s, bitmapData->bitmapDataStream, bitmapData->bitmapLength);
383 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
386 Stream_Read_UINT16(s, bitmapUpdate->number);
387 WLog_Print(up->log, WLOG_TRACE,
"BitmapUpdate: %" PRIu32
"", bitmapUpdate->number);
391 if (!bitmapUpdate->rectangles)
395 for (UINT32 i = 0; i < bitmapUpdate->number; i++)
397 if (!update_read_bitmap_data(update, s, &bitmapUpdate->rectangles[i]))
403 WINPR_PRAGMA_DIAG_PUSH
404 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
405 free_bitmap_update(update->context, bitmapUpdate);
406 WINPR_PRAGMA_DIAG_POP
411static BOOL update_write_bitmap_update(rdpUpdate* update,
wStream* s,
414 WINPR_ASSERT(update);
415 WINPR_ASSERT(bitmapUpdate);
417 if (!Stream_EnsureRemainingCapacity(s, 32))
420 Stream_Write_UINT16(s, UPDATE_TYPE_BITMAP);
421 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(
422 uint16_t, bitmapUpdate->number));
425 for (UINT32 i = 0; i < bitmapUpdate->number; i++)
427 if (!update_write_bitmap_data(update, s, &bitmapUpdate->rectangles[i]))
441 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
444 Stream_Seek_UINT16(s);
445 Stream_Read_UINT32(s, palette_update->number);
447 if (palette_update->number > 256)
448 palette_update->number = 256;
450 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, palette_update->number, 3ull))
454 for (UINT32 i = 0; i < palette_update->number; i++)
457 Stream_Read_UINT8(s, entry->red);
458 Stream_Read_UINT8(s, entry->green);
459 Stream_Read_UINT8(s, entry->blue);
462 return palette_update;
464 WINPR_PRAGMA_DIAG_PUSH
465 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
466 free_palette_update(update->context, palette_update);
467 WINPR_PRAGMA_DIAG_POP
472static BOOL update_read_synchronize(rdpUpdate* update,
wStream* s)
474 WINPR_UNUSED(update);
475 return Stream_SafeSeek(s, 2);
485 WINPR_ASSERT(play_sound);
487 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
490 Stream_Read_UINT32(s, play_sound->duration);
491 Stream_Read_UINT32(s, play_sound->frequency);
495BOOL update_recv_play_sound(rdpUpdate* update,
wStream* s)
499 WINPR_ASSERT(update);
501 if (!rdp_has_reached_state(update->context->rdp, CONNECTION_STATE_ACTIVE))
504 if (!update_read_play_sound(s, &play_sound))
507 return IFCALLRESULT(TRUE, update->PlaySound, update->context, &play_sound);
514 WINPR_ASSERT(update);
516 if (!pointer_position)
519 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
522 Stream_Read_UINT16(s, pointer_position->xPos);
523 Stream_Read_UINT16(s, pointer_position->yPos);
524 return pointer_position;
526 WINPR_PRAGMA_DIAG_PUSH
527 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
528 free_pointer_position_update(update->context, pointer_position);
529 WINPR_PRAGMA_DIAG_POP
537 WINPR_ASSERT(update);
542 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
545 Stream_Read_UINT32(s, pointer_system->type);
546 return pointer_system;
548 WINPR_PRAGMA_DIAG_PUSH
549 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
550 free_pointer_system_update(update->context, pointer_system);
551 WINPR_PRAGMA_DIAG_POP
555WINPR_ATTR_NODISCARD
static BOOL s_update_read_pointer_color(
wStream* s,
557 BYTE xorBpp, UINT32 flags)
559 BYTE* newMask =
nullptr;
560 UINT32 scanlineSize = 0;
563 WINPR_ASSERT(pointer_color);
565 if (flags & LARGE_POINTER_FLAG_96x96)
571 if (!Stream_CheckAndLogRequiredLength(TAG, s, 14))
574 Stream_Read_UINT16(s, pointer_color->cacheIndex);
575 Stream_Read_UINT16(s, pointer_color->hotSpotX);
576 Stream_Read_UINT16(s, pointer_color->hotSpotY);
586 Stream_Read_UINT16(s, pointer_color->width);
587 Stream_Read_UINT16(s, pointer_color->height);
589 if ((pointer_color->width > max) || (pointer_color->height > max))
592 Stream_Read_UINT16(s, pointer_color->lengthAndMask);
593 Stream_Read_UINT16(s, pointer_color->lengthXorMask);
601 if (pointer_color->hotSpotX >= pointer_color->width)
602 pointer_color->hotSpotX = 0;
604 if (pointer_color->hotSpotY >= pointer_color->height)
605 pointer_color->hotSpotY = 0;
607 if (pointer_color->lengthXorMask > 0)
620 if (!Stream_CheckAndLogRequiredLength(TAG, s, pointer_color->lengthXorMask))
623 scanlineSize = (7 + xorBpp * pointer_color->width) / 8;
624 scanlineSize = ((scanlineSize + 1) / 2) * 2;
626 if (scanlineSize * pointer_color->height != pointer_color->lengthXorMask)
629 "invalid lengthXorMask: width=%" PRIu32
" height=%" PRIu32
", %" PRIu32
630 " instead of %" PRIu32
"",
631 pointer_color->width, pointer_color->height, pointer_color->lengthXorMask,
632 scanlineSize * pointer_color->height);
636 newMask = realloc(pointer_color->xorMaskData, pointer_color->lengthXorMask);
641 pointer_color->xorMaskData = newMask;
642 Stream_Read(s, pointer_color->xorMaskData, pointer_color->lengthXorMask);
645 if (pointer_color->lengthAndMask > 0)
654 if (!Stream_CheckAndLogRequiredLength(TAG, s, pointer_color->lengthAndMask))
657 scanlineSize = ((7 + pointer_color->width) / 8);
658 scanlineSize = ((1 + scanlineSize) / 2) * 2;
660 if (scanlineSize * pointer_color->height != pointer_color->lengthAndMask)
662 WLog_ERR(TAG,
"invalid lengthAndMask: %" PRIu32
" instead of %" PRIu32
"",
663 pointer_color->lengthAndMask, scanlineSize * pointer_color->height);
667 newMask = realloc(pointer_color->andMaskData, pointer_color->lengthAndMask);
672 pointer_color->andMaskData = newMask;
673 Stream_Read(s, pointer_color->andMaskData, pointer_color->lengthAndMask);
676 if (Stream_GetRemainingLength(s) > 0)
677 Stream_Seek_UINT8(s);
688 WINPR_ASSERT(update);
693 if (!s_update_read_pointer_color(s, pointer_color, xorBpp,
694 update->context->settings->LargePointerFlag))
697 return pointer_color;
699 WINPR_PRAGMA_DIAG_PUSH
700 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
701 free_pointer_color_update(update->context, pointer_color);
702 WINPR_PRAGMA_DIAG_POP
706WINPR_ATTR_NODISCARD
static BOOL s_update_read_pointer_large(
wStream* s,
709 BYTE* newMask =
nullptr;
710 UINT32 scanlineSize = 0;
715 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
718 Stream_Read_UINT16(s, pointer->xorBpp);
719 Stream_Read_UINT16(s, pointer->cacheIndex);
720 Stream_Read_UINT16(s, pointer->hotSpotX);
721 Stream_Read_UINT16(s, pointer->hotSpotY);
723 Stream_Read_UINT16(s, pointer->width);
724 Stream_Read_UINT16(s, pointer->height);
726 if ((pointer->width > 384) || (pointer->height > 384))
729 Stream_Read_UINT32(s, pointer->lengthAndMask);
730 Stream_Read_UINT32(s, pointer->lengthXorMask);
732 if (pointer->hotSpotX >= pointer->width)
733 pointer->hotSpotX = 0;
735 if (pointer->hotSpotY >= pointer->height)
736 pointer->hotSpotY = 0;
738 if (pointer->lengthXorMask > 0)
751 if (!Stream_CheckAndLogRequiredLength(TAG, s, pointer->lengthXorMask))
754 scanlineSize = (7 + pointer->xorBpp * pointer->width) / 8;
755 scanlineSize = ((scanlineSize + 1) / 2) * 2;
757 if (scanlineSize * pointer->height != pointer->lengthXorMask)
760 "invalid lengthXorMask: width=%" PRIu32
" height=%" PRIu32
", %" PRIu32
761 " instead of %" PRIu32
"",
762 pointer->width, pointer->height, pointer->lengthXorMask,
763 scanlineSize * pointer->height);
767 newMask = realloc(pointer->xorMaskData, pointer->lengthXorMask);
772 pointer->xorMaskData = newMask;
773 Stream_Read(s, pointer->xorMaskData, pointer->lengthXorMask);
776 if (pointer->lengthAndMask > 0)
785 if (!Stream_CheckAndLogRequiredLength(TAG, s, pointer->lengthAndMask))
788 scanlineSize = ((7 + pointer->width) / 8);
789 scanlineSize = ((1 + scanlineSize) / 2) * 2;
791 if (scanlineSize * pointer->height != pointer->lengthAndMask)
793 WLog_ERR(TAG,
"invalid lengthAndMask: %" PRIu32
" instead of %" PRIu32
"",
794 pointer->lengthAndMask, scanlineSize * pointer->height);
798 newMask = realloc(pointer->andMaskData, pointer->lengthAndMask);
803 pointer->andMaskData = newMask;
804 Stream_Read(s, pointer->andMaskData, pointer->lengthAndMask);
807 if (Stream_GetRemainingLength(s) > 0)
808 Stream_Seek_UINT8(s);
819 WINPR_ASSERT(update);
824 if (!s_update_read_pointer_large(s, pointer))
829 WINPR_PRAGMA_DIAG_PUSH
830 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
831 free_pointer_large_update(update->context, pointer);
832 WINPR_PRAGMA_DIAG_POP
840 WINPR_ASSERT(update);
845 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
848 Stream_Read_UINT16(s, pointer_new->xorBpp);
850 if ((pointer_new->xorBpp < 1) || (pointer_new->xorBpp > 32))
852 WLog_ERR(TAG,
"invalid xorBpp %" PRIu32
"", pointer_new->xorBpp);
856 WINPR_ASSERT(pointer_new->xorBpp <= UINT8_MAX);
857 if (!s_update_read_pointer_color(
858 s, &pointer_new->colorPtrAttr, (UINT8)pointer_new->xorBpp,
859 update->context->settings->LargePointerFlag))
864 WINPR_PRAGMA_DIAG_PUSH
865 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
866 free_pointer_new_update(update->context, pointer_new);
867 WINPR_PRAGMA_DIAG_POP
875 WINPR_ASSERT(update);
880 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
883 Stream_Read_UINT16(s, pointer->cacheIndex);
886 WINPR_PRAGMA_DIAG_PUSH
887 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
888 free_pointer_cached_update(update->context, pointer);
889 WINPR_PRAGMA_DIAG_POP
893BOOL update_recv_pointer(rdpUpdate* update,
wStream* s)
896 UINT16 messageType = 0;
898 WINPR_ASSERT(update);
900 rdpContext* context = update->context;
901 rdpPointerUpdate* pointer = update->pointer;
903 if (!rdp_has_reached_state(update->context->rdp, CONNECTION_STATE_ACTIVE))
906 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2 + 2))
909 Stream_Read_UINT16(s, messageType);
910 Stream_Seek_UINT16(s);
914 case PTR_MSG_TYPE_POSITION:
918 if (pointer_position)
920 rc = IFCALLRESULT(FALSE, pointer->PointerPosition, context, pointer_position);
921 free_pointer_position_update(context, pointer_position);
926 case PTR_MSG_TYPE_SYSTEM:
932 rc = IFCALLRESULT(FALSE, pointer->PointerSystem, context, pointer_system);
933 free_pointer_system_update(context, pointer_system);
938 case PTR_MSG_TYPE_COLOR:
944 rc = IFCALLRESULT(FALSE, pointer->PointerColor, context, pointer_color);
945 free_pointer_color_update(context, pointer_color);
950 case PTR_MSG_TYPE_POINTER_LARGE:
956 rc = IFCALLRESULT(FALSE, pointer->PointerLarge, context, pointer_large);
957 free_pointer_large_update(context, pointer_large);
962 case PTR_MSG_TYPE_POINTER:
968 rc = IFCALLRESULT(FALSE, pointer->PointerNew, context, pointer_new);
969 free_pointer_new_update(context, pointer_new);
974 case PTR_MSG_TYPE_CACHED:
980 rc = IFCALLRESULT(FALSE, pointer->PointerCached, context, pointer_cached);
981 free_pointer_cached_update(context, pointer_cached);
993BOOL update_recv(rdpUpdate* update,
wStream* s)
996 UINT16 updateType = 0;
998 rdpContext* context = update->context;
1000 WINPR_ASSERT(context);
1002 if (!rdp_has_reached_state(update->context->rdp, CONNECTION_STATE_ACTIVE))
1005 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
1008 Stream_Read_UINT16(s, updateType);
1009 WLog_Print(up->log, WLOG_TRACE,
"%s Update Data PDU", update_type_to_string(updateType));
1011 if (!update_begin_paint(update))
1016 case UPDATE_TYPE_ORDERS:
1017 rc = update_recv_orders(update, s);
1020 case UPDATE_TYPE_BITMAP:
1022 BITMAP_UPDATE* bitmap_update = update_read_bitmap_update(update, s);
1026 WLog_ERR(TAG,
"UPDATE_TYPE_BITMAP - update_read_bitmap_update() failed");
1030 up->stats.base[RDP_STATS_BITMAP_UPDATE]++;
1031 rc = IFCALLRESULT(FALSE, update->BitmapUpdate, context, bitmap_update);
1032 free_bitmap_update(context, bitmap_update);
1036 case UPDATE_TYPE_PALETTE:
1040 if (!palette_update)
1042 WLog_ERR(TAG,
"UPDATE_TYPE_PALETTE - update_read_palette() failed");
1046 up->stats.base[RDP_STATS_PALETTE]++;
1047 rc = IFCALLRESULT(FALSE, update->Palette, context, palette_update);
1048 free_palette_update(context, palette_update);
1052 case UPDATE_TYPE_SYNCHRONIZE:
1053 if (!update_read_synchronize(update, s))
1055 up->stats.base[RDP_STATS_SYNC]++;
1056 rc = IFCALLRESULT(TRUE, update->Synchronize, context);
1065 if (!update_end_paint(update))
1070 WLog_ERR(TAG,
"UPDATE_TYPE %s [%" PRIu16
"] failed", update_type_to_string(updateType),
1078void update_reset_state(rdpUpdate* update)
1083 WINPR_ASSERT(primary);
1085 ZeroMemory(&primary->order_info,
sizeof(
ORDER_INFO));
1098 free(primary->polyline.points);
1107 free(primary->fast_glyph.glyphData.aj);
1110 free(primary->polygon_sc.points);
1113 free(primary->polygon_cb.points);
1118 primary->order_info.orderType = ORDER_TYPE_PATBLT;
1120 if (!up->initialState)
1123 WINPR_ASSERT(altsec);
1125 altsec->switch_surface.bitmapId = SCREEN_BITMAP_SURFACE;
1126 if (altsec->common.SwitchSurface)
1128 if (!altsec->common.SwitchSurface(update->context, &(altsec->switch_surface)))
1129 WLog_Print(up->log, WLOG_WARN,
"altsec->common.SwitchSurface failed");
1134BOOL update_post_connect(rdpUpdate* update)
1139 WINPR_ASSERT(update->context);
1140 WINPR_ASSERT(update->context->settings);
1141 up->asynchronous = update->context->settings->AsyncUpdate;
1143 if (up->asynchronous)
1145#if defined(FORCE_ASYNC_UPDATE_OFF)
1146 WLog_WARN(TAG,
"AsyncUpdate requested, but forced deactivated");
1147 WLog_WARN(TAG,
"see https://github.com/FreeRDP/FreeRDP/issues/10153 for details");
1149 if (!(up->proxy = update_message_proxy_new(update)))
1154 altsec->switch_surface.bitmapId = SCREEN_BITMAP_SURFACE;
1155 const BOOL rc = IFCALLRESULT(TRUE, update->altsec->SwitchSurface, update->context,
1156 &(altsec->switch_surface));
1157 up->initialState = FALSE;
1161void update_post_disconnect(rdpUpdate* update)
1165 WINPR_ASSERT(update->context);
1166 WINPR_ASSERT(update->context->settings);
1168 up->asynchronous = update->context->settings->AsyncUpdate;
1170 if (up->asynchronous)
1172#if !defined(FORCE_ASYNC_UPDATE_OFF)
1173 update_message_proxy_free(up->proxy);
1177 up->initialState = TRUE;
1180WINPR_ATTR_NODISCARD
static BOOL s_update_begin_paint(rdpContext* context)
1183 WINPR_ASSERT(context);
1188 if (!update_end_paint(&update->common))
1192 WINPR_ASSERT(context->rdp);
1193 s = fastpath_update_pdu_init_new(context->rdp->fastpath);
1198 Stream_SealLength(s);
1199 Stream_GetLength(s, update->offsetOrders);
1201 update->combineUpdates = TRUE;
1202 update->numberOrders = 0;
1207WINPR_ATTR_NODISCARD
static BOOL s_update_end_paint(rdpContext* context)
1211 WINPR_ASSERT(context);
1218 update->us =
nullptr;
1220 Stream_SealLength(s);
1221 if (!Stream_SetPosition(s, update->offsetOrders))
1223 Stream_Write_UINT16(s, update->numberOrders);
1224 if (!Stream_SetPosition(s, Stream_Length(s)))
1227 if (update->numberOrders > 0)
1229 WLog_DBG(TAG,
"sending %" PRIu16
" orders", update->numberOrders);
1230 if (!fastpath_send_update_pdu(context->rdp->fastpath, FASTPATH_UPDATETYPE_ORDERS, s, FALSE))
1234 update->combineUpdates = FALSE;
1235 update->numberOrders = 0;
1236 update->offsetOrders = 0;
1240 Stream_Free(s, TRUE);
1244WINPR_ATTR_NODISCARD
static BOOL update_flush(rdpContext* context)
1248 WINPR_ASSERT(context);
1249 update = update_cast(context->update);
1251 if (update->numberOrders > 0)
1253 if (!update_end_paint(&update->common))
1256 if (!update_begin_paint(&update->common))
1262WINPR_ATTR_NODISCARD
static BOOL update_force_flush(rdpContext* context)
1264 return update_flush(context);
1267WINPR_ATTR_NODISCARD
static BOOL update_check_flush(rdpContext* context,
size_t size)
1269 WINPR_ASSERT(context);
1276 if (!update_begin_paint(&update->common))
1281 if (Stream_GetPosition(s) + size + 64 >= FASTPATH_MAX_PACKET_SIZE)
1284 if (!update_flush(context))
1291WINPR_ATTR_NODISCARD
static BOOL update_set_bounds(rdpContext* context,
const rdpBounds* bounds)
1295 WINPR_ASSERT(context);
1297 update = update_cast(context->update);
1299 CopyMemory(&update->previousBounds, &update->currentBounds,
sizeof(rdpBounds));
1302 ZeroMemory(&update->currentBounds,
sizeof(rdpBounds));
1304 CopyMemory(&update->currentBounds, bounds,
sizeof(rdpBounds));
1309WINPR_ATTR_NODISCARD
static BOOL update_bounds_is_null(rdpBounds* bounds)
1311 WINPR_ASSERT(bounds);
1312 return ((bounds->left == 0) && (bounds->top == 0) && (bounds->right == 0) &&
1313 (bounds->bottom == 0));
1316WINPR_ATTR_NODISCARD
static BOOL update_bounds_equals(rdpBounds* bounds1, rdpBounds* bounds2)
1318 WINPR_ASSERT(bounds1);
1319 WINPR_ASSERT(bounds2);
1321 return ((bounds1->left == bounds2->left) && (bounds1->top == bounds2->top) &&
1322 (bounds1->right == bounds2->right) && (bounds1->bottom == bounds2->bottom));
1325WINPR_ATTR_NODISCARD
static size_t update_prepare_bounds(rdpContext* context,
ORDER_INFO* orderInfo)
1330 WINPR_ASSERT(context);
1331 WINPR_ASSERT(orderInfo);
1333 update = update_cast(context->update);
1335 orderInfo->boundsFlags = 0;
1337 if (update_bounds_is_null(&update->currentBounds))
1340 orderInfo->controlFlags |= ORDER_BOUNDS;
1342 if (update_bounds_equals(&update->previousBounds, &update->currentBounds))
1344 orderInfo->controlFlags |= ORDER_ZERO_BOUNDS_DELTAS;
1351 if (update->previousBounds.left != update->currentBounds.left)
1353 orderInfo->bounds.left = update->currentBounds.left;
1354 orderInfo->boundsFlags |= BOUND_LEFT;
1358 if (update->previousBounds.top != update->currentBounds.top)
1360 orderInfo->bounds.top = update->currentBounds.top;
1361 orderInfo->boundsFlags |= BOUND_TOP;
1365 if (update->previousBounds.right != update->currentBounds.right)
1367 orderInfo->bounds.right = update->currentBounds.right;
1368 orderInfo->boundsFlags |= BOUND_RIGHT;
1372 if (update->previousBounds.bottom != update->currentBounds.bottom)
1374 orderInfo->bounds.bottom = update->currentBounds.bottom;
1375 orderInfo->boundsFlags |= BOUND_BOTTOM;
1383WINPR_ATTR_NODISCARD
static size_t
1384update_prepare_order_info(rdpContext* context,
ORDER_INFO* orderInfo, UINT32 orderType)
1386 WINPR_ASSERT(context);
1387 WINPR_ASSERT(orderInfo);
1389 orderInfo->fieldFlags = 0;
1390 orderInfo->orderType = orderType;
1391 orderInfo->controlFlags = ORDER_STANDARD;
1392 orderInfo->controlFlags |= ORDER_TYPE_CHANGE;
1394 length += get_primary_drawing_order_field_bytes(orderInfo->orderType,
nullptr);
1395 length += update_prepare_bounds(context, orderInfo);
1400static int update_write_order_info(rdpContext* context,
wStream* s,
const ORDER_INFO* orderInfo,
1403 WINPR_UNUSED(context);
1404 WINPR_ASSERT(orderInfo);
1405 WINPR_ASSERT(orderInfo->controlFlags <= UINT8_MAX);
1407 const size_t position = Stream_GetPosition(s);
1408 const UINT8 controlFlags = (UINT8)orderInfo->controlFlags;
1410 if (!Stream_SetPosition(s, offset))
1413 Stream_Write_UINT8(s, controlFlags);
1415 if (orderInfo->controlFlags & ORDER_TYPE_CHANGE)
1417 s, WINPR_ASSERTING_INT_CAST(uint8_t, orderInfo->orderType));
1419 if (!update_write_field_flags(
1420 s, orderInfo->fieldFlags, controlFlags,
1421 get_primary_drawing_order_field_bytes(orderInfo->orderType,
nullptr)))
1423 if (!update_write_bounds(s, orderInfo))
1425 if (!Stream_SetPosition(s, position))
1433 WINPR_ASSERT(areas || (count == 0));
1435 Stream_Write_UINT8(s, count);
1438 for (BYTE i = 0; i < count; i++)
1440 Stream_Write_UINT16(s, areas[i].left);
1441 Stream_Write_UINT16(s, areas[i].top);
1442 Stream_Write_UINT16(s, areas[i].right);
1443 Stream_Write_UINT16(s, areas[i].bottom);
1447WINPR_ATTR_NODISCARD
static BOOL update_send_refresh_rect(rdpContext* context, BYTE count,
1450 WINPR_ASSERT(context);
1451 rdpRdp* rdp = context->rdp;
1453 WINPR_ASSERT(rdp->settings);
1454 if (rdp->settings->RefreshRect)
1456 UINT16 sec_flags = 0;
1457 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
1462 update_write_refresh_rect(s, count, areas);
1463 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_REFRESH_RECT, rdp->mcs->userId, sec_flags);
1473 Stream_Write_UINT8(s, allow);
1480 Stream_Write_UINT16(s, area->left);
1481 Stream_Write_UINT16(s, area->top);
1482 Stream_Write_UINT16(s, area->right);
1483 Stream_Write_UINT16(s, area->bottom);
1487WINPR_ATTR_NODISCARD
static BOOL update_send_suppress_output(rdpContext* context, BYTE allow,
1490 WINPR_ASSERT(context);
1491 rdpRdp* rdp = context->rdp;
1494 WINPR_ASSERT(rdp->settings);
1495 if (rdp->settings->SuppressOutput)
1497 UINT16 sec_flags = 0;
1498 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
1503 update_write_suppress_output(s, allow, area);
1504 WINPR_ASSERT(rdp->mcs);
1505 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SUPPRESS_OUTPUT, rdp->mcs->userId,
1512WINPR_ATTR_NODISCARD
static BOOL update_send_surface_command(rdpContext* context,
wStream* s)
1515 WINPR_ASSERT(context);
1516 rdpRdp* rdp = context->rdp;
1520 update = fastpath_update_pdu_init(rdp->fastpath);
1525 if (!Stream_EnsureRemainingCapacity(update, Stream_GetPosition(s)))
1531 Stream_Write(update, Stream_Buffer(s), Stream_GetPosition(s));
1532 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, update, FALSE);
1534 Stream_Release(update);
1538WINPR_ATTR_NODISCARD
static BOOL
1542 WINPR_ASSERT(context);
1543 rdpRdp* rdp = context->rdp;
1546 WINPR_ASSERT(surfaceBitsCommand);
1549 if (!update_force_flush(context))
1551 s = fastpath_update_pdu_init(rdp->fastpath);
1556 if (!update_write_surfcmd_surface_bits(s, surfaceBitsCommand))
1559 if (!fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s,
1560 surfaceBitsCommand->skipCompression))
1563 ret = update_force_flush(context);
1569WINPR_ATTR_NODISCARD
static BOOL
1570update_send_surface_frame_marker(rdpContext* context,
1574 WINPR_ASSERT(context);
1575 rdpRdp* rdp = context->rdp;
1577 if (!update_force_flush(context))
1581 s = fastpath_update_pdu_init(rdp->fastpath);
1586 WINPR_ASSERT(surfaceFrameMarker->frameAction <= UINT16_MAX);
1587 if (!update_write_surfcmd_frame_marker(s, (UINT16)surfaceFrameMarker->frameAction,
1588 surfaceFrameMarker->frameId) ||
1589 !fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s, FALSE))
1592 ret = update_force_flush(context);
1598WINPR_ATTR_NODISCARD
static BOOL update_send_surface_frame_bits(rdpContext* context,
1600 BOOL first, BOOL last,
1605 WINPR_ASSERT(context);
1606 rdpRdp* rdp = context->rdp;
1609 if (!update_force_flush(context))
1613 s = fastpath_update_pdu_init(rdp->fastpath);
1620 if (!update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_BEGIN, frameId))
1624 if (!update_write_surfcmd_surface_bits(s, cmd))
1629 if (!update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_END, frameId))
1633 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s,
1634 cmd->skipCompression);
1638 ret = update_force_flush(context);
1644WINPR_ATTR_NODISCARD
static BOOL update_send_frame_acknowledge(rdpContext* context, UINT32 frameId)
1646 WINPR_ASSERT(context);
1647 rdpRdp* rdp = context->rdp;
1650 WINPR_ASSERT(rdp->settings);
1651 WINPR_ASSERT(rdp->settings->ReceivedCapabilities);
1652 WINPR_ASSERT(rdp->settings->ReceivedCapabilitiesSize > CAPSET_TYPE_FRAME_ACKNOWLEDGE);
1653 if (rdp->settings->ReceivedCapabilities[CAPSET_TYPE_FRAME_ACKNOWLEDGE])
1655 UINT16 sec_flags = 0;
1656 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
1661 Stream_Write_UINT32(s, frameId);
1662 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FRAME_ACKNOWLEDGE, rdp->mcs->userId,
1669WINPR_ATTR_NODISCARD
static BOOL update_send_synchronize(rdpContext* context)
1672 WINPR_ASSERT(context);
1673 rdpRdp* rdp = context->rdp;
1677 s = fastpath_update_pdu_init(rdp->fastpath);
1683 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SYNCHRONIZE, s, FALSE);
1688WINPR_ATTR_NODISCARD
static BOOL update_send_desktop_resize(rdpContext* context)
1690 WINPR_ASSERT(context);
1691 return rdp_server_reactivate(context->rdp);
1694WINPR_ATTR_NODISCARD
static BOOL update_send_bitmap_update(rdpContext* context,
1698 WINPR_ASSERT(context);
1699 rdpRdp* rdp = context->rdp;
1700 rdpUpdate* update = context->update;
1703 if (!update_force_flush(context))
1707 s = fastpath_update_pdu_init(rdp->fastpath);
1712 if (!update_write_bitmap_update(update, s, bitmapUpdate) ||
1713 !fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_BITMAP, s,
1714 bitmapUpdate->skipCompression))
1720 ret = update_force_flush(context);
1727WINPR_ATTR_NODISCARD
static BOOL update_send_play_sound(rdpContext* context,
1730 UINT16 sec_flags = 0;
1732 WINPR_ASSERT(context);
1733 rdpRdp* rdp = context->rdp;
1736 WINPR_ASSERT(rdp->settings);
1737 WINPR_ASSERT(play_sound);
1738 WINPR_ASSERT(rdp->settings->ReceivedCapabilities);
1739 WINPR_ASSERT(rdp->settings->ReceivedCapabilitiesSize > CAPSET_TYPE_SOUND);
1740 if (!rdp->settings->ReceivedCapabilities[CAPSET_TYPE_SOUND])
1745 s = rdp_data_pdu_init(rdp, &sec_flags);
1750 Stream_Write_UINT32(s, play_sound->duration);
1751 Stream_Write_UINT32(s, play_sound->frequency);
1752 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_PLAY_SOUND, rdp->mcs->userId, sec_flags);
1759WINPR_ATTR_NODISCARD
static BOOL update_send_dstblt(rdpContext* context,
const DSTBLT_ORDER* dstblt)
1763 WINPR_ASSERT(context);
1764 WINPR_ASSERT(dstblt);
1768 const size_t headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_DSTBLT);
1769 const size_t inf = update_approximate_dstblt_order(&orderInfo, dstblt);
1770 if (!update_check_flush(context, headerLength + inf))
1778 const size_t offset = Stream_GetPosition(s);
1780 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1783 Stream_Seek(s, headerLength);
1785 if (!update_write_dstblt_order(s, &orderInfo, dstblt))
1788 if (update_write_order_info(context, s, &orderInfo, offset) < 0)
1790 update->numberOrders++;
1794WINPR_ATTR_NODISCARD
static BOOL update_send_patblt(rdpContext* context,
PATBLT_ORDER* patblt)
1799 WINPR_ASSERT(context);
1800 WINPR_ASSERT(patblt);
1803 const size_t headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_PATBLT);
1804 if (!update_check_flush(context,
1805 headerLength + update_approximate_patblt_order(&orderInfo, patblt)))
1813 offset = Stream_GetPosition(s);
1815 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1818 Stream_Seek(s, headerLength);
1819 if (!update_write_patblt_order(s, &orderInfo, patblt))
1821 if (update_write_order_info(context, s, &orderInfo, offset) < 0)
1823 update->numberOrders++;
1827WINPR_ATTR_NODISCARD
static BOOL update_send_scrblt(rdpContext* context,
const SCRBLT_ORDER* scrblt)
1831 WINPR_ASSERT(context);
1832 WINPR_ASSERT(scrblt);
1835 const size_t headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_SCRBLT);
1836 const size_t inf = update_approximate_scrblt_order(&orderInfo, scrblt);
1837 if (!update_check_flush(context, headerLength + inf))
1845 const size_t offset = Stream_GetPosition(s);
1847 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1850 Stream_Seek(s, headerLength);
1851 if (!update_write_scrblt_order(s, &orderInfo, scrblt))
1853 if (update_write_order_info(context, s, &orderInfo, offset) < 0)
1855 update->numberOrders++;
1859WINPR_ATTR_NODISCARD
static BOOL update_send_opaque_rect(rdpContext* context,
1865 WINPR_ASSERT(context);
1866 WINPR_ASSERT(opaque_rect);
1869 const size_t headerLength =
1870 update_prepare_order_info(context, &orderInfo, ORDER_TYPE_OPAQUE_RECT);
1871 if (!update_check_flush(
1872 context, headerLength + update_approximate_opaque_rect_order(&orderInfo, opaque_rect)))
1880 offset = Stream_GetPosition(s);
1882 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1885 Stream_Seek(s, headerLength);
1886 if (!update_write_opaque_rect_order(s, &orderInfo, opaque_rect))
1888 if (update_write_order_info(context, s, &orderInfo, offset) < 0)
1890 update->numberOrders++;
1894WINPR_ATTR_NODISCARD
static BOOL update_send_line_to(rdpContext* context,
1899 WINPR_ASSERT(context);
1900 WINPR_ASSERT(line_to);
1902 const size_t headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_LINE_TO);
1903 const size_t inf = update_approximate_line_to_order(&orderInfo, line_to);
1904 if (!update_check_flush(context, headerLength + inf))
1912 const size_t offset = Stream_GetPosition(s);
1914 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1917 Stream_Seek(s, headerLength);
1918 if (!update_write_line_to_order(s, &orderInfo, line_to))
1920 if (update_write_order_info(context, s, &orderInfo, offset) < 0)
1922 update->numberOrders++;
1926WINPR_ATTR_NODISCARD
static BOOL update_send_memblt(rdpContext* context,
MEMBLT_ORDER* memblt)
1931 WINPR_ASSERT(context);
1932 WINPR_ASSERT(memblt);
1934 const size_t headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_MEMBLT);
1935 if (!update_check_flush(context,
1936 headerLength + update_approximate_memblt_order(&orderInfo, memblt)))
1944 offset = Stream_GetPosition(s);
1946 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1949 Stream_Seek(s, headerLength);
1950 if (!update_write_memblt_order(s, &orderInfo, memblt))
1952 if (update_write_order_info(context, s, &orderInfo, offset) < 0)
1954 update->numberOrders++;
1958WINPR_ATTR_NODISCARD
static BOOL update_send_glyph_index(rdpContext* context,
1963 WINPR_ASSERT(context);
1964 WINPR_ASSERT(glyph_index);
1967 const size_t headerLength =
1968 update_prepare_order_info(context, &orderInfo, ORDER_TYPE_GLYPH_INDEX);
1969 const size_t inf = update_approximate_glyph_index_order(&orderInfo, glyph_index);
1970 if (!update_check_flush(context, headerLength + inf))
1978 const size_t offset = Stream_GetPosition(s);
1980 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1983 Stream_Seek(s, headerLength);
1984 if (!update_write_glyph_index_order(s, &orderInfo, glyph_index))
1986 if (update_write_order_info(context, s, &orderInfo, offset) < 0)
1988 update->numberOrders++;
1996WINPR_ATTR_NODISCARD
static BOOL update_send_cache_bitmap(rdpContext* context,
1999 const size_t headerLength = 6;
2000 UINT16 extraFlags = 0;
2002 WINPR_ASSERT(context);
2003 WINPR_ASSERT(cache_bitmap);
2006 const BYTE orderType = cache_bitmap->compressed ? ORDER_TYPE_CACHE_BITMAP_COMPRESSED
2007 : ORDER_TYPE_BITMAP_UNCOMPRESSED;
2009 update_approximate_cache_bitmap_order(cache_bitmap, cache_bitmap->compressed, &extraFlags);
2010 if (!update_check_flush(context, headerLength + inf))
2018 const size_t bm = Stream_GetPosition(s);
2020 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2023 Stream_Seek(s, headerLength);
2025 if (!update_write_cache_bitmap_order(s, cache_bitmap, cache_bitmap->compressed, &extraFlags))
2028 const size_t em = Stream_GetPosition(s);
2029 WINPR_ASSERT(em >= bm + 13);
2030 const size_t orderLength = (em - bm) - 13;
2031 WINPR_ASSERT(orderLength <= UINT16_MAX);
2033 if (!Stream_SetPosition(s, bm))
2035 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
2036 Stream_Write_UINT16(s, (UINT16)orderLength);
2037 Stream_Write_UINT16(s, extraFlags);
2038 Stream_Write_UINT8(s, orderType);
2039 update->numberOrders++;
2040 return Stream_SetPosition(s, em);
2043WINPR_ATTR_NODISCARD
static BOOL update_send_cache_bitmap_v2(rdpContext* context,
2046 const size_t headerLength = 6;
2047 UINT16 extraFlags = 0;
2049 WINPR_ASSERT(context);
2050 WINPR_ASSERT(cache_bitmap_v2);
2053 const BYTE orderType = cache_bitmap_v2->compressed ? ORDER_TYPE_BITMAP_COMPRESSED_V2
2054 : ORDER_TYPE_BITMAP_UNCOMPRESSED_V2;
2056 if (context->settings->NoBitmapCompressionHeader)
2057 cache_bitmap_v2->flags |= CBR2_NO_BITMAP_COMPRESSION_HDR;
2059 if (!update_check_flush(
2060 context, headerLength + update_approximate_cache_bitmap_v2_order(
2061 cache_bitmap_v2, cache_bitmap_v2->compressed, &extraFlags)))
2069 const size_t bm = Stream_GetPosition(s);
2071 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2074 Stream_Seek(s, headerLength);
2076 if (!update_write_cache_bitmap_v2_order(s, cache_bitmap_v2, cache_bitmap_v2->compressed,
2080 const size_t em = Stream_GetPosition(s);
2081 WINPR_ASSERT(em >= bm + 13);
2082 const size_t orderLength = (em - bm) - 13;
2083 WINPR_ASSERT(orderLength <= UINT16_MAX);
2085 if (!Stream_SetPosition(s, bm))
2087 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
2088 Stream_Write_UINT16(s, (UINT16)orderLength);
2089 Stream_Write_UINT16(s, extraFlags);
2090 Stream_Write_UINT8(s, orderType);
2091 update->numberOrders++;
2092 return Stream_SetPosition(s, em);
2095WINPR_ATTR_NODISCARD
static BOOL update_send_cache_bitmap_v3(rdpContext* context,
2098 const size_t headerLength = 6;
2099 UINT16 extraFlags = 0;
2101 WINPR_ASSERT(context);
2102 WINPR_ASSERT(cache_bitmap_v3);
2105 const BYTE orderType = ORDER_TYPE_BITMAP_COMPRESSED_V3;
2106 if (!update_check_flush(context, headerLength + update_approximate_cache_bitmap_v3_order(
2107 cache_bitmap_v3, &extraFlags)))
2115 const size_t bm = Stream_GetPosition(s);
2117 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2120 Stream_Seek(s, headerLength);
2122 if (!update_write_cache_bitmap_v3_order(s, cache_bitmap_v3, &extraFlags))
2125 const size_t em = Stream_GetPosition(s);
2126 WINPR_ASSERT(em >= bm + 13);
2127 const size_t orderLength = (em - bm) - 13;
2128 WINPR_ASSERT(orderLength <= UINT16_MAX);
2130 if (!Stream_SetPosition(s, bm))
2132 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
2133 Stream_Write_UINT16(s, (UINT16)orderLength);
2134 Stream_Write_UINT16(s, extraFlags);
2135 Stream_Write_UINT8(s, orderType);
2136 update->numberOrders++;
2137 return Stream_SetPosition(s, em);
2140WINPR_ATTR_NODISCARD
static BOOL
2144 size_t headerLength = 6;
2146 WINPR_ASSERT(context);
2147 WINPR_ASSERT(cache_color_table);
2150 const size_t inf = update_approximate_cache_color_table_order(cache_color_table, &flags);
2151 if (!update_check_flush(context, headerLength + inf))
2159 const size_t bm = Stream_GetPosition(s);
2161 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2164 Stream_Seek(s, headerLength);
2166 if (!update_write_cache_color_table_order(s, cache_color_table, &flags))
2169 const size_t em = Stream_GetPosition(s);
2170 WINPR_ASSERT(em >= bm + 13);
2171 const size_t orderLength = (em - bm) - 13;
2172 WINPR_ASSERT(orderLength <= UINT16_MAX);
2173 if (!Stream_SetPosition(s, bm))
2175 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
2176 Stream_Write_UINT16(s, (UINT16)orderLength);
2177 Stream_Write_UINT16(s, flags);
2178 Stream_Write_UINT8(s, ORDER_TYPE_CACHE_COLOR_TABLE);
2179 update->numberOrders++;
2180 return Stream_SetPosition(s, em);
2183WINPR_ATTR_NODISCARD
static BOOL update_send_cache_glyph(rdpContext* context,
2187 const size_t headerLength = 6;
2189 WINPR_ASSERT(context);
2190 WINPR_ASSERT(cache_glyph);
2193 const size_t inf = update_approximate_cache_glyph_order(cache_glyph, &flags);
2194 if (!update_check_flush(context, headerLength + inf))
2202 const size_t bm = Stream_GetPosition(s);
2204 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2207 Stream_Seek(s, headerLength);
2209 if (!update_write_cache_glyph_order(s, cache_glyph, &flags))
2212 const size_t em = Stream_GetPosition(s);
2213 WINPR_ASSERT(em >= bm + 13);
2214 const size_t orderLength = (em - bm) - 13;
2215 WINPR_ASSERT(orderLength <= UINT16_MAX);
2216 if (!Stream_SetPosition(s, bm))
2218 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
2219 Stream_Write_UINT16(s, (UINT16)orderLength);
2220 Stream_Write_UINT16(s, flags);
2221 Stream_Write_UINT8(s, ORDER_TYPE_CACHE_GLYPH);
2222 update->numberOrders++;
2223 return Stream_SetPosition(s, em);
2226WINPR_ATTR_NODISCARD
static BOOL
2230 const size_t headerLength = 6;
2232 WINPR_ASSERT(context);
2233 WINPR_ASSERT(cache_glyph_v2);
2236 const size_t inf = update_approximate_cache_glyph_v2_order(cache_glyph_v2, &flags);
2237 if (!update_check_flush(context, headerLength + inf))
2245 const size_t bm = Stream_GetPosition(s);
2247 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2250 Stream_Seek(s, headerLength);
2252 if (!update_write_cache_glyph_v2_order(s, cache_glyph_v2, &flags))
2255 const size_t em = Stream_GetPosition(s);
2256 WINPR_ASSERT(em >= bm + 13);
2257 const size_t orderLength = (em - bm) - 13;
2258 WINPR_ASSERT(orderLength <= UINT16_MAX);
2259 if (!Stream_SetPosition(s, bm))
2261 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
2262 Stream_Write_UINT16(s, (UINT16)orderLength);
2263 Stream_Write_UINT16(s, flags);
2264 Stream_Write_UINT8(s, ORDER_TYPE_CACHE_GLYPH);
2265 update->numberOrders++;
2266 return Stream_SetPosition(s, em);
2269WINPR_ATTR_NODISCARD
static BOOL update_send_cache_brush(rdpContext* context,
2273 const size_t headerLength = 6;
2275 WINPR_ASSERT(context);
2276 WINPR_ASSERT(cache_brush);
2279 const size_t inf = update_approximate_cache_brush_order(cache_brush, &flags);
2280 if (!update_check_flush(context, headerLength + inf))
2288 const size_t bm = Stream_GetPosition(s);
2290 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2293 Stream_Seek(s, headerLength);
2295 if (!update_write_cache_brush_order(s, cache_brush, &flags))
2298 const size_t em = Stream_GetPosition(s);
2302 const size_t orderLength = (em - bm) - 13;
2303 WINPR_ASSERT(orderLength <= UINT16_MAX);
2304 if (!Stream_SetPosition(s, bm))
2306 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
2307 Stream_Write_UINT16(s, (UINT16)orderLength);
2308 Stream_Write_UINT16(s, flags);
2309 Stream_Write_UINT8(s, ORDER_TYPE_CACHE_BRUSH);
2310 update->numberOrders++;
2311 return Stream_SetPosition(s, em);
2318WINPR_ATTR_NODISCARD
static BOOL update_send_create_offscreen_bitmap_order(
2321 WINPR_ASSERT(context);
2322 WINPR_ASSERT(create_offscreen_bitmap);
2325 const size_t headerLength = 1;
2326 const size_t orderType = ORDER_TYPE_CREATE_OFFSCREEN_BITMAP;
2327 const size_t controlFlags = ORDER_SECONDARY | (orderType << 2);
2328 const size_t inf = update_approximate_create_offscreen_bitmap_order(create_offscreen_bitmap);
2329 if (!update_check_flush(context, headerLength + inf))
2337 const size_t bm = Stream_GetPosition(s);
2339 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2342 Stream_Seek(s, headerLength);
2344 if (!update_write_create_offscreen_bitmap_order(s, create_offscreen_bitmap))
2347 const size_t em = Stream_GetPosition(s);
2348 if (!Stream_SetPosition(s, bm))
2350 Stream_Write_UINT8(s,
2351 WINPR_ASSERTING_INT_CAST(uint8_t, controlFlags));
2352 update->numberOrders++;
2353 return Stream_SetPosition(s, em);
2356WINPR_ATTR_NODISCARD
static BOOL
2357update_send_switch_surface_order(rdpContext* context,
const SWITCH_SURFACE_ORDER* switch_surface)
2359 WINPR_ASSERT(context);
2360 WINPR_ASSERT(switch_surface);
2363 const size_t headerLength = 1;
2364 const size_t orderType = ORDER_TYPE_SWITCH_SURFACE;
2365 const size_t controlFlags = ORDER_SECONDARY | (orderType << 2);
2366 const size_t inf = update_approximate_switch_surface_order(switch_surface);
2367 if (!update_check_flush(context, headerLength + inf))
2375 const size_t bm = Stream_GetPosition(s);
2377 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2380 Stream_Seek(s, headerLength);
2382 if (!update_write_switch_surface_order(s, switch_surface))
2385 const size_t em = Stream_GetPosition(s);
2386 if (!Stream_SetPosition(s, bm))
2388 Stream_Write_UINT8(s,
2389 WINPR_ASSERTING_INT_CAST(uint8_t, controlFlags));
2390 update->numberOrders++;
2391 return Stream_SetPosition(s, em);
2394WINPR_ATTR_NODISCARD
static BOOL
2398 BYTE updateCode = 0;
2400 WINPR_ASSERT(context);
2401 rdpRdp* rdp = context->rdp;
2405 s = fastpath_update_pdu_init(rdp->fastpath);
2410 if (pointer_system->type == SYSPTR_NULL)
2411 updateCode = FASTPATH_UPDATETYPE_PTR_NULL;
2413 updateCode = FASTPATH_UPDATETYPE_PTR_DEFAULT;
2415 ret = fastpath_send_update_pdu(rdp->fastpath, updateCode, s, FALSE);
2420WINPR_ATTR_NODISCARD
static BOOL
2424 WINPR_ASSERT(context);
2425 rdpRdp* rdp = context->rdp;
2429 s = fastpath_update_pdu_init(rdp->fastpath);
2434 if (!Stream_EnsureRemainingCapacity(s, 16))
2437 Stream_Write_UINT16(
2438 s, WINPR_ASSERTING_INT_CAST(uint16_t, pointerPosition->xPos));
2439 Stream_Write_UINT16(
2440 s, WINPR_ASSERTING_INT_CAST(uint16_t, pointerPosition->yPos));
2441 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_PTR_POSITION, s, FALSE);
2447WINPR_ATTR_NODISCARD
static BOOL
2450 WINPR_ASSERT(pointer_color);
2451 if (!Stream_EnsureRemainingCapacity(s, 32ull + pointer_color->lengthAndMask +
2452 pointer_color->lengthXorMask))
2455 Stream_Write_UINT16(s, pointer_color->cacheIndex);
2456 Stream_Write_UINT16(s, pointer_color->hotSpotX);
2457 Stream_Write_UINT16(s, pointer_color->hotSpotY);
2458 Stream_Write_UINT16(s, pointer_color->width);
2459 Stream_Write_UINT16(s, pointer_color->height);
2460 Stream_Write_UINT16(s, pointer_color->lengthAndMask);
2461 Stream_Write_UINT16(s, pointer_color->lengthXorMask);
2463 if (pointer_color->lengthXorMask > 0)
2464 Stream_Write(s, pointer_color->xorMaskData, pointer_color->lengthXorMask);
2466 if (pointer_color->lengthAndMask > 0)
2467 Stream_Write(s, pointer_color->andMaskData, pointer_color->lengthAndMask);
2469 Stream_Write_UINT8(s, 0);
2473WINPR_ATTR_NODISCARD
static BOOL
2478 WINPR_ASSERT(context);
2479 rdpRdp* rdp = context->rdp;
2483 WINPR_ASSERT(pointer_color);
2484 s = fastpath_update_pdu_init(rdp->fastpath);
2489 if (!update_write_pointer_color(s, pointer_color))
2492 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_COLOR, s, FALSE);
2498WINPR_ATTR_NODISCARD
static BOOL update_write_pointer_large(
wStream* s,
2501 WINPR_ASSERT(pointer);
2503 if (!Stream_EnsureRemainingCapacity(s, 32ull + pointer->lengthAndMask + pointer->lengthXorMask))
2506 Stream_Write_UINT16(s, pointer->xorBpp);
2507 Stream_Write_UINT16(s, pointer->cacheIndex);
2508 Stream_Write_UINT16(s, pointer->hotSpotX);
2509 Stream_Write_UINT16(s, pointer->hotSpotY);
2510 Stream_Write_UINT16(s, pointer->width);
2511 Stream_Write_UINT16(s, pointer->height);
2512 Stream_Write_UINT32(s, pointer->lengthAndMask);
2513 Stream_Write_UINT32(s, pointer->lengthXorMask);
2514 Stream_Write(s, pointer->xorMaskData, pointer->lengthXorMask);
2515 Stream_Write(s, pointer->andMaskData, pointer->lengthAndMask);
2516 Stream_Write_UINT8(s, 0);
2520WINPR_ATTR_NODISCARD
static BOOL update_send_pointer_large(rdpContext* context,
2524 WINPR_ASSERT(context);
2525 rdpRdp* rdp = context->rdp;
2529 WINPR_ASSERT(pointer);
2530 s = fastpath_update_pdu_init(rdp->fastpath);
2535 if (!update_write_pointer_large(s, pointer))
2538 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_LARGE_POINTER, s, FALSE);
2544WINPR_ATTR_NODISCARD
static BOOL update_send_pointer_new(rdpContext* context,
2549 WINPR_ASSERT(context);
2550 rdpRdp* rdp = context->rdp;
2554 WINPR_ASSERT(pointer_new);
2555 s = fastpath_update_pdu_init(rdp->fastpath);
2560 if (!Stream_EnsureRemainingCapacity(s, 16))
2563 Stream_Write_UINT16(
2564 s, WINPR_ASSERTING_INT_CAST(uint16_t, pointer_new->xorBpp));
2565 if (!update_write_pointer_color(s, &pointer_new->colorPtrAttr))
2567 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_POINTER, s, FALSE);
2573WINPR_ATTR_NODISCARD
static BOOL
2578 WINPR_ASSERT(context);
2579 rdpRdp* rdp = context->rdp;
2583 WINPR_ASSERT(pointer_cached);
2584 s = fastpath_update_pdu_init(rdp->fastpath);
2589 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(
2590 uint16_t, pointer_cached->cacheIndex));
2591 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_CACHED, s, FALSE);
2596BOOL update_read_refresh_rect(rdpUpdate* update,
wStream* s)
2598 BYTE numberOfAreas = 0;
2602 if (!freerdp_is_active_state(update->context))
2604 WLog_Print(up->log, WLOG_ERROR,
2605 "refresh rect request from client before activation, aborting");
2609 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
2612 Stream_Read_UINT8(s, numberOfAreas);
2615 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, numberOfAreas, 8ull))
2618 for (BYTE index = 0; index < numberOfAreas; index++)
2622 Stream_Read_UINT16(s, area->left);
2623 Stream_Read_UINT16(s, area->top);
2624 Stream_Read_UINT16(s, area->right);
2625 Stream_Read_UINT16(s, area->bottom);
2628 WINPR_ASSERT(update->context);
2629 WINPR_ASSERT(update->context->settings);
2630 if (update->context->settings->RefreshRect)
2631 IFCALL(update->RefreshRect, update->context, numberOfAreas, areas);
2633 WLog_Print(up->log, WLOG_WARN,
"ignoring refresh rect request from client");
2638BOOL update_read_suppress_output(rdpUpdate* update,
wStream* s)
2643 BYTE allowDisplayUpdates = 0;
2648 if (!freerdp_is_active_state(update->context))
2650 WLog_Print(up->log, WLOG_ERROR,
"suppress output from client before activation, aborting");
2653 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
2656 Stream_Read_UINT8(s, allowDisplayUpdates);
2659 if (allowDisplayUpdates > 0)
2661 if (!Stream_CheckAndLogRequiredLength(TAG, s,
sizeof(
RECTANGLE_16)))
2664 Stream_Read_UINT16(s, rect.left);
2665 Stream_Read_UINT16(s, rect.top);
2666 Stream_Read_UINT16(s, rect.right);
2667 Stream_Read_UINT16(s, rect.bottom);
2672 WINPR_ASSERT(update->context);
2673 WINPR_ASSERT(update->context->settings);
2674 if (update->context->settings->SuppressOutput)
2675 IFCALL(update->SuppressOutput, update->context, allowDisplayUpdates, prect);
2677 WLog_Print(up->log, WLOG_WARN,
"ignoring suppress output request from client");
2682WINPR_ATTR_NODISCARD
static BOOL update_send_set_keyboard_indicators(rdpContext* context,
2685 UINT16 sec_flags = 0;
2688 WINPR_ASSERT(context);
2689 rdpRdp* rdp = context->rdp;
2690 s = rdp_data_pdu_init(rdp, &sec_flags);
2695 Stream_Write_UINT16(s, 0);
2696 Stream_Write_UINT16(s, led_flags);
2698 WINPR_ASSERT(rdp->mcs);
2699 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS, rdp->mcs->userId,
2703WINPR_ATTR_NODISCARD
static BOOL update_send_set_keyboard_ime_status(rdpContext* context,
2704 UINT16 imeId, UINT32 imeState,
2707 UINT16 sec_flags = 0;
2710 WINPR_ASSERT(context);
2711 rdpRdp* rdp = context->rdp;
2712 s = rdp_data_pdu_init(rdp, &sec_flags);
2718 Stream_Write_UINT16(s, imeId);
2719 Stream_Write_UINT32(s, imeState);
2720 Stream_Write_UINT32(s, imeConvMode);
2722 WINPR_ASSERT(rdp->mcs);
2723 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS, rdp->mcs->userId,
2727WINPR_ATTR_NODISCARD
static UINT16
2731 size_t orderSize = 11;
2733 WINPR_ASSERT(orderInfo);
2734 WINPR_ASSERT(stateOrder);
2736 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OWNER) != 0)
2739 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_STYLE) != 0)
2742 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_SHOW) != 0)
2745 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE) != 0)
2746 orderSize += 2 + stateOrder->titleInfo.length;
2748 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) != 0)
2751 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) != 0)
2754 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_X) != 0)
2757 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_Y) != 0)
2760 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT) != 0)
2763 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT) != 0)
2766 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) != 0)
2769 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) != 0)
2772 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) != 0)
2775 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) != 0)
2777 const size_t len = 2ULL + stateOrder->numWindowRects *
sizeof(
RECTANGLE_16);
2781 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) != 0)
2784 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) != 0)
2787 const size_t len = 2ULL + stateOrder->numVisibilityRects *
sizeof(
RECTANGLE_16);
2791 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OVERLAY_DESCRIPTION) != 0)
2792 orderSize += 2 + stateOrder->OverlayDescription.length;
2794 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TASKBAR_BUTTON) != 0)
2797 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ENFORCE_SERVER_ZORDER) != 0)
2800 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_STATE) != 0)
2803 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_EDGE) != 0)
2806 return WINPR_ASSERTING_INT_CAST(uint16_t, orderSize);
2809WINPR_ATTR_NODISCARD
static BOOL
2812 WINPR_ASSERT(stateOrder);
2814 if ((fieldFlags & WINDOW_ORDER_FIELD_OWNER) != 0)
2815 Stream_Write_UINT32(s, stateOrder->ownerWindowId);
2817 if ((fieldFlags & WINDOW_ORDER_FIELD_STYLE) != 0)
2819 Stream_Write_UINT32(s, stateOrder->style);
2820 Stream_Write_UINT32(s, stateOrder->extendedStyle);
2823 if ((fieldFlags & WINDOW_ORDER_FIELD_SHOW) != 0)
2825 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, stateOrder->showState));
2828 if ((fieldFlags & WINDOW_ORDER_FIELD_TITLE) != 0)
2830 if (rail_write_unicode_string(s, &stateOrder->titleInfo) != CHANNEL_RC_OK)
2834 if ((fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) != 0)
2836 Stream_Write_INT32(s, stateOrder->clientOffsetX);
2837 Stream_Write_INT32(s, stateOrder->clientOffsetY);
2840 if ((fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) != 0)
2842 Stream_Write_UINT32(s, stateOrder->clientAreaWidth);
2843 Stream_Write_UINT32(s, stateOrder->clientAreaHeight);
2846 if ((fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_X) != 0)
2848 Stream_Write_UINT32(s, stateOrder->resizeMarginLeft);
2849 Stream_Write_UINT32(s, stateOrder->resizeMarginRight);
2852 if ((fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_Y) != 0)
2854 Stream_Write_UINT32(s, stateOrder->resizeMarginTop);
2855 Stream_Write_UINT32(s, stateOrder->resizeMarginBottom);
2858 if ((fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT) != 0)
2860 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, stateOrder->RPContent));
2863 if ((fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT) != 0)
2865 Stream_Write_UINT32(s, stateOrder->rootParentHandle);
2868 if ((fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) != 0)
2870 Stream_Write_INT32(s, stateOrder->windowOffsetX);
2871 Stream_Write_INT32(s, stateOrder->windowOffsetY);
2874 if ((fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) != 0)
2876 Stream_Write_INT32(s, stateOrder->windowClientDeltaX);
2877 Stream_Write_INT32(s, stateOrder->windowClientDeltaY);
2880 if ((fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) != 0)
2882 Stream_Write_UINT32(s, stateOrder->windowWidth);
2883 Stream_Write_UINT32(s, stateOrder->windowHeight);
2886 if ((fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) != 0)
2888 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, stateOrder->numWindowRects));
2889 Stream_Write(s, stateOrder->windowRects, stateOrder->numWindowRects *
sizeof(
RECTANGLE_16));
2892 if ((fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) != 0)
2894 Stream_Write_INT32(s, stateOrder->visibleOffsetX);
2895 Stream_Write_INT32(s, stateOrder->visibleOffsetY);
2898 if ((fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) != 0)
2900 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, stateOrder->numVisibilityRects));
2901 Stream_Write(s, stateOrder->visibilityRects,
2902 stateOrder->numVisibilityRects *
sizeof(
RECTANGLE_16));
2905 if ((fieldFlags & WINDOW_ORDER_FIELD_OVERLAY_DESCRIPTION) != 0)
2907 if (rail_write_unicode_string(s, &stateOrder->OverlayDescription) != CHANNEL_RC_OK)
2911 if ((fieldFlags & WINDOW_ORDER_FIELD_TASKBAR_BUTTON) != 0)
2913 Stream_Write_UINT8(s, stateOrder->TaskbarButton);
2916 if ((fieldFlags & WINDOW_ORDER_FIELD_ENFORCE_SERVER_ZORDER) != 0)
2918 Stream_Write_UINT8(s, stateOrder->EnforceServerZOrder);
2921 if ((fieldFlags & WINDOW_ORDER_FIELD_APPBAR_STATE) != 0)
2923 Stream_Write_UINT8(s, stateOrder->AppBarState);
2926 if ((fieldFlags & WINDOW_ORDER_FIELD_APPBAR_EDGE) != 0)
2928 Stream_Write_UINT8(s, stateOrder->AppBarEdge);
2934WINPR_ATTR_NODISCARD
static BOOL
2935update_send_new_or_existing_window(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
2938 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2939 UINT16 orderSize = update_calculate_new_or_existing_window(orderInfo, stateOrder);
2941 WINPR_ASSERT(context);
2942 WINPR_ASSERT(orderInfo);
2943 WINPR_ASSERT(stateOrder);
2947 if (!update_check_flush(context, orderSize))
2955 if (!Stream_EnsureRemainingCapacity(s, orderSize))
2958 Stream_Write_UINT8(s, controlFlags);
2959 Stream_Write_UINT16(s, orderSize);
2960 Stream_Write_UINT32(s, orderInfo->fieldFlags);
2961 Stream_Write_UINT32(s, orderInfo->windowId);
2963 if (!update_write_order_field_flags(orderInfo->fieldFlags, stateOrder, s))
2966 update->numberOrders++;
2970WINPR_ATTR_NODISCARD
static BOOL update_send_window_create(rdpContext* context,
2974 return update_send_new_or_existing_window(context, orderInfo, stateOrder);
2977WINPR_ATTR_NODISCARD
static BOOL update_send_window_update(rdpContext* context,
2981 return update_send_new_or_existing_window(context, orderInfo, stateOrder);
2984WINPR_ATTR_NODISCARD
static UINT16
2985update_calculate_window_icon_order(WINPR_ATTR_UNUSED
const WINDOW_ORDER_INFO* orderInfo,
2988 UINT16 orderSize = 23;
2990 WINPR_ASSERT(iconOrder);
2991 ICON_INFO* iconInfo = iconOrder->iconInfo;
2992 WINPR_ASSERT(iconInfo);
2994 orderSize += iconInfo->cbBitsColor + iconInfo->cbBitsMask;
2996 if (iconInfo->bpp <= 8)
2997 orderSize += 2 + iconInfo->cbColorTable;
3002WINPR_ATTR_NODISCARD
static BOOL update_send_window_icon(rdpContext* context,
3006 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
3008 WINPR_ASSERT(iconOrder);
3009 ICON_INFO* iconInfo = iconOrder->iconInfo;
3010 UINT16 orderSize = update_calculate_window_icon_order(orderInfo, iconOrder);
3012 WINPR_ASSERT(context);
3013 WINPR_ASSERT(orderInfo);
3014 WINPR_ASSERT(iconInfo);
3018 if (!update_check_flush(context, orderSize))
3023 if (!s || !iconInfo)
3026 if (!Stream_EnsureRemainingCapacity(s, orderSize))
3030 Stream_Write_UINT8(s, controlFlags);
3031 Stream_Write_UINT16(s, orderSize);
3032 Stream_Write_UINT32(s, orderInfo->fieldFlags);
3033 Stream_Write_UINT32(s, orderInfo->windowId);
3035 Stream_Write_UINT16(
3036 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->cacheEntry));
3037 Stream_Write_UINT8(s,
3038 WINPR_ASSERTING_INT_CAST(uint8_t, iconInfo->cacheId));
3039 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, iconInfo->bpp));
3040 Stream_Write_UINT16(s,
3041 WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->width));
3042 Stream_Write_UINT16(
3043 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->height));
3045 if (iconInfo->bpp <= 8)
3047 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(
3048 uint16_t, iconInfo->cbColorTable));
3051 Stream_Write_UINT16(
3052 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->cbBitsMask));
3053 Stream_Write_UINT16(
3054 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->cbBitsColor));
3055 Stream_Write(s, iconInfo->bitsMask, iconInfo->cbBitsMask);
3057 if (iconInfo->bpp <= 8)
3059 Stream_Write(s, iconInfo->colorTable, iconInfo->cbColorTable);
3062 Stream_Write(s, iconInfo->bitsColor, iconInfo->cbBitsColor);
3064 update->numberOrders++;
3068WINPR_ATTR_NODISCARD
static BOOL
3069update_send_window_cached_icon(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
3072 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
3073 UINT16 orderSize = 14;
3075 WINPR_ASSERT(cachedIconOrder);
3078 WINPR_ASSERT(context);
3079 WINPR_ASSERT(orderInfo);
3080 WINPR_ASSERT(cachedIcon);
3084 if (!update_check_flush(context, orderSize))
3091 if (!Stream_EnsureRemainingCapacity(s, orderSize))
3095 Stream_Write_UINT8(s, controlFlags);
3096 Stream_Write_UINT16(s, orderSize);
3097 Stream_Write_UINT32(s, orderInfo->fieldFlags);
3098 Stream_Write_UINT32(s, orderInfo->windowId);
3100 Stream_Write_UINT16(
3101 s, WINPR_ASSERTING_INT_CAST(uint16_t, cachedIcon->cacheEntry));
3103 s, WINPR_ASSERTING_INT_CAST(uint8_t, cachedIcon->cacheId));
3104 update->numberOrders++;
3108WINPR_ATTR_NODISCARD
static BOOL update_send_window_delete(rdpContext* context,
3111 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
3112 UINT16 orderSize = 11;
3114 WINPR_ASSERT(context);
3115 WINPR_ASSERT(orderInfo);
3118 if (!update_check_flush(context, orderSize))
3126 if (!Stream_EnsureRemainingCapacity(s, orderSize))
3130 Stream_Write_UINT8(s, controlFlags);
3131 Stream_Write_UINT16(s, orderSize);
3132 Stream_Write_UINT32(s, orderInfo->fieldFlags);
3133 Stream_Write_UINT32(s, orderInfo->windowId);
3134 update->numberOrders++;
3138WINPR_ATTR_NODISCARD
static UINT16 update_calculate_new_or_existing_notification_icons_order(
3141 UINT16 orderSize = 15;
3143 WINPR_ASSERT(orderInfo);
3144 WINPR_ASSERT(iconStateOrder);
3146 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_VERSION) != 0)
3149 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP) != 0)
3151 orderSize += 2 + iconStateOrder->toolTip.length;
3154 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP) != 0)
3157 orderSize += 12 + infoTip.text.length + infoTip.title.length;
3160 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_STATE) != 0)
3165 if ((orderInfo->fieldFlags & WINDOW_ORDER_ICON) != 0)
3167 ICON_INFO iconInfo = iconStateOrder->icon;
3170 if (iconInfo.bpp <= 8)
3171 orderSize += 2 + iconInfo.cbColorTable;
3173 orderSize += iconInfo.cbBitsMask + iconInfo.cbBitsColor;
3175 else if ((orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON) != 0)
3183WINPR_ATTR_NODISCARD
static BOOL update_send_new_or_existing_order_icon(
const ICON_INFO* iconInfo,
3186 WINPR_ASSERT(iconInfo);
3188 if (!Stream_EnsureRemainingCapacity(s, 8))
3191 Stream_Write_UINT16(
3192 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->cacheEntry));
3193 Stream_Write_UINT8(s,
3194 WINPR_ASSERTING_INT_CAST(uint8_t, iconInfo->cacheId));
3195 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, iconInfo->bpp));
3196 Stream_Write_UINT16(s,
3197 WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->width));
3198 Stream_Write_UINT16(
3199 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->height));
3201 if (iconInfo->bpp <= 8)
3203 if (!Stream_EnsureRemainingCapacity(s, 2))
3205 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(
3206 uint16_t, iconInfo->cbColorTable));
3209 if (!Stream_EnsureRemainingCapacity(s, 4ULL + iconInfo->cbBitsMask))
3211 Stream_Write_UINT16(
3212 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->cbBitsMask));
3213 Stream_Write_UINT16(
3214 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->cbBitsColor));
3215 Stream_Write(s, iconInfo->bitsMask, iconInfo->cbBitsMask);
3217 if (iconInfo->bpp <= 8)
3219 if (!Stream_EnsureRemainingCapacity(s, iconInfo->cbColorTable))
3221 Stream_Write(s, iconInfo->colorTable, iconInfo->cbColorTable);
3224 if (!Stream_EnsureRemainingCapacity(s, iconInfo->cbBitsColor))
3226 Stream_Write(s, iconInfo->bitsColor, iconInfo->cbBitsColor);
3230WINPR_ATTR_NODISCARD
static BOOL
3231update_send_new_or_existing_notification_icons(rdpContext* context,
3235 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
3236 BOOL versionFieldPresent = FALSE;
3237 const UINT16 orderSize =
3238 update_calculate_new_or_existing_notification_icons_order(orderInfo, iconStateOrder);
3240 WINPR_ASSERT(context);
3241 WINPR_ASSERT(orderInfo);
3242 WINPR_ASSERT(iconStateOrder);
3245 if (!update_check_flush(context, orderSize))
3252 if (!Stream_EnsureRemainingCapacity(s, orderSize))
3256 Stream_Write_UINT8(s, controlFlags);
3257 Stream_Write_UINT16(s, orderSize);
3258 Stream_Write_UINT32(s, orderInfo->fieldFlags);
3259 Stream_Write_UINT32(s, orderInfo->windowId);
3260 Stream_Write_UINT32(s, orderInfo->notifyIconId);
3263 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_VERSION) != 0)
3265 versionFieldPresent = TRUE;
3266 Stream_Write_UINT32(s, iconStateOrder->version);
3269 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP) != 0)
3271 if (rail_write_unicode_string(s, &iconStateOrder->toolTip) != CHANNEL_RC_OK)
3275 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP) != 0)
3280 if (versionFieldPresent && iconStateOrder->version == 0)
3283 Stream_Write_UINT32(s, infoTip.timeout);
3284 Stream_Write_UINT32(s, infoTip.flags);
3285 if (rail_write_unicode_string(s, &infoTip.text) != CHANNEL_RC_OK)
3287 if (rail_write_unicode_string(s, &infoTip.title) != CHANNEL_RC_OK)
3291 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_STATE) != 0)
3294 if (versionFieldPresent && iconStateOrder->version == 0)
3297 Stream_Write_UINT32(s, iconStateOrder->state);
3300 if ((orderInfo->fieldFlags & WINDOW_ORDER_ICON) != 0)
3302 const ICON_INFO* iconInfo = &iconStateOrder->icon;
3304 if (!update_send_new_or_existing_order_icon(iconInfo, s))
3307 else if ((orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON) != 0)
3310 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(
3311 uint16_t, cachedIcon.cacheEntry));
3313 s, WINPR_ASSERTING_INT_CAST(uint8_t, cachedIcon.cacheId));
3316 update->numberOrders++;
3320WINPR_ATTR_NODISCARD
static BOOL
3321update_send_notify_icon_create(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
3324 return update_send_new_or_existing_notification_icons(context, orderInfo, iconStateOrder);
3327WINPR_ATTR_NODISCARD
static BOOL
3328update_send_notify_icon_update(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
3331 return update_send_new_or_existing_notification_icons(context, orderInfo, iconStateOrder);
3334WINPR_ATTR_NODISCARD
static BOOL update_send_notify_icon_delete(rdpContext* context,
3337 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
3338 UINT16 orderSize = 15;
3340 WINPR_ASSERT(context);
3341 WINPR_ASSERT(orderInfo);
3344 if (!update_check_flush(context, orderSize))
3353 Stream_Write_UINT8(s, controlFlags);
3354 Stream_Write_UINT16(s, orderSize);
3355 Stream_Write_UINT32(s, orderInfo->fieldFlags);
3356 Stream_Write_UINT32(s, orderInfo->windowId);
3357 Stream_Write_UINT32(s, orderInfo->notifyIconId);
3358 update->numberOrders++;
3362WINPR_ATTR_NODISCARD
static UINT16
3366 UINT16 orderSize = 7;
3368 WINPR_ASSERT(orderInfo);
3369 WINPR_ASSERT(monitoredDesktop);
3371 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
3376 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
3378 orderSize += 1 + (4 * monitoredDesktop->numWindowIds);
3384WINPR_ATTR_NODISCARD
static BOOL
3385update_send_monitored_desktop(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
3388 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
3389 UINT16 orderSize = update_calculate_monitored_desktop(orderInfo, monitoredDesktop);
3391 WINPR_ASSERT(context);
3392 WINPR_ASSERT(orderInfo);
3393 WINPR_ASSERT(monitoredDesktop);
3397 if (!update_check_flush(context, orderSize))
3405 Stream_Write_UINT8(s, controlFlags);
3406 Stream_Write_UINT16(s, orderSize);
3407 Stream_Write_UINT32(s, orderInfo->fieldFlags);
3409 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
3411 Stream_Write_UINT32(s, monitoredDesktop->activeWindowId);
3414 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
3417 s, WINPR_ASSERTING_INT_CAST(
3418 uint8_t, monitoredDesktop->numWindowIds));
3421 for (UINT32 i = 0; i < monitoredDesktop->numWindowIds; i++)
3423 Stream_Write_UINT32(s,
3424 WINPR_ASSERTING_INT_CAST(uint32_t, monitoredDesktop->windowIds[i]));
3428 update->numberOrders++;
3432WINPR_ATTR_NODISCARD
static BOOL
3433update_send_non_monitored_desktop(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo)
3435 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
3436 UINT16 orderSize = 7;
3438 WINPR_ASSERT(context);
3439 WINPR_ASSERT(orderInfo);
3442 if (!update_check_flush(context, orderSize))
3450 Stream_Write_UINT8(s, controlFlags);
3451 Stream_Write_UINT16(s, orderSize);
3452 Stream_Write_UINT32(s, orderInfo->fieldFlags);
3453 update->numberOrders++;
3457void update_register_server_callbacks(rdpUpdate* update)
3459 WINPR_ASSERT(update);
3461 update->BeginPaint = s_update_begin_paint;
3462 update->EndPaint = s_update_end_paint;
3463 update->SetBounds = update_set_bounds;
3464 update->Synchronize = update_send_synchronize;
3465 update->DesktopResize = update_send_desktop_resize;
3466 update->BitmapUpdate = update_send_bitmap_update;
3467 update->SurfaceBits = update_send_surface_bits;
3468 update->SurfaceFrameMarker = update_send_surface_frame_marker;
3469 update->SurfaceCommand = update_send_surface_command;
3470 update->SurfaceFrameBits = update_send_surface_frame_bits;
3471 update->PlaySound = update_send_play_sound;
3472 update->SetKeyboardIndicators = update_send_set_keyboard_indicators;
3473 update->SetKeyboardImeStatus = update_send_set_keyboard_ime_status;
3474 update->SaveSessionInfo = rdp_send_save_session_info;
3475 update->ServerStatusInfo = rdp_send_server_status_info;
3476 update->primary->DstBlt = update_send_dstblt;
3477 update->primary->PatBlt = update_send_patblt;
3478 update->primary->ScrBlt = update_send_scrblt;
3479 update->primary->OpaqueRect = update_send_opaque_rect;
3480 update->primary->LineTo = update_send_line_to;
3481 update->primary->MemBlt = update_send_memblt;
3482 update->primary->GlyphIndex = update_send_glyph_index;
3483 update->secondary->CacheBitmap = update_send_cache_bitmap;
3484 update->secondary->CacheBitmapV2 = update_send_cache_bitmap_v2;
3485 update->secondary->CacheBitmapV3 = update_send_cache_bitmap_v3;
3486 update->secondary->CacheColorTable = update_send_cache_color_table;
3487 update->secondary->CacheGlyph = update_send_cache_glyph;
3488 update->secondary->CacheGlyphV2 = update_send_cache_glyph_v2;
3489 update->secondary->CacheBrush = update_send_cache_brush;
3490 update->altsec->CreateOffscreenBitmap = update_send_create_offscreen_bitmap_order;
3491 update->altsec->SwitchSurface = update_send_switch_surface_order;
3492 update->pointer->PointerSystem = update_send_pointer_system;
3493 update->pointer->PointerPosition = update_send_pointer_position;
3494 update->pointer->PointerColor = update_send_pointer_color;
3495 update->pointer->PointerLarge = update_send_pointer_large;
3496 update->pointer->PointerNew = update_send_pointer_new;
3497 update->pointer->PointerCached = update_send_pointer_cached;
3498 update->window->WindowCreate = update_send_window_create;
3499 update->window->WindowUpdate = update_send_window_update;
3500 update->window->WindowIcon = update_send_window_icon;
3501 update->window->WindowCachedIcon = update_send_window_cached_icon;
3502 update->window->WindowDelete = update_send_window_delete;
3503 update->window->NotifyIconCreate = update_send_notify_icon_create;
3504 update->window->NotifyIconUpdate = update_send_notify_icon_update;
3505 update->window->NotifyIconDelete = update_send_notify_icon_delete;
3506 update->window->MonitoredDesktop = update_send_monitored_desktop;
3507 update->window->NonMonitoredDesktop = update_send_non_monitored_desktop;
3510void update_register_client_callbacks(rdpUpdate* update)
3512 WINPR_ASSERT(update);
3514 update->RefreshRect = update_send_refresh_rect;
3515 update->SuppressOutput = update_send_suppress_output;
3516 update->SurfaceFrameAcknowledge = update_send_frame_acknowledge;
3519int update_process_messages(rdpUpdate* update)
3521 return update_message_queue_process_pending_messages(update);
3524static void update_free_queued_message(
void* obj)
3526 wMessage* msg = (wMessage*)obj;
3527 update_message_queue_free_message(msg);
3535 rail_unicode_string_free(&window_state->OverlayDescription);
3536 rail_unicode_string_free(&window_state->titleInfo);
3537 free(window_state->windowRects);
3538 free(window_state->visibilityRects);
3542rdpUpdate* update_new(rdpRdp* rdp)
3544 const wObject cb = {
nullptr,
nullptr,
nullptr, update_free_queued_message,
nullptr };
3547 WINPR_ASSERT(rdp->context);
3554 update->common.context = rdp->context;
3555 update->log = WLog_Get(
"com.freerdp.core.update");
3556 InitializeCriticalSection(&(update->mux));
3557 update->common.pointer = (rdpPointerUpdate*)calloc(1,
sizeof(rdpPointerUpdate));
3559 if (!update->common.pointer)
3568 update->common.primary = &primary->common;
3577 update->common.secondary = &secondary->common;
3587 update->common.altsec = &altsec->common;
3589 update->common.window = (rdpWindowUpdate*)calloc(1,
sizeof(rdpWindowUpdate));
3591 if (!update->common.window)
3596 deleteList->sIndices = 64;
3597 deleteList->indices = calloc(deleteList->sIndices, 2);
3599 if (!deleteList->indices)
3602 deleteList->cIndices = 0;
3606 update->common.SuppressOutput = update_send_suppress_output;
3607 update->initialState = TRUE;
3608 update->common.autoCalculateBitmapData = TRUE;
3609 update->queue = MessageQueue_New(&cb);
3614 return &update->common;
3616 WINPR_PRAGMA_DIAG_PUSH
3617 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
3618 update_free(&update->common);
3619 WINPR_PRAGMA_DIAG_POP
3623void update_free(rdpUpdate* update)
3625 if (update !=
nullptr)
3632 free(deleteList->indices);
3634 free(update->pointer);
3636 if (update->primary)
3640 free(primary->polygon_cb.points);
3641 free(primary->polyline.points);
3642 free(primary->polygon_sc.points);
3643 free(primary->fast_glyph.glyphData.aj);
3647 free(update->secondary);
3651 free(update->window);
3653 MessageQueue_Free(up->queue);
3654 DeleteCriticalSection(&up->mux);
3657 Stream_Free(up->us, TRUE);
3662void rdp_update_lock(rdpUpdate* update)
3665 EnterCriticalSection(&up->mux);
3668void rdp_update_unlock(rdpUpdate* update)
3671 LeaveCriticalSection(&up->mux);
3674BOOL update_begin_paint(rdpUpdate* update)
3677 WINPR_ASSERT(update);
3678 rdp_update_lock(update);
3680 up->withinBeginEndPaint = TRUE;
3682 WINPR_ASSERT(update->context);
3684 up->stats.base[RDP_STATS_BEGIN_PAINT]++;
3685 BOOL rc = IFCALLRESULT(TRUE, update->BeginPaint, update->context);
3687 WLog_WARN(TAG,
"BeginPaint call failed");
3690 rdpGdi* gdi = update->context->gdi;
3694 if (gdi->hdc && gdi->primary && gdi->primary->hdc)
3696 HGDI_WND hwnd = gdi->primary->hdc->hwnd;
3698 WINPR_ASSERT(hwnd->invalid);
3700 hwnd->invalid->null = TRUE;
3707BOOL update_end_paint(rdpUpdate* update)
3712 WINPR_ASSERT(update);
3713 up->stats.base[RDP_STATS_END_PAINT]++;
3715 IFCALLRET(update->EndPaint, rc, update->context);
3717 WLog_WARN(TAG,
"EndPaint call failed");
3719 if (!up->withinBeginEndPaint)
3721 up->withinBeginEndPaint = FALSE;
3723 rdp_update_unlock(update);
3727uint64_t rdp_stats_value_for_index(rdpUpdate* context,
size_t index)
3732 size_t limit = ARRAYSIZE(up->stats.primary);
3735 return up->stats.primary[index];
3738 limit += ARRAYSIZE(up->stats.secondary);
3740 return up->stats.secondary[index - offset];
3743 limit += ARRAYSIZE(up->stats.altsec);
3745 return up->stats.altsec[index - offset];
3748 limit += ARRAYSIZE(up->stats.base);
3750 return up->stats.base[index - offset];
3755const char* rdp_stats_name_for_index(
size_t index)
3757 if (!InitOnceExecuteOnce(&stats_names_once, stats_names_generate,
nullptr,
nullptr))
3758 return "RDP_STATS_UNUSED";
3759 if (index < rdp_stats_max_index())
3760 return stats_names[index];
3761 return "RDP_STATS_UNUSED";
3764size_t rdp_stats_max_index(
void)
3766 return RDP_STATS_COUNT;
3769void update_dump_stats(rdpUpdate* update)
3774 wLog* log = up->log;
3775 const DWORD level = WLOG_TRACE;
3776 if (!WLog_IsLevelActive(log, level))
3779 WLog_Print(log, level,
"RdpCodecStats");
3780 for (
size_t x = 0; x < rdp_stats_max_index(); x++)
3782 const char* name = rdp_stats_name_for_index(x);
3783 const uint64_t val = rdp_stats_value_for_index(update, x);
3787 WINPR_ASSERT(name && strnlen(name, 2) > 0);
3788 const bool unknown = strstr(name,
" UNKNOWN") !=
nullptr;
3789 const bool unused = strstr(name,
"UNUSED") !=
nullptr;
3790 const bool sunused = strcmp(
"RDP_STATS_UNUSED", name) == 0;
3791 if ((val != 0) || (!unknown && !sunused && !unused))
3792 WLog_Print(log, level,
"%s: %" PRIu64, name, val);
This struct contains function pointer to initialize/free objects.