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