/// <summary>
        /// Create SMB_COM_NEGOTIATE response 
        /// </summary>
        /// <param name="connection">the connection identified the client</param>
        /// <param name = "securityMode">
        /// An 8-bit field, indicating the security modes supported or REQUIRED by the server 
        /// </param>
        /// <param name = "maxBufferSize">
        /// The maximum size, in bytes, of the largest SMB message the server can receive. This is the size of the  
        /// SMB message that the client MAY send to the server. SMB message size includes the size of the  SMB  
        /// parameter, and data blocks. This size does not include any  transport-layer framing or other  data. The 
        /// server MUST provide a MaxBufferSize of 1024 bytes (1Kbyte) or larger. If CAP_RAW_MODE is  then the 
        /// SMB_COM_WRITE_RAW command can bypass the MaxBufferSize limit. Otherwise, SMB messages sent to  server  
        /// MUST have a total size less than or equal to the MaxBufferSize value. This includes AndX chained 
        /// </param>
        /// <param name="maxMpxCount">
        /// The maximum number of outstanding SMB operations the server supports. This value includes existing 
        /// OpLocks, the NT_TRANSACT_NOTIFY_CHANGE subcommand, and any other command that are pending on the server. 
        /// If the negotiated MaxMpxCount is one, then OpLock support MUST be disabled for this session. The 
        /// MaxMpxCount MUST be greater than zero. This parameter has no specific relationship to the 
        /// SMB_COM_READ_MPX and SMB_COM_WRITE_MPX commands. 
        /// </param>
        /// <returns>a smb negotiate response packet </returns>
        /// <exception cref="ArgumentNullException">connection must not be null</exception>
        /// <exception cref="NotImplementedException">the security package is invalid</exception>
        public virtual SmbNegotiateResponsePacket CreateSmbComNegotiateResponse(
            SmbServerConnection connection,
            SecurityModes securityMode,
            uint maxBufferSize,
            ushort maxMpxCount)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            SmbNegotiateResponsePacket packet = new SmbNegotiateResponsePacket();

            // create smb packet header
            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(
                SmbCommand.SMB_COM_NEGOTIATE, connection.ProcessId, connection.MessageId, 0, 0,
                (SmbFlags)connection.Capability.Flag, (SmbFlags2)connection.Capability.Flags2);

            // update smb parameters
            SMB_COM_NEGOTIATE_NtLanManagerResponse_SMB_Parameters smbParameters = packet.SmbParameters;

            ushort dialectIndex = 0x00;
            byte wordCount = 0x00;
            connection.GetPreferedDialectIndex(out dialectIndex, out wordCount);

            smbParameters.WordCount = wordCount;
            smbParameters.DialectIndex = dialectIndex;
            smbParameters.SecurityMode = securityMode;
            smbParameters.MaxBufferSize = maxBufferSize;
            smbParameters.MaxMpxCount = maxMpxCount;
            smbParameters.Capabilities = connection.ServerCapabilities;
            smbParameters.SystemTime.Time = (ulong)DateTime.Now.ToFileTime();

            // update smb data
            SMB_COM_NEGOTIATE_NtLanManagerResponse_SMB_Data smbData = packet.SmbData;

            if (connection.GssApi == null)
            {
                connection.GssApi = new SspiServerSecurityContext(
                    SecurityPackageType.Negotiate,
                    this.credential,
                    "cifs/" + Environment.MachineName,
                    ServerSecurityContextAttribute.Connection,
                    SecurityTargetDataRepresentation.SecurityNetworkDrep);
            }

            // to generate the token.
            connection.GssApi.Accept(null);

            smbData.SecurityBlob = connection.GssApi.Token;

            // update smbData.ByteCount
            smbData.ByteCount = 0;
            smbData.ByteCount += (ushort)CifsMessageUtils.GetSize<Guid>(smbData.ServerGuid);
            if (smbData.SecurityBlob != null)
            {
                smbData.ByteCount += (ushort)smbData.SecurityBlob.Length;
            }

            // store the parameters and data to packet.
            packet.SmbParameters = smbParameters;
            packet.SmbData = smbData;

            return packet;
        }
        /// <summary>
        /// Create SMB_COM_NEGOTIATE response 
        /// </summary>
        /// <param name="connection">the connection identified the client</param>
        /// <param name = "securityMode">
        /// An 8-bit field, indicating the security modes supported or REQUIRED by the server 
        /// </param>
        /// <param name = "maxBufferSize">
        /// The maximum size, in bytes, of the largest SMB message the servercan receive. This is the size of the  SMB 
        /// message that the clientMAY send to the server. SMB message size includes the size of the SMB header,  and 
        /// data blocks. This size does not include any transport-layer framing or other transport-layer data.  server 
        /// MUSTprovide a MaxBufferSize of 1024 bytes (1Kbyte) or larger.If CAP_RAW_MODE is negotiated, then  
        /// SMB_COM_WRITE_RAW commandcan bypass the MaxBufferSize limit. Otherwise, SMB messages sent to the server  
        /// have a total size less than or equal to the MaxBufferSize value.This includes AndX chained  default 
        /// MaxBufferSize on Windows NT server is 4356 bytes(4KB + 260Bytes) if the server has 512MB of  or less. If 
        /// the server has more than 512MB of memory, then the default MaxBufferSize is 16644 bytes (16KB  260Bytes). 
        /// Windows NT servers always use a MaxBufferSize value that is a multiple of four (4). The  can be configured 
        /// through the following registry setting: 
        /// </param>
        /// <param name="maxMpxCount">
        /// The maximum number of outstanding SMB operations the server
        /// supports. This value includes existing OpLocks, 
        /// the NT_TRANSACT_NOTIFY_CHANGE subcommand, and any other command 
        /// that are pending on the server. If the negotiated MaxMpxCount is one, 
        /// then OpLock support MUST be disabled for this session. The MaxMpxCount
        /// MUST be greater than zero. This parameter has no specific 
        /// relationship to the SMB_COM_READ_MPX and SMB_COM_WRITE_MPX commands. 
        /// </param>
        /// <returns>a smb implicit ntlm negotiate response packet </returns>
        /// <exception cref="ArgumentNullException">connection must not be null</exception>
        public virtual SmbNegotiateImplicitNtlmResponsePacket CreateSmbComNegotiateImplicitNtlmResponse(
            SmbServerConnection connection,
            SecurityModes securityMode,
            uint maxBufferSize,
            ushort maxMpxCount)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            Cifs.SmbNegotiateResponsePacket packet = new Cifs.SmbNegotiateResponsePacket();

            // create smb packet header
            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(
                SmbCommand.SMB_COM_NEGOTIATE, connection.ProcessId, connection.MessageId, 0, 0,
                (SmbFlags)connection.Capability.Flag, (SmbFlags2)connection.Capability.Flags2);

            // update smb parameters
            Cifs.SMB_COM_NEGOTIATE_NtLanManagerResponse_SMB_Parameters smbParameters = packet.SmbParameters;

            ushort dialectIndex = 0x00;
            byte wordCount = 0x00;
            connection.GetPreferedDialectIndex(out dialectIndex, out wordCount);

            smbParameters.WordCount = wordCount;
            smbParameters.DialectIndex = dialectIndex;
            smbParameters.SecurityMode = securityMode;
            smbParameters.MaxBufferSize = maxBufferSize;
            smbParameters.MaxMpxCount = maxMpxCount;
            smbParameters.Capabilities = (Cifs.Capabilities)connection.ServerCapabilities;
            smbParameters.SystemTime.Time = (ulong)connection.SystemTime;
            smbParameters.ChallengeLength = (byte)connection.NtlmEncryptionKey.Length;

            // update smb data
            Cifs.SMB_COM_NEGOTIATE_NtLanManagerResponse_SMB_Data smbData = packet.SmbData;

            smbData.Challenge = connection.NtlmEncryptionKey;

            // update smbData.ByteCount
            smbData.ByteCount = 0;
            if (smbData.Challenge != null)
            {
                smbData.ByteCount += (ushort)smbData.Challenge.Length;
            }
            if (smbData.DomainName != null)
            {
                smbData.ByteCount += (ushort)smbData.DomainName.Length;
            }

            // store the parameters and data to packet.
            packet.SmbParameters = smbParameters;
            packet.SmbData = smbData;

            return new SmbNegotiateImplicitNtlmResponsePacket(packet);
        }