Coverage Report

Created: 2025-07-01 06:46

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