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