FreeRDP
Loading...
Searching...
No Matches
window.c
1
21#include <freerdp/config.h>
22
23#include "settings.h"
24
25#include <winpr/crt.h>
26#include <winpr/assert.h>
27
28#include <freerdp/log.h>
29
30#include "window.h"
31
32#define TAG FREERDP_TAG("core.window")
33
34static void update_free_window_icon_info(ICON_INFO* iconInfo);
35
36BOOL rail_read_unicode_string(wStream* s, RAIL_UNICODE_STRING* unicode_string)
37{
38 WINPR_ASSERT(unicode_string);
39
40 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
41 return FALSE;
42
43 const UINT16 new_len = Stream_Get_UINT16(s); /* cbString (2 bytes) */
44
45 if (!Stream_CheckAndLogRequiredLength(TAG, s, new_len))
46 return FALSE;
47
48 if ((new_len == 0) || ((new_len % sizeof(WCHAR)) != 0))
49 {
50 rail_unicode_string_free(unicode_string);
51 return TRUE;
52 }
53
54 WCHAR* new_str = realloc(unicode_string->string, new_len);
55 if (!new_str)
56 {
57 rail_unicode_string_free(unicode_string);
58 return FALSE;
59 }
60
61 unicode_string->string = new_str;
62 unicode_string->length = new_len;
63 Stream_Read(s, unicode_string->string, unicode_string->length);
64 if (_wcsnlen(unicode_string->string, unicode_string->length) != unicode_string->length)
65 {
66 WLog_ERR(TAG, "Failed to read UNICODE_STRING, data contains \\0 characters!");
67 return FALSE;
68 }
69 return TRUE;
70}
71
72UINT rail_write_unicode_string_value(wStream* s, const RAIL_UNICODE_STRING* unicode_string)
73{
74 if (!s || !unicode_string)
75 return ERROR_INVALID_PARAMETER;
76
77 const size_t length = unicode_string->length;
78 WINPR_ASSERT((length % sizeof(WCHAR)) == 0);
79 if (length > 0)
80 {
81 if (!Stream_EnsureRemainingCapacity(s, length))
82 {
83 WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
84 return CHANNEL_RC_NO_MEMORY;
85 }
86
87 Stream_Write(s, unicode_string->string, length); /* string */
88 }
89
90 return CHANNEL_RC_OK;
91}
92
93UINT rail_write_unicode_string(wStream* s, const RAIL_UNICODE_STRING* unicode_string)
94{
95 if (!s || !unicode_string)
96 return ERROR_INVALID_PARAMETER;
97
98 if (!Stream_EnsureRemainingCapacity(s, 2 + unicode_string->length))
99 {
100 WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
101 return CHANNEL_RC_NO_MEMORY;
102 }
103
104 Stream_Write_UINT16(s, unicode_string->length); /* cbString (2 bytes) */
105 return rail_write_unicode_string_value(s, unicode_string);
106}
107
108void rail_unicode_string_free(RAIL_UNICODE_STRING* unicode_string)
109{
110 WINPR_ASSERT(unicode_string);
111 free(unicode_string->string);
112 unicode_string->string = nullptr;
113 unicode_string->length = 0;
114}
115
116BOOL utf8_string_to_rail_string(const char* string, RAIL_UNICODE_STRING* unicode_string)
117{
118 WINPR_ASSERT(unicode_string);
119
120 rail_unicode_string_free(unicode_string);
121
122 if (!string || strlen(string) < 1)
123 return TRUE;
124
125 size_t len = 0;
126 WCHAR* buffer = ConvertUtf8ToWCharAlloc(string, &len);
127
128 const size_t wlen = len * sizeof(WCHAR);
129 if (!buffer || (wlen > UINT16_MAX))
130 {
131 free(buffer);
132 return FALSE;
133 }
134
135 unicode_string->string = buffer;
136 unicode_string->length = WINPR_ASSERTING_INT_CAST(UINT16, len * sizeof(WCHAR));
137 return TRUE;
138}
139
140char* rail_string_to_utf8_string(const RAIL_UNICODE_STRING* unicode_string)
141{
142 WINPR_ASSERT(unicode_string);
143 WINPR_ASSERT((unicode_string->length % sizeof(WCHAR)) == 0);
144 WINPR_ASSERT(((unicode_string->length > 0) && (unicode_string->string)) ||
145 (unicode_string->length == 0));
146
147 size_t outLen = 0;
148 size_t inLen = unicode_string->length / sizeof(WCHAR);
149 return ConvertWCharNToUtf8Alloc(unicode_string->string, inLen, &outLen);
150}
151
152/* See [MS-RDPERP] 2.2.1.2.3 Icon Info (TS_ICON_INFO) */
153static BOOL update_read_icon_info(wStream* s, ICON_INFO* iconInfo)
154{
155 BYTE* newBitMask = nullptr;
156
157 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
158 return FALSE;
159
160 Stream_Read_UINT16(s, iconInfo->cacheEntry); /* cacheEntry (2 bytes) */
161 Stream_Read_UINT8(s, iconInfo->cacheId); /* cacheId (1 byte) */
162 Stream_Read_UINT8(s, iconInfo->bpp); /* bpp (1 byte) */
163
164 if ((iconInfo->bpp < 1) || (iconInfo->bpp > 32))
165 {
166 WLog_ERR(TAG, "invalid bpp value %" PRIu32 "", iconInfo->bpp);
167 return FALSE;
168 }
169
170 Stream_Read_UINT16(s, iconInfo->width); /* width (2 bytes) */
171 Stream_Read_UINT16(s, iconInfo->height); /* height (2 bytes) */
172
173 /* cbColorTable is only present when bpp is 1, 4 or 8 */
174 switch (iconInfo->bpp)
175 {
176 case 1:
177 case 4:
178 case 8:
179 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
180 return FALSE;
181
182 Stream_Read_UINT16(s, iconInfo->cbColorTable); /* cbColorTable (2 bytes) */
183 break;
184
185 default:
186 iconInfo->cbColorTable = 0;
187 break;
188 }
189
190 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
191 return FALSE;
192
193 Stream_Read_UINT16(s, iconInfo->cbBitsMask); /* cbBitsMask (2 bytes) */
194 Stream_Read_UINT16(s, iconInfo->cbBitsColor); /* cbBitsColor (2 bytes) */
195
196 /* bitsMask */
197 if (iconInfo->cbBitsMask > 0)
198 {
199 newBitMask = (BYTE*)realloc(iconInfo->bitsMask, iconInfo->cbBitsMask);
200
201 if (!newBitMask)
202 {
203 free(iconInfo->bitsMask);
204 iconInfo->bitsMask = nullptr;
205 return FALSE;
206 }
207
208 iconInfo->bitsMask = newBitMask;
209 if (!Stream_CheckAndLogRequiredLength(TAG, s, iconInfo->cbBitsMask))
210 return FALSE;
211 Stream_Read(s, iconInfo->bitsMask, iconInfo->cbBitsMask);
212 }
213 else
214 {
215 free(iconInfo->bitsMask);
216 iconInfo->bitsMask = nullptr;
217 iconInfo->cbBitsMask = 0;
218 }
219
220 /* colorTable */
221 if (iconInfo->cbColorTable > 0)
222 {
223 BYTE* new_tab = nullptr;
224 new_tab = (BYTE*)realloc(iconInfo->colorTable, iconInfo->cbColorTable);
225
226 if (!new_tab)
227 {
228 free(iconInfo->colorTable);
229 iconInfo->colorTable = nullptr;
230 return FALSE;
231 }
232
233 iconInfo->colorTable = new_tab;
234 }
235 else
236 {
237 free(iconInfo->colorTable);
238 iconInfo->colorTable = nullptr;
239 }
240
241 if (iconInfo->colorTable)
242 {
243 if (!Stream_CheckAndLogRequiredLength(TAG, s, iconInfo->cbColorTable))
244 return FALSE;
245 Stream_Read(s, iconInfo->colorTable, iconInfo->cbColorTable);
246 }
247
248 /* bitsColor */
249 if (iconInfo->cbBitsColor > 0)
250 {
251 newBitMask = (BYTE*)realloc(iconInfo->bitsColor, iconInfo->cbBitsColor);
252
253 if (!newBitMask)
254 {
255 free(iconInfo->bitsColor);
256 iconInfo->bitsColor = nullptr;
257 return FALSE;
258 }
259
260 iconInfo->bitsColor = newBitMask;
261 if (!Stream_CheckAndLogRequiredLength(TAG, s, iconInfo->cbBitsColor))
262 return FALSE;
263 Stream_Read(s, iconInfo->bitsColor, iconInfo->cbBitsColor);
264 }
265 else
266 {
267 free(iconInfo->bitsColor);
268 iconInfo->bitsColor = nullptr;
269 iconInfo->cbBitsColor = 0;
270 }
271 return TRUE;
272}
273
274static BOOL update_read_cached_icon_info(wStream* s, CACHED_ICON_INFO* cachedIconInfo)
275{
276 if (!Stream_CheckAndLogRequiredLength(TAG, s, 3))
277 return FALSE;
278
279 Stream_Read_UINT16(s, cachedIconInfo->cacheEntry); /* cacheEntry (2 bytes) */
280 Stream_Read_UINT8(s, cachedIconInfo->cacheId); /* cacheId (1 byte) */
281 return TRUE;
282}
283
284static BOOL update_read_notify_icon_infotip(wStream* s, NOTIFY_ICON_INFOTIP* notifyIconInfoTip)
285{
286 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
287 return FALSE;
288
289 Stream_Read_UINT32(s, notifyIconInfoTip->timeout); /* timeout (4 bytes) */
290 Stream_Read_UINT32(s, notifyIconInfoTip->flags); /* infoFlags (4 bytes) */
291 return rail_read_unicode_string(s, &notifyIconInfoTip->text) && /* infoTipText */
292 rail_read_unicode_string(s, &notifyIconInfoTip->title); /* title */
293}
294
295static BOOL update_read_window_state_order(wStream* s, WINDOW_ORDER_INFO* orderInfo,
296 WINDOW_STATE_ORDER* windowState)
297{
298 size_t size = 0;
299 RECTANGLE_16* newRect = nullptr;
300
301 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OWNER)
302 {
303 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
304 return FALSE;
305
306 Stream_Read_UINT32(s, windowState->ownerWindowId); /* ownerWindowId (4 bytes) */
307 }
308
309 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_STYLE)
310 {
311 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
312 return FALSE;
313
314 Stream_Read_UINT32(s, windowState->style); /* style (4 bytes) */
315 Stream_Read_UINT32(s, windowState->extendedStyle); /* extendedStyle (4 bytes) */
316 }
317
318 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_SHOW)
319 {
320 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
321 return FALSE;
322
323 Stream_Read_UINT8(s, windowState->showState); /* showState (1 byte) */
324 }
325
326 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE)
327 {
328 if (!rail_read_unicode_string(s, &windowState->titleInfo)) /* titleInfo */
329 return FALSE;
330 }
331
332 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET)
333 {
334 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
335 return FALSE;
336
337 Stream_Read_INT32(s, windowState->clientOffsetX); /* clientOffsetX (4 bytes) */
338 Stream_Read_INT32(s, windowState->clientOffsetY); /* clientOffsetY (4 bytes) */
339 }
340
341 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE)
342 {
343 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
344 return FALSE;
345
346 Stream_Read_UINT32(s, windowState->clientAreaWidth); /* clientAreaWidth (4 bytes) */
347 Stream_Read_UINT32(s, windowState->clientAreaHeight); /* clientAreaHeight (4 bytes) */
348 }
349
350 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_X)
351 {
352 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
353 return FALSE;
354
355 Stream_Read_UINT32(s, windowState->resizeMarginLeft);
356 Stream_Read_UINT32(s, windowState->resizeMarginRight);
357 }
358
359 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_Y)
360 {
361 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
362 return FALSE;
363
364 Stream_Read_UINT32(s, windowState->resizeMarginTop);
365 Stream_Read_UINT32(s, windowState->resizeMarginBottom);
366 }
367
368 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT)
369 {
370 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
371 return FALSE;
372
373 Stream_Read_UINT8(s, windowState->RPContent); /* RPContent (1 byte) */
374 }
375
376 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT)
377 {
378 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
379 return FALSE;
380
381 Stream_Read_UINT32(s, windowState->rootParentHandle); /* rootParentHandle (4 bytes) */
382 }
383
384 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET)
385 {
386 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
387 return FALSE;
388
389 Stream_Read_INT32(s, windowState->windowOffsetX); /* windowOffsetX (4 bytes) */
390 Stream_Read_INT32(s, windowState->windowOffsetY); /* windowOffsetY (4 bytes) */
391 }
392
393 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA)
394 {
395 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
396 return FALSE;
397
398 Stream_Read_INT32(s, windowState->windowClientDeltaX); /* windowClientDeltaX (4 bytes) */
399 Stream_Read_INT32(s, windowState->windowClientDeltaY); /* windowClientDeltaY (4 bytes) */
400 }
401
402 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)
403 {
404 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
405 return FALSE;
406
407 Stream_Read_UINT32(s, windowState->windowWidth); /* windowWidth (4 bytes) */
408 Stream_Read_UINT32(s, windowState->windowHeight); /* windowHeight (4 bytes) */
409 }
410
411 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS)
412 {
413 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
414 return FALSE;
415
416 Stream_Read_UINT16(s, windowState->numWindowRects); /* numWindowRects (2 bytes) */
417
418 if (windowState->numWindowRects > 0)
419 {
420 size = sizeof(RECTANGLE_16) * windowState->numWindowRects;
421 newRect = (RECTANGLE_16*)realloc(windowState->windowRects, size);
422
423 if (!newRect)
424 {
425 free(windowState->windowRects);
426 windowState->windowRects = nullptr;
427 return FALSE;
428 }
429
430 windowState->windowRects = newRect;
431
432 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, windowState->numWindowRects, 8ull))
433 return FALSE;
434
435 /* windowRects */
436 for (UINT32 i = 0; i < windowState->numWindowRects; i++)
437 {
438 Stream_Read_UINT16(s, windowState->windowRects[i].left); /* left (2 bytes) */
439 Stream_Read_UINT16(s, windowState->windowRects[i].top); /* top (2 bytes) */
440 Stream_Read_UINT16(s, windowState->windowRects[i].right); /* right (2 bytes) */
441 Stream_Read_UINT16(s, windowState->windowRects[i].bottom); /* bottom (2 bytes) */
442 }
443 }
444 }
445
446 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET)
447 {
448 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
449 return FALSE;
450
451 Stream_Read_INT32(s, windowState->visibleOffsetX); /* visibleOffsetX (4 bytes) */
452 Stream_Read_INT32(s, windowState->visibleOffsetY); /* visibleOffsetY (4 bytes) */
453 }
454
455 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
456 {
457 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
458 return FALSE;
459
460 Stream_Read_UINT16(s, windowState->numVisibilityRects); /* numVisibilityRects (2 bytes) */
461
462 if (windowState->numVisibilityRects != 0)
463 {
464 size = sizeof(RECTANGLE_16) * windowState->numVisibilityRects;
465 newRect = (RECTANGLE_16*)realloc(windowState->visibilityRects, size);
466
467 if (!newRect)
468 {
469 free(windowState->visibilityRects);
470 windowState->visibilityRects = nullptr;
471 return FALSE;
472 }
473
474 windowState->visibilityRects = newRect;
475
476 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, windowState->numVisibilityRects,
477 8ull))
478 return FALSE;
479
480 /* visibilityRects */
481 for (UINT32 i = 0; i < windowState->numVisibilityRects; i++)
482 {
483 Stream_Read_UINT16(s, windowState->visibilityRects[i].left); /* left (2 bytes) */
484 Stream_Read_UINT16(s, windowState->visibilityRects[i].top); /* top (2 bytes) */
485 Stream_Read_UINT16(s, windowState->visibilityRects[i].right); /* right (2 bytes) */
486 Stream_Read_UINT16(s,
487 windowState->visibilityRects[i].bottom); /* bottom (2 bytes) */
488 }
489 }
490 }
491
492 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OVERLAY_DESCRIPTION)
493 {
494 if (!rail_read_unicode_string(s, &windowState->OverlayDescription))
495 return FALSE;
496 }
497
498 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ICON_OVERLAY_NULL)
499 {
500 /* no data to be read here */
501 }
502
503 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TASKBAR_BUTTON)
504 {
505 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
506 return FALSE;
507
508 Stream_Read_UINT8(s, windowState->TaskbarButton);
509 }
510
511 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ENFORCE_SERVER_ZORDER)
512 {
513 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
514 return FALSE;
515
516 Stream_Read_UINT8(s, windowState->EnforceServerZOrder);
517 }
518
519 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_STATE)
520 {
521 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
522 return FALSE;
523
524 Stream_Read_UINT8(s, windowState->AppBarState);
525 }
526
527 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_EDGE)
528 {
529 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
530 return FALSE;
531
532 Stream_Read_UINT8(s, windowState->AppBarEdge);
533 }
534
535 return TRUE;
536}
537
538static BOOL update_read_window_icon_order(wStream* s, WINDOW_ORDER_INFO* orderInfo,
539 WINDOW_ICON_ORDER* window_icon)
540{
541 WINPR_UNUSED(orderInfo);
542 window_icon->iconInfo = (ICON_INFO*)calloc(1, sizeof(ICON_INFO));
543
544 if (!window_icon->iconInfo)
545 return FALSE;
546
547 return update_read_icon_info(s, window_icon->iconInfo); /* iconInfo (ICON_INFO) */
548}
549
550static BOOL update_read_window_cached_icon_order(wStream* s, WINDOW_ORDER_INFO* orderInfo,
551 WINDOW_CACHED_ICON_ORDER* window_cached_icon)
552{
553 WINPR_UNUSED(orderInfo);
554 return update_read_cached_icon_info(
555 s, &window_cached_icon->cachedIcon); /* cachedIcon (CACHED_ICON_INFO) */
556}
557
558static void update_read_window_delete_order(WINPR_ATTR_UNUSED wStream* s,
559 WINPR_ATTR_UNUSED WINDOW_ORDER_INFO* orderInfo)
560{
561 /* window deletion event */
562}
563
564static BOOL window_order_supported(const rdpSettings* settings, UINT32 fieldFlags)
565{
566 const UINT32 mask = (WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE | WINDOW_ORDER_FIELD_RP_CONTENT |
567 WINDOW_ORDER_FIELD_ROOT_PARENT);
568
569 if (!settings)
570 return FALSE;
571
572 /* See [MS-RDPERP] 2.2.1.1.2 Window List Capability Set */
573 const BOOL dresult =
574 freerdp_settings_get_bool(settings, FreeRDP_AllowUnanouncedOrdersFromServer);
575
576 switch (freerdp_settings_get_uint32(settings, FreeRDP_RemoteWndSupportLevel))
577 {
578 case WINDOW_LEVEL_SUPPORTED_EX:
579 return TRUE;
580
581 case WINDOW_LEVEL_SUPPORTED:
582 return ((fieldFlags & mask) == 0) || dresult;
583
584 case WINDOW_LEVEL_NOT_SUPPORTED:
585 return dresult;
586
587 default:
588 return dresult;
589 }
590}
591
592#define DUMP_APPEND(buffer, size, ...) \
593 do \
594 { \
595 char* b = (buffer); \
596 size_t s = (size); \
597 size_t pos = strnlen(b, s); \
598 (void)_snprintf(&b[pos], s - pos, __VA_ARGS__); \
599 } while (0)
600
601static void dump_window_style(char* buffer, size_t bufferSize, UINT32 style)
602{
603 DUMP_APPEND(buffer, bufferSize, " style=<0x%" PRIx32 ": ", style);
604 if (style & WS_BORDER)
605 DUMP_APPEND(buffer, bufferSize, " border");
606 if (style & WS_CAPTION)
607 DUMP_APPEND(buffer, bufferSize, " caption");
608 if (style & WS_CHILD)
609 DUMP_APPEND(buffer, bufferSize, " child");
610 if (style & WS_CHILDWINDOW)
611 DUMP_APPEND(buffer, bufferSize, " childwindow");
612 if (style & WS_CLIPCHILDREN)
613 DUMP_APPEND(buffer, bufferSize, " clipchildren");
614 if (style & WS_CLIPSIBLINGS)
615 DUMP_APPEND(buffer, bufferSize, " clipsiblings");
616 if (style & WS_DISABLED)
617 DUMP_APPEND(buffer, bufferSize, " disabled");
618 if (style & WS_DLGFRAME)
619 DUMP_APPEND(buffer, bufferSize, " dlgframe");
620 if (style & WS_GROUP)
621 DUMP_APPEND(buffer, bufferSize, " group");
622 if (style & WS_HSCROLL)
623 DUMP_APPEND(buffer, bufferSize, " hscroll");
624 if (style & WS_ICONIC)
625 DUMP_APPEND(buffer, bufferSize, " iconic");
626 if (style & WS_MAXIMIZE)
627 DUMP_APPEND(buffer, bufferSize, " maximize");
628 if (style & WS_MAXIMIZEBOX)
629 DUMP_APPEND(buffer, bufferSize, " maximizebox");
630 if (style & WS_MINIMIZE)
631 DUMP_APPEND(buffer, bufferSize, " minimize");
632 if (style & WS_MINIMIZEBOX)
633 DUMP_APPEND(buffer, bufferSize, " minimizebox");
634 if (style & WS_POPUP)
635 DUMP_APPEND(buffer, bufferSize, " popup");
636 if (style & WS_SIZEBOX)
637 DUMP_APPEND(buffer, bufferSize, " sizebox");
638 if (style & WS_SYSMENU)
639 DUMP_APPEND(buffer, bufferSize, " sysmenu");
640 if (style & WS_TABSTOP)
641 DUMP_APPEND(buffer, bufferSize, " tabstop");
642 if (style & WS_THICKFRAME)
643 DUMP_APPEND(buffer, bufferSize, " thickframe");
644 if (style & WS_VISIBLE)
645 DUMP_APPEND(buffer, bufferSize, " visible");
646 if (style & WS_VSCROLL)
647 DUMP_APPEND(buffer, bufferSize, " vscroll");
648 DUMP_APPEND(buffer, bufferSize, ">");
649}
650
651static void dump_window_style_ex(char* buffer, size_t bufferSize, UINT32 extendedStyle)
652{
653 DUMP_APPEND(buffer, bufferSize, " styleEx=<0x%" PRIx32 ": ", extendedStyle);
654 if (extendedStyle & WS_EX_ACCEPTFILES)
655 DUMP_APPEND(buffer, bufferSize, " acceptfiles");
656 if (extendedStyle & WS_EX_APPWINDOW)
657 DUMP_APPEND(buffer, bufferSize, " appwindow");
658 if (extendedStyle & WS_EX_CLIENTEDGE)
659 DUMP_APPEND(buffer, bufferSize, " clientedge");
660 if (extendedStyle & WS_EX_COMPOSITED)
661 DUMP_APPEND(buffer, bufferSize, " composited");
662 if (extendedStyle & WS_EX_CONTEXTHELP)
663 DUMP_APPEND(buffer, bufferSize, " contexthelp");
664 if (extendedStyle & WS_EX_CONTROLPARENT)
665 DUMP_APPEND(buffer, bufferSize, " controlparent");
666 if (extendedStyle & WS_EX_DLGMODALFRAME)
667 DUMP_APPEND(buffer, bufferSize, " dlgmodalframe");
668 if (extendedStyle & WS_EX_LAYERED)
669 DUMP_APPEND(buffer, bufferSize, " layered");
670 if (extendedStyle & WS_EX_LAYOUTRTL)
671 DUMP_APPEND(buffer, bufferSize, " layoutrtl");
672 if (extendedStyle & WS_EX_LEFT)
673 DUMP_APPEND(buffer, bufferSize, " left");
674 if (extendedStyle & WS_EX_LEFTSCROLLBAR)
675 DUMP_APPEND(buffer, bufferSize, " leftscrollbar");
676 if (extendedStyle & WS_EX_LTRREADING)
677 DUMP_APPEND(buffer, bufferSize, " ltrreading");
678 if (extendedStyle & WS_EX_MDICHILD)
679 DUMP_APPEND(buffer, bufferSize, " mdichild");
680 if (extendedStyle & WS_EX_NOACTIVATE)
681 DUMP_APPEND(buffer, bufferSize, " noactivate");
682 if (extendedStyle & WS_EX_NOINHERITLAYOUT)
683 DUMP_APPEND(buffer, bufferSize, " noinheritlayout");
684#if defined(WS_EX_NOREDIRECTIONBITMAP)
685 if (extendedStyle & WS_EX_NOREDIRECTIONBITMAP)
686 DUMP_APPEND(buffer, bufferSize, " noredirectionbitmap");
687#endif
688 if (extendedStyle & WS_EX_RIGHT)
689 DUMP_APPEND(buffer, bufferSize, " right");
690 if (extendedStyle & WS_EX_RIGHTSCROLLBAR)
691 DUMP_APPEND(buffer, bufferSize, " rightscrollbar");
692 if (extendedStyle & WS_EX_RTLREADING)
693 DUMP_APPEND(buffer, bufferSize, " rtlreading");
694 if (extendedStyle & WS_EX_STATICEDGE)
695 DUMP_APPEND(buffer, bufferSize, " staticedge");
696 if (extendedStyle & WS_EX_TOOLWINDOW)
697 DUMP_APPEND(buffer, bufferSize, " toolWindow");
698 if (extendedStyle & WS_EX_TOPMOST)
699 DUMP_APPEND(buffer, bufferSize, " topMost");
700 if (extendedStyle & WS_EX_TRANSPARENT)
701 DUMP_APPEND(buffer, bufferSize, " transparent");
702 if (extendedStyle & WS_EX_WINDOWEDGE)
703 DUMP_APPEND(buffer, bufferSize, " windowedge");
704 DUMP_APPEND(buffer, bufferSize, ">");
705}
706
707static void dump_window_state_order(wLog* log, const char* msg, const WINDOW_ORDER_INFO* order,
708 const WINDOW_STATE_ORDER* state)
709{
710 char buffer[3000] = WINPR_C_ARRAY_INIT;
711 const size_t bufferSize = sizeof(buffer) - 1;
712
713 (void)_snprintf(buffer, bufferSize, "%s windowId=%" PRIu32 "", msg, order->windowId);
714
715 if (order->fieldFlags & WINDOW_ORDER_FIELD_OWNER)
716 DUMP_APPEND(buffer, bufferSize, " owner=%" PRIu32 "", state->ownerWindowId);
717 if (order->fieldFlags & WINDOW_ORDER_FIELD_STYLE)
718 {
719 dump_window_style(buffer, bufferSize, state->style);
720 dump_window_style_ex(buffer, bufferSize, state->extendedStyle);
721 }
722
723 if (order->fieldFlags & WINDOW_ORDER_FIELD_SHOW)
724 {
725 const char* showStr = nullptr;
726 switch (state->showState)
727 {
728 case 0:
729 showStr = "hidden";
730 break;
731 case 2:
732 showStr = "minimized";
733 break;
734 case 3:
735 showStr = "maximized";
736 break;
737 case 5:
738 showStr = "show";
739 break;
740 default:
741 showStr = "<unknown>";
742 break;
743 }
744 DUMP_APPEND(buffer, bufferSize, " show=%s", showStr);
745 }
746
747 if (order->fieldFlags & WINDOW_ORDER_FIELD_TITLE)
748 {
749 char* title = rail_string_to_utf8_string(&state->titleInfo);
750 if (title)
751 {
752 DUMP_APPEND(buffer, bufferSize, " title=\"%s\"", title);
753 free(title);
754 }
755 else
756 DUMP_APPEND(buffer, bufferSize, " title=<decode failed>");
757 }
758 if (order->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET)
759 DUMP_APPEND(buffer, bufferSize, " clientOffset=(%" PRId32 ",%" PRId32 ")",
760 state->clientOffsetX, state->clientOffsetY);
761 if (order->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE)
762 DUMP_APPEND(buffer, bufferSize, " clientAreaWidth=%" PRIu32 " clientAreaHeight=%" PRIu32 "",
763 state->clientAreaWidth, state->clientAreaHeight);
764 if (order->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_X)
765 DUMP_APPEND(buffer, bufferSize,
766 " resizeMarginLeft=%" PRIu32 " resizeMarginRight=%" PRIu32 "",
767 state->resizeMarginLeft, state->resizeMarginRight);
768 if (order->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_Y)
769 DUMP_APPEND(buffer, bufferSize,
770 " resizeMarginTop=%" PRIu32 " resizeMarginBottom=%" PRIu32 "",
771 state->resizeMarginTop, state->resizeMarginBottom);
772 if (order->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT)
773 DUMP_APPEND(buffer, bufferSize, " rpContent=0x%" PRIx32 "", state->RPContent);
774 if (order->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT)
775 DUMP_APPEND(buffer, bufferSize, " rootParent=0x%" PRIx32 "", state->rootParentHandle);
776 if (order->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET)
777 DUMP_APPEND(buffer, bufferSize, " windowOffset=(%" PRId32 ",%" PRId32 ")",
778 state->windowOffsetX, state->windowOffsetY);
779 if (order->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA)
780 DUMP_APPEND(buffer, bufferSize, " windowClientDelta=(%" PRId32 ",%" PRId32 ")",
781 state->windowClientDeltaX, state->windowClientDeltaY);
782 if (order->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)
783 DUMP_APPEND(buffer, bufferSize, " windowWidth=%" PRIu32 " windowHeight=%" PRIu32 "",
784 state->windowWidth, state->windowHeight);
785
786 if (order->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS)
787 {
788 DUMP_APPEND(buffer, bufferSize, " windowRects=(");
789 for (UINT32 i = 0; i < state->numWindowRects; i++)
790 {
791 DUMP_APPEND(buffer, bufferSize, "(%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ")",
792 state->windowRects[i].left, state->windowRects[i].top,
793 state->windowRects[i].right, state->windowRects[i].bottom);
794 }
795 DUMP_APPEND(buffer, bufferSize, ")");
796 }
797
798 if (order->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET)
799 DUMP_APPEND(buffer, bufferSize, " visibleOffset=(%" PRId32 ",%" PRId32 ")",
800 state->visibleOffsetX, state->visibleOffsetY);
801
802 if (order->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
803 {
804 DUMP_APPEND(buffer, bufferSize, " visibilityRects=(");
805 for (UINT32 i = 0; i < state->numVisibilityRects; i++)
806 {
807 DUMP_APPEND(buffer, bufferSize, "(%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ")",
808 state->visibilityRects[i].left, state->visibilityRects[i].top,
809 state->visibilityRects[i].right, state->visibilityRects[i].bottom);
810 }
811 DUMP_APPEND(buffer, bufferSize, ")");
812 }
813
814 if (order->fieldFlags & WINDOW_ORDER_FIELD_OVERLAY_DESCRIPTION)
815 DUMP_APPEND(buffer, bufferSize, " overlayDescr");
816
817 if (order->fieldFlags & WINDOW_ORDER_FIELD_ICON_OVERLAY_NULL)
818 DUMP_APPEND(buffer, bufferSize, " iconOverlayNull");
819
820 if (order->fieldFlags & WINDOW_ORDER_FIELD_TASKBAR_BUTTON)
821 DUMP_APPEND(buffer, bufferSize, " taskBarButton=0x%" PRIx8 "", state->TaskbarButton);
822
823 if (order->fieldFlags & WINDOW_ORDER_FIELD_ENFORCE_SERVER_ZORDER)
824 DUMP_APPEND(buffer, bufferSize, " enforceServerZOrder=0x%" PRIx8 "",
825 state->EnforceServerZOrder);
826 if (order->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_STATE)
827 DUMP_APPEND(buffer, bufferSize, " appBarState=0x%" PRIx8 "", state->AppBarState);
828 if (order->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_EDGE)
829 {
830 const char* appBarEdgeStr = nullptr;
831 switch (state->AppBarEdge)
832 {
833 case 0:
834 appBarEdgeStr = "left";
835 break;
836 case 1:
837 appBarEdgeStr = "top";
838 break;
839 case 2:
840 appBarEdgeStr = "right";
841 break;
842 case 3:
843 appBarEdgeStr = "bottom";
844 break;
845 default:
846 appBarEdgeStr = "<unknown>";
847 break;
848 }
849 DUMP_APPEND(buffer, bufferSize, " appBarEdge=%s", appBarEdgeStr);
850 }
851
852 WLog_Print(log, WLOG_DEBUG, "%s", buffer);
853}
854
855static BOOL update_recv_window_info_order(rdpUpdate* update, wStream* s,
856 WINDOW_ORDER_INFO* orderInfo)
857{
858 rdp_update_internal* up = update_cast(update);
859 rdpContext* context = update->context;
860 rdpWindowUpdate* window = update->window;
861
862 BOOL result = TRUE;
863
864 WINPR_ASSERT(s);
865 WINPR_ASSERT(context);
866 WINPR_ASSERT(window);
867 WINPR_ASSERT(orderInfo);
868
869 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
870 return FALSE;
871
872 Stream_Read_UINT32(s, orderInfo->windowId); /* windowId (4 bytes) */
873
874 if (orderInfo->fieldFlags & WINDOW_ORDER_ICON)
875 {
876 WINDOW_ICON_ORDER window_icon = WINPR_C_ARRAY_INIT;
877 result = update_read_window_icon_order(s, orderInfo, &window_icon);
878
879 if (result)
880 {
881 WLog_Print(up->log, WLOG_DEBUG, "WindowIcon windowId=0x%" PRIx32 "",
882 orderInfo->windowId);
883 IFCALLRET(window->WindowIcon, result, context, orderInfo, &window_icon);
884 }
885
886 update_free_window_icon_info(window_icon.iconInfo);
887 free(window_icon.iconInfo);
888 }
889 else if (orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON)
890 {
891 WINDOW_CACHED_ICON_ORDER window_cached_icon = WINPR_C_ARRAY_INIT;
892 result = update_read_window_cached_icon_order(s, orderInfo, &window_cached_icon);
893
894 if (result)
895 {
896 WLog_Print(up->log, WLOG_DEBUG, "WindowCachedIcon windowId=0x%" PRIx32 "",
897 orderInfo->windowId);
898 IFCALLRET(window->WindowCachedIcon, result, context, orderInfo, &window_cached_icon);
899 }
900 }
901 else if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_DELETED)
902 {
903 update_read_window_delete_order(s, orderInfo);
904 WLog_Print(up->log, WLOG_DEBUG, "WindowDelete windowId=0x%" PRIx32 "", orderInfo->windowId);
905 IFCALLRET(window->WindowDelete, result, context, orderInfo);
906 }
907 else
908 {
909 WINDOW_STATE_ORDER windowState = WINPR_C_ARRAY_INIT;
910 result = update_read_window_state_order(s, orderInfo, &windowState);
911
912 if (result)
913 {
914 if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW)
915 {
916 dump_window_state_order(up->log, "WindowCreate", orderInfo, &windowState);
917 IFCALLRET(window->WindowCreate, result, context, orderInfo, &windowState);
918 }
919 else
920 {
921 dump_window_state_order(up->log, "WindowUpdate", orderInfo, &windowState);
922 IFCALLRET(window->WindowUpdate, result, context, orderInfo, &windowState);
923 }
924
925 update_free_window_state(&windowState);
926 }
927 }
928
929 return result;
930}
931
932static void update_notify_icon_state_order_free(NOTIFY_ICON_STATE_ORDER* notify)
933{
934 WINPR_ASSERT(notify);
935 rail_unicode_string_free(&notify->toolTip);
936 rail_unicode_string_free(&notify->infoTip.text);
937 rail_unicode_string_free(&notify->infoTip.title);
938 update_free_window_icon_info(&notify->icon);
939 memset(notify, 0, sizeof(NOTIFY_ICON_STATE_ORDER));
940}
941
942static BOOL update_read_notification_icon_state_order(wStream* s, WINDOW_ORDER_INFO* orderInfo,
943 NOTIFY_ICON_STATE_ORDER* notify_icon_state)
944{
945 WINPR_ASSERT(orderInfo);
946 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_VERSION)
947 {
948 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
949 return FALSE;
950
951 Stream_Read_UINT32(s, notify_icon_state->version); /* version (4 bytes) */
952 }
953
954 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP)
955 {
956 if (!rail_read_unicode_string(s,
957 &notify_icon_state->toolTip)) /* toolTip (UNICODE_STRING) */
958 return FALSE;
959 }
960
961 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP)
962 {
963 if (!update_read_notify_icon_infotip(
964 s, &notify_icon_state->infoTip)) /* infoTip (NOTIFY_ICON_INFOTIP) */
965 return FALSE;
966 }
967
968 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_STATE)
969 {
970 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
971 return FALSE;
972
973 Stream_Read_UINT32(s, notify_icon_state->state); /* state (4 bytes) */
974 }
975
976 if (orderInfo->fieldFlags & WINDOW_ORDER_ICON)
977 {
978 if (!update_read_icon_info(s, &notify_icon_state->icon)) /* icon (ICON_INFO) */
979 return FALSE;
980 }
981
982 if (orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON)
983 {
984 if (!update_read_cached_icon_info(
985 s, &notify_icon_state->cachedIcon)) /* cachedIcon (CACHED_ICON_INFO) */
986 return FALSE;
987 }
988
989 return TRUE;
990}
991
992static void
993update_read_notification_icon_delete_order(WINPR_ATTR_UNUSED wStream* s,
994 WINPR_ATTR_UNUSED WINDOW_ORDER_INFO* orderInfo)
995{
996 /* notification icon deletion event */
997}
998
999static BOOL update_recv_notification_icon_info_order(rdpUpdate* update, wStream* s,
1000 WINDOW_ORDER_INFO* orderInfo)
1001{
1002 rdp_update_internal* up = update_cast(update);
1003 rdpContext* context = update->context;
1004 rdpWindowUpdate* window = update->window;
1005 BOOL result = TRUE;
1006
1007 WINPR_ASSERT(s);
1008 WINPR_ASSERT(orderInfo);
1009 WINPR_ASSERT(context);
1010 WINPR_ASSERT(window);
1011
1012 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1013 return FALSE;
1014
1015 Stream_Read_UINT32(s, orderInfo->windowId); /* windowId (4 bytes) */
1016 Stream_Read_UINT32(s, orderInfo->notifyIconId); /* notifyIconId (4 bytes) */
1017
1018 if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_DELETED)
1019 {
1020 update_read_notification_icon_delete_order(s, orderInfo);
1021 WLog_Print(up->log, WLOG_DEBUG, "NotifyIconDelete");
1022 IFCALLRET(window->NotifyIconDelete, result, context, orderInfo);
1023 }
1024 else
1025 {
1026 NOTIFY_ICON_STATE_ORDER notify_icon_state = WINPR_C_ARRAY_INIT;
1027 result = update_read_notification_icon_state_order(s, orderInfo, &notify_icon_state);
1028
1029 if (!result)
1030 goto fail;
1031
1032 if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW)
1033 {
1034 WLog_Print(up->log, WLOG_DEBUG, "NotifyIconCreate");
1035 IFCALLRET(window->NotifyIconCreate, result, context, orderInfo, &notify_icon_state);
1036 }
1037 else
1038 {
1039 WLog_Print(up->log, WLOG_DEBUG, "NotifyIconUpdate");
1040 IFCALLRET(window->NotifyIconUpdate, result, context, orderInfo, &notify_icon_state);
1041 }
1042 fail:
1043 update_notify_icon_state_order_free(&notify_icon_state);
1044 }
1045
1046 return result;
1047}
1048
1049static BOOL update_read_desktop_actively_monitored_order(wStream* s,
1050 const WINDOW_ORDER_INFO* orderInfo,
1051 MONITORED_DESKTOP_ORDER* monitored_desktop)
1052{
1053 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
1054 {
1055 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1056 return FALSE;
1057
1058 Stream_Read_UINT32(s, monitored_desktop->activeWindowId); /* activeWindowId (4 bytes) */
1059 }
1060
1061 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
1062 {
1063 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
1064 return FALSE;
1065
1066 Stream_Read_UINT8(s, monitored_desktop->numWindowIds); /* numWindowIds (1 byte) */
1067
1068 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, monitored_desktop->numWindowIds, 4ull))
1069 {
1070 monitored_desktop->numWindowIds = 0;
1071 return FALSE;
1072 }
1073
1074 if (monitored_desktop->numWindowIds > 0)
1075 {
1076 const size_t size = sizeof(UINT32) * monitored_desktop->numWindowIds;
1077 UINT32* newid = (UINT32*)realloc(monitored_desktop->windowIds, size);
1078
1079 if (!newid)
1080 {
1081 free(monitored_desktop->windowIds);
1082 monitored_desktop->windowIds = nullptr;
1083 monitored_desktop->numWindowIds = 0;
1084 return FALSE;
1085 }
1086
1087 monitored_desktop->windowIds = newid;
1088
1089 /* windowIds */
1090 for (UINT32 i = 0; i < monitored_desktop->numWindowIds; i++)
1091 {
1092 Stream_Read_UINT32(s, monitored_desktop->windowIds[i]);
1093 }
1094 }
1095 else
1096 {
1097 free(monitored_desktop->windowIds);
1098 monitored_desktop->windowIds = nullptr;
1099 }
1100 }
1101
1102 return TRUE;
1103}
1104
1105static void update_read_desktop_non_monitored_order(WINPR_ATTR_UNUSED wStream* s,
1106 WINPR_ATTR_UNUSED WINDOW_ORDER_INFO* orderInfo)
1107{
1108 /* non-monitored desktop notification event */
1109}
1110
1111static void dump_monitored_desktop(wLog* log, const char* msg, const WINDOW_ORDER_INFO* orderInfo,
1112 const MONITORED_DESKTOP_ORDER* monitored)
1113{
1114 char buffer[1000] = WINPR_C_ARRAY_INIT;
1115 const size_t bufferSize = sizeof(buffer) - 1;
1116
1117 DUMP_APPEND(buffer, bufferSize, "%s", msg);
1118
1119 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
1120 DUMP_APPEND(buffer, bufferSize, " activeWindowId=0x%" PRIx32 "", monitored->activeWindowId);
1121
1122 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
1123 {
1124 DUMP_APPEND(buffer, bufferSize, " windows=(");
1125 for (UINT32 i = 0; i < monitored->numWindowIds; i++)
1126 {
1127 WINPR_ASSERT(monitored->windowIds);
1128 DUMP_APPEND(buffer, bufferSize, "0x%" PRIx32 ",", monitored->windowIds[i]);
1129 }
1130 DUMP_APPEND(buffer, bufferSize, ")");
1131 }
1132 WLog_Print(log, WLOG_DEBUG, "%s", buffer);
1133}
1134
1135static BOOL update_recv_desktop_info_order(rdpUpdate* update, wStream* s,
1136 WINDOW_ORDER_INFO* orderInfo)
1137{
1138 rdp_update_internal* up = update_cast(update);
1139 rdpContext* context = update->context;
1140 rdpWindowUpdate* window = update->window;
1141 BOOL result = TRUE;
1142
1143 WINPR_ASSERT(s);
1144 WINPR_ASSERT(orderInfo);
1145 WINPR_ASSERT(context);
1146 WINPR_ASSERT(window);
1147
1148 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_NONE)
1149 {
1150 update_read_desktop_non_monitored_order(s, orderInfo);
1151 WLog_Print(up->log, WLOG_DEBUG, "NonMonitoredDesktop, windowId=0x%" PRIx32 "",
1152 orderInfo->windowId);
1153 IFCALLRET(window->NonMonitoredDesktop, result, context, orderInfo);
1154 }
1155 else
1156 {
1157 MONITORED_DESKTOP_ORDER monitored_desktop = WINPR_C_ARRAY_INIT;
1158 result = update_read_desktop_actively_monitored_order(s, orderInfo, &monitored_desktop);
1159
1160 if (result)
1161 {
1162 dump_monitored_desktop(up->log, "ActivelyMonitoredDesktop", orderInfo,
1163 &monitored_desktop);
1164 IFCALLRET(window->MonitoredDesktop, result, context, orderInfo, &monitored_desktop);
1165 }
1166
1167 free(monitored_desktop.windowIds);
1168 }
1169
1170 return result;
1171}
1172
1173void update_free_window_icon_info(ICON_INFO* iconInfo)
1174{
1175 if (!iconInfo)
1176 return;
1177
1178 free(iconInfo->bitsColor);
1179 iconInfo->bitsColor = nullptr;
1180 free(iconInfo->bitsMask);
1181 iconInfo->bitsMask = nullptr;
1182 free(iconInfo->colorTable);
1183 iconInfo->colorTable = nullptr;
1184}
1185
1186BOOL update_recv_altsec_window_order(rdpUpdate* update, wStream* s)
1187{
1188 BOOL rc = TRUE;
1189 size_t remaining = 0;
1190 UINT16 orderSize = 0;
1191 WINDOW_ORDER_INFO orderInfo = WINPR_C_ARRAY_INIT;
1192 rdp_update_internal* up = update_cast(update);
1193
1194 remaining = Stream_GetRemainingLength(s);
1195
1196 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
1197 return FALSE;
1198
1199 Stream_Read_UINT16(s, orderSize); /* orderSize (2 bytes) */
1200 Stream_Read_UINT32(s, orderInfo.fieldFlags); /* FieldsPresentFlags (4 bytes) */
1201
1202 if (remaining + 1 < orderSize)
1203 {
1204 WLog_Print(up->log, WLOG_ERROR, "Stream short orderSize");
1205 return FALSE;
1206 }
1207
1208 if (!window_order_supported(update->context->settings, orderInfo.fieldFlags))
1209 {
1210 WLog_INFO(TAG, "Window order %08" PRIx32 " not supported!", orderInfo.fieldFlags);
1211 return FALSE;
1212 }
1213
1214 if (orderInfo.fieldFlags & WINDOW_ORDER_TYPE_WINDOW)
1215 rc = update_recv_window_info_order(update, s, &orderInfo);
1216 else if (orderInfo.fieldFlags & WINDOW_ORDER_TYPE_NOTIFY)
1217 rc = update_recv_notification_icon_info_order(update, s, &orderInfo);
1218 else if (orderInfo.fieldFlags & WINDOW_ORDER_TYPE_DESKTOP)
1219 rc = update_recv_desktop_info_order(update, s, &orderInfo);
1220
1221 if (!rc)
1222 WLog_Print(up->log, WLOG_ERROR, "windoworder flags %08" PRIx32 " failed",
1223 orderInfo.fieldFlags);
1224
1225 return rc;
1226}
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.