Example #1
0
        /// <summary>
        /// Establish a DVC after received a Create Request PDU
        /// </summary>
        /// <param name="createReq"></param>
        /// <param name="transportType"></param>
        /// <param name="receiveCallBack"></param>
        private void EstablishChannel(CreateReqDvcPdu createReq, DynamicVC_TransportType transportType, ReceiveData receiveCallBack = null)
        {
            if (channelDicbyId.ContainsKey(createReq.ChannelId))
            {
                throw new InvalidOperationException("Cannot establish the DVC, since a channel with same channelId have been established. Channel ID is " + createReq.ChannelId);
            }

            DynamicVirtualChannel channel = new DynamicVirtualChannel(createReq.ChannelId, createReq.ChannelName, (ushort)createReq.HeaderBits.Sp, transportDic[transportType]);

            if (receiveCallBack != null)
            {
                // Add event method here can make sure processing the first DVC data packet
                channel.Received += receiveCallBack;
            }
            else
            {
                if (callBackMethodsDic != null && callBackMethodsDic.ContainsKey(createReq.ChannelName))
                {
                    channel.Received += callBackMethodsDic[createReq.ChannelName];
                }
            }

            channelDicbyId.Add(createReq.ChannelId, channel);

            this.SendDVCCreateResponsePDU(createReq.ChannelId, 0, transportType);
        }
        /// <summary>
        /// Expect server send a create SVC request
        /// </summary>
        /// <param name="timeout">Timeout</param>
        /// <param name="channelName">Channel Name</param>
        /// <param name="transportType">Transport Type</param>
        /// <returns></returns>
        public DynamicVirtualChannel ExpectChannel(TimeSpan timeout, string channelName, DynamicVC_TransportType transportType)
        {
            if (autoCreateChannel)
            {
                throw new InvalidOperationException("Cannot establish a DVC manually if autoCreateChannel is true!");
            }

            if (!transportDic.ContainsKey(transportType))
            {
                throw new InvalidOperationException("DVC transport:" + transportType + " does not exist.");
            }


            CreateReqDvcPdu createReq = this.ExpectDVCCreateRequestPDU(timeout, channelName, transportType);

            if (createReq == null)
            {
                throw new System.IO.IOException("Creation of channel: " + channelName + " failed, cannot receive a Create Request PDU");
            }

            DynamicVirtualChannel channel = new DynamicVirtualChannel(createReq.ChannelId, channelName, (ushort)createReq.HeaderBits.Sp, transportDic[transportType]);

            channelDicbyId.Add(createReq.ChannelId, channel);

            this.SendDVCCreateResponsePDU(createReq.ChannelId, 0, transportType);

            return(channel);
        }
        /// <summary>
        /// Create a dynamic virtual channel
        /// </summary>
        /// <param name="priority">Priority</param>
        /// <param name="channelName">Channel name</param>
        /// <param name="transportType">Transport type</param>
        /// <param name="receiveCallBack">Callback method called when received data</param>
        /// <returns>DVC created</returns>
        public DynamicVirtualChannel CreateChannel(TimeSpan timeout, ushort priority, string channelName, DynamicVC_TransportType transportType, ReceiveData receiveCallBack = null)
        {
            if (!transportDic.ContainsKey(transportType))
            {
                throw new InvalidOperationException("Not create DVC transport:" + transportType);
            }

            UInt32 channelId = DynamicVirtualChannel.NewChannelId();
            DynamicVirtualChannel channel = new DynamicVirtualChannel(channelId, channelName, priority, transportDic[transportType]);

            if (receiveCallBack != null)
            {
                // Add event method here can make sure processing the first DVC data packet
                channel.Received += receiveCallBack;
            }

            channelDicbyId.Add(channelId, channel);

            this.SendDVCCreateRequestPDU(priority, channelId, channelName, transportType);
            CreateRespDvcPdu createResp = this.ExpectDVCCreateResponsePDU(timeout, channelId, transportType);

            if (createResp == null)
            {
                throw new System.IO.IOException("Creation of channel: " + channelName + " failed, cannot receive a Create Response PDU");
            }
            if (createResp.CreationStatus < 0)
            {
                //Create failed
                throw new System.IO.IOException("Creation of DVC failed with error code: " + createResp.CreationStatus + ", channel name is " + channelName);
            }

            return(channel);
        }
        /// <summary>
        /// Close a channel after received a Close DVC PDU
        /// </summary>
        /// <param name="pdu"></param>
        private void CloseChannel(CloseDvcPdu pdu)
        {
            if (!channelDicbyId.ContainsKey(pdu.ChannelId))
            {
                throw new InvalidOperationException("The channel has not been created, channel id:" + pdu.ChannelId);
            }
            DynamicVirtualChannel channel = channelDicbyId[pdu.ChannelId];

            channelDicbyId.Remove(channel.ChannelId);
            channel.IsActive = false;
        }
        /// <summary>
        /// Establish a DVC after received a Create Request PDU
        /// </summary>
        /// <param name="createReq"></param>
        /// <param name="transportType"></param>
        /// <param name="receiveCallBack"></param>
        private void EstablishChannel(CreateReqDvcPdu createReq, DynamicVC_TransportType transportType, ReceiveData receiveCallBack = null)
        {
            if (channelDicbyId.ContainsKey(createReq.ChannelId))
            {
                throw new InvalidOperationException("Cannot establish the DVC, since a channel with same channelId have been established. Channel ID is " + createReq.ChannelId);
            }

            DynamicVirtualChannel channel = new DynamicVirtualChannel(createReq.ChannelId, createReq.ChannelName, (ushort)createReq.HeaderBits.Sp, transportDic[transportType]);

            channelDicbyId.Add(createReq.ChannelId, channel);

            this.SendDVCCreateResponsePDU(createReq.ChannelId, 0, transportType);
        }
        /// <summary>
        /// Expect server send a close DVC request
        /// </summary>
        /// <param name="channelId">Channel Id</param>
        public void CloseChannel(UInt16 channelId)
        {
            if (!channelDicbyId.ContainsKey(channelId))
            {
                throw new InvalidOperationException("The channel has not been created, channel id:" + channelId);
            }
            DynamicVirtualChannel channel = channelDicbyId[channelId];

            // Send DVC close PDU
            this.SendDVCClosePDU(channelId, channel.TransportType);

            // Remove the channel from dictionary
            channelDicbyId.Remove(channelId);
        }
