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