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];
57static BOOL stats_names_generate(WINPR_ATTR_UNUSED
PINIT_ONCE InitOnce,
58 WINPR_ATTR_UNUSED PVOID Parameter,
59 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);
72 primary_order_string(WINPR_ASSERTING_INT_CAST(UINT32, index), buffer, bufferlen);
75 WINPR_ASSERT(strnlen(buffer, 2) > 0);
80 limit += ARRAYSIZE(stats.secondary);
83 const char* str = secondary_order_string(
84 WINPR_ASSERTING_INT_CAST(UINT32, index - offset), buffer, bufferlen);
87 WINPR_ASSERT(strnlen(buffer, 2) > 0);
92 limit += ARRAYSIZE(stats.altsec);
95 const char* str = altsec_order_string(WINPR_ASSERTING_INT_CAST(BYTE, index - offset),
99 WINPR_ASSERT(strnlen(buffer, 2) > 0);
104 limit += ARRAYSIZE(stats.base);
109 (void)_snprintf(buffer, bufferlen, "%s", #x); \
112 switch (index - offset)
114 EVCASE(RDP_STATS_SURFACE_BITS);
115 EVCASE(RDP_STATS_SURFACE_BITS_NSC);
116 EVCASE(RDP_STATS_SURFACE_BITS_RFX);
117 EVCASE(RDP_STATS_SURFACE_BITS_RFX_IMAGE);
118 EVCASE(RDP_STATS_SURFACE_BITS_NONE);
119 EVCASE(RDP_STATS_SURFACE_BITS_UNKNOWN);
120 EVCASE(RDP_STATS_BEGIN_PAINT);
121 EVCASE(RDP_STATS_END_PAINT);
122 EVCASE(RDP_STATS_SET_BOUNDS);
123 EVCASE(RDP_STATS_SYNC);
124 EVCASE(RDP_STATS_RESIZE);
125 EVCASE(RDP_STATS_BITMAP_UPDATE);
126 EVCASE(RDP_STATS_PALETTE);
127 EVCASE(RDP_STATS_REFRESH_RECT);
128 EVCASE(RDP_STATS_SUPPRESS_OUTPUT);
129 EVCASE(RDP_STATS_SURFACE_COMMAND);
130 EVCASE(RDP_STATS_SURFACE_FRAME_MARKER);
131 EVCASE(RDP_STATS_SURFACE_FRAME_ACK);
132 EVCASE(RDP_STATS_POINTER_SYSTEM);
133 EVCASE(RDP_STATS_POINTER_DEFAULT);
134 EVCASE(RDP_STATS_POINTER_POSITION);
135 EVCASE(RDP_STATS_POINTER_COLOR);
136 EVCASE(RDP_STATS_POINTER_CACHED);
137 EVCASE(RDP_STATS_POINTER_NEW);
138 EVCASE(RDP_STATS_POINTER_LARGE);
140 (void)_snprintf(buffer, bufferlen,
"RDP_STATS_UNUSED");
146 (
void)_snprintf(buffer, bufferlen,
"RDP_STATS_UNUSED");
151static const char*
const UPDATE_TYPE_STRINGS[] = {
"Orders",
"Bitmap",
"Palette",
"Synchronize" };
153static const char* update_type_to_string(UINT16 updateType)
155 if (updateType >= ARRAYSIZE(UPDATE_TYPE_STRINGS))
158 return UPDATE_TYPE_STRINGS[updateType];
161static BOOL update_recv_orders(rdpUpdate* update,
wStream* s)
163 UINT16 numberOrders = 0;
165 WINPR_ASSERT(update);
167 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
170 Stream_Seek_UINT16(s);
171 Stream_Read_UINT16(s, numberOrders);
172 Stream_Seek_UINT16(s);
174 while (numberOrders > 0)
176 if (!update_recv_order(update, s))
178 WLog_ERR(TAG,
"update_recv_order() failed");
188static BOOL update_read_bitmap_data(rdpUpdate* update,
wStream* s,
BITMAP_DATA* bitmapData)
190 WINPR_UNUSED(update);
191 WINPR_ASSERT(bitmapData);
193 if (!Stream_CheckAndLogRequiredLength(TAG, s, 18))
196 Stream_Read_UINT16(s, bitmapData->destLeft);
197 Stream_Read_UINT16(s, bitmapData->destTop);
198 Stream_Read_UINT16(s, bitmapData->destRight);
199 Stream_Read_UINT16(s, bitmapData->destBottom);
200 Stream_Read_UINT16(s, bitmapData->width);
201 Stream_Read_UINT16(s, bitmapData->height);
202 Stream_Read_UINT16(s, bitmapData->bitsPerPixel);
203 Stream_Read_UINT16(s, bitmapData->flags);
204 Stream_Read_UINT16(s, bitmapData->bitmapLength);
206 if ((bitmapData->width == 0) || (bitmapData->height == 0))
208 WLog_ERR(TAG,
"Invalid BITMAP_DATA: width=%" PRIu16
", height=%" PRIu16, bitmapData->width,
213 if (bitmapData->flags & BITMAP_COMPRESSION)
215 if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR))
217 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
220 Stream_Read_UINT16(s,
221 bitmapData->cbCompFirstRowSize);
222 Stream_Read_UINT16(s,
223 bitmapData->cbCompMainBodySize);
224 Stream_Read_UINT16(s, bitmapData->cbScanWidth);
225 Stream_Read_UINT16(s,
226 bitmapData->cbUncompressedSize);
227 bitmapData->bitmapLength = bitmapData->cbCompMainBodySize;
230 bitmapData->compressed = TRUE;
233 bitmapData->compressed = FALSE;
235 if (!Stream_CheckAndLogRequiredLength(TAG, s, bitmapData->bitmapLength))
238 if (bitmapData->bitmapLength > 0)
240 bitmapData->bitmapDataStream = malloc(bitmapData->bitmapLength);
242 if (!bitmapData->bitmapDataStream)
245 memcpy(bitmapData->bitmapDataStream, Stream_ConstPointer(s), bitmapData->bitmapLength);
246 Stream_Seek(s, bitmapData->bitmapLength);
254 WINPR_ASSERT(bitmapData);
255 if (!Stream_EnsureRemainingCapacity(s, 18))
257 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->destLeft));
258 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->destTop));
259 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->destRight));
260 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->destBottom));
261 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->width));
262 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->height));
263 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->bitsPerPixel));
264 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->flags));
265 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->bitmapLength));
269static BOOL update_write_bitmap_data_no_comp_header(
const BITMAP_DATA* bitmapData,
wStream* s)
271 WINPR_ASSERT(bitmapData);
272 if (!Stream_EnsureRemainingCapacity(s, 8))
276 s, WINPR_ASSERTING_INT_CAST(
277 uint16_t, bitmapData->cbCompFirstRowSize));
279 s, WINPR_ASSERTING_INT_CAST(
280 uint16_t, bitmapData->cbCompMainBodySize));
282 s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->cbScanWidth));
284 s, WINPR_ASSERTING_INT_CAST(
285 uint16_t, bitmapData->cbUncompressedSize));
289static BOOL update_write_bitmap_data(rdpUpdate* update_pub,
wStream* s,
BITMAP_DATA* bitmapData)
293 WINPR_ASSERT(bitmapData);
295 if (!Stream_EnsureRemainingCapacity(s, 64 + bitmapData->bitmapLength))
298 if (update->common.autoCalculateBitmapData)
300 bitmapData->flags = 0;
301 bitmapData->cbCompFirstRowSize = 0;
303 if (bitmapData->compressed)
304 bitmapData->flags |= BITMAP_COMPRESSION;
306 if (update->common.context->settings->NoBitmapCompressionHeader)
308 bitmapData->flags |= NO_BITMAP_COMPRESSION_HDR;
309 bitmapData->cbCompMainBodySize = bitmapData->bitmapLength;
313 if (!update_write_bitmap_data_header(bitmapData, s))
316 if (bitmapData->flags & BITMAP_COMPRESSION)
318 if ((bitmapData->flags & NO_BITMAP_COMPRESSION_HDR) == 0)
320 if (!update_write_bitmap_data_no_comp_header(bitmapData, s))
325 if (!Stream_EnsureRemainingCapacity(s, bitmapData->bitmapLength))
327 Stream_Write(s, bitmapData->bitmapDataStream, bitmapData->bitmapLength);
340 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
343 Stream_Read_UINT16(s, bitmapUpdate->number);
344 WLog_Print(up->log, WLOG_TRACE,
"BitmapUpdate: %" PRIu32
"", bitmapUpdate->number);
348 if (!bitmapUpdate->rectangles)
352 for (UINT32 i = 0; i < bitmapUpdate->number; i++)
354 if (!update_read_bitmap_data(update, s, &bitmapUpdate->rectangles[i]))
360 WINPR_PRAGMA_DIAG_PUSH
361 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
362 free_bitmap_update(update->context, bitmapUpdate);
363 WINPR_PRAGMA_DIAG_POP
367static BOOL update_write_bitmap_update(rdpUpdate* update,
wStream* s,
370 WINPR_ASSERT(update);
371 WINPR_ASSERT(bitmapUpdate);
373 if (!Stream_EnsureRemainingCapacity(s, 32))
376 Stream_Write_UINT16(s, UPDATE_TYPE_BITMAP);
377 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(
378 uint16_t, bitmapUpdate->number));
381 for (UINT32 i = 0; i < bitmapUpdate->number; i++)
383 if (!update_write_bitmap_data(update, s, &bitmapUpdate->rectangles[i]))
397 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
400 Stream_Seek_UINT16(s);
401 Stream_Read_UINT32(s, palette_update->number);
403 if (palette_update->number > 256)
404 palette_update->number = 256;
406 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, palette_update->number, 3ull))
410 for (UINT32 i = 0; i < palette_update->number; i++)
413 Stream_Read_UINT8(s, entry->red);
414 Stream_Read_UINT8(s, entry->green);
415 Stream_Read_UINT8(s, entry->blue);
418 return palette_update;
420 WINPR_PRAGMA_DIAG_PUSH
421 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
422 free_palette_update(update->context, palette_update);
423 WINPR_PRAGMA_DIAG_POP
427static BOOL update_read_synchronize(rdpUpdate* update,
wStream* s)
429 WINPR_UNUSED(update);
430 return Stream_SafeSeek(s, 2);
439 WINPR_ASSERT(play_sound);
441 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
444 Stream_Read_UINT32(s, play_sound->duration);
445 Stream_Read_UINT32(s, play_sound->frequency);
449BOOL update_recv_play_sound(rdpUpdate* update,
wStream* s)
453 WINPR_ASSERT(update);
455 if (!update_read_play_sound(s, &play_sound))
458 return IFCALLRESULT(TRUE, update->PlaySound, update->context, &play_sound);
465 WINPR_ASSERT(update);
467 if (!pointer_position)
470 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
473 Stream_Read_UINT16(s, pointer_position->xPos);
474 Stream_Read_UINT16(s, pointer_position->yPos);
475 return pointer_position;
477 WINPR_PRAGMA_DIAG_PUSH
478 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
479 free_pointer_position_update(update->context, pointer_position);
480 WINPR_PRAGMA_DIAG_POP
488 WINPR_ASSERT(update);
493 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
496 Stream_Read_UINT32(s, pointer_system->type);
497 return pointer_system;
499 WINPR_PRAGMA_DIAG_PUSH
500 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
501 free_pointer_system_update(update->context, pointer_system);
502 WINPR_PRAGMA_DIAG_POP
507 BYTE xorBpp, UINT32 flags)
509 BYTE* newMask =
nullptr;
510 UINT32 scanlineSize = 0;
513 WINPR_ASSERT(pointer_color);
515 if (flags & LARGE_POINTER_FLAG_96x96)
521 if (!Stream_CheckAndLogRequiredLength(TAG, s, 14))
524 Stream_Read_UINT16(s, pointer_color->cacheIndex);
525 Stream_Read_UINT16(s, pointer_color->hotSpotX);
526 Stream_Read_UINT16(s, pointer_color->hotSpotY);
536 Stream_Read_UINT16(s, pointer_color->width);
537 Stream_Read_UINT16(s, pointer_color->height);
539 if ((pointer_color->width > max) || (pointer_color->height > max))
542 Stream_Read_UINT16(s, pointer_color->lengthAndMask);
543 Stream_Read_UINT16(s, pointer_color->lengthXorMask);
551 if (pointer_color->hotSpotX >= pointer_color->width)
552 pointer_color->hotSpotX = 0;
554 if (pointer_color->hotSpotY >= pointer_color->height)
555 pointer_color->hotSpotY = 0;
557 if (pointer_color->lengthXorMask > 0)
570 if (!Stream_CheckAndLogRequiredLength(TAG, s, pointer_color->lengthXorMask))
573 scanlineSize = (7 + xorBpp * pointer_color->width) / 8;
574 scanlineSize = ((scanlineSize + 1) / 2) * 2;
576 if (scanlineSize * pointer_color->height != pointer_color->lengthXorMask)
579 "invalid lengthXorMask: width=%" PRIu32
" height=%" PRIu32
", %" PRIu32
580 " instead of %" PRIu32
"",
581 pointer_color->width, pointer_color->height, pointer_color->lengthXorMask,
582 scanlineSize * pointer_color->height);
586 newMask = realloc(pointer_color->xorMaskData, pointer_color->lengthXorMask);
591 pointer_color->xorMaskData = newMask;
592 Stream_Read(s, pointer_color->xorMaskData, pointer_color->lengthXorMask);
595 if (pointer_color->lengthAndMask > 0)
604 if (!Stream_CheckAndLogRequiredLength(TAG, s, pointer_color->lengthAndMask))
607 scanlineSize = ((7 + pointer_color->width) / 8);
608 scanlineSize = ((1 + scanlineSize) / 2) * 2;
610 if (scanlineSize * pointer_color->height != pointer_color->lengthAndMask)
612 WLog_ERR(TAG,
"invalid lengthAndMask: %" PRIu32
" instead of %" PRIu32
"",
613 pointer_color->lengthAndMask, scanlineSize * pointer_color->height);
617 newMask = realloc(pointer_color->andMaskData, pointer_color->lengthAndMask);
622 pointer_color->andMaskData = newMask;
623 Stream_Read(s, pointer_color->andMaskData, pointer_color->lengthAndMask);
626 if (Stream_GetRemainingLength(s) > 0)
627 Stream_Seek_UINT8(s);
638 WINPR_ASSERT(update);
643 if (!s_update_read_pointer_color(s, pointer_color, xorBpp,
644 update->context->settings->LargePointerFlag))
647 return pointer_color;
649 WINPR_PRAGMA_DIAG_PUSH
650 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
651 free_pointer_color_update(update->context, pointer_color);
652 WINPR_PRAGMA_DIAG_POP
658 BYTE* newMask =
nullptr;
659 UINT32 scanlineSize = 0;
664 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
667 Stream_Read_UINT16(s, pointer->xorBpp);
668 Stream_Read_UINT16(s, pointer->cacheIndex);
669 Stream_Read_UINT16(s, pointer->hotSpotX);
670 Stream_Read_UINT16(s, pointer->hotSpotY);
672 Stream_Read_UINT16(s, pointer->width);
673 Stream_Read_UINT16(s, pointer->height);
675 if ((pointer->width > 384) || (pointer->height > 384))
678 Stream_Read_UINT32(s, pointer->lengthAndMask);
679 Stream_Read_UINT32(s, pointer->lengthXorMask);
681 if (pointer->hotSpotX >= pointer->width)
682 pointer->hotSpotX = 0;
684 if (pointer->hotSpotY >= pointer->height)
685 pointer->hotSpotY = 0;
687 if (pointer->lengthXorMask > 0)
700 if (!Stream_CheckAndLogRequiredLength(TAG, s, pointer->lengthXorMask))
703 scanlineSize = (7 + pointer->xorBpp * pointer->width) / 8;
704 scanlineSize = ((scanlineSize + 1) / 2) * 2;
706 if (scanlineSize * pointer->height != pointer->lengthXorMask)
709 "invalid lengthXorMask: width=%" PRIu32
" height=%" PRIu32
", %" PRIu32
710 " instead of %" PRIu32
"",
711 pointer->width, pointer->height, pointer->lengthXorMask,
712 scanlineSize * pointer->height);
716 newMask = realloc(pointer->xorMaskData, pointer->lengthXorMask);
721 pointer->xorMaskData = newMask;
722 Stream_Read(s, pointer->xorMaskData, pointer->lengthXorMask);
725 if (pointer->lengthAndMask > 0)
734 if (!Stream_CheckAndLogRequiredLength(TAG, s, pointer->lengthAndMask))
737 scanlineSize = ((7 + pointer->width) / 8);
738 scanlineSize = ((1 + scanlineSize) / 2) * 2;
740 if (scanlineSize * pointer->height != pointer->lengthAndMask)
742 WLog_ERR(TAG,
"invalid lengthAndMask: %" PRIu32
" instead of %" PRIu32
"",
743 pointer->lengthAndMask, scanlineSize * pointer->height);
747 newMask = realloc(pointer->andMaskData, pointer->lengthAndMask);
752 pointer->andMaskData = newMask;
753 Stream_Read(s, pointer->andMaskData, pointer->lengthAndMask);
756 if (Stream_GetRemainingLength(s) > 0)
757 Stream_Seek_UINT8(s);
768 WINPR_ASSERT(update);
773 if (!s_update_read_pointer_large(s, pointer))
778 WINPR_PRAGMA_DIAG_PUSH
779 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
780 free_pointer_large_update(update->context, pointer);
781 WINPR_PRAGMA_DIAG_POP
789 WINPR_ASSERT(update);
794 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
797 Stream_Read_UINT16(s, pointer_new->xorBpp);
799 if ((pointer_new->xorBpp < 1) || (pointer_new->xorBpp > 32))
801 WLog_ERR(TAG,
"invalid xorBpp %" PRIu32
"", pointer_new->xorBpp);
805 WINPR_ASSERT(pointer_new->xorBpp <= UINT8_MAX);
806 if (!s_update_read_pointer_color(
807 s, &pointer_new->colorPtrAttr, (UINT8)pointer_new->xorBpp,
808 update->context->settings->LargePointerFlag))
813 WINPR_PRAGMA_DIAG_PUSH
814 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
815 free_pointer_new_update(update->context, pointer_new);
816 WINPR_PRAGMA_DIAG_POP
824 WINPR_ASSERT(update);
829 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
832 Stream_Read_UINT16(s, pointer->cacheIndex);
835 WINPR_PRAGMA_DIAG_PUSH
836 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
837 free_pointer_cached_update(update->context, pointer);
838 WINPR_PRAGMA_DIAG_POP
842BOOL update_recv_pointer(rdpUpdate* update,
wStream* s)
845 UINT16 messageType = 0;
847 WINPR_ASSERT(update);
849 rdpContext* context = update->context;
850 rdpPointerUpdate* pointer = update->pointer;
852 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2 + 2))
855 Stream_Read_UINT16(s, messageType);
856 Stream_Seek_UINT16(s);
860 case PTR_MSG_TYPE_POSITION:
864 if (pointer_position)
866 rc = IFCALLRESULT(FALSE, pointer->PointerPosition, context, pointer_position);
867 free_pointer_position_update(context, pointer_position);
872 case PTR_MSG_TYPE_SYSTEM:
878 rc = IFCALLRESULT(FALSE, pointer->PointerSystem, context, pointer_system);
879 free_pointer_system_update(context, pointer_system);
884 case PTR_MSG_TYPE_COLOR:
890 rc = IFCALLRESULT(FALSE, pointer->PointerColor, context, pointer_color);
891 free_pointer_color_update(context, pointer_color);
896 case PTR_MSG_TYPE_POINTER_LARGE:
902 rc = IFCALLRESULT(FALSE, pointer->PointerLarge, context, pointer_large);
903 free_pointer_large_update(context, pointer_large);
908 case PTR_MSG_TYPE_POINTER:
914 rc = IFCALLRESULT(FALSE, pointer->PointerNew, context, pointer_new);
915 free_pointer_new_update(context, pointer_new);
920 case PTR_MSG_TYPE_CACHED:
926 rc = IFCALLRESULT(FALSE, pointer->PointerCached, context, pointer_cached);
927 free_pointer_cached_update(context, pointer_cached);
939BOOL update_recv(rdpUpdate* update,
wStream* s)
942 UINT16 updateType = 0;
944 rdpContext* context = update->context;
946 WINPR_ASSERT(context);
948 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
951 Stream_Read_UINT16(s, updateType);
952 WLog_Print(up->log, WLOG_TRACE,
"%s Update Data PDU", update_type_to_string(updateType));
954 if (!update_begin_paint(update))
959 case UPDATE_TYPE_ORDERS:
960 rc = update_recv_orders(update, s);
963 case UPDATE_TYPE_BITMAP:
965 BITMAP_UPDATE* bitmap_update = update_read_bitmap_update(update, s);
969 WLog_ERR(TAG,
"UPDATE_TYPE_BITMAP - update_read_bitmap_update() failed");
973 up->stats.base[RDP_STATS_BITMAP_UPDATE]++;
974 rc = IFCALLRESULT(FALSE, update->BitmapUpdate, context, bitmap_update);
975 free_bitmap_update(context, bitmap_update);
979 case UPDATE_TYPE_PALETTE:
985 WLog_ERR(TAG,
"UPDATE_TYPE_PALETTE - update_read_palette() failed");
989 up->stats.base[RDP_STATS_PALETTE]++;
990 rc = IFCALLRESULT(FALSE, update->Palette, context, palette_update);
991 free_palette_update(context, palette_update);
995 case UPDATE_TYPE_SYNCHRONIZE:
996 if (!update_read_synchronize(update, s))
998 up->stats.base[RDP_STATS_SYNC]++;
999 rc = IFCALLRESULT(TRUE, update->Synchronize, context);
1008 if (!update_end_paint(update))
1013 WLog_ERR(TAG,
"UPDATE_TYPE %s [%" PRIu16
"] failed", update_type_to_string(updateType),
1021void update_reset_state(rdpUpdate* update)
1026 WINPR_ASSERT(primary);
1028 ZeroMemory(&primary->order_info,
sizeof(
ORDER_INFO));
1041 free(primary->polyline.points);
1050 free(primary->fast_glyph.glyphData.aj);
1053 free(primary->polygon_sc.points);
1056 free(primary->polygon_cb.points);
1061 primary->order_info.orderType = ORDER_TYPE_PATBLT;
1063 if (!up->initialState)
1066 WINPR_ASSERT(altsec);
1068 altsec->switch_surface.bitmapId = SCREEN_BITMAP_SURFACE;
1069 if (altsec->common.SwitchSurface)
1071 if (!altsec->common.SwitchSurface(update->context, &(altsec->switch_surface)))
1072 WLog_Print(up->log, WLOG_WARN,
"altsec->common.SwitchSurface failed");
1077BOOL update_post_connect(rdpUpdate* update)
1082 WINPR_ASSERT(update->context);
1083 WINPR_ASSERT(update->context->settings);
1084 up->asynchronous = update->context->settings->AsyncUpdate;
1086 if (up->asynchronous)
1088#if defined(FORCE_ASYNC_UPDATE_OFF)
1089 WLog_WARN(TAG,
"AsyncUpdate requested, but forced deactivated");
1090 WLog_WARN(TAG,
"see https://github.com/FreeRDP/FreeRDP/issues/10153 for details");
1092 if (!(up->proxy = update_message_proxy_new(update)))
1097 altsec->switch_surface.bitmapId = SCREEN_BITMAP_SURFACE;
1098 const BOOL rc = IFCALLRESULT(TRUE, update->altsec->SwitchSurface, update->context,
1099 &(altsec->switch_surface));
1100 up->initialState = FALSE;
1104void update_post_disconnect(rdpUpdate* update)
1108 WINPR_ASSERT(update->context);
1109 WINPR_ASSERT(update->context->settings);
1111 up->asynchronous = update->context->settings->AsyncUpdate;
1113 if (up->asynchronous)
1115#if !defined(FORCE_ASYNC_UPDATE_OFF)
1116 update_message_proxy_free(up->proxy);
1120 up->initialState = TRUE;
1123static BOOL s_update_begin_paint(rdpContext* context)
1126 WINPR_ASSERT(context);
1131 if (!update_end_paint(&update->common))
1135 WINPR_ASSERT(context->rdp);
1136 s = fastpath_update_pdu_init_new(context->rdp->fastpath);
1141 Stream_SealLength(s);
1142 Stream_GetLength(s, update->offsetOrders);
1144 update->combineUpdates = TRUE;
1145 update->numberOrders = 0;
1150static BOOL s_update_end_paint(rdpContext* context)
1154 WINPR_ASSERT(context);
1161 update->us =
nullptr;
1163 Stream_SealLength(s);
1164 if (!Stream_SetPosition(s, update->offsetOrders))
1166 Stream_Write_UINT16(s, update->numberOrders);
1167 if (!Stream_SetPosition(s, Stream_Length(s)))
1170 if (update->numberOrders > 0)
1172 WLog_DBG(TAG,
"sending %" PRIu16
" orders", update->numberOrders);
1173 if (!fastpath_send_update_pdu(context->rdp->fastpath, FASTPATH_UPDATETYPE_ORDERS, s, FALSE))
1177 update->combineUpdates = FALSE;
1178 update->numberOrders = 0;
1179 update->offsetOrders = 0;
1183 Stream_Free(s, TRUE);
1187static BOOL update_flush(rdpContext* context)
1191 WINPR_ASSERT(context);
1192 update = update_cast(context->update);
1194 if (update->numberOrders > 0)
1196 if (!update_end_paint(&update->common))
1199 if (!update_begin_paint(&update->common))
1205static BOOL update_force_flush(rdpContext* context)
1207 return update_flush(context);
1210static BOOL update_check_flush(rdpContext* context,
size_t size)
1212 WINPR_ASSERT(context);
1219 if (!update_begin_paint(&update->common))
1224 if (Stream_GetPosition(s) + size + 64 >= FASTPATH_MAX_PACKET_SIZE)
1227 if (!update_flush(context))
1234static BOOL update_set_bounds(rdpContext* context,
const rdpBounds* bounds)
1238 WINPR_ASSERT(context);
1240 update = update_cast(context->update);
1242 CopyMemory(&update->previousBounds, &update->currentBounds,
sizeof(rdpBounds));
1245 ZeroMemory(&update->currentBounds,
sizeof(rdpBounds));
1247 CopyMemory(&update->currentBounds, bounds,
sizeof(rdpBounds));
1252static BOOL update_bounds_is_null(rdpBounds* bounds)
1254 WINPR_ASSERT(bounds);
1255 return ((bounds->left == 0) && (bounds->top == 0) && (bounds->right == 0) &&
1256 (bounds->bottom == 0));
1259static BOOL update_bounds_equals(rdpBounds* bounds1, rdpBounds* bounds2)
1261 WINPR_ASSERT(bounds1);
1262 WINPR_ASSERT(bounds2);
1264 return ((bounds1->left == bounds2->left) && (bounds1->top == bounds2->top) &&
1265 (bounds1->right == bounds2->right) && (bounds1->bottom == bounds2->bottom));
1268static size_t update_prepare_bounds(rdpContext* context,
ORDER_INFO* orderInfo)
1273 WINPR_ASSERT(context);
1274 WINPR_ASSERT(orderInfo);
1276 update = update_cast(context->update);
1278 orderInfo->boundsFlags = 0;
1280 if (update_bounds_is_null(&update->currentBounds))
1283 orderInfo->controlFlags |= ORDER_BOUNDS;
1285 if (update_bounds_equals(&update->previousBounds, &update->currentBounds))
1287 orderInfo->controlFlags |= ORDER_ZERO_BOUNDS_DELTAS;
1294 if (update->previousBounds.left != update->currentBounds.left)
1296 orderInfo->bounds.left = update->currentBounds.left;
1297 orderInfo->boundsFlags |= BOUND_LEFT;
1301 if (update->previousBounds.top != update->currentBounds.top)
1303 orderInfo->bounds.top = update->currentBounds.top;
1304 orderInfo->boundsFlags |= BOUND_TOP;
1308 if (update->previousBounds.right != update->currentBounds.right)
1310 orderInfo->bounds.right = update->currentBounds.right;
1311 orderInfo->boundsFlags |= BOUND_RIGHT;
1315 if (update->previousBounds.bottom != update->currentBounds.bottom)
1317 orderInfo->bounds.bottom = update->currentBounds.bottom;
1318 orderInfo->boundsFlags |= BOUND_BOTTOM;
1326static size_t update_prepare_order_info(rdpContext* context,
ORDER_INFO* orderInfo,
1329 WINPR_ASSERT(context);
1330 WINPR_ASSERT(orderInfo);
1332 orderInfo->fieldFlags = 0;
1333 orderInfo->orderType = orderType;
1334 orderInfo->controlFlags = ORDER_STANDARD;
1335 orderInfo->controlFlags |= ORDER_TYPE_CHANGE;
1337 length += get_primary_drawing_order_field_bytes(orderInfo->orderType,
nullptr);
1338 length += update_prepare_bounds(context, orderInfo);
1343static int update_write_order_info(rdpContext* context,
wStream* s,
const ORDER_INFO* orderInfo,
1346 WINPR_UNUSED(context);
1347 WINPR_ASSERT(orderInfo);
1348 WINPR_ASSERT(orderInfo->controlFlags <= UINT8_MAX);
1350 const size_t position = Stream_GetPosition(s);
1351 const UINT8 controlFlags = (UINT8)orderInfo->controlFlags;
1353 if (!Stream_SetPosition(s, offset))
1356 Stream_Write_UINT8(s, controlFlags);
1358 if (orderInfo->controlFlags & ORDER_TYPE_CHANGE)
1360 s, WINPR_ASSERTING_INT_CAST(uint8_t, orderInfo->orderType));
1362 if (!update_write_field_flags(
1363 s, orderInfo->fieldFlags, controlFlags,
1364 get_primary_drawing_order_field_bytes(orderInfo->orderType,
nullptr)))
1366 if (!update_write_bounds(s, orderInfo))
1368 if (!Stream_SetPosition(s, position))
1376 WINPR_ASSERT(areas || (count == 0));
1378 Stream_Write_UINT8(s, count);
1381 for (BYTE i = 0; i < count; i++)
1383 Stream_Write_UINT16(s, areas[i].left);
1384 Stream_Write_UINT16(s, areas[i].top);
1385 Stream_Write_UINT16(s, areas[i].right);
1386 Stream_Write_UINT16(s, areas[i].bottom);
1390static BOOL update_send_refresh_rect(rdpContext* context, BYTE count,
const RECTANGLE_16* areas)
1392 WINPR_ASSERT(context);
1393 rdpRdp* rdp = context->rdp;
1395 WINPR_ASSERT(rdp->settings);
1396 if (rdp->settings->RefreshRect)
1398 UINT16 sec_flags = 0;
1399 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
1404 update_write_refresh_rect(s, count, areas);
1405 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_REFRESH_RECT, rdp->mcs->userId, sec_flags);
1415 Stream_Write_UINT8(s, allow);
1422 Stream_Write_UINT16(s, area->left);
1423 Stream_Write_UINT16(s, area->top);
1424 Stream_Write_UINT16(s, area->right);
1425 Stream_Write_UINT16(s, area->bottom);
1429static BOOL update_send_suppress_output(rdpContext* context, BYTE allow,
const RECTANGLE_16* area)
1431 WINPR_ASSERT(context);
1432 rdpRdp* rdp = context->rdp;
1435 WINPR_ASSERT(rdp->settings);
1436 if (rdp->settings->SuppressOutput)
1438 UINT16 sec_flags = 0;
1439 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
1444 update_write_suppress_output(s, allow, area);
1445 WINPR_ASSERT(rdp->mcs);
1446 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SUPPRESS_OUTPUT, rdp->mcs->userId,
1453static BOOL update_send_surface_command(rdpContext* context,
wStream* s)
1456 WINPR_ASSERT(context);
1457 rdpRdp* rdp = context->rdp;
1461 update = fastpath_update_pdu_init(rdp->fastpath);
1466 if (!Stream_EnsureRemainingCapacity(update, Stream_GetPosition(s)))
1472 Stream_Write(update, Stream_Buffer(s), Stream_GetPosition(s));
1473 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, update, FALSE);
1475 Stream_Release(update);
1479static BOOL update_send_surface_bits(rdpContext* context,
1483 WINPR_ASSERT(context);
1484 rdpRdp* rdp = context->rdp;
1487 WINPR_ASSERT(surfaceBitsCommand);
1490 if (!update_force_flush(context))
1492 s = fastpath_update_pdu_init(rdp->fastpath);
1497 if (!update_write_surfcmd_surface_bits(s, surfaceBitsCommand))
1500 if (!fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s,
1501 surfaceBitsCommand->skipCompression))
1504 ret = update_force_flush(context);
1510static BOOL update_send_surface_frame_marker(rdpContext* context,
1514 WINPR_ASSERT(context);
1515 rdpRdp* rdp = context->rdp;
1517 if (!update_force_flush(context))
1521 s = fastpath_update_pdu_init(rdp->fastpath);
1526 WINPR_ASSERT(surfaceFrameMarker->frameAction <= UINT16_MAX);
1527 if (!update_write_surfcmd_frame_marker(s, (UINT16)surfaceFrameMarker->frameAction,
1528 surfaceFrameMarker->frameId) ||
1529 !fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s, FALSE))
1532 ret = update_force_flush(context);
1538static BOOL update_send_surface_frame_bits(rdpContext* context,
const SURFACE_BITS_COMMAND* cmd,
1539 BOOL first, BOOL last, UINT32 frameId)
1543 WINPR_ASSERT(context);
1544 rdpRdp* rdp = context->rdp;
1547 if (!update_force_flush(context))
1551 s = fastpath_update_pdu_init(rdp->fastpath);
1558 if (!update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_BEGIN, frameId))
1562 if (!update_write_surfcmd_surface_bits(s, cmd))
1567 if (!update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_END, frameId))
1571 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s,
1572 cmd->skipCompression);
1576 ret = update_force_flush(context);
1582static BOOL update_send_frame_acknowledge(rdpContext* context, UINT32 frameId)
1584 WINPR_ASSERT(context);
1585 rdpRdp* rdp = context->rdp;
1588 WINPR_ASSERT(rdp->settings);
1589 WINPR_ASSERT(rdp->settings->ReceivedCapabilities);
1590 WINPR_ASSERT(rdp->settings->ReceivedCapabilitiesSize > CAPSET_TYPE_FRAME_ACKNOWLEDGE);
1591 if (rdp->settings->ReceivedCapabilities[CAPSET_TYPE_FRAME_ACKNOWLEDGE])
1593 UINT16 sec_flags = 0;
1594 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
1599 Stream_Write_UINT32(s, frameId);
1600 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FRAME_ACKNOWLEDGE, rdp->mcs->userId,
1607static BOOL update_send_synchronize(rdpContext* context)
1610 WINPR_ASSERT(context);
1611 rdpRdp* rdp = context->rdp;
1615 s = fastpath_update_pdu_init(rdp->fastpath);
1621 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SYNCHRONIZE, s, FALSE);
1626static BOOL update_send_desktop_resize(rdpContext* context)
1628 WINPR_ASSERT(context);
1629 return rdp_server_reactivate(context->rdp);
1632static BOOL update_send_bitmap_update(rdpContext* context,
const BITMAP_UPDATE* bitmapUpdate)
1635 WINPR_ASSERT(context);
1636 rdpRdp* rdp = context->rdp;
1637 rdpUpdate* update = context->update;
1640 if (!update_force_flush(context))
1644 s = fastpath_update_pdu_init(rdp->fastpath);
1649 if (!update_write_bitmap_update(update, s, bitmapUpdate) ||
1650 !fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_BITMAP, s,
1651 bitmapUpdate->skipCompression))
1657 ret = update_force_flush(context);
1664static BOOL update_send_play_sound(rdpContext* context,
const PLAY_SOUND_UPDATE* play_sound)
1666 UINT16 sec_flags = 0;
1668 WINPR_ASSERT(context);
1669 rdpRdp* rdp = context->rdp;
1672 WINPR_ASSERT(rdp->settings);
1673 WINPR_ASSERT(play_sound);
1674 WINPR_ASSERT(rdp->settings->ReceivedCapabilities);
1675 WINPR_ASSERT(rdp->settings->ReceivedCapabilitiesSize > CAPSET_TYPE_SOUND);
1676 if (!rdp->settings->ReceivedCapabilities[CAPSET_TYPE_SOUND])
1681 s = rdp_data_pdu_init(rdp, &sec_flags);
1686 Stream_Write_UINT32(s, play_sound->duration);
1687 Stream_Write_UINT32(s, play_sound->frequency);
1688 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_PLAY_SOUND, rdp->mcs->userId, sec_flags);
1695static BOOL update_send_dstblt(rdpContext* context,
const DSTBLT_ORDER* dstblt)
1699 WINPR_ASSERT(context);
1700 WINPR_ASSERT(dstblt);
1704 const size_t headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_DSTBLT);
1705 const size_t inf = update_approximate_dstblt_order(&orderInfo, dstblt);
1706 if (!update_check_flush(context, headerLength + inf))
1714 const size_t offset = Stream_GetPosition(s);
1716 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1719 Stream_Seek(s, headerLength);
1721 if (!update_write_dstblt_order(s, &orderInfo, dstblt))
1724 if (update_write_order_info(context, s, &orderInfo, offset) < 0)
1726 update->numberOrders++;
1730static BOOL update_send_patblt(rdpContext* context,
PATBLT_ORDER* patblt)
1735 WINPR_ASSERT(context);
1736 WINPR_ASSERT(patblt);
1739 const size_t headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_PATBLT);
1740 if (!update_check_flush(context,
1741 headerLength + update_approximate_patblt_order(&orderInfo, patblt)))
1749 offset = Stream_GetPosition(s);
1751 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1754 Stream_Seek(s, headerLength);
1755 if (!update_write_patblt_order(s, &orderInfo, patblt))
1757 if (update_write_order_info(context, s, &orderInfo, offset) < 0)
1759 update->numberOrders++;
1763static BOOL update_send_scrblt(rdpContext* context,
const SCRBLT_ORDER* scrblt)
1767 WINPR_ASSERT(context);
1768 WINPR_ASSERT(scrblt);
1771 const size_t headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_SCRBLT);
1772 const size_t inf = update_approximate_scrblt_order(&orderInfo, scrblt);
1773 if (!update_check_flush(context, headerLength + inf))
1781 const size_t offset = Stream_GetPosition(s);
1783 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1786 Stream_Seek(s, headerLength);
1787 if (!update_write_scrblt_order(s, &orderInfo, scrblt))
1789 if (update_write_order_info(context, s, &orderInfo, offset) < 0)
1791 update->numberOrders++;
1795static BOOL update_send_opaque_rect(rdpContext* context,
const OPAQUE_RECT_ORDER* opaque_rect)
1800 WINPR_ASSERT(context);
1801 WINPR_ASSERT(opaque_rect);
1804 const size_t headerLength =
1805 update_prepare_order_info(context, &orderInfo, ORDER_TYPE_OPAQUE_RECT);
1806 if (!update_check_flush(
1807 context, headerLength + update_approximate_opaque_rect_order(&orderInfo, opaque_rect)))
1815 offset = Stream_GetPosition(s);
1817 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1820 Stream_Seek(s, headerLength);
1821 if (!update_write_opaque_rect_order(s, &orderInfo, opaque_rect))
1823 if (update_write_order_info(context, s, &orderInfo, offset) < 0)
1825 update->numberOrders++;
1829static BOOL update_send_line_to(rdpContext* context,
const LINE_TO_ORDER* line_to)
1833 WINPR_ASSERT(context);
1834 WINPR_ASSERT(line_to);
1836 const size_t headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_LINE_TO);
1837 const size_t inf = update_approximate_line_to_order(&orderInfo, line_to);
1838 if (!update_check_flush(context, headerLength + inf))
1846 const size_t offset = Stream_GetPosition(s);
1848 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1851 Stream_Seek(s, headerLength);
1852 if (!update_write_line_to_order(s, &orderInfo, line_to))
1854 if (update_write_order_info(context, s, &orderInfo, offset) < 0)
1856 update->numberOrders++;
1860static BOOL update_send_memblt(rdpContext* context,
MEMBLT_ORDER* memblt)
1865 WINPR_ASSERT(context);
1866 WINPR_ASSERT(memblt);
1868 const size_t headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_MEMBLT);
1869 if (!update_check_flush(context,
1870 headerLength + update_approximate_memblt_order(&orderInfo, memblt)))
1878 offset = Stream_GetPosition(s);
1880 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1883 Stream_Seek(s, headerLength);
1884 if (!update_write_memblt_order(s, &orderInfo, memblt))
1886 if (update_write_order_info(context, s, &orderInfo, offset) < 0)
1888 update->numberOrders++;
1892static BOOL update_send_glyph_index(rdpContext* context,
GLYPH_INDEX_ORDER* glyph_index)
1896 WINPR_ASSERT(context);
1897 WINPR_ASSERT(glyph_index);
1900 const size_t headerLength =
1901 update_prepare_order_info(context, &orderInfo, ORDER_TYPE_GLYPH_INDEX);
1902 const size_t inf = update_approximate_glyph_index_order(&orderInfo, glyph_index);
1903 if (!update_check_flush(context, headerLength + inf))
1911 const size_t offset = Stream_GetPosition(s);
1913 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1916 Stream_Seek(s, headerLength);
1917 if (!update_write_glyph_index_order(s, &orderInfo, glyph_index))
1919 if (update_write_order_info(context, s, &orderInfo, offset) < 0)
1921 update->numberOrders++;
1929static BOOL update_send_cache_bitmap(rdpContext* context,
const CACHE_BITMAP_ORDER* cache_bitmap)
1931 const size_t headerLength = 6;
1932 UINT16 extraFlags = 0;
1934 WINPR_ASSERT(context);
1935 WINPR_ASSERT(cache_bitmap);
1938 const BYTE orderType = cache_bitmap->compressed ? ORDER_TYPE_CACHE_BITMAP_COMPRESSED
1939 : ORDER_TYPE_BITMAP_UNCOMPRESSED;
1941 update_approximate_cache_bitmap_order(cache_bitmap, cache_bitmap->compressed, &extraFlags);
1942 if (!update_check_flush(context, headerLength + inf))
1950 const size_t bm = Stream_GetPosition(s);
1952 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1955 Stream_Seek(s, headerLength);
1957 if (!update_write_cache_bitmap_order(s, cache_bitmap, cache_bitmap->compressed, &extraFlags))
1960 const size_t em = Stream_GetPosition(s);
1961 WINPR_ASSERT(em >= bm + 13);
1962 const size_t orderLength = (em - bm) - 13;
1963 WINPR_ASSERT(orderLength <= UINT16_MAX);
1965 if (!Stream_SetPosition(s, bm))
1967 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
1968 Stream_Write_UINT16(s, (UINT16)orderLength);
1969 Stream_Write_UINT16(s, extraFlags);
1970 Stream_Write_UINT8(s, orderType);
1971 update->numberOrders++;
1972 return Stream_SetPosition(s, em);
1977 const size_t headerLength = 6;
1978 UINT16 extraFlags = 0;
1980 WINPR_ASSERT(context);
1981 WINPR_ASSERT(cache_bitmap_v2);
1984 const BYTE orderType = cache_bitmap_v2->compressed ? ORDER_TYPE_BITMAP_COMPRESSED_V2
1985 : ORDER_TYPE_BITMAP_UNCOMPRESSED_V2;
1987 if (context->settings->NoBitmapCompressionHeader)
1988 cache_bitmap_v2->flags |= CBR2_NO_BITMAP_COMPRESSION_HDR;
1990 if (!update_check_flush(
1991 context, headerLength + update_approximate_cache_bitmap_v2_order(
1992 cache_bitmap_v2, cache_bitmap_v2->compressed, &extraFlags)))
2000 const size_t bm = Stream_GetPosition(s);
2002 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2005 Stream_Seek(s, headerLength);
2007 if (!update_write_cache_bitmap_v2_order(s, cache_bitmap_v2, cache_bitmap_v2->compressed,
2011 const size_t em = Stream_GetPosition(s);
2012 WINPR_ASSERT(em >= bm + 13);
2013 const size_t orderLength = (em - bm) - 13;
2014 WINPR_ASSERT(orderLength <= UINT16_MAX);
2016 if (!Stream_SetPosition(s, bm))
2018 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
2019 Stream_Write_UINT16(s, (UINT16)orderLength);
2020 Stream_Write_UINT16(s, extraFlags);
2021 Stream_Write_UINT8(s, orderType);
2022 update->numberOrders++;
2023 return Stream_SetPosition(s, em);
2028 const size_t headerLength = 6;
2029 UINT16 extraFlags = 0;
2031 WINPR_ASSERT(context);
2032 WINPR_ASSERT(cache_bitmap_v3);
2035 const BYTE orderType = ORDER_TYPE_BITMAP_COMPRESSED_V3;
2036 if (!update_check_flush(context, headerLength + update_approximate_cache_bitmap_v3_order(
2037 cache_bitmap_v3, &extraFlags)))
2045 const size_t bm = Stream_GetPosition(s);
2047 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2050 Stream_Seek(s, headerLength);
2052 if (!update_write_cache_bitmap_v3_order(s, cache_bitmap_v3, &extraFlags))
2055 const size_t em = Stream_GetPosition(s);
2056 WINPR_ASSERT(em >= bm + 13);
2057 const size_t orderLength = (em - bm) - 13;
2058 WINPR_ASSERT(orderLength <= UINT16_MAX);
2060 if (!Stream_SetPosition(s, bm))
2062 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
2063 Stream_Write_UINT16(s, (UINT16)orderLength);
2064 Stream_Write_UINT16(s, extraFlags);
2065 Stream_Write_UINT8(s, orderType);
2066 update->numberOrders++;
2067 return Stream_SetPosition(s, em);
2070static BOOL update_send_cache_color_table(rdpContext* context,
2074 size_t headerLength = 6;
2076 WINPR_ASSERT(context);
2077 WINPR_ASSERT(cache_color_table);
2080 const size_t inf = update_approximate_cache_color_table_order(cache_color_table, &flags);
2081 if (!update_check_flush(context, headerLength + inf))
2089 const size_t bm = Stream_GetPosition(s);
2091 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2094 Stream_Seek(s, headerLength);
2096 if (!update_write_cache_color_table_order(s, cache_color_table, &flags))
2099 const size_t em = Stream_GetPosition(s);
2100 WINPR_ASSERT(em >= bm + 13);
2101 const size_t orderLength = (em - bm) - 13;
2102 WINPR_ASSERT(orderLength <= UINT16_MAX);
2103 if (!Stream_SetPosition(s, bm))
2105 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
2106 Stream_Write_UINT16(s, (UINT16)orderLength);
2107 Stream_Write_UINT16(s, flags);
2108 Stream_Write_UINT8(s, ORDER_TYPE_CACHE_COLOR_TABLE);
2109 update->numberOrders++;
2110 return Stream_SetPosition(s, em);
2113static BOOL update_send_cache_glyph(rdpContext* context,
const CACHE_GLYPH_ORDER* cache_glyph)
2116 const size_t headerLength = 6;
2118 WINPR_ASSERT(context);
2119 WINPR_ASSERT(cache_glyph);
2122 const size_t inf = update_approximate_cache_glyph_order(cache_glyph, &flags);
2123 if (!update_check_flush(context, headerLength + inf))
2131 const size_t bm = Stream_GetPosition(s);
2133 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2136 Stream_Seek(s, headerLength);
2138 if (!update_write_cache_glyph_order(s, cache_glyph, &flags))
2141 const size_t em = Stream_GetPosition(s);
2142 WINPR_ASSERT(em >= bm + 13);
2143 const size_t orderLength = (em - bm) - 13;
2144 WINPR_ASSERT(orderLength <= UINT16_MAX);
2145 if (!Stream_SetPosition(s, bm))
2147 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
2148 Stream_Write_UINT16(s, (UINT16)orderLength);
2149 Stream_Write_UINT16(s, flags);
2150 Stream_Write_UINT8(s, ORDER_TYPE_CACHE_GLYPH);
2151 update->numberOrders++;
2152 return Stream_SetPosition(s, em);
2155static BOOL update_send_cache_glyph_v2(rdpContext* context,
2159 const size_t headerLength = 6;
2161 WINPR_ASSERT(context);
2162 WINPR_ASSERT(cache_glyph_v2);
2165 const size_t inf = update_approximate_cache_glyph_v2_order(cache_glyph_v2, &flags);
2166 if (!update_check_flush(context, headerLength + inf))
2174 const size_t bm = Stream_GetPosition(s);
2176 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2179 Stream_Seek(s, headerLength);
2181 if (!update_write_cache_glyph_v2_order(s, cache_glyph_v2, &flags))
2184 const size_t em = Stream_GetPosition(s);
2185 WINPR_ASSERT(em >= bm + 13);
2186 const size_t orderLength = (em - bm) - 13;
2187 WINPR_ASSERT(orderLength <= UINT16_MAX);
2188 if (!Stream_SetPosition(s, bm))
2190 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
2191 Stream_Write_UINT16(s, (UINT16)orderLength);
2192 Stream_Write_UINT16(s, flags);
2193 Stream_Write_UINT8(s, ORDER_TYPE_CACHE_GLYPH);
2194 update->numberOrders++;
2195 return Stream_SetPosition(s, em);
2198static BOOL update_send_cache_brush(rdpContext* context,
const CACHE_BRUSH_ORDER* cache_brush)
2201 const size_t headerLength = 6;
2203 WINPR_ASSERT(context);
2204 WINPR_ASSERT(cache_brush);
2207 const size_t inf = update_approximate_cache_brush_order(cache_brush, &flags);
2208 if (!update_check_flush(context, headerLength + inf))
2216 const size_t bm = Stream_GetPosition(s);
2218 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2221 Stream_Seek(s, headerLength);
2223 if (!update_write_cache_brush_order(s, cache_brush, &flags))
2226 const size_t em = Stream_GetPosition(s);
2230 const size_t orderLength = (em - bm) - 13;
2231 WINPR_ASSERT(orderLength <= UINT16_MAX);
2232 if (!Stream_SetPosition(s, bm))
2234 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
2235 Stream_Write_UINT16(s, (UINT16)orderLength);
2236 Stream_Write_UINT16(s, flags);
2237 Stream_Write_UINT8(s, ORDER_TYPE_CACHE_BRUSH);
2238 update->numberOrders++;
2239 return Stream_SetPosition(s, em);
2246static BOOL update_send_create_offscreen_bitmap_order(
2249 WINPR_ASSERT(context);
2250 WINPR_ASSERT(create_offscreen_bitmap);
2253 const size_t headerLength = 1;
2254 const size_t orderType = ORDER_TYPE_CREATE_OFFSCREEN_BITMAP;
2255 const size_t controlFlags = ORDER_SECONDARY | (orderType << 2);
2256 const size_t inf = update_approximate_create_offscreen_bitmap_order(create_offscreen_bitmap);
2257 if (!update_check_flush(context, headerLength + inf))
2265 const size_t bm = Stream_GetPosition(s);
2267 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2270 Stream_Seek(s, headerLength);
2272 if (!update_write_create_offscreen_bitmap_order(s, create_offscreen_bitmap))
2275 const size_t em = Stream_GetPosition(s);
2276 if (!Stream_SetPosition(s, bm))
2278 Stream_Write_UINT8(s,
2279 WINPR_ASSERTING_INT_CAST(uint8_t, controlFlags));
2280 update->numberOrders++;
2281 return Stream_SetPosition(s, em);
2284static BOOL update_send_switch_surface_order(rdpContext* context,
2287 WINPR_ASSERT(context);
2288 WINPR_ASSERT(switch_surface);
2291 const size_t headerLength = 1;
2292 const size_t orderType = ORDER_TYPE_SWITCH_SURFACE;
2293 const size_t controlFlags = ORDER_SECONDARY | (orderType << 2);
2294 const size_t inf = update_approximate_switch_surface_order(switch_surface);
2295 if (!update_check_flush(context, headerLength + inf))
2303 const size_t bm = Stream_GetPosition(s);
2305 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2308 Stream_Seek(s, headerLength);
2310 if (!update_write_switch_surface_order(s, switch_surface))
2313 const size_t em = Stream_GetPosition(s);
2314 if (!Stream_SetPosition(s, bm))
2316 Stream_Write_UINT8(s,
2317 WINPR_ASSERTING_INT_CAST(uint8_t, controlFlags));
2318 update->numberOrders++;
2319 return Stream_SetPosition(s, em);
2322static BOOL update_send_pointer_system(rdpContext* context,
2326 BYTE updateCode = 0;
2328 WINPR_ASSERT(context);
2329 rdpRdp* rdp = context->rdp;
2333 s = fastpath_update_pdu_init(rdp->fastpath);
2338 if (pointer_system->type == SYSPTR_NULL)
2339 updateCode = FASTPATH_UPDATETYPE_PTR_NULL;
2341 updateCode = FASTPATH_UPDATETYPE_PTR_DEFAULT;
2343 ret = fastpath_send_update_pdu(rdp->fastpath, updateCode, s, FALSE);
2348static BOOL update_send_pointer_position(rdpContext* context,
2352 WINPR_ASSERT(context);
2353 rdpRdp* rdp = context->rdp;
2357 s = fastpath_update_pdu_init(rdp->fastpath);
2362 if (!Stream_EnsureRemainingCapacity(s, 16))
2365 Stream_Write_UINT16(
2366 s, WINPR_ASSERTING_INT_CAST(uint16_t, pointerPosition->xPos));
2367 Stream_Write_UINT16(
2368 s, WINPR_ASSERTING_INT_CAST(uint16_t, pointerPosition->yPos));
2369 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_PTR_POSITION, s, FALSE);
2377 WINPR_ASSERT(pointer_color);
2378 if (!Stream_EnsureRemainingCapacity(s, 32 + pointer_color->lengthAndMask +
2379 pointer_color->lengthXorMask))
2382 Stream_Write_UINT16(s, pointer_color->cacheIndex);
2383 Stream_Write_UINT16(s, pointer_color->hotSpotX);
2384 Stream_Write_UINT16(s, pointer_color->hotSpotY);
2385 Stream_Write_UINT16(s, pointer_color->width);
2386 Stream_Write_UINT16(s, pointer_color->height);
2387 Stream_Write_UINT16(s, pointer_color->lengthAndMask);
2388 Stream_Write_UINT16(s, pointer_color->lengthXorMask);
2390 if (pointer_color->lengthXorMask > 0)
2391 Stream_Write(s, pointer_color->xorMaskData, pointer_color->lengthXorMask);
2393 if (pointer_color->lengthAndMask > 0)
2394 Stream_Write(s, pointer_color->andMaskData, pointer_color->lengthAndMask);
2396 Stream_Write_UINT8(s, 0);
2400static BOOL update_send_pointer_color(rdpContext* context,
2405 WINPR_ASSERT(context);
2406 rdpRdp* rdp = context->rdp;
2410 WINPR_ASSERT(pointer_color);
2411 s = fastpath_update_pdu_init(rdp->fastpath);
2416 if (!update_write_pointer_color(s, pointer_color))
2419 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_COLOR, s, FALSE);
2427 WINPR_ASSERT(pointer);
2429 if (!Stream_EnsureRemainingCapacity(s, 32 + pointer->lengthAndMask + pointer->lengthXorMask))
2432 Stream_Write_UINT16(s, pointer->xorBpp);
2433 Stream_Write_UINT16(s, pointer->cacheIndex);
2434 Stream_Write_UINT16(s, pointer->hotSpotX);
2435 Stream_Write_UINT16(s, pointer->hotSpotY);
2436 Stream_Write_UINT16(s, pointer->width);
2437 Stream_Write_UINT16(s, pointer->height);
2438 Stream_Write_UINT32(s, pointer->lengthAndMask);
2439 Stream_Write_UINT32(s, pointer->lengthXorMask);
2440 Stream_Write(s, pointer->xorMaskData, pointer->lengthXorMask);
2441 Stream_Write(s, pointer->andMaskData, pointer->lengthAndMask);
2442 Stream_Write_UINT8(s, 0);
2449 WINPR_ASSERT(context);
2450 rdpRdp* rdp = context->rdp;
2454 WINPR_ASSERT(pointer);
2455 s = fastpath_update_pdu_init(rdp->fastpath);
2460 if (!update_write_pointer_large(s, pointer))
2463 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_LARGE_POINTER, s, FALSE);
2469static BOOL update_send_pointer_new(rdpContext* context,
const POINTER_NEW_UPDATE* pointer_new)
2473 WINPR_ASSERT(context);
2474 rdpRdp* rdp = context->rdp;
2478 WINPR_ASSERT(pointer_new);
2479 s = fastpath_update_pdu_init(rdp->fastpath);
2484 if (!Stream_EnsureRemainingCapacity(s, 16))
2487 Stream_Write_UINT16(
2488 s, WINPR_ASSERTING_INT_CAST(uint16_t, pointer_new->xorBpp));
2489 update_write_pointer_color(s, &pointer_new->colorPtrAttr);
2490 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_POINTER, s, FALSE);
2496static BOOL update_send_pointer_cached(rdpContext* context,
2501 WINPR_ASSERT(context);
2502 rdpRdp* rdp = context->rdp;
2506 WINPR_ASSERT(pointer_cached);
2507 s = fastpath_update_pdu_init(rdp->fastpath);
2512 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(
2513 uint16_t, pointer_cached->cacheIndex));
2514 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_CACHED, s, FALSE);
2519BOOL update_read_refresh_rect(rdpUpdate* update,
wStream* s)
2521 BYTE numberOfAreas = 0;
2525 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
2528 Stream_Read_UINT8(s, numberOfAreas);
2531 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, numberOfAreas, 8ull))
2534 for (BYTE index = 0; index < numberOfAreas; index++)
2538 Stream_Read_UINT16(s, area->left);
2539 Stream_Read_UINT16(s, area->top);
2540 Stream_Read_UINT16(s, area->right);
2541 Stream_Read_UINT16(s, area->bottom);
2544 WINPR_ASSERT(update->context);
2545 WINPR_ASSERT(update->context->settings);
2546 if (update->context->settings->RefreshRect)
2547 IFCALL(update->RefreshRect, update->context, numberOfAreas, areas);
2549 WLog_Print(up->log, WLOG_WARN,
"ignoring refresh rect request from client");
2554BOOL update_read_suppress_output(rdpUpdate* update,
wStream* s)
2559 BYTE allowDisplayUpdates = 0;
2564 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
2567 Stream_Read_UINT8(s, allowDisplayUpdates);
2570 if (allowDisplayUpdates > 0)
2572 if (!Stream_CheckAndLogRequiredLength(TAG, s,
sizeof(
RECTANGLE_16)))
2575 Stream_Read_UINT16(s, rect.left);
2576 Stream_Read_UINT16(s, rect.top);
2577 Stream_Read_UINT16(s, rect.right);
2578 Stream_Read_UINT16(s, rect.bottom);
2583 WINPR_ASSERT(update->context);
2584 WINPR_ASSERT(update->context->settings);
2585 if (update->context->settings->SuppressOutput)
2586 IFCALL(update->SuppressOutput, update->context, allowDisplayUpdates, prect);
2588 WLog_Print(up->log, WLOG_WARN,
"ignoring suppress output request from client");
2593static BOOL update_send_set_keyboard_indicators(rdpContext* context, UINT16 led_flags)
2595 UINT16 sec_flags = 0;
2598 WINPR_ASSERT(context);
2599 rdpRdp* rdp = context->rdp;
2600 s = rdp_data_pdu_init(rdp, &sec_flags);
2605 Stream_Write_UINT16(s, 0);
2606 Stream_Write_UINT16(s, led_flags);
2608 WINPR_ASSERT(rdp->mcs);
2609 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS, rdp->mcs->userId,
2613static BOOL update_send_set_keyboard_ime_status(rdpContext* context, UINT16 imeId, UINT32 imeState,
2616 UINT16 sec_flags = 0;
2619 WINPR_ASSERT(context);
2620 rdpRdp* rdp = context->rdp;
2621 s = rdp_data_pdu_init(rdp, &sec_flags);
2627 Stream_Write_UINT16(s, imeId);
2628 Stream_Write_UINT32(s, imeState);
2629 Stream_Write_UINT32(s, imeConvMode);
2631 WINPR_ASSERT(rdp->mcs);
2632 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS, rdp->mcs->userId,
2636static UINT16 update_calculate_new_or_existing_window(
const WINDOW_ORDER_INFO* orderInfo,
2639 size_t orderSize = 11;
2641 WINPR_ASSERT(orderInfo);
2642 WINPR_ASSERT(stateOrder);
2644 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OWNER) != 0)
2647 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_STYLE) != 0)
2650 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_SHOW) != 0)
2653 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE) != 0)
2654 orderSize += 2 + stateOrder->titleInfo.length;
2656 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) != 0)
2659 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) != 0)
2662 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_X) != 0)
2665 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_Y) != 0)
2668 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT) != 0)
2671 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT) != 0)
2674 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) != 0)
2677 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) != 0)
2680 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) != 0)
2683 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) != 0)
2685 const size_t len = 2ULL + stateOrder->numWindowRects *
sizeof(
RECTANGLE_16);
2689 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) != 0)
2692 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) != 0)
2695 const size_t len = 2ULL + stateOrder->numVisibilityRects *
sizeof(
RECTANGLE_16);
2699 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OVERLAY_DESCRIPTION) != 0)
2700 orderSize += 2 + stateOrder->OverlayDescription.length;
2702 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TASKBAR_BUTTON) != 0)
2705 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ENFORCE_SERVER_ZORDER) != 0)
2708 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_STATE) != 0)
2711 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_EDGE) != 0)
2714 return WINPR_ASSERTING_INT_CAST(uint16_t, orderSize);
2717static BOOL update_write_order_field_flags(UINT32 fieldFlags,
const WINDOW_STATE_ORDER* stateOrder,
2720 WINPR_ASSERT(stateOrder);
2722 if ((fieldFlags & WINDOW_ORDER_FIELD_OWNER) != 0)
2723 Stream_Write_UINT32(s, stateOrder->ownerWindowId);
2725 if ((fieldFlags & WINDOW_ORDER_FIELD_STYLE) != 0)
2727 Stream_Write_UINT32(s, stateOrder->style);
2728 Stream_Write_UINT32(s, stateOrder->extendedStyle);
2731 if ((fieldFlags & WINDOW_ORDER_FIELD_SHOW) != 0)
2733 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, stateOrder->showState));
2736 if ((fieldFlags & WINDOW_ORDER_FIELD_TITLE) != 0)
2738 Stream_Write_UINT16(s, stateOrder->titleInfo.length);
2739 Stream_Write(s, stateOrder->titleInfo.string, stateOrder->titleInfo.length);
2742 if ((fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) != 0)
2744 Stream_Write_INT32(s, stateOrder->clientOffsetX);
2745 Stream_Write_INT32(s, stateOrder->clientOffsetY);
2748 if ((fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) != 0)
2750 Stream_Write_UINT32(s, stateOrder->clientAreaWidth);
2751 Stream_Write_UINT32(s, stateOrder->clientAreaHeight);
2754 if ((fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_X) != 0)
2756 Stream_Write_UINT32(s, stateOrder->resizeMarginLeft);
2757 Stream_Write_UINT32(s, stateOrder->resizeMarginRight);
2760 if ((fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_Y) != 0)
2762 Stream_Write_UINT32(s, stateOrder->resizeMarginTop);
2763 Stream_Write_UINT32(s, stateOrder->resizeMarginBottom);
2766 if ((fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT) != 0)
2768 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, stateOrder->RPContent));
2771 if ((fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT) != 0)
2773 Stream_Write_UINT32(s, stateOrder->rootParentHandle);
2776 if ((fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) != 0)
2778 Stream_Write_INT32(s, stateOrder->windowOffsetX);
2779 Stream_Write_INT32(s, stateOrder->windowOffsetY);
2782 if ((fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) != 0)
2784 Stream_Write_INT32(s, stateOrder->windowClientDeltaX);
2785 Stream_Write_INT32(s, stateOrder->windowClientDeltaY);
2788 if ((fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) != 0)
2790 Stream_Write_UINT32(s, stateOrder->windowWidth);
2791 Stream_Write_UINT32(s, stateOrder->windowHeight);
2794 if ((fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) != 0)
2796 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, stateOrder->numWindowRects));
2797 Stream_Write(s, stateOrder->windowRects, stateOrder->numWindowRects *
sizeof(
RECTANGLE_16));
2800 if ((fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) != 0)
2802 Stream_Write_INT32(s, stateOrder->visibleOffsetX);
2803 Stream_Write_INT32(s, stateOrder->visibleOffsetY);
2806 if ((fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) != 0)
2808 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, stateOrder->numVisibilityRects));
2809 Stream_Write(s, stateOrder->visibilityRects,
2810 stateOrder->numVisibilityRects *
sizeof(
RECTANGLE_16));
2813 if ((fieldFlags & WINDOW_ORDER_FIELD_OVERLAY_DESCRIPTION) != 0)
2815 Stream_Write_UINT16(s, stateOrder->OverlayDescription.length);
2816 Stream_Write(s, stateOrder->OverlayDescription.string,
2817 stateOrder->OverlayDescription.length);
2820 if ((fieldFlags & WINDOW_ORDER_FIELD_TASKBAR_BUTTON) != 0)
2822 Stream_Write_UINT8(s, stateOrder->TaskbarButton);
2825 if ((fieldFlags & WINDOW_ORDER_FIELD_ENFORCE_SERVER_ZORDER) != 0)
2827 Stream_Write_UINT8(s, stateOrder->EnforceServerZOrder);
2830 if ((fieldFlags & WINDOW_ORDER_FIELD_APPBAR_STATE) != 0)
2832 Stream_Write_UINT8(s, stateOrder->AppBarState);
2835 if ((fieldFlags & WINDOW_ORDER_FIELD_APPBAR_EDGE) != 0)
2837 Stream_Write_UINT8(s, stateOrder->AppBarEdge);
2843static BOOL update_send_new_or_existing_window(rdpContext* context,
2847 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2848 UINT16 orderSize = update_calculate_new_or_existing_window(orderInfo, stateOrder);
2850 WINPR_ASSERT(context);
2851 WINPR_ASSERT(orderInfo);
2852 WINPR_ASSERT(stateOrder);
2856 if (!update_check_flush(context, orderSize))
2864 if (!Stream_EnsureRemainingCapacity(s, orderSize))
2867 Stream_Write_UINT8(s, controlFlags);
2868 Stream_Write_UINT16(s, orderSize);
2869 Stream_Write_UINT32(s, orderInfo->fieldFlags);
2870 Stream_Write_UINT32(s, orderInfo->windowId);
2872 if (!update_write_order_field_flags(orderInfo->fieldFlags, stateOrder, s))
2875 update->numberOrders++;
2879static BOOL update_send_window_create(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
2882 return update_send_new_or_existing_window(context, orderInfo, stateOrder);
2885static BOOL update_send_window_update(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
2888 return update_send_new_or_existing_window(context, orderInfo, stateOrder);
2892update_calculate_window_icon_order(WINPR_ATTR_UNUSED
const WINDOW_ORDER_INFO* orderInfo,
2895 UINT16 orderSize = 23;
2897 WINPR_ASSERT(iconOrder);
2898 ICON_INFO* iconInfo = iconOrder->iconInfo;
2899 WINPR_ASSERT(iconInfo);
2901 orderSize += iconInfo->cbBitsColor + iconInfo->cbBitsMask;
2903 if (iconInfo->bpp <= 8)
2904 orderSize += 2 + iconInfo->cbColorTable;
2909static BOOL update_send_window_icon(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
2912 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2914 WINPR_ASSERT(iconOrder);
2915 ICON_INFO* iconInfo = iconOrder->iconInfo;
2916 UINT16 orderSize = update_calculate_window_icon_order(orderInfo, iconOrder);
2918 WINPR_ASSERT(context);
2919 WINPR_ASSERT(orderInfo);
2920 WINPR_ASSERT(iconInfo);
2924 if (!update_check_flush(context, orderSize))
2929 if (!s || !iconInfo)
2932 if (!Stream_EnsureRemainingCapacity(s, orderSize))
2936 Stream_Write_UINT8(s, controlFlags);
2937 Stream_Write_UINT16(s, orderSize);
2938 Stream_Write_UINT32(s, orderInfo->fieldFlags);
2939 Stream_Write_UINT32(s, orderInfo->windowId);
2941 Stream_Write_UINT16(
2942 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->cacheEntry));
2943 Stream_Write_UINT8(s,
2944 WINPR_ASSERTING_INT_CAST(uint8_t, iconInfo->cacheId));
2945 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, iconInfo->bpp));
2946 Stream_Write_UINT16(s,
2947 WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->width));
2948 Stream_Write_UINT16(
2949 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->height));
2951 if (iconInfo->bpp <= 8)
2953 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(
2954 uint16_t, iconInfo->cbColorTable));
2957 Stream_Write_UINT16(
2958 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->cbBitsMask));
2959 Stream_Write_UINT16(
2960 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->cbBitsColor));
2961 Stream_Write(s, iconInfo->bitsMask, iconInfo->cbBitsMask);
2963 if (iconInfo->bpp <= 8)
2965 Stream_Write(s, iconInfo->colorTable, iconInfo->cbColorTable);
2968 Stream_Write(s, iconInfo->bitsColor, iconInfo->cbBitsColor);
2970 update->numberOrders++;
2974static BOOL update_send_window_cached_icon(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
2977 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2978 UINT16 orderSize = 14;
2980 WINPR_ASSERT(cachedIconOrder);
2983 WINPR_ASSERT(context);
2984 WINPR_ASSERT(orderInfo);
2985 WINPR_ASSERT(cachedIcon);
2989 if (!update_check_flush(context, orderSize))
2996 if (!Stream_EnsureRemainingCapacity(s, orderSize))
3000 Stream_Write_UINT8(s, controlFlags);
3001 Stream_Write_UINT16(s, orderSize);
3002 Stream_Write_UINT32(s, orderInfo->fieldFlags);
3003 Stream_Write_UINT32(s, orderInfo->windowId);
3005 Stream_Write_UINT16(
3006 s, WINPR_ASSERTING_INT_CAST(uint16_t, cachedIcon->cacheEntry));
3008 s, WINPR_ASSERTING_INT_CAST(uint8_t, cachedIcon->cacheId));
3009 update->numberOrders++;
3013static BOOL update_send_window_delete(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo)
3015 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
3016 UINT16 orderSize = 11;
3018 WINPR_ASSERT(context);
3019 WINPR_ASSERT(orderInfo);
3022 if (!update_check_flush(context, orderSize))
3030 if (!Stream_EnsureRemainingCapacity(s, orderSize))
3034 Stream_Write_UINT8(s, controlFlags);
3035 Stream_Write_UINT16(s, orderSize);
3036 Stream_Write_UINT32(s, orderInfo->fieldFlags);
3037 Stream_Write_UINT32(s, orderInfo->windowId);
3038 update->numberOrders++;
3042static UINT16 update_calculate_new_or_existing_notification_icons_order(
3045 UINT16 orderSize = 15;
3047 WINPR_ASSERT(orderInfo);
3048 WINPR_ASSERT(iconStateOrder);
3050 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_VERSION) != 0)
3053 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP) != 0)
3055 orderSize += 2 + iconStateOrder->toolTip.length;
3058 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP) != 0)
3061 orderSize += 12 + infoTip.text.length + infoTip.title.length;
3064 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_STATE) != 0)
3069 if ((orderInfo->fieldFlags & WINDOW_ORDER_ICON) != 0)
3071 ICON_INFO iconInfo = iconStateOrder->icon;
3074 if (iconInfo.bpp <= 8)
3075 orderSize += 2 + iconInfo.cbColorTable;
3077 orderSize += iconInfo.cbBitsMask + iconInfo.cbBitsColor;
3079 else if ((orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON) != 0)
3087static BOOL update_send_new_or_existing_order_icon(
const ICON_INFO* iconInfo,
wStream* s)
3089 WINPR_ASSERT(iconInfo);
3091 if (!Stream_EnsureRemainingCapacity(s, 8))
3094 Stream_Write_UINT16(
3095 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->cacheEntry));
3096 Stream_Write_UINT8(s,
3097 WINPR_ASSERTING_INT_CAST(uint8_t, iconInfo->cacheId));
3098 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, iconInfo->bpp));
3099 Stream_Write_UINT16(s,
3100 WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->width));
3101 Stream_Write_UINT16(
3102 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->height));
3104 if (iconInfo->bpp <= 8)
3106 if (!Stream_EnsureRemainingCapacity(s, 2))
3108 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(
3109 uint16_t, iconInfo->cbColorTable));
3112 if (!Stream_EnsureRemainingCapacity(s, 4ULL + iconInfo->cbBitsMask))
3114 Stream_Write_UINT16(
3115 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->cbBitsMask));
3116 Stream_Write_UINT16(
3117 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->cbBitsColor));
3118 Stream_Write(s, iconInfo->bitsMask, iconInfo->cbBitsMask);
3120 if (iconInfo->bpp <= 8)
3122 if (!Stream_EnsureRemainingCapacity(s, iconInfo->cbColorTable))
3124 Stream_Write(s, iconInfo->colorTable, iconInfo->cbColorTable);
3127 if (!Stream_EnsureRemainingCapacity(s, iconInfo->cbBitsColor))
3129 Stream_Write(s, iconInfo->bitsColor, iconInfo->cbBitsColor);
3134update_send_new_or_existing_notification_icons(rdpContext* context,
3138 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
3139 BOOL versionFieldPresent = FALSE;
3140 const UINT16 orderSize =
3141 update_calculate_new_or_existing_notification_icons_order(orderInfo, iconStateOrder);
3143 WINPR_ASSERT(context);
3144 WINPR_ASSERT(orderInfo);
3145 WINPR_ASSERT(iconStateOrder);
3148 if (!update_check_flush(context, orderSize))
3155 if (!Stream_EnsureRemainingCapacity(s, orderSize))
3159 Stream_Write_UINT8(s, controlFlags);
3160 Stream_Write_UINT16(s, orderSize);
3161 Stream_Write_UINT32(s, orderInfo->fieldFlags);
3162 Stream_Write_UINT32(s, orderInfo->windowId);
3163 Stream_Write_UINT32(s, orderInfo->notifyIconId);
3166 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_VERSION) != 0)
3168 versionFieldPresent = TRUE;
3169 Stream_Write_UINT32(s, iconStateOrder->version);
3172 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP) != 0)
3174 Stream_Write_UINT16(s, iconStateOrder->toolTip.length);
3175 Stream_Write(s, iconStateOrder->toolTip.string, iconStateOrder->toolTip.length);
3178 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP) != 0)
3183 if (versionFieldPresent && iconStateOrder->version == 0)
3186 Stream_Write_UINT32(s, infoTip.timeout);
3187 Stream_Write_UINT32(s, infoTip.flags);
3188 Stream_Write_UINT16(s, infoTip.text.length);
3189 Stream_Write(s, infoTip.text.string, infoTip.text.length);
3190 Stream_Write_UINT16(s, infoTip.title.length);
3191 Stream_Write(s, infoTip.title.string, infoTip.title.length);
3194 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_STATE) != 0)
3197 if (versionFieldPresent && iconStateOrder->version == 0)
3200 Stream_Write_UINT32(s, iconStateOrder->state);
3203 if ((orderInfo->fieldFlags & WINDOW_ORDER_ICON) != 0)
3205 const ICON_INFO* iconInfo = &iconStateOrder->icon;
3207 if (!update_send_new_or_existing_order_icon(iconInfo, s))
3210 else if ((orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON) != 0)
3213 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(
3214 uint16_t, cachedIcon.cacheEntry));
3216 s, WINPR_ASSERTING_INT_CAST(uint8_t, cachedIcon.cacheId));
3219 update->numberOrders++;
3223static BOOL update_send_notify_icon_create(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
3226 return update_send_new_or_existing_notification_icons(context, orderInfo, iconStateOrder);
3229static BOOL update_send_notify_icon_update(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
3232 return update_send_new_or_existing_notification_icons(context, orderInfo, iconStateOrder);
3235static BOOL update_send_notify_icon_delete(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo)
3237 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
3238 UINT16 orderSize = 15;
3240 WINPR_ASSERT(context);
3241 WINPR_ASSERT(orderInfo);
3244 if (!update_check_flush(context, orderSize))
3253 Stream_Write_UINT8(s, controlFlags);
3254 Stream_Write_UINT16(s, orderSize);
3255 Stream_Write_UINT32(s, orderInfo->fieldFlags);
3256 Stream_Write_UINT32(s, orderInfo->windowId);
3257 Stream_Write_UINT32(s, orderInfo->notifyIconId);
3258 update->numberOrders++;
3262static UINT16 update_calculate_monitored_desktop(
const WINDOW_ORDER_INFO* orderInfo,
3265 UINT16 orderSize = 7;
3267 WINPR_ASSERT(orderInfo);
3268 WINPR_ASSERT(monitoredDesktop);
3270 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
3275 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
3277 orderSize += 1 + (4 * monitoredDesktop->numWindowIds);
3283static BOOL update_send_monitored_desktop(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
3286 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
3287 UINT16 orderSize = update_calculate_monitored_desktop(orderInfo, monitoredDesktop);
3289 WINPR_ASSERT(context);
3290 WINPR_ASSERT(orderInfo);
3291 WINPR_ASSERT(monitoredDesktop);
3295 if (!update_check_flush(context, orderSize))
3303 Stream_Write_UINT8(s, controlFlags);
3304 Stream_Write_UINT16(s, orderSize);
3305 Stream_Write_UINT32(s, orderInfo->fieldFlags);
3307 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
3309 Stream_Write_UINT32(s, monitoredDesktop->activeWindowId);
3312 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
3315 s, WINPR_ASSERTING_INT_CAST(
3316 uint8_t, monitoredDesktop->numWindowIds));
3319 for (UINT32 i = 0; i < monitoredDesktop->numWindowIds; i++)
3321 Stream_Write_UINT32(s,
3322 WINPR_ASSERTING_INT_CAST(uint32_t, monitoredDesktop->windowIds[i]));
3326 update->numberOrders++;
3330static BOOL update_send_non_monitored_desktop(rdpContext* context,
3333 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
3334 UINT16 orderSize = 7;
3336 WINPR_ASSERT(context);
3337 WINPR_ASSERT(orderInfo);
3340 if (!update_check_flush(context, orderSize))
3348 Stream_Write_UINT8(s, controlFlags);
3349 Stream_Write_UINT16(s, orderSize);
3350 Stream_Write_UINT32(s, orderInfo->fieldFlags);
3351 update->numberOrders++;
3355void update_register_server_callbacks(rdpUpdate* update)
3357 WINPR_ASSERT(update);
3359 update->BeginPaint = s_update_begin_paint;
3360 update->EndPaint = s_update_end_paint;
3361 update->SetBounds = update_set_bounds;
3362 update->Synchronize = update_send_synchronize;
3363 update->DesktopResize = update_send_desktop_resize;
3364 update->BitmapUpdate = update_send_bitmap_update;
3365 update->SurfaceBits = update_send_surface_bits;
3366 update->SurfaceFrameMarker = update_send_surface_frame_marker;
3367 update->SurfaceCommand = update_send_surface_command;
3368 update->SurfaceFrameBits = update_send_surface_frame_bits;
3369 update->PlaySound = update_send_play_sound;
3370 update->SetKeyboardIndicators = update_send_set_keyboard_indicators;
3371 update->SetKeyboardImeStatus = update_send_set_keyboard_ime_status;
3372 update->SaveSessionInfo = rdp_send_save_session_info;
3373 update->ServerStatusInfo = rdp_send_server_status_info;
3374 update->primary->DstBlt = update_send_dstblt;
3375 update->primary->PatBlt = update_send_patblt;
3376 update->primary->ScrBlt = update_send_scrblt;
3377 update->primary->OpaqueRect = update_send_opaque_rect;
3378 update->primary->LineTo = update_send_line_to;
3379 update->primary->MemBlt = update_send_memblt;
3380 update->primary->GlyphIndex = update_send_glyph_index;
3381 update->secondary->CacheBitmap = update_send_cache_bitmap;
3382 update->secondary->CacheBitmapV2 = update_send_cache_bitmap_v2;
3383 update->secondary->CacheBitmapV3 = update_send_cache_bitmap_v3;
3384 update->secondary->CacheColorTable = update_send_cache_color_table;
3385 update->secondary->CacheGlyph = update_send_cache_glyph;
3386 update->secondary->CacheGlyphV2 = update_send_cache_glyph_v2;
3387 update->secondary->CacheBrush = update_send_cache_brush;
3388 update->altsec->CreateOffscreenBitmap = update_send_create_offscreen_bitmap_order;
3389 update->altsec->SwitchSurface = update_send_switch_surface_order;
3390 update->pointer->PointerSystem = update_send_pointer_system;
3391 update->pointer->PointerPosition = update_send_pointer_position;
3392 update->pointer->PointerColor = update_send_pointer_color;
3393 update->pointer->PointerLarge = update_send_pointer_large;
3394 update->pointer->PointerNew = update_send_pointer_new;
3395 update->pointer->PointerCached = update_send_pointer_cached;
3396 update->window->WindowCreate = update_send_window_create;
3397 update->window->WindowUpdate = update_send_window_update;
3398 update->window->WindowIcon = update_send_window_icon;
3399 update->window->WindowCachedIcon = update_send_window_cached_icon;
3400 update->window->WindowDelete = update_send_window_delete;
3401 update->window->NotifyIconCreate = update_send_notify_icon_create;
3402 update->window->NotifyIconUpdate = update_send_notify_icon_update;
3403 update->window->NotifyIconDelete = update_send_notify_icon_delete;
3404 update->window->MonitoredDesktop = update_send_monitored_desktop;
3405 update->window->NonMonitoredDesktop = update_send_non_monitored_desktop;
3408void update_register_client_callbacks(rdpUpdate* update)
3410 WINPR_ASSERT(update);
3412 update->RefreshRect = update_send_refresh_rect;
3413 update->SuppressOutput = update_send_suppress_output;
3414 update->SurfaceFrameAcknowledge = update_send_frame_acknowledge;
3417int update_process_messages(rdpUpdate* update)
3419 return update_message_queue_process_pending_messages(update);
3422static void update_free_queued_message(
void* obj)
3424 wMessage* msg = (wMessage*)obj;
3425 update_message_queue_free_message(msg);
3433 free(window_state->OverlayDescription.string);
3434 free(window_state->titleInfo.string);
3435 free(window_state->windowRects);
3436 free(window_state->visibilityRects);
3440rdpUpdate* update_new(rdpRdp* rdp)
3442 const wObject cb = {
nullptr,
nullptr,
nullptr, update_free_queued_message,
nullptr };
3445 WINPR_ASSERT(rdp->context);
3452 update->common.context = rdp->context;
3453 update->log = WLog_Get(
"com.freerdp.core.update");
3454 InitializeCriticalSection(&(update->mux));
3455 update->common.pointer = (rdpPointerUpdate*)calloc(1,
sizeof(rdpPointerUpdate));
3457 if (!update->common.pointer)
3466 update->common.primary = &primary->common;
3475 update->common.secondary = &secondary->common;
3485 update->common.altsec = &altsec->common;
3487 update->common.window = (rdpWindowUpdate*)calloc(1,
sizeof(rdpWindowUpdate));
3489 if (!update->common.window)
3494 deleteList->sIndices = 64;
3495 deleteList->indices = calloc(deleteList->sIndices, 2);
3497 if (!deleteList->indices)
3500 deleteList->cIndices = 0;
3504 update->common.SuppressOutput = update_send_suppress_output;
3505 update->initialState = TRUE;
3506 update->common.autoCalculateBitmapData = TRUE;
3507 update->queue = MessageQueue_New(&cb);
3512 return &update->common;
3514 WINPR_PRAGMA_DIAG_PUSH
3515 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
3516 update_free(&update->common);
3517 WINPR_PRAGMA_DIAG_POP
3521void update_free(rdpUpdate* update)
3523 if (update !=
nullptr)
3530 free(deleteList->indices);
3532 free(update->pointer);
3534 if (update->primary)
3538 free(primary->polygon_cb.points);
3539 free(primary->polyline.points);
3540 free(primary->polygon_sc.points);
3541 free(primary->fast_glyph.glyphData.aj);
3545 free(update->secondary);
3549 free(update->window);
3551 MessageQueue_Free(up->queue);
3552 DeleteCriticalSection(&up->mux);
3555 Stream_Free(up->us, TRUE);
3560void rdp_update_lock(rdpUpdate* update)
3563 EnterCriticalSection(&up->mux);
3566void rdp_update_unlock(rdpUpdate* update)
3569 LeaveCriticalSection(&up->mux);
3572BOOL update_begin_paint(rdpUpdate* update)
3575 WINPR_ASSERT(update);
3576 rdp_update_lock(update);
3578 up->withinBeginEndPaint = TRUE;
3580 WINPR_ASSERT(update->context);
3582 up->stats.base[RDP_STATS_BEGIN_PAINT]++;
3583 BOOL rc = IFCALLRESULT(TRUE, update->BeginPaint, update->context);
3585 WLog_WARN(TAG,
"BeginPaint call failed");
3588 rdpGdi* gdi = update->context->gdi;
3592 if (gdi->hdc && gdi->primary && gdi->primary->hdc)
3594 HGDI_WND hwnd = gdi->primary->hdc->hwnd;
3596 WINPR_ASSERT(hwnd->invalid);
3598 hwnd->invalid->null = TRUE;
3605BOOL update_end_paint(rdpUpdate* update)
3610 WINPR_ASSERT(update);
3611 up->stats.base[RDP_STATS_END_PAINT]++;
3613 IFCALLRET(update->EndPaint, rc, update->context);
3615 WLog_WARN(TAG,
"EndPaint call failed");
3617 if (!up->withinBeginEndPaint)
3619 up->withinBeginEndPaint = FALSE;
3621 rdp_update_unlock(update);
3625uint64_t rdp_stats_value_for_index(rdpUpdate* context,
size_t index)
3630 size_t limit = ARRAYSIZE(up->stats.primary);
3633 return up->stats.primary[index];
3636 limit += ARRAYSIZE(up->stats.secondary);
3638 return up->stats.secondary[index - offset];
3641 limit += ARRAYSIZE(up->stats.altsec);
3643 return up->stats.altsec[index - offset];
3646 limit += ARRAYSIZE(up->stats.base);
3648 return up->stats.base[index - offset];
3653const char* rdp_stats_name_for_index(
size_t index)
3655 if (!InitOnceExecuteOnce(&stats_names_once, stats_names_generate,
nullptr,
nullptr))
3656 return "RDP_STATS_UNUSED";
3657 if (index < rdp_stats_max_index())
3658 return stats_names[index];
3659 return "RDP_STATS_UNUSED";
3662size_t rdp_stats_max_index(
void)
3664 return RDP_STATS_COUNT;
3667void update_dump_stats(rdpUpdate* update)
3672 wLog* log = up->log;
3673 const DWORD level = WLOG_TRACE;
3674 if (!WLog_IsLevelActive(log, level))
3677 WLog_Print(log, level,
"RdpCodecStats");
3678 for (
size_t x = 0; x < rdp_stats_max_index(); x++)
3680 const char* name = rdp_stats_name_for_index(x);
3681 const uint64_t val = rdp_stats_value_for_index(update, x);
3682 WINPR_ASSERT(name && strnlen(name, 2) > 0);
3683 const bool unknown = strstr(name,
" UNKNOWN") !=
nullptr;
3684 const bool unused = strstr(name,
"UNUSED") !=
nullptr;
3685 const bool sunused = strcmp(
"RDP_STATS_UNUSED", name) == 0;
3686 if ((val != 0) || (!unknown && !sunused && !unused))
3687 WLog_Print(log, level,
"%s: %" PRIu64, name, val);
This struct contains function pointer to initialize/free objects.