diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index c00eb9314..54ea65533 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -753,6 +753,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL; #define FreeRDP_RemoteAppNumIconCaches (2122) #define FreeRDP_RemoteAppNumIconCacheEntries (2123) #define FreeRDP_RemoteAppLanguageBarSupported (2124) +#define FreeRDP_RemoteWndSupportLevel (2125) #define FreeRDP_ReceivedCapabilities (2240) #define FreeRDP_ReceivedCapabilitiesSize (2241) #define FreeRDP_OsMajorType (2304) @@ -1248,7 +1249,8 @@ struct rdp_settings ALIGN64 UINT32 RemoteAppNumIconCaches; /* 2122 */ ALIGN64 UINT32 RemoteAppNumIconCacheEntries; /* 2123 */ ALIGN64 BOOL RemoteAppLanguageBarSupported; /* 2124 */ - UINT64 padding2176[2176 - 2125]; /* 2125 */ + ALIGN64 UINT32 RemoteWndSupportLevel; /* 2125 */ + UINT64 padding2176[2176 - 2126]; /* 2126 */ UINT64 padding2240[2240 - 2176]; /* 2176 */ /** diff --git a/libfreerdp/core/capabilities.c b/libfreerdp/core/capabilities.c index a811160fb..c33301281 100644 --- a/libfreerdp/core/capabilities.c +++ b/libfreerdp/core/capabilities.c @@ -2244,7 +2244,7 @@ static BOOL rdp_read_window_list_capability_set(wStream* s, UINT16 length, if (length < 11) return FALSE; - Stream_Seek_UINT32(s); /* wndSupportLevel (4 bytes) */ + Stream_Read_UINT32(s, settings->RemoteWndSupportLevel); /* wndSupportLevel (4 bytes) */ Stream_Read_UINT8(s, settings->RemoteAppNumIconCaches); /* numIconCaches (1 byte) */ Stream_Read_UINT16(s, settings->RemoteAppNumIconCacheEntries); /* numIconCacheEntries (2 bytes) */ return TRUE; @@ -2260,14 +2260,12 @@ static BOOL rdp_read_window_list_capability_set(wStream* s, UINT16 length, static BOOL rdp_write_window_list_capability_set(wStream* s, rdpSettings* settings) { int header; - UINT32 wndSupportLevel; if (!Stream_EnsureRemainingCapacity(s, 32)) return FALSE; header = rdp_capability_set_start(s); - wndSupportLevel = WINDOW_LEVEL_SUPPORTED_EX; - Stream_Write_UINT32(s, wndSupportLevel); /* wndSupportLevel (4 bytes) */ + Stream_Write_UINT32(s, settings->RemoteWndSupportLevel); /* wndSupportLevel (4 bytes) */ Stream_Write_UINT8(s, settings->RemoteAppNumIconCaches); /* numIconCaches (1 byte) */ Stream_Write_UINT16(s, settings->RemoteAppNumIconCacheEntries); /* numIconCacheEntries (2 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_WINDOW); diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c index 7b04cfe75..6af74c65a 100644 --- a/libfreerdp/core/orders.c +++ b/libfreerdp/core/orders.c @@ -168,9 +168,12 @@ static BOOL check_alt_order_supported(wLog* log, rdpSettings* settings, BYTE ord condition = settings->DrawGdiPlusCacheEnabled; break; + case ORDER_TYPE_WINDOW: + condition = settings->RemoteWndSupportLevel != WINDOW_LEVEL_NOT_SUPPORTED; + break; + case ORDER_TYPE_STREAM_BITMAP_FIRST: case ORDER_TYPE_STREAM_BITMAP_NEXT: - case ORDER_TYPE_WINDOW: case ORDER_TYPE_COMPDESK_FIRST: condition = TRUE; break; diff --git a/libfreerdp/core/settings.c b/libfreerdp/core/settings.c index e7798459b..1e2b453dd 100644 --- a/libfreerdp/core/settings.c +++ b/libfreerdp/core/settings.c @@ -497,6 +497,7 @@ rdpSettings* freerdp_settings_new(DWORD flags) if (!settings->ClientDir) goto out_fail; + settings->RemoteWndSupportLevel = WINDOW_LEVEL_SUPPORTED_EX; settings->RemoteAppNumIconCaches = 3; settings->RemoteAppNumIconCacheEntries = 12; settings->VirtualChannelChunkSize = CHANNEL_CHUNK_LENGTH; diff --git a/libfreerdp/core/window.c b/libfreerdp/core/window.c index 06fa87e0c..f2e18c576 100644 --- a/libfreerdp/core/window.c +++ b/libfreerdp/core/window.c @@ -405,6 +405,31 @@ static void update_read_window_delete_order(wStream* s, WINDOW_ORDER_INFO* order /* window deletion event */ } +static BOOL window_order_supported(const rdpSettings* settings, UINT32 fieldFlags) +{ + const UINT32 mask = (WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE || WINDOW_ORDER_FIELD_RP_CONTENT || + WINDOW_ORDER_FIELD_ROOT_PARENT); + + if (!settings) + return FALSE; + + /* See [MS-RDPERP] 2.2.1.1.2 Window List Capability Set */ + switch (settings->RemoteWndSupportLevel) + { + case WINDOW_LEVEL_SUPPORTED_EX: + return TRUE; + + case WINDOW_LEVEL_SUPPORTED: + return (fieldFlags & mask) == 0; + + case WINDOW_LEVEL_NOT_SUPPORTED: + return FALSE; + + default: + return FALSE; + } +} + static BOOL update_recv_window_info_order(rdpUpdate* update, wStream* s, WINDOW_ORDER_INFO* orderInfo) { @@ -661,6 +686,9 @@ BOOL update_recv_altsec_window_order(rdpUpdate* update, wStream* s) Stream_Read_UINT16(s, orderSize); /* orderSize (2 bytes) */ Stream_Read_UINT32(s, window->orderInfo.fieldFlags); /* FieldsPresentFlags (4 bytes) */ + if (!window_order_supported(update->context->settings, window->orderInfo.fieldFlags)) + return FALSE; + if (window->orderInfo.fieldFlags & WINDOW_ORDER_TYPE_WINDOW) rc = update_recv_window_info_order(update, s, &window->orderInfo); else if (window->orderInfo.fieldFlags & WINDOW_ORDER_TYPE_NOTIFY)