/// <summary>
        /// to create a ReadRaw 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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="fid">This field MUST be a valid 16-bit signed integer indicating the file from which the data
        /// MUST be read.</param>
        /// <param name="offset">The offset in bytes from the start of the file at which the read MUST begin. This is
        /// the lower 32 bits of a 64 bit value if the WordCount is 10</param>
        /// <param name="maxCountOfBytesToReturn">The requested maximum number of bytes to read from the file and
        /// return to the client. The value MAY exceed the negotiated buffer size</param>
        /// <param name="minCountOfBytesToReturn">The requested minimum number of bytes to read from the file and
        /// return to the client. This field is used only when reading from a named pipe or a device. It is ignored
        /// when reading from a standard file</param>
        /// <param name="timeout">Support for this field is optional and this field is used only when reading from a
        /// named pipe or i/o device.</param>
        /// <param name="offsetHigh">the upper 32 bits of the offset in bytes from the start of the file at which
        /// the read MUST start.</param>
        /// <returns>a ReadRaw request packet</returns>
        public SmbReadRawRequestPacket CreateReadRawRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            ushort fid,
            uint offset,
            ushort maxCountOfBytesToReturn,
            ushort minCountOfBytesToReturn,
            uint timeout,
            uint offsetHigh)
        {
            SmbReadRawRequestPacket packet = new SmbReadRawRequestPacket();

            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_READ_RAW,
                messageId, uid, treeId, flags, flags2);

            SMB_COM_READ_RAW_Request_SMB_Parameters smbParameters = new SMB_COM_READ_RAW_Request_SMB_Parameters();
            smbParameters.FID = fid;
            smbParameters.Offset = offset;
            smbParameters.MaxCountOfBytesToReturn = maxCountOfBytesToReturn;
            smbParameters.MinCountOfBytesToReturn = minCountOfBytesToReturn;
            smbParameters.Timeout = timeout;
            smbParameters.Reserved = 0;
            smbParameters.OffsetHigh = offsetHigh;
            smbParameters.WordCount = (byte)(Marshal.SizeOf(smbParameters) / NumBytesOfWord);

            SMB_COM_READ_RAW_Request_SMB_Data smbData = new SMB_COM_READ_RAW_Request_SMB_Data();
            smbData.ByteCount = 0;

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

            return packet;
        }
        /// <summary>
        /// to create a WriteAndClose 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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="fid">This field MUST be a valid 16-bit signed integer indicating the file to which the data
        /// SHOULD be written.</param>
        /// <param name="writeOffsetInBytes">This field is a 16-bit unsigned integer indicating the number of bytes to
        /// be written to the file</param>
        /// <param name="lastWriteTime">This field is a 32-bit unsigned integer indicating  the number of seconds since
        /// Jan 1, 1970, 00:00:00.0. The server SHOULD set the last write time of the file represented by the FID to
        /// this value. If the value is zero (0), the server SHOULD use the current local time of the server to set the
        /// value. Failure to set the time MUST not result in an error response from the server.</param>
        /// <param name="data">The raw bytes to be written to the file</param>
        /// <returns>a WriteAndClose request packet</returns>
        public SmbWriteAndCloseRequestPacket CreateWriteAndCloseRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            ushort fid,
            uint writeOffsetInBytes,
            UTime lastWriteTime,
            byte[] data)
        {
            if (data == null)
            {
                data = new byte[0];
            }

            SmbWriteAndCloseRequestPacket packet = new SmbWriteAndCloseRequestPacket();

            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_WRITE_AND_CLOSE,
                messageId, uid, treeId, flags, flags2);

            SMB_COM_WRITE_AND_CLOSE_Request_SMB_Parameters smbParameters =
                new SMB_COM_WRITE_AND_CLOSE_Request_SMB_Parameters();
            smbParameters.FID = fid;
            smbParameters.CountOfBytesToWrite = (ushort)data.Length;
            smbParameters.WriteOffsetInBytes = writeOffsetInBytes;
            smbParameters.LastWriteTime = lastWriteTime;
            smbParameters.Reserved = new uint[3]; // the correct length of Reserved word is always 3.
            smbParameters.WordCount = (byte)(CifsMessageUtils.GetSize<SMB_COM_WRITE_AND_CLOSE_Request_SMB_Parameters>(
                smbParameters) / NumBytesOfWord);

            SMB_COM_WRITE_AND_CLOSE_Request_SMB_Data smbData = new SMB_COM_WRITE_AND_CLOSE_Request_SMB_Data();
            smbData.Pad = 0;
            smbData.Data = data;
            smbData.ByteCount = (ushort)(Marshal.SizeOf(smbData.Pad) + smbData.Data.Length);

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

            return packet;
        }
        /// <summary>
        /// to create a WriteAndx 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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="fid">This field MUST be a valid FID indicating the file from which the data MUST be
        /// read.</param>
        /// <param name="offset">If WordCount is 10 this field represents a 32-bit offset, measured in bytes, of where
        /// the read MUST start relative to the beginning of the file. If WordCount is 12 this field represents the
        /// lower 32 bits of a 64-bit offset</param>
        /// <param name="timeout">This field represents the amount of time, in milliseconds, that a server MUST wait
        /// before sending a response</param>
        /// <param name="writeMode">A 16-bit field containing flags </param>
        /// <param name="offsetHigh">This field is optional. If WordCount is 12 this field is not included in the
        /// request. If WordCount is 14 this field represents the upper 32 bits of a 64-bit offset, measured in bytes,
        /// of where the write SHOULD start relative to the beginning of the file</param>
        /// <param name="data">The bytes to be written to the file</param>
        /// <param name="andxPacket">the andx packet.</param>
        /// <returns>a WriteAndx request packet</returns>
        public SmbWriteAndxRequestPacket CreateWriteAndxRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            ushort fid,
            uint offset,
            uint timeout,
            WriteAndxWriteMode writeMode,
            uint offsetHigh,
            byte[] data,
            SmbPacket andxPacket)
        {
            if (data == null)
            {
                data = new byte[0];
            }

            SmbWriteAndxRequestPacket packet = new SmbWriteAndxRequestPacket();

            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_WRITE_ANDX,
                messageId, uid, treeId, flags, flags2);

            SMB_COM_WRITE_ANDX_Request_SMB_Parameters smbParameters = new SMB_COM_WRITE_ANDX_Request_SMB_Parameters();
            smbParameters.AndXReserved = 0;
            smbParameters.Remaining = 0;
            smbParameters.Reserved = 0;

            if (andxPacket == null)
            {
                smbParameters.AndXCommand = SmbCommand.SMB_COM_NO_ANDX_COMMAND;
            }
            else
            {
                smbParameters.AndXCommand = andxPacket.SmbHeader.Command;
            }
            smbParameters.FID = fid;
            smbParameters.Offset = offset;
            smbParameters.WriteMode = writeMode;
            smbParameters.Timeout = timeout;
            smbParameters.OffsetHigh = offsetHigh;
            smbParameters.Remaining = (ushort)data.Length;
            smbParameters.DataLength = (ushort)data.Length;
            smbParameters.WordCount = (byte)(Marshal.SizeOf(smbParameters) / NumBytesOfWord);

            SMB_COM_WRITE_ANDX_Request_SMB_Data smbData = new SMB_COM_WRITE_ANDX_Request_SMB_Data();
            smbData.Pad = 0;
            smbData.Data = data;
            smbData.ByteCount = (ushort)(Marshal.SizeOf(smbData.Pad) + smbData.Data.Length);

            smbParameters.DataOffset = (ushort)(Marshal.SizeOf(packet.SmbHeader) + Marshal.SizeOf(smbParameters)
                + Marshal.SizeOf(smbData.ByteCount) + Marshal.SizeOf(smbData.Pad));

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

            return packet;
        }
        /// <summary>
        /// to create a TreeConnect 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="uid">This field SHOULD identify the authenticated instance of the user.</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="path">A null-terminated string that represents the server and share name of the resource to
        /// which the client is attempting to connect</param>
        /// <param name="password">A null-terminated string that represents a share password in plaintext form</param>
        /// <param name="service">A null-terminated string representing the type of resource the client intends to
        /// access</param>
        /// <returns>a TreeConnect request packet</returns>
        public SmbTreeConnectRequestPacket CreateTreeConnectRequest(
            ushort messageId,
            ushort uid,
            SmbFlags flags,
            SmbFlags2 flags2,
            string path,
            string password,
            string service)
        {
            if (path == null)
            {
                path = string.Empty;
            }
            if (password == null)
            {
                password = string.Empty;
            }
            if (service == null)
            {
                service = string.Empty;
            }

            SmbTreeConnectRequestPacket packet = new SmbTreeConnectRequestPacket();

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

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

            SMB_COM_TREE_CONNECT_Request_SMB_Data smbData = new SMB_COM_TREE_CONNECT_Request_SMB_Data();
            smbData.BufferFormat1 = (byte)DataBufferFormat.SmbString;
            smbData.BufferFormat2 = (byte)DataBufferFormat.SmbString;
            smbData.BufferFormat3 = (byte)DataBufferFormat.SmbString;
            smbData.Path = CifsMessageUtils.ToSmbStringBytes(path, false);
            smbData.Password = CifsMessageUtils.ToSmbStringBytes(password, false);
            smbData.Service = CifsMessageUtils.ToSmbStringBytes(service, false);

            smbData.ByteCount = (ushort)(Marshal.SizeOf(smbData.BufferFormat1) + smbData.Path.Length
                + Marshal.SizeOf(smbData.BufferFormat2) + smbData.Password.Length
                + Marshal.SizeOf(smbData.BufferFormat3) + smbData.Service.Length);

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

            return packet;
        }
        /// <summary>
        /// to create a UnlockByteRange 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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="fid">This field MUST be a valid 16-bit signed integer indicating the file from which the data
        /// MUST be read</param>
        /// <param name="countOfBytesToUnlock">This field is a 32-bit unsigned integer indicating the number of
        /// contiguous bytes to be unlocked</param>
        /// <param name="unlockOffsetInBytes">ULONG This field is a 32-bit unsigned integer indicating the offset in
        /// number of bytes from which to begin the unlock. Because this field is limited to 32-bits this command is
        /// inappropriate for files having 64-bit offsets</param>
        /// <returns>a UnlockByteRange request packet</returns>
        public SmbUnlockByteRangeRequestPacket CreateUnlockByteRangeRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            ushort fid,
            uint countOfBytesToUnlock,
            uint unlockOffsetInBytes)
        {
            SmbUnlockByteRangeRequestPacket packet = new SmbUnlockByteRangeRequestPacket();

            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_UNLOCK_byte_RANGE,
                messageId, uid, treeId, flags, flags2);

            SMB_COM_UNLOCK_BYTE_RANGE_Request_SMB_Parameters smbParameters =
                new SMB_COM_UNLOCK_BYTE_RANGE_Request_SMB_Parameters();
            smbParameters.FID = fid;
            smbParameters.CountOfBytesToUnlock = countOfBytesToUnlock;
            smbParameters.UnlockOffsetInBytes = unlockOffsetInBytes;
            smbParameters.WordCount = (byte)(Marshal.SizeOf(smbParameters) / NumBytesOfWord);

            SMB_COM_UNLOCK_BYTE_RANGE_Request_SMB_Data smbData = new SMB_COM_UNLOCK_BYTE_RANGE_Request_SMB_Data();
            smbData.ByteCount = 0;

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

            return packet;
        }
        /// <summary>
        /// to create a CreateTemporary 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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="creationTime">The time the file was created on the client represented as the number of seconds
        /// since Jan 1, 1970, 00:00:00.0. Server support of this field is OPTIONAL</param>
        /// <param name="directoryName">A null-terminated string that represents the fully qualified name of the
        /// directory relative to the supplied TID in which to create the temporary file.</param>
        /// <returns>a CreateTemporary request packet</returns>
        public SmbCreateTemporaryRequestPacket CreateCreateTemporaryRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            UTime creationTime,
            string directoryName)
        {
            if (directoryName == null)
            {
                directoryName = string.Empty;
            }

            SmbCreateTemporaryRequestPacket packet = new SmbCreateTemporaryRequestPacket();

            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_CREATE_TEMPORARY,
                messageId, uid, treeId, flags, flags2);

            SMB_COM_CREATE_TEMPORARY_Request_SMB_Parameters smbParameters =
                new SMB_COM_CREATE_TEMPORARY_Request_SMB_Parameters();
            smbParameters.FileAttributes = SmbFileAttributes.SMB_FILE_ATTRIBUTE_NORMAL;
            smbParameters.CreationTime = creationTime;
            smbParameters.WordCount = (byte)(Marshal.SizeOf(smbParameters) / NumBytesOfWord);

            SMB_COM_CREATE_TEMPORARY_Request_SMB_Data smbData = new SMB_COM_CREATE_TEMPORARY_Request_SMB_Data();
            smbData.BufferFormat = (byte)DataBufferFormat.SmbString;
            smbData.DirectoryName = CifsMessageUtils.ToSmbStringBytes(directoryName,
                (flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE);
            smbData.ByteCount = (ushort)(Marshal.SizeOf(smbData.BufferFormat) + smbData.DirectoryName.Length);

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

            return packet;
        }
        /// <summary>
        /// to create a TransWriteNmpipe 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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="maxParameterCount">The maximum number of parameter bytes that the client will accept in the
        /// transaction reply. The server MUST NOT return more than this number of parameter bytes.</param>
        /// <param name="maxDataCount">The maximum number of data bytes that the client will accept in the transaction
        /// reply. The server MUST NOT return more than this number of data bytes.</param>
        /// <param name="maxSetupCount">Maximum number of setup bytes that the client will accept in the transaction
        /// reply. The server MUST NOT return more than this number of setup bytes</param>
        /// <param name="smbParametersflags">A set of bit flags that alter the behavior of the requested
        /// operation</param>
        /// <param name="timeout">The value of this field MUST be the maximum number of milliseconds the server SHOULD
        /// wait for completion of the transaction before generating a timeout and returning a response to the
        /// client. </param>
        /// <param name="fid">MUST contain a valid FID obtained from a previously successful SMB open command.</param>
        /// <param name="writeData">This field MUST contain the bytes to be written to the named pipe as part of the
        /// transacted operation.</param>
        /// <param name="name">The pathname of the mailslot or named pipe to which the transaction subcommand applies
        /// or a client supplied identifier that provides a name for the transaction.</param>
        /// <returns>a TransWriteNmpipe request packet</returns>
        public SmbTransWriteNmpipeRequestPacket CreateTransWriteNmpipeRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            ushort maxParameterCount,
            ushort maxDataCount,
            byte maxSetupCount,
            TransSmbParametersFlags smbParametersflags,
            uint timeout,
            ushort fid,
            byte[] writeData,
            string name)
        {
            if (writeData == null)
            {
                writeData = new byte[0];
            }
            if (name == null)
            {
                name = string.Empty;
            }

            SmbTransWriteNmpipeRequestPacket packet = new SmbTransWriteNmpipeRequestPacket();
            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_TRANSACTION,
                messageId, uid, treeId, flags, flags2);

            // Set Smb Parameters
            SMB_COM_TRANSACTION_Request_SMB_Parameters smbParameters =
                new SMB_COM_TRANSACTION_Request_SMB_Parameters();
            smbParameters.MaxParameterCount = maxParameterCount;
            smbParameters.MaxDataCount = maxDataCount;
            smbParameters.MaxSetupCount = maxSetupCount;
            smbParameters.Flags = smbParametersflags;
            smbParameters.Timeout = timeout;
            smbParameters.SetupCount = 2; // the correct count in word of the Setup is always 2.
            smbParameters.Setup = new ushort[2];
            smbParameters.Setup[0] = (ushort)TransSubCommand.TRANS_WRITE_NMPIPE;
            smbParameters.Setup[1] = fid;
            smbParameters.WordCount = (byte)(CifsMessageUtils.GetSize<SMB_COM_TRANSACTION_Request_SMB_Parameters>(
                smbParameters) / NumBytesOfWord);

            // Set Smb Data
            SMB_COM_TRANSACTION_Request_SMB_Data smbData = new SMB_COM_TRANSACTION_Request_SMB_Data();
            smbData.Name = CifsMessageUtils.ToSmbStringBytes(name,
                (flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE);

            // Set Trans_Data
            TRANS_WRITE_NMPIPE_Request_Trans_Data transData = new TRANS_WRITE_NMPIPE_Request_Trans_Data();
            transData.WriteData = writeData;

            packet.SmbParameters = smbParameters;
            packet.SmbData = smbData;
            packet.TransData = transData;
            packet.UpdateCountAndOffset();

            return packet;
        }
        /// <summary>
        /// to create a Seek 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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="fid">The File ID of the open file within which to seek</param>
        /// <param name="mode">The seek mode. Possible values are 0,1,2</param>
        /// <param name="offset">A 32-bit signed long value indicating the file position, relative to the position
        /// indicated in Mode, to which to set the updated file pointer.</param>
        /// <returns>a Seek request packet</returns>
        public SmbSeekRequestPacket CreateSeekRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            ushort fid,
            SeekModeValues mode,
            int offset)
        {
            SmbSeekRequestPacket packet = new SmbSeekRequestPacket();

            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_SEEK,
                messageId, uid, treeId, flags, flags2);

            SMB_COM_SEEK_Request_SMB_Parameters smbParameters = new SMB_COM_SEEK_Request_SMB_Parameters();
            smbParameters.FID = fid;
            smbParameters.Mode = (ushort)mode;
            smbParameters.Offset = offset;
            smbParameters.WordCount = (byte)(Marshal.SizeOf(smbParameters) / NumBytesOfWord);

            SMB_COM_SEEK_Request_SMB_Data smbData = new SMB_COM_SEEK_Request_SMB_Data();
            smbData.ByteCount = 0;

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

            return packet;
        }
        /// <summary>
        /// to create a SessionSetupAndx 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="maxBufferSize">The maximum size, in bytes, of the largest SMB message that the client can
        /// receive. This is the size of the largest SMB message that the server MAY send to the client. SMB message
        /// size includes the size of the SMB header, parameter, and data blocks. This size MUST not include any
        /// transport-layer framing or other transport-layer data</param>
        /// <param name="maxMpxCount">The maximum number of pending multiplexed requests supported by the client. This
        /// value MUST be less than or equal to the MaxMpxCount value provided by the server in the SMB_COM_NEGOTIATE
        /// response</param>
        /// <param name="vcNumber">The number of this VC (virtual circuit) between the client and the server. This
        /// field SHOULD be set to a value of 0 for the first virtual circuit between the client and the server and it
        /// SHOULD be set to a unique nonzero value for additional virtual circuit.</param>
        /// <param name="sessionKey">The client MUST set this to be equal to the SessionKey field in the
        /// SMB_COM_NEGOTIATE response for this SMB connection</param>
        /// <param name="capabilities">A 32-bit field providing a set of client capability indicators. The client uses
        /// this field to report its own set of capabilities to the server. The client capabilities are a subset of the
        /// server capabilities, specified in section </param>
        /// <param name="userInfo">the user account information with which the user authenticates.</param>     
        /// <param name="nativeOs">A string representing the native operating system of the CIFS client. </param>     
        /// <param name="nativeLanMan">A string that represents the native LAN manager type of the client.</param>     
        /// <param name="andxPacket">the andx packet.</param>
        /// <param name="ntlmAuthenticationPolicy">the NT LAN Manager challenge/response authentication mechanism
        /// to be used.</param>     
        /// <param name="lmAuthenticationPolicy">the LAN Manager challenge/response authentication mechanism
        /// to be used. </param>     
        /// <returns>a SessionSetupAndx request packet</returns>
        /// <exception cref="System.ArgumentNullException">the userInfo must not be null.</exception>
        public SmbSessionSetupAndxRequestPacket CreateSessionSetupAndxRequest(
            ushort messageId,
            SmbFlags flags,
            SmbFlags2 flags2,
            ushort maxBufferSize,
            ushort maxMpxCount,
            ushort vcNumber,
            uint sessionKey,
            Capabilities capabilities,
            CifsUserAccount userInfo,
            string nativeOs,
            string nativeLanMan,
            SmbPacket andxPacket,
            NTLMAuthenticationPolicyValues ntlmAuthenticationPolicy,
            LMAuthenticationPolicyValues lmAuthenticationPolicy)
        {
            #region Check parameters

            if (userInfo == null)
            {
                throw new ArgumentNullException("userInfo");
            }
            if (nativeOs == null)
            {
                nativeOs = string.Empty;
            }
            if (nativeLanMan == null)
            {
                nativeLanMan = string.Empty;
            }

            #endregion

            #region GetConnection and create SmbSessionSetupAndxRequestPacket

            CifsClientPerConnection connection = this.Context.GetConnection(this.connectionId);
            if (connection == null)
            {
                throw new InvalidOperationException("No connection set up."
                    + " Please call this method after receiving successful Negotiate response.");
            }

            this.context.NtlmAuthenticationPolicy = ntlmAuthenticationPolicy;
            this.context.LmAuthenticationPolicy = lmAuthenticationPolicy;
            this.context.PlaintextAuthenticationPolicy = PlaintextAuthenticationPolicyValues.Disabled;

            bool isUnicode = (flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE;

            SmbSessionSetupAndxRequestPacket packet = new SmbSessionSetupAndxRequestPacket();

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

            SMB_COM_SESSION_SETUP_ANDX_Request_SMB_Parameters smbParameters =
                new SMB_COM_SESSION_SETUP_ANDX_Request_SMB_Parameters();
            smbParameters.AndXReserved = 0;
            smbParameters.MaxBufferSize = maxBufferSize;
            smbParameters.MaxMpxCount = maxMpxCount;
            smbParameters.VcNumber = vcNumber;
            smbParameters.SessionKey = sessionKey;
            smbParameters.OEMPasswordLen = 0;
            smbParameters.UnicodePasswordLen = 0;
            smbParameters.Capabilities = capabilities;
            smbParameters.Reserved = 0;
            smbParameters.WordCount = (byte)(Marshal.SizeOf(smbParameters) / NumBytesOfWord);
            if (andxPacket == null)
            {
                smbParameters.AndXCommand = SmbCommand.SMB_COM_NO_ANDX_COMMAND;
            }
            else
            {
                smbParameters.AndXCommand = andxPacket.SmbHeader.Command;
            }

            SMB_COM_SESSION_SETUP_ANDX_Request_SMB_Data smbData = new SMB_COM_SESSION_SETUP_ANDX_Request_SMB_Data();
            smbData.AccountName = CifsMessageUtils.ToSmbStringBytes(userInfo.UserName, isUnicode);
            smbData.PrimaryDomain = CifsMessageUtils.ToSmbStringBytes(userInfo.DomainName, isUnicode);
            smbData.NativeOS = CifsMessageUtils.ToSmbStringBytes(nativeOs, isUnicode);
            smbData.NativeLanMan = CifsMessageUtils.ToSmbStringBytes(nativeLanMan, isUnicode);
            // The size of the preceding SmbParameters part plus Header part is an odd number for all cifs messages
            // If the format is Unicode, needs to add one 16 bits align pad
            if (isUnicode)
            {
                // pad 1 byte for 16-bits align:
                smbData.Pad = new byte[1];
            }
            else
            {
                smbData.Pad = new byte[0];
            }
            #endregion

            #region Get caseSensitivePassword, caseInsensitivePassword and ImplicitNtlmSessionKey

            // Initialize Implicit NTLM Token:
            NlmpVersion ntlmVersion = new NlmpVersion();
            if (ntlmAuthenticationPolicy == NTLMAuthenticationPolicyValues.Disabled)
            {
                ntlmVersion = NlmpVersion.v1;
            }
            else
            {
                ntlmVersion = NlmpVersion.v2;
            }

            byte[] caseInsensitivePassword = null;
            byte[] caseSensitivePassword = null;
            byte[] sessionBaseKey = null;
            byte[] responseKeyNT = NlmpUtility.GetResponseKeyNt(ntlmVersion, userInfo.DomainName, userInfo.UserName, userInfo.Password);
            byte[] responseKeyLM = NlmpUtility.GetResponseKeyLm(ntlmVersion, userInfo.DomainName, userInfo.UserName, userInfo.Password);
            ulong clientChallenge = BitConverter.ToUInt64(NlmpUtility.Nonce(8), 0);
            NegotiateTypes negotiateFlags = NegotiateTypes.NTLMSSP_NEGOTIATE_NTLM | NegotiateTypes.NTLM_NEGOTIATE_OEM;

            NlmpUtility.ComputeResponse(ntlmVersion,
                negotiateFlags,
                responseKeyNT,
                responseKeyLM,
                connection.Challenge,
                clientChallenge,
                connection.SystemTime,
                Encoding.Unicode.GetBytes(connection.ServerNetbiosName),
                out caseSensitivePassword,
                out caseInsensitivePassword,
                out sessionBaseKey);

            byte[] implicitNtlmSessionKey = new byte[sessionBaseKey.Length + caseSensitivePassword.Length];
            Array.Copy(sessionBaseKey, implicitNtlmSessionKey, sessionBaseKey.Length);
            Array.Copy(caseSensitivePassword, 0, implicitNtlmSessionKey, sessionBaseKey.Length, caseSensitivePassword.Length);
            packet.ImplicitNtlmSessionKey = implicitNtlmSessionKey;

            #endregion

            #region Update Password

            // Update caseSensitivePassword if it is PlainTextPassword
            if (ntlmAuthenticationPolicy == NTLMAuthenticationPolicyValues.Disabled
                && lmAuthenticationPolicy == LMAuthenticationPolicyValues.Disabled)
            {
                if (isUnicode)
                {
                    caseSensitivePassword = NlmpUtility.StringGetBytes(userInfo.Password, true);
                }
                else
                {
                    caseInsensitivePassword = NlmpUtility.StringGetBytes(userInfo.Password, false);
                }
                this.context.PlaintextAuthenticationPolicy = PlaintextAuthenticationPolicyValues.Enabled;
            }

            // Set smbData and smbParameters for the Password
            if (caseSensitivePassword != null)
            {
                smbData.UnicodePassword = caseSensitivePassword;
                smbParameters.UnicodePasswordLen = (ushort)caseSensitivePassword.Length;
            }
            if (caseInsensitivePassword != null)
            {
                smbData.OEMPassword = caseInsensitivePassword;
                smbParameters.OEMPasswordLen = (ushort)caseInsensitivePassword.Length;
            }

            #endregion

            #region Update smbData.ByteCount

            smbData.ByteCount = 0;
            if (smbData.OEMPassword != null)
            {
                smbData.ByteCount += (ushort)smbData.OEMPassword.Length;
            }
            if (smbData.UnicodePassword != null)
            {
                smbData.ByteCount += (ushort)smbData.UnicodePassword.Length;
            }
            if (smbData.Pad != null)
            {
                smbData.ByteCount += (ushort)smbData.Pad.Length;
            }
            if (smbData.AccountName != null)
            {
                smbData.ByteCount += (ushort)smbData.AccountName.Length;
            }
            if (smbData.PrimaryDomain != null)
            {
                smbData.ByteCount += (ushort)smbData.PrimaryDomain.Length;
            }
            if (smbData.NativeOS != null)
            {
                smbData.ByteCount += (ushort)smbData.NativeOS.Length;
            }
            if (smbData.NativeLanMan != null)
            {
                smbData.ByteCount += (ushort)smbData.NativeLanMan.Length;
            }
            #endregion

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

            return packet;
        }
        /// <summary>
        /// to create a Search 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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="maxCount">The maximum number of directory entries to return</param>
        /// <param name="searchAttributes">ATTRIBUTES  An attribute mask used to specify the standard attributes a file
        /// MUST have in order to match the search</param>
        /// <param name="fileName">null-terminated SMB_STRING. This is the full directory path (relative to the TID) of
        /// the file(s) being sought</param>
        /// <param name="resumeKey">The ResumeKey contains data used by both the client and the server to maintain the
        /// state of the search</param>
        /// <returns>a Search request packet</returns>
        public SmbSearchRequestPacket CreateSearchRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            ushort maxCount,
            SmbFileAttributes searchAttributes,
            string fileName,
            SMB_Resume_Key[] resumeKey)
        {
            if (fileName == null)
            {
                fileName = string.Empty;
            }
            if (resumeKey == null)
            {
                resumeKey = new SMB_Resume_Key[0];
            }

            SmbSearchRequestPacket packet = new SmbSearchRequestPacket();

            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_SEARCH,
                messageId, uid, treeId, flags, flags2);

            SMB_COM_SEARCH_Request_SMB_Parameters smbParameters = new SMB_COM_SEARCH_Request_SMB_Parameters();
            smbParameters.MaxCount = maxCount;
            smbParameters.SearchAttributes = searchAttributes;
            smbParameters.WordCount = (byte)(Marshal.SizeOf(smbParameters) / NumBytesOfWord);

            SMB_COM_SEARCH_Request_SMB_Data smbData = new SMB_COM_SEARCH_Request_SMB_Data();
            int resumeKeySize = 0;
            if (resumeKey.Length > 0)
            {
                resumeKeySize = CifsMessageUtils.GetSize<SMB_Resume_Key>(resumeKey[0]);
            }
            smbData.BufferFormat1 = (byte)DataBufferFormat.SmbString;
            smbData.BufferFormat2 = (byte)DataBufferFormat.VariableBlock;
            smbData.ResumeKey = resumeKey;
            smbData.ResumeKeyLength = (ushort)resumeKeySize;
            smbData.FileName = CifsMessageUtils.ToSmbStringBytes(fileName,
                (flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE);
            smbData.ByteCount = (ushort)(Marshal.SizeOf(smbData.BufferFormat1) + smbData.FileName.Length
                + Marshal.SizeOf(smbData.BufferFormat2) + Marshal.SizeOf(smbData.ResumeKeyLength)
                + smbData.ResumeKeyLength);

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

            return packet;
        }
        /// <summary>
        /// to create a SecurityPackageAndx 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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>
        /// <returns>a SecurityPackageAndx request packet</returns>
        public SmbSecurityPackageAndxRequestPacket CreateSecurityPackageAndxRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2)
        {
            SmbSecurityPackageAndxRequestPacket packet = new SmbSecurityPackageAndxRequestPacket();

            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_SECURITY_PACKAGE_ANDX,
                messageId, uid, treeId, flags, flags2);

            return packet;
        }
        /// <summary>
        /// to create a Close 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is 
        /// accessing.</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="fid">The FID of the object to be closed</param>
        /// <param name="lastTimeModified">A time value encoded as the number of seconds since January 1, 
        /// 1970 00:00:00.0. The client MAY request that the last modification time for the file be updated to this
        /// time value. A value of 0 or 0xFFFFFF results in the server using the default value. The server is NOT 
        /// REQUIRED to support this request</param>
        /// <returns>a Close request packet</returns>
        public SmbCloseRequestPacket CreateCloseRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            ushort fid,
            UTime lastTimeModified)
        {
            SmbCloseRequestPacket packet = new SmbCloseRequestPacket();

            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_CLOSE,
                messageId, uid, treeId, flags, flags2);

            SMB_COM_CLOSE_Request_SMB_Parameters smbParameters = new SMB_COM_CLOSE_Request_SMB_Parameters();
            smbParameters.FID = fid;
            smbParameters.LastTimeModified = lastTimeModified;
            smbParameters.WordCount = (byte)(Marshal.SizeOf(smbParameters) / NumBytesOfWord);

            SMB_COM_CLOSE_Request_SMB_Data smbData = new SMB_COM_CLOSE_Request_SMB_Data();
            smbData.ByteCount = 0;

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

            return packet;
        }
        /// <summary>
        /// to create a Rename 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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="searchAttributes">The file attributes of the file(s) to be deleted. If the value of this
        /// field is zero, then only normal files MUST be matched for deletion.  If the System or Hidden attributes
        /// MUST be specified, then entries with those attributes are matched in addition to the normal files. 
        /// Read-only files MAY NOT be deleted. The read-only attribute of the file MUST be cleared before the file
        /// MAY be deleted.</param>
        /// <param name="oldFileName">A null-terminated string containing the name of the file or files to be renamed.
        /// Wildcards MAY be used in the filename component of the path</param>
        /// <param name="newFileName">A null-terminated string containing the new name(s) to be given to the file(s)
        /// that matches OldFileName or the name of the destination directory into which the files matching 
        /// OldFileName MUST be moved.</param>
        /// <returns>a Rename request packet</returns>
        public SmbRenameRequestPacket CreateRenameRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            SmbFileAttributes searchAttributes,
            string oldFileName,
            string newFileName)
        {
            if (oldFileName == null)
            {
                oldFileName = string.Empty;
            }
            if (newFileName == null)
            {
                newFileName = string.Empty;
            }

            SmbRenameRequestPacket packet = new SmbRenameRequestPacket();

            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_RENAME,
                messageId, uid, treeId, flags, flags2);

            SMB_COM_RENAME_Request_SMB_Parameters smbParameters = new SMB_COM_RENAME_Request_SMB_Parameters();
            smbParameters.SearchAttributes = searchAttributes;
            smbParameters.WordCount = (byte)(Marshal.SizeOf(smbParameters) / NumBytesOfWord);

            SMB_COM_RENAME_Request_SMB_Data smbData = new SMB_COM_RENAME_Request_SMB_Data();
            smbData.BufferFormat1 = (byte)DataBufferFormat.SmbString;
            smbData.OldFileName = CifsMessageUtils.ToSmbStringBytes(oldFileName,
                (flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE);
            smbData.BufferFormat2 = (byte)DataBufferFormat.SmbString;

            if ((flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE)
            {
                // if Unicode, add 1 byte pad for align on 16-bits.
                smbData.NewFileName = new byte[1 + (newFileName.Length + 1) * 2];
                Array.Copy(CifsMessageUtils.ToSmbStringBytes(newFileName, true), 0, smbData.NewFileName, 1,
                    (newFileName.Length + 1) * 2);
            }
            else
            {
                smbData.NewFileName = CifsMessageUtils.ToSmbStringBytes(newFileName, false);
            }
            smbData.ByteCount = (ushort)(Marshal.SizeOf(smbData.BufferFormat1) + smbData.OldFileName.Length
                + Marshal.SizeOf(smbData.BufferFormat2) + smbData.NewFileName.Length);

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

            return packet;
        }
        /// <summary>
        /// to create a Read 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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="fid">This field MUST be a valid 16-bit signed integer indicating the file from which the data
        /// MUST be read.</param>
        /// <param name="countOfBytesToRead">This field is a 16-bit unsigned integer indicating the number of bytes to
        /// be read from the file. The client MUST ensure that the amount of data requested will fit in the negotiated
        /// maximum buffer size</param>
        /// <param name="readOffsetInBytes">This field is a 32-bit unsigned integer indicating the offset in number of
        /// bytes from which to begin reading from the file. The client MUST ensure that the amount of data requested
        /// fits in the negotiated maximum buffer size. Because this field is limited to 32-bits this command is
        /// inappropriate for files having 64-bit offsets</param>
        /// <param name="estimateOfRemainingBytesToBeRead">This field is a 16-bit unsigned integer indicating the
        /// remaining number of bytes that the client intends to read from the file. This is an advisory field and MAY
        /// be zero</param>
        /// <returns>a Read request packet</returns>
        public SmbReadRequestPacket CreateReadRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            ushort fid,
            ushort countOfBytesToRead,
            uint readOffsetInBytes,
            ushort estimateOfRemainingBytesToBeRead)
        {
            SmbReadRequestPacket packet = new SmbReadRequestPacket();

            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_READ,
                messageId, uid, treeId, flags, flags2);

            SMB_COM_READ_Request_SMB_Parameters smbParameters = new SMB_COM_READ_Request_SMB_Parameters();
            smbParameters.FID = fid;
            smbParameters.CountOfBytesToRead = countOfBytesToRead;
            smbParameters.ReadOffsetInBytes = readOffsetInBytes;
            smbParameters.EstimateOfRemainingBytesToBeRead = estimateOfRemainingBytesToBeRead;
            smbParameters.WordCount = (byte)(Marshal.SizeOf(smbParameters) / NumBytesOfWord);

            SMB_COM_READ_Request_SMB_Data smbData = new SMB_COM_READ_Request_SMB_Data();
            smbData.ByteCount = 0;

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

            return packet;
        }
        /// <summary>
        /// to create a Trans2SetFsInformation 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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="maxParameterCount">The maximum number of parameter bytes that the client will accept in the
        /// transaction reply. The server MUST NOT return more than this number of parameter bytes.</param>
        /// <param name="maxDataCount">The maximum number of data bytes that the client will accept in the transaction
        /// reply. The server MUST NOT return more than this number of data bytes.</param>
        /// <param name="maxSetupCount">Maximum number of setup bytes that the client will accept in the transaction
        /// reply. The server MUST NOT return more than this number of setup bytes</param>
        /// <param name="smbParametersFlags">A set of bit flags that alter the behavior of the requested operation.
        /// Unused bit fields MUST be set to zero by the client sending the request, and MUST be ignored by the server
        /// receiving the request. The client MAY set either or both of the following bit flags</param>
        /// <param name="timeout">The number of milliseconds the server SHOULD wait for completion of the transaction
        /// before generating a timeout. A value of zero indicates that the operation MUST NOT block.</param>
        /// <param name="name">This field is present but not used in SMB_COM_TRANSACTION2 requests. If Unicode support
        /// has been negotiated, then this field MUST be aligned to a 16-bit boundary and MUST consist of two null bytes
        /// (a null-terminator). If Unicode support has not been negotiated this field will contain only one null
        /// byte.</param>
        /// <returns>a Trans2SetFsInformation request packet</returns>
        public SmbTrans2SetFsInformationRequestPacket CreateTrans2SetFsInformationRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            ushort maxParameterCount,
            ushort maxDataCount,
            byte maxSetupCount,
            Trans2SmbParametersFlags smbParametersFlags,
            uint timeout,
            string name)
        {
            if (name == null)
            {
                name = string.Empty;
            }

            SmbTrans2SetFsInformationRequestPacket packet = new SmbTrans2SetFsInformationRequestPacket();
            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_TRANSACTION2,
                messageId, uid, treeId, flags, flags2);

            // Set Smb_Parameters
            SMB_COM_TRANSACTION2_Request_SMB_Parameters smbParameters =
                new SMB_COM_TRANSACTION2_Request_SMB_Parameters();
            smbParameters.MaxParameterCount = maxParameterCount;
            smbParameters.MaxDataCount = maxDataCount;
            smbParameters.MaxSetupCount = maxSetupCount;
            smbParameters.Flags = (ushort)smbParametersFlags;
            smbParameters.Timeout = timeout;
            smbParameters.SetupCount = 1; // the correct count in word of the Setup is always 1.
            smbParameters.Setup = new ushort[] { (ushort)Trans2SubCommand.TRANS2_SET_FS_INFORMATION };
            smbParameters.WordCount = (byte)(CifsMessageUtils.GetSize<SMB_COM_TRANSACTION2_Request_SMB_Parameters>(
                smbParameters) / NumBytesOfWord);

            // Set Smb_Data
            SMB_COM_TRANSACTION2_Request_SMB_Data smbData = new SMB_COM_TRANSACTION2_Request_SMB_Data();
            smbData.Name = CifsMessageUtils.ToSmbStringBytes(name,
                (flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE);

            packet.SmbParameters = smbParameters;
            packet.SmbData = smbData;
            packet.UpdateCountAndOffset();

            return packet;
        }
 /// <summary>
 /// to create a SessionSetupAndx request packet. the plaintext Authentication Policy will be used.
 /// </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="maxBufferSize">The maximum size, in bytes, of the largest SMB message that the client can
 /// receive. This is the size of the largest SMB message that the server MAY send to the client. SMB message
 /// size includes the size of the SMB header, parameter, and data blocks. This size MUST not include any
 /// transport-layer framing or other transport-layer data</param>
 /// <param name="maxMpxCount">The maximum number of pending multiplexed requests supported by the client. This
 /// value MUST be less than or equal to the MaxMpxCount value provided by the server in the SMB_COM_NEGOTIATE
 /// response</param>
 /// <param name="vcNumber">The number of this VC (virtual circuit) between the client and the server. This
 /// field SHOULD be set to a value of 0 for the first virtual circuit between the client and the server and it
 /// SHOULD be set to a unique nonzero value for additional virtual circuit.</param>
 /// <param name="sessionKey">The client MUST set this to be equal to the SessionKey field in the
 /// SMB_COM_NEGOTIATE response for this SMB connection</param>
 /// <param name="capabilities">A 32-bit field providing a set of client capability indicators. The client uses
 /// this field to report its own set of capabilities to the server. The client capabilities are a subset of the
 /// server capabilities, specified in section </param>
 /// <param name="userInfo">the user account information with which the user authenticates.</param>     
 /// <param name="nativeOs">A string representing the native operating system of the CIFS client. </param>     
 /// <param name="nativeLanMan">A string that represents the native LAN manager type of the client.</param>     
 /// <param name="andxPacket">the andx packet.</param>
 /// <returns>a SessionSetupAndx request packet</returns>
 /// <exception cref="System.ArgumentNullException">the userInfo must not be null.</exception>
 public SmbSessionSetupAndxRequestPacket CreateSessionSetupAndxRequest(
     ushort messageId,
     SmbFlags flags,
     SmbFlags2 flags2,
     ushort maxBufferSize,
     ushort maxMpxCount,
     ushort vcNumber,
     uint sessionKey,
     Capabilities capabilities,
     CifsUserAccount userInfo,
     string nativeOs,
     string nativeLanMan,
     SmbPacket andxPacket)
 {
     return this.CreateSessionSetupAndxRequest(messageId, flags, flags2, maxBufferSize, maxMpxCount,
         vcNumber, sessionKey, capabilities, userInfo, nativeOs, nativeLanMan, andxPacket,
         NTLMAuthenticationPolicyValues.Disabled, LMAuthenticationPolicyValues.Disabled);
 }
        /// <summary>
        /// to create a Trans2SetPathInformation 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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="maxParameterCount">The maximum number of parameter bytes that the client will accept in the
        /// transaction reply. The server MUST NOT return more than this number of parameter bytes.</param>
        /// <param name="maxDataCount">The maximum number of data bytes that the client will accept in the transaction
        /// reply. The server MUST NOT return more than this number of data bytes.</param>
        /// <param name="maxSetupCount">Maximum number of setup bytes that the client will accept in the transaction
        /// reply. The server MUST NOT return more than this number of setup bytes</param>
        /// <param name="smbParametersFlags">A set of bit flags that alter the behavior of the requested operation.
        /// Unused bit fields MUST be set to zero by the client sending the request, and MUST be ignored by the server
        /// receiving the request. The client MAY set either or both of the following bit flags</param>
        /// <param name="timeout">The number of milliseconds the server SHOULD wait for completion of the transaction
        /// before generating a timeout. A value of zero indicates that the operation MUST NOT block.</param>
        /// <param name="informationLevel">This field contains an information level code, which determines the
        /// information contained in the response.</param>
        /// <param name="name">A buffer containing the name of the file to be opened, created, or truncated. The
        /// string MUST be null terminated</param>
        /// <param name="data">the information data to be set.</param>
        /// <returns>a Trans2SetPathInformation request packet</returns>
        public SmbTrans2SetPathInformationRequestPacket CreateTrans2SetPathInformationRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            ushort maxParameterCount,
            ushort maxDataCount,
            byte maxSetupCount,
            Trans2SmbParametersFlags smbParametersFlags,
            uint timeout,
            SetInformationLevel informationLevel,
            string name,
            Object data)
        {
            if (name == null)
            {
                name = string.Empty;
            }

            SmbTrans2SetPathInformationRequestPacket packet = new SmbTrans2SetPathInformationRequestPacket();
            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_TRANSACTION2,
                messageId, uid, treeId, flags, flags2);

            // Set Smb_Parameters
            SMB_COM_TRANSACTION2_Request_SMB_Parameters smbParameters =
                new SMB_COM_TRANSACTION2_Request_SMB_Parameters();
            smbParameters.MaxParameterCount = maxParameterCount;
            smbParameters.MaxDataCount = maxDataCount;
            smbParameters.MaxSetupCount = maxSetupCount;
            smbParameters.Flags = (ushort)smbParametersFlags;
            smbParameters.Timeout = timeout;
            smbParameters.SetupCount = 1; // the correct count in word of the Setup is always 1.
            smbParameters.Setup = new ushort[] { (ushort)Trans2SubCommand.TRANS2_SET_PATH_INFORMATION };
            smbParameters.WordCount = (byte)(CifsMessageUtils.GetSize<SMB_COM_TRANSACTION2_Request_SMB_Parameters>(
                smbParameters) / NumBytesOfWord);

            // Set Smb_Data
            SMB_COM_TRANSACTION2_Request_SMB_Data smbData = new SMB_COM_TRANSACTION2_Request_SMB_Data();
            smbData.Name = CifsMessageUtils.ToSmbStringBytes(name,
                (flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE);

            // Set Trans2_Parameters
            TRANS2_SET_PATH_INFORMATION_Request_Trans2_Parameters trans2Parameters =
                new TRANS2_SET_PATH_INFORMATION_Request_Trans2_Parameters();
            trans2Parameters.InformationLevel = informationLevel;
            trans2Parameters.FileName = CifsMessageUtils.ToSmbStringBytes(name,
                (flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE);

            // The size of the preceding SmbParameters part plus Header part is an odd number for all cifs messages
            // Use Name field to judge whether needs to add one 16-bits align pad.
            if ((flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE && smbData.Name.Length
                % twoBytesAlign == 0)
            {
                // pad 1 byte for 16-bits align:
                smbData.Pad1 = new byte[1];
            }
            else
            {
                smbData.Pad1 = new byte[0];
            }

            // Set Trans2_Data
            TRANS2_SET_PATH_INFORMATION_Request_Trans2_Data trans2Data =
                new TRANS2_SET_PATH_INFORMATION_Request_Trans2_Data();

            if (data != null)
            {
                if (data.GetType() == typeof(SMB_INFO_SET_EAS))
                {
                    SMB_INFO_SET_EAS info = (SMB_INFO_SET_EAS)data;

                    if (info.ExtendedAttributeList == null)
                    {
                        info.ExtendedAttributeList = new SMB_FEA[0];
                    }
                    info.SizeOfListInBytes = (uint)CifsMessageUtils.GetSize<uint>(info.SizeOfListInBytes);
                    info.SizeOfListInBytes += CifsMessageUtils.GetSmbEAListSize(info.ExtendedAttributeList);
                    data = info;
                }
                else if (data.GetType() == typeof(SMB_INFO_STANDARD_OF_TRANS2_SET_PATH_INFORMATION))
                {
                    SMB_INFO_STANDARD_OF_TRANS2_SET_PATH_INFORMATION info =
                        (SMB_INFO_STANDARD_OF_TRANS2_SET_PATH_INFORMATION)data;
                    {
                        // Reserved (10 bytes): MUST be set to zero when sent and MUST be ignored on receipt.
                        info.Reserved = new byte[10];
                        data = info;
                    }
                }
                else
                {
                    // Nothing needs to do.
                }
            }
            trans2Data.Data = data;

            packet.SmbParameters = smbParameters;
            packet.SmbData = smbData;
            packet.Trans2Parameters = trans2Parameters;
            packet.Trans2Data = trans2Data;
            packet.UpdateCountAndOffset();

            return packet;
        }
        /// <summary>
        /// to create a Copy 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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>
        /// <returns>a Copy request packet</returns>
        public SmbCopyRequestPacket CreateCopyRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2)
        {
            SmbCopyRequestPacket packet = new SmbCopyRequestPacket();

            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_COPY,
                messageId, uid, treeId, flags, flags2);

            return packet;
        }
        /// <summary>
        /// to create a DeleteDirectory 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is 
        /// accessing.</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="directoryName">A null-terminated string that contains the full pathname, relative to the 
        /// supplied TID, of the directory to be deleted.</param>
        /// <returns>the DeleteDirectory request packet.</returns>
        public SmbDeleteDirectoryRequestPacket CreateDeleteDirectoryRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            string directoryName)
        {
            if (directoryName == null)
            {
                directoryName = string.Empty;
            }

            SmbDeleteDirectoryRequestPacket packet = new SmbDeleteDirectoryRequestPacket();

            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_DELETE_DIRECTORY,
                messageId, uid, treeId, flags, flags2);

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

            SMB_COM_DELETE_DIRECTORY_Request_SMB_Data smbData = new SMB_COM_DELETE_DIRECTORY_Request_SMB_Data();
            smbData.BufferFormat = (byte)DataBufferFormat.SmbString;
            smbData.DirectoryName = CifsMessageUtils.ToSmbStringBytes(directoryName,
                (flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE);
            smbData.ByteCount = (ushort)(Marshal.SizeOf(smbData.BufferFormat) + smbData.DirectoryName.Length);

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

            return packet;
        }
        /// <summary>
        /// to create a SetInformation2 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</param>
        /// <param name="fid">This is the FID representing the file for which attributes are to be set.</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="createDate">This is the FID representing the file for which attributes are to be set</param>
        /// <param name="creationTime">This is the date when the file was created</param>
        /// <param name="lastAccessDate">This is the date when the file was last accessed</param>
        /// <param name="lastAccessTime">This is the time on LastAccessDate when the file was last accessed.</param>
        /// <param name="lastWriteDate">This is the date when data were last written to the file</param>
        /// <param name="lastWriteTime">This is the time on LastWriteDate when data were last written to the
        /// file.</param>
        /// <returns>a SetInformation2 request packet</returns>
        public SmbSetInformation2RequestPacket CreateSetInformation2Request(
            ushort messageId,
            ushort uid,
            ushort treeId,
            ushort fid,
            SmbFlags flags,
            SmbFlags2 flags2,
            SmbDate createDate,
            SmbTime creationTime,
            SmbDate lastAccessDate,
            SmbTime lastAccessTime,
            SmbDate lastWriteDate,
            SmbTime lastWriteTime)
        {
            SmbSetInformation2RequestPacket packet = new SmbSetInformation2RequestPacket();

            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_SET_INFORMATION2,
                messageId, uid, treeId, flags, flags2);

            SMB_COM_SET_INFORMATION2_Request_SMB_Parameters smbParameters =
                new SMB_COM_SET_INFORMATION2_Request_SMB_Parameters();
            smbParameters.FID = fid;
            smbParameters.CreateDate = createDate;
            smbParameters.CreationTime = creationTime;
            smbParameters.LastAccessDate = lastAccessDate;
            smbParameters.LastAccessTime = lastAccessTime;
            smbParameters.LastWriteDate = lastWriteDate;
            smbParameters.LastWriteTime = lastWriteTime;
            smbParameters.WordCount = (byte)(Marshal.SizeOf(smbParameters) / NumBytesOfWord);

            SMB_COM_SET_INFORMATION2_Request_SMB_Data smbData = new SMB_COM_SET_INFORMATION2_Request_SMB_Data();
            smbData.ByteCount = 0;

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

            return packet;
        }
        /// <summary>
        /// to create a TreeConnectAndx 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="uid">This field SHOULD identify the authenticated instance of the user.</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="smbParametersFlags">USHORT  A 16-bit field used to modify the SMB_COM_TREE_CONNECT_ANDX
        /// request. The client MUST set reserved values to 0, and the server MUST ignore them.</param>
        /// <param name="path">STRING A null-terminated string that represents the server and share name of the resource
        /// to which the client is attempting to connect</param>
        /// <param name="service">The type of resource that the client intends to access</param>
        /// <param name="password">A null-terminated string that represents a share password in plaintext form.</param>
        /// <param name="andxPacket">the andx packet.</param>
        /// <returns>a TreeConnectAndx request packet</returns>
        public SmbTreeConnectAndxRequestPacket CreateTreeConnectAndxRequest(
            ushort messageId,
            ushort uid,
            SmbFlags flags,
            SmbFlags2 flags2,
            TreeConnectAndxFlags smbParametersFlags,
            string path,
            string service,
            byte[] password,
            SmbPacket andxPacket)
        {
            if (path == null)
            {
                path = string.Empty;
            }
            if (service == null)
            {
                service = string.Empty;
            }
            if (password == null)
            {
                password = new byte[0];
            }

            SmbTreeConnectAndxRequestPacket packet = new SmbTreeConnectAndxRequestPacket();

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

            SMB_COM_TREE_CONNECT_ANDX_Request_SMB_Parameters smbParameters =
                new SMB_COM_TREE_CONNECT_ANDX_Request_SMB_Parameters();
            if (andxPacket == null)
            {
                smbParameters.AndXCommand = SmbCommand.SMB_COM_NO_ANDX_COMMAND;
            }
            else
            {
                smbParameters.AndXCommand = andxPacket.SmbHeader.Command;
            }
            smbParameters.AndXReserved = 0;
            smbParameters.Flags = (ushort)smbParametersFlags;
            smbParameters.PasswordLength = (ushort)password.Length;
            smbParameters.WordCount = (byte)(Marshal.SizeOf(smbParameters) / NumBytesOfWord);

            SMB_COM_TREE_CONNECT_ANDX_Request_SMB_Data smbData = new SMB_COM_TREE_CONNECT_ANDX_Request_SMB_Data();
            smbData.Password = password;
            if ((flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE)
            {
                smbData.Pad = new byte[(smbData.Password.Length + 1) % 2];
                smbData.Path = CifsMessageUtils.ToSmbStringBytes(path, true);
            }
            else
            {
                smbData.Pad = new byte[0];
                smbData.Path = CifsMessageUtils.ToSmbStringBytes(path, false);
            }
            smbData.Service = CifsMessageUtils.ToSmbStringBytes(service, false);
            smbData.ByteCount = (ushort)(smbData.Password.Length + smbData.Pad.Length + smbData.Path.Length
                + smbData.Service.Length);

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

            return packet;
        }
        /// <summary>
        /// to create a SetInformation 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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="fileAttributes">This field is a 16 bit unsigned bit field encoded as 
        /// SMB_FILE_ATTRIBUTES</param>
        /// <param name="lastWriteTime">The time of the last write to the file</param>
        /// <param name="fileName">A null-terminated string that represents the fully qualified name of the file 
        /// relative to the supplied TID. This is the file for which attributes are set.</param>
        /// <returns>a SetInformation request packet</returns>
        public SmbSetInformationRequestPacket CreateSetInformationRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            SmbFileAttributes fileAttributes,
            UTime lastWriteTime,
            string fileName)
        {
            if (fileName == null)
            {
                fileName = string.Empty;
            }

            SmbSetInformationRequestPacket packet = new SmbSetInformationRequestPacket();

            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_SET_INFORMATION,
                messageId, uid, treeId, flags, flags2);

            SMB_COM_SET_INFORMATION_Request_SMB_Parameters smbParameters;
            smbParameters = new SMB_COM_SET_INFORMATION_Request_SMB_Parameters();
            smbParameters.FileAttributes = fileAttributes;
            smbParameters.LastWriteTime = lastWriteTime;
            smbParameters.Reserved = new ushort[5]; // the correct length of Reserved word is always 5.
            smbParameters.WordCount = (byte)(CifsMessageUtils.GetSize<SMB_COM_SET_INFORMATION_Request_SMB_Parameters>(
                smbParameters) / NumBytesOfWord);

            SMB_COM_SET_INFORMATION_Request_SMB_Data smbData = new SMB_COM_SET_INFORMATION_Request_SMB_Data();
            smbData.BufferFormat = (byte)DataBufferFormat.SmbString;
            smbData.FileName = CifsMessageUtils.ToSmbStringBytes(fileName,
                (flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE);
            smbData.ByteCount = (ushort)(Marshal.SizeOf(smbData.BufferFormat) + smbData.FileName.Length);

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

            return packet;
        }
        /// <summary>
        /// to create a TreeDisconnect 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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>
        /// <returns>a TreeConnect request packet</returns>
        public SmbTreeDisconnectRequestPacket CreateTreeDisconnectRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2)
        {
            SmbTreeDisconnectRequestPacket packet = new SmbTreeDisconnectRequestPacket();

            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_TREE_DISCONNECT,
                messageId, uid, treeId, flags, flags2);

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

            SMB_COM_TREE_DISCONNECT_Request_SMB_Data smbData = new SMB_COM_TREE_DISCONNECT_Request_SMB_Data();
            smbData.ByteCount = 0;

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

            return packet;
        }
        /// <summary>
        /// to create a Trans2Open2 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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="maxParameterCount">The maximum number of parameter bytes that the client will accept in the
        /// transaction reply. The server MUST NOT return more than this number of parameter bytes.</param>
        /// <param name="maxDataCount">The maximum number of data bytes that the client will accept in the transaction
        /// reply. The server MUST NOT return more than this number of data bytes.</param>
        /// <param name="maxSetupCount">Maximum number of setup bytes that the client will accept in the transaction
        /// reply. The server MUST NOT return more than this number of setup bytes</param>
        /// <param name="smbParametersFlags">A set of bit flags that alter the behavior of the requested operation.
        /// Unused bit fields MUST be set to zero by the client sending the request, and MUST be ignored by the server
        /// receiving the request. The client MAY set either or both of the following bit flags</param>
        /// <param name="timeout">The number of milliseconds the server SHOULD wait for completion of the transaction
        /// before generating a timeout. A value of zero indicates that the operation MUST NOT block.</param>
        /// <param name="allocationSize">The number of bytes to reserve for the file if the file is being created or
        /// truncated. </param>
        /// <param name="creationTimeInSeconds">A time value expressed in seconds past Jan 1, 1970 00:00:00:00 to apply
        /// to the file's attributes if the file is created</param>
        /// <param name="desiredAccess">A 16-bit field for encoding the requested access mode. See section 3.2.4.5.1
        /// for a discussion on sharing modes</param>
        /// <param name="extendedAttributeList">A list of extended file attribute name / value pairs that are to be
        /// assigned to the file.</param>
        /// <param name="fileAttributes">Attributes to apply to the file if it needs to be created.</param>
        /// <param name="name">A buffer containing the name of the file to be opened, created, or truncated. The
        /// string MUST be null terminated</param>
        /// <param name="open2Flags">This 16-bit field of flags is used to request that the server take certain
        /// actions.</param>
        /// <param name="openMode">A 16-bit field that controls the way a file SHOULD be treated when it is opened for
        /// use by certain extended SMB requests</param>
        /// <returns>a Trans2Open2 request packet</returns>
        public SmbTrans2Open2RequestPacket CreateTrans2Open2Request(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            ushort maxParameterCount,
            ushort maxDataCount,
            byte maxSetupCount,
            Trans2SmbParametersFlags smbParametersFlags,
            uint timeout,
            Trans2Open2Flags open2Flags,
            Trans2Open2DesiredAccess desiredAccess,
            SmbFileAttributes fileAttributes,
            uint creationTimeInSeconds,
            OpenMode openMode,
            uint allocationSize,
            string name,
            SMB_FEA[] extendedAttributeList)
        {
            if (name == null)
            {
                name = string.Empty;
            }
            if (extendedAttributeList == null)
            {
                extendedAttributeList = new SMB_FEA[0];
            }

            SmbTrans2Open2RequestPacket packet = new SmbTrans2Open2RequestPacket();
            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_TRANSACTION2,
                messageId, uid, treeId, flags, flags2);

            // Set Smb_Parameters
            SMB_COM_TRANSACTION2_Request_SMB_Parameters smbParameters =
                new SMB_COM_TRANSACTION2_Request_SMB_Parameters();
            smbParameters.MaxParameterCount = maxParameterCount;
            smbParameters.MaxDataCount = maxDataCount;
            smbParameters.MaxSetupCount = maxSetupCount;
            smbParameters.Flags = (ushort)smbParametersFlags;
            smbParameters.Timeout = timeout;
            smbParameters.SetupCount = 1; // the correct count in word of the Setup is always 1.
            smbParameters.Setup = new ushort[] { (ushort)Trans2SubCommand.TRANS2_OPEN2 };
            smbParameters.WordCount = (byte)(CifsMessageUtils.GetSize<SMB_COM_TRANSACTION2_Request_SMB_Parameters>(
                smbParameters) / NumBytesOfWord);

            // Set Smb_Data
            SMB_COM_TRANSACTION2_Request_SMB_Data smbData = new SMB_COM_TRANSACTION2_Request_SMB_Data();
            smbData.Name = CifsMessageUtils.ToSmbStringBytes(name,
                (flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE);

            // The size of the preceding SmbParameters part plus Header part is an odd number for all cifs messages
            // Use Name field to judge whether needs to add one 16-bits align pad.
            if ((flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE && smbData.Name.Length
                % twoBytesAlign == 0)
            {
                // pad 1 byte for 16-bits align:
                smbData.Pad1 = new byte[1];
            }
            else
            {
                smbData.Pad1 = new byte[0];
            }

            // Set Trans2_Parameters
            TRANS2_OPEN2_Request_Trans2_Parameters trans2Parameters = new TRANS2_OPEN2_Request_Trans2_Parameters();
            trans2Parameters.Flags = (ushort)open2Flags;
            trans2Parameters.AccessMode = (ushort)desiredAccess;
            trans2Parameters.FileAttributes = fileAttributes;
            trans2Parameters.CreationTime = creationTimeInSeconds;
            trans2Parameters.OpenMode = (ushort)openMode;
            trans2Parameters.AllocationSize = allocationSize;
            trans2Parameters.Reserved = new ushort[5]; // the correct length of Reserved word is always 5.
            trans2Parameters.FileName = CifsMessageUtils.ToSmbStringBytes(name,
                (flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE);

            // Set Trans2_Data
            TRANS2_OPEN2_Request_Trans2_Data trans2Data = new TRANS2_OPEN2_Request_Trans2_Data();
            trans2Data.ExtendedAttributeList.FEAList = extendedAttributeList;
            trans2Data.ExtendedAttributeList.SizeOfListInBytes =
                (uint)CifsMessageUtils.GetSize<uint>(trans2Data.ExtendedAttributeList.SizeOfListInBytes);
            trans2Data.ExtendedAttributeList.SizeOfListInBytes +=
                CifsMessageUtils.GetSmbEAListSize(extendedAttributeList);

            packet.SmbParameters = smbParameters;
            packet.SmbData = smbData;
            packet.Trans2Parameters = trans2Parameters;
            packet.Trans2Data = trans2Data;
            packet.UpdateCountAndOffset();

            return packet;
        }
        /// <summary>
        /// to create a Delete 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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="searchAttributes">The file attributes of the file(s) to be deleted. If the value of this
        /// field is zero, then only normal files MUST be matched for deletion.  If the System or Hidden attributes
        /// MUST be specified, then entries with those attributes are matched in addition to the normal files.  
        /// Read-only files MAY NOT be deleted. The read-only attribute of the file MUST be cleared before the file
        /// MAY be deleted.</param>
        /// <param name="fileNames">The pathname of the file(s) to be deleted, relative to the supplied TID. Wildcards
        /// MAY be used in the filename component of the path.</param>
        /// <returns>a Delete request packet</returns>
        public SmbDeleteRequestPacket CreateDeleteRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            SmbFileAttributes searchAttributes,
            string[] fileNames)
        {
            if (fileNames == null)
            {
                fileNames = new string[0];
            }

            SmbDeleteRequestPacket packet = new SmbDeleteRequestPacket();

            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_DELETE,
                messageId, uid, treeId, flags, flags2);

            SMB_COM_DELETE_Request_SMB_Parameters smbParameters = new SMB_COM_DELETE_Request_SMB_Parameters();
            smbParameters.SearchAttributes = searchAttributes;
            smbParameters.WordCount = (byte)(Marshal.SizeOf(smbParameters) / NumBytesOfWord);

            SMB_COM_DELETE_Request_SMB_Data smbData = new SMB_COM_DELETE_Request_SMB_Data();
            smbData.ByteCount = 0;
            smbData.BufferFormatAndFileName = new byte[0];
            bool isUnicode = (flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE;
            const int bufferFormatSize = 1; // the size in bytes of BufferFormat is always 1.
            const int nullTerminalSize = 1; // the num of null Terminal character is always 1.
            foreach (string file in fileNames)
            {
                if (isUnicode)
                {
                    smbData.ByteCount += (byte)(bufferFormatSize + (file.Length + nullTerminalSize) * 2);
                }
                else
                {
                    smbData.ByteCount += (byte)(bufferFormatSize + (file.Length + nullTerminalSize));
                }
            }
            smbData.BufferFormatAndFileName = new byte[smbData.ByteCount];
            int index = 0;
            foreach (string file in fileNames)
            {
                smbData.BufferFormatAndFileName[index++] = (byte)DataBufferFormat.SmbString;
                byte[] fileNameBytes = CifsMessageUtils.ToSmbStringBytes(file, isUnicode);
                Array.Copy(fileNameBytes, 0, smbData.BufferFormatAndFileName, index, fileNameBytes.Length);
                index += fileNameBytes.Length;
            }

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

            return packet;
        }
        /// <summary>
        /// to create a Trans2QueryFileInformation 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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="maxParameterCount">The maximum number of parameter bytes that the client will accept in the
        /// transaction reply. The server MUST NOT return more than this number of parameter bytes.</param>
        /// <param name="maxDataCount">The maximum number of data bytes that the client will accept in the transaction
        /// reply. The server MUST NOT return more than this number of data bytes.</param>
        /// <param name="maxSetupCount">Maximum number of setup bytes that the client will accept in the transaction
        /// reply. The server MUST NOT return more than this number of setup bytes</param>
        /// <param name="smbParametersFlags">A set of bit flags that alter the behavior of the requested operation.
        /// Unused bit fields MUST be set to zero by the client sending the request, and MUST be ignored by the server
        /// receiving the request. The client MAY set either or both of the following bit flags</param>
        /// <param name="timeout">The number of milliseconds the server SHOULD wait for completion of the transaction
        /// before generating a timeout. A value of zero indicates that the operation MUST NOT block.</param>
        /// <param name="informationLevel">This field contains an information level code, which determines the
        /// information contained in the response.</param>
        /// <param name="fid">This field MUST contain a valid FID returned from a previously successful SMB open
        /// command</param>
        /// <param name="name">This field is present but not used in SMB_COM_TRANSACTION2 requests. If Unicode support
        /// has been negotiated, then this field MUST be aligned to a 16-bit boundary and MUST consist of two null bytes
        /// (a null-terminator). If Unicode support has not been negotiated this field will contain only one null
        /// byte.</param>
        /// <param name="extendedAttributeList">This field MUST contain an array of extended file attribute name value
        /// pairs.</param>
        /// <returns>a Trans2QueryFileInformation request packet</returns>
        public SmbTrans2QueryFileInformationRequestPacket CreateTrans2QueryFileInformationRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            ushort maxParameterCount,
            ushort maxDataCount,
            byte maxSetupCount,
            Trans2SmbParametersFlags smbParametersFlags,
            uint timeout,
            string name,
            ushort fid,
            QueryInformationLevel informationLevel,
            SMB_GEA[] extendedAttributeList)
        {
            if (name == null)
            {
                name = string.Empty;
            }
            if (extendedAttributeList == null)
            {
                extendedAttributeList = new SMB_GEA[0];
            }

            SmbTrans2QueryFileInformationRequestPacket packet = new SmbTrans2QueryFileInformationRequestPacket();
            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_TRANSACTION2,
                messageId, uid, treeId, flags, flags2);

            // Set Smb_Parameters
            SMB_COM_TRANSACTION2_Request_SMB_Parameters smbParameters =
                new SMB_COM_TRANSACTION2_Request_SMB_Parameters();
            smbParameters.MaxParameterCount = maxParameterCount;
            smbParameters.MaxDataCount = maxDataCount;
            smbParameters.MaxSetupCount = maxSetupCount;
            smbParameters.Flags = (ushort)smbParametersFlags;
            smbParameters.Timeout = timeout;
            smbParameters.SetupCount = 1; // the correct count in word of the Setup is always 1.
            smbParameters.Setup = new ushort[] { (ushort)Trans2SubCommand.TRANS2_QUERY_FILE_INFORMATION };
            smbParameters.WordCount = (byte)(CifsMessageUtils.GetSize<SMB_COM_TRANSACTION2_Request_SMB_Parameters>(
                smbParameters) / NumBytesOfWord);

            // Set Smb_Data
            SMB_COM_TRANSACTION2_Request_SMB_Data smbData = new SMB_COM_TRANSACTION2_Request_SMB_Data();
            smbData.Name = CifsMessageUtils.ToSmbStringBytes(name,
                (flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE);

            // Set Trans2_Parameters
            TRANS2_QUERY_FILE_INFORMATION_Request_Trans2_Parameters trans2Parameters =
                new TRANS2_QUERY_FILE_INFORMATION_Request_Trans2_Parameters();
            trans2Parameters.FID = fid;
            trans2Parameters.InformationLevel = informationLevel;

            // Set Trans2_Data
            TRANS2_QUERY_PATH_INFORMATION_Request_Trans2_Data trans2Data =
                new TRANS2_QUERY_PATH_INFORMATION_Request_Trans2_Data();
            trans2Data.GetExtendedAttributeList.GEAList = extendedAttributeList;
            trans2Data.GetExtendedAttributeList.SizeOfListInBytes =
                (uint)CifsMessageUtils.GetSize<uint>(trans2Data.GetExtendedAttributeList.SizeOfListInBytes);
            trans2Data.GetExtendedAttributeList.SizeOfListInBytes +=
                CifsMessageUtils.GetSmbQueryEAListSize(extendedAttributeList);

            packet.SmbParameters = smbParameters;
            packet.SmbData = smbData;
            packet.Trans2Parameters = trans2Parameters;
            packet.Trans2Data = trans2Data;
            packet.UpdateCountAndOffset();

            return packet;
        }
        /// <summary>
        /// to create a WriteAndUnlock 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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="fid">This field MUST be a valid 16-bit signed integer indicating the file to which the data
        /// MUST be written</param>
        /// <param name="writeOffsetInBytes">This field is a 32-bit unsigned integer indicating the offset in number of
        /// bytes from the beginning of the file at which to begin writing to the file. The client MUST ensure that the
        /// amount of data sent can fit in the negotiated maximum buffer size. Because this field is limited to 32-bits
        /// this command is inappropriate for files having 64-bit offsets.</param>
        /// <param name="estimateOfRemainingBytesToBeWritten">This field is a 16-bit unsigned integer indicating the
        /// remaining number of bytes the client anticipates to write to the file. This is an advisory field and MAY be
        /// zero. This information can be used by the server to optimize cache behavior.</param>
        /// <param name="data">The raw bytes to be written to the file</param>
        /// <returns> a WriteAndUnlock request packet</returns>
        public SmbWriteAndUnlockRequestPacket CreateWriteAndUnlockRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            ushort fid,
            uint writeOffsetInBytes,
            ushort estimateOfRemainingBytesToBeWritten,
            byte[] data)
        {
            if (data == null)
            {
                data = new byte[0];
            }

            SmbWriteAndUnlockRequestPacket packet = new SmbWriteAndUnlockRequestPacket();

            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_WRITE_AND_UNLOCK,
                messageId, uid, treeId, flags, flags2);

            SMB_COM_WRITE_AND_UNLOCK_Request_SMB_Parameters smbParameters =
                new SMB_COM_WRITE_AND_UNLOCK_Request_SMB_Parameters();
            smbParameters.FID = fid;
            smbParameters.CountOfBytesToWrite = (ushort)data.Length;
            smbParameters.WriteOffsetInBytes = writeOffsetInBytes;
            smbParameters.EstimateOfRemainingBytesToBeWritten = estimateOfRemainingBytesToBeWritten;
            smbParameters.WordCount = (byte)(Marshal.SizeOf(smbParameters) / NumBytesOfWord);

            SMB_COM_WRITE_AND_UNLOCK_Request_SMB_Data smbData = new SMB_COM_WRITE_AND_UNLOCK_Request_SMB_Data();
            smbData.BufferFormat = (byte)DataBufferFormat.DataBuffer;
            smbData.DataLength = (ushort)data.Length;
            smbData.Data = data;
            smbData.ByteCount = (ushort)(Marshal.SizeOf(smbData.BufferFormat) + Marshal.SizeOf(smbData.DataLength)
                + smbData.DataLength);

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

            return packet;
        }
        /// <summary>
        /// to create a Trans2QueryPathInformation 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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="maxParameterCount">The maximum number of parameter bytes that the client will accept in the
        /// transaction reply. The server MUST NOT return more than this number of parameter bytes.</param>
        /// <param name="maxDataCount">The maximum number of data bytes that the client will accept in the transaction
        /// reply. The server MUST NOT return more than this number of data bytes.</param>
        /// <param name="maxSetupCount">Maximum number of setup bytes that the client will accept in the transaction
        /// reply. The server MUST NOT return more than this number of setup bytes</param>
        /// <param name="smbParametersFlags">A set of bit flags that alter the behavior of the requested operation.
        /// Unused bit fields MUST be set to zero by the client sending the request, and MUST be ignored by the server
        /// receiving the request. The client MAY set either or both of the following bit flags</param>
        /// <param name="timeout">The number of milliseconds the server SHOULD wait for completion of the transaction
        /// before generating a timeout. A value of zero indicates that the operation MUST NOT block.</param>
        /// <param name="informationLevel">This field contains an information level code, which determines the
        /// information contained in the response.</param>
        /// <param name="name">A buffer containing the name of the file to be opened, created, or truncated. The
        /// string MUST be null terminated</param>
        /// <param name="extendedAttributeList">This field MUST contain an array of extended file attribute name value
        /// pairs. </param>
        /// <returns>a Trans2QueryPathInformation request packet</returns>
        public SmbTrans2QueryPathInformationRequestPacket CreateTrans2QueryPathInformationRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            ushort maxParameterCount,
            ushort maxDataCount,
            byte maxSetupCount,
            Trans2SmbParametersFlags smbParametersFlags,
            uint timeout,
            QueryInformationLevel informationLevel,
            string name,
            SMB_GEA[] extendedAttributeList)
        {
            if (name == null)
            {
                name = string.Empty;
            }
            if (extendedAttributeList == null)
            {
                extendedAttributeList = new SMB_GEA[0];
            }

            SmbTrans2QueryPathInformationRequestPacket packet = new SmbTrans2QueryPathInformationRequestPacket();
            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_TRANSACTION2,
                messageId, uid, treeId, flags, flags2);

            // Set Smb_Parameters
            SMB_COM_TRANSACTION2_Request_SMB_Parameters smbParameters =
                new SMB_COM_TRANSACTION2_Request_SMB_Parameters();
            smbParameters.MaxParameterCount = maxParameterCount;
            smbParameters.MaxDataCount = maxDataCount;
            smbParameters.MaxSetupCount = maxSetupCount;
            smbParameters.Flags = (ushort)smbParametersFlags;
            smbParameters.Timeout = timeout;
            smbParameters.SetupCount = 1; // the correct count in word of the Setup is always 1.
            smbParameters.Setup = new ushort[] { (ushort)Trans2SubCommand.TRANS2_QUERY_PATH_INFORMATION };
            smbParameters.WordCount = (byte)(CifsMessageUtils.GetSize<SMB_COM_TRANSACTION2_Request_SMB_Parameters>(
                smbParameters) / NumBytesOfWord);

            // Set Smb_Data
            SMB_COM_TRANSACTION2_Request_SMB_Data smbData = new SMB_COM_TRANSACTION2_Request_SMB_Data();
            smbData.Name = CifsMessageUtils.ToSmbStringBytes(name,
                (flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE);

            // Set Trans2_Parameters
            TRANS2_QUERY_PATH_INFORMATION_Request_Trans2_Parameters trans2Parameters =
                new TRANS2_QUERY_PATH_INFORMATION_Request_Trans2_Parameters();
            trans2Parameters.InformationLevel = informationLevel;
            trans2Parameters.FileName = CifsMessageUtils.ToSmbStringBytes(name,
                (flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE);

            // The size of the preceding SmbParameters part plus Header part is an odd number for all cifs messages
            // Use Name field to judge whether needs to add one 16-bits align pad.
            if ((flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) == SmbFlags2.SMB_FLAGS2_UNICODE && smbData.Name.Length
                % twoBytesAlign == 0)
            {
                // pad 1 byte for 16-bits align:
                smbData.Pad1 = new byte[1];
            }
            else
            {
                smbData.Pad1 = new byte[0];
            }

            // Set Trans2_Data
            TRANS2_QUERY_PATH_INFORMATION_Request_Trans2_Data trans2Data =
                new TRANS2_QUERY_PATH_INFORMATION_Request_Trans2_Data();
            trans2Data.GetExtendedAttributeList.GEAList = extendedAttributeList;
            trans2Data.GetExtendedAttributeList.SizeOfListInBytes =
                (uint)CifsMessageUtils.GetSize<uint>(trans2Data.GetExtendedAttributeList.SizeOfListInBytes);
            trans2Data.GetExtendedAttributeList.SizeOfListInBytes +=
                CifsMessageUtils.GetSmbQueryEAListSize(extendedAttributeList);

            packet.SmbParameters = smbParameters;
            packet.SmbData = smbData;
            packet.Trans2Parameters = trans2Parameters;
            packet.Trans2Data = trans2Data;
            packet.UpdateCountAndOffset();

            return packet;
        }
        /// <summary>
        /// to create a WriteBulkData 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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>
        /// <returns>a WriteBulkData request packet</returns>
        public SmbWriteBulkDataRequestPacket CreateWriteBulkDataRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2)
        {
            SmbWriteBulkDataRequestPacket packet = new SmbWriteBulkDataRequestPacket();

            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_WRITE_BULK_DATA,
                messageId, uid, treeId, flags, flags2);

            return packet;
        }
        /// <summary>
        /// to create a ReadAndx 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="uid">This field SHOULD identify the authenticated instance of the user.</param>
        /// <param name="treeId">This field identifies the subdirectory (or tree) on the server that the client is
        /// accessing.</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="fid">This field MUST be a valid FID indicating the file from which the data MUST be
        /// read.</param>
        /// <param name="offset">If WordCount is 10 this field represents a 32-bit offset, measured in bytes, of where
        /// the read MUST start relative to the beginning of the file. If WordCount is 12 this field represents the
        /// lower 32 bits of a 64-bit offset</param>
        /// <param name="maxNumberOfBytesToReturn">The maximum number of bytes to read. A single request MAY NOT return
        /// more data than the maximum negotiated buffer size for the session. If MaxCountOfBytesToReturn exceeds the
        /// maximum negotiated buffer size the server MUST return the number of bytes that fit within the maximum
        /// negotiated buffer size</param>
        /// <param name="minNumberOfBytesToReturn">USHORT The requested minimum number of bytes to return. This field
        /// is used only when reading from a named pipe or a device. It is ignored when reading from a standard
        /// file.</param>
        /// <param name="timeout">This field represents the amount of time, in milliseconds, that a server MUST wait
        /// before sending a response.</param>
        /// <param name="offsetHigh">This field is OPTIONAL. If WordCount is 10 this field is not included in the
        /// request. If WordCount is 12 this field represents the upper 32 bits of a 64-bit offset, measured in bytes,
        /// of where the read SHOULD start relative to the beginning of the file</param>
        /// <param name="andxPacket">the andx packet.</param>
        /// <returns>a ReadAndx request packet</returns>
        public SmbReadAndxRequestPacket CreateReadAndxRequest(
            ushort messageId,
            ushort uid,
            ushort treeId,
            SmbFlags flags,
            SmbFlags2 flags2,
            ushort fid,
            uint offset,
            ushort maxNumberOfBytesToReturn,
            ushort minNumberOfBytesToReturn,
            uint timeout,
            uint offsetHigh,
            SmbPacket andxPacket)
        {
            SmbReadAndxRequestPacket packet = new SmbReadAndxRequestPacket();
            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(SmbCommand.SMB_COM_READ_ANDX,
                messageId, uid, treeId, flags, flags2);

            SMB_COM_READ_ANDX_Request_SMB_Parameters smbParameters = new SMB_COM_READ_ANDX_Request_SMB_Parameters();
            smbParameters.Remaining = 0;
            smbParameters.AndXReserved = 0;
            if (andxPacket == null)
            {
                smbParameters.AndXCommand = SmbCommand.SMB_COM_NO_ANDX_COMMAND;
            }
            else
            {
                smbParameters.AndXCommand = andxPacket.SmbHeader.Command;
            }
            smbParameters.FID = fid;
            smbParameters.Offset = offset;
            smbParameters.MaxNumberOfBytesToReturn = maxNumberOfBytesToReturn;
            smbParameters.MinNumberOfBytesToReturn = minNumberOfBytesToReturn;
            smbParameters.Timeout = timeout;
            smbParameters.OffsetHigh = offsetHigh;
            smbParameters.WordCount = (byte)(Marshal.SizeOf(smbParameters) / NumBytesOfWord);

            SMB_COM_READ_ANDX_Request_SMB_Data smbData = new SMB_COM_READ_ANDX_Request_SMB_Data();
            smbData.ByteCount = 0;

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

            return packet;
        }