Example #7
0
        /// <summary>
        /// Expect to create a SVC
        /// </summary>
        /// <param name="timeout">Timeout</param>
        /// <param name="channelName">Channel Name</param>
        /// <param name="transportType">Transport Type</param>
        /// <returns></returns>
        public DynamicVirtualChannel ExpectChannel(TimeSpan timeout, string channelName, DynamicVC_TransportType transportType, ReceiveData receiveCallBack = null)
        {
            if (autoCreateChannel)
            {
                throw new InvalidOperationException("Cannot establish a DVC manually if autoCreateChannel is true!");
            }

            if (!transportDic.ContainsKey(transportType))
            {
                throw new InvalidOperationException("Not create DVC transport:" + transportType);
            }


            CreateReqDvcPdu createReq = this.ExpectDVCCreateRequestPDU(timeout, channelName, transportType);

            if (createReq == null)
            {
                throw new System.IO.IOException("Creation of channel: " + channelName + " failed, cannot receive a Create Request PDU");
            }

            DynamicVirtualChannel channel = new DynamicVirtualChannel(createReq.ChannelId, channelName, (ushort)createReq.HeaderBits.Sp, transportDic[transportType]);

            if (receiveCallBack != null)
            {
                // Add event method here can make sure processing the first DVC data packet
                channel.Received += receiveCallBack;
            }
            else
            {
                if (callBackMethodsDic != null && callBackMethodsDic.ContainsKey(channelName))
                {
                    channel.Received += callBackMethodsDic[channelName];
                }
            }

            channelDicbyId.Add(createReq.ChannelId, channel);

            this.SendDVCCreateResponsePDU(createReq.ChannelId, 0, transportType);

            return(channel);
        }
        /// <summary>
        /// Receives an IOCONTROL_COMPLETION, URB_COMPLETION or URB_COMPLETION_NO_DATA request from the client.
        /// </summary>
        /// <param name="channel">The channel to be received in.</param>
        /// <returns>The received completion PDU. Returns null, if timeout or required .</returns>
        public EusbPdu ExpectCompletion(DynamicVirtualChannel channel)
        {
            EusbPdu pdu = this.rdpeusbServer.ExpectRdpeusbPdu<EusbPdu>(channel.ChannelId, waitTime);

            if (null == pdu)
            {
                return null;
            }

            bool isCompletionPdu = (
                (pdu is EusbIoControlCompletionPdu) ||
                (pdu is EusbUrbCompletionPdu) ||
                (pdu is EusbUrbCompletionNoDataPdu)
                );

            Site.Assert.IsTrue(isCompletionPdu, "Expect a completion PDU, current pdu is {0}.", pdu.ToString());

            return pdu;
        }
        /// <summary>
        /// Establish a DVC after received a Create Request PDU
        /// </summary>
        /// <param name="createReq"></param>
        /// <param name="transportType"></param>
        /// <param name="receiveCallBack"></param>
        private void EstablishChannel(CreateReqDvcPdu createReq, DynamicVC_TransportType transportType, ReceiveData receiveCallBack = null)
        {
            if (channelDicbyId.ContainsKey(createReq.ChannelId))
            {
                throw new InvalidOperationException("Cannot establish the DVC, since a channel with same channelId have been established. Channel ID is " + createReq.ChannelId);
            }

            DynamicVirtualChannel channel = new DynamicVirtualChannel(createReq.ChannelId, createReq.ChannelName, (ushort)createReq.HeaderBits.Sp, transportDic[transportType]);
            if (receiveCallBack != null)
            {
                // Add event method here can make sure processing the first DVC data packet
                channel.Received += receiveCallBack;
            }
            else
            {
                if (callBackMethodsDic != null && callBackMethodsDic.ContainsKey(createReq.ChannelName))
                {
                    channel.Received += callBackMethodsDic[createReq.ChannelName];
                }
            }

            channelDicbyId.Add(createReq.ChannelId, channel);

            this.SendDVCCreateResponsePDU(createReq.ChannelId, 0, transportType);
        }
 /// <summary>
 /// Wait for creation of dynamic virtual channel for RDPEGT
 /// </summary>
 /// <param name="timeout"></param>
 /// <param name="transportType"></param>
 /// <returns></returns>
 public bool WaitForRdpegtDvcCreation(TimeSpan timeout, DynamicVC_TransportType transportType = DynamicVC_TransportType.RDP_TCP)
 {
     try
     {
         rdpegtDVC = rdpedycClient.ExpectChannel(timeout, RdpegtChannelName, transportType, OnDataReceived);
     }
     catch
     {
     }
     if (rdpegtDVC != null)
     {
         return true;
     }
     return false;
 }
        /// <summary>
        /// Create a dynamic virtual channel 
        /// </summary>
        /// <param name="priority">Priority</param>
        /// <param name="channelName">Channel name</param>
        /// <param name="transportType">Transport type</param>
        /// <param name="receiveCallBack">Callback method called when received data</param>
        /// <returns>DVC created</returns>
        public DynamicVirtualChannel CreateChannel(TimeSpan timeout, ushort priority, string channelName, DynamicVC_TransportType transportType, ReceiveData receiveCallBack = null, uint? channelId = null)
        {
            if (!transportDic.ContainsKey(transportType))
            {
                throw new InvalidOperationException("Not create DVC transport:" + transportType);
            }

            if (channelId == null)
                channelId = DynamicVirtualChannel.NewChannelId();
            DynamicVirtualChannel channel = new DynamicVirtualChannel((UInt32)channelId, channelName, priority, transportDic[transportType]);

            if (receiveCallBack != null)
            {
                // Add event method here can make sure processing the first DVC data packet
                channel.Received += receiveCallBack;
            }

            channelDicbyId.Add((UInt32)channelId, channel);

            this.SendDVCCreateRequestPDU(priority, (UInt32)channelId, channelName, transportType);
            CreateRespDvcPdu createResp = this.ExpectDVCCreateResponsePDU(timeout, (UInt32)channelId, transportType);
            if (createResp == null)
            {
                throw new System.IO.IOException("Creation of channel: " + channelName + " failed, cannot receive a Create Response PDU");
            }
            if (createResp.CreationStatus < 0)
            {
                //Create failed
                throw new System.IO.IOException("Creation of DVC failed with error code: " + createResp.CreationStatus + ", channel name is " + channelName);
            }

            return channel;
        }
        private void SendPdu(EusbPdu pdu, DynamicVirtualChannel channel)
        {
            Site.Assume.IsNotNull(channel, "DynamicVirtualChannel must be initialized.");

            channel.Send(PduMarshaler.Marshal(pdu));

            Site.Log.Add(LogEntryKind.Debug, "Sending {0}: \r\n{1}\r\n", pdu.GetType().ToString(), pdu.ToString());
        }
        private bool IsChannelClosed(DynamicVirtualChannel channel)
        {
            double timeout = Config.Timeout.TotalMilliseconds;
            const int wait = 100;

            Thread.Sleep(wait);
            timeout -= wait;
            while (timeout >= 0 && channel.IsActive)
            {
                Thread.Sleep(wait);
                timeout -= wait;
            }

            if (channel.IsActive)
            {
                Site.Log.Add(LogEntryKind.Debug, "The channel {0} is not closed within {1}", channel.ChannelId, Config.Timeout.ToString("c"));
            }

            return true;
        }
        /// <summary>
        /// Sends CHANNEL_CREATED to notify the client the channel has been created.
        /// </summary>
        /// <param name="channel">The channel to be sent in.</param>
        /// <param name="messageId">A unique ID for the request or response pair.</param>
        /// <param name="majorVersion">The major version of RDP USB redirection supported.</param>
        /// <param name="minorVersion">The minor version of RDP USB redirection supported.</param>
        /// <param name="capability">The capabilities of RDP USB redirection supported.</param>
        public void ChannelCreated(DynamicVirtualChannel channel, uint messageId, uint majorVersion, uint minorVersion, uint capability)
        {
            Site.Log.Add(
                LogEntryKind.Debug,
                "Sending CHANNEL_CREATED: Channel ID {0}, Message ID {1}, Version major {2} minor {3}, Capability {4}.",
                channel.ChannelId,
                messageId,
                majorVersion,
                minorVersion,
                capability
            );

            EusbChannelCreatedPdu requestPdu = new EusbChannelCreatedPdu(true);
            requestPdu.MessageId = messageId;
            requestPdu.MajorVersion = majorVersion;
            requestPdu.MinorVersion = minorVersion;
            requestPdu.Capabilities = capability;

            SendPdu(requestPdu, channel);

            if (majorVersion == 1 && minorVersion == 0 && capability == 0)
            {
                // Positive tests so expect a valid response.
                Site.Log.Add(LogEntryKind.Debug, "Receiving CHANNEL_CREATED.");
                EusbChannelCreatedPdu responsePdu = this.rdpeusbServer.ExpectRdpeusbPdu<EusbChannelCreatedPdu>(channel.ChannelId, waitTime);

                #region Verify CHANNEL_CREATED Response

                Site.Assert.IsNotNull(
                    responsePdu,
                    "Expect that the response from the client is EusbChannelCreatedPdu.");

                // Log this PDU if responsePdu is not null
                LogPdu(responsePdu);

                Site.Assert.AreEqual<uint>(
                    0x000000003,
                    responsePdu.InterfaceId,
                    "Expect that the InterfaceId in the response PDU equals 0x000000003. The actual value is 0x{0:x8}.",
                    responsePdu.InterfaceId);

                Site.Assert.AreEqual<FunctionId_Values>(
                    FunctionId_Values.CHANNEL_CREATED,
                    (FunctionId_Values)responsePdu.FunctionId,
                    "Expect that the FunctionId in the response PDU is CHANNEL_CREATED. The actual value is 0x{0:x8}.",
                    responsePdu.FunctionId);

                Site.Assert.AreEqual<uint>(responsePdu.MajorVersion,
                    1,
                    "Expect that the MajorVersion in the response PDU is 1. The actual value is {0}.",
                    responsePdu.MajorVersion);

                Site.Assert.AreEqual<uint>(responsePdu.MinorVersion,
                    0,
                    "Expect that the MinorVersion in the response PDU is 0. The actual value is {0}.",
                    responsePdu.MinorVersion);

                Site.Assert.AreEqual<uint>(responsePdu.Capabilities,
                    0,
                    "Expect that the Capabilities in the response PDU is 0. The actual value is {0}.",
                    responsePdu.Capabilities);

                #endregion
            }
            else
            {
                // Negative tests so expect the channel to be closed.
                bool channelClosed = IsChannelClosed(channel);
                Site.Assert.IsTrue(channelClosed, "Expect the channel {0} to be closed.", channel.ChannelId);
            }
        }
        /// <summary>
        /// Negotiates the capability through the specified channel with the connected RDP client.
        /// </summary>
        /// <param name="channel">The channel which the negotiation is sent in.</param>
        /// <param name="messageId">A unique ID for the request or response pair.</param>
        /// <param name="capability">The server's capability.</param>
        public void NegotiateCapability(DynamicVirtualChannel channel, uint messageId, CapabilityValue_Values capability)
        {
            Site.Log.Add(LogEntryKind.Debug, "Sending RIM_EXCHANGE_CAPABILITY_REQUEST: Channel ID {0}, Message ID {1}, Capability {2}.", channel.ChannelId, messageId, capability.ToString());

            EusbRimExchangeCapRequestPdu requestPdu = new EusbRimExchangeCapRequestPdu();
            requestPdu.MessageId = messageId;
            SendPdu(requestPdu, channel);

            if (capability == CapabilityValue_Values.RIM_CAPABILITY_VERSION_01)
            {
                // Positive tests so expect a valid response.
                Site.Log.Add(LogEntryKind.Debug, "Receiving EusbRimExchangeCapResponsePdu.");
                EusbRimExchangeCapResponsePdu responsePdu = this.rdpeusbServer.ExpectRdpeusbPdu<EusbRimExchangeCapResponsePdu>(channel.ChannelId, waitTime);

                #region Verify RIM_EXCHANGE_CAPABILITY_RESPONSE

                Site.Assert.IsNotNull(
                    responsePdu,
                    "Expect that the response from the client is EusbRimExchangeCapResponsePdu.");

                Site.Assert.AreEqual<uint>(
                    requestPdu.InterfaceId,
                    responsePdu.InterfaceId,
                    "Expect that the InterfaceId in the response PDU equals the InterfaceId in the request PDU. The actual value is 0x{0:x8}.",
                    responsePdu.InterfaceId);

                Site.Assert.AreEqual<uint>(
                    requestPdu.MessageId,
                    responsePdu.MessageId,
                    "Expect that the MessageId in the response PDU equals the MessageId in the request PDU. The actual value is 0x{0:x8}.",
                    responsePdu.MessageId);

                Site.Assert.AreEqual<Mask_Values>(
                    Mask_Values.STREAM_ID_NONE,
                    responsePdu.Mask,
                    "Expect that the Mask in the response PDU is STREAM_ID_NONE.");

                Site.Assert.AreEqual<uint>(
                    (uint)CapabilityValue_Values.RIM_CAPABILITY_VERSION_01,
                    responsePdu.CapabilityValue,
                    "Expect that the CapabilityValue in the response PDU is 0x00000001.");

                Site.Assert.AreEqual<uint>(
                    0,
                    responsePdu.Result,
                    "Expect that the Result in the response PDU is 0x00000000. The actual value is 0x{0:x8}.",
                    responsePdu.MessageId);

                #endregion
            }
            else
            {
                // Negative tests so expect the channel to be closed.
                bool channelClosed = IsChannelClosed(channel);
                Site.Assert.IsTrue(channelClosed, "Expect the channel {0} to be closed.", channel.ChannelId);
            }
        }
        /// <summary>
        /// Expect to create a SVC
        /// </summary>
        /// <param name="timeout">Timeout</param>
        /// <param name="channelName">Channel Name</param>
        /// <param name="transportType">Transport Type</param>
        /// <returns></returns>
        public DynamicVirtualChannel ExpectChannel(TimeSpan timeout, string channelName, DynamicVC_TransportType transportType, ReceiveData receiveCallBack = null)
        {
            if (autoCreateChannel)
            {
                throw new InvalidOperationException("Cannot establish a DVC manually if autoCreateChannel is true!");
            }

            if (!transportDic.ContainsKey(transportType))
            {
                throw new InvalidOperationException("Not create DVC transport:" + transportType);
            }

            CreateReqDvcPdu createReq = this.ExpectDVCCreateRequestPDU(timeout, channelName, transportType);
            if (createReq == null)
            {
                throw new System.IO.IOException("Creation of channel: " + channelName + " failed, cannot receive a Create Request PDU");
            }

            DynamicVirtualChannel channel = new DynamicVirtualChannel(createReq.ChannelId, channelName, (ushort)createReq.HeaderBits.Sp, transportDic[transportType]);
            if (receiveCallBack != null)
            {
                // Add event method here can make sure processing the first DVC data packet
                channel.Received += receiveCallBack;
            }
            else
            {
                if (callBackMethodsDic != null && callBackMethodsDic.ContainsKey(channelName))
                {
                    channel.Received += callBackMethodsDic[channelName];
                }
            }

            channelDicbyId.Add(createReq.ChannelId, channel);

            this.SendDVCCreateResponsePDU(createReq.ChannelId, 0, transportType);

            return channel;
        }
        /// <summary>
        /// Receives the ADD_VIRTUAL_CHANNEL request from the client.
        /// </summary>
        /// <param name="channelId">The channel received in.</param>
        public void ExpectAddVirtualChannel(DynamicVirtualChannel channel)
        {
            Site.Log.Add(LogEntryKind.Debug, "Receiving ADD_VIRTUAL_CHANNEL: Channel ID {0}", channel.ChannelId);

            EusbAddVirtualChannelPdu responsePdu = this.rdpeusbServer.ExpectRdpeusbPdu<EusbAddVirtualChannelPdu>(channel.ChannelId, waitTime);

            #region Verify ADD_VIRTUAL_CHANNEL

            Site.Assert.IsNotNull(
                responsePdu,
                "Expect that the response from the client is EusbAddVirtualChannelPdu.");

            // Log this PDU if responsePdu is not null
            LogPdu(responsePdu);

            Site.Assert.AreEqual<uint>(
                0x00000001,
                responsePdu.InterfaceId,
                "Expect that the InterfaceId in the response PDU equals 0x00000001. The actual value is 0x{0:x8}.",
                responsePdu.InterfaceId);

            Site.Assert.AreEqual<Mask_Values>(
                Mask_Values.STREAM_ID_PROXY,
                responsePdu.Mask,
                "Expect that the Mask in the response PDU is STREAM_ID_PROXY.");

            Site.Assert.AreEqual<FunctionId_Values>(
                FunctionId_Values.ADD_VIRTUAL_CHANNEL,
                (FunctionId_Values)responsePdu.FunctionId,
                "Expect that the FunctionId in the response PDU is ADD_VIRTUAL_CHANNEL. The actual value is 0x{0:x8}.",
                responsePdu.FunctionId);

            #endregion
        }
        /// <summary>
        /// Receives the ADD_DEVICE request from the client.
        /// </summary>
        /// <param name="channel">The channel to be received from.</param>
        /// <returns>The context of the device which is being added.</returns>
        public EusbDeviceContext ExpectAddDevice(DynamicVirtualChannel channel)
        {
            Site.Log.Add(LogEntryKind.Debug, "Receiving ADD_DEVICE, Channel ID {0}.", channel.ChannelId);

            EusbAddDevicePdu pdu = this.rdpeusbServer.ExpectRdpeusbPdu<EusbAddDevicePdu>(channel.ChannelId, waitTime);
            USB_DEVICE_CAPABILITIES cap = new USB_DEVICE_CAPABILITIES();

            if (!PduMarshaler.Unmarshal(pdu.UsbDeviceCapabilities, cap))
            {
                Site.Assert.Fail(
                    "UsbDeviceCapabilities (size in bytes: {0}) in ADD_DEVICE cannot be decoded.",
                    pdu.UsbDeviceCapabilities.Length
                    );
            }

            #region Verify ADD_DEVICE

            Site.Assert.IsNotNull(
                pdu,
                "Expect that the response from the client is EusbAddDevicePdu."
                );

            Site.Assert.AreEqual<uint>(
                0x00000001,
                pdu.InterfaceId,
                "Expect that the InterfaceId in the response PDU equals 0x00000001. The actual value is 0x{0:x8}.",
                pdu.InterfaceId);

            Site.Assert.AreEqual<Mask_Values>(
                Mask_Values.STREAM_ID_PROXY,
                pdu.Mask,
                "Expect that the Mask in the response PDU is STREAM_ID_PROXY.");

            Site.Assert.AreEqual<FunctionId_Values>(
                FunctionId_Values.ADD_DEVICE,
                (FunctionId_Values)pdu.FunctionId,
                "Expect that the FunctionId in the response PDU is ADD_DEVICE. The actual value is 0x{0:x8}.",
                pdu.FunctionId);

            Site.Assert.AreEqual<uint>(
                0x00000001,
                pdu.NumUsbDevice,
                "Expect that the NumUsbDevice in the response PDU equals 0x00000001. The actual value is 0x{0:x8}.",
                pdu.NumUsbDevice);

            Site.Assert.AreNotEqual<uint>(
                0x00000000,
                pdu.cchDeviceInstanceId,
                "Expect that the cchDeviceInstanceId in the response PDU is zero. The actual value is 0x{0:x8}.",
                pdu.cchDeviceInstanceId);

            if (Config.IsWindowsImplementation)
            {
                Site.Assert.AreNotEqual<uint>(
                    0x00000000,
                    pdu.cchHwIds,
                    "Expect that the cchHwIds in the response PDU is not zero in an implementation of Windows. The actual value is 0x{0:x8}.",
                    pdu.cchHwIds);
            }

            #region Verify UsbDeviceCapabilities

            Site.Assert.AreEqual<uint>(
                (uint)USB_DEVICE_CAPABILITIES.USB_DEVICE_CAPABILITIES_SIZE,
                cap.CbSize,
                "Expect that the CbSize of the USB_DEVICE_CAPABILITIES in the response PDU equals 28. The actual value is {0}.",
                cap.CbSize);

            Site.Assert.IsTrue(
                cap.UsbBusInterfaceVersion == (uint)UsbBusInterfaceVersion_Values.USB_BUS_VERSION_0
                || cap.UsbBusInterfaceVersion == (uint)UsbBusInterfaceVersion_Values.USB_BUS_VERSION_1
                || cap.UsbBusInterfaceVersion == (uint)UsbBusInterfaceVersion_Values.USB_BUS_VERSION_2,
                "Expect that the UsbBusInterfaceVersion of the USB_DEVICE_CAPABILITIES in the response PDU equals 0x00000000 or 0x00000001 or 0x00000002. The actual value is {0}.",
                cap.UsbBusInterfaceVersion);

            Site.Assert.IsTrue(
                cap.USBDI_Version == (uint)USBDI_VER.USBDI_VERSION_5 || cap.USBDI_Version == (uint)USBDI_VER.USBDI_VERSION_6,
                "Expect that the USBDI_Version of the USB_DEVICE_CAPABILITIES in the response PDU equals 0x00000500 or 0x00000600. The actual value is {0}.",
                cap.USBDI_Version);

            Site.Assert.IsTrue(
                cap.Supported_USB_Version == (uint)Supported_USB_Version_Values.USB_1_0
                || cap.Supported_USB_Version == (uint)Supported_USB_Version_Values.USB_1_1
                || cap.Supported_USB_Version == (uint)Supported_USB_Version_Values.USB_2_0,
                "Expect that the Supported_USB_Version of the USB_DEVICE_CAPABILITIES in the response PDU equals 0x100 or 0x110 or 0x200. The actual value is {0}.",
                cap.Supported_USB_Version);

            Site.Assert.AreEqual<uint>(
                0,
                cap.HcdCapabilities,
                "Expect that the HcdCapabilities of the USB_DEVICE_CAPABILITIES in the response PDU is zero. The actual value is {0}.",
                cap.HcdCapabilities);

            if (cap.UsbBusInterfaceVersion == (uint)UsbBusInterfaceVersion_Values.USB_BUS_VERSION_0)
            {
                Site.Assert.AreEqual<uint>(
                    (uint)DeviceSpeed_Values.FULL_SPEED,
                    cap.DeviceIsHighSpeed,
                    "Expect that the DeviceIsHighSpeed of the USB_DEVICE_CAPABILITIES in the response PDU is zero when UsbBusInterfaceVersion is 0x00000000. The actual value is {0}.",
                    cap.HcdCapabilities);
            }
            else
            {
                Site.Assert.IsTrue(
                    cap.DeviceIsHighSpeed == (uint)DeviceSpeed_Values.FULL_SPEED
                    || cap.DeviceIsHighSpeed == (uint)DeviceSpeed_Values.HIGH_SPEED,
                    "Expect that the DeviceIsHighSpeed of the USB_DEVICE_CAPABILITIES in the response PDU equals 0x100 or 0x110 or 0x200. The actual value is {0}.",
                    cap.DeviceIsHighSpeed);
            }

            if (cap.NoAckIsochWriteJitterBufferSizeInMs != 0)
            {
                Site.Assert.IsTrue(
                    cap.NoAckIsochWriteJitterBufferSizeInMs >= 10
                    && cap.NoAckIsochWriteJitterBufferSizeInMs <= 512,
                    "Expect that the NoAckIsochWriteJitterBufferSizeInMs of the USB_DEVICE_CAPABILITIES in the response PDU is greater than or equal to 10 and less than or equal to 512. The actual value is {0}.",
                    cap.NoAckIsochWriteJitterBufferSizeInMs);
            }

            #endregion

            #endregion

            EusbDeviceContext device = new EusbDeviceContext();
            device.VirtualChannel = channel;
            device.NoAckIsochWriteJitterBufferSizeInMs = (cap.NoAckIsochWriteJitterBufferSizeInMs != 0);
            device.UsbDeviceInterfaceId = pdu.UsbDevice;
            device.DeviceInstanceId = pdu.DeviceInstanceId;

            Site.Log.Add(LogEntryKind.Debug, "Received device request. Device: {0}", device);
            return device;
        }
        /// <summary>
        /// Create dynamic virtual channel.
        /// </summary>
        /// <param name="transportType">selected transport type for created channels</param>
        /// <param name="timeout">Timeout</param>
        /// <returns>true if client supports this protocol; otherwise, return false.</returns>
        public bool CreateRdpegtDvc(TimeSpan timeout, DynamicVC_TransportType transportType = DynamicVC_TransportType.RDP_TCP)
        {
            const ushort priority = 0;

            rdpegtDVC = rdpedycServer.CreateChannel(timeout, priority, RdpegtChannelName, transportType, null);

            if (rdpegtDVC != null)
            {
                return true;
            }
            return false;
        }