/// <summary>
        /// Create NT_TRANSACT_QUERY_QUOTA Server Response 
        /// </summary>
        /// <param name="connection">the connection identified the client</param>
        /// <param name = "quotaInfo">quota information </param>
        /// <returns>The SmbNtTransQueryQuotaResponsePacket </returns>
        /// <exception cref="ArgumentNullException">connection must not be null</exception>
        public virtual SmbNtTransQueryQuotaResponsePacket CreateNtTransQueryQuotaResponse(
            SmbServerConnection connection,
            params NT_TRANSACT_QUERY_QUOTA_Response_NT_Trans_Data[] quotaInfo)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            SmbNtTransQueryQuotaResponsePacket packet = new SmbNtTransQueryQuotaResponsePacket();

            // get the request packet
            SmbPacket request = connection.GetRequestPacket(connection.MessageId);

            // create smb packet header
            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(
                SmbCommand.SMB_COM_NT_TRANSACT,
                connection.ProcessId, connection.MessageId, request.SmbHeader.Uid, request.SmbHeader.Tid,
                (SmbFlags)connection.Capability.Flag, (SmbFlags2)connection.Capability.Flags2);

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

            // reserved 3 bytes.
            smbParameters.Reserved1 = new byte[3];
            smbParameters.Setup = new ushort[0];

            smbParameters.WordCount = (byte)(CifsMessageUtils.GetSize<SMB_COM_NT_TRANSACT_SuccessResponse_SMB_Parameters>(
                smbParameters) / SmbCapability.NUM_BYTES_OF_WORD);

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

            // update query quota data
            Collection<NT_TRANSACT_QUERY_QUOTA_Response_NT_Trans_Data> ntTransDataList =
                new Collection<NT_TRANSACT_QUERY_QUOTA_Response_NT_Trans_Data>();
            if (quotaInfo != null)
            {
                ntTransDataList = new Collection<NT_TRANSACT_QUERY_QUOTA_Response_NT_Trans_Data>(quotaInfo);
            }

            // update trans2 param
            NT_TRANSACT_QUERY_QUOTA_Response_NT_Trans_Parameters ntTransParameters = packet.NtTransParameters;

            foreach (NT_TRANSACT_QUERY_QUOTA_Response_NT_Trans_Data data in ntTransDataList)
            {
                ntTransParameters.QuotaDataSize += (uint)
                    CifsMessageUtils.GetSize<NT_TRANSACT_QUERY_QUOTA_Response_NT_Trans_Data>(data);
            }

            // store the parameters and data to packet.
            packet.NtTransParameters = ntTransParameters;
            packet.NtTransDataList = ntTransDataList;
            packet.SmbParameters = smbParameters;
            packet.SmbData = smbData;

            packet.UpdateCountAndOffset();

            return packet;
        }
        /// <summary>
        /// Verify Application Requests Querying User Quota Information.
        /// </summary>
        /// <param name="isReturnSingleEntry">Whether Entry is single or not.</param>
        /// <param name="response">The NT_TRANSACT_QUERY_QUOTA response.</param>
        private void VerifyNtTransQueryQuotaRequestAndResponse(
            bool isReturnSingleEntry,
            SmbNtTransQueryQuotaResponsePacket response)
        {
            // In the stackSDK ReturnSinEntry is defined as a byte type, here judge if it is equal to 1.
            if (isReturnSingleEntry)
            {
                //
                // The following statement code will be run only when debugging.
                //
                Site.Log.Add(LogEntryKind.Debug,
                    @"Verify MS-SMB_R8457");

                //
                // Verify MS-SMB requirement: MS-SMB_R8457.
                //
                // The user quota information entry is returned in NtTransDataList. If the NtTransDataList's count is
                // 1, it means the SUT only returns one user quota information entry.
                Site.CaptureRequirementIfAreEqual<int>(
                    1,
                    response.NtTransDataList.Count,
                    8457,
                    @"[In Application Requests Querying Quota Information,The application MUST provide:]
                    ReturnSingleEntry: If TRUE,then the server MUST return a single user quota information entry.");
            }
        }
        private void VerifyMessageSyntaxNtTransactQueryQuotaResponse(
            SmbNtTransQueryQuotaResponsePacket response,
            int sidListLength,
            int startSidLength,
            int quotaInfoCount,
            uint ntTranMaxDataCount)
        {
            //
            // The following statement code will be run only when debugging.
            //
            Site.Log.Add(LogEntryKind.Debug,
                @"Verify MS-SMB_R9454");

            //
            // Verify MS-SMB requirement: MS-SMB_R9454.
            //
            Site.CaptureRequirementIfAreEqual<uint>(
                response.SmbParameters.TotalDataCount,
                response.NtTransParameters.QuotaDataSize,
                9454,
                @"[In Server Response]DataLength (4 bytes):  This field MUST be equal to the SMB_Parameters.Words.
                TotalDataCount field.");

            //
            // The following statement code will be run only when debugging.
            //
            Site.Log.Add(LogEntryKind.Debug,
                @"Verify MS-SMB_R30016");

            //
            // Verify MS-SMB requirement: MS-SMB_R30016.
            //
            // Copying is the server behavior. If "Status" isn't null, it means the SUT has copied
            // "Status" into reponse.
            Site.CaptureRequirementIfIsNotNull(
                response.SmbHeader.Status,
                30016,
                @"[In Receiving an NT_TRANS_QUERY_QUOTA Request] <128> Section 3.3.5.10.2: The returned Status is
                copied into the SMB_Header.Status field of the response. ");

            //
            // The following statement code will be run only when debugging.
            //
            Site.Log.Add(LogEntryKind.Debug,
                @"Verify MS-SMB_R2464, the Count is: {0}",
                response.NtTransDataList.Count);

            //
            // Verify MS-SMB requirement: MS-SMB_R2464.
            //
            Site.CaptureRequirementIfIsTrue(
                response.NtTransDataList.Count <= ntTranMaxDataCount,
                2464,
                @"The server MUST return as much of the available quota information that is able to fit in the maximum
                response buffer size denoted by MaxDataCount.");

            // This is R9433's condition: Whether both[NT_Trans_Parameters.SidListLength and
            // NT_Trans_Parameters.StartSidLength] are zero.
            if ((sidListLength == 0) && (startSidLength == 0))
            {
                //
                // The following statement code will be run only when debugging.
                //
                Site.Log.Add(LogEntryKind.Debug,
                    @"Verify MS-SMB_R9433, response.NtTransDataList: {0}",
                    response.NtTransDataList);

                // If Count isn't null, it means the SUT has enumerated the quota information.
                //
                // Verify MS-SMB requirement: MS-SMB_R9433.
                //
                Site.CaptureRequirementIfIsNotNull(
                    response.NtTransDataList,
                    9433,
                    @"[In Client Request]If both[NT_Trans_Parameters.SidListLength and
                    NT_Trans_Parameters.StartSidLength] are zero, then the quota information for all SIDs on the
                    underlying object store of a share MUST be enumerated by the server.");
            }

            //
            // The following statement code will be run only when debugging.
            //
            Site.Log.Add(LogEntryKind.Debug,
                @"Verify MS-SMB_R2465,NtTransDataList.Count{0}",
                response.NtTransDataList.Count);

            //
            // Verify MS-SMB requirement: MS-SMB_R2465.
            //
            // The SUT place the quota information in the NtTransDataList.
            bool isVerifyR2465 = response.NtTransDataList.Count >= 0;

            Site.CaptureRequirementIfIsTrue(
                isVerifyR2465,
                2465,
                @"The server MUST place the quota information in the response, as specified in section 2.2.7.3.2, and
                send the response back to the client.");
        }
        /// <summary>
        /// create the nt transaction packet
        /// </summary>
        /// <param name="request">the request packet</param>
        /// <param name="smbHeader">the smb header of response packet</param>
        /// <param name="channel">the channel contains the packet bytes</param>
        /// <returns>the response packet</returns>
        private SmbPacket CreateNtTransactionResponsePacket(SmbPacket request, SmbHeader smbHeader, Channel channel)
        {
            SmbPacket smbPacket = null;

            if (smbHeader.Status == 0 && channel.Peek<byte>(0) == 0 && channel.Peek<ushort>(1) == 0)
            {
                return smbPacket;
            }

            SmbNtTransactRequestPacket ntTransactRequest = request as SmbNtTransactRequestPacket;
            if (ntTransactRequest == null)
            {
                return smbPacket;
            }

            // find regular packet
            switch ((uint)ntTransactRequest.SmbParameters.Function)
            {
                case (uint)NtTransSubCommand.NT_TRANSACT_RENAME:
                    smbPacket = new SmbNtTransRenameResponsePacket();
                    break;

                case (uint)NtTransSubCommand.NT_TRANSACT_CREATE:
                    smbPacket = new SmbNtTransactCreateResponsePacket();
                    break;

                case (uint)NtTransSubCommand.NT_TRANSACT_IOCTL:

                    NT_TRANSACT_IOCTL_SETUP setup =
                       CifsMessageUtils.ToStuct<NT_TRANSACT_IOCTL_SETUP>(
                       CifsMessageUtils.ToBytesArray<ushort>(ntTransactRequest.SmbParameters.Setup));

                    switch ((NtTransFunctionCode)setup.FunctionCode)
                    {
                        case NtTransFunctionCode.FSCTL_SRV_ENUMERATE_SNAPSHOTS:
                            smbPacket = new SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket();
                            break;

                        case NtTransFunctionCode.FSCTL_SRV_REQUEST_RESUME_KEY:
                            smbPacket = new SmbNtTransFsctlSrvRequestResumeKeyResponsePacket();
                            break;

                        case NtTransFunctionCode.FSCTL_SRV_COPYCHUNK:
                            smbPacket = new SmbNtTransFsctlSrvCopyChunkResponsePacket();
                            break;

                        default:
                            smbPacket = new SmbNtTransactIoctlResponsePacket();
                            break;
                    }

                    break;

                case (uint)SmbNtTransSubCommand.NT_TRANSACT_QUERY_QUOTA:
                    smbPacket = new SmbNtTransQueryQuotaResponsePacket();
                    break;

                case (uint)SmbNtTransSubCommand.NT_TRANSACT_SET_QUOTA:
                    smbPacket = new SmbNtTransSetQuotaResponsePacket();
                    break;

                default:
                    break;
            }

            return smbPacket;
        }
        /// <summary>
        /// create the nt transaction packet
        /// </summary>
        /// <param name="request">the request packet</param>
        /// <param name="smbHeader">the smb header of response packet</param>
        /// <param name="channel">the channel contains the packet bytes</param>
        /// <returns>the response packet</returns>
        private SmbPacket CreateNtTransactionResponsePacket(SmbPacket request, SmbHeader smbHeader, Channel channel)
        {
            SmbPacket smbPacket = null;

            if (smbHeader.Status == 0 && channel.Peek <byte>(0) == 0 && channel.Peek <ushort>(1) == 0)
            {
                return(smbPacket);
            }

            SmbNtTransactRequestPacket ntTransactRequest = request as SmbNtTransactRequestPacket;

            if (ntTransactRequest == null)
            {
                return(smbPacket);
            }

            // find regular packet
            switch ((uint)ntTransactRequest.SmbParameters.Function)
            {
            case (uint)NtTransSubCommand.NT_TRANSACT_RENAME:
                smbPacket = new SmbNtTransRenameResponsePacket();
                break;

            case (uint)NtTransSubCommand.NT_TRANSACT_CREATE:
                smbPacket = new SmbNtTransactCreateResponsePacket();
                break;

            case (uint)NtTransSubCommand.NT_TRANSACT_IOCTL:

                NT_TRANSACT_IOCTL_SETUP setup =
                    CifsMessageUtils.ToStuct <NT_TRANSACT_IOCTL_SETUP>(
                        CifsMessageUtils.ToBytesArray <ushort>(ntTransactRequest.SmbParameters.Setup));

                switch ((NtTransFunctionCode)setup.FunctionCode)
                {
                case NtTransFunctionCode.FSCTL_SRV_ENUMERATE_SNAPSHOTS:
                    smbPacket = new SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket();
                    break;

                case NtTransFunctionCode.FSCTL_SRV_REQUEST_RESUME_KEY:
                    smbPacket = new SmbNtTransFsctlSrvRequestResumeKeyResponsePacket();
                    break;

                case NtTransFunctionCode.FSCTL_SRV_COPYCHUNK:
                    smbPacket = new SmbNtTransFsctlSrvCopyChunkResponsePacket();
                    break;

                default:
                    smbPacket = new SmbNtTransactIoctlResponsePacket();
                    break;
                }

                break;

            case (uint)SmbNtTransSubCommand.NT_TRANSACT_QUERY_QUOTA:
                smbPacket = new SmbNtTransQueryQuotaResponsePacket();
                break;

            case (uint)SmbNtTransSubCommand.NT_TRANSACT_SET_QUOTA:
                smbPacket = new SmbNtTransSetQuotaResponsePacket();
                break;

            default:
                break;
            }

            return(smbPacket);
        }
        /// <summary>
        /// Verify whether the two NtTransQueryQuota response are equal or not.
        /// </summary>
        /// <param name="smbNtTransQueryQuotaPacket1"> The first NtTransQueryQuota response.</param>
        /// <param name="smbNtTransQueryQuotaPacket2"> The second NtTransQueryQuota response.</param>
        /// <returns></returns>
        private bool VerifyNtTransQueryQuotaResponse(
            SmbNtTransQueryQuotaResponsePacket smbNtTransQueryQuotaPacket1,
            SmbNtTransQueryQuotaResponsePacket smbNtTransQueryQuotaPacket2)
        {
            return (smbNtTransQueryQuotaPacket1.IsSignRequired == smbNtTransQueryQuotaPacket2.IsSignRequired)
                && (smbNtTransQueryQuotaPacket1.NtTransDataList.Count ==
                smbNtTransQueryQuotaPacket2.NtTransDataList.Count)
                && CompareArrayEquals(
                smbNtTransQueryQuotaPacket1.PacketBytes,
                smbNtTransQueryQuotaPacket2.PacketBytes)
                && (smbNtTransQueryQuotaPacket1.PacketType == smbNtTransQueryQuotaPacket2.PacketType)
                && CompareArrayEquals(
                smbNtTransQueryQuotaPacket1.SmbData.Pad1,
                smbNtTransQueryQuotaPacket2.SmbData.Pad1)
                && CompareArrayEquals(
                smbNtTransQueryQuotaPacket1.SmbData.Pad2,

                smbNtTransQueryQuotaPacket2.SmbData.Pad2)
                && (smbNtTransQueryQuotaPacket1.SmbParameters.DataDisplacement == smbNtTransQueryQuotaPacket2.SmbParameters.DataDisplacement)
                && (smbNtTransQueryQuotaPacket1.SmbParameters.DataOffset ==
                smbNtTransQueryQuotaPacket2.SmbParameters.DataOffset)
                && (smbNtTransQueryQuotaPacket1.SmbParameters.ParameterCount ==
                smbNtTransQueryQuotaPacket2.SmbParameters.ParameterCount)
                && (smbNtTransQueryQuotaPacket1.SmbParameters.ParameterDisplacement ==
                smbNtTransQueryQuotaPacket2.SmbParameters.ParameterDisplacement)
                && (smbNtTransQueryQuotaPacket1.SmbParameters.ParameterOffset ==
                smbNtTransQueryQuotaPacket2.SmbParameters.ParameterOffset)
                && CompareArrayEquals(
                smbNtTransQueryQuotaPacket1.SmbParameters.Reserved1,
                smbNtTransQueryQuotaPacket2.SmbParameters.Reserved1)
                && CompareArrayEquals(
                smbNtTransQueryQuotaPacket1.SmbParameters.Setup,
                smbNtTransQueryQuotaPacket2.SmbParameters.Setup)
                && (smbNtTransQueryQuotaPacket1.SmbParameters.SetupCount ==
                smbNtTransQueryQuotaPacket2.SmbParameters.SetupCount)
                && (smbNtTransQueryQuotaPacket1.SmbParameters.TotalParameterCount ==
                smbNtTransQueryQuotaPacket2.SmbParameters.TotalParameterCount)
                && (smbNtTransQueryQuotaPacket1.SmbParameters.WordCount ==
                smbNtTransQueryQuotaPacket2.SmbParameters.WordCount);
        }
 /// <summary>
 /// Deep copy constructor.
 /// </summary>
 public SmbNtTransQueryQuotaResponsePacket(SmbNtTransQueryQuotaResponsePacket packet)
     : base(packet)
 {
     this.InitDefaultValue();
 }
 /// <summary>
 /// Deep copy constructor. 
 /// </summary>
 public SmbNtTransQueryQuotaResponsePacket(SmbNtTransQueryQuotaResponsePacket packet)
     : base(packet)
 {
     this.InitDefaultValue();
 }