/// <summary>
        /// create negotiate request packet. client sends this packet to server to negotiate the dialects. 
        /// </summary>
        /// <param name = "messageId">
        /// This field SHOULD be the multiplex ID that is used to associate a response with a request, as specified in 
        ///  [CIFS] sections 2.4.2 and 3.1.5. 
        /// </param>
        /// <param name = "flags">
        /// The Flags field contains individual flags, as specified in [CIFS] sections 2.4.2 and 3.1.1. 
        /// </param>
        /// <param name = "flags2">
        /// The Flags2 field contains individual bit flags that, depending on the negotiated SMB dialect, indicate   
        /// various client and server capabilities. 
        /// </param>
        /// <param name = "dialects">
        /// Array of null-terminated ASCII strings that indicate the SMB dialects supported by the client. 
        /// </param>
        /// <returns>a smb negotiate packet. </returns>
        private SmbNegotiateRequestPacket CreateNegotiateRequest(
            ushort messageId,
            SmbHeader_Flags_Values flags,
            SmbHeader_Flags2_Values flags2,
            params string[] dialects)
        {
            // update global context using flags2
            this.capability.IsSupportsExtendedSecurity =
                (flags2 & SmbHeader_Flags2_Values.SMB_FLAGS2_EXTENDED_SECURITY)
                == SmbHeader_Flags2_Values.SMB_FLAGS2_EXTENDED_SECURITY;

            this.capability.IsUnicode =
                (flags2 & SmbHeader_Flags2_Values.SMB_FLAGS2_UNICODE)
                == SmbHeader_Flags2_Values.SMB_FLAGS2_UNICODE;

            this.capability.IsKnowEAS =
                (flags2 & SmbHeader_Flags2_Values.SMB_FLAGS2_KNOWS_EAS)
                == SmbHeader_Flags2_Values.SMB_FLAGS2_KNOWS_EAS;

            // initialize the dialects
            SMB_Dialect[] smbDialects = new SMB_Dialect[dialects.Length];

            for (int i = 0; i < smbDialects.Length; i++)
            {
                SMB_Dialect dialect = new SMB_Dialect();

                // Each string MUST be prefixed with ASCII code 0x02
                dialect.BufferFormat = 0x02;
                dialect.DialectString = dialects[i];

                smbDialects[i] = dialect;
            }

            return new SmbNegotiateRequestPacket(
                this.cifsClient.CreateNegotiateRequest(messageId, (SmbFlags)flags, (SmbFlags2)flags2, smbDialects));
        }
 /// <summary>
 /// to create a Negotiate request packet.
 /// </summary>
 /// <param name="dialects">This is a variable length list of dialect identifiers in order of preference from
 /// least to most preferred</param>
 /// <returns>a Negotiate request packet</returns>
 /// <exception cref="System.NullReferenceException">There is no connection in context. </exception>
 public SmbNegotiateRequestPacket CreateNegotiateRequest(
     SMB_Dialect[] dialects)
 {
     return this.CreateNegotiateRequest(this.Context.GetMessageId(this.connectionId),
         this.defaultParameters.Flag, this.defaultParameters.Flag2, dialects);
 }
        /// <summary>
        /// Set up connection with server.
        /// Including 4 steps: 1. Tcp connection 2. Negotiation 3. SessionSetup 4. TreeConnect in order
        /// </summary>
        /// <param name="server">server name of ip address</param>
        /// <param name="client">client name of ip address</param>
        /// <param name="domain">user's domain</param>
        /// <param name="userName">user's name</param>
        /// <param name="password">user's password</param>
        /// <param name="timeout">The pending time to get server's response in step 2, 3 or 4</param>
        /// <exception cref="System.Net.ProtocolViolationException">Fail to set up connection with server</exception>
        public override void Connect(
            string server,
            string client,
            string domain,
            string userName,
            string password,
            TimeSpan timeout,
            SecurityPackageType securityPackage = SecurityPackageType.Ntlm,
            bool useServerToken = false)
        {
            this.cifsClient.Connect(server, client);

            SmbPacket request, response;
            uint status;

            // Negotiate:
            SMB_Dialect dialectLM21 = new SMB_Dialect();
            dialectLM21.BufferFormat = dialectBufferFormat;
            dialectLM21.DialectString = dialectLanMan21;
            SMB_Dialect dialectNTLM = new SMB_Dialect();
            dialectNTLM.BufferFormat = dialectBufferFormat;
            dialectNTLM.DialectString = dialectNtLanMan;
            request = this.cifsClient.CreateNegotiateRequest(new SMB_Dialect[] { dialectLM21, dialectNTLM });
            this.cifsClient.SendPacket(request);
            response = this.cifsClient.ExpectPacket(timeout);
            status = (response as SmbNegotiateResponsePacket).SmbHeader.Status;

            if (status != 0)
            {
                throw new ProtocolViolationException("Negotiate Failed. ErrorCode: " + status);
            }

            // Session setup:
            CifsUserAccount userAccount = new CifsUserAccount(domain, userName, password);
            request = this.cifsClient.CreateSessionSetupRequest(userAccount, nativeOS, nativeLanMan);
            this.cifsClient.SendPacket(request);
            response = this.cifsClient.ExpectPacket(timeout);
            SmbSessionSetupAndxResponsePacket sessionSetupResponse = response as SmbSessionSetupAndxResponsePacket;
            status = sessionSetupResponse.SmbHeader.Status;

            if (status != 0)
            {
                throw new ProtocolViolationException("Session Setup Failed. ErrorCode: " + status);
            }
            this.uid = sessionSetupResponse.SmbHeader.Uid;

            // Tree connect:
            string ipcAddress = "\\\\" + server + '\\' + ipcConnectString;
            request = this.cifsClient.CreateTreeConnectAndxRequest(this.uid, TreeConnectAndxFlags.NONE,
                ipcAddress, treeConnectService, null, null);
            this.cifsClient.SendPacket(request);
            response = this.cifsClient.ExpectPacket(timeout);
            SmbTreeConnectAndxResponsePacket treeConnectResponse = response as SmbTreeConnectAndxResponsePacket;
            status = treeConnectResponse.SmbHeader.Status;

            if (status != 0)
            {
                throw new ProtocolViolationException("Tree Connect Failed. ErrorCode: " + status);
            }
            this.treeId = treeConnectResponse.SmbHeader.Tid;
        }
        /// <summary>
        /// to create a Negotiate request packet.
        /// </summary>
        /// <param name="messageId">This field SHOULD be the multiplex ID that is used to associate a response with a
        /// request.</param>
        /// <param name="flags">An 8-bit field of 1-bit flags describing various features in effect for the
        /// message</param>
        /// <param name="flags2">A 16-bit field of 1-bit flags that represent various features in effect for the
        /// message. Unspecified bits are reserved and MUST be zero.</param>
        /// <param name="dialects">This is a variable length list of dialect identifiers in order of preference from
        /// least to most preferred</param>
        /// <returns>a Negotiate request packet</returns>
        public SmbNegotiateRequestPacket CreateNegotiateRequest(
            ushort messageId,
            SmbFlags flags,
            SmbFlags2 flags2,
            SMB_Dialect[] dialects)
        {
            if (dialects == null)
            {
                dialects = new SMB_Dialect[0];
            }

            SmbNegotiateRequestPacket packet = new SmbNegotiateRequestPacket();

            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_NEGOTIATE,
                messageId, 0, 0, flags, flags2);

            SMB_COM_NEGOTIATE_Request_SMB_Parameters smbParameters = new SMB_COM_NEGOTIATE_Request_SMB_Parameters();
            smbParameters.WordCount = 0;

            SMB_COM_NEGOTIATE_Request_SMB_Data smbData = new SMB_COM_NEGOTIATE_Request_SMB_Data();
            List<byte> list = new List<byte>();
            foreach (SMB_Dialect dialect in dialects)
            {
                list.Add(dialect.BufferFormat);
                list.AddRange(CifsMessageUtils.ToSmbStringBytes(dialect.DialectString, false));
            }
            smbData.Dialects = list.ToArray();
            smbData.ByteCount = (ushort)(smbData.Dialects.Length);

            packet.SmbParameters = smbParameters;
            packet.SmbData = smbData;

            return packet;
        }