The TS_FP_UPDATE structure is used to describe and encapsulate the data for a fast-path update sent from server to client. All fast-path updates conform to this basic structure (see sections to ).
file:///C:/ts_dev/TestSuites/MS-RDPBCGR/TestSuite/Src/TD/latest_XMLS_16may/RDPBCGR/ _rfc_ms-rdpbcgr2_1_8_1_2_1.xml
        /// <summary>
        /// Method to send RDPRFX raw data.
        /// </summary>
        /// <param name="surfStreamCmd">TS_SURFCMD_STREAM_SURF_BITS to be send.</param>
        private void SendSurfaceCmd_StreamSurfBits(TS_SURFCMD_STREAM_SURF_BITS surfStreamCmd)
        {
            if (rdpbcgrAdapter != null)
            {
                rdpbcgrAdapter.SendStreamSurfaceBitsCommand(surfStreamCmd);
            }
            else if (this.rdpbcgrServerStack != null && this.rdpbcgrSessionContext != null)
            {
                //TS_FRAME_MARKER frameMakerCmdBegin = new TS_FRAME_MARKER();
                //frameMakerCmdBegin.cmdType = cmdType_Values.CMDTYPE_FRAME_MARKER;
                //frameMakerCmdBegin.frameAction = frameAction_Values.SURFACECMD_FRAMEACTION_BEGIN;
                //frameMakerCmdBegin.frameId = frameIndex;

                //TS_FRAME_MARKER frameMakerCmdEnd = new TS_FRAME_MARKER();
                //frameMakerCmdEnd.cmdType = cmdType_Values.CMDTYPE_FRAME_MARKER;
                //frameMakerCmdEnd.frameAction = frameAction_Values.SURFACECMD_FRAMEACTION_END;
                //frameMakerCmdEnd.frameId = frameIndex++;

                TS_FP_SURFCMDS surfCmds = new TS_FP_SURFCMDS();
                surfCmds.updateHeader = (byte)(((int)updateCode_Values.FASTPATH_UPDATETYPE_SURFCMDS & 0x0f)
                | (((int)fragmentation_Value.FASTPATH_FRAGMENT_SINGLE) << 4)
                | ((int)compressedType_Values.None << 6));
                surfCmds.compressionFlags = compressedType_Values.None;
                int subLength = 8 + 8 + 22;
                if(surfStreamCmd.bitmapData.exBitmapDataHeader != null)
                {
                    subLength += 24;
                }
                surfCmds.size = (ushort)(subLength + surfStreamCmd.bitmapData.bitmapDataLength);//size of TS_SURFCMD_STREAM_SURF_BITS;
                surfCmds.surfaceCommands = new TS_SURFCMD[1];
                surfCmds.surfaceCommands[0] = surfStreamCmd;

                TS_FP_UPDATE_PDU fpOutput;
                TS_FP_UPDATE[] updates = new TS_FP_UPDATE[1];
                updates[0] = surfCmds;
                fpOutput = rdpbcgrServerStack.CreateFastPathUpdatePdu(rdpbcgrSessionContext, updates);
                rdpbcgrServerStack.SendPdu(rdpbcgrSessionContext, fpOutput);
            }
        }
        /// <summary>
        /// Parse TS_FP_UPDATE array
        /// (parser index is updated according to parsed length)
        /// </summary>
        /// <param name="data">data to be parsed</param>
        /// <param name="currentIndex">current parser index</param>
        /// <returns>parsed TS_FP_UPDATE array</returns>
        private TS_FP_UPDATE[] ParseTsFpUpdates(byte[] data, ref int currentIndex)
        {
            List<TS_FP_UPDATE> listUpdate = new List<TS_FP_UPDATE>();

            // One by one parse TS_FP_UPDATE
            while (currentIndex < data.Length)
            {
                TS_FP_UPDATE update = null;

                // Update header
                byte updateHeader = ParseByte(data, ref currentIndex);

                // Get infomation from updateHeader
                updateCode_Values updateCode;
                fragmentation_Value fragmentation;
                compression_Values compression;
                GetFpUpdateHeaderInfo(updateHeader, out updateCode, out fragmentation, out compression);

                // Get compressionFlags (optional)
                compressedType_Values compressionFlags = 0;
                if (compression_Values.FASTPATH_OUTPUT_COMPRESSION_USED == compression)
                {
                    compressionFlags = (compressedType_Values)ParseByte(data, ref currentIndex);
                }

                // Get size and update data
                UInt16 updateDataSize = ParseUInt16(data, ref currentIndex, false);
                byte[] updateData = GetBytes(data, ref currentIndex, updateDataSize);

                // Decompress update data (according to compressionFlags)
                byte[] decompressedUpdateData = clientContext.Decompress(updateData, compressionFlags);

                // Parse fast-path updates by updateCode
                switch (updateCode)
                {
                    // Fast-Path Orders Update
                    case updateCode_Values.FASTPATH_UPDATETYPE_ORDERS:
                        update = ParseTsFpUpdateOrders(updateHeader, compressionFlags,
                            updateDataSize, decompressedUpdateData);
                        break;

                    // Fast-Path Bitmap Update
                    case updateCode_Values.FASTPATH_UPDATETYPE_BITMAP:
                        update = ParseTsFpUpdateBitmap(updateHeader, compressionFlags,
                            updateDataSize, decompressedUpdateData);
                        break;

                    // Fast-Path Palette Update
                    case updateCode_Values.FASTPATH_UPDATETYPE_PALETTE:
                        update = ParseTsFpUpdatePalette(updateHeader, compressionFlags,
                            updateDataSize, decompressedUpdateData);
                        break;

                    // Fast-Path Synchronize Update
                    case updateCode_Values.FASTPATH_UPDATETYPE_SYNCHRONIZE:
                        update = ParseTsFpUpdateSynchronize(
                            updateHeader, compressionFlags, updateDataSize);
                        break;

                    // Fast-Path Surface commands Update
                    case updateCode_Values.FASTPATH_UPDATETYPE_SURFCMDS:
                        update = ParseTsFpSurfCmds(updateHeader, compressionFlags,
                            updateDataSize, decompressedUpdateData);
                        break;

                    // Fast-Path System Pointer Hidden Update
                    case updateCode_Values.FASTPATH_UPDATETYPE_PTR_NULL:
                        update = ParseTsFpSystemPointerHiddenAttribute(
                            updateHeader, compressionFlags, updateDataSize);
                        break;

                    // Fast-Path System Pointer Default Update
                    case updateCode_Values.FASTPATH_UPDATETYPE_PTR_DEFAULT:
                        update = ParseTsFpSystemPointerDefaultAttribute(
                            updateHeader, compressionFlags, updateDataSize);
                        break;

                    // Fast-Path Pointer Position Update
                    case updateCode_Values.FASTPATH_UPDATETYPE_PTR_POSITION:
                        update = ParseTsFpPointerPosAttribute(updateHeader, compressionFlags,
                            updateDataSize, decompressedUpdateData);
                        break;

                    // Fast-Path Color Pointer Update
                    case updateCode_Values.FASTPATH_UPDATETYPE_COLOR:
                        update = ParseTsFpColorPointerAttribute(updateHeader, compressionFlags,
                            updateDataSize, decompressedUpdateData);
                        break;

                    // Fast-Path Cached Pointer Update
                    case updateCode_Values.FASTPATH_UPDATETYPE_CACHED:
                        update = ParseTsFpCachedPointerAttribute(updateHeader, compressionFlags,
                            updateDataSize, decompressedUpdateData);
                        break;

                    // Fast-Path New Pointer Update
                    case updateCode_Values.FASTPATH_UPDATETYPE_POINTER:
                        update = ParseTsFpPointerAttribute(updateHeader, compressionFlags,
                            updateDataSize, decompressedUpdateData);
                        break;

                    default:
                        throw new FormatException(ConstValue.ERROR_MESSAGE_ENUM_UNRECOGNIZED);
                }
                listUpdate.Add(update);
            }

            // Copy list to array
            TS_FP_UPDATE[] updates = new TS_FP_UPDATE[listUpdate.Count];
            for (int i = 0; i < updates.Length; i++)
            {
                updates[i] = listUpdate[i];
            }
            return updates;
        }
        public static TS_FP_UPDATE_PDU CreateFPUpdatePDU(RdpbcgrServerSessionContext context, TS_FP_UPDATE update)
        {
            TS_FP_UPDATE_PDU fpOutput = new TS_FP_UPDATE_PDU(context);

            fpOutput.fpOutputHeader = (byte)(((int)nested_TS_FP_UPDATE_PDU_fpOutputHeader_actionCode_Values.FASTPATH_OUTPUT_ACTION_FASTPATH & 0x03)
                | ((int)((int)reserved_Values.V1 & 0x0f) << 2));
            fpOutput.dataSignature = null;
            fpOutput.length1 = 0;
            fpOutput.length2 = 0;

            fpOutput.fpOutputUpdates = new TS_FP_UPDATE[1];
            fpOutput.fpOutputUpdates[0] = update;

            return fpOutput;
        }