The Virtual Channel PDU is sent from client to server or from server to client and is used to transport data between static virtual channel end-points.
file:///C:/ts_dev/TestSuites/MS-RDPBCGR/TestSuite/Src/TD/latest_XMLS_16may/RDPBCGR/ _rfc_ms-rdpbcgr2_1_6_1a.xml
Inheritance: RdpbcgrServerPdu
        /// <summary>
        /// Decode Virtual Channel PDU
        /// </summary>
        /// <param name="data">data to be parsed</param>
        /// <param name="decryptedUserData">decrypted user data</param>
        /// <param name="type">security header type</param>
        /// <returns>decoded Virtual Channel PDU</returns>
        public StackPacket DecodeVirtualChannelPDU(
            byte[] data,
            byte[] decryptedUserData,
            SecurityHeaderType type)
        {
            Virtual_Channel_RAW_Server_Pdu pdu = new Virtual_Channel_RAW_Server_Pdu();

            // data index
            int dataIndex = 0;

            // Virtual_Channel_RAW_Pdu: commonHeader
            pdu.commonHeader = ParseMcsCommonHeader(data, ref dataIndex, type);

            // user data index
            int userDataIndex = 0;

            // Virtual_Channel_RAW_PDU: channelPduHeader
            pdu.channelPduHeader = ParseChannelPduHeader(decryptedUserData, ref userDataIndex);

            // Virtual_Channel_RAW_PDU: virtualChannelData
            int remainLength = decryptedUserData.Length - Marshal.SizeOf(pdu.channelPduHeader);
            pdu.virtualChannelData = GetBytes(decryptedUserData, ref userDataIndex, remainLength);

            // Check if data length exceeded expectation
            VerifyDataLength(decryptedUserData.Length, userDataIndex, ConstValue.ERROR_MESSAGE_DATA_LENGTH_EXCEEDED);
            return pdu;
        }
 /// <summary>
 /// Reassemble chunk data by the member field channelManager.
 /// This method is called when processing Virtual Channel PDU.
 /// </summary>
 /// <param name="pdu">The channel pdu includes header and data. This argument can be null.</param>
 /// <returns>If the reassemble is complete, then return the Virtual_Channel_Complete_PDU.
 /// Else return null.</returns>
 public Virtual_Channel_Complete_Server_Pdu ReassembleChunkData(Virtual_Channel_RAW_Server_Pdu pdu)
 {
     lock (contextLock)
     {
         return channelManager.ReassembleChunkData(pdu);
     }
 }
        /// <summary>
        /// Send static virtual channel data
        /// </summary>
        /// <param name="channelId">Channel ID</param>
        /// <param name="channelPduHeader">Channel PDU Header</param>
        /// <param name="SVCData"></param>
        public void SendPacket(UInt16 channelId, CHANNEL_PDU_HEADER channelPduHeader, byte[] SVCData)
        {
            Virtual_Channel_RAW_Server_Pdu rawPdu = new Virtual_Channel_RAW_Server_Pdu(context);
            rawPdu.channelPduHeader = channelPduHeader;
            rawPdu.virtualChannelData = SVCData;

            RdpbcgrUtility.FillCommonHeader(ref rawPdu.commonHeader,
                                     TS_SECURITY_HEADER_flags_Values.SEC_IGNORE_SEQNO
                                     | TS_SECURITY_HEADER_flags_Values.SEC_RESET_SEQNO,
                                     context,
                                     channelId);

            context.Server.SendPdu(context, rawPdu);
        }
        public override StackPacket Clone()
        {
            Virtual_Channel_RAW_Server_Pdu pduClone = new Virtual_Channel_RAW_Server_Pdu();
            pduClone.commonHeader = commonHeader;
            pduClone.channelPduHeader = channelPduHeader;

            pduClone.virtualChannelData = RdpbcgrUtility.CloneByteArray(virtualChannelData);

            return pduClone;
        }
        /// <summary>
        /// Split the virtualChannelData to several chunk data to send. 
        /// </summary>
        public void SplitToChunks()
        {
            ChannelChunk[] chunks = serverSessionContext.SplitToChunks(channelId, virtualChannelData);
            if (chunks != null && chunks.Length > 0)
            {
                rawPdus = new Collection<Virtual_Channel_RAW_Server_Pdu>();
                for (int i = 0; i < chunks.Length; ++i)
                {
                    Virtual_Channel_RAW_Server_Pdu rawPdu = new Virtual_Channel_RAW_Server_Pdu(serverSessionContext);
                    rawPdu.channelPduHeader = chunks[i].channelPduHeader;
                    rawPdu.virtualChannelData = chunks[i].chunkData;
                    rawPdus.Add(rawPdu);

                    RdpbcgrUtility.FillCommonHeader(ref rawPdus[i].commonHeader,
                                             TS_SECURITY_HEADER_flags_Values.SEC_IGNORE_SEQNO
                                             | TS_SECURITY_HEADER_flags_Values.SEC_RESET_SEQNO,
                                             serverSessionContext,
                                             channelId);
                }
            }
        }
 public Virtual_Channel_RAW_Server_Pdu_Ex(Virtual_Channel_RAW_Server_Pdu orgPdu, RdpbcgrServerSessionContext serverSessionContext)
     : base(serverSessionContext)
 {
     this.commonHeader = orgPdu.commonHeader;
     this.channelPduHeader = orgPdu.channelPduHeader;
     this.virtualChannelData = orgPdu.virtualChannelData;
 }
        /// <summary>
        /// Reassemble static virtual channel PDU
        /// </summary>
        /// <param name="pdu"></param>
        /// <returns></returns>
        internal Virtual_Channel_Complete_Server_Pdu ReassembleChunkData(Virtual_Channel_RAW_Server_Pdu pdu)
        {
            if (pdu == null || pdu.virtualChannelData == null)
            {
                return null;
            }

            // the first chunk
            if ((pdu.channelPduHeader.flags & CHANNEL_PDU_HEADER_flags_Values.CHANNEL_FLAG_FIRST)
                == CHANNEL_PDU_HEADER_flags_Values.CHANNEL_FLAG_FIRST)
            {
                completeServerPdu = new Virtual_Channel_Complete_Server_Pdu();
                completeServerPdu.rawPdus = new System.Collections.ObjectModel.Collection<Virtual_Channel_RAW_Server_Pdu>();
                completeServerPdu.channelId = channelId;
                decompressedBuffer.Clear();
            }

            byte[] decompressedData = pdu.virtualChannelData;

            if (mppcDecompressor != null)   // has compression
            {
                CompressMode flag = CompressMode.None;

                if ((pdu.channelPduHeader.flags & CHANNEL_PDU_HEADER_flags_Values.CHANNEL_PACKET_AT_FRONT)
                    == CHANNEL_PDU_HEADER_flags_Values.CHANNEL_PACKET_AT_FRONT)
                {
                    flag |= CompressMode.SetToFront;
                }

                if ((pdu.channelPduHeader.flags & CHANNEL_PDU_HEADER_flags_Values.CHANNEL_PACKET_COMPRESSED)
                    == CHANNEL_PDU_HEADER_flags_Values.CHANNEL_PACKET_COMPRESSED)
                {
                    flag |= CompressMode.Compressed;
                }

                if ((pdu.channelPduHeader.flags & CHANNEL_PDU_HEADER_flags_Values.CHANNEL_PACKET_FLUSHED)
                    == CHANNEL_PDU_HEADER_flags_Values.CHANNEL_PACKET_FLUSHED)
                {
                    flag |= CompressMode.Flush;
                }

                if (flag != CompressMode.None)
                {
                    decompressedData = mppcDecompressor.Decompress(pdu.virtualChannelData, flag);
                }
            }

            if (completeServerPdu != null)
            {
                completeServerPdu.rawPdus.Add(pdu);
                decompressedBuffer.AddRange(decompressedData);
            }
            else
            {
                // not need to reassemble
                Virtual_Channel_Complete_Server_Pdu returnPDU = new Virtual_Channel_Complete_Server_Pdu();
                returnPDU.rawPdus = new System.Collections.ObjectModel.Collection<Virtual_Channel_RAW_Server_Pdu>();
                returnPDU.channelId = channelId;
                returnPDU.rawPdus.Add(pdu);
                returnPDU.virtualChannelData = decompressedData;
                return returnPDU;
            }

            // the last chunk
            if ((pdu.channelPduHeader.flags & CHANNEL_PDU_HEADER_flags_Values.CHANNEL_FLAG_LAST)
                == CHANNEL_PDU_HEADER_flags_Values.CHANNEL_FLAG_LAST)
            {
                if (decompressedBuffer != null)
                {
                    completeServerPdu.virtualChannelData = decompressedBuffer.ToArray();
                }
                Virtual_Channel_Complete_Server_Pdu returnPDU = completeServerPdu;
                completeServerPdu = null;
                return returnPDU;
            }

            return null;
        }