/// <summary>
 /// Deep copy constructor.
 /// </summary>
 public CifsClientPerOpenFile(CifsClientPerOpenFile smbClientPerOpen)
     : base(smbClientPerOpen)
 {
     lock (smbClientPerOpen)
     {
         this.fileHandle = smbClientPerOpen.fileHandle;
         this.fileName   = smbClientPerOpen.fileName;
     }
 }
 /// <summary>
 /// Deep copy constructor.
 /// </summary>
 public CifsClientPerOpenFile(CifsClientPerOpenFile smbClientPerOpen)
     : base(smbClientPerOpen)
 {
     lock (smbClientPerOpen)
     {
         this.fileHandle = smbClientPerOpen.fileHandle;
         this.fileName = smbClientPerOpen.fileName;
     }
 }
 /// <summary>
 /// Add Or Update an Open in the OpenFileTable of the session.
 /// </summary>
 /// <param name="open">the open to be added or updated.</param>
 /// <returns>if the connection exists, add or update the session and return true. otherwise return
 /// false.</returns>
 private bool AddOrUpdateOpenFileInSession(CifsClientPerOpenFile open)
 {
     for (int i = this.contextCollection.ConnectionList.Count - 1; i >= 0; i--)
     {
         CifsClientPerConnection connection = this.contextCollection.ConnectionList[i] as
             CifsClientPerConnection;
         // if the connection exists, add or update the open:
         if (connection.ConnectionId == open.ConnectionId)
         {
             for (int j = connection.SessionTable.Count - 1; j >= 0; j--)
             {
                 CifsClientPerSession session = connection.SessionTable[j] as CifsClientPerSession;
                 // if the session exists, add or update the open:
                 if (session.SessionId == open.SessionId)
                 {
                     // if the open exists, update it:
                     for (int k = session.OpenFileTable.Count - 1; k >= 0; k--)
                     {
                         if (session.OpenFileTable[k].Volatile == open.Volatile
                             && session.OpenFileTable[k].Volatile == open.Volatile)
                         {
                             // update the open:
                             session.OpenFileTable[k] = open;
                             return true;
                         }
                     }
                     // add the open:
                     open.GlobalIndex = this.contextCollection.NextOpenGlobalIndex;
                     open.Volatile = (ulong)open.GlobalIndex;
                     session.OpenFileTable.Add(open);
                     return true;
                 }
             }
             return false;
         }
     }
     return false;
 }
 /// <summary>
 /// Add Or Update an Open in the GlobalOpenFileTable.
 /// </summary>
 /// <param name="open">the open to be added or updated.</param>
 private void AddOrUpdateOpenFileInGlobal(CifsClientPerOpenFile open)
 {
     for (int i = this.contextCollection.GlobalOpenFileTable.Count - 1; i >= 0; i--)
     {
         if (this.contextCollection.GlobalOpenFileTable[i].ConnectionId == open.ConnectionId
             && this.contextCollection.GlobalOpenFileTable[i].SessionId == open.SessionId
             && this.contextCollection.GlobalOpenFileTable[i].TreeConnectId == open.TreeConnectId
             && this.contextCollection.GlobalOpenFileTable[i].Persistent == open.Persistent
             && this.contextCollection.GlobalOpenFileTable[i].Volatile == open.Volatile)
         {
             // update the open:
             this.contextCollection.GlobalOpenFileTable[i] = open;
             return;
         }
     }
     // add the open:
     open.GlobalIndex = this.contextCollection.NextOpenGlobalIndex;
     open.Volatile = (ulong)open.GlobalIndex;
     this.contextCollection.GlobalOpenFileTable.Add(open);
     this.contextCollection.NextOpenGlobalIndex += 1;
 }
        /// <summary>
        /// if the open identified by the connectionId, sessionId, treeId, fileHandle has 
        /// been existed in globalOpenTable, this open will be updated into the globalOpenTable.
        /// otherwise, this open will be added into the globalOpenTable.
        /// </summary>
        /// <param name="open">the open to be added or updated.</param>
        /// <exception cref="System.InvalidOperationException">Failed in AddOrUpdateOpen because
        /// the Session or Connection of the Open does not found.</exception>
        public void AddOrUpdateOpenFile(CifsClientPerOpenFile open)
        {
            if (open == null)
            {
                return;
            }

            lock (this.contextCollection)
            {
                if (AddOrUpdateOpenFileInSession(open))
                {
                    AddOrUpdateOpenFileInGlobal(open);
                }
                else
                {
                    throw new InvalidOperationException(
                        "Failed in AddOrUpdateOpen because the Session or Connection of the Open does not found.");
                }
            }
        }
        protected virtual void ResponsePacketUpdateRoleContext(
            CifsClientPerConnection connection,
            SmbPacket request,
            SmbPacket response)
        {
            int connectionId = connection.ConnectionId;

            if (request ==null | response == null)
            {
                return;
            }

            #region To update Connection/Session/Tree/Open with response

            // Update context with success response:
            if (response.SmbHeader.Status == 0)
            {
                CifsClientPerSession session = new CifsClientPerSession();
                CifsClientPerTreeConnect tree = new CifsClientPerTreeConnect();
                CifsClientPerOpenFile openFile = new CifsClientPerOpenFile();
                CifsClientPerOpenSearch openSearch = new CifsClientPerOpenSearch();
                switch (response.SmbHeader.Command)
                {
                    #region connection
                    case SmbCommand.SMB_COM_NEGOTIATE:
                        #region SMB_COM_NEGOTIATE
                        SmbNegotiateRequestPacket negotiateRequest = request as SmbNegotiateRequestPacket;
                        SmbNegotiateResponsePacket negotiateResponse = response as SmbNegotiateResponsePacket;
                        if (negotiateRequest == null || negotiateResponse == null)
                        {
                            break;
                        }
                        // base class Connection:
                        connection.NegotiateReceived = true;
                        // common ADM:
                        int dialectIndex = (int)(negotiateResponse.SmbParameters.DialectIndex);
                        byte[] dialectBytes = negotiateRequest.SmbData.Dialects;
                        int startIndex = 0;
                        for (int i = 0; i < dialectIndex; i++)
                        {
                            startIndex = Array.IndexOf<byte>(dialectBytes, 0, startIndex,
                                dialectBytes.Length - startIndex) + 1;
                        }
                        connection.SelectedDialect = CifsMessageUtils.ToSmbString(dialectBytes, startIndex, true);
                        // client ADM:
                        connection.ShareLevelAccessControl = ((negotiateResponse.SmbParameters.SecurityMode
                            & SecurityModes.NEGOTIATE_ENCRYPT_PASSWORDS) == SecurityModes.NONE);
                        connection.ServerChallengeResponse = ((negotiateResponse.SmbParameters.SecurityMode
                            & SecurityModes.NEGOTIATE_ENCRYPT_PASSWORDS)
                            == SecurityModes.NEGOTIATE_ENCRYPT_PASSWORDS);
                        if (connection.ServerChallengeResponse
                            && ((negotiateResponse.SmbParameters.SecurityMode
                            & SecurityModes.NEGOTIATE_SECURITY_SIGNATURES_ENABLED)
                            == SecurityModes.NEGOTIATE_SECURITY_SIGNATURES_ENABLED))
                        {
                            connection.ServerSigningState = SignStateValue.ENABLED;
                        }
                        if (connection.ServerSigningState == SignStateValue.ENABLED
                           && ((negotiateResponse.SmbParameters.SecurityMode
                           & SecurityModes.NEGOTIATE_SECURITY_SIGNATURES_REQUIRED)
                           == SecurityModes.NEGOTIATE_SECURITY_SIGNATURES_REQUIRED))
                        {
                            connection.ServerSigningState = SignStateValue.REQUIRED;
                        }
                        connection.ServerCapabilities = negotiateResponse.SmbParameters.Capabilities;
                        connection.MaxBufferSize = negotiateResponse.SmbParameters.MaxBufferSize;
                        // negotiate response:
                        connection.SecurityMode = negotiateResponse.SmbParameters.SecurityMode;
                        connection.MaxMpxCount = negotiateResponse.SmbParameters.MaxMpxCount;
                        connection.MaxNumberVcs = negotiateResponse.SmbParameters.MaxNumberVcs;
                        connection.MaxRawSize = negotiateResponse.SmbParameters.MaxRawSize;
                        connection.SessionKey = negotiateResponse.SmbParameters.SessionKey;
                        connection.SystemTime = negotiateResponse.SmbParameters.SystemTime.Time;
                        connection.ServerTimeZone = negotiateResponse.SmbParameters.ServerTimeZone;
                        if (negotiateResponse.SmbData.Challenge != null
                            && negotiateResponse.SmbData.Challenge.Length >= 8)
                        {
                            connection.Challenge =
                                BitConverter.ToUInt64(negotiateResponse.SmbData.Challenge, 0);
                        }
                        if (negotiateResponse.SmbData.DomainName != null)
                        {
                            connection.DomainName = new byte[negotiateResponse.SmbData.DomainName.Length];
                            Array.Copy(negotiateResponse.SmbData.DomainName, connection.DomainName,
                                negotiateResponse.SmbData.DomainName.Length);
                        }
                        // stack sdk design:
                        connection.ConnectionState = StackTransportState.ConnectionEstablished;
                        // update:
                        this.AddOrUpdateConnection(connection);
                        #endregion
                        break;
                    #endregion

                    #region session
                    case SmbCommand.SMB_COM_SESSION_SETUP_ANDX:
                        #region SMB_COM_SESSION_SETUP_ANDX
                        SmbSessionSetupAndxRequestPacket sessionSetupRequest =
                            request as SmbSessionSetupAndxRequestPacket;
                        SmbSessionSetupAndxResponsePacket sessionSetupResponse =
                            response as SmbSessionSetupAndxResponsePacket;
                        if (sessionSetupRequest == null || sessionSetupResponse == null)
                        {
                            break;
                        }

                        session.ConnectionId = connectionId;
                        session.SessionId = (ulong)sessionSetupResponse.SmbHeader.Uid;
                        // in request:
                        session.SessionKey = sessionSetupRequest.ImplicitNtlmSessionKey;
                        session.MaxBufferSize = sessionSetupRequest.SmbParameters.MaxBufferSize;
                        session.MaxMpxCount = sessionSetupRequest.SmbParameters.MaxMpxCount;
                        session.VcNumber = sessionSetupRequest.SmbParameters.VcNumber;
                        session.SessionKeyOfNegotiated = sessionSetupRequest.SmbParameters.SessionKey;
                        session.Capabilities = sessionSetupRequest.SmbParameters.Capabilities;
                        if ((sessionSetupRequest.SmbHeader.Flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) ==
                            SmbFlags2.SMB_FLAGS2_UNICODE)
                        {
                            session.UserAccount = new CifsUserAccount(
                                Encoding.Unicode.GetString(sessionSetupRequest.SmbData.PrimaryDomain),
                                Encoding.Unicode.GetString(sessionSetupRequest.SmbData.AccountName),
                                Encoding.Unicode.GetString(sessionSetupRequest.SmbData.OEMPassword));
                            session.ClientNativeOs =
                                Encoding.Unicode.GetString(sessionSetupRequest.SmbData.NativeOS);
                            session.ClientNativeLanMan =
                                Encoding.Unicode.GetString(sessionSetupRequest.SmbData.NativeLanMan);
                        }
                        else
                        {
                            session.UserAccount = new CifsUserAccount(
                                Encoding.ASCII.GetString(sessionSetupRequest.SmbData.PrimaryDomain),
                                Encoding.ASCII.GetString(sessionSetupRequest.SmbData.AccountName),
                                Encoding.ASCII.GetString(sessionSetupRequest.SmbData.OEMPassword));
                            session.ClientNativeOs =
                                Encoding.ASCII.GetString(sessionSetupRequest.SmbData.NativeOS);
                            session.ClientNativeLanMan =
                                Encoding.ASCII.GetString(sessionSetupRequest.SmbData.NativeLanMan);
                        }
                        // in response:
                        session.Action = sessionSetupResponse.SmbParameters.Action;
                        if ((sessionSetupResponse.SmbHeader.Flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) ==
                            SmbFlags2.SMB_FLAGS2_UNICODE)
                        {
                            session.ServerNativeOs =
                                Encoding.Unicode.GetString(sessionSetupResponse.SmbData.NativeOS);
                            session.ServerNativeLanMan =
                                Encoding.Unicode.GetString(sessionSetupResponse.SmbData.NativeLanMan);
                            session.ServerPrimaryDomain =
                                Encoding.Unicode.GetString(sessionSetupResponse.SmbData.PrimaryDomain);
                        }
                        else
                        {
                            session.ServerNativeOs =
                                Encoding.ASCII.GetString(sessionSetupResponse.SmbData.NativeOS);
                            session.ServerNativeLanMan =
                                Encoding.ASCII.GetString(sessionSetupResponse.SmbData.NativeLanMan);
                            session.ServerPrimaryDomain =
                                Encoding.ASCII.GetString(sessionSetupResponse.SmbData.PrimaryDomain);
                        }

                        if (connection.ShareLevelAccessControl == false)
                        {
                            connection.IsSigningActive = true;
                            connection.ConnectionSigningSessionKey = sessionSetupRequest.ImplicitNtlmSessionKey;
                            connection.ConnectionSigningChallengeResponse = sessionSetupRequest.SmbData.UnicodePassword;
                            AddOrUpdateConnection(connection);
                        }

                        // update:
                        this.AddOrUpdateSession(session);
                        #endregion
                        break;

                    case SmbCommand.SMB_COM_LOGOFF_ANDX:
                        #region SMB_COM_LOGOFF_ANDX
                        SmbLogoffAndxResponsePacket logoffResponse = response as SmbLogoffAndxResponsePacket;
                        if (logoffResponse == null)
                        {
                            break;
                        }
                        this.RemoveSession(connectionId, (ulong)logoffResponse.SmbHeader.Uid);
                        #endregion
                        break;
                    #endregion

                    #region treeconnect
                    case SmbCommand.SMB_COM_TREE_CONNECT:
                        #region SMB_COM_TREE_CONNECT
                        SmbTreeConnectRequestPacket treeConnectRequest =
                            request as SmbTreeConnectRequestPacket;
                        SmbTreeConnectResponsePacket treeConnectResponse =
                            response as SmbTreeConnectResponsePacket;
                        if (treeConnectRequest == null || treeConnectResponse == null)
                        {
                            break;
                        }
                        tree.ConnectionId = connectionId;
                        tree.SessionId = (ulong)treeConnectResponse.SmbHeader.Uid;
                        tree.TreeId = (ulong)treeConnectResponse.SmbHeader.Tid;
                        tree.ShareName = CifsMessageUtils.ToSmbString(treeConnectRequest.SmbData.Path, 0, false);
                        int index = tree.ShareName.LastIndexOf(@"\");
                        if (index > 0)
                        {
                            tree.Share = tree.ShareName.Substring(index + 1);
                        }
                        else
                        {
                            tree.Share = tree.ShareName;
                        }
                        this.AddOrUpdateTreeConnect(tree);
                        #endregion
                        break;

                    case SmbCommand.SMB_COM_TREE_CONNECT_ANDX:
                        #region SMB_COM_TREE_CONNECT_ANDX
                        SmbTreeConnectAndxRequestPacket treeConnectAndxRequest =
                            request as SmbTreeConnectAndxRequestPacket;
                        SmbTreeConnectAndxResponsePacket treeConnectAndxResponse =
                            response as SmbTreeConnectAndxResponsePacket;
                        if (treeConnectAndxRequest == null || treeConnectAndxResponse == null)
                        {
                            break;
                        }
                        tree.ConnectionId = connectionId;
                        tree.SessionId = (ulong)treeConnectAndxResponse.SmbHeader.Uid;
                        tree.TreeId = (ulong)treeConnectAndxResponse.SmbHeader.Tid;
                        if ((treeConnectAndxRequest.SmbHeader.Flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) ==
                            SmbFlags2.SMB_FLAGS2_UNICODE)
                        {
                            tree.ShareName = Encoding.Unicode.GetString(treeConnectAndxRequest.SmbData.Path);
                        }
                        else
                        {
                            tree.ShareName = Encoding.ASCII.GetString(treeConnectAndxRequest.SmbData.Path);
                        }
                        int IndexOfShare = tree.ShareName.LastIndexOf(@"\");
                        if (IndexOfShare > 0)
                        {
                            tree.Share = tree.ShareName.Substring(IndexOfShare + 1);
                        }
                        else
                        {
                            tree.Share = tree.ShareName;
                        }
                        this.AddOrUpdateTreeConnect(tree);
                        #endregion
                        break;

                    case SmbCommand.SMB_COM_TREE_DISCONNECT:
                        #region SMB_COM_TREE_DISCONNECT
                        SmbTreeDisconnectResponsePacket treeDisconnectResponse =
                            response as SmbTreeDisconnectResponsePacket;
                        if (treeDisconnectResponse == null)
                        {
                            break;
                        }
                        this.RemoveTreeConnect(connectionId,
                            (ulong)treeDisconnectResponse.SmbHeader.Uid,
                            (ulong)treeDisconnectResponse.SmbHeader.Tid);
                        #endregion
                        break;
                    #endregion

                    #region openfile
                    case SmbCommand.SMB_COM_OPEN:
                        #region SMB_COM_OPEN
                        SmbOpenRequestPacket openRequest = request as SmbOpenRequestPacket;
                        SmbOpenResponsePacket openResponse = response as SmbOpenResponsePacket;
                        if (openRequest == null || openResponse == null)
                        {
                            break;
                        }
                        openFile.ConnectionId = connectionId;
                        openFile.SessionId = (ulong)openResponse.SmbHeader.Uid;
                        openFile.TreeConnectId = (ulong)openResponse.SmbHeader.Tid;
                        openFile.FileHandle = openResponse.SmbParameters.FID;
                        openFile.FileName = CifsMessageUtils.ToSmbString(openRequest.SmbData.FileName, 0, false);
                        this.AddOrUpdateOpenFile(openFile);
                        #endregion
                        break;

                    case SmbCommand.SMB_COM_CREATE:
                        #region SMB_COM_CREATE
                        SmbCreateRequestPacket createRequest = request as SmbCreateRequestPacket;
                        SmbCreateResponsePacket createResponse = response as SmbCreateResponsePacket;
                        if (createRequest == null || createResponse == null)
                        {
                            break;
                        }
                        openFile.ConnectionId = connectionId;
                        openFile.SessionId = (ulong)createResponse.SmbHeader.Uid;
                        openFile.TreeConnectId = (ulong)createResponse.SmbHeader.Tid;
                        openFile.FileHandle = createResponse.SmbParameters.FID;
                        openFile.FileName = CifsMessageUtils.ToSmbString(createRequest.SmbData.FileName, 0, false);
                        this.AddOrUpdateOpenFile(openFile);
                        #endregion
                        break;

                    case SmbCommand.SMB_COM_CREATE_TEMPORARY:
                        #region SMB_COM_CREATE_TEMPORARY
                        SmbCreateTemporaryRequestPacket createTemporaryRequest =
                            request as SmbCreateTemporaryRequestPacket;
                        SmbCreateTemporaryResponsePacket createTemporaryResponse =
                            response as SmbCreateTemporaryResponsePacket;
                        if (createTemporaryRequest == null || createTemporaryResponse == null)
                        {
                            break;
                        }
                        openFile.ConnectionId = connectionId;
                        openFile.SessionId = (ulong)createTemporaryResponse.SmbHeader.Uid;
                        openFile.TreeConnectId = (ulong)createTemporaryResponse.SmbHeader.Tid;
                        openFile.FileHandle = createTemporaryResponse.SmbParameters.FID;
                        openFile.FileName = CifsMessageUtils.ToSmbString(
                            createTemporaryResponse.SmbData.TemporaryFileName, 0, false);
                        this.AddOrUpdateOpenFile(openFile);
                        #endregion
                        break;

                    case SmbCommand.SMB_COM_CREATE_NEW:
                        #region SMB_COM_CREATE_NEW
                        SmbCreateNewRequestPacket createNewRequest = request as SmbCreateNewRequestPacket;
                        SmbCreateNewResponsePacket createNewResponse = response as SmbCreateNewResponsePacket;
                        if (createNewRequest == null || createNewResponse == null)
                        {
                            break;
                        }
                        openFile.ConnectionId = connectionId;
                        openFile.SessionId = (ulong)createNewResponse.SmbHeader.Uid;
                        openFile.TreeConnectId = (ulong)createNewResponse.SmbHeader.Tid;
                        openFile.FileHandle = createNewResponse.SmbParameters.FID;
                        openFile.FileName = CifsMessageUtils.ToSmbString(createNewRequest.SmbData.FileName, 0, false);
                        this.AddOrUpdateOpenFile(openFile);
                        #endregion
                        break;

                    case SmbCommand.SMB_COM_OPEN_ANDX:
                        #region SMB_COM_OPEN_ANDX
                        SmbOpenAndxRequestPacket openAndxRequest = request as SmbOpenAndxRequestPacket;
                        SmbOpenAndxResponsePacket openAndxResponse = response as SmbOpenAndxResponsePacket;
                        if (openAndxRequest == null || openAndxResponse == null)
                        {
                            break;
                        }
                        openFile.ConnectionId = connectionId;
                        openFile.SessionId = (ulong)openAndxResponse.SmbHeader.Uid;
                        openFile.TreeConnectId = (ulong)openAndxResponse.SmbHeader.Tid;
                        openFile.FileHandle = openAndxResponse.SmbParameters.FID;
                        if ((openAndxRequest.SmbHeader.Flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) ==
                            SmbFlags2.SMB_FLAGS2_UNICODE)
                        {
                            openFile.FileName = Encoding.Unicode.GetString(openAndxRequest.SmbData.FileName);
                        }
                        else
                        {
                            openFile.FileName = Encoding.ASCII.GetString(openAndxRequest.SmbData.FileName);
                        }
                        this.AddOrUpdateOpenFile(openFile);
                        #endregion

                        //save FID for chained response like:
                        //treeConnect->openAndx->readAndx->close
                        //when "close", FID is need to close the open opened in openAndx.
                        if (openAndxResponse.AndxPacket != null)
                        {
                            //borrow smbHeader.Protocol to save FID for later process.
                            //smbHeader.Protocol also use a flag to differentiate a single packet from a
                            //batched andx packet.
                            //FID is ushort, impossible to impact smbHeader.Protocol's usage as
                            //a real packet header 0x424D53FF(0xFF, 'S', 'M', 'B')
                            SmbHeader andxHeader = openAndxResponse.AndxPacket.SmbHeader;
                            andxHeader.Protocol = openAndxResponse.SmbParameters.FID;
                            openAndxResponse.AndxPacket.SmbHeader = andxHeader;
                        }
                        break;

                    case SmbCommand.SMB_COM_NT_CREATE_ANDX:
                        #region SMB_COM_NT_CREATE_ANDX
                        SmbNtCreateAndxRequestPacket ntCreateAndxRequest =
                            request as SmbNtCreateAndxRequestPacket;
                        SmbNtCreateAndxResponsePacket ntCreateAndxResponse =
                            response as SmbNtCreateAndxResponsePacket;
                        if (ntCreateAndxRequest == null || ntCreateAndxResponse == null)
                        {
                            break;
                        }
                        openFile.ConnectionId = connectionId;
                        openFile.SessionId = (ulong)ntCreateAndxResponse.SmbHeader.Uid;
                        openFile.TreeConnectId = (ulong)ntCreateAndxResponse.SmbHeader.Tid;
                        openFile.FileHandle = ntCreateAndxResponse.SmbParameters.FID;
                        if ((ntCreateAndxRequest.SmbHeader.Flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) ==
                            SmbFlags2.SMB_FLAGS2_UNICODE)
                        {
                            openFile.FileName = Encoding.Unicode.GetString(ntCreateAndxRequest.SmbData.FileName);
                        }
                        else
                        {
                            openFile.FileName = Encoding.ASCII.GetString(ntCreateAndxRequest.SmbData.FileName);
                        }
                        this.AddOrUpdateOpenFile(openFile);
                        #endregion
                        break;

                    case SmbCommand.SMB_COM_OPEN_PRINT_FILE:
                        #region SMB_COM_OPEN_PRINT_FILE
                        SmbOpenPrintFileRequestPacket openPrintFileRequest =
                            request as SmbOpenPrintFileRequestPacket;
                        SmbOpenPrintFileResponsePacket openPrintFileResponse =
                            response as SmbOpenPrintFileResponsePacket;
                        if (openPrintFileRequest == null || openPrintFileResponse == null)
                        {
                            break;
                        }
                        openFile.ConnectionId = connectionId;
                        openFile.SessionId = (ulong)openPrintFileResponse.SmbHeader.Uid;
                        openFile.TreeConnectId = (ulong)openPrintFileResponse.SmbHeader.Tid;
                        openFile.FileHandle = openPrintFileResponse.SmbParameters.FID;
                        openFile.FileName = CifsMessageUtils.ToSmbString(
                            openPrintFileRequest.SmbData.Identifier, 0, false);
                        this.AddOrUpdateOpenFile(openFile);
                        #endregion
                        break;

                    case SmbCommand.SMB_COM_TRANSACTION2:
                        #region Trans2Open2
                        SmbTrans2Open2RequestPacket trans2Open2Request =
                            request as SmbTrans2Open2RequestPacket;
                        SmbTrans2Open2FinalResponsePacket trans2Open2Response =
                            response as SmbTrans2Open2FinalResponsePacket;
                        if (trans2Open2Request != null && trans2Open2Response != null)
                        {
                            openFile.ConnectionId = connectionId;
                            openFile.SessionId = (ulong)trans2Open2Response.SmbHeader.Uid;
                            openFile.TreeConnectId = (ulong)trans2Open2Response.SmbHeader.Tid;
                            openFile.FileHandle = trans2Open2Response.Trans2Parameters.Fid;
                            if ((trans2Open2Request.SmbHeader.Flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) ==
                                SmbFlags2.SMB_FLAGS2_UNICODE)
                            {
                                openFile.FileName = Encoding.Unicode.GetString(
                                    trans2Open2Request.Trans2Parameters.FileName);
                            }
                            else
                            {
                                openFile.FileName = Encoding.ASCII.GetString(
                                    trans2Open2Request.Trans2Parameters.FileName);
                            }
                            this.AddOrUpdateOpenFile(openFile);
                            break;
                        }
                        #endregion

                        #region Trans2FindFirst2
                        SmbTrans2FindFirst2RequestPacket trans2FindFirst2Request =
                            request as SmbTrans2FindFirst2RequestPacket;
                        SmbTrans2FindFirst2FinalResponsePacket trans2FindFirst2Response =
                            response as SmbTrans2FindFirst2FinalResponsePacket;
                        if (trans2FindFirst2Request != null && trans2FindFirst2Response != null)
                        {
                            openSearch.ConnectionId = connectionId;
                            openSearch.SessionId = (ulong)trans2FindFirst2Response.SmbHeader.Uid;
                            openSearch.TreeConnectId = (ulong)trans2FindFirst2Response.SmbHeader.Tid;
                            openSearch.SearchID = trans2FindFirst2Response.Trans2Parameters.SID;
                            if ((trans2FindFirst2Request.SmbHeader.Flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) ==
                                SmbFlags2.SMB_FLAGS2_UNICODE)
                            {
                                openSearch.SearchName = Encoding.Unicode.GetString(
                                    trans2FindFirst2Request.Trans2Parameters.FileName);
                            }
                            else
                            {
                                openSearch.SearchName = Encoding.ASCII.GetString(
                                    trans2FindFirst2Request.Trans2Parameters.FileName);
                            }
                            this.AddOrUpdateOpenSearch(openSearch);
                            break;
                        }
                        #endregion
                        break;

                    case SmbCommand.SMB_COM_WRITE_AND_CLOSE:
                        #region SMB_COM_WRITE_AND_CLOSE
                        SmbWriteAndCloseRequestPacket writeAndCloseRequest =
                            request as SmbWriteAndCloseRequestPacket;
                        if (writeAndCloseRequest == null)
                        {
                            break;
                        }
                        this.RemoveOpenFile(connectionId, (ulong)response.SmbHeader.Uid,
                            (ulong)response.SmbHeader.Tid, writeAndCloseRequest.SmbParameters.FID);
                        #endregion
                        break;

                    case SmbCommand.SMB_COM_CLOSE:
                        #region SMB_COM_CLOSE
                        // Get FID from CLOSE request.
                        // If fail, then get FID from the Batched Request.
                        // If still fail, then Get FID from the Batched Response.
                        ushort closeFId = 0;
                        SmbCloseRequestPacket closeRequest = request as SmbCloseRequestPacket;
                        if (closeRequest != null)
                        {
                            //Neither SMB_PROTOCOL_IDENTIFIER, or SMB_PROTOCOL_ANDXPACKET, then must be a FID
                            if (response.SmbHeader.Protocol != CifsMessageUtils.SMB_PROTOCOL_IDENTIFIER
                                && response.SmbHeader.Protocol != CifsMessageUtils.SMB_PROTOCOL_ANDXPACKET)
                            {
                                closeFId = (ushort)response.SmbHeader.Protocol;
                            }
                            else
                            {
                                closeFId = closeRequest.SmbParameters.FID;
                            }
                            this.RemoveOpenFile(connectionId, (ulong)response.SmbHeader.Uid,
                                (ulong)response.SmbHeader.Tid, closeFId);
                        }

                        #endregion
                        break;
                    #endregion

                    #region opensearch
                    case SmbCommand.SMB_COM_FIND_CLOSE2:
                        #region SMB_COM_FIND_CLOSE2
                        SmbFindClose2RequestPacket findClose2Request =
                            request as SmbFindClose2RequestPacket;
                        if (findClose2Request == null)
                        {
                            break;
                        }
                        this.RemoveOpenSearch(connectionId, (ulong)response.SmbHeader.Uid,
                            (ulong)response.SmbHeader.Tid, findClose2Request.SmbParameters.SearchHandle);
                        #endregion
                        break;
                    #endregion

                    default:
                        // No Connection/Session/Tree/Open will be updated if other types of response.
                        break;
                }

                SmbBatchedRequestPacket smbBatchedRequest = request as SmbBatchedRequestPacket;
                SmbBatchedResponsePacket smbBatchedResponse = response as SmbBatchedResponsePacket;

                if (smbBatchedRequest != null && smbBatchedResponse != null)
                {
                    //pass the FID stored in the andxHeader.Protocol into response.AndxPacket
                    if (smbBatchedRequest.AndxPacket != null && smbBatchedResponse.AndxPacket != null
                        && response.SmbHeader.Protocol != CifsMessageUtils.SMB_PROTOCOL_ANDXPACKET
                        && response.SmbHeader.Protocol != CifsMessageUtils.SMB_PROTOCOL_IDENTIFIER)
                    {
                        SmbHeader andxHeader = smbBatchedResponse.AndxPacket.SmbHeader;
                        andxHeader.Protocol = smbBatchedResponse.SmbHeader.Protocol;
                        smbBatchedResponse.AndxPacket.SmbHeader = andxHeader;
                    }
                    this.ResponsePacketUpdateRoleContext(connection, smbBatchedRequest.AndxPacket,
                        smbBatchedResponse.AndxPacket);
                }
            }
            #endregion
        }
 /// <summary>
 /// Constructor with base class.
 /// </summary>
 internal SmbClientOpen(CifsClientPerOpenFile open)
     : base(open)
 {
 }