The TS_INFO_PACKET structure contains extra information not passed to the server during the Basic Settings Exchange phase (see section ) of the Standard RDP Connection Sequence, primarily to ensure that it gets encrypted (as auto-logon password data and other sensitive information is passed here).
file:///C:/ts_dev/TestSuites/MS-RDPBCGR/TestSuite/Src/TD/latest_XMLS_16may/RDPBCGR/ _rfc_ms-rdpbcgr2_1_1_11_1_1.xml
        /// <summary>
        /// Clear all the members except the reconnection relative members.
        /// </summary>
        internal void ClearForReconnect()
        {
            lock (contextLock)
            {
                x224ConnectionRequestPdu = null;
                x224ConnectionConfirmPdu = null;
                x224NegotiateFailurePdu = null;
                mcsConnectInitialPdu = null;
                mcsConnectResponsePdu = null;
                userChannelId = 0;
                ioChannelId = 0;
                serverChannelId = 0;
                clientInfo = null;
                securityExchangePdu = null;
                licenseErrorPdu = null;
                demandActivePdu = null;
                comfirmActivePdu = null;
                logonInfoV1 = new TS_LOGON_INFO();
                logonInfoV2 = new TS_LOGON_INFO_VERSION_2();
                logonErrorsInfo = null;
                encryptionCount = 0;
                decryptionCount = 0;

                if (encryptionAlgorithm != null)
                {
                    encryptionAlgorithm.Dispose();
                    encryptionAlgorithm = null;
                }

                if (ioDecompressor != null)
                {
                    ioDecompressor.Dispose();
                    ioDecompressor = null;
                }

                if (ioCompressor != null)
                {
                    ioCompressor.Dispose();
                    ioCompressor = null;
                }
            }
        }
        /// <summary>
        /// Update some members of context with the specified pdu.
        /// </summary>
        /// <param name="pdu">The sending or receiving pdu.</param>
        public void UpdateContext(StackPacket pdu)
        {
            lock (contextLock)
            {
                if (!isSwitchOn)
                {
                    // Don't update context but wait for upper layer TSD to do so.
                    return;
                }

                if (pdu.GetType() == typeof(Client_X_224_Connection_Request_Pdu))
                {
                    x224ConnectionRequestPdu = (Client_X_224_Connection_Request_Pdu)pdu.Clone();
                }
                else if (pdu.GetType() == typeof(Server_X_224_Connection_Confirm_Pdu))
                {
                    x224ConnectionConfirmPdu = ((Server_X_224_Connection_Confirm_Pdu)pdu.Clone()).rdpNegData;
                }
                else if (pdu.GetType() == typeof(Server_X_224_Negotiate_Failure_Pdu))
                {
                    x224NegotiateFailurePdu = ((Server_X_224_Negotiate_Failure_Pdu)pdu.Clone()).rdpNegFailure;
                }
                else if (pdu.GetType() == typeof(Client_MCS_Connect_Initial_Pdu_with_GCC_Conference_Create_Request))
                {
                    mcsConnectInitialPdu = ((Client_MCS_Connect_Initial_Pdu_with_GCC_Conference_Create_Request)
                        pdu.Clone()).mcsCi;
                }
                else if (pdu is Server_MCS_Connect_Response_Pdu_with_GCC_Conference_Create_Response)
                {
                    mcsConnectResponsePdu = (Server_MCS_Connect_Response_Pdu_with_GCC_Conference_Create_Response)
                        pdu.Clone();
                    serverRandom = RdpbcgrUtility.CloneByteArray(mcsConnectResponsePdu.mcsCrsp.gccPdu.serverSecurityData.serverRandom);
                    ioChannelId = mcsConnectResponsePdu.mcsCrsp.gccPdu.serverNetworkData.MCSChannelId;
                    if(mcsConnectResponsePdu.mcsCrsp.gccPdu.serverMessageChannelData != null)
                        mcsMsgChannelId = mcsConnectResponsePdu.mcsCrsp.gccPdu.serverMessageChannelData.MCSChannelID;
                    encryptionAlgorithm = new EncryptionAlgorithm(RdpEncryptionMethod);
                }
                else if (pdu.GetType() == typeof(Server_MCS_Attach_User_Confirm_Pdu))
                {
                    if (((Server_MCS_Attach_User_Confirm_Pdu)pdu).attachUserConfirm.initiator != null)
                    {
                        userChannelId = (ushort)((Server_MCS_Attach_User_Confirm_Pdu)pdu).attachUserConfirm.initiator.Value;
                    }
                }
                else if (pdu.GetType() == typeof(Client_Security_Exchange_Pdu))
                {
                    securityExchangePdu = (Client_Security_Exchange_Pdu)pdu.Clone();
                    clientRandom = RdpbcgrUtility.CloneByteArray(
                        ((Client_Security_Exchange_Pdu)pdu).securityExchangePduData.clientRandom);
                    GenerateSessionKey();
                }
                else if (pdu.GetType() == typeof(Client_Info_Pdu))
                {
                    clientInfo = ((Client_Info_Pdu)pdu.Clone()).infoPacket;
                    if (clientInfo != null
                        && (clientInfo.flags & flags_Values.INFO_COMPRESSION) == flags_Values.INFO_COMPRESSION)
                    {
                        ioDecompressor = new Decompressor(SlidingWindowSize.EightKB);
                        ioCompressor = new Compressor(SlidingWindowSize.EightKB);
                    }
                    isWaitingLicenseErrorPdu = true;
                }
                else if (pdu.GetType() == typeof(Server_Auto_Detect_Request_PDU))
                {

                    NETWORK_DETECTION_REQUEST requestData = ((Server_Auto_Detect_Request_PDU)pdu).autoDetectReqData.Clone();
                    if (requestData.requestType == AUTO_DETECT_REQUEST_TYPE.RDP_RTT_REQUEST_IN_CONNECTTIME || requestData.requestType == AUTO_DETECT_REQUEST_TYPE.RDP_RTT_REQUEST_AFTER_CONNECTTIME)
                    {
                        RDP_RTT_REQUEST rttRequest = (RDP_RTT_REQUEST)requestData;
                        rttRequest.sendTime = DateTime.Now;
                        this.serverAutoDetectRequestData.Add(rttRequest.sequenceNumber, rttRequest);
                    }
                }
                else if (pdu.GetType() == typeof(Client_Auto_Detect_Response_PDU))
                {
                    clientAutoDetectResponsePdu = (Client_Auto_Detect_Response_PDU)pdu.Clone();
                    NETWORK_DETECTION_RESPONSE responseData = clientAutoDetectResponsePdu.autodetectRspPduData;
                    if (responseData.responseType == AUTO_DETECT_RESPONSE_TYPE.RDP_RTT_RESPONSE)
                    {
                        RDP_RTT_REQUEST rttRequest = (RDP_RTT_REQUEST)serverAutoDetectRequestData[responseData.sequenceNumber];
                        if (rttRequest != null)
                        {
                            TimeSpan interval = DateTime.Now -  rttRequest.sendTime;
                            this.autoDetectedRTTList.Add((uint)interval.TotalMilliseconds);
                            serverAutoDetectRequestData.Remove(responseData.sequenceNumber);
                        }
                    }
                    else if (responseData.responseType == AUTO_DETECT_RESPONSE_TYPE.RDP_BW_RESULTS_AFTER_CONNECT || responseData.responseType == AUTO_DETECT_RESPONSE_TYPE.RDP_BW_RESULTS_DURING_CONNECT)
                    {
                        RDP_BW_RESULTS bwResult = (RDP_BW_RESULTS)responseData;
                        if(bwResult.timeDelta != 0)
                            this.autoDetectedBandwidth = (uint)(bwResult.byteCount / bwResult.timeDelta);
                    }
                    else if (responseData.responseType == AUTO_DETECT_RESPONSE_TYPE.RDP_NETCHAR_SYNC)
                    {
                        RDP_NETCHAR_SYNC netSync = (RDP_NETCHAR_SYNC)responseData;
                        this.autoDetectedRTTList.Add(netSync.rtt);
                        this.autoDetectedBandwidth = netSync.bandwidth;
                    }
                }
                else if (pdu.GetType() == typeof(Server_License_Error_Pdu_Valid_Client))
                {
                    licenseErrorPdu = (Server_License_Error_Pdu_Valid_Client)pdu.Clone();
                    serverChannelId = licenseErrorPdu.commonHeader.initiator;
                }
                else if (pdu.GetType() == typeof(Server_Initiate_Multitransport_Request_PDU))
                {
                    Server_Initiate_Multitransport_Request_PDU requestPDU = (Server_Initiate_Multitransport_Request_PDU)pdu;
                    serverInitiateMultitransportRequestPduDictionary.Add(requestPDU.requestId, requestPDU);
                }
                else if (pdu.GetType() == typeof(Client_Initiate_Multitransport_Response_PDU))
                {
                    clientInitiateMultitransportResponsePdu = (Client_Initiate_Multitransport_Response_PDU)pdu;
                }
                else if (pdu.GetType() == typeof(Server_Demand_Active_Pdu))
                {
                    serverChannelId = ((Server_Demand_Active_Pdu)pdu.Clone()).commonHeader.initiator;
                    demandActivePdu = ((Server_Demand_Active_Pdu)pdu.Clone()).demandActivePduData;

                }
                else if (pdu.GetType() == typeof(Client_Confirm_Active_Pdu))
                {
                    comfirmActivePdu = ((Client_Confirm_Active_Pdu)pdu.Clone()).confirmActivePduData;
                    if (channelManager == null)
                    {
                        channelManager = new ServerStaticVirtualChannelManager(this);
                    }
                }
                else if (pdu.GetType() == typeof(MCS_Disconnect_Provider_Ultimatum_Server_Pdu))
                {
                    lastDisconnectReason = (int)((MCS_Disconnect_Provider_Ultimatum_Server_Pdu)
                        pdu).disconnectProvider.reason.Value;
                }
                else if (pdu.GetType() == typeof(MCS_Disconnect_Provider_Ultimatum_Pdu))
                {
                    lastDisconnectReason = (int)((MCS_Disconnect_Provider_Ultimatum_Pdu)
                        pdu).disconnectProvider.reason.Value;
                }
                else if (pdu.GetType() == typeof(Server_Set_Error_Info_Pdu))
                {
                    lastErrorInfo = ((Server_Set_Error_Info_Pdu)pdu).errorInfoPduData.errorInfo;
                }
                else if (pdu.GetType() == typeof(Server_Status_Info_Pdu))
                {
                    lastStatusInfo = ((Server_Status_Info_Pdu)pdu).statusCode;
                }
                else if (pdu.GetType() == typeof(Server_Save_Session_Info_Pdu))
                {
                    Server_Save_Session_Info_Pdu saveSessionInfoPdu = (Server_Save_Session_Info_Pdu)pdu.Clone();

                    switch (saveSessionInfoPdu.saveSessionInfoPduData.infoType)
                    {
                        case infoType_Values.INFOTYPE_LOGON:
                            logonInfoV1 = (TS_LOGON_INFO)saveSessionInfoPdu.saveSessionInfoPduData.infoData;
                            break;

                        case infoType_Values.INFOTYPE_LOGON_LONG:
                            logonInfoV2 = (TS_LOGON_INFO_VERSION_2)saveSessionInfoPdu.saveSessionInfoPduData.infoData;
                            break;

                        case infoType_Values.INFOTYPE_LOGON_EXTENDED_INF:
                            TS_LOGON_INFO_EXTENDED infoExtended =
                                (TS_LOGON_INFO_EXTENDED)saveSessionInfoPdu.saveSessionInfoPduData.infoData;
                            switch (infoExtended.FieldsPresent)
                            {
                                case FieldsPresent_Values.LOGON_EX_AUTORECONNECTCOOKIE
                                   | FieldsPresent_Values.LOGON_EX_LOGONERRORS:
                                    autoReconnectCookie = (ARC_SC_PRIVATE_PACKET)infoExtended.LogonFields[0].FieldData;
                                    logonErrorsInfo = (TS_LOGON_ERRORS_INFO)infoExtended.LogonFields[1].FieldData;
                                    break;

                                case FieldsPresent_Values.LOGON_EX_AUTORECONNECTCOOKIE:
                                    autoReconnectCookie = (ARC_SC_PRIVATE_PACKET)infoExtended.LogonFields[0].FieldData;
                                    break;

                                case FieldsPresent_Values.LOGON_EX_LOGONERRORS:
                                    logonErrorsInfo = (TS_LOGON_ERRORS_INFO)infoExtended.LogonFields[0].FieldData;
                                    break;

                                default:
                                    break;
                            }
                            break;

                        default:
                            break;
                    }
                }
            }
        }
        /// <summary>
        /// Update some members of context with the specified pdu.
        /// </summary>
        /// <param name="pdu">The sending or receiving pdu.</param>
        public void UpdateContext(StackPacket pdu)
        {
            lock (contextLock)
            {
                if (!isSwitchOn)
                {
                    // Don't update context but wait for upper layer TSD to do so.
                    return;
                }

                if (pdu.GetType() == typeof(Client_X_224_Connection_Request_Pdu))
                {
                    x224ConnectionRequestPdu = (Client_X_224_Connection_Request_Pdu)pdu.Clone();
                }
                else if (pdu.GetType() == typeof(Server_X_224_Connection_Confirm_Pdu))
                {
                    x224ConnectionConfirmPdu = ((Server_X_224_Connection_Confirm_Pdu)pdu.Clone()).rdpNegData;
                }
                else if (pdu.GetType() == typeof(Server_X_224_Negotiate_Failure_Pdu))
                {
                    x224NegotiateFailurePdu = ((Server_X_224_Negotiate_Failure_Pdu)pdu.Clone()).rdpNegFailure;
                }
                else if (pdu.GetType() == typeof(Client_MCS_Connect_Initial_Pdu_with_GCC_Conference_Create_Request))
                {
                    mcsConnectInitialPdu = ((Client_MCS_Connect_Initial_Pdu_with_GCC_Conference_Create_Request)
                        pdu.Clone()).mcsCi;
                }
                else if (pdu.GetType() == typeof(Server_MCS_Connect_Response_Pdu_with_GCC_Conference_Create_Response))
                {
                    mcsConnectResponsePdu = (Server_MCS_Connect_Response_Pdu_with_GCC_Conference_Create_Response)
                        pdu.Clone();
                    encryptionAlgorithm = new EncryptionAlgorithm(RdpEncryptionMethod);
                }
                else if (pdu.GetType() == typeof(Server_MCS_Attach_User_Confirm_Pdu))
                {
                    userChannelId = (long)((Server_MCS_Attach_User_Confirm_Pdu)pdu).attachUserConfirm.initiator.Value;
                }
                else if (pdu.GetType() == typeof(Client_Security_Exchange_Pdu))
                {
                    clientRandom = RdpbcgrUtility.CloneByteArray(
                        ((Client_Security_Exchange_Pdu)pdu).securityExchangePduData.clientRandom);
                }
                else if (pdu.GetType() == typeof(Client_Info_Pdu))
                {
                    clientInfo = ((Client_Info_Pdu)pdu.Clone()).infoPacket;
                    if (clientInfo != null
                        && (clientInfo.flags & flags_Values.INFO_COMPRESSION) == flags_Values.INFO_COMPRESSION)
                    {
                        ioDecompressor = new Decompressor((SlidingWindowSize)CompressionTypeSupported);
                    }
                }
                else if (pdu.GetType() == typeof(Server_License_Error_Pdu_Valid_Client))
                {
                    licenseErrorPdu = (Server_License_Error_Pdu_Valid_Client)pdu.Clone();
                }
                else if (pdu.GetType() == typeof(Server_Initiate_Multitransport_Request_PDU))
                {
                    Server_Initiate_Multitransport_Request_PDU initRequset = pdu as Server_Initiate_Multitransport_Request_PDU;
                    if (initRequset.requestedProtocol == Multitransport_Protocol_value.INITITATE_REQUEST_PROTOCOL_UDPFECR)
                    {
                        requestIdReliable = initRequset.requestId;
                        cookieReliable = initRequset.securityCookie;
                    }
                    else
                    {
                        requestIdLossy = initRequset.requestId;
                        cookieLossy = initRequset.securityCookie;
                    }
                }
                else if (pdu.GetType() == typeof(Server_Demand_Active_Pdu))
                {
                    demandActivePdu = ((Server_Demand_Active_Pdu)pdu.Clone()).demandActivePduData;
                }
                else if (pdu.GetType() == typeof(Client_Confirm_Active_Pdu))
                {
                    comfirmActivePdu = ((Client_Confirm_Active_Pdu)pdu.Clone()).confirmActivePduData;
                    if (channelManager == null)
                    {
                        channelManager = new ClientStaticVirtualChannelManager(this);
                    }
                }
                else if (pdu.GetType() == typeof(MCS_Disconnect_Provider_Ultimatum_Pdu))
                {
                    lastDisconnectReason = (int)((MCS_Disconnect_Provider_Ultimatum_Pdu)
                        pdu).disconnectProvider.reason.Value;
                }
                else if (pdu.GetType() == typeof(Server_Set_Error_Info_Pdu))
                {
                    lastErrorInfo = ((Server_Set_Error_Info_Pdu)pdu).errorInfoPduData.errorInfo;
                }
                else if (pdu.GetType() == typeof(Server_Status_Info_Pdu))
                {
                    lastStatusInfo = ((Server_Status_Info_Pdu)pdu).statusCode;
                }
                else if (pdu.GetType() == typeof(Server_Save_Session_Info_Pdu))
                {
                    Server_Save_Session_Info_Pdu saveSessionInfoPdu = (Server_Save_Session_Info_Pdu)pdu.Clone();

                    switch (saveSessionInfoPdu.saveSessionInfoPduData.infoType)
                    {
                        case infoType_Values.INFOTYPE_LOGON:
                            logonInfoV1 = (TS_LOGON_INFO)saveSessionInfoPdu.saveSessionInfoPduData.infoData;
                            break;

                        case infoType_Values.INFOTYPE_LOGON_LONG:
                            logonInfoV2 = (TS_LOGON_INFO_VERSION_2)saveSessionInfoPdu.saveSessionInfoPduData.infoData;
                            break;

                        case infoType_Values.INFOTYPE_LOGON_EXTENDED_INF:
                            TS_LOGON_INFO_EXTENDED infoExtended =
                                (TS_LOGON_INFO_EXTENDED)saveSessionInfoPdu.saveSessionInfoPduData.infoData;
                            switch (infoExtended.FieldsPresent)
                            {
                                case FieldsPresent_Values.LOGON_EX_AUTORECONNECTCOOKIE
                                   | FieldsPresent_Values.LOGON_EX_LOGONERRORS:
                                    autoReconnectCookie = (ARC_SC_PRIVATE_PACKET)infoExtended.LogonFields[0].FieldData;
                                    logonErrorsInfo = (TS_LOGON_ERRORS_INFO)infoExtended.LogonFields[1].FieldData;
                                    break;

                                case FieldsPresent_Values.LOGON_EX_AUTORECONNECTCOOKIE:
                                    autoReconnectCookie = (ARC_SC_PRIVATE_PACKET)infoExtended.LogonFields[0].FieldData;
                                    break;

                                case FieldsPresent_Values.LOGON_EX_LOGONERRORS:
                                    logonErrorsInfo = (TS_LOGON_ERRORS_INFO)infoExtended.LogonFields[0].FieldData;
                                    break;

                                default:
                                    break;
                            }
                            break;

                        default:
                            break;
                    }
                }
            }
        }
        /// <summary>
        /// 2.2.1.11.1
        /// </summary>
        /// <param name="info"></param>
        public void VerifyStructure(TS_INFO_PACKET info)
        {
            //Unicode = 2 * Ansi
            site.CaptureRequirementIfAreEqual<int>(info.Domain.Length*2, (int)info.cbDomain, 464,
                @"In the TS_INFO_PACKET structure, cbDomain represents the size in bytes of the character data in the Domain field."
                + @" This size excludes the length of the mandatory null terminator.");
            site.CaptureRequirementIfAreEqual<int>(info.UserName.Length*2, (int)info.cbUserName, 466,
                @"In the TS_INFO_PACKET structure, cbUserName represents the size in bytes of the character data in the UserName "
                + @"field. This size excludes the length of the mandatory null terminator.");
            site.CaptureRequirementIfAreEqual<int>(info.Password.Length*2, (int)info.cbPassword, 468,
                @"In the TS_INFO_PACKET structure, cbPassword represents the size in bytes of the character data in the Password "
                + @"field. This size excludes the length of the mandatory null terminator.");
            site.CaptureRequirementIfAreEqual<int>(info.AlternateShell.Length*2, (int)info.cbAlternateShell, 470,
                @"In the TS_INFO_PACKET structure, cbAlternateShell represents the size in bytes of the character data in the "
                + @"AlternateShell field. This size excludes the length of the mandatory null terminator.");
            site.CaptureRequirementIfAreEqual<int>(info.WorkingDir.Length*2, (int)info.cbWorkingDir, 472,
                @"In the TS_INFO_PACKET structure, cbWorkingDir represents the size in bytes of the character data in the WorkingDir"
                + @" field. This size excludes the length of the mandatory null terminator.");
            //<bug> Domain not contains /0
            //site.CaptureRequirementIfIsTrue(info.Domain.Contains("\0"), 476,
            //    @"In the TS_INFO_PACKET structure, Domain field MUST contain at least a null terminator character in ANSI or Unicode"
            //    + @" format (depending on the presence of the INFO_UNICODE flag)");
            //site.CaptureRequirementIfIsTrue(info.UserName.Contains("\0"), 480,
            //    @"In the TS_INFO_PACKET structure, UserName field MUST contain at least a null terminator character in ANSI or Unicode"
            //    + @" format (depending on the presence of the INFO_UNICODE flag)");
            //site.CaptureRequirementIfIsTrue(info.Password.Contains("\0"), 483,
            //    @"In the TS_INFO_PACKET structure, Password field MUST contain at least a null terminator character in ANSI or Unicode"
            //    + @" format (depending on the presence of the INFO_UNICODE flag)");
            site.CaptureRequirementIfIsTrue(info.AlternateShell.Length <= 512, 485,
                @"In the TS_INFO_PACKET structure, for AlternateShell, the maximum allowed length is 512 bytes (including the mandatory"
                + @" null terminator).");
            //site.CaptureRequirementIfIsTrue(info.AlternateShell.Contains("\0"), 487,
            //    @"In the TS_INFO_PACKET structure, AlternateShell field MUST contain at least a null terminator character in ANSI or "
            //    + @"Unicode format (depending on the presence of the INFO_UNICODE flag)");
            //site.CaptureRequirementIfIsTrue(info.WorkingDir.Contains("\0"), 491,
            //    @"In the TS_INFO_PACKET structure, WorkingDir field MUST contain at least a null terminator character in ANSI or "
            //    + @"Unicode format (depending on the presence of the INFO_UNICODE flag)");
            if (info.extraInfo != null)
            {
                //bugbug:
                //AF_INET 0x00002
                //AF_INET6 0x0017
                //<hardcode>
                if (!this.Site.Properties["RDP.Version"].Equals("8.1"))
                {
                    site.CaptureRequirementIfIsTrue(info.extraInfo.clientAddressFamily == clientAddressFamily_Values.V1 || (int)info.extraInfo.clientAddressFamily == 0x17, 495,
                        @"[In Extended Info Packet (TS_EXTENDED_INFO_PACKET)]clientAddressFamily (2 bytes):clientAddressFamily can have the "
                        + @"following values: 1.AF_INET 0x00002 2.AF_INET6 0x0017");
                }

                Console.WriteLine("RS503, clientDir.Length = " + info.extraInfo.clientDir.Length);
                Console.WriteLine("RS503, cbClientDir=" + info.extraInfo.cbClientDir);

                bool isR505Satisfied = info.extraInfo.cbClientDir <= 512;
                site.CaptureRequirementIfIsTrue(isR505Satisfied, 505,
                    @"[In Extended Info Packet (TS_EXTENDED_INFO_PACKET)] clientDir (variable):The maximum allowed length is 512 bytes "
                    + @"(including the mandatory null terminator).");

                bool isR528Satisfied = info.extraInfo.cbAutoReconnectLen <= 128;
                site.CaptureRequirementIfIsTrue(isR528Satisfied, 528,
                    @"[Extended Info Packet (TS_EXTENDED_INFO_PACKET)]autoReconnectCookie (28 bytes):the maximum allowed length "
                    + @"is 128 bytes.");
            }
        }
        /// <summary>
        /// Parse TS_INFO_PACKET
        /// (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>TS_INFO_PACKET</returns>
        private TS_INFO_PACKET ParseClientInfo(byte[] data, ref int currentIndex)
        {
            TS_INFO_PACKET infoData = new TS_INFO_PACKET();
            infoData.CodePage = ParseUInt32(data, ref currentIndex, false);
            infoData.flags = (flags_Values)ParseUInt32(data, ref currentIndex, false);
            infoData.cbDomain = ParseUInt16(data, ref currentIndex, false);
            infoData.cbUserName = ParseUInt16(data, ref currentIndex, false);
            infoData.cbPassword = ParseUInt16(data, ref currentIndex, false);
            infoData.cbAlternateShell = ParseUInt16(data, ref currentIndex, false);
            infoData.cbWorkingDir = ParseUInt16(data, ref currentIndex, false);
            Encoding converter = new UnicodeEncoding();

            if ((infoData.flags & flags_Values.INFO_UNICODE) == flags_Values.INFO_UNICODE)
            {
                converter = new UnicodeEncoding();

                byte[] domain = GetBytes(data, ref currentIndex, (int)infoData.cbDomain);
                infoData.Domain = converter.GetString(domain);
                currentIndex += 2;
                byte[] userName = GetBytes(data, ref currentIndex, (int)infoData.cbUserName);
                infoData.UserName = converter.GetString(userName);
                currentIndex += 2;

                byte[] password = GetBytes(data, ref currentIndex, (int)infoData.cbPassword);
                infoData.Password = converter.GetString(password);
                currentIndex += 2;
                byte[] alternateShell = GetBytes(data, ref currentIndex, (int)infoData.cbAlternateShell);
                infoData.AlternateShell = converter.GetString(alternateShell);
                currentIndex += 2;
                byte[] workingDir = GetBytes(data, ref currentIndex, (int)infoData.cbWorkingDir);
                infoData.WorkingDir = converter.GetString(workingDir);
                currentIndex += 2;
            }

            else
            {
                converter = new ASCIIEncoding();

                byte[] domain = GetBytes(data, ref currentIndex, (int)infoData.cbDomain);
                infoData.Domain = converter.GetString(domain);
                currentIndex += 1;

                byte[] userName = GetBytes(data, ref currentIndex, (int)infoData.cbUserName);
                infoData.UserName = converter.GetString(userName);
                currentIndex += 1;

                byte[] password = GetBytes(data, ref currentIndex, (int)infoData.cbPassword);
                infoData.Password = converter.GetString(password);
                currentIndex += 1;

                byte[] alternateShell = GetBytes(data, ref currentIndex, (int)infoData.cbAlternateShell);
                infoData.AlternateShell = converter.GetString(alternateShell);
                currentIndex += 1;

                byte[] workingDir = GetBytes(data, ref currentIndex, (int)infoData.cbWorkingDir);
                infoData.WorkingDir = converter.GetString(workingDir);
                currentIndex += 1;
            }

            if (currentIndex < data.Length)
            {
                infoData.extraInfo = ParseExtendedInfo(data, ref currentIndex, converter);
            }

            return infoData;
        }
        /// <summary>
        /// Encode infoPacket field.
        /// </summary>
        /// <param name="infoPacket">The data to be encoded.</param>
        /// <returns>The encoded data.</returns>
        private static byte[] EncodeInfoData(TS_INFO_PACKET infoPacket)
        {
            List<byte> infoBuffer = new List<byte>();
            if (infoPacket != null)
            {
                RdpbcgrEncoder.EncodeStructure(infoBuffer, infoPacket.CodePage);
                RdpbcgrEncoder.EncodeStructure(infoBuffer, (uint)infoPacket.flags);
                RdpbcgrEncoder.EncodeStructure(infoBuffer, infoPacket.cbDomain);
                RdpbcgrEncoder.EncodeStructure(infoBuffer, infoPacket.cbUserName);
                RdpbcgrEncoder.EncodeStructure(infoBuffer, infoPacket.cbPassword);
                RdpbcgrEncoder.EncodeStructure(infoBuffer, infoPacket.cbAlternateShell);
                RdpbcgrEncoder.EncodeStructure(infoBuffer, infoPacket.cbWorkingDir);
                if ((infoPacket.flags & flags_Values.INFO_UNICODE) == flags_Values.INFO_UNICODE)
                {
                    // +2 means add a null-terminator for a unicode string
                    RdpbcgrEncoder.EncodeUnicodeString(infoBuffer, infoPacket.Domain, (uint)(infoPacket.cbDomain + 2));
                    RdpbcgrEncoder.EncodeUnicodeString(infoBuffer,
                                                       infoPacket.UserName,
                                                       (uint)(infoPacket.cbUserName + 2));
                    RdpbcgrEncoder.EncodeUnicodeString(infoBuffer,
                                                       infoPacket.Password,
                                                       (uint)(infoPacket.cbPassword + 2));
                    RdpbcgrEncoder.EncodeUnicodeString(infoBuffer,
                                                       infoPacket.AlternateShell,
                                                       (uint)(infoPacket.cbAlternateShell + 2));
                    RdpbcgrEncoder.EncodeUnicodeString(infoBuffer,
                                                       infoPacket.WorkingDir,
                                                       (uint)(infoPacket.cbWorkingDir + 2));
                }
                else
                {
                    // +1 means add a null-terminator for an ansi string
                    RdpbcgrEncoder.EncodeAnsiString(infoBuffer, infoPacket.Domain, (uint)(infoPacket.cbDomain + 1));
                    RdpbcgrEncoder.EncodeAnsiString(infoBuffer,
                                                    infoPacket.UserName,
                                                    (uint)(infoPacket.cbUserName + 1));
                    RdpbcgrEncoder.EncodeAnsiString(infoBuffer,
                                                    infoPacket.Password,
                                                    (uint)(infoPacket.cbPassword + 1));
                    RdpbcgrEncoder.EncodeAnsiString(infoBuffer,
                                                    infoPacket.AlternateShell,
                                                    (uint)(infoPacket.cbAlternateShell + 1));
                    RdpbcgrEncoder.EncodeAnsiString(infoBuffer,
                                                    infoPacket.WorkingDir,
                                                    (uint)(infoPacket.cbWorkingDir + 1));
                }

                if (infoPacket.extraInfo != null)
                {
                    RdpbcgrEncoder.EncodeStructure(infoBuffer, (ushort)infoPacket.extraInfo.clientAddressFamily);
                    RdpbcgrEncoder.EncodeStructure(infoBuffer, infoPacket.extraInfo.cbClientAddress);
                    if ((infoPacket.flags & flags_Values.INFO_UNICODE) == flags_Values.INFO_UNICODE)
                    {
                        RdpbcgrEncoder.EncodeUnicodeString(infoBuffer,
                                                           infoPacket.extraInfo.clientAddress,
                                                           infoPacket.extraInfo.cbClientAddress);
                    }
                    else
                    {
                        RdpbcgrEncoder.EncodeAnsiString(infoBuffer,
                                                        infoPacket.extraInfo.clientAddress,
                                                        infoPacket.extraInfo.cbClientAddress);
                    }

                    RdpbcgrEncoder.EncodeStructure(infoBuffer, infoPacket.extraInfo.cbClientDir);
                    if ((infoPacket.flags & flags_Values.INFO_UNICODE) == flags_Values.INFO_UNICODE)
                    {
                        RdpbcgrEncoder.EncodeUnicodeString(infoBuffer,
                                                           infoPacket.extraInfo.clientDir,
                                                           infoPacket.extraInfo.cbClientDir);
                    }
                    else
                    {
                        RdpbcgrEncoder.EncodeAnsiString(infoBuffer,
                                                        infoPacket.extraInfo.clientDir,
                                                        infoPacket.extraInfo.cbClientDir);
                    }

                    RdpbcgrEncoder.EncodeStructure(infoBuffer, (ushort)infoPacket.extraInfo.clientTimeZone.Bias);
                    RdpbcgrEncoder.EncodeUnicodeString(infoBuffer,
                                                       infoPacket.extraInfo.clientTimeZone.StandardName,
                                                       ConstValue.TIME_ZONE_STANDARD_NAME_SIZE);
                    RdpbcgrEncoder.EncodeStructure(infoBuffer, infoPacket.extraInfo.clientTimeZone.StandardDate);
                    RdpbcgrEncoder.EncodeStructure(infoBuffer, infoPacket.extraInfo.clientTimeZone.StandardBias);
                    RdpbcgrEncoder.EncodeUnicodeString(infoBuffer,
                                                       infoPacket.extraInfo.clientTimeZone.DaylightName,
                                                       ConstValue.TIME_ZONE_DAYLIGHT_NAME_SIZE);
                    RdpbcgrEncoder.EncodeStructure(infoBuffer, infoPacket.extraInfo.clientTimeZone.DaylightDate);
                    RdpbcgrEncoder.EncodeStructure(infoBuffer, infoPacket.extraInfo.clientTimeZone.DaylightBias);

                    RdpbcgrEncoder.EncodeStructure(infoBuffer, infoPacket.extraInfo.clientSessionId);
                    RdpbcgrEncoder.EncodeStructure(infoBuffer, (uint)infoPacket.extraInfo.performanceFlags);
                    RdpbcgrEncoder.EncodeStructure(infoBuffer, infoPacket.extraInfo.cbAutoReconnectLen);

                    if (infoPacket.extraInfo.cbAutoReconnectLen != 0)
                    {
                        RdpbcgrEncoder.EncodeStructure(infoBuffer,
                                                       (uint)infoPacket.extraInfo.autoReconnectCookie.cbLen);
                        RdpbcgrEncoder.EncodeStructure(infoBuffer,
                                                       (uint)infoPacket.extraInfo.autoReconnectCookie.Version);
                        RdpbcgrEncoder.EncodeStructure(infoBuffer, infoPacket.extraInfo.autoReconnectCookie.LogonId);
                        RdpbcgrEncoder.EncodeBytes(infoBuffer,
                                                   infoPacket.extraInfo.autoReconnectCookie.SecurityVerifier); ;
                    }

                    if (infoPacket.extraInfo.reserved1 != null)
                    {
                        RdpbcgrEncoder.EncodeStructure(infoBuffer, infoPacket.extraInfo.reserved1.actualData);
                    }

                    if (infoPacket.extraInfo.reserved2 != null)
                    {
                        RdpbcgrEncoder.EncodeStructure(infoBuffer, infoPacket.extraInfo.reserved2.actualData);
                    }

                    if (infoPacket.extraInfo.cbDynamicDSTTimeZoneKeyName != null)
                    {
                        RdpbcgrEncoder.EncodeStructure(infoBuffer, infoPacket.extraInfo.cbDynamicDSTTimeZoneKeyName.actualData);
                    }

                    if (infoPacket.extraInfo.dynamicDSTTimeZoneKeyName != null)
                    {
                        RdpbcgrEncoder.EncodeUnicodeString(infoBuffer,
                                                           infoPacket.extraInfo.dynamicDSTTimeZoneKeyName,
                                                           infoPacket.extraInfo.cbDynamicDSTTimeZoneKeyName.actualData);
                    }

                    if (infoPacket.extraInfo.dynamicDaylightTimeDisabled != null)
                    {
                        RdpbcgrEncoder.EncodeStructure(infoBuffer, infoPacket.extraInfo.dynamicDaylightTimeDisabled.actualData);
                    }
                }
            }

            return infoBuffer.ToArray();
        }