/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, ¬ifyIconInfoTip->text) && /* infoTipText */ |
245 | 0 | rail_read_unicode_string(s, ¬ifyIconInfoTip->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(¬ify->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 | ¬ify_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, ¬ify_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, ¬ify_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, ¬ify_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, ¬ify_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, ¬ify_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, ¬ify_icon_state); |
992 | 0 | } |
993 | 0 | fail: |
994 | 0 | update_notify_icon_state_order_free(¬ify_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 | } |