/// <summary>
        /// Decode one PDU
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static RdpegfxPdu DecodeSinglePdu(byte[] data)
        {
            RdpegfxPdu pdu     = new RdpegfxPdu();
            bool       fResult = PduMarshaler.Unmarshal(data, pdu);

            if (fResult)
            {
                RdpegfxServerPdu receivedPdu = null;
                if (pdu.Header.cmdId == PacketTypeValues.RDPGFX_CMDID_WIRETOSURFACE_1)
                {
                    receivedPdu = new RDPGFX_WIRE_TO_SURFACE_PDU_1();
                }
                else if (pdu.Header.cmdId == PacketTypeValues.RDPGFX_CMDID_WIRETOSURFACE_2)
                {
                    receivedPdu = new RDPGFX_WIRE_TO_SURFACE_PDU_2();
                }
                else if (pdu.Header.cmdId == PacketTypeValues.RDPGFX_CMDID_DELETEENCODINGCONTEXT)
                {
                    receivedPdu = new RDPGFX_DELETE_ENCODING_CONTEXT();
                }
                else if (pdu.Header.cmdId == PacketTypeValues.RDPGFX_CMDID_SOLIDFILL)
                {
                    receivedPdu = new RDPGFX_SOLIDFILL();
                }
                else if (pdu.Header.cmdId == PacketTypeValues.RDPGFX_CMDID_SURFACETOSURFACE)
                {
                    receivedPdu = new RDPGFX_SURFACE_TO_SURFACE();
                }
                else if (pdu.Header.cmdId == PacketTypeValues.RDPGFX_CMDID_SURFACETOCACHE)
                {
                    receivedPdu = new RDPGFX_SURFACE_TO_CACHE();
                }
                else if (pdu.Header.cmdId == PacketTypeValues.RDPGFX_CMDID_CACHETOSURFACE)
                {
                    receivedPdu = new RDPGFX_CACHE_TO_SURFACE();
                }
                else if (pdu.Header.cmdId == PacketTypeValues.RDPGFX_CMDID_EVICTCACHEENTRY)
                {
                    receivedPdu = new RDPGFX_EVICT_CACHE_ENTRY();
                }
                else if (pdu.Header.cmdId == PacketTypeValues.RDPGFX_CMDID_CREATESURFACE)
                {
                    receivedPdu = new RDPGFX_CREATE_SURFACE();
                }
                else if (pdu.Header.cmdId == PacketTypeValues.RDPGFX_CMDID_DELETESURFACE)
                {
                    receivedPdu = new RDPGFX_DELETE_SURFACE();
                }
                else if (pdu.Header.cmdId == PacketTypeValues.RDPGFX_CMDID_STARTFRAME)
                {
                    receivedPdu = new RDPGFX_START_FRAME();
                }
                else if (pdu.Header.cmdId == PacketTypeValues.RDPGFX_CMDID_ENDFRAME)
                {
                    receivedPdu = new RDPGFX_END_FRAME();
                }
                else if (pdu.Header.cmdId == PacketTypeValues.RDPGFX_CMDID_RESETGRAPHICS)
                {
                    receivedPdu = new RDPGFX_RESET_GRAPHICS();
                }
                else if (pdu.Header.cmdId == PacketTypeValues.RDPGFX_CMDID_MAPSURFACETOOUTPUT)
                {
                    receivedPdu = new RDPGFX_MAPSURFACE_TO_OUTPUT();
                }
                else if (pdu.Header.cmdId == PacketTypeValues.RDPGFX_CMDID_CACHEIMPORTREPLY)
                {
                    receivedPdu = new RDPGFX_CACHE_IMPORT_REPLY();
                }
                else if (pdu.Header.cmdId == PacketTypeValues.RDPGFX_CMDID_CAPSCONFIRM)
                {
                    receivedPdu = new RDPGFX_CAPS_CONFIRM();
                }
                else if (pdu.Header.cmdId == PacketTypeValues.RDPGFX_CMDID_MAPSURFACETOWINDOW)
                {
                    receivedPdu = new RDPGFX_MAP_SURFACE_TO_WINDOW();
                }
                else if (pdu.Header.cmdId == PacketTypeValues.RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE)
                {
                    receivedPdu = new RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU();
                }
                else if (pdu.Header.cmdId == PacketTypeValues.RDPGFX_CMDID_MAPSURFACETOSCALEDOUTPUT)
                {
                    receivedPdu = new RDPGFX_MAP_SURFACE_TO_SCALED_OUTPUT_PDU();
                }
                else if (pdu.Header.cmdId == PacketTypeValues.RDPGFX_CMDID_MAPSURFACETOSCALEDWINDOW)
                {
                    receivedPdu = new RDPGFX_MAP_SURFACE_TO_SCALED_WINDOW_PDU();
                }

                if (receivedPdu != null && PduMarshaler.Unmarshal(data, receivedPdu))
                {
                    return(receivedPdu);
                }
            }
            RdpegfxUnkownPdu unkown = new RdpegfxUnkownPdu();

            PduMarshaler.Unmarshal(data, unkown);
            return(unkown);
        }
        /// <summary>
        /// Create a surface to cache Pdu.
        /// </summary>
        /// <param name="sid">This is used to indicate surface id.</param>
        /// <param name="key">This is used to indicate a key to associate with the bitmap cache entry.</param>
        /// <param name="slot">This is used to indicate the index of the bitmap cache entry in which
        /// the source bitmap data is stored.</param>
        /// <param name="rect">This is used to indicate rectangle that bounds the source bitmap.</param>
        public RDPGFX_SURFACE_TO_CACHE CreateSurfaceToCachePdu(ushort sid, ulong key, ushort slot, RDPGFX_RECT16 rect)
        {
            RDPGFX_SURFACE_TO_CACHE surfaceToCache = new RDPGFX_SURFACE_TO_CACHE(sid, key, slot, rect);

            return(surfaceToCache);
        }