The TS_BITMAPCACHE_CAPABILITYSET_REV2 structure is used to advertise support for Revision 2 Bitmap Caches (see [MS-RDPEGDI] section 3.1.1.1.1). This capability is only sent from client to server. In addition to specifying bitmap caching parameters in the Revision 2 Bitmap Cache Capability Set, a client MUST also support the MemBlt and Mem3Blt Primary Drawing Orders (see [MS-RDPEGDI] sections 2.2.2.2.1.1.2.9 and 2.2.2.2.1.1.2.10 respectively) in order to receive the Cache Bitmap (Revision 2) Secondary Drawing Order (see [MS-RDPEGDI] section 2.2.2.2.1.2.3).
file:///C:/ts_dev/TestSuites/MS-RDPBCGR/TestSuite/Src/TD/latest_XMLS_16may/RDPBCGR/ _rfc_ms-rdpbcgr2_1_6_1_5_2.xml
        /// <summary>
        /// Method to receive and decode client capabilities.
        /// </summary>
        /// <param name="serverMaxRequestSize">The MaxRequestSize field of the server-to-client Multifragment Update Capability Set. </param>
        /// <param name="supportedRfxCaps">Output the TS_RFX_ICAP array supported by the client.</param>
        public void ReceiveAndCheckClientCapabilities(uint serverMaxRequestSize, out TS_RFX_ICAP[] supportedRfxCaps)
        {
            supportedRfxCaps = null;
            s2cMaxRequestSize = serverMaxRequestSize;
            ConfirmCapabilitySets =  this.rdpbcgrSessionContext.ConfirmCapabilitySets;
            foreach (ITsCapsSet capSet in ConfirmCapabilitySets)
            {
                if (capSet is TS_MULTIFRAGMENTUPDATE_CAPABILITYSET)
                {
                    this.is_Client_Multifragment_Update_CapabilitySet_Received = true;
                    this.client_Multifragment_Update_CapabilitySet = (TS_MULTIFRAGMENTUPDATE_CAPABILITYSET)capSet;
                }
                else if (capSet is TS_LARGE_POINTER_CAPABILITYSET)
                {
                    this.is_Client_Large_Pointer_Capability_Set_Received = true;
                    this.client_Large_Pointer_Capability_Set = (TS_LARGE_POINTER_CAPABILITYSET)capSet;
                }
                else if (capSet is TS_BITMAPCACHE_CAPABILITYSET_REV2)
                {
                    this.is_Client_Revision2_Bitmap_Cache_Capability_Set_Received = true;
                    this.client_Revision2_Bitmap_Cache_Capability_Set = (TS_BITMAPCACHE_CAPABILITYSET_REV2)capSet;
                }
                else if (capSet is TS_FRAME_ACKNOWLEDGE_CAPABILITYSET)
                {
                    this.is_TS_FRAME_ACKNOWLEDGE_CAPABILITYSET_Received = true;
                    this.clientTS_FRAME_ACKNOWLEDGE_CAPABILITYSET = (TS_FRAME_ACKNOWLEDGE_CAPABILITYSET)capSet;
                }
                else if (capSet is TS_SURFCMDS_CAPABILITYSET)
                {
                    this.is_Client_Surface_Commands_Capability_Set_Received = true;
                    this.client_Surface_Commands_Capability_Set = (TS_SURFCMDS_CAPABILITYSET)capSet;
                    if ((this.client_Surface_Commands_Capability_Set.cmdFlags & CmdFlags_Values.SURFCMDS_STREAMSURFACEBITS) == CmdFlags_Values.SURFCMDS_STREAMSURFACEBITS)
                    {
                        this.clientupportStreamSurfaceBits = true;
                    }
                }
                else if (capSet is TS_BITMAPCODECS_CAPABILITYSET)
                {
                    this.is_Client_Bitmap_Codecs_Capability_Set_Received = true;
                    this.client_Bitmap_Codecs_Capability_Set = (TS_BITMAPCODECS_CAPABILITYSET)capSet;
                    foreach (TS_BITMAPCODEC codec in this.client_Bitmap_Codecs_Capability_Set.supportedBitmapCodecs.bitmapCodecArray)
                    {
                        if (is_REMOTEFX_CODEC_GUID(codec.codecGUID))
                        {
                            is_TS_RFX_CLNT_CAPS_CONTAINER_Received = true;
                            remoteFXCodecID = codec.codecID;
                            this.client_RFX_Caps_Container =  rdprfxServerDecoder.Decode_TS_RFX_CLNT_CAPS_CONTAINER(codec.codecProperties);
                            supportedRfxCaps = this.client_RFX_Caps_Container.capsData.capsetsData[0].icapsData;
                            break;
                        }
                    }
                }
            }

            //Verify Client Capabilities
            VerifyClientCapabilities();
        }
        /// <summary>
        /// 2.2.7.1.4.2
        /// </summary>
        /// <param name="cache2"></param>
        public void VerifyStructure(TS_BITMAPCACHE_CAPABILITYSET_REV2 cache2)
        {
            site.CaptureRequirementIfAreEqual<capabilitySetType_Values>(capabilitySetType_Values.CAPSTYPE_BITMAPCACHE_REV2, cache2.capabilitySetType, 1248,
                @"In TS_BITMAPCACHE_CAPABILITYSET_REV2 structure capabilitySetType field MUST be set to "
                + @"CAPSTYPE_BITMAPCACHE_REV2 (19).");
            bool isR1252Satisfied = cache2.CacheFlags == CacheFlags_Values.ALLOW_CACHE_WAITING_LIST_FLAG ||
                cache2.CacheFlags == CacheFlags_Values.PERSISTENT_KEYS_EXPECTED_FLAG ||
                cache2.CacheFlags == (CacheFlags_Values.ALLOW_CACHE_WAITING_LIST_FLAG | CacheFlags_Values.PERSISTENT_KEYS_EXPECTED_FLAG) ||
                cache2.CacheFlags == CacheFlags_Values.None;
            site.CaptureRequirementIfIsTrue(isR1252Satisfied, 1252,
                @"In TS_BITMAPCACHE_CAPABILITYSET_REV2 structure,  the CacheFlags can be of the following"
                + @" PERSISTENT_KEYS_EXPECTED_FLAG 0x0001, ALLOW_CACHE_WAITING_LIST_FLAG 0x0002, None 0x0000");

            site.CaptureRequirementIfIsTrue(cache2.NumCellCaches <= 5, 1258,
                @"In TS_BITMAPCACHE_CAPABILITYSET_REV2 structure, the NumCellCaches field is the number of"
                + @" bitmap caches (with a maximum allowed value of 5). ");

            if (cache2.NumCellCaches >= 1)
            {
                //<?>
                CaptureRequirement((cache2.BitmapCache1CellInfo.NumEntriesAndK & 0xfffffff) <= 600, 1260);
            }

            if (cache2.NumCellCaches>=2)
            {
                //<?>
                CaptureRequirement((cache2.BitmapCache2CellInfo.NumEntriesAndK & 0xfffffff) <= 600, 1263);
            }

            if (cache2.NumCellCaches >= 3)
            {
                //<?>
                CaptureRequirement((cache2.BitmapCache3CellInfo.NumEntriesAndK & 0xfffffff) <= 65536, 1266);
            }

            if (cache2.NumCellCaches >= 4)
            {
                //<?>
                CaptureRequirement((cache2.BitmapCache4CellInfo.NumEntriesAndK & 0xfffffff) <= 4096, 1269);
            }

            if (cache2.NumCellCaches >= 5)
            {
                //<?>
                CaptureRequirement((cache2.BitmapCache5CellInfo.NumEntriesAndK & 0xfffffff) <= 2048, 1272);
            }
        }
        /// <summary>
        /// Parse TS_BITMAPCACHE_CAPABILITYSET_REV2
        /// </summary>
        /// <param name="data">data to be parsed</param>
        /// <returns>TS_BITMAPCACHE_CAPABILITYSET_REV2</returns>
        private TS_BITMAPCACHE_CAPABILITYSET_REV2 ParseCapsTypeBitmapCacheRev2(byte[] data)
        {
            int currentIndex = 0;
            TS_BITMAPCACHE_CAPABILITYSET_REV2 set = new TS_BITMAPCACHE_CAPABILITYSET_REV2();
            set.capabilitySetType = (capabilitySetType_Values)ParseUInt16(data, ref currentIndex, false);
            set.lengthCapability = ParseUInt16(data, ref currentIndex, false);
            set.CacheFlags = (CacheFlags_Values)ParseUInt16(data, ref currentIndex, false);
            set.pad2 = ParseByte(data, ref currentIndex);
            set.NumCellCaches = ParseByte(data, ref currentIndex);
            set.BitmapCache1CellInfo = ParseBitmapCacheCellInfo(data, ref currentIndex);
            set.BitmapCache2CellInfo = ParseBitmapCacheCellInfo(data, ref currentIndex);
            set.BitmapCache3CellInfo = ParseBitmapCacheCellInfo(data, ref currentIndex);
            set.BitmapCache4CellInfo = ParseBitmapCacheCellInfo(data, ref currentIndex);
            set.BitmapCache5CellInfo = ParseBitmapCacheCellInfo(data, ref currentIndex);
            set.Pad3 = GetBytes(data, ref currentIndex, 12);

            // Check if data length is consistent with the decoded struct length
            VerifyDataLength(data.Length, currentIndex, ConstValue.ERROR_MESSAGE_DATA_LENGTH_INCONSISTENT);
            return set;
        }