/// <summary>
        /// Verify FSCTL_SRV_ENUMERATE_SNAPSHOTS Server Response.
        /// </summary>
        /// <param name="response">The FSCTL_SRV_ENUMERATE_SNAPSHOTS Server Response.</param>
        private void VerifyMessageSyntaxFsctlSrvEnumerateSnapshotsRequest(
            SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket response)
        {
            if (response.NtTransData.snapShotMultiSZ != null)
            {
                //
                // The following statement code will be run only when debugging.
                //
                Site.Log.Add(LogEntryKind.Debug,
                    @"Verify MS-SMB_R9403,the length of snapShotMultiSZ is {0}",
                    response.NtTransData.snapShotMultiSZ.Length);

                //
                // Verify MS-SMB requirement: MS-SMB_R9403.
                //
                // The snapshots take the form "@GMT-YYYY.MM.DD-HH.MM.SS." and are terminated by two additional 16-bit
                // unicode NULL characters, so one snapshot is 50 bytes.The byte length divide 50 is the number
                // of returned snapshots.
                Site.CaptureRequirementIfAreEqual<uint>(
                    (uint)response.NtTransData.snapShotMultiSZ.Length / 50,
                    response.NtTransData.NumberOfSnapShotsReturned,
                    9403,
                    @"[In FSCTL_SRV_ENUMERATE_SNAPSHOTS Response]NumberOfSnapShotsReturned (4 bytes):  This value MUST
                    be the number of snapshots that are returned in this response.");

                //
                // The following statement code will be run only when debugging.
                //
                Site.Log.Add(LogEntryKind.Debug,
                    @"Verify MS-SMB_R9407,SnapShotMultiSZ:{0}",
                    BitConverter.ToString(response.NtTransData.snapShotMultiSZ));

                //
                // Verify MS-SMB requirement: MS-SMB_R9407.
                //
                bool isVerifyR9407 = true;

                // Check if every snapshot is null-terminated.
                // One snapshot is 50 bytes, and the last two bytes should be '\0'.
                for (int i = 0; i < response.NtTransData.NumberOfSnapShotsReturned; ++i)
                {
                    if (!((response.NtTransData.snapShotMultiSZ[i * 50 + 48] == '\0')
                        && (response.NtTransData.snapShotMultiSZ[i * 50 + 49] == '\0')))
                    {
                        isVerifyR9407 = false;
                        break;
                    }
                }

                Site.CaptureRequirementIfIsTrue(
                    isVerifyR9407,
                    9407,
                    @"[In FSCTL_SRV_ENUMERATE_SNAPSHOTS Response]SnapShotMultiSZ (variable):  Each snapshot MUST be
                    encoded as a NULL-terminated sequence of 16-bit Unicode characters.");

                //
                // The following statement code will be run only when debugging.
                //
                Site.Log.Add(LogEntryKind.Debug,
                    @"Verify MS-SMB_R9408,snapShotMultisz:{0}",
                    BitConverter.ToString(response.NtTransData.snapShotMultiSZ));

                //
                // Verify MS-SMB requirement: MS-SMB_R9408.
                //
                bool isVerifyR9408 = true;

                // Check if every snapshot takes the form: @GMT-YYYY.MM.DD-HH.MM.SS.
                for (int i = 0; i < response.NtTransData.NumberOfSnapShotsReturned; ++i)
                {
                    if (!IsSnapShotValid(response.SnapShots[i]))
                    {
                        isVerifyR9408 = false;
                        break;
                    }
                }

                Site.CaptureRequirementIfIsTrue(
                    isVerifyR9408,
                    9408,
                    @"[In FSCTL_SRV_ENUMERATE_SNAPSHOTS Response]SnapShotMultiSZ (variable):  Each snapshot MUST take
                    on the following form: @GMT-YYYY.MM.DD-HH.MM.SS.");

                //
                // The following statement code will be run only when debugging.
                //
                Site.Log.Add(LogEntryKind.Debug,
                    @"Verify MS-SMB_R9409,SnapShotMultiSZ:{0}",
                    BitConverter.ToString(response.NtTransData.snapShotMultiSZ));

                //
                // Verify MS-SMB requirement: MS-SMB_R9409.
                //
                bool isVerifyR9409 = true;

                // For every 50 snapShotMultiSZ combian composing a snapShot, if snapShot is unicode null
                // characters, the last 2 snapShotMultiSZ must be '0'.
                for (int i = 0; i < response.NtTransData.NumberOfSnapShotsReturned; ++i)
                {
                    if (!((response.NtTransData.snapShotMultiSZ[i * 50 + 48] == '\0')
                        && (response.NtTransData.snapShotMultiSZ[i * 50 + 49] == '\0')))
                    {
                        isVerifyR9409 = false;
                        break;
                    }
                }

                Site.CaptureRequirementIfIsTrue(
                    isVerifyR9409,
                    9409,
                    @"[In FSCTL_SRV_ENUMERATE_SNAPSHOTS Response]SnapShotMultiSZ (variable):  The concatenated list
                    MUST be terminated by two additional 16-bit Unicode NULL characters.");

                if (response.NtTransData.NumberOfSnapShotsReturned == 0)
                {
                    //
                    // Verify requirement MS-SMB_R9410 and MS-SMB_R109410
                    //
                    string isR9410Implementated = Site.Properties.Get("SHOULDMAYR9410Implementation");
                    bool isR109410Satisfied = (('\0' == response.NtTransData.snapShotMultiSZ[0])
                        && ('\0' == response.NtTransData.snapShotMultiSZ[1]));

                    if (isWindows)
                    {
                        //
                        // The following statement code will be run only when debugging.
                        //
                        Site.Log.Add(LogEntryKind.Debug,
                            @"Verify MS-SMB_R109410,SnapShotMultiSZ:{0}",
                            BitConverter.ToString(response.NtTransData.snapShotMultiSZ));

                        //
                        // Verify MS-SMB requirement: MS-SMB_R109410.
                        //
                        Site.CaptureRequirementIfIsTrue(
                            isR109410Satisfied,
                            109410,
                            @"[In FSCTL_SRV_ENUMERATE_SNAPSHOTS Response]SnapShotMultiSZ (variable):  If the response
                            contains no snapshots,then the server  sets this field to two 16-bit Unicode NULL
                            characters in Windows.");

                        if (null == isR9410Implementated)
                        {
                            Site.Properties.Add("SHOULDMAYR9410Implementation", Boolean.TrueString);
                            isR9410Implementated = Boolean.TrueString;
                        }
                    }

                    if (null != isR9410Implementated)
                    {
                        bool implemented = Boolean.Parse(isR9410Implementated);
                        bool isSatisfied = isR109410Satisfied;

                        //
                        // The following statement code will be run only when debugging.
                        //
                        Site.Log.Add(LogEntryKind.Debug,
                            @"Verify MS-SMB_R9410,SnapShotMultiSZ:{0}",
                            BitConverter.ToString(response.NtTransData.snapShotMultiSZ));

                        //
                        // Verify MS-SMB requirement: MS-SMB_R9410.
                        //
                        Site.CaptureRequirementIfAreEqual<Boolean>(
                            implemented,
                            isSatisfied,
                            9410,
                            String.Format("[In FSCTL_SRV_ENUMERATE_SNAPSHOTS Response]SnapShotMultiSZ (variable): If " +
                            "the response contains no snapshots, then the server SHOULD set this field to two 16-bit " +
                            "Unicode NULL characters. This requirement is {0}implemented", implemented ? "" : "not "));
                    }
                }
            }
        }
        /// <summary>
        /// Create FSCTL_SRV_ENUMERATE_SNAPSHOTS Response 
        /// </summary>
        /// <param name="connection">the connection identified the client</param>
        /// <param name="numberOfSnapShots">This value MUST be the number of snapshots for the volume. </param>
        /// <param name = "snapShotData">
        /// A concatenated set of snapshot names. Each snapshot name MUST be formatted as a null-terminated array of 
        /// 16-bit Unicode characters. The concatenated list MUST be terminated by two 16-bit Unicode NULL characters 
        /// </param>
        /// <returns>The SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket </returns>
        /// <exception cref="ArgumentNullException">connection must not be null</exception>
        public virtual SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket CreateFsctlSrvEnumerateSnapshotsResponse(
            SmbServerConnection connection,
            uint numberOfSnapShots,
            params string[] snapShotData)
        {
            if (snapShotData == null)
            {
                snapShotData = new string[0];
            }

            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket packet = new SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket();

            // 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 trans2 data
            NT_TRANSACT_ENUMERATE_SNAPSHOTS_Response_NT_Trans_Data ntTransData = packet.NtTransData;
            ntTransData.NumberOfSnapShots = numberOfSnapShots;
            ntTransData.NumberOfSnapShotsReturned = (uint)snapShotData.Length;
            // initiallize to zero
            ntTransData.SnapShotArraySize = 0x00;
            ntTransData.snapShotMultiSZ = new byte[ntTransData.SnapShotArraySize];

            // update snapshots
            packet.SnapShots = new Collection<string>(snapShotData);

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

            packet.UpdateCountAndOffset();

            return packet;
        }
        private void VerifyReceiveFsctlSrvEnumerateSnapshotsFunctionCode(
            SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket response,
            int expectedSnapShotsCount,
            int expectedSnapshotsReturnedCount,
            bool isMaxDataCountLargeEnough)
        {
            //
            // The following statement code will be run only when debugging.
            //
            Site.Log.Add(LogEntryKind.Debug,
                @"Verify MS-SMB_R2437");

            //
            // Verify MS-SMB requirement: MS-SMB_R2437.
            //
            // The total number of previous versions can't be got.
            Site.CaptureRequirementIfAreEqual<uint>(
                (uint)response.SnapShots.Count,
                response.NtTransData.NumberOfSnapShotsReturned,
                2437,
                @"The NumberOfSnapshots MUST contain the total number of previous versions that are available for
                    the volume, and NumberOfSnapshotsReturned contains the number of entries that are returned in this
                    enumeration.");

            // isMaxDataCountLargeEnough means if MaxDataCount is large enough.
            if (!isMaxDataCountLargeEnough)
            {
                //
                // Verify requirement MS-SMB_R4980 and MS-SMB_R4981
                //
                string isR4980Implementated = Site.Properties.Get("SHOULDMAYR4980Implementation");

                // NumberOfSnapShotsReturned is the number of returned entries.
                bool isR4981Satisfied = (0 == response.NtTransData.NumberOfSnapShotsReturned);

                if (isWindows)
                {
                    //
                    // The following statement code will be run only when debugging.
                    //
                    Site.Log.Add(LogEntryKind.Debug,
                        @"Verify MS-SMB_R4981,NumberOfSnapShotsReturned:{0}",
                        response.NtTransData.NumberOfSnapShotsReturned);

                    //
                    // Verify MS-SMB requirement: MS-SMB_R4981.
                    //
                    Site.CaptureRequirementIfIsTrue(
                        isR4981Satisfied,
                        4981,
                        @"[In Receiving an FSCTL_SRV_ENUMERATE_SNAPSHOTS Function Code]If MaxDataCount is not large
                            enough to hold all of the entries,then the server does return zero entries in windows.");

                    if (null == isR4980Implementated)
                    {
                        Site.Properties.Add("SHOULDMAYR4980Implementation", Boolean.TrueString);
                        isR4980Implementated = Boolean.TrueString;
                    }
                }

                if (null != isR4980Implementated)
                {
                    bool implemented = Boolean.Parse(isR4980Implementated);
                    bool isSatisfied = isR4981Satisfied;

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

                    //
                    // Verify MS-SMB requirement: MS-SMB_R4980.
                    //
                    Site.CaptureRequirementIfAreEqual<Boolean>(
                        implemented,
                        isSatisfied,
                        4980,
                        String.Format("[In Receiving an FSCTL_SRV_ENUMERATE_SNAPSHOTS Function Code]If " +
                        "MaxDataCount is not large enough to hold all of the entries,then the server SHOULD return " +
                        "zero entry. This requirement is {0}implemented", implemented ? "" : "not "));
                }
            }
            if (response.NtTransData.snapShotMultiSZ != null)
            {

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

                //
                // Verify MS-SMB requirement: MS-SMB_R4982.
                //
                // The available previous versions are stored in the SnapShotMultiSZ. Once the snapShotArraySize is
                // equal to the length of SnapShotMultiSZ, this requirement is verified.
                Site.CaptureRequirementIfAreEqual<int>(
                    response.NtTransData.snapShotMultiSZ.Length,
                    (int)response.NtTransData.SnapShotArraySize,
                    4982,
                    @"[In Receiving an FSCTL_SRV_ENUMERATE_SNAPSHOTS Function Code]The value returned in
                    SnapShotArraySize MUST be the size required to receive all of the available previous versions.");

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

                //
                // Verify MS-SMB requirement: MS-SMB_R2436.
                //
                // NumberOfSnapShotsReturned contains the number of entries that are returned in the enumeration.
                bool isVerifyR2436 = response.NtTransData.NumberOfSnapShotsReturned >= 0;

                Site.CaptureRequirementIfIsTrue(
                    isVerifyR2436,
                    2436,
                    @"[In Receiving an FSCTL_SRV_ENUMERATE_SNAPSHOTS Function Code] The server MUST return an
                    enumeration of available previous versions, as specified in section 2.2.7.2.2.");
            }
        }
 /// <summary>
 /// Deep copy constructor. 
 /// </summary>
 public SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket(
     SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket packet)
     : base(packet)
 {
 }
        /// <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>
 /// Deep copy constructor.
 /// </summary>
 public SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket(
     SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket packet)
     : base(packet)
 {
 }