The TS_FP_SURFCMDS structure is the fast-path variant of the TS_UPDATE_SURFCMDS (section 2.2.9.1.1.3.1.4) structure.
Inheritance: TS_FP_UPDATE
        /// <summary>
        /// Parse TS_FP_SURFCMDS
        /// </summary>
        /// <param name="updateHeader">update header</param>
        /// <param name="compressionFlags">compression flags</param>
        /// <param name="size">update data size(before decompression)</param>
        /// <param name="updateData">update data(decompressed)</param>
        /// <returns>TS_FP_SURFCMDS</returns>
        private TS_FP_SURFCMDS ParseTsFpSurfCmds(
            byte updateHeader,
            compressedType_Values compressionFlags,
            UInt16 size,
            byte[] updateData)
        {
            TS_FP_SURFCMDS cmds = new TS_FP_SURFCMDS();

            // TS_FP_SURFCMDS: updateHeader
            cmds.updateHeader = updateHeader;

            // TS_FP_SURFCMDS: compressionFlags
            cmds.compressionFlags = compressionFlags;

            // TS_FP_SURFCMDS: size
            cmds.size = size;

            // TS_FP_SURFCMDS: surfaceCommands
            int index = 0;
            cmds.surfaceCommands = ParseTsSurfCmd(updateData, ref index);

            // Check if data length exceeded expectation
            VerifyDataLength(updateData.Length, index, ConstValue.ERROR_MESSAGE_DATA_LENGTH_EXCEEDED);
            return cmds;
        }
        private byte[] EncodeSurfCmds(TS_FP_SURFCMDS surfCmdsData)
        {
            List<byte> totalBuffer = new List<byte>();
            List<byte> buffer = new List<byte>();

            if (surfCmdsData.surfaceCommands != null)
            {
                for (int i = 0; i < surfCmdsData.surfaceCommands.Length; ++i)
                {
                    if (surfCmdsData.surfaceCommands[i].GetType() == typeof(TS_SURFCMD_SET_SURF_BITS))
                    {
                        RdpbcgrEncoder.EncodeBytes(
                            buffer, EncodeSurfBits((TS_SURFCMD_SET_SURF_BITS)surfCmdsData.surfaceCommands[i]));
                    }
                    else if (surfCmdsData.surfaceCommands[i].GetType() == typeof(TS_SURFCMD_STREAM_SURF_BITS))
                    {
                        RdpbcgrEncoder.EncodeBytes(
                            buffer, EncodeSurfStream((TS_SURFCMD_STREAM_SURF_BITS)surfCmdsData.surfaceCommands[i]));
                    }
                    else
                    {
                        RdpbcgrEncoder.EncodeBytes(
                            buffer, EncodeSurfFrameMaker((TS_FRAME_MARKER)surfCmdsData.surfaceCommands[i]));
                    }

                }
            }

            if (surfCmdsData.compressionFlags != compressedType_Values.None)
            {
                RdpbcgrEncoder.EncodeBytes(
                    totalBuffer, serverSessionContext.Compress(surfCmdsData.compressionFlags, buffer.ToArray()));
            }
            else
            {
                RdpbcgrEncoder.EncodeBytes(totalBuffer, buffer.ToArray());
            }

            return totalBuffer.ToArray();
        }
        /// <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);
            }
        }
        public static TS_FP_SURFCMDS CreateFPSurfCmds(TS_SURFCMD_SET_SURF_BITS setSurfBits)
        {
            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;
            surfCmds.surfaceCommands = new TS_SURFCMD[1];
            surfCmds.surfaceCommands[0] = setSurfBits;
            surfCmds.size = (ushort)(22 + setSurfBits.bitmapData.bitmapDataLength);

            return surfCmds;
        }