rdpegfx: use 1-based indexing for bitmap cache
authorNorbert Federa <norbert.federa@thincast.com>
Thu, 27 Feb 2020 15:43:01 +0000 (16:43 +0100)
committerNorbert Federa <norbert.federa@thincast.com>
Mon, 2 Mar 2020 08:55:25 +0000 (09:55 +0100)
Weird but Microsoft uses 1-based indexing in the RDPGFX bitmap
cache PDU's.

This does not seem to be documented but can be deducted from the
RDP client test code in Microsoft's "Windows Protocol Test Suites"
GitHub repository and the observation that mstsc aborts with a
protocol error if the cacheSlot index value 0 is used in e.g. a
GFX surface to cache PDU.

channels/rdpgfx/client/rdpgfx_main.c

index 0da0bc0..4979820 100644 (file)
@@ -1991,14 +1991,15 @@ static UINT rdpgfx_set_cache_slot_data(RdpgfxClientContext* context, UINT16 cach
 {
        RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)context->handle;
 
-       if (cacheSlot >= gfx->MaxCacheSlot)
+       /* Microsoft uses 1-based indexing for the egfx bitmap cache ! */
+       if (cacheSlot == 0 || cacheSlot > gfx->MaxCacheSlot)
        {
-               WLog_ERR(TAG, "%s: invalid cache slot %" PRIu16 " maxAllowed=%" PRIu16 "", __FUNCTION__,
+               WLog_ERR(TAG, "%s: invalid cache slot %" PRIu16 ", must be between 1 and %" PRIu16 "", __FUNCTION__,
                         cacheSlot, gfx->MaxCacheSlot);
                return ERROR_INVALID_INDEX;
        }
 
-       gfx->CacheSlots[cacheSlot] = pData;
+       gfx->CacheSlots[cacheSlot - 1] = pData;
        return CHANNEL_RC_OK;
 }
 
@@ -2007,14 +2008,15 @@ static void* rdpgfx_get_cache_slot_data(RdpgfxClientContext* context, UINT16 cac
        void* pData = NULL;
        RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)context->handle;
 
-       if (cacheSlot >= gfx->MaxCacheSlot)
+       /* Microsoft uses 1-based indexing for the egfx bitmap cache ! */
+       if (cacheSlot == 0 || cacheSlot > gfx->MaxCacheSlot)
        {
-               WLog_ERR(TAG, "%s: invalid cache slot %" PRIu16 " maxAllowed=%" PRIu16 "", __FUNCTION__,
+               WLog_ERR(TAG, "%s: invalid cache slot %" PRIu16 ", must be between 1 and %" PRIu16 "", __FUNCTION__,
                         cacheSlot, gfx->MaxCacheSlot);
                return NULL;
        }
 
-       pData = gfx->CacheSlots[cacheSlot];
+       pData = gfx->CacheSlots[cacheSlot - 1];
        return pData;
 }