/// <summary>
        /// Create TRANS2_FIND_FIRST2 Response 
        /// </summary>
        /// <param name="connection">the connection identified the client</param>
        /// <param name = "sid">
        /// The security identifier of this user. For details, see [MS-DTYP] section 2.4.2. Note that [CIFS] sections 
        /// 4.3.4, 4.3.4.7, 4.3.5, and 4.3.5.6 use Sid as the field name for  a search handle. In [XOPEN-SMB], the 
        /// search handle field is called a findfirst_dirhandle  or findnext_dirhandle. These are better field names 
        /// for a search handle. 
        /// </param>
        /// <param name = "searchCount">search count </param>
        /// <param name = "isEndOfSearch">whether end of search </param>
        /// <param name = "eaErrorOffset">eaError Offset </param>
        /// <param name = "lastNameOffset">last name offset </param>
        /// <param name = "data">data specified by [FSCC] </param>
        /// <returns>The SmbTrans2FindFirst2ResponsePacket </returns>
        /// <exception cref="ArgumentNullException">connection must not be null</exception>
        public virtual SmbTrans2FindFirst2ResponsePacket CreateTrans2FindFirst2Response(
            SmbServerConnection connection,
            ushort sid,
            ushort searchCount,
            bool isEndOfSearch,
            ushort eaErrorOffset,
            ushort lastNameOffset,
            object data)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            SmbTrans2FindFirst2ResponsePacket packet = new SmbTrans2FindFirst2ResponsePacket();

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

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

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

            smbParameters.Setup = new ushort[0];

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

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

            // update trans2 param
            TRANS2_FIND_FIRST2_Response_Trans2_Parameters trans2Parameters = packet.Trans2Parameters;

            trans2Parameters.SID = sid;
            trans2Parameters.SearchCount = searchCount;
            trans2Parameters.EndOfSearch = (ushort)(isEndOfSearch ? 1 : 0);
            trans2Parameters.EaErrorOffset = eaErrorOffset;
            trans2Parameters.LastNameOffset = lastNameOffset;

            // update trans2 data
            TRANS2_FIND_FIRST2_Response_Trans2_Data trans2Data = packet.Trans2Data;

            trans2Data.Data = data;

            // store the parameters and data to packet.
            packet.Trans2Parameters = trans2Parameters;
            packet.Trans2Data = trans2Data;
            packet.SmbParameters = smbParameters;
            packet.SmbData = smbData;

            packet.UpdateCountAndOffset();

            return packet;
        }
        private SmbPacket CreateTransaction2ResponsePacket(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;
            }

            SmbTransaction2RequestPacket transaction2Request = request as SmbTransaction2RequestPacket;
            if (transaction2Request == null)
            {
                return smbPacket;
            }

            // if no setup command. break
            if (transaction2Request.SmbParameters.SetupCount == 0)
            {
                return smbPacket;
            }

            // decode packet using the setup command
            switch ((Trans2SubCommand)transaction2Request.SmbParameters.Setup[0])
            {
                case Trans2SubCommand.TRANS2_QUERY_FILE_INFORMATION:
                    SmbTrans2QueryFileInformationRequestPacket queryFileRequest =
                        transaction2Request as SmbTrans2QueryFileInformationRequestPacket;
                    if (queryFileRequest != null)
                    {
                        smbPacket = new SmbTrans2QueryFileInformationResponsePacket(
                            queryFileRequest.Trans2Parameters.InformationLevel);
                    }
                    break;

                case Trans2SubCommand.TRANS2_QUERY_PATH_INFORMATION:
                    SmbTrans2QueryPathInformationRequestPacket queryPathRequest =
                       transaction2Request as SmbTrans2QueryPathInformationRequestPacket;
                    if (queryPathRequest != null)
                    {
                        smbPacket = new SmbTrans2QueryPathInformationResponsePacket(
                            queryPathRequest.Trans2Parameters.InformationLevel);
                    }
                    break;

                case Trans2SubCommand.TRANS2_SET_FILE_INFORMATION:
                    smbPacket = new SmbTrans2SetFileInformationResponsePacket();
                    break;

                case Trans2SubCommand.TRANS2_SET_PATH_INFORMATION:
                    smbPacket = new SmbTrans2SetPathInformationResponsePacket();
                    break;

                case Trans2SubCommand.TRANS2_QUERY_FS_INFORMATION:
                    SmbTrans2QueryFsInformationRequestPacket queryFsRequest =
                        transaction2Request as SmbTrans2QueryFsInformationRequestPacket;
                    if (queryFsRequest != null)
                    {
                        smbPacket = new SmbTrans2QueryFsInformationResponsePacket(
                            queryFsRequest.Trans2Parameters.InformationLevel);
                    }
                    break;

                case Trans2SubCommand.TRANS2_SET_FS_INFORMATION:
                    smbPacket = new SmbTrans2SetFsInformationResponsePacket();
                    break;

                case Trans2SubCommand.TRANS2_FIND_FIRST2:
                    SmbTrans2FindFirst2RequestPacket first2Request =
                       transaction2Request as SmbTrans2FindFirst2RequestPacket;
                    if (first2Request != null)
                    {
                        smbPacket = new SmbTrans2FindFirst2ResponsePacket(first2Request.Trans2Parameters.InformationLevel,
                            (first2Request.Trans2Parameters.Flags & Trans2FindFlags.SMB_FIND_RETURN_RESUME_KEYS)
                            == Trans2FindFlags.SMB_FIND_RETURN_RESUME_KEYS);
                    }
                    break;

                case Trans2SubCommand.TRANS2_FIND_NEXT2:
                    SmbTrans2FindNext2RequestPacket next2Request =
                       transaction2Request as SmbTrans2FindNext2RequestPacket;
                    if (next2Request != null)
                    {
                        smbPacket = new SmbTrans2FindNext2ResponsePacket(next2Request.Trans2Parameters.InformationLevel,
                            (next2Request.Trans2Parameters.Flags & Trans2FindFlags.SMB_FIND_RETURN_RESUME_KEYS)
                            == Trans2FindFlags.SMB_FIND_RETURN_RESUME_KEYS);
                    }
                    break;

                case Trans2SubCommand.TRANS2_GET_DFS_REFERRAL:
                    smbPacket = new SmbTrans2GetDfsReferralResponsePacket();
                    break;

                default:
                    break;
            }

            return smbPacket;
        }
        /// <summary>
        /// Verify TRAN2_FIND_FIRST2 Client Request.
        /// </summary>
        /// <param name="informationLevel">The InformationLevel in the Trans2Parameters of the 
        /// TRAN2_FIND_FIRST2 Client Request.</param>
        /// <param name="response">The TRAN2_FIND_FIRST2 Server Response.</param>
        /// <param name="isFindFullDirectoryInfoNull">To verify whether the struct of 
        /// SMB_FIND_FILE_FULL_DIRECTORY_INFO_OF_TRANS2_FIND_FIRST2 is null or not.</param>
        /// <param name="isFindBothDirectoryInfoNull">To verify whether the struct of 
        /// SMB_FIND_FILE_BOTH_DIRECTORY_INFO_OF_TRANS2_FIND_FIRST2 is null or not.</param>
        private void VerifyMessageSyntaxTrans2FindFirst2Request(
            InformationLevel informationLevel,
            SmbTrans2FindFirst2ResponsePacket response,
            bool isFindFullDirectoryInfoNull,
            bool isFindBothDirectoryInfoNull)
        {
            // SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO and SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO are the new
            // informationLevel specified in section 2.2.2.3.1.
            if ((informationLevel == InformationLevel.SmbFindFileIdBothDirectoryInfo)
               || (informationLevel == InformationLevel.SmbFindFileIdFullDirectoryInfo))
            {
                // The following statement code will be run only when debugging.
                //
                Site.Log.Add(LogEntryKind.Debug,
                    @"Verify MS-SMB_R2404 ,isfindIdFullDirectoryInfoNull is : {0},
                    isfinIdBothDirectoryInfoNull is {1}",
                    isFindFullDirectoryInfoNull,
                    isFindBothDirectoryInfoNull);

                //
                // Verify MS-SMB requirement: MS-SMB_R2404.
                //
                // If one of the new Information Levels structure isn't null, it means the structure has been used for
                // the return of subsequent entries in the enumeration continuation.
                bool isVerifyR2404 = (isFindFullDirectoryInfoNull
                    || isFindBothDirectoryInfoNull);

                Site.CaptureRequirementIfIsTrue(
                    isVerifyR2404,
                    2404,
                    @"[In Receiving a TRANS2_FIND_NEXT2 Request New Information Levels] If the query is started using
                    one of the new Information Levels, then as specified in section 2.2.2.3.1, the same Information
                    Level structure MUST be used for the return of subsequent entries in the enumeration
                    continuation.");

                if (isWindows)
                {
                    // 0x0105 is the number of SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO,
                    // 0x0106 is the number of SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO,
                    // These two numbers are the new Infromation Level.

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

                    //
                    // Verify MS-SMB requirement: MS-SMB_R30038.
                    //
                    // 0xC00000BB is the errorcode STATUS_NOT_SUPPORTED's number.
                    // According to TD, if the SUT doesn't support the new Information Levels, it will
                    // return STATUS_NOT_SUPPORTED. Otherwise it wouldn't return STATUS_NOT_SUPPORTED.
                    Site.CaptureRequirementIfAreNotEqual<uint>(
                        0xC00000BB,
                        response.SmbHeader.Status,
                        30038,
                        @"[InReceiving a TRANS2_FIND_FIRST2 Request New Information Levels] <123> Section
                        3.3.5.9.2:Windows servers support these new Information Levels for directory queries.");
                }
                if (informationLevel == InformationLevel.SmbFindFileIdBothDirectoryInfo)
                {
                    SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO[] payload =
                    (SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO[])response.Trans2Data.Data;
                    //
                    // Verify MS-SMB requirement: MS-SMB_R9487.
                    //
                    Site.CaptureRequirementIfAreEqual<CIFS.SmbFileAttributes32>(
                        CIFS.SmbFileAttributes32.FILE_ATTRIBUTE_DIRECTORY,
                        (CIFS.SmbFileAttributes32)payload[0].FileAttributes,
                        9487,
                        @"[In SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO Extensions]ExtFileAttributes (4 bytes):  Extended attributes
                for this file that MUST be marked as a DIRECTORY.");

                    //
                    // Verify MS-SMB requirement: MS-SMB_R9488.
                    //
                    Site.CaptureRequirementIfAreEqual<uint>(
                        0,
                        payload[0].EaSize,
                        9488,
                        @"[In SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO Extensions]EaSize (4 bytes):  This field MUST be set to zero
                when sending a response .");

                    //
                    // Verify MS-SMB requirement: MS-SMB_R9491.
                    //
                    Site.CaptureRequirementIfAreEqual<uint>(
                        0x00,
                        payload[0].Reserved,
                        9491,
                        @"[In SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO] Reserved (1 byte):  This member MUST be 0x00.");

                    //
                    // Verify MS-SMB requirement: MS-SMB_R9493.
                    //
                    Site.CaptureRequirementIfAreEqual<uint>(
                        0x0000,
                        payload[0].Reserved2,
                        9493,
                        @"[In SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO]Reserved2 (2 bytes):This member MUST be 0x0000.");

                    //
                    // Verify MS-SMB requirement: MS-SMB_R3478.
                    //
                    Site.CaptureRequirementIfAreEqual<uint>(
                        0x0000,
                        payload[0].Reserved2,
                        3478,
                        @"[In SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO]Reserved2 (2 bytes):This member MUST be 0x0000.");

                    //
                    // Verify MS-SMB requirement: MS-SMB_R9483.
                    //
                    Site.CaptureRequirementIfAreEqual<ulong>(
                        0x00000000,
                        payload[0].FileIndex,
                        9483,
                        @"[In SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO]FileIndex (4 bytes):  This field MUST be set to zero when sending a response.");

                    //
                    // Verify MS-SMB requirement: MS-SMB_R9485.
                    //
                    Site.CaptureRequirementIfAreEqual<ulong>(
                        0x00000000,
                        payload[0].AllocationSize,
                        9485,
                        @"[In SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO]AllocationSize (8 bytes):  This LARGE_INTEGER field MUST be set to zero when sending a response.");

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

                    // If Field isn't unique, it will throw exception and the case will stop and won't come here.
                    // So this requirement has been verified by the protocol SDK.
                    Site.CaptureRequirement(
                        9495,
                        @"[In SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO]FileId (8 bytes):This number MUST be unique
                        for each file on a given volume.");

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

                    // If Field isn't unique, it will throw exception and the case will stop and won't come here.
                    // So this requirement has been verified by the protocol SDK.
                    Site.CaptureRequirement(
                        3480,
                        @"[In SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO]FileId (8 bytes):This number MUST be unique
                        for each file on a given volume.");
                }
            }
        }
        private SmbPacket CreateTransaction2ResponsePacket(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);
            }

            SmbTransaction2RequestPacket transaction2Request = request as SmbTransaction2RequestPacket;

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

            // if no setup command. break
            if (transaction2Request.SmbParameters.SetupCount == 0)
            {
                return(smbPacket);
            }

            // decode packet using the setup command
            switch ((Trans2SubCommand)transaction2Request.SmbParameters.Setup[0])
            {
            case Trans2SubCommand.TRANS2_QUERY_FILE_INFORMATION:
                SmbTrans2QueryFileInformationRequestPacket queryFileRequest =
                    transaction2Request as SmbTrans2QueryFileInformationRequestPacket;
                if (queryFileRequest != null)
                {
                    smbPacket = new SmbTrans2QueryFileInformationResponsePacket(
                        queryFileRequest.Trans2Parameters.InformationLevel);
                }
                break;

            case Trans2SubCommand.TRANS2_QUERY_PATH_INFORMATION:
                SmbTrans2QueryPathInformationRequestPacket queryPathRequest =
                    transaction2Request as SmbTrans2QueryPathInformationRequestPacket;
                if (queryPathRequest != null)
                {
                    smbPacket = new SmbTrans2QueryPathInformationResponsePacket(
                        queryPathRequest.Trans2Parameters.InformationLevel);
                }
                break;

            case Trans2SubCommand.TRANS2_SET_FILE_INFORMATION:
                smbPacket = new SmbTrans2SetFileInformationResponsePacket();
                break;

            case Trans2SubCommand.TRANS2_SET_PATH_INFORMATION:
                smbPacket = new SmbTrans2SetPathInformationResponsePacket();
                break;

            case Trans2SubCommand.TRANS2_QUERY_FS_INFORMATION:
                SmbTrans2QueryFsInformationRequestPacket queryFsRequest =
                    transaction2Request as SmbTrans2QueryFsInformationRequestPacket;
                if (queryFsRequest != null)
                {
                    smbPacket = new SmbTrans2QueryFsInformationResponsePacket(
                        queryFsRequest.Trans2Parameters.InformationLevel);
                }
                break;

            case Trans2SubCommand.TRANS2_SET_FS_INFORMATION:
                smbPacket = new SmbTrans2SetFsInformationResponsePacket();
                break;

            case Trans2SubCommand.TRANS2_FIND_FIRST2:
                SmbTrans2FindFirst2RequestPacket first2Request =
                    transaction2Request as SmbTrans2FindFirst2RequestPacket;
                if (first2Request != null)
                {
                    smbPacket = new SmbTrans2FindFirst2ResponsePacket(first2Request.Trans2Parameters.InformationLevel,
                                                                      (first2Request.Trans2Parameters.Flags & Trans2FindFlags.SMB_FIND_RETURN_RESUME_KEYS)
                                                                      == Trans2FindFlags.SMB_FIND_RETURN_RESUME_KEYS);
                }
                break;

            case Trans2SubCommand.TRANS2_FIND_NEXT2:
                SmbTrans2FindNext2RequestPacket next2Request =
                    transaction2Request as SmbTrans2FindNext2RequestPacket;
                if (next2Request != null)
                {
                    smbPacket = new SmbTrans2FindNext2ResponsePacket(next2Request.Trans2Parameters.InformationLevel,
                                                                     (next2Request.Trans2Parameters.Flags & Trans2FindFlags.SMB_FIND_RETURN_RESUME_KEYS)
                                                                     == Trans2FindFlags.SMB_FIND_RETURN_RESUME_KEYS);
                }
                break;

            case Trans2SubCommand.TRANS2_GET_DFS_REFERRAL:
                smbPacket = new SmbTrans2GetDfsReferralResponsePacket();
                break;

            default:
                break;
            }

            return(smbPacket);
        }