22 #include <freerdp/config.h>
24 #include <winpr/crt.h>
25 #include <winpr/print.h>
26 #include <winpr/synch.h>
27 #include <winpr/thread.h>
28 #include <winpr/collections.h>
29 #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 static const char*
const UPDATE_TYPE_STRINGS[] = {
"Orders",
"Bitmap",
"Palette",
"Synchronize" };
53 static const char* update_type_to_string(UINT16 updateType)
55 if (updateType >= ARRAYSIZE(UPDATE_TYPE_STRINGS))
58 return UPDATE_TYPE_STRINGS[updateType];
61 static BOOL update_recv_orders(rdpUpdate* update,
wStream* s)
63 UINT16 numberOrders = 0;
67 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
70 Stream_Seek_UINT16(s);
71 Stream_Read_UINT16(s, numberOrders);
72 Stream_Seek_UINT16(s);
74 while (numberOrders > 0)
76 if (!update_recv_order(update, s))
78 WLog_ERR(TAG,
"update_recv_order() failed");
88 static BOOL update_read_bitmap_data(rdpUpdate* update,
wStream* s,
BITMAP_DATA* bitmapData)
91 WINPR_ASSERT(bitmapData);
93 if (!Stream_CheckAndLogRequiredLength(TAG, s, 18))
96 Stream_Read_UINT16(s, bitmapData->destLeft);
97 Stream_Read_UINT16(s, bitmapData->destTop);
98 Stream_Read_UINT16(s, bitmapData->destRight);
99 Stream_Read_UINT16(s, bitmapData->destBottom);
100 Stream_Read_UINT16(s, bitmapData->width);
101 Stream_Read_UINT16(s, bitmapData->height);
102 Stream_Read_UINT16(s, bitmapData->bitsPerPixel);
103 Stream_Read_UINT16(s, bitmapData->flags);
104 Stream_Read_UINT16(s, bitmapData->bitmapLength);
106 if ((bitmapData->width == 0) || (bitmapData->height == 0))
108 WLog_ERR(TAG,
"Invalid BITMAP_DATA: width=%" PRIu16
", height=%" PRIu16, bitmapData->width,
113 if (bitmapData->flags & BITMAP_COMPRESSION)
115 if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR))
117 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
120 Stream_Read_UINT16(s,
121 bitmapData->cbCompFirstRowSize);
122 Stream_Read_UINT16(s,
123 bitmapData->cbCompMainBodySize);
124 Stream_Read_UINT16(s, bitmapData->cbScanWidth);
125 Stream_Read_UINT16(s,
126 bitmapData->cbUncompressedSize);
127 bitmapData->bitmapLength = bitmapData->cbCompMainBodySize;
130 bitmapData->compressed = TRUE;
133 bitmapData->compressed = FALSE;
135 if (!Stream_CheckAndLogRequiredLength(TAG, s, bitmapData->bitmapLength))
138 if (bitmapData->bitmapLength > 0)
140 bitmapData->bitmapDataStream = malloc(bitmapData->bitmapLength);
142 if (!bitmapData->bitmapDataStream)
145 memcpy(bitmapData->bitmapDataStream, Stream_ConstPointer(s), bitmapData->bitmapLength);
146 Stream_Seek(s, bitmapData->bitmapLength);
152 static BOOL update_write_bitmap_data(rdpUpdate* update_pub,
wStream* s,
BITMAP_DATA* bitmapData)
156 WINPR_ASSERT(bitmapData);
158 if (!Stream_EnsureRemainingCapacity(s, 64 + bitmapData->bitmapLength))
161 if (update->common.autoCalculateBitmapData)
163 bitmapData->flags = 0;
164 bitmapData->cbCompFirstRowSize = 0;
166 if (bitmapData->compressed)
167 bitmapData->flags |= BITMAP_COMPRESSION;
169 if (update->common.context->settings->NoBitmapCompressionHeader)
171 bitmapData->flags |= NO_BITMAP_COMPRESSION_HDR;
172 bitmapData->cbCompMainBodySize = bitmapData->bitmapLength;
176 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->destLeft));
177 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->destTop));
178 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->destRight));
179 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->destBottom));
180 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->width));
181 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->height));
182 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->bitsPerPixel));
183 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->flags));
184 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, bitmapData->bitmapLength));
186 if (bitmapData->flags & BITMAP_COMPRESSION)
188 if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR))
192 WINPR_ASSERTING_INT_CAST(
193 uint16_t, bitmapData->cbCompFirstRowSize));
196 WINPR_ASSERTING_INT_CAST(
197 uint16_t, bitmapData->cbCompMainBodySize));
199 s, WINPR_ASSERTING_INT_CAST(uint16_t,
200 bitmapData->cbScanWidth));
203 WINPR_ASSERTING_INT_CAST(
204 uint16_t, bitmapData->cbUncompressedSize));
207 Stream_Write(s, bitmapData->bitmapDataStream, bitmapData->bitmapLength);
211 Stream_Write(s, bitmapData->bitmapDataStream, bitmapData->bitmapLength);
225 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
228 Stream_Read_UINT16(s, bitmapUpdate->number);
229 WLog_Print(up->log, WLOG_TRACE,
"BitmapUpdate: %" PRIu32
"", bitmapUpdate->number);
233 if (!bitmapUpdate->rectangles)
237 for (UINT32 i = 0; i < bitmapUpdate->number; i++)
239 if (!update_read_bitmap_data(update, s, &bitmapUpdate->rectangles[i]))
245 WINPR_PRAGMA_DIAG_PUSH
246 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
247 free_bitmap_update(update->context, bitmapUpdate);
248 WINPR_PRAGMA_DIAG_POP
252 static BOOL update_write_bitmap_update(rdpUpdate* update,
wStream* s,
255 WINPR_ASSERT(update);
256 WINPR_ASSERT(bitmapUpdate);
258 if (!Stream_EnsureRemainingCapacity(s, 32))
261 Stream_Write_UINT16(s, UPDATE_TYPE_BITMAP);
262 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(
263 uint16_t, bitmapUpdate->number));
266 for (UINT32 i = 0; i < bitmapUpdate->number; i++)
268 if (!update_write_bitmap_data(update, s, &bitmapUpdate->rectangles[i]))
282 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
285 Stream_Seek_UINT16(s);
286 Stream_Read_UINT32(s, palette_update->number);
288 if (palette_update->number > 256)
289 palette_update->number = 256;
291 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, palette_update->number, 3ull))
295 for (UINT32 i = 0; i < palette_update->number; i++)
298 Stream_Read_UINT8(s, entry->red);
299 Stream_Read_UINT8(s, entry->green);
300 Stream_Read_UINT8(s, entry->blue);
303 return palette_update;
305 WINPR_PRAGMA_DIAG_PUSH
306 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
307 free_palette_update(update->context, palette_update);
308 WINPR_PRAGMA_DIAG_POP
312 static BOOL update_read_synchronize(rdpUpdate* update,
wStream* s)
314 WINPR_UNUSED(update);
315 return Stream_SafeSeek(s, 2);
324 WINPR_ASSERT(play_sound);
326 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
329 Stream_Read_UINT32(s, play_sound->duration);
330 Stream_Read_UINT32(s, play_sound->frequency);
334 BOOL update_recv_play_sound(rdpUpdate* update,
wStream* s)
338 WINPR_ASSERT(update);
340 if (!update_read_play_sound(s, &play_sound))
343 return IFCALLRESULT(FALSE, update->PlaySound, update->context, &play_sound);
350 WINPR_ASSERT(update);
352 if (!pointer_position)
355 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
358 Stream_Read_UINT16(s, pointer_position->xPos);
359 Stream_Read_UINT16(s, pointer_position->yPos);
360 return pointer_position;
362 WINPR_PRAGMA_DIAG_PUSH
363 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
364 free_pointer_position_update(update->context, pointer_position);
365 WINPR_PRAGMA_DIAG_POP
373 WINPR_ASSERT(update);
378 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
381 Stream_Read_UINT32(s, pointer_system->type);
382 return pointer_system;
384 WINPR_PRAGMA_DIAG_PUSH
385 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
386 free_pointer_system_update(update->context, pointer_system);
387 WINPR_PRAGMA_DIAG_POP
392 BYTE xorBpp, UINT32 flags)
394 BYTE* newMask = NULL;
395 UINT32 scanlineSize = 0;
398 WINPR_ASSERT(pointer_color);
400 if (flags & LARGE_POINTER_FLAG_96x96)
406 if (!Stream_CheckAndLogRequiredLength(TAG, s, 14))
409 Stream_Read_UINT16(s, pointer_color->cacheIndex);
410 Stream_Read_UINT16(s, pointer_color->hotSpotX);
411 Stream_Read_UINT16(s, pointer_color->hotSpotY);
421 Stream_Read_UINT16(s, pointer_color->width);
422 Stream_Read_UINT16(s, pointer_color->height);
424 if ((pointer_color->width > max) || (pointer_color->height > max))
427 Stream_Read_UINT16(s, pointer_color->lengthAndMask);
428 Stream_Read_UINT16(s, pointer_color->lengthXorMask);
436 if (pointer_color->hotSpotX >= pointer_color->width)
437 pointer_color->hotSpotX = 0;
439 if (pointer_color->hotSpotY >= pointer_color->height)
440 pointer_color->hotSpotY = 0;
442 if (pointer_color->lengthXorMask > 0)
455 if (!Stream_CheckAndLogRequiredLength(TAG, s, pointer_color->lengthXorMask))
458 scanlineSize = (7 + xorBpp * pointer_color->width) / 8;
459 scanlineSize = ((scanlineSize + 1) / 2) * 2;
461 if (scanlineSize * pointer_color->height != pointer_color->lengthXorMask)
464 "invalid lengthXorMask: width=%" PRIu32
" height=%" PRIu32
", %" PRIu32
465 " instead of %" PRIu32
"",
466 pointer_color->width, pointer_color->height, pointer_color->lengthXorMask,
467 scanlineSize * pointer_color->height);
471 newMask = realloc(pointer_color->xorMaskData, pointer_color->lengthXorMask);
476 pointer_color->xorMaskData = newMask;
477 Stream_Read(s, pointer_color->xorMaskData, pointer_color->lengthXorMask);
480 if (pointer_color->lengthAndMask > 0)
489 if (!Stream_CheckAndLogRequiredLength(TAG, s, pointer_color->lengthAndMask))
492 scanlineSize = ((7 + pointer_color->width) / 8);
493 scanlineSize = ((1 + scanlineSize) / 2) * 2;
495 if (scanlineSize * pointer_color->height != pointer_color->lengthAndMask)
497 WLog_ERR(TAG,
"invalid lengthAndMask: %" PRIu32
" instead of %" PRIu32
"",
498 pointer_color->lengthAndMask, scanlineSize * pointer_color->height);
502 newMask = realloc(pointer_color->andMaskData, pointer_color->lengthAndMask);
507 pointer_color->andMaskData = newMask;
508 Stream_Read(s, pointer_color->andMaskData, pointer_color->lengthAndMask);
511 if (Stream_GetRemainingLength(s) > 0)
512 Stream_Seek_UINT8(s);
523 WINPR_ASSERT(update);
528 if (!s_update_read_pointer_color(s, pointer_color, xorBpp,
529 update->context->settings->LargePointerFlag))
532 return pointer_color;
534 WINPR_PRAGMA_DIAG_PUSH
535 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
536 free_pointer_color_update(update->context, pointer_color);
537 WINPR_PRAGMA_DIAG_POP
543 BYTE* newMask = NULL;
544 UINT32 scanlineSize = 0;
549 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
552 Stream_Read_UINT16(s, pointer->xorBpp);
553 Stream_Read_UINT16(s, pointer->cacheIndex);
554 Stream_Read_UINT16(s, pointer->hotSpotX);
555 Stream_Read_UINT16(s, pointer->hotSpotY);
557 Stream_Read_UINT16(s, pointer->width);
558 Stream_Read_UINT16(s, pointer->height);
560 if ((pointer->width > 384) || (pointer->height > 384))
563 Stream_Read_UINT32(s, pointer->lengthAndMask);
564 Stream_Read_UINT32(s, pointer->lengthXorMask);
566 if (pointer->hotSpotX >= pointer->width)
567 pointer->hotSpotX = 0;
569 if (pointer->hotSpotY >= pointer->height)
570 pointer->hotSpotY = 0;
572 if (pointer->lengthXorMask > 0)
585 if (!Stream_CheckAndLogRequiredLength(TAG, s, pointer->lengthXorMask))
588 scanlineSize = (7 + pointer->xorBpp * pointer->width) / 8;
589 scanlineSize = ((scanlineSize + 1) / 2) * 2;
591 if (scanlineSize * pointer->height != pointer->lengthXorMask)
594 "invalid lengthXorMask: width=%" PRIu32
" height=%" PRIu32
", %" PRIu32
595 " instead of %" PRIu32
"",
596 pointer->width, pointer->height, pointer->lengthXorMask,
597 scanlineSize * pointer->height);
601 newMask = realloc(pointer->xorMaskData, pointer->lengthXorMask);
606 pointer->xorMaskData = newMask;
607 Stream_Read(s, pointer->xorMaskData, pointer->lengthXorMask);
610 if (pointer->lengthAndMask > 0)
619 if (!Stream_CheckAndLogRequiredLength(TAG, s, pointer->lengthAndMask))
622 scanlineSize = ((7 + pointer->width) / 8);
623 scanlineSize = ((1 + scanlineSize) / 2) * 2;
625 if (scanlineSize * pointer->height != pointer->lengthAndMask)
627 WLog_ERR(TAG,
"invalid lengthAndMask: %" PRIu32
" instead of %" PRIu32
"",
628 pointer->lengthAndMask, scanlineSize * pointer->height);
632 newMask = realloc(pointer->andMaskData, pointer->lengthAndMask);
637 pointer->andMaskData = newMask;
638 Stream_Read(s, pointer->andMaskData, pointer->lengthAndMask);
641 if (Stream_GetRemainingLength(s) > 0)
642 Stream_Seek_UINT8(s);
653 WINPR_ASSERT(update);
658 if (!s_update_read_pointer_large(s, pointer))
663 WINPR_PRAGMA_DIAG_PUSH
664 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
665 free_pointer_large_update(update->context, pointer);
666 WINPR_PRAGMA_DIAG_POP
674 WINPR_ASSERT(update);
679 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
682 Stream_Read_UINT16(s, pointer_new->xorBpp);
684 if ((pointer_new->xorBpp < 1) || (pointer_new->xorBpp > 32))
686 WLog_ERR(TAG,
"invalid xorBpp %" PRIu32
"", pointer_new->xorBpp);
690 WINPR_ASSERT(pointer_new->xorBpp <= UINT8_MAX);
691 if (!s_update_read_pointer_color(
692 s, &pointer_new->colorPtrAttr, (UINT8)pointer_new->xorBpp,
693 update->context->settings->LargePointerFlag))
698 WINPR_PRAGMA_DIAG_PUSH
699 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
700 free_pointer_new_update(update->context, pointer_new);
701 WINPR_PRAGMA_DIAG_POP
709 WINPR_ASSERT(update);
714 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
717 Stream_Read_UINT16(s, pointer->cacheIndex);
720 WINPR_PRAGMA_DIAG_PUSH
721 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
722 free_pointer_cached_update(update->context, pointer);
723 WINPR_PRAGMA_DIAG_POP
727 BOOL update_recv_pointer(rdpUpdate* update,
wStream* s)
730 UINT16 messageType = 0;
732 WINPR_ASSERT(update);
734 rdpContext* context = update->context;
735 rdpPointerUpdate* pointer = update->pointer;
737 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2 + 2))
740 Stream_Read_UINT16(s, messageType);
741 Stream_Seek_UINT16(s);
745 case PTR_MSG_TYPE_POSITION:
749 if (pointer_position)
751 rc = IFCALLRESULT(FALSE, pointer->PointerPosition, context, pointer_position);
752 free_pointer_position_update(context, pointer_position);
757 case PTR_MSG_TYPE_SYSTEM:
763 rc = IFCALLRESULT(FALSE, pointer->PointerSystem, context, pointer_system);
764 free_pointer_system_update(context, pointer_system);
769 case PTR_MSG_TYPE_COLOR:
775 rc = IFCALLRESULT(FALSE, pointer->PointerColor, context, pointer_color);
776 free_pointer_color_update(context, pointer_color);
781 case PTR_MSG_TYPE_POINTER_LARGE:
787 rc = IFCALLRESULT(FALSE, pointer->PointerLarge, context, pointer_large);
788 free_pointer_large_update(context, pointer_large);
793 case PTR_MSG_TYPE_POINTER:
799 rc = IFCALLRESULT(FALSE, pointer->PointerNew, context, pointer_new);
800 free_pointer_new_update(context, pointer_new);
805 case PTR_MSG_TYPE_CACHED:
811 rc = IFCALLRESULT(FALSE, pointer->PointerCached, context, pointer_cached);
812 free_pointer_cached_update(context, pointer_cached);
824 BOOL update_recv(rdpUpdate* update,
wStream* s)
827 UINT16 updateType = 0;
829 rdpContext* context = update->context;
831 WINPR_ASSERT(context);
833 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
836 Stream_Read_UINT16(s, updateType);
837 WLog_Print(up->log, WLOG_TRACE,
"%s Update Data PDU", update_type_to_string(updateType));
839 if (!update_begin_paint(update))
844 case UPDATE_TYPE_ORDERS:
845 rc = update_recv_orders(update, s);
848 case UPDATE_TYPE_BITMAP:
850 BITMAP_UPDATE* bitmap_update = update_read_bitmap_update(update, s);
854 WLog_ERR(TAG,
"UPDATE_TYPE_BITMAP - update_read_bitmap_update() failed");
858 rc = IFCALLRESULT(FALSE, update->BitmapUpdate, context, bitmap_update);
859 free_bitmap_update(context, bitmap_update);
863 case UPDATE_TYPE_PALETTE:
869 WLog_ERR(TAG,
"UPDATE_TYPE_PALETTE - update_read_palette() failed");
873 rc = IFCALLRESULT(FALSE, update->Palette, context, palette_update);
874 free_palette_update(context, palette_update);
878 case UPDATE_TYPE_SYNCHRONIZE:
879 if (!update_read_synchronize(update, s))
881 rc = IFCALLRESULT(TRUE, update->Synchronize, context);
890 if (!update_end_paint(update))
895 WLog_ERR(TAG,
"UPDATE_TYPE %s [%" PRIu16
"] failed", update_type_to_string(updateType),
903 void update_reset_state(rdpUpdate* update)
908 WINPR_ASSERT(primary);
910 ZeroMemory(&primary->order_info,
sizeof(
ORDER_INFO));
923 free(primary->polyline.points);
932 free(primary->fast_glyph.glyphData.aj);
935 free(primary->polygon_sc.points);
938 free(primary->polygon_cb.points);
943 primary->order_info.orderType = ORDER_TYPE_PATBLT;
945 if (!up->initialState)
948 WINPR_ASSERT(altsec);
950 altsec->switch_surface.bitmapId = SCREEN_BITMAP_SURFACE;
951 IFCALL(altsec->common.SwitchSurface, update->context, &(altsec->switch_surface));
955 BOOL update_post_connect(rdpUpdate* update)
960 WINPR_ASSERT(update->context);
961 WINPR_ASSERT(update->context->settings);
962 up->asynchronous = update->context->settings->AsyncUpdate;
964 if (up->asynchronous)
966 #if defined(FORCE_ASYNC_UPDATE_OFF)
967 WLog_WARN(TAG,
"AsyncUpdate requested, but forced deactivated");
968 WLog_WARN(TAG,
"see https://github.com/FreeRDP/FreeRDP/issues/10153 for details");
970 if (!(up->proxy = update_message_proxy_new(update)))
975 altsec->switch_surface.bitmapId = SCREEN_BITMAP_SURFACE;
976 IFCALL(update->altsec->SwitchSurface, update->context, &(altsec->switch_surface));
977 up->initialState = FALSE;
981 void update_post_disconnect(rdpUpdate* update)
985 WINPR_ASSERT(update->context);
986 WINPR_ASSERT(update->context->settings);
988 up->asynchronous = update->context->settings->AsyncUpdate;
990 if (up->asynchronous)
992 #if !defined(FORCE_ASYNC_UPDATE_OFF)
993 update_message_proxy_free(up->proxy);
997 up->initialState = TRUE;
1000 static BOOL s_update_begin_paint(rdpContext* context)
1003 WINPR_ASSERT(context);
1008 if (!update_end_paint(&update->common))
1012 WINPR_ASSERT(context->rdp);
1013 s = fastpath_update_pdu_init_new(context->rdp->fastpath);
1018 Stream_SealLength(s);
1019 Stream_GetLength(s, update->offsetOrders);
1021 update->combineUpdates = TRUE;
1022 update->numberOrders = 0;
1027 static BOOL s_update_end_paint(rdpContext* context)
1030 WINPR_ASSERT(context);
1037 Stream_SealLength(s);
1038 Stream_SetPosition(s, update->offsetOrders);
1039 Stream_Write_UINT16(s, update->numberOrders);
1040 Stream_SetPosition(s, Stream_Length(s));
1042 if (update->numberOrders > 0)
1044 WLog_DBG(TAG,
"sending %" PRIu16
" orders", update->numberOrders);
1045 fastpath_send_update_pdu(context->rdp->fastpath, FASTPATH_UPDATETYPE_ORDERS, s, FALSE);
1048 update->combineUpdates = FALSE;
1049 update->numberOrders = 0;
1050 update->offsetOrders = 0;
1052 Stream_Free(s, TRUE);
1056 static void update_flush(rdpContext* context)
1060 WINPR_ASSERT(context);
1061 update = update_cast(context->update);
1063 if (update->numberOrders > 0)
1065 update_end_paint(&update->common);
1066 update_begin_paint(&update->common);
1070 static void update_force_flush(rdpContext* context)
1072 update_flush(context);
1075 static BOOL update_check_flush(rdpContext* context,
size_t size)
1077 WINPR_ASSERT(context);
1084 update_begin_paint(&update->common);
1088 if (Stream_GetPosition(s) + size + 64 >= 0x3FFF)
1090 update_flush(context);
1097 static BOOL update_set_bounds(rdpContext* context,
const rdpBounds* bounds)
1101 WINPR_ASSERT(context);
1103 update = update_cast(context->update);
1105 CopyMemory(&update->previousBounds, &update->currentBounds,
sizeof(rdpBounds));
1108 ZeroMemory(&update->currentBounds,
sizeof(rdpBounds));
1110 CopyMemory(&update->currentBounds, bounds,
sizeof(rdpBounds));
1115 static BOOL update_bounds_is_null(rdpBounds* bounds)
1117 WINPR_ASSERT(bounds);
1118 if ((bounds->left == 0) && (bounds->top == 0) && (bounds->right == 0) && (bounds->bottom == 0))
1124 static BOOL update_bounds_equals(rdpBounds* bounds1, rdpBounds* bounds2)
1126 WINPR_ASSERT(bounds1);
1127 WINPR_ASSERT(bounds2);
1129 if ((bounds1->left == bounds2->left) && (bounds1->top == bounds2->top) &&
1130 (bounds1->right == bounds2->right) && (bounds1->bottom == bounds2->bottom))
1136 static size_t update_prepare_bounds(rdpContext* context,
ORDER_INFO* orderInfo)
1141 WINPR_ASSERT(context);
1142 WINPR_ASSERT(orderInfo);
1144 update = update_cast(context->update);
1146 orderInfo->boundsFlags = 0;
1148 if (update_bounds_is_null(&update->currentBounds))
1151 orderInfo->controlFlags |= ORDER_BOUNDS;
1153 if (update_bounds_equals(&update->previousBounds, &update->currentBounds))
1155 orderInfo->controlFlags |= ORDER_ZERO_BOUNDS_DELTAS;
1162 if (update->previousBounds.left != update->currentBounds.left)
1164 orderInfo->bounds.left = update->currentBounds.left;
1165 orderInfo->boundsFlags |= BOUND_LEFT;
1169 if (update->previousBounds.top != update->currentBounds.top)
1171 orderInfo->bounds.top = update->currentBounds.top;
1172 orderInfo->boundsFlags |= BOUND_TOP;
1176 if (update->previousBounds.right != update->currentBounds.right)
1178 orderInfo->bounds.right = update->currentBounds.right;
1179 orderInfo->boundsFlags |= BOUND_RIGHT;
1183 if (update->previousBounds.bottom != update->currentBounds.bottom)
1185 orderInfo->bounds.bottom = update->currentBounds.bottom;
1186 orderInfo->boundsFlags |= BOUND_BOTTOM;
1194 static size_t update_prepare_order_info(rdpContext* context,
ORDER_INFO* orderInfo,
1197 WINPR_ASSERT(context);
1198 WINPR_ASSERT(orderInfo);
1200 orderInfo->fieldFlags = 0;
1201 orderInfo->orderType = orderType;
1202 orderInfo->controlFlags = ORDER_STANDARD;
1203 orderInfo->controlFlags |= ORDER_TYPE_CHANGE;
1205 length += get_primary_drawing_order_field_bytes(orderInfo->orderType, NULL);
1206 length += update_prepare_bounds(context, orderInfo);
1210 static int update_write_order_info(rdpContext* context,
wStream* s,
const ORDER_INFO* orderInfo,
1213 WINPR_UNUSED(context);
1214 WINPR_ASSERT(orderInfo);
1215 WINPR_ASSERT(orderInfo->controlFlags <= UINT8_MAX);
1217 const size_t position = Stream_GetPosition(s);
1218 const UINT8 controlFlags = (UINT8)orderInfo->controlFlags;
1220 Stream_SetPosition(s, offset);
1221 Stream_Write_UINT8(s, controlFlags);
1223 if (orderInfo->controlFlags & ORDER_TYPE_CHANGE)
1225 s, WINPR_ASSERTING_INT_CAST(uint8_t, orderInfo->orderType));
1227 if (!update_write_field_flags(
1228 s, orderInfo->fieldFlags, controlFlags,
1229 get_primary_drawing_order_field_bytes(orderInfo->orderType, NULL)))
1231 if (!update_write_bounds(s, orderInfo))
1233 Stream_SetPosition(s, position);
1240 WINPR_ASSERT(areas || (count == 0));
1242 Stream_Write_UINT8(s, count);
1245 for (BYTE i = 0; i < count; i++)
1247 Stream_Write_UINT16(s, areas[i].left);
1248 Stream_Write_UINT16(s, areas[i].top);
1249 Stream_Write_UINT16(s, areas[i].right);
1250 Stream_Write_UINT16(s, areas[i].bottom);
1254 static BOOL update_send_refresh_rect(rdpContext* context, BYTE count,
const RECTANGLE_16* areas)
1256 WINPR_ASSERT(context);
1257 rdpRdp* rdp = context->rdp;
1259 WINPR_ASSERT(rdp->settings);
1260 if (rdp->settings->RefreshRect)
1262 wStream* s = rdp_data_pdu_init(rdp);
1267 update_write_refresh_rect(s, count, areas);
1268 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_REFRESH_RECT, rdp->mcs->userId);
1274 static void update_write_suppress_output(
wStream* s, BYTE allow,
const RECTANGLE_16* area)
1278 Stream_Write_UINT8(s, allow);
1285 Stream_Write_UINT16(s, area->left);
1286 Stream_Write_UINT16(s, area->top);
1287 Stream_Write_UINT16(s, area->right);
1288 Stream_Write_UINT16(s, area->bottom);
1292 static BOOL update_send_suppress_output(rdpContext* context, BYTE allow,
const RECTANGLE_16* area)
1294 WINPR_ASSERT(context);
1295 rdpRdp* rdp = context->rdp;
1298 WINPR_ASSERT(rdp->settings);
1299 if (rdp->settings->SuppressOutput)
1301 wStream* s = rdp_data_pdu_init(rdp);
1306 update_write_suppress_output(s, allow, area);
1307 WINPR_ASSERT(rdp->mcs);
1308 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SUPPRESS_OUTPUT, rdp->mcs->userId);
1314 static BOOL update_send_surface_command(rdpContext* context,
wStream* s)
1317 WINPR_ASSERT(context);
1318 rdpRdp* rdp = context->rdp;
1322 update = fastpath_update_pdu_init(rdp->fastpath);
1327 if (!Stream_EnsureRemainingCapacity(update, Stream_GetPosition(s)))
1333 Stream_Write(update, Stream_Buffer(s), Stream_GetPosition(s));
1334 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, update, FALSE);
1336 Stream_Release(update);
1340 static BOOL update_send_surface_bits(rdpContext* context,
1344 WINPR_ASSERT(context);
1345 rdpRdp* rdp = context->rdp;
1348 WINPR_ASSERT(surfaceBitsCommand);
1351 update_force_flush(context);
1352 s = fastpath_update_pdu_init(rdp->fastpath);
1357 if (!update_write_surfcmd_surface_bits(s, surfaceBitsCommand))
1360 if (!fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s,
1361 surfaceBitsCommand->skipCompression))
1364 update_force_flush(context);
1371 static BOOL update_send_surface_frame_marker(rdpContext* context,
1375 WINPR_ASSERT(context);
1376 rdpRdp* rdp = context->rdp;
1378 update_force_flush(context);
1381 s = fastpath_update_pdu_init(rdp->fastpath);
1386 WINPR_ASSERT(surfaceFrameMarker->frameAction <= UINT16_MAX);
1387 if (!update_write_surfcmd_frame_marker(s, (UINT16)surfaceFrameMarker->frameAction,
1388 surfaceFrameMarker->frameId) ||
1389 !fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s, FALSE))
1392 update_force_flush(context);
1399 static BOOL update_send_surface_frame_bits(rdpContext* context,
const SURFACE_BITS_COMMAND* cmd,
1400 BOOL first, BOOL last, UINT32 frameId)
1404 WINPR_ASSERT(context);
1405 rdpRdp* rdp = context->rdp;
1408 update_force_flush(context);
1411 s = fastpath_update_pdu_init(rdp->fastpath);
1418 if (!update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_BEGIN, frameId))
1422 if (!update_write_surfcmd_surface_bits(s, cmd))
1427 if (!update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_END, frameId))
1431 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s,
1432 cmd->skipCompression);
1433 update_force_flush(context);
1439 static BOOL update_send_frame_acknowledge(rdpContext* context, UINT32 frameId)
1441 WINPR_ASSERT(context);
1442 rdpRdp* rdp = context->rdp;
1445 WINPR_ASSERT(rdp->settings);
1446 if (rdp->settings->ReceivedCapabilities[CAPSET_TYPE_FRAME_ACKNOWLEDGE])
1448 wStream* s = rdp_data_pdu_init(rdp);
1453 Stream_Write_UINT32(s, frameId);
1454 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FRAME_ACKNOWLEDGE, rdp->mcs->userId);
1460 static BOOL update_send_synchronize(rdpContext* context)
1463 WINPR_ASSERT(context);
1464 rdpRdp* rdp = context->rdp;
1468 s = fastpath_update_pdu_init(rdp->fastpath);
1474 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SYNCHRONIZE, s, FALSE);
1479 static BOOL update_send_desktop_resize(rdpContext* context)
1481 WINPR_ASSERT(context);
1482 return rdp_server_reactivate(context->rdp);
1485 static BOOL update_send_bitmap_update(rdpContext* context,
const BITMAP_UPDATE* bitmapUpdate)
1488 WINPR_ASSERT(context);
1489 rdpRdp* rdp = context->rdp;
1490 rdpUpdate* update = context->update;
1493 update_force_flush(context);
1496 s = fastpath_update_pdu_init(rdp->fastpath);
1501 if (!update_write_bitmap_update(update, s, bitmapUpdate) ||
1502 !fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_BITMAP, s,
1503 bitmapUpdate->skipCompression))
1509 update_force_flush(context);
1515 static BOOL update_send_play_sound(rdpContext* context,
const PLAY_SOUND_UPDATE* play_sound)
1518 WINPR_ASSERT(context);
1519 rdpRdp* rdp = context->rdp;
1522 WINPR_ASSERT(rdp->settings);
1523 WINPR_ASSERT(play_sound);
1524 if (!rdp->settings->ReceivedCapabilities[CAPSET_TYPE_SOUND])
1529 s = rdp_data_pdu_init(rdp);
1534 Stream_Write_UINT32(s, play_sound->duration);
1535 Stream_Write_UINT32(s, play_sound->frequency);
1536 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_PLAY_SOUND, rdp->mcs->userId);
1543 static BOOL update_send_dstblt(rdpContext* context,
const DSTBLT_ORDER* dstblt)
1547 WINPR_ASSERT(context);
1548 WINPR_ASSERT(dstblt);
1552 const size_t headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_DSTBLT);
1553 const size_t inf = update_approximate_dstblt_order(&orderInfo, dstblt);
1554 if (!update_check_flush(context, headerLength + inf))
1562 const size_t offset = Stream_GetPosition(s);
1564 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1567 Stream_Seek(s, headerLength);
1569 if (!update_write_dstblt_order(s, &orderInfo, dstblt))
1572 update_write_order_info(context, s, &orderInfo, offset);
1573 update->numberOrders++;
1577 static BOOL update_send_patblt(rdpContext* context,
PATBLT_ORDER* patblt)
1582 WINPR_ASSERT(context);
1583 WINPR_ASSERT(patblt);
1586 const size_t headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_PATBLT);
1587 if (!update_check_flush(context,
1588 headerLength + update_approximate_patblt_order(&orderInfo, patblt)))
1596 offset = Stream_GetPosition(s);
1598 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1601 Stream_Seek(s, headerLength);
1602 update_write_patblt_order(s, &orderInfo, patblt);
1603 update_write_order_info(context, s, &orderInfo, offset);
1604 update->numberOrders++;
1608 static BOOL update_send_scrblt(rdpContext* context,
const SCRBLT_ORDER* scrblt)
1612 WINPR_ASSERT(context);
1613 WINPR_ASSERT(scrblt);
1616 const size_t headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_SCRBLT);
1617 const size_t inf = update_approximate_scrblt_order(&orderInfo, scrblt);
1618 if (!update_check_flush(context, headerLength + inf))
1626 const size_t offset = Stream_GetPosition(s);
1628 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1631 Stream_Seek(s, headerLength);
1632 update_write_scrblt_order(s, &orderInfo, scrblt);
1633 update_write_order_info(context, s, &orderInfo, offset);
1634 update->numberOrders++;
1638 static BOOL update_send_opaque_rect(rdpContext* context,
const OPAQUE_RECT_ORDER* opaque_rect)
1643 WINPR_ASSERT(context);
1644 WINPR_ASSERT(opaque_rect);
1647 const size_t headerLength =
1648 update_prepare_order_info(context, &orderInfo, ORDER_TYPE_OPAQUE_RECT);
1649 if (!update_check_flush(
1650 context, headerLength + update_approximate_opaque_rect_order(&orderInfo, opaque_rect)))
1658 offset = Stream_GetPosition(s);
1660 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1663 Stream_Seek(s, headerLength);
1664 update_write_opaque_rect_order(s, &orderInfo, opaque_rect);
1665 update_write_order_info(context, s, &orderInfo, offset);
1666 update->numberOrders++;
1670 static BOOL update_send_line_to(rdpContext* context,
const LINE_TO_ORDER* line_to)
1674 WINPR_ASSERT(context);
1675 WINPR_ASSERT(line_to);
1677 const size_t headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_LINE_TO);
1678 const size_t inf = update_approximate_line_to_order(&orderInfo, line_to);
1679 if (!update_check_flush(context, headerLength + inf))
1687 const size_t offset = Stream_GetPosition(s);
1689 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1692 Stream_Seek(s, headerLength);
1693 update_write_line_to_order(s, &orderInfo, line_to);
1694 update_write_order_info(context, s, &orderInfo, offset);
1695 update->numberOrders++;
1699 static BOOL update_send_memblt(rdpContext* context,
MEMBLT_ORDER* memblt)
1704 WINPR_ASSERT(context);
1705 WINPR_ASSERT(memblt);
1707 const size_t headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_MEMBLT);
1708 if (!update_check_flush(context,
1709 headerLength + update_approximate_memblt_order(&orderInfo, memblt)))
1717 offset = Stream_GetPosition(s);
1719 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1722 Stream_Seek(s, headerLength);
1723 update_write_memblt_order(s, &orderInfo, memblt);
1724 update_write_order_info(context, s, &orderInfo, offset);
1725 update->numberOrders++;
1729 static BOOL update_send_glyph_index(rdpContext* context,
GLYPH_INDEX_ORDER* glyph_index)
1733 WINPR_ASSERT(context);
1734 WINPR_ASSERT(glyph_index);
1737 const size_t headerLength =
1738 update_prepare_order_info(context, &orderInfo, ORDER_TYPE_GLYPH_INDEX);
1739 const size_t inf = update_approximate_glyph_index_order(&orderInfo, glyph_index);
1740 if (!update_check_flush(context, headerLength + inf))
1748 const size_t offset = Stream_GetPosition(s);
1750 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1753 Stream_Seek(s, headerLength);
1754 update_write_glyph_index_order(s, &orderInfo, glyph_index);
1755 update_write_order_info(context, s, &orderInfo, offset);
1756 update->numberOrders++;
1764 static BOOL update_send_cache_bitmap(rdpContext* context,
const CACHE_BITMAP_ORDER* cache_bitmap)
1766 const size_t headerLength = 6;
1767 UINT16 extraFlags = 0;
1769 WINPR_ASSERT(context);
1770 WINPR_ASSERT(cache_bitmap);
1773 const BYTE orderType = cache_bitmap->compressed ? ORDER_TYPE_CACHE_BITMAP_COMPRESSED
1774 : ORDER_TYPE_BITMAP_UNCOMPRESSED;
1776 update_approximate_cache_bitmap_order(cache_bitmap, cache_bitmap->compressed, &extraFlags);
1777 if (!update_check_flush(context, headerLength + inf))
1785 const size_t bm = Stream_GetPosition(s);
1787 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1790 Stream_Seek(s, headerLength);
1792 if (!update_write_cache_bitmap_order(s, cache_bitmap, cache_bitmap->compressed, &extraFlags))
1795 const size_t em = Stream_GetPosition(s);
1796 WINPR_ASSERT(em >= bm + 13);
1797 const size_t orderLength = (em - bm) - 13;
1798 WINPR_ASSERT(orderLength <= UINT16_MAX);
1800 Stream_SetPosition(s, bm);
1801 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
1802 Stream_Write_UINT16(s, (UINT16)orderLength);
1803 Stream_Write_UINT16(s, extraFlags);
1804 Stream_Write_UINT8(s, orderType);
1805 Stream_SetPosition(s, em);
1806 update->numberOrders++;
1810 static BOOL update_send_cache_bitmap_v2(rdpContext* context,
CACHE_BITMAP_V2_ORDER* cache_bitmap_v2)
1812 const size_t headerLength = 6;
1813 UINT16 extraFlags = 0;
1815 WINPR_ASSERT(context);
1816 WINPR_ASSERT(cache_bitmap_v2);
1819 const BYTE orderType = cache_bitmap_v2->compressed ? ORDER_TYPE_BITMAP_COMPRESSED_V2
1820 : ORDER_TYPE_BITMAP_UNCOMPRESSED_V2;
1822 if (context->settings->NoBitmapCompressionHeader)
1823 cache_bitmap_v2->flags |= CBR2_NO_BITMAP_COMPRESSION_HDR;
1825 if (!update_check_flush(
1826 context, headerLength + update_approximate_cache_bitmap_v2_order(
1827 cache_bitmap_v2, cache_bitmap_v2->compressed, &extraFlags)))
1835 const size_t bm = Stream_GetPosition(s);
1837 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1840 Stream_Seek(s, headerLength);
1842 if (!update_write_cache_bitmap_v2_order(s, cache_bitmap_v2, cache_bitmap_v2->compressed,
1846 const size_t em = Stream_GetPosition(s);
1847 WINPR_ASSERT(em >= bm + 13);
1848 const size_t orderLength = (em - bm) - 13;
1849 WINPR_ASSERT(orderLength <= UINT16_MAX);
1851 Stream_SetPosition(s, bm);
1852 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
1853 Stream_Write_UINT16(s, (UINT16)orderLength);
1854 Stream_Write_UINT16(s, extraFlags);
1855 Stream_Write_UINT8(s, orderType);
1856 Stream_SetPosition(s, em);
1857 update->numberOrders++;
1861 static BOOL update_send_cache_bitmap_v3(rdpContext* context,
CACHE_BITMAP_V3_ORDER* cache_bitmap_v3)
1863 const size_t headerLength = 6;
1864 UINT16 extraFlags = 0;
1866 WINPR_ASSERT(context);
1867 WINPR_ASSERT(cache_bitmap_v3);
1870 const BYTE orderType = ORDER_TYPE_BITMAP_COMPRESSED_V3;
1871 if (!update_check_flush(context, headerLength + update_approximate_cache_bitmap_v3_order(
1872 cache_bitmap_v3, &extraFlags)))
1880 const size_t bm = Stream_GetPosition(s);
1882 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1885 Stream_Seek(s, headerLength);
1887 if (!update_write_cache_bitmap_v3_order(s, cache_bitmap_v3, &extraFlags))
1890 const size_t em = Stream_GetPosition(s);
1891 WINPR_ASSERT(em >= bm + 13);
1892 const size_t orderLength = (em - bm) - 13;
1893 WINPR_ASSERT(orderLength <= UINT16_MAX);
1895 Stream_SetPosition(s, bm);
1896 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
1897 Stream_Write_UINT16(s, (UINT16)orderLength);
1898 Stream_Write_UINT16(s, extraFlags);
1899 Stream_Write_UINT8(s, orderType);
1900 Stream_SetPosition(s, em);
1901 update->numberOrders++;
1905 static BOOL update_send_cache_color_table(rdpContext* context,
1909 size_t headerLength = 6;
1911 WINPR_ASSERT(context);
1912 WINPR_ASSERT(cache_color_table);
1915 const size_t inf = update_approximate_cache_color_table_order(cache_color_table, &flags);
1916 if (!update_check_flush(context, headerLength + inf))
1924 const size_t bm = Stream_GetPosition(s);
1926 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1929 Stream_Seek(s, headerLength);
1931 if (!update_write_cache_color_table_order(s, cache_color_table, &flags))
1934 const size_t em = Stream_GetPosition(s);
1935 WINPR_ASSERT(em >= bm + 13);
1936 const size_t orderLength = (em - bm) - 13;
1937 WINPR_ASSERT(orderLength <= UINT16_MAX);
1938 Stream_SetPosition(s, bm);
1939 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
1940 Stream_Write_UINT16(s, (UINT16)orderLength);
1941 Stream_Write_UINT16(s, flags);
1942 Stream_Write_UINT8(s, ORDER_TYPE_CACHE_COLOR_TABLE);
1943 Stream_SetPosition(s, em);
1944 update->numberOrders++;
1948 static BOOL update_send_cache_glyph(rdpContext* context,
const CACHE_GLYPH_ORDER* cache_glyph)
1951 const size_t headerLength = 6;
1953 WINPR_ASSERT(context);
1954 WINPR_ASSERT(cache_glyph);
1957 const size_t inf = update_approximate_cache_glyph_order(cache_glyph, &flags);
1958 if (!update_check_flush(context, headerLength + inf))
1966 const size_t bm = Stream_GetPosition(s);
1968 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1971 Stream_Seek(s, headerLength);
1973 if (!update_write_cache_glyph_order(s, cache_glyph, &flags))
1976 const size_t em = Stream_GetPosition(s);
1977 WINPR_ASSERT(em >= bm + 13);
1978 const size_t orderLength = (em - bm) - 13;
1979 WINPR_ASSERT(orderLength <= UINT16_MAX);
1980 Stream_SetPosition(s, bm);
1981 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
1982 Stream_Write_UINT16(s, (UINT16)orderLength);
1983 Stream_Write_UINT16(s, flags);
1984 Stream_Write_UINT8(s, ORDER_TYPE_CACHE_GLYPH);
1985 Stream_SetPosition(s, em);
1986 update->numberOrders++;
1990 static BOOL update_send_cache_glyph_v2(rdpContext* context,
1994 const size_t headerLength = 6;
1996 WINPR_ASSERT(context);
1997 WINPR_ASSERT(cache_glyph_v2);
2000 const size_t inf = update_approximate_cache_glyph_v2_order(cache_glyph_v2, &flags);
2001 if (!update_check_flush(context, headerLength + inf))
2009 const size_t bm = Stream_GetPosition(s);
2011 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2014 Stream_Seek(s, headerLength);
2016 if (!update_write_cache_glyph_v2_order(s, cache_glyph_v2, &flags))
2019 const size_t em = Stream_GetPosition(s);
2020 WINPR_ASSERT(em >= bm + 13);
2021 const size_t orderLength = (em - bm) - 13;
2022 WINPR_ASSERT(orderLength <= UINT16_MAX);
2023 Stream_SetPosition(s, bm);
2024 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
2025 Stream_Write_UINT16(s, (UINT16)orderLength);
2026 Stream_Write_UINT16(s, flags);
2027 Stream_Write_UINT8(s, ORDER_TYPE_CACHE_GLYPH);
2028 Stream_SetPosition(s, em);
2029 update->numberOrders++;
2033 static BOOL update_send_cache_brush(rdpContext* context,
const CACHE_BRUSH_ORDER* cache_brush)
2036 const size_t headerLength = 6;
2038 WINPR_ASSERT(context);
2039 WINPR_ASSERT(cache_brush);
2042 const size_t inf = update_approximate_cache_brush_order(cache_brush, &flags);
2043 if (!update_check_flush(context, headerLength + inf))
2051 const size_t bm = Stream_GetPosition(s);
2053 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2056 Stream_Seek(s, headerLength);
2058 if (!update_write_cache_brush_order(s, cache_brush, &flags))
2061 const size_t em = Stream_GetPosition(s);
2065 const size_t orderLength = (em - bm) - 13;
2066 WINPR_ASSERT(orderLength <= UINT16_MAX);
2067 Stream_SetPosition(s, bm);
2068 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY);
2069 Stream_Write_UINT16(s, (UINT16)orderLength);
2070 Stream_Write_UINT16(s, flags);
2071 Stream_Write_UINT8(s, ORDER_TYPE_CACHE_BRUSH);
2072 Stream_SetPosition(s, em);
2073 update->numberOrders++;
2081 static BOOL update_send_create_offscreen_bitmap_order(
2084 WINPR_ASSERT(context);
2085 WINPR_ASSERT(create_offscreen_bitmap);
2088 const size_t headerLength = 1;
2089 const size_t orderType = ORDER_TYPE_CREATE_OFFSCREEN_BITMAP;
2090 const size_t controlFlags = ORDER_SECONDARY | (orderType << 2);
2091 const size_t inf = update_approximate_create_offscreen_bitmap_order(create_offscreen_bitmap);
2092 if (!update_check_flush(context, headerLength + inf))
2100 const size_t bm = Stream_GetPosition(s);
2102 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2105 Stream_Seek(s, headerLength);
2107 if (!update_write_create_offscreen_bitmap_order(s, create_offscreen_bitmap))
2110 const size_t em = Stream_GetPosition(s);
2111 Stream_SetPosition(s, bm);
2112 Stream_Write_UINT8(s, controlFlags);
2113 Stream_SetPosition(s, em);
2114 update->numberOrders++;
2118 static BOOL update_send_switch_surface_order(rdpContext* context,
2121 WINPR_ASSERT(context);
2122 WINPR_ASSERT(switch_surface);
2125 const size_t headerLength = 1;
2126 const size_t orderType = ORDER_TYPE_SWITCH_SURFACE;
2127 const size_t controlFlags = ORDER_SECONDARY | (orderType << 2);
2128 const size_t inf = update_approximate_switch_surface_order(switch_surface);
2129 if (!update_check_flush(context, headerLength + inf))
2137 const size_t bm = Stream_GetPosition(s);
2139 if (!Stream_EnsureRemainingCapacity(s, headerLength))
2142 Stream_Seek(s, headerLength);
2144 if (!update_write_switch_surface_order(s, switch_surface))
2147 const size_t em = Stream_GetPosition(s);
2148 Stream_SetPosition(s, bm);
2149 Stream_Write_UINT8(s, controlFlags);
2150 Stream_SetPosition(s, em);
2151 update->numberOrders++;
2155 static BOOL update_send_pointer_system(rdpContext* context,
2159 BYTE updateCode = 0;
2161 WINPR_ASSERT(context);
2162 rdpRdp* rdp = context->rdp;
2166 s = fastpath_update_pdu_init(rdp->fastpath);
2171 if (pointer_system->type == SYSPTR_NULL)
2172 updateCode = FASTPATH_UPDATETYPE_PTR_NULL;
2174 updateCode = FASTPATH_UPDATETYPE_PTR_DEFAULT;
2176 ret = fastpath_send_update_pdu(rdp->fastpath, updateCode, s, FALSE);
2181 static BOOL update_send_pointer_position(rdpContext* context,
2185 WINPR_ASSERT(context);
2186 rdpRdp* rdp = context->rdp;
2190 s = fastpath_update_pdu_init(rdp->fastpath);
2195 if (!Stream_EnsureRemainingCapacity(s, 16))
2198 Stream_Write_UINT16(
2199 s, WINPR_ASSERTING_INT_CAST(uint16_t, pointerPosition->xPos));
2200 Stream_Write_UINT16(
2201 s, WINPR_ASSERTING_INT_CAST(uint16_t, pointerPosition->yPos));
2202 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_PTR_POSITION, s, FALSE);
2210 WINPR_ASSERT(pointer_color);
2211 if (!Stream_EnsureRemainingCapacity(s, 32 + pointer_color->lengthAndMask +
2212 pointer_color->lengthXorMask))
2215 Stream_Write_UINT16(s, pointer_color->cacheIndex);
2216 Stream_Write_UINT16(s, pointer_color->hotSpotX);
2217 Stream_Write_UINT16(s, pointer_color->hotSpotY);
2218 Stream_Write_UINT16(s, pointer_color->width);
2219 Stream_Write_UINT16(s, pointer_color->height);
2220 Stream_Write_UINT16(s, pointer_color->lengthAndMask);
2221 Stream_Write_UINT16(s, pointer_color->lengthXorMask);
2223 if (pointer_color->lengthXorMask > 0)
2224 Stream_Write(s, pointer_color->xorMaskData, pointer_color->lengthXorMask);
2226 if (pointer_color->lengthAndMask > 0)
2227 Stream_Write(s, pointer_color->andMaskData, pointer_color->lengthAndMask);
2229 Stream_Write_UINT8(s, 0);
2233 static BOOL update_send_pointer_color(rdpContext* context,
2238 WINPR_ASSERT(context);
2239 rdpRdp* rdp = context->rdp;
2243 WINPR_ASSERT(pointer_color);
2244 s = fastpath_update_pdu_init(rdp->fastpath);
2249 if (!update_write_pointer_color(s, pointer_color))
2252 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_COLOR, s, FALSE);
2260 WINPR_ASSERT(pointer);
2262 if (!Stream_EnsureRemainingCapacity(s, 32 + pointer->lengthAndMask + pointer->lengthXorMask))
2265 Stream_Write_UINT16(s, pointer->xorBpp);
2266 Stream_Write_UINT16(s, pointer->cacheIndex);
2267 Stream_Write_UINT16(s, pointer->hotSpotX);
2268 Stream_Write_UINT16(s, pointer->hotSpotY);
2269 Stream_Write_UINT16(s, pointer->width);
2270 Stream_Write_UINT16(s, pointer->height);
2271 Stream_Write_UINT32(s, pointer->lengthAndMask);
2272 Stream_Write_UINT32(s, pointer->lengthXorMask);
2273 Stream_Write(s, pointer->xorMaskData, pointer->lengthXorMask);
2274 Stream_Write(s, pointer->andMaskData, pointer->lengthAndMask);
2275 Stream_Write_UINT8(s, 0);
2279 static BOOL update_send_pointer_large(rdpContext* context,
const POINTER_LARGE_UPDATE* pointer)
2282 WINPR_ASSERT(context);
2283 rdpRdp* rdp = context->rdp;
2287 WINPR_ASSERT(pointer);
2288 s = fastpath_update_pdu_init(rdp->fastpath);
2293 if (!update_write_pointer_large(s, pointer))
2296 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_LARGE_POINTER, s, FALSE);
2302 static BOOL update_send_pointer_new(rdpContext* context,
const POINTER_NEW_UPDATE* pointer_new)
2306 WINPR_ASSERT(context);
2307 rdpRdp* rdp = context->rdp;
2311 WINPR_ASSERT(pointer_new);
2312 s = fastpath_update_pdu_init(rdp->fastpath);
2317 if (!Stream_EnsureRemainingCapacity(s, 16))
2320 Stream_Write_UINT16(
2321 s, WINPR_ASSERTING_INT_CAST(uint16_t, pointer_new->xorBpp));
2322 update_write_pointer_color(s, &pointer_new->colorPtrAttr);
2323 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_POINTER, s, FALSE);
2329 static BOOL update_send_pointer_cached(rdpContext* context,
2334 WINPR_ASSERT(context);
2335 rdpRdp* rdp = context->rdp;
2339 WINPR_ASSERT(pointer_cached);
2340 s = fastpath_update_pdu_init(rdp->fastpath);
2345 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(
2346 uint16_t, pointer_cached->cacheIndex));
2347 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_CACHED, s, FALSE);
2352 BOOL update_read_refresh_rect(rdpUpdate* update,
wStream* s)
2354 BYTE numberOfAreas = 0;
2358 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
2361 Stream_Read_UINT8(s, numberOfAreas);
2364 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, numberOfAreas, 8ull))
2367 for (BYTE index = 0; index < numberOfAreas; index++)
2371 Stream_Read_UINT16(s, area->left);
2372 Stream_Read_UINT16(s, area->top);
2373 Stream_Read_UINT16(s, area->right);
2374 Stream_Read_UINT16(s, area->bottom);
2377 WINPR_ASSERT(update->context);
2378 WINPR_ASSERT(update->context->settings);
2379 if (update->context->settings->RefreshRect)
2380 IFCALL(update->RefreshRect, update->context, numberOfAreas, areas);
2382 WLog_Print(up->log, WLOG_WARN,
"ignoring refresh rect request from client");
2387 BOOL update_read_suppress_output(rdpUpdate* update,
wStream* s)
2392 BYTE allowDisplayUpdates = 0;
2397 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
2400 Stream_Read_UINT8(s, allowDisplayUpdates);
2403 if (allowDisplayUpdates > 0)
2405 if (!Stream_CheckAndLogRequiredLength(TAG, s,
sizeof(
RECTANGLE_16)))
2408 Stream_Read_UINT16(s, rect.left);
2409 Stream_Read_UINT16(s, rect.top);
2410 Stream_Read_UINT16(s, rect.right);
2411 Stream_Read_UINT16(s, rect.bottom);
2416 WINPR_ASSERT(update->context);
2417 WINPR_ASSERT(update->context->settings);
2418 if (update->context->settings->SuppressOutput)
2419 IFCALL(update->SuppressOutput, update->context, allowDisplayUpdates, prect);
2421 WLog_Print(up->log, WLOG_WARN,
"ignoring suppress output request from client");
2426 static BOOL update_send_set_keyboard_indicators(rdpContext* context, UINT16 led_flags)
2430 WINPR_ASSERT(context);
2431 rdpRdp* rdp = context->rdp;
2432 s = rdp_data_pdu_init(rdp);
2437 Stream_Write_UINT16(s, 0);
2438 Stream_Write_UINT16(s, led_flags);
2440 WINPR_ASSERT(rdp->mcs);
2441 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS, rdp->mcs->userId);
2444 static BOOL update_send_set_keyboard_ime_status(rdpContext* context, UINT16 imeId, UINT32 imeState,
2449 WINPR_ASSERT(context);
2450 rdpRdp* rdp = context->rdp;
2451 s = rdp_data_pdu_init(rdp);
2457 Stream_Write_UINT16(s, imeId);
2458 Stream_Write_UINT32(s, imeState);
2459 Stream_Write_UINT32(s, imeConvMode);
2461 WINPR_ASSERT(rdp->mcs);
2462 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS, rdp->mcs->userId);
2465 static UINT16 update_calculate_new_or_existing_window(
const WINDOW_ORDER_INFO* orderInfo,
2468 UINT16 orderSize = 11;
2470 WINPR_ASSERT(orderInfo);
2471 WINPR_ASSERT(stateOrder);
2473 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OWNER) != 0)
2476 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_STYLE) != 0)
2479 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_SHOW) != 0)
2482 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE) != 0)
2483 orderSize += 2 + stateOrder->titleInfo.length;
2485 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) != 0)
2488 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) != 0)
2491 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_X) != 0)
2494 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_Y) != 0)
2497 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT) != 0)
2500 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT) != 0)
2503 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) != 0)
2506 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) != 0)
2509 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) != 0)
2512 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) != 0)
2513 orderSize += 2 + stateOrder->numWindowRects *
sizeof(
RECTANGLE_16);
2515 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) != 0)
2518 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) != 0)
2519 orderSize += 2 + stateOrder->numVisibilityRects *
sizeof(
RECTANGLE_16);
2521 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OVERLAY_DESCRIPTION) != 0)
2522 orderSize += 2 + stateOrder->OverlayDescription.length;
2524 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TASKBAR_BUTTON) != 0)
2527 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ENFORCE_SERVER_ZORDER) != 0)
2530 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_STATE) != 0)
2533 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_EDGE) != 0)
2539 static BOOL update_send_new_or_existing_window(rdpContext* context,
2543 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2544 UINT16 orderSize = update_calculate_new_or_existing_window(orderInfo, stateOrder);
2546 WINPR_ASSERT(context);
2547 WINPR_ASSERT(orderInfo);
2548 WINPR_ASSERT(stateOrder);
2552 if (!update_check_flush(context, orderSize))
2560 if (!Stream_EnsureRemainingCapacity(s, orderSize))
2563 Stream_Write_UINT8(s, controlFlags);
2564 Stream_Write_UINT16(s, orderSize);
2565 Stream_Write_UINT32(s, orderInfo->fieldFlags);
2566 Stream_Write_UINT32(s, orderInfo->windowId);
2568 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OWNER) != 0)
2569 Stream_Write_UINT32(s, stateOrder->ownerWindowId);
2571 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_STYLE) != 0)
2573 Stream_Write_UINT32(s, stateOrder->style);
2574 Stream_Write_UINT32(s, stateOrder->extendedStyle);
2577 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_SHOW) != 0)
2579 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, stateOrder->showState));
2582 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE) != 0)
2584 Stream_Write_UINT16(s, stateOrder->titleInfo.length);
2585 Stream_Write(s, stateOrder->titleInfo.string, stateOrder->titleInfo.length);
2588 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) != 0)
2590 Stream_Write_INT32(s, stateOrder->clientOffsetX);
2591 Stream_Write_INT32(s, stateOrder->clientOffsetY);
2594 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) != 0)
2596 Stream_Write_UINT32(s, stateOrder->clientAreaWidth);
2597 Stream_Write_UINT32(s, stateOrder->clientAreaHeight);
2600 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_X) != 0)
2602 Stream_Write_UINT32(s, stateOrder->resizeMarginLeft);
2603 Stream_Write_UINT32(s, stateOrder->resizeMarginRight);
2606 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_Y) != 0)
2608 Stream_Write_UINT32(s, stateOrder->resizeMarginTop);
2609 Stream_Write_UINT32(s, stateOrder->resizeMarginBottom);
2612 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT) != 0)
2614 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, stateOrder->RPContent));
2617 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT) != 0)
2619 Stream_Write_UINT32(s, stateOrder->rootParentHandle);
2622 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) != 0)
2624 Stream_Write_INT32(s, stateOrder->windowOffsetX);
2625 Stream_Write_INT32(s, stateOrder->windowOffsetY);
2628 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) != 0)
2630 Stream_Write_INT32(s, stateOrder->windowClientDeltaX);
2631 Stream_Write_INT32(s, stateOrder->windowClientDeltaY);
2634 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) != 0)
2636 Stream_Write_UINT32(s, stateOrder->windowWidth);
2637 Stream_Write_UINT32(s, stateOrder->windowHeight);
2640 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) != 0)
2642 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, stateOrder->numWindowRects));
2643 Stream_Write(s, stateOrder->windowRects, stateOrder->numWindowRects *
sizeof(
RECTANGLE_16));
2646 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) != 0)
2648 Stream_Write_INT32(s, stateOrder->visibleOffsetX);
2649 Stream_Write_INT32(s, stateOrder->visibleOffsetY);
2652 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) != 0)
2654 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, stateOrder->numVisibilityRects));
2655 Stream_Write(s, stateOrder->visibilityRects,
2656 stateOrder->numVisibilityRects *
sizeof(
RECTANGLE_16));
2659 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OVERLAY_DESCRIPTION) != 0)
2661 Stream_Write_UINT16(s, stateOrder->OverlayDescription.length);
2662 Stream_Write(s, stateOrder->OverlayDescription.string,
2663 stateOrder->OverlayDescription.length);
2666 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TASKBAR_BUTTON) != 0)
2668 Stream_Write_UINT8(s, stateOrder->TaskbarButton);
2671 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ENFORCE_SERVER_ZORDER) != 0)
2673 Stream_Write_UINT8(s, stateOrder->EnforceServerZOrder);
2676 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_STATE) != 0)
2678 Stream_Write_UINT8(s, stateOrder->AppBarState);
2681 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_EDGE) != 0)
2683 Stream_Write_UINT8(s, stateOrder->AppBarEdge);
2686 update->numberOrders++;
2690 static BOOL update_send_window_create(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
2693 return update_send_new_or_existing_window(context, orderInfo, stateOrder);
2696 static BOOL update_send_window_update(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
2699 return update_send_new_or_existing_window(context, orderInfo, stateOrder);
2702 static UINT16 update_calculate_window_icon_order(
const WINDOW_ORDER_INFO* orderInfo,
2705 UINT16 orderSize = 23;
2707 WINPR_ASSERT(iconOrder);
2708 ICON_INFO* iconInfo = iconOrder->iconInfo;
2709 WINPR_ASSERT(iconInfo);
2711 orderSize += iconInfo->cbBitsColor + iconInfo->cbBitsMask;
2713 if (iconInfo->bpp <= 8)
2714 orderSize += 2 + iconInfo->cbColorTable;
2719 static BOOL update_send_window_icon(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
2722 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2724 WINPR_ASSERT(iconOrder);
2725 ICON_INFO* iconInfo = iconOrder->iconInfo;
2726 UINT16 orderSize = update_calculate_window_icon_order(orderInfo, iconOrder);
2728 WINPR_ASSERT(context);
2729 WINPR_ASSERT(orderInfo);
2730 WINPR_ASSERT(iconInfo);
2734 if (!update_check_flush(context, orderSize))
2739 if (!s || !iconInfo)
2742 if (!Stream_EnsureRemainingCapacity(s, orderSize))
2746 Stream_Write_UINT8(s, controlFlags);
2747 Stream_Write_UINT16(s, orderSize);
2748 Stream_Write_UINT32(s, orderInfo->fieldFlags);
2749 Stream_Write_UINT32(s, orderInfo->windowId);
2751 Stream_Write_UINT16(
2752 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->cacheEntry));
2753 Stream_Write_UINT8(s,
2754 WINPR_ASSERTING_INT_CAST(uint8_t, iconInfo->cacheId));
2755 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, iconInfo->bpp));
2756 Stream_Write_UINT16(s,
2757 WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->width));
2758 Stream_Write_UINT16(
2759 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->height));
2761 if (iconInfo->bpp <= 8)
2763 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(
2764 uint16_t, iconInfo->cbColorTable));
2767 Stream_Write_UINT16(
2768 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->cbBitsMask));
2769 Stream_Write_UINT16(
2770 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo->cbBitsColor));
2771 Stream_Write(s, iconInfo->bitsMask, iconInfo->cbBitsMask);
2773 if (iconInfo->bpp <= 8)
2775 Stream_Write(s, iconInfo->colorTable, iconInfo->cbColorTable);
2778 Stream_Write(s, iconInfo->bitsColor, iconInfo->cbBitsColor);
2780 update->numberOrders++;
2784 static BOOL update_send_window_cached_icon(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
2787 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2788 UINT16 orderSize = 14;
2790 WINPR_ASSERT(cachedIconOrder);
2793 WINPR_ASSERT(context);
2794 WINPR_ASSERT(orderInfo);
2795 WINPR_ASSERT(cachedIcon);
2799 if (!update_check_flush(context, orderSize))
2806 if (!Stream_EnsureRemainingCapacity(s, orderSize))
2810 Stream_Write_UINT8(s, controlFlags);
2811 Stream_Write_UINT16(s, orderSize);
2812 Stream_Write_UINT32(s, orderInfo->fieldFlags);
2813 Stream_Write_UINT32(s, orderInfo->windowId);
2815 Stream_Write_UINT16(
2816 s, WINPR_ASSERTING_INT_CAST(uint16_t, cachedIcon->cacheEntry));
2818 s, WINPR_ASSERTING_INT_CAST(uint8_t, cachedIcon->cacheId));
2819 update->numberOrders++;
2823 static BOOL update_send_window_delete(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo)
2825 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2826 UINT16 orderSize = 11;
2828 WINPR_ASSERT(context);
2829 WINPR_ASSERT(orderInfo);
2832 if (!update_check_flush(context, orderSize))
2840 if (!Stream_EnsureRemainingCapacity(s, orderSize))
2844 Stream_Write_UINT8(s, controlFlags);
2845 Stream_Write_UINT16(s, orderSize);
2846 Stream_Write_UINT32(s, orderInfo->fieldFlags);
2847 Stream_Write_UINT32(s, orderInfo->windowId);
2848 update->numberOrders++;
2852 static UINT16 update_calculate_new_or_existing_notification_icons_order(
2855 UINT16 orderSize = 15;
2857 WINPR_ASSERT(orderInfo);
2858 WINPR_ASSERT(iconStateOrder);
2860 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_VERSION) != 0)
2863 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP) != 0)
2865 orderSize += 2 + iconStateOrder->toolTip.length;
2868 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP) != 0)
2871 orderSize += 12 + infoTip.text.length + infoTip.title.length;
2874 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_STATE) != 0)
2879 if ((orderInfo->fieldFlags & WINDOW_ORDER_ICON) != 0)
2881 ICON_INFO iconInfo = iconStateOrder->icon;
2884 if (iconInfo.bpp <= 8)
2885 orderSize += 2 + iconInfo.cbColorTable;
2887 orderSize += iconInfo.cbBitsMask + iconInfo.cbBitsColor;
2889 else if ((orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON) != 0)
2898 update_send_new_or_existing_notification_icons(rdpContext* context,
2902 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2903 BOOL versionFieldPresent = FALSE;
2904 const UINT16 orderSize =
2905 update_calculate_new_or_existing_notification_icons_order(orderInfo, iconStateOrder);
2907 WINPR_ASSERT(context);
2908 WINPR_ASSERT(orderInfo);
2909 WINPR_ASSERT(iconStateOrder);
2912 if (!update_check_flush(context, orderSize))
2919 if (!Stream_EnsureRemainingCapacity(s, orderSize))
2923 Stream_Write_UINT8(s, controlFlags);
2924 Stream_Write_UINT16(s, orderSize);
2925 Stream_Write_UINT32(s, orderInfo->fieldFlags);
2926 Stream_Write_UINT32(s, orderInfo->windowId);
2927 Stream_Write_UINT32(s, orderInfo->notifyIconId);
2930 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_VERSION) != 0)
2932 versionFieldPresent = TRUE;
2933 Stream_Write_UINT32(s, iconStateOrder->version);
2936 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP) != 0)
2938 Stream_Write_UINT16(s, iconStateOrder->toolTip.length);
2939 Stream_Write(s, iconStateOrder->toolTip.string, iconStateOrder->toolTip.length);
2942 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP) != 0)
2947 if (versionFieldPresent && iconStateOrder->version == 0)
2950 Stream_Write_UINT32(s, infoTip.timeout);
2951 Stream_Write_UINT32(s, infoTip.flags);
2952 Stream_Write_UINT16(s, infoTip.text.length);
2953 Stream_Write(s, infoTip.text.string, infoTip.text.length);
2954 Stream_Write_UINT16(s, infoTip.title.length);
2955 Stream_Write(s, infoTip.title.string, infoTip.title.length);
2958 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_STATE) != 0)
2961 if (versionFieldPresent && iconStateOrder->version == 0)
2964 Stream_Write_UINT32(s, iconStateOrder->state);
2967 if ((orderInfo->fieldFlags & WINDOW_ORDER_ICON) != 0)
2969 const ICON_INFO iconInfo = iconStateOrder->icon;
2971 Stream_Write_UINT16(
2972 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo.cacheEntry));
2974 s, WINPR_ASSERTING_INT_CAST(uint8_t, iconInfo.cacheId));
2975 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, iconInfo.bpp));
2976 Stream_Write_UINT16(
2977 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo.width));
2978 Stream_Write_UINT16(
2979 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo.height));
2981 if (iconInfo.bpp <= 8)
2983 Stream_Write_UINT16(
2984 s, WINPR_ASSERTING_INT_CAST(uint16_t,
2985 iconInfo.cbColorTable));
2988 Stream_Write_UINT16(
2989 s, WINPR_ASSERTING_INT_CAST(uint16_t, iconInfo.cbBitsMask));
2990 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(
2991 uint16_t, iconInfo.cbBitsColor));
2992 Stream_Write(s, iconInfo.bitsMask, iconInfo.cbBitsMask);
2994 if (iconInfo.bpp <= 8)
2996 Stream_Write(s, iconInfo.colorTable, iconInfo.cbColorTable);
2999 Stream_Write(s, iconInfo.bitsColor, iconInfo.cbBitsColor);
3001 else if ((orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON) != 0)
3004 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(
3005 uint16_t, cachedIcon.cacheEntry));
3007 s, WINPR_ASSERTING_INT_CAST(uint8_t, cachedIcon.cacheId));
3010 update->numberOrders++;
3014 static BOOL update_send_notify_icon_create(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
3017 return update_send_new_or_existing_notification_icons(context, orderInfo, iconStateOrder);
3020 static BOOL update_send_notify_icon_update(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
3023 return update_send_new_or_existing_notification_icons(context, orderInfo, iconStateOrder);
3026 static BOOL update_send_notify_icon_delete(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo)
3028 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
3029 UINT16 orderSize = 15;
3031 WINPR_ASSERT(context);
3032 WINPR_ASSERT(orderInfo);
3035 if (!update_check_flush(context, orderSize))
3044 Stream_Write_UINT8(s, controlFlags);
3045 Stream_Write_UINT16(s, orderSize);
3046 Stream_Write_UINT32(s, orderInfo->fieldFlags);
3047 Stream_Write_UINT32(s, orderInfo->windowId);
3048 Stream_Write_UINT32(s, orderInfo->notifyIconId);
3049 update->numberOrders++;
3053 static UINT16 update_calculate_monitored_desktop(
const WINDOW_ORDER_INFO* orderInfo,
3056 UINT16 orderSize = 7;
3058 WINPR_ASSERT(orderInfo);
3059 WINPR_ASSERT(monitoredDesktop);
3061 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
3066 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
3068 orderSize += 1 + (4 * monitoredDesktop->numWindowIds);
3074 static BOOL update_send_monitored_desktop(rdpContext* context,
const WINDOW_ORDER_INFO* orderInfo,
3077 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
3078 UINT16 orderSize = update_calculate_monitored_desktop(orderInfo, monitoredDesktop);
3080 WINPR_ASSERT(context);
3081 WINPR_ASSERT(orderInfo);
3082 WINPR_ASSERT(monitoredDesktop);
3086 if (!update_check_flush(context, orderSize))
3094 Stream_Write_UINT8(s, controlFlags);
3095 Stream_Write_UINT16(s, orderSize);
3096 Stream_Write_UINT32(s, orderInfo->fieldFlags);
3098 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
3100 Stream_Write_UINT32(s, monitoredDesktop->activeWindowId);
3103 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
3106 s, WINPR_ASSERTING_INT_CAST(
3107 uint8_t, monitoredDesktop->numWindowIds));
3110 for (UINT32 i = 0; i < monitoredDesktop->numWindowIds; i++)
3112 Stream_Write_UINT32(s,
3113 WINPR_ASSERTING_INT_CAST(uint32_t, monitoredDesktop->windowIds[i]));
3117 update->numberOrders++;
3121 static BOOL update_send_non_monitored_desktop(rdpContext* context,
3124 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
3125 UINT16 orderSize = 7;
3127 WINPR_ASSERT(context);
3128 WINPR_ASSERT(orderInfo);
3131 if (!update_check_flush(context, orderSize))
3139 Stream_Write_UINT8(s, controlFlags);
3140 Stream_Write_UINT16(s, orderSize);
3141 Stream_Write_UINT32(s, orderInfo->fieldFlags);
3142 update->numberOrders++;
3146 void update_register_server_callbacks(rdpUpdate* update)
3148 WINPR_ASSERT(update);
3150 update->BeginPaint = s_update_begin_paint;
3151 update->EndPaint = s_update_end_paint;
3152 update->SetBounds = update_set_bounds;
3153 update->Synchronize = update_send_synchronize;
3154 update->DesktopResize = update_send_desktop_resize;
3155 update->BitmapUpdate = update_send_bitmap_update;
3156 update->SurfaceBits = update_send_surface_bits;
3157 update->SurfaceFrameMarker = update_send_surface_frame_marker;
3158 update->SurfaceCommand = update_send_surface_command;
3159 update->SurfaceFrameBits = update_send_surface_frame_bits;
3160 update->PlaySound = update_send_play_sound;
3161 update->SetKeyboardIndicators = update_send_set_keyboard_indicators;
3162 update->SetKeyboardImeStatus = update_send_set_keyboard_ime_status;
3163 update->SaveSessionInfo = rdp_send_save_session_info;
3164 update->ServerStatusInfo = rdp_send_server_status_info;
3165 update->primary->DstBlt = update_send_dstblt;
3166 update->primary->PatBlt = update_send_patblt;
3167 update->primary->ScrBlt = update_send_scrblt;
3168 update->primary->OpaqueRect = update_send_opaque_rect;
3169 update->primary->LineTo = update_send_line_to;
3170 update->primary->MemBlt = update_send_memblt;
3171 update->primary->GlyphIndex = update_send_glyph_index;
3172 update->secondary->CacheBitmap = update_send_cache_bitmap;
3173 update->secondary->CacheBitmapV2 = update_send_cache_bitmap_v2;
3174 update->secondary->CacheBitmapV3 = update_send_cache_bitmap_v3;
3175 update->secondary->CacheColorTable = update_send_cache_color_table;
3176 update->secondary->CacheGlyph = update_send_cache_glyph;
3177 update->secondary->CacheGlyphV2 = update_send_cache_glyph_v2;
3178 update->secondary->CacheBrush = update_send_cache_brush;
3179 update->altsec->CreateOffscreenBitmap = update_send_create_offscreen_bitmap_order;
3180 update->altsec->SwitchSurface = update_send_switch_surface_order;
3181 update->pointer->PointerSystem = update_send_pointer_system;
3182 update->pointer->PointerPosition = update_send_pointer_position;
3183 update->pointer->PointerColor = update_send_pointer_color;
3184 update->pointer->PointerLarge = update_send_pointer_large;
3185 update->pointer->PointerNew = update_send_pointer_new;
3186 update->pointer->PointerCached = update_send_pointer_cached;
3187 update->window->WindowCreate = update_send_window_create;
3188 update->window->WindowUpdate = update_send_window_update;
3189 update->window->WindowIcon = update_send_window_icon;
3190 update->window->WindowCachedIcon = update_send_window_cached_icon;
3191 update->window->WindowDelete = update_send_window_delete;
3192 update->window->NotifyIconCreate = update_send_notify_icon_create;
3193 update->window->NotifyIconUpdate = update_send_notify_icon_update;
3194 update->window->NotifyIconDelete = update_send_notify_icon_delete;
3195 update->window->MonitoredDesktop = update_send_monitored_desktop;
3196 update->window->NonMonitoredDesktop = update_send_non_monitored_desktop;
3199 void update_register_client_callbacks(rdpUpdate* update)
3201 WINPR_ASSERT(update);
3203 update->RefreshRect = update_send_refresh_rect;
3204 update->SuppressOutput = update_send_suppress_output;
3205 update->SurfaceFrameAcknowledge = update_send_frame_acknowledge;
3208 int update_process_messages(rdpUpdate* update)
3210 return update_message_queue_process_pending_messages(update);
3213 static void update_free_queued_message(
void* obj)
3215 wMessage* msg = (wMessage*)obj;
3216 update_message_queue_free_message(msg);
3224 free(window_state->OverlayDescription.string);
3225 free(window_state->titleInfo.string);
3226 free(window_state->windowRects);
3227 free(window_state->visibilityRects);
3231 rdpUpdate* update_new(rdpRdp* rdp)
3233 const wObject cb = { NULL, NULL, NULL, update_free_queued_message, NULL };
3236 WINPR_ASSERT(rdp->context);
3243 update->common.context = rdp->context;
3244 update->log = WLog_Get(
"com.freerdp.core.update");
3245 InitializeCriticalSection(&(update->mux));
3246 update->common.pointer = (rdpPointerUpdate*)calloc(1,
sizeof(rdpPointerUpdate));
3248 if (!update->common.pointer)
3256 update->common.primary = &primary->common;
3263 update->common.secondary = &secondary->common;
3271 update->common.altsec = &altsec->common;
3272 update->common.window = (rdpWindowUpdate*)calloc(1,
sizeof(rdpWindowUpdate));
3274 if (!update->common.window)
3278 deleteList->sIndices = 64;
3279 deleteList->indices = calloc(deleteList->sIndices, 2);
3281 if (!deleteList->indices)
3284 deleteList->cIndices = 0;
3285 update->common.SuppressOutput = update_send_suppress_output;
3286 update->initialState = TRUE;
3287 update->common.autoCalculateBitmapData = TRUE;
3288 update->queue = MessageQueue_New(&cb);
3293 return &update->common;
3295 WINPR_PRAGMA_DIAG_PUSH
3296 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
3297 update_free(&update->common);
3298 WINPR_PRAGMA_DIAG_POP
3302 void update_free(rdpUpdate* update)
3311 free(deleteList->indices);
3313 free(update->pointer);
3315 if (update->primary)
3319 free(primary->polygon_cb.points);
3320 free(primary->polyline.points);
3321 free(primary->polygon_sc.points);
3322 free(primary->fast_glyph.glyphData.aj);
3326 free(update->secondary);
3330 free(update->window);
3332 MessageQueue_Free(up->queue);
3333 DeleteCriticalSection(&up->mux);
3336 Stream_Free(up->us, TRUE);
3341 void rdp_update_lock(rdpUpdate* update)
3344 EnterCriticalSection(&up->mux);
3347 void rdp_update_unlock(rdpUpdate* update)
3350 LeaveCriticalSection(&up->mux);
3353 BOOL update_begin_paint(rdpUpdate* update)
3356 WINPR_ASSERT(update);
3357 rdp_update_lock(update);
3359 up->withinBeginEndPaint = TRUE;
3361 WINPR_ASSERT(update->context);
3363 BOOL rc = IFCALLRESULT(TRUE, update->BeginPaint, update->context);
3365 WLog_WARN(TAG,
"BeginPaint call failed");
3368 rdpGdi* gdi = update->context->gdi;
3372 if (gdi->hdc && gdi->primary && gdi->primary->hdc)
3374 HGDI_WND hwnd = gdi->primary->hdc->hwnd;
3376 WINPR_ASSERT(hwnd->invalid);
3378 hwnd->invalid->null = TRUE;
3385 BOOL update_end_paint(rdpUpdate* update)
3389 WINPR_ASSERT(update);
3390 IFCALLRET(update->EndPaint, rc, update->context);
3392 WLog_WARN(TAG,
"EndPaint call failed");
3396 if (!up->withinBeginEndPaint)
3398 up->withinBeginEndPaint = FALSE;
3400 rdp_update_unlock(update);
This struct contains function pointer to initialize/free objects.