diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 23782db2e..e348e366c 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -60,7 +60,7 @@ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) RDPGFX_PLUGIN* gfx; RDPGFX_HEADER header; RDPGFX_CAPSET* capsSet; - RDPGFX_CAPSET capsSets[3]; + RDPGFX_CAPSET capsSets[RDPGFX_NUMBER_CAPSETS]; RDPGFX_CAPS_ADVERTISE_PDU pdu; gfx = (RDPGFX_PLUGIN*) callback->plugin; header.flags = 0; @@ -101,6 +101,9 @@ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) if (!gfx->H264) capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; + + capsSets[pdu.capsSetCount] = *capsSet; + capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_102; } header.pduLength = RDPGFX_HEADER_SIZE + 2 + (pdu.capsSetCount * diff --git a/channels/rdpgfx/server/rdpgfx_main.c b/channels/rdpgfx/server/rdpgfx_main.c index 47d2bf4a3..4f6452564 100644 --- a/channels/rdpgfx/server/rdpgfx_main.c +++ b/channels/rdpgfx/server/rdpgfx_main.c @@ -572,6 +572,7 @@ static UINT rdpgfx_write_surface_command(wStream* s, UINT32 bitmapDataStart = 0; UINT32 bitmapDataLength = 0; UINT8 pixelFormat = 0; + switch (cmd->format) { case PIXEL_FORMAT_BGRX32: @@ -1156,8 +1157,7 @@ static UINT rdpgfx_recv_caps_advertise_pdu(RdpgfxServerContext* context, wStream* s) { UINT16 index; - RDPGFX_CAPSET* capsSet; - RDPGFX_CAPSET capsSets[3]; + RDPGFX_CAPSET* capsSets; RDPGFX_CAPS_ADVERTISE_PDU pdu; UINT error = CHANNEL_RC_OK; UINT32 capsDataLength; @@ -1170,24 +1170,22 @@ static UINT rdpgfx_recv_caps_advertise_pdu(RdpgfxServerContext* context, Stream_Read_UINT16(s, pdu.capsSetCount); /* capsSetCount (2 bytes) */ - if (pdu.capsSetCount > 3) - { - /* According to the latest spec, capsSetCount <= 3 */ - WLog_ERR(TAG, "capsSetCount is greater than 3: %u", pdu.capsSetCount); - return ERROR_INVALID_DATA; - } - - if (Stream_GetRemainingLength(s) < (pdu.capsSetCount * 12)) + if (Stream_GetRemainingLength(s) < (pdu.capsSetCount * RDPGFX_CAPSET_SIZE)) { WLog_ERR(TAG, "not enough data!"); return ERROR_INVALID_DATA; } + capsSets = calloc(pdu.capsSetCount, RDPGFX_CAPSET_SIZE); + + if (!capsSets) + return ERROR_OUTOFMEMORY; + pdu.capsSets = (RDPGFX_CAPSET*) capsSets; for (index = 0; index < pdu.capsSetCount; index++) { - capsSet = &(pdu.capsSets[index]); + RDPGFX_CAPSET* capsSet = &(pdu.capsSets[index]); Stream_Read_UINT32(s, capsSet->version); /* version (4 bytes) */ Stream_Read_UINT32(s, capsDataLength); /* capsDataLength (4 bytes) */ @@ -1195,6 +1193,7 @@ static UINT rdpgfx_recv_caps_advertise_pdu(RdpgfxServerContext* context, { WLog_ERR(TAG, "capsDataLength does not equal to 4: %lu", capsDataLength); + free(capsSets); return ERROR_INVALID_DATA; } @@ -1209,6 +1208,7 @@ static UINT rdpgfx_recv_caps_advertise_pdu(RdpgfxServerContext* context, WLog_ERR(TAG, "context->CapsAdvertise failed with error %lu", error); } + free(capsSets); return error; } diff --git a/include/freerdp/channels/rdpgfx.h b/include/freerdp/channels/rdpgfx.h index 97e863fef..7f737a2f8 100644 --- a/include/freerdp/channels/rdpgfx.h +++ b/include/freerdp/channels/rdpgfx.h @@ -92,7 +92,9 @@ typedef struct _RDPGFX_HEADER RDPGFX_HEADER; #define RDPGFX_CAPVERSION_8 0x00080004 #define RDPGFX_CAPVERSION_81 0x00080105 #define RDPGFX_CAPVERSION_10 0x000A0002 +#define RDPGFX_CAPVERSION_102 0x000A0200 +#define RDPGFX_NUMBER_CAPSETS 4 #define RDPGFX_CAPSET_SIZE 12 struct _RDPGFX_CAPSET diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index a536de9f7..3af9eafa0 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -617,19 +617,37 @@ static UINT shadow_client_rdpgfx_qoe_frame_acknowledge(RdpgfxServerContext* * * @return 0 on success, otherwise a Win32 error code */ -static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context, RDPGFX_CAPS_ADVERTISE_PDU* capsAdvertise) +static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context, + RDPGFX_CAPS_ADVERTISE_PDU* capsAdvertise) { UINT16 index; RDPGFX_CAPS_CONFIRM_PDU pdu; rdpSettings* settings = context->rdpcontext->settings; UINT32 flags = 0; - /* Request full screen update for new gfx channel */ - shadow_client_refresh_rect((rdpShadowClient *)context->custom, 0, NULL); + shadow_client_refresh_rect((rdpShadowClient*)context->custom, 0, NULL); for (index = 0; index < capsAdvertise->capsSetCount; index++) { pdu.capsSet = &(capsAdvertise->capsSets[index]); + + if (pdu.capsSet->version == RDPGFX_CAPVERSION_102) + { + if (settings) + { + flags = pdu.capsSet->flags; + settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE); + settings->GfxH264 = !(flags & RDPGFX_CAPS_FLAG_AVC_DISABLED); + } + + return context->CapsConfirm(context, &pdu); + } + } + + for (index = 0; index < capsAdvertise->capsSetCount; index++) + { + pdu.capsSet = &(capsAdvertise->capsSets[index]); + if (pdu.capsSet->version == RDPGFX_CAPVERSION_10) { if (settings) @@ -642,6 +660,7 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context, RD return context->CapsConfirm(context, &pdu); } } + for (index = 0; index < capsAdvertise->capsSetCount; index++) { if (pdu.capsSet->version == RDPGFX_CAPVERSION_81) @@ -657,6 +676,7 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context, RD return context->CapsConfirm(context, &pdu); } } + for (index = 0; index < capsAdvertise->capsSetCount; index++) { if (pdu.capsSet->version == RDPGFX_CAPVERSION_8)