public void MSOXCFOLD_S03_TC16_GetPropertyPidTagFolderFlags()
        {
            this.CheckWhetherSupportTransport();
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            this.GenericFolderInitialization();

            #region Step 1. Call RopCreateFolder to create [MSOXCFOLDSubfolder1] under the root folder.
            uint subfolderHandle1 = 0;
            ulong subfolderId1 = 0;
            this.CreateFolder(this.RootFolderHandle, Constants.Subfolder1, ref subfolderId1, ref subfolderHandle1);
            #endregion

            #region Step 2. Creates a none-FAI message in [MSOXCFOLDSubfolder1].
            ulong messageId = 0;
            uint messageHandle = 0;
            this.CreateSaveMessage(subfolderHandle1, subfolderId1, ref messageId, ref messageHandle);
            #endregion

            #region Step 3. Create a FAI message and saves it in [MSOXCFOLDSubfolder1].
            uint messageHandle2 = 0;
            ulong messageId2 = 0;
            this.CreateSaveMessage(subfolderHandle1, subfolderId1, 0x01, ref messageId2, ref messageHandle2);
            #endregion

            #region Step 4. The client calls RopCreateFolder to create the search folder [MSOXCFOLDSearchFolder1] under the root folder.
            RopCreateFolderRequest createFolderRequest = new RopCreateFolderRequest
            {
                RopId = (byte)RopId.RopCreateFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                FolderType = (byte)FolderType.Searchfolder,
                UseUnicodeStrings = 0x0,
                OpenExisting = 0x00,
                Reserved = 0x0,
                DisplayName = Encoding.ASCII.GetBytes(Constants.SearchFolder),
                Comment = Encoding.ASCII.GetBytes(Constants.SearchFolder)
            };
            RopCreateFolderResponse createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.RootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully!");
            uint searchFolderHandle = this.responseHandles[0][createFolderResponse.OutputHandleIndex];
            #endregion            

            #region Step 5. The client calls RopSetSearchCriteria to establish search criteria for [MSOXCFOLDSearchFolder1].
            RopSetSearchCriteriaRequest setSearchCriteriaRequest = new RopSetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopSetSearchCriteria,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex
            };
            PropertyTag propertyTag = new PropertyTag
            {
                PropertyId = (ushort)MessagePropertyId.PidTagMessageClass,
                PropertyType = (ushort)PropertyType.PtypString
            };
            ExistRestriction existRestriction = new ExistRestriction
            {
                PropTag = propertyTag
            };
            setSearchCriteriaRequest.RestrictionDataSize = (ushort)existRestriction.Size();
            setSearchCriteriaRequest.RestrictionData = existRestriction.Serialize();
            setSearchCriteriaRequest.FolderIds = new ulong[] { subfolderId1 };
            setSearchCriteriaRequest.FolderIdCount = (ushort)setSearchCriteriaRequest.FolderIds.Length;
            setSearchCriteriaRequest.SearchFlags = (uint)SetSearchFlags.NonContentIndexedSearch | (uint)SetSearchFlags.RestartSearch;
            RopSetSearchCriteriaResponse setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, searchFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, setSearchCriteriaResponse.ReturnValue, "RopSearchCriteria ROP operation performs successfully!");
            #endregion

            #region Step 6. The client calls RopGetContentsTable to retrieve the contents table for the search folder [MSOXCFOLDSearchFolder1].
            RopGetContentsTableRequest getContentsTableRequest = new RopGetContentsTableRequest();
            RopGetContentsTableResponse getContentsTableResponse;
            getContentsTableRequest.RopId = (byte)RopId.RopGetContentsTable;
            getContentsTableRequest.LogonId = Constants.CommonLogonId;
            getContentsTableRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            getContentsTableRequest.OutputHandleIndex = Constants.CommonOutputHandleIndex;
            getContentsTableRequest.TableFlags = (byte)FolderTableFlags.None;

            int count = 0;
            do
            {
                getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, searchFolderHandle, ref this.responseHandles);
                Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");
                if (getContentsTableResponse.RowCount != 1)
                {
                    Thread.Sleep(this.WaitTime);
                }
                else
                {
                    break;
                }

                count++;
            }
            while (count < this.RetryCount);
            #endregion

            #region Step 7. The client creates rules on [MSOXCFOLDSubfolder1] folder.
            RuleData[] sampleRuleDataArray;
            object ropResponse = null;
            sampleRuleDataArray = this.CreateSampleRuleDataArrayForAdd();

            RopModifyRulesRequest modifyRulesRequest = new RopModifyRulesRequest()
            {
                RopId = (byte)RopId.RopModifyRules,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                ModifyRulesFlags = 0x00,
                RulesCount = (ushort)sampleRuleDataArray.Length,
                RulesData = sampleRuleDataArray,
            };

            modifyRulesRequest.RopId = (byte)RopId.RopModifyRules;
            modifyRulesRequest.LogonId = Constants.CommonLogonId;
            modifyRulesRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            sampleRuleDataArray = this.CreateSampleRuleDataArrayForAdd();
            modifyRulesRequest.ModifyRulesFlags = 0x00;
            modifyRulesRequest.RulesCount = (ushort)sampleRuleDataArray.Length;
            modifyRulesRequest.RulesData = sampleRuleDataArray;
            this.Adapter.DoRopCall(modifyRulesRequest, subfolderHandle1, ref ropResponse, ref this.responseHandles);
            RopModifyRulesResponse modifyRulesResponse = (RopModifyRulesResponse)ropResponse;
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, modifyRulesResponse.ReturnValue, "RopModifyRules ROP operation performs successfully!");           
            #endregion

            #region Step 8. The client calls RopOpenFolder to open [MSOXCFOLDSubfolder1] folder.

            RopOpenFolderRequest openFolderRequest = new RopOpenFolderRequest
            {
                RopId = (byte)RopId.RopOpenFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                FolderId = subfolderId1,
                OpenModeFlags = (byte)FolderOpenModeFlags.None
            };
            RopOpenFolderResponse openFolderResponse = this.Adapter.OpenFolder(openFolderRequest, subfolderHandle1, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, openFolderResponse.ReturnValue, "RopOpenFolder ROP operation performs successfully!");
            #endregion
            
            #region Step 9. The client gets the PidTagFolderFlags propertie from [MSOXCFOLDSubfolder1].
            PropertyTag[] propertyTagArray = new PropertyTag[1];
            propertyTag = new PropertyTag
            {
                PropertyId = (ushort)FolderPropertyId.PidTagFolderFlags,
                PropertyType = (ushort)PropertyType.PtypInteger32
            };
            propertyTagArray[0] = propertyTag;
                        
            RopGetPropertiesSpecificRequest getPropertiesSpecificRequest = new RopGetPropertiesSpecificRequest();
            RopGetPropertiesSpecificResponse getPropertiesSpecificResponse;
            getPropertiesSpecificRequest.RopId = (byte)RopId.RopGetPropertiesSpecific;
            getPropertiesSpecificRequest.LogonId = Constants.CommonLogonId;
            getPropertiesSpecificRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            getPropertiesSpecificRequest.PropertySizeLimit = 0xFFFF;
            getPropertiesSpecificRequest.PropertyTagCount = (ushort)propertyTagArray.Length;
            getPropertiesSpecificRequest.PropertyTags = propertyTagArray;

            getPropertiesSpecificResponse = this.Adapter.GetFolderObjectSpecificProperties(getPropertiesSpecificRequest, subfolderHandle1, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, getPropertiesSpecificResponse.ReturnValue, "RopGetPropertiesSpecific ROP operation performs successfully!");
            uint pidTagFolderFlags = BitConverter.ToUInt32(getPropertiesSpecificResponse.RowData.PropertyValues[0].Value, 0);

            #region Verify MS-OXCFOLD_R1035110, MS-OXCFOLD_R1035111, MS-OXCFOLD_R1035103 and MS-OXCFOLD_R1035107
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, @"Verify MS-OXCFOLD_R1035110: [In PidTagFolderFlags Property] The PidTagFolderId property ([MS-OXPROPS] section 2.692) contains a computed value that specifies the type or state of a folder.");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1035110
            Site.CaptureRequirement(
                1035110,
                @"[In PidTagFolderFlags Property] The PidTagFolderId property ([MS-OXPROPS] section 2.692) contains a computed value that specifies the type or state of a folder.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, @"Verify MS-OXCFOLD_R1035111: [In PidTagFolderFlags Property] The value is a bitwise OR of zero or more values [1: IPM, 2: SEARCH, 4: NORMAL, 8: RULES] from the following table.");

            bool isR1035111Verified = false;
            if (((pidTagFolderFlags & 1) == 1) || ((pidTagFolderFlags & 2) == 2) || ((pidTagFolderFlags & 4) == 4) || ((pidTagFolderFlags & 8) == 8))
            {
                isR1035111Verified = true;
            }

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1035111
            Site.CaptureRequirementIfIsTrue(
                isR1035111Verified,
                1035111,
                @"[In PidTagFolderFlags Property] The value is a bitwise OR of zero or more values [1: IPM, 2: SEARCH, 4: NORMAL, 8: RULES] from the following table.");
            

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, @"Verify MS-OXCFOLD_R1035103: [In PidTagFolderFlags Property] [The folder flag named ""IPM"" specified] the folder belongs to the IPM subtree portion of the mailbox.");

            bool isR1035103Verified = false;
            if ((pidTagFolderFlags & 1) == 1)
            {
                isR1035103Verified = true;
            }

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1035103
            Site.CaptureRequirementIfIsTrue(
                isR1035103Verified,
                1035103,
                @"[In PidTagFolderFlags Property] [The folder flag named ""IPM"" specified] the folder belongs to the IPM subtree portion of the mailbox.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, @"Verify MS-OXCFOLD_R1035107: [In PidTagFolderFlags Property] [The folder flag named ""NORMAL"" specified] the folder is a generic folder that contains messages and other folders.");

            bool isR1035107Verified = false;
            if ((pidTagFolderFlags & 4) == 4)
            {
                isR1035107Verified = true;
            }

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1035107
            Site.CaptureRequirementIfIsTrue(
                isR1035107Verified,
                1035107,
                @"[In PidTagFolderFlags Property] [The folder flag named ""NORMAL"" specified] the folder is a generic folder that contains messages and other folders.");
            #endregion
            #endregion
        }
        public void MSOXCFOLD_S03_TC14_ContentIndexedSearchVerification()
        {
            this.CheckWhetherSupportTransport();
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            this.GenericFolderInitialization();

            #region Step 1. The client calls RopCreateFolder to create the general folder [MSOXCFOLDSubfolder1] under the root folder.

            RopCreateFolderRequest createFolderRequest = new RopCreateFolderRequest
            {
                RopId = (byte)RopId.RopCreateFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                FolderType = (byte)FolderType.Genericfolder,
                UseUnicodeStrings = 0x0,
                OpenExisting = 0x00,
                Reserved = 0x0,
                DisplayName = Encoding.ASCII.GetBytes(Constants.Subfolder1),
                Comment = Encoding.ASCII.GetBytes(Constants.Subfolder1)
            };
            RopCreateFolderResponse createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.RootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully!");
            uint subfolderHandle1 = this.responseHandles[0][createFolderResponse.OutputHandleIndex];
            ulong subfolderId1 = createFolderResponse.FolderId;

            #endregion

            #region Step 2. The client creates a non-FAI message under the general folder [MSOXCFOLDSubfolder1].

            uint messageNonFAIHandle1 = 0;
            ulong messageNonFAIId1 = 0;
            this.CreateSaveMessage(subfolderHandle1, subfolderId1, ref messageNonFAIId1, ref messageNonFAIHandle1);

            #endregion

            #region Step 3. The client calls RopCreateFolder to create the general folder [MSOXCFOLDSubfolder2] under the general folder [MSOXCFOLDSubfolder1].

            createFolderRequest.FolderType = (byte)FolderType.Genericfolder;
            createFolderRequest.DisplayName = Encoding.ASCII.GetBytes(Constants.Subfolder2);
            createFolderRequest.Comment = Encoding.ASCII.GetBytes(Constants.Subfolder2);
            createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, subfolderHandle1, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully!");
            uint subfolderHandle2 = this.responseHandles[0][createFolderResponse.OutputHandleIndex];
            ulong subfolderId2 = createFolderResponse.FolderId;

            #endregion

            #region Step 4. The client creates a non-FAI message under the general folder [MSOXCFOLDSubfolder2].

            uint messageNonFAIHandle2 = 0;
            ulong messageNonFAIId2 = 0;
            this.CreateSaveMessage(subfolderHandle2, subfolderId2, ref messageNonFAIId2, ref messageNonFAIHandle2);

            #endregion

            #region Step 5. The client calls RopCreateFolder to create the search folder [MSOXCFOLDSearchFolder1] under the root folder.

            createFolderRequest.FolderType = (byte)FolderType.Searchfolder;
            createFolderRequest.DisplayName = Encoding.ASCII.GetBytes(Constants.SearchFolder);
            createFolderRequest.Comment = Encoding.ASCII.GetBytes(Constants.SearchFolder);
            createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.RootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully!");
            uint searchFolderHandle1 = this.responseHandles[0][createFolderResponse.OutputHandleIndex];

            #endregion

            #region Step 6. The client calls RopSetSearchCriteria to establish search criteria for [MSOXCFOLDSearchFolder1].

            RopSetSearchCriteriaRequest setSearchCriteriaRequest = new RopSetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopSetSearchCriteria,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex
            };
            PropertyTag propertyTag = new PropertyTag
            {
                PropertyId = (ushort)MessagePropertyId.PidTagMessageClass,
                PropertyType = (ushort)PropertyType.PtypString
            };
            ExistRestriction existRestriction = new ExistRestriction
            {
                PropTag = propertyTag
            };
            setSearchCriteriaRequest.RestrictionDataSize = (ushort)existRestriction.Size();
            setSearchCriteriaRequest.RestrictionData = existRestriction.Serialize();
            setSearchCriteriaRequest.FolderIds = new ulong[] { subfolderId1 };
            setSearchCriteriaRequest.FolderIdCount = (ushort)setSearchCriteriaRequest.FolderIds.Length;
            setSearchCriteriaRequest.SearchFlags = (uint)SetSearchFlags.ContentIndexedSearch | (uint)SetSearchFlags.RestartSearch | (uint)SetSearchFlags.ForGroundSearch | (uint)SetSearchFlags.RecursiveSearch;
            RopSetSearchCriteriaResponse setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, searchFolderHandle1, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, setSearchCriteriaResponse.ReturnValue, "RopSearchCriteria ROP operation performs successfully!");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R782");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R782
            Site.CaptureRequirementIfAreEqual<uint>(
                Constants.SuccessCode,
                setSearchCriteriaResponse.ReturnValue,
                782,
                @"[In RopSetSearchCriteria ROP Request Buffer] SearchFlags (4 bytes): CONTENT_INDEXED_SEARCH (0x00010000) means that the search uses a content-indexed search.");

            #endregion

            #region Step 7. The client calls RopGetSearchCriteria to obtain the search criteria and the status of the search folder [MSOXCFOLDSearchFolder1].

            RopGetSearchCriteriaRequest getSearchCriteriaRequest = new RopGetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopGetSearchCriteria,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                UseUnicode = 0x00,
                IncludeRestriction = 0x01,
                IncludeFolders = 0x01
            };
            RopGetSearchCriteriaResponse getSearchCriteriaResponse = this.Adapter.GetSearchCriteria(getSearchCriteriaRequest, searchFolderHandle1, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getSearchCriteriaResponse.ReturnValue, "RopGetSearchCriteria ROP operation performs successfully!");
            ulong priviewFolderId = getSearchCriteriaResponse.FolderIds[0];

            #endregion

            #region Step 8. The client calls RopGetContentsTable to retrieve the contents table for the search folder [MSOXCFOLDSearchFolder1].

            RopGetContentsTableRequest getContentsTableRequest = new RopGetContentsTableRequest();
            RopGetContentsTableResponse getContentsTableResponse;
            getContentsTableRequest.RopId = (byte)RopId.RopGetContentsTable;
            getContentsTableRequest.LogonId = Constants.CommonLogonId;
            getContentsTableRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            getContentsTableRequest.OutputHandleIndex = Constants.CommonOutputHandleIndex;
            getContentsTableRequest.TableFlags = (byte)FolderTableFlags.None;

            int count = 0;
            do
            {
                getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, searchFolderHandle1, ref this.responseHandles);
                Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");
                if (getContentsTableResponse.RowCount != 2)
                {
                    Thread.Sleep(this.WaitTime);
                }
                else
                {
                    break;
                }

                count++;
            }
            while (count < this.RetryCount);

            #region Verify the requirements: MS-OXCFOLD_R515, MS-OXCFOLD_R770, and MS-OXCFOLD_R789.

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R515");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R515
            // There has 2 messages matched the search criteria, so the RowCount should be 2.
            Site.CaptureRequirementIfAreEqual<uint>(
                2,
                getContentsTableResponse.RowCount,
                515,
                @"[In Processing a RopSetSearchCriteria ROP Request] The server fills the search folder according to the search criteria and search scope that are specified in the RopSetSearchCriteria ROP request.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R770");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R770
            Site.CaptureRequirementIfAreEqual<uint>(
                2,
                getContentsTableResponse.RowCount,
                770,
                @"[In RopSetSearchCriteria ROP Request Buffer]SearchFlags (4 bytes): RECURSIVE_SEARCH (0x00000004) means that the search includes the search folder containers and all of their child folders.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R789");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R789
            // There has 2 messages matched search criteria, so the RowCount should be 2.
            Site.CaptureRequirementIfAreEqual<uint>(
                2,
                getContentsTableResponse.RowCount,
                789,
                @"[In RopGetSearchCriteria ROP Response Buffer] SearchFlags (4 bytes): If this bit [SEARCH_RECURSIVE (0x00000004)] is set, the specified search folder containers and all their child search folder containers are searched for matching entries.");

            #endregion

            #endregion

            #region Step 9. The client creates a non-FAI message under the general folder [MSOXCFOLDSubfolder1].

            uint messageNonFAIHandle3 = 0;
            ulong messageNonFAIId3 = 0;
            this.CreateSaveMessage(subfolderHandle1, subfolderId1, ref messageNonFAIId3, ref messageNonFAIHandle3);

            #endregion

            #region Step 10. The client calls RopSetSearchCriteria without setting the SearchFlags field to establish search criteria for [MSOXCFOLDSearchFolder1].

            setSearchCriteriaRequest.FolderIdCount = 0;
            setSearchCriteriaRequest.FolderIds = null;
            setSearchCriteriaRequest.SearchFlags = (uint)SetSearchFlags.None;
            setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, searchFolderHandle1, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, setSearchCriteriaResponse.ReturnValue, "RopSearchCriteria ROP operation performs successfully!");

            #endregion

            #region Step 11. The client calls RopGetSearchCriteria to obtain the search criteria and the status of the search folder [MSOXCFOLDSearchFolder1].

            getSearchCriteriaResponse = this.Adapter.GetSearchCriteria(getSearchCriteriaRequest, searchFolderHandle1, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getSearchCriteriaResponse.ReturnValue, "RopGetSearchCriteria ROP operation performs successfully!");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R109");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R109
            Site.CaptureRequirementIfAreEqual<ulong>(
                priviewFolderId,
                getSearchCriteriaResponse.FolderIds[0],
                109,
                @"[In RopSetSearchCriteria ROP Request Buffer] FolderIdCount (2 bytes): If the FolderIdCount field is set to zero, the folders that were used in the most recent search are used again.");
            #endregion

            #region Step 12. The client calls RopCreateFolder to create the search folder [MSOXCFOLDSearchFolder2] under the root folder.

            createFolderRequest.FolderType = (byte)FolderType.Searchfolder;
            createFolderRequest.DisplayName = Encoding.ASCII.GetBytes(Constants.SearchFolder2);
            createFolderRequest.Comment = Encoding.ASCII.GetBytes(Constants.SearchFolder2);
            createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.RootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully!");
            uint searchFolderHandle2 = this.responseHandles[0][createFolderResponse.OutputHandleIndex];

            #endregion

            #region Step 13. The client calls RopSetSearchCriteria to establish search criteria for [MSOXCFOLDSearchFolder2].

            setSearchCriteriaRequest = new RopSetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopSetSearchCriteria,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex
            };
            propertyTag = new PropertyTag
            {
                PropertyId = (ushort)MessagePropertyId.PidTagMessageClass,
                PropertyType = (ushort)PropertyType.PtypString
            };
            existRestriction = new ExistRestriction
            {
                PropTag = propertyTag
            };
            setSearchCriteriaRequest.RestrictionDataSize = (ushort)existRestriction.Size();
            setSearchCriteriaRequest.RestrictionData = existRestriction.Serialize();
            setSearchCriteriaRequest.FolderIds = new ulong[] { subfolderId1 };
            setSearchCriteriaRequest.FolderIdCount = (ushort)setSearchCriteriaRequest.FolderIds.Length;
            setSearchCriteriaRequest.SearchFlags = (uint)SetSearchFlags.ContentIndexedSearch | (uint)SetSearchFlags.RestartSearch;
            setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, searchFolderHandle2, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, setSearchCriteriaResponse.ReturnValue, "RopSearchCriteria ROP operation performs successfully!");

            #endregion

            #region Step 14. The client calls RopGetSearchCriteria to obtain the search criteria and the status of the search folder [MSOXCFOLDSearchFolder2].

            getSearchCriteriaResponse = this.Adapter.GetSearchCriteria(getSearchCriteriaRequest, searchFolderHandle2, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getSearchCriteriaResponse.ReturnValue, "RopGetSearchCriteria ROP operation performs successfully!");

            #endregion

            #region Step 15. The client calls RopGetContentsTable to retrieve the contents table for the search folder [MSOXCFOLDSearchFolder2].
            count = 0;
            do
            {
                getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, searchFolderHandle2, ref this.responseHandles);
                Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");
                if (getContentsTableResponse.RowCount != 2)
                {
                    Thread.Sleep(this.WaitTime);
                }
                else
                {
                    break;
                }

                count++;
            }
            while (count < this.RetryCount);

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R960");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R960
            // There has 2 messages matched the search criteria, so the RowCount should be 2.
            Site.CaptureRequirementIfAreEqual<uint>(
                2,
                getContentsTableResponse.RowCount,
                960,
                @"[In RopGetSearchCriteria ROP Response Buffer] If this bit [SEARCH_RECURSIVE] is not set, only the search folder containers that are specified in the last RopSetSearchCriteria ROP request (section 2.2.1.4.1) are being searched.");

            #endregion
        }
        public void MSOXCFOLD_S03_TC15_NonContentIndexedSearchVerification()
        {
            this.CheckWhetherSupportTransport();
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            this.GenericFolderInitialization();

            #region Step 1. The client calls RopCreateFolder to create the general folder [MSOXCFOLDSubfolder1] under the root folder.

            RopCreateFolderRequest createFolderRequest = new RopCreateFolderRequest
            {
                RopId = (byte)RopId.RopCreateFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                FolderType = 0x01,
                UseUnicodeStrings = 0x0,
                OpenExisting = 0x00,
                Reserved = 0x0,
                DisplayName = Encoding.ASCII.GetBytes(Constants.Subfolder1),
                Comment = Encoding.ASCII.GetBytes(Constants.Subfolder1)
            };
            RopCreateFolderResponse createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.RootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully!");
            uint subfolderHandle1 = this.responseHandles[0][createFolderResponse.OutputHandleIndex];
            ulong subfolderId1 = createFolderResponse.FolderId;

            #endregion

            #region Step 2. The client creates a non-FAI message under the general folder [MSOXCFOLDSubfolder1].

            uint messageNonFAIHandle1 = 0;
            ulong messageNonFAIId1 = 0;
            this.CreateSaveMessage(subfolderHandle1, subfolderId1, ref messageNonFAIId1, ref messageNonFAIHandle1);

            #endregion

            #region Step 3. The client calls RopCreateFolder to create the search folder [MSOXCFOLDSearchFolder1] under the root folder.

            createFolderRequest.FolderType = (byte)FolderType.Searchfolder;
            createFolderRequest.DisplayName = Encoding.ASCII.GetBytes(Constants.SearchFolder);
            createFolderRequest.Comment = Encoding.ASCII.GetBytes(Constants.SearchFolder);
            createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.RootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully!");
            uint searchFolderHandle = this.responseHandles[0][createFolderResponse.OutputHandleIndex];

            #endregion

            #region Step 4. The client calls RopSetSearchCriteria to establish search criteria for [MSOXCFOLDSearchFolder1].

            RopSetSearchCriteriaRequest setSearchCriteriaRequest = new RopSetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopSetSearchCriteria,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex
            };
            PropertyTag propertyTag = new PropertyTag
            {
                PropertyId = (ushort)MessagePropertyId.PidTagMessageClass,
                PropertyType = (ushort)PropertyType.PtypString
            };
            ExistRestriction existRestriction = new ExistRestriction
            {
                PropTag = propertyTag
            };
            setSearchCriteriaRequest.RestrictionDataSize = (ushort)existRestriction.Size();
            setSearchCriteriaRequest.RestrictionData = existRestriction.Serialize();
            setSearchCriteriaRequest.FolderIds = new ulong[] { subfolderId1 };
            setSearchCriteriaRequest.FolderIdCount = (ushort)setSearchCriteriaRequest.FolderIds.Length;
            setSearchCriteriaRequest.SearchFlags = (uint)SetSearchFlags.NonContentIndexedSearch | (uint)SetSearchFlags.RestartSearch;
            RopSetSearchCriteriaResponse setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, searchFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, setSearchCriteriaResponse.ReturnValue, "RopSearchCriteria ROP operation performs successfully!");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R783");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R783
            Site.CaptureRequirementIfAreEqual<uint>(
                Constants.SuccessCode,
                setSearchCriteriaResponse.ReturnValue,
                783,
                @"[In RopSetSearchCriteria ROP Request Buffer] SearchFlags (4 bytes): NON_CONTENT_INDEXED_SEARCH (0x00020000) means that the search does not use a content-indexed search.");
            #endregion

            #region Step 5. The client calls RopGetContentsTable to retrieve the contents table for the search folder [MSOXCFOLDSearchFolder1].

            RopGetContentsTableRequest getContentsTableRequest = new RopGetContentsTableRequest();
            RopGetContentsTableResponse getContentsTableResponse;
            getContentsTableRequest.RopId = (byte)RopId.RopGetContentsTable;
            getContentsTableRequest.LogonId = Constants.CommonLogonId;
            getContentsTableRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            getContentsTableRequest.OutputHandleIndex = Constants.CommonOutputHandleIndex;
            getContentsTableRequest.TableFlags = (byte)FolderTableFlags.None;

            int count = 0;
            do
            {
                getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, searchFolderHandle, ref this.responseHandles);
                Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");
                if (getContentsTableResponse.RowCount != 1)
                {
                    Thread.Sleep(this.WaitTime);
                }
                else
                {
                    break;
                }

                count++;
            }
            while (count < this.RetryCount);

            #endregion

            #region Step 6. The client calls RopSetSearchCriteria to stop establish search criteria for [MSOXCFOLDSearchFolder1].

            setSearchCriteriaRequest.SearchFlags = (uint)SetSearchFlags.StopSearch;
            setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, searchFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, setSearchCriteriaResponse.ReturnValue, "RopSearchCriteria ROP operation performs successfully!");

            #endregion

            #region Step 7. The client calls RopGetSearchCriteria to obtain the search criteria and the status of the search folder [MSOXCFOLDSearchFolder1].

            RopGetSearchCriteriaRequest getSearchCriteriaRequest = new RopGetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopGetSearchCriteria,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                UseUnicode = 0x00,
                IncludeRestriction = 0x01,
                IncludeFolders = 0x01
            };
            RopGetSearchCriteriaResponse getSearchCriteriaResponse = this.Adapter.GetSearchCriteria(getSearchCriteriaRequest, searchFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getSearchCriteriaResponse.ReturnValue, "RopGetSearchCriteria ROP operation performs successfully!");

            #region Verify the requirements: MS-OXCFOLD_R673, MS-OXCFOLD_R54301.

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R673");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R673
            Site.CaptureRequirementIfAreNotEqual<uint>(
                (uint)GetSearchFlags.Running,
                getSearchCriteriaResponse.SearchFlags & (uint)GetSearchFlags.Running,
                673,
                @"[In RopSetSearchCriteria ROP Request Buffer] SearchFlags (4 bytes):STOP_SEARCH (0x00000001) means that the search is aborted.");

            if (Common.IsRequirementEnabled(54301, this.Site))
            {
                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R54301");

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R54301
                Site.CaptureRequirementIfAreNotEqual<uint>(
                    (uint)GetSearchFlags.Running,
                    getSearchCriteriaResponse.SearchFlags & (uint)GetSearchFlags.Running,
                    54301,
                    @"[In Processing a RopSetSearchCriteria ROP Request] Implementation does stop the initial population of the search folder if the STOP_SEARCH bit is set in the SearchFlags field. (Exchange 2007 and above follow this behavior).");
            }

            #endregion

            #endregion

            #region Step 8. The client calls RopSetSearchCriteria to restart establish search criteria for [MSOXCFOLDSearchFolder1].

            setSearchCriteriaRequest.SearchFlags = (uint)SetSearchFlags.RestartSearch;
            setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, searchFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, setSearchCriteriaResponse.ReturnValue, "RopSearchCriteria ROP operation performs successfully!");

            #endregion

            #region Step 9. The client calls RopGetSearchCriteria to obtain the search criteria and the status of the search folder [MSOXCFOLDSearchFolder1].

            getSearchCriteriaResponse = this.Adapter.GetSearchCriteria(getSearchCriteriaRequest, searchFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getSearchCriteriaResponse.ReturnValue, "RopGetSearchCriteria ROP operation performs successfully!");
            Site.Assert.AreEqual<uint>((uint)GetSearchFlags.Running, getSearchCriteriaResponse.SearchFlags & (uint)GetSearchFlags.Running, "The SearchFlags field contains the 'SEARCH_RUNNING' bits.");

            #region Verify the requirements: MS-OXCFOLD_R546, MS-OXCFOLD_R768, and MS-OXCFOLD_R767.

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R767");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R767
            Site.CaptureRequirementIfAreEqual<uint>(
                (uint)GetSearchFlags.Running,
                getSearchCriteriaResponse.SearchFlags & (uint)GetSearchFlags.Running,
                767,
                @"[In RopSetSearchCriteria ROP Request Buffer] SearchFlags (4 bytes): RESTART_SEARCH (0x00000002) means that the search is initiated, if the search is restarted.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R768");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R768
            Site.CaptureRequirementIfAreEqual<uint>(
                (uint)GetSearchFlags.Running,
                getSearchCriteriaResponse.SearchFlags & (uint)GetSearchFlags.Running,
                768,
                @"[In RopSetSearchCriteria ROP Request Buffer] SearchFlags (4 bytes): RESTART_SEARCH (0x00000002) means that the search is initiated, if the search is inactive.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R546");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R546
            Site.CaptureRequirementIfAreEqual<uint>(
                (uint)GetSearchFlags.Running,
                getSearchCriteriaResponse.SearchFlags & (uint)GetSearchFlags.Running,
                546,
                @"[In Processing a RopSetSearchCriteria ROP Request] If the RESTART_SEARCH bit is set in the SearchFlags field, the server restarts the population of the search folder.");

            #endregion

            #endregion
        }
        public void MSOXCFOLD_S03_TC06_RopGetContentsTableSuccess()
        {
            this.CheckWhetherSupportTransport();
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            this.GenericFolderInitialization();

            #region Step 1. The client creates a FAI message in the root folder.

            uint messageFAIHandle = 0;
            ulong mesageFAIId = 0;
            this.CreateSaveMessage(this.RootFolderHandle, this.RootFolderId, 0x01, ref mesageFAIId, ref messageFAIHandle);

            #endregion

            #region Step 2. The client creates two non-FAI message in the root folder.

            uint messageNonFAIHandle1 = 0;
            ulong mesageNonFAIId1 = 0;
            this.CreateSaveMessage(this.RootFolderHandle, this.RootFolderId, ref mesageNonFAIId1, ref messageNonFAIHandle1);

            uint messageNonFAIHandle2 = 0;
            ulong mesageNonFAIId2 = 0;
            this.CreateSaveMessage(this.RootFolderHandle, this.RootFolderId, ref mesageNonFAIId2, ref messageNonFAIHandle2);

            #endregion

            #region Step 3. The client calls RopGetContentsTable to retrieve the contents table for the root folder without 'Associated' flag.

            RopGetContentsTableRequest getContentsTableRequest = new RopGetContentsTableRequest
            {
                RopId = (byte)RopId.RopGetContentsTable,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                TableFlags = (byte)FolderTableFlags.None
            };
            RopGetContentsTableResponse getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, this.RootFolderHandle, ref this.responseHandles);

            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1167");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1167
            // Method GetContentsTable succeeds indicates that the server responds with a RopGetContentsTable ROP response buffer.
            Site.CaptureRequirement(
                1167,
                @"[In Processing a RopGetContentsTable ROP Request] The server responds with a RopGetContentsTable ROP response buffer.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1170");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1170
            // Method GetContentsTable succeeds indicates that the server returns a contents table on which table operations can be performed.
            Site.CaptureRequirement(
                1170,
                @"[In Processing a RopGetContentsTable ROP Request] The server returns a contents table on which table operations can be performed.");

            #region Verify the requirements: MS-OXCFOLD_R663, MS-OXCFOLD_R100502,MS-OXCFOLD_R665 and MS-OXCFOLD_R333.

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R100502");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R100502.
            Site.CaptureRequirementIfAreEqual<uint>(
                Constants.SuccessCode,
                getContentsTableResponse.ReturnValue,
                100502,
                @"[In RopGetContentsTable ROP] This ROP [RopGetContentsTable] applies to [both public folders and] private mailboxes.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R663");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R663
            // There has 2 non-FAI messages under the root folder, so the RowCount should be 2.
            Site.CaptureRequirementIfAreEqual<uint>(
                0x00000002,
                getContentsTableResponse.RowCount,
                663,
                @"[In RopGetContentsTable ROP Request Buffer] If this bit [Associated] is not set, the contents table lists only the non-FAI messages.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R333");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R333
            // There has 2 messages under the root folder, so the RowCount should be 2.
            Site.CaptureRequirementIfAreEqual<uint>(
                0x00000002,
                getContentsTableResponse.RowCount,
                333,
                @"[In RopGetContentsTable ROP Response Buffer] RowCount (4 bytes): An integer that specifies the number of rows in the contents table.");

            // Add debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R665");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R665
            // There has only 2 messages existed, so the RowCount should be 2.
            Site.CaptureRequirementIfAreEqual<uint>(
                0x00000002,
                getContentsTableResponse.RowCount,
                665,
                @"[In RopGetContentsTable ROP Request Buffer]If this bit [SoftDeletes] is not set, the contents table lists only the existing messages.");

            #endregion

            #endregion

            #region Step 4. The client calls RopGetContentsTable to retrieve the contents table for the root folder with 'Associated' flag.

            getContentsTableRequest.TableFlags = 0x02;
            getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, this.RootFolderHandle, ref this.responseHandles);
            uint tableHandle = this.responseHandles[0][getContentsTableResponse.OutputHandleIndex];
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R662");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R662
            // There has 1 FAI messages contained in the folder, so the RowCount should be 1.
            Site.CaptureRequirementIfAreEqual<uint>(
                0x00000001,
                getContentsTableResponse.RowCount,
                662,
                @"[In RopGetContentsTable ROP Request Buffer] If this bit [Associated] is set, the contents table lists only the FAI messages.");
            #endregion

            #region Step 5. The client calls RopGetContentsTable to retrieve the contents table for the root folder with 'ConversationMembers' flag.

            getContentsTableRequest.TableFlags = 0x80;
            getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, this.RootFolderHandle, ref this.responseHandles);

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R10251: the return value of the getContentsTableResponse is {0}", getContentsTableResponse.ReturnValue);

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R10251
            // The'ConversationMembers' flag is set in the getContentsTableRequest, so if the getContentsTableResponse returns success. R10251 can be verified. 
            Site.CaptureRequirementIfAreEqual<uint>(
                0,
                getContentsTableResponse.ReturnValue,
                10251,
                @"[In RopGetContentsTable ROP Request Buffer] This bit [ConversationMembers] is supported on the Root folder of a mailbox.");
            #endregion

            #region Step 6. Delete one non-FAI message created in step 2 in root folder.
            object ropResponse = null;
            ulong[] messageIds = new ulong[] { mesageNonFAIId1 };

            RopDeleteMessagesRequest deleteMessagesRequest = new RopDeleteMessagesRequest();
            RopDeleteMessagesResponse deleteMessagesResponse;
            deleteMessagesRequest.RopId = (byte)RopId.RopDeleteMessages;
            deleteMessagesRequest.LogonId = Constants.CommonLogonId;
            deleteMessagesRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            deleteMessagesRequest.WantAsynchronous = 0x00;

            // The server does not generate a non-read receipt for the deleted messages.
            deleteMessagesRequest.NotifyNonRead = 0x00;
            deleteMessagesRequest.MessageIdCount = (ushort)messageIds.Length;
            deleteMessagesRequest.MessageIds = messageIds;
            this.Adapter.DoRopCall(deleteMessagesRequest, this.RootFolderHandle, ref ropResponse, ref this.responseHandles);
            deleteMessagesResponse = (RopDeleteMessagesResponse)ropResponse;
            Site.Assert.AreEqual<uint>(
                0,
                deleteMessagesResponse.ReturnValue,
                "If ROP succeeds, the ReturnValue of its response is 0(success)");
            #endregion

            #region Step 7. The client calls RopGetContentsTable to retrieve the contents table for the root folder with 'Soft-delete' set.
            if (Common.IsRequirementEnabled(1017, this.Site))
            {
                getContentsTableRequest.TableFlags = 0x20;
                getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, this.RootFolderHandle, ref this.responseHandles);

                Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");

                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1017: the expected RowCount is {0}, and actually, the RowCount in the getContentsTableResponse is {1}.", 1, getContentsTableResponse.RowCount);

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1017
                // One non-FAI message has been soft-deleted in step 5, so the return count of the getContentsTableResponse should be 1.
                Site.CaptureRequirementIfAreEqual<uint>(
                    0x00000001,
                    getContentsTableResponse.RowCount,
                    1017,
                    @"[In RopGetContentsTable ROP Request Buffer] If this bit [SoftDeletes] is set, the contents table lists only the messages that are soft deleted.");
            }
            #endregion
          
            #region Step 8. Sets the properties PidTagMid visible on the content table.
            RopSetColumnsRequest setColumnsRequest;
            PropertyTag[] propertyTags = new PropertyTag[1];
            propertyTags[0].PropertyId = (ushort)MessagePropertyId.PidTagMid;
            propertyTags[0].PropertyType = (ushort)PropertyType.PtypInteger64;

            setColumnsRequest.RopId = 0x12;
            setColumnsRequest.LogonId = 0x00;
            setColumnsRequest.InputHandleIndex = 0x00;
            setColumnsRequest.PropertyTagCount = (ushort)propertyTags.Length;
            setColumnsRequest.PropertyTags = propertyTags;
            setColumnsRequest.SetColumnsFlags = 0x00; // Sync

            this.Adapter.DoRopCall(setColumnsRequest, tableHandle, ref ropResponse, ref this.responseHandles);
            #endregion

            #region Step 9. Gets the message ID of the message in content table.

            RopQueryRowsRequest queryRowsRequest;
            RopQueryRowsResponse queryRowsResponse;

            queryRowsRequest.RopId = 0x15;
            queryRowsRequest.LogonId = 0x00;
            queryRowsRequest.InputHandleIndex = 0x00;
            queryRowsRequest.QueryRowsFlags = 0x00;
            queryRowsRequest.ForwardRead = 0x01;
            queryRowsRequest.RowCount = 1;

            this.Adapter.DoRopCall(queryRowsRequest, tableHandle, ref ropResponse, ref this.responseHandles);
            queryRowsResponse = (RopQueryRowsResponse)ropResponse;
            ulong messageID = BitConverter.ToUInt64(queryRowsResponse.RowData.PropertyRows[0].PropertyValues[0].Value, 0);

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R661");
        
            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R661
            this.Site.CaptureRequirementIfAreEqual<ulong>(
                mesageFAIId,
                messageID,
                661,
                @"[In Processing a RopGetContentsTable ROP Request] The Table object that is returned provides information about messages that are directly under the Folder object on which this ROP [RopGetContentsTable ROP] is executed.");
            #endregion
        }
        public void MSOXCFOLD_S03_TC10_RopGetContentsTableFailure()
        {
            this.CheckWhetherSupportTransport();
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            this.GenericFolderInitialization();

            #region Step 1. The client creates a FAI message in the root folder.

            uint messageFAIHandle = 0;
            ulong mesageFAIId = 0;
            this.CreateSaveMessage(this.RootFolderHandle, this.RootFolderId, 0x01, ref mesageFAIId, ref messageFAIHandle);

            #endregion

            #region Step 2. The client creates a non-FAI message in the root folder.

            uint messageNonFAIHandle = 0;
            ulong mesageNonFAIId = 0;
            this.CreateSaveMessage(this.RootFolderHandle, this.RootFolderId, ref mesageNonFAIId, ref messageNonFAIHandle);

            #endregion

            #region Step 3. The client calls RopGetContentsTable with a logon object handle rather than a folder handle.

            RopGetContentsTableRequest getContentsTableRequest = new RopGetContentsTableRequest
            {
                RopId = (byte)RopId.RopGetContentsTable,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                TableFlags = (byte)FolderTableFlags.None
            };

            // Use logon object handle in which case is purposed get test error code ecNotSupported [0x80040102].  
            RopGetContentsTableResponse getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, this.LogonHandle, ref this.responseHandles);

            Site.Assert.AreEqual<uint>(0x80040102, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation failed with ecNotSupported [0x80040102].");

            #region Verify the requirements: MS-OXCFOLD_R671, MS-OXCFOLD_R672.

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R671");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R671
            Site.CaptureRequirementIfAreEqual<uint>(
                0x80040102,
                getContentsTableResponse.ReturnValue,
                671,
                @"[In Processing a RopGetContentsTable ROP Request] The value of error code ecNotSupported is 0x80040102.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R672");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R672
            Site.CaptureRequirementIfAreEqual<uint>(
                0x80040102,
                getContentsTableResponse.ReturnValue,
                672,
                @"[In Processing a RopGetContentsTable ROP Request] When the error code is ecNotSupported, it indicates that the object that this ROP [RopGetContentsTable ROP] was called on is not a Folder object.");

            #endregion

            #endregion

            #region Step 4. The client calls RopGetContentsTable operation with invalid 'TableFlags'.

            // Set an invalid TableFlags in the RopGetContentsTable ROP operation request.
            getContentsTableRequest.TableFlags = 0x04;
            getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, this.RootFolderHandle, ref this.responseHandles);

            #region Verify the requirements: MS-OXCFOLD_R1178, MS-OXCFOLD_R330002, MS-OXCFOLD_R1179, and MS-OXCFOLD_R330001.

            if (Common.IsRequirementEnabled(330002, this.Site))
            {
                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R330002");

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R330002
                Site.CaptureRequirementIfAreEqual<uint>(
                    0x80070057,
                    getContentsTableResponse.ReturnValue,
                    330002,
                    @"[In Appendix A: Product Behavior] If the client sets an invalid bit in the TableFlags field, implementation fails the ROP [RopGetContentsTable]. (Microsoft Exchange Server 2010 and above follow this behavior.)");

                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1178");

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1178
                Site.CaptureRequirementIfAreEqual<uint>(
                    0x80070057,
                    getContentsTableResponse.ReturnValue,
                    1178,
                    @"[In Processing a RopGetContentsTable ROP Request] The value of error code ecInvalidParam is 0x80070057.");

                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1179");

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1179
                Site.CaptureRequirementIfAreEqual<uint>(
                    0x80070057,
                    getContentsTableResponse.ReturnValue,
                    1179,
                    @"[In Processing a RopGetContentsTable ROP Request] When the error code is ecInvalidParam, it indicates that an invalid value was specified in a field.");
            }

            if (Common.IsRequirementEnabled(330001, this.Site))
            {
                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R330001");

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R330001
                Site.CaptureRequirementIfAreEqual<uint>(
                    Constants.SuccessCode,
                    getContentsTableResponse.ReturnValue,
                    330001,
                    @"[In Appendix A: Product Behavior] If the client sets an invalid bit in the TableFlags field, implementation does not fail the ROP [RopGetContentsTable]. <22> Section 3.2.5.14:  Exchange 2007 ignores invalid bits instead of failing the ROP.");
            }

            #endregion

            #endregion
        }
        /// <summary>
        /// Retrieve the content table for a folder. 
        /// </summary>
        /// <param name="serverId">A 32-bit signed integer represent the Identity of server.</param>
        /// <param name="folderHandleIndex">The folder handle index</param>
        /// <param name="deleteFlags">The delete flag indicates whether checking delete.</param>
        /// <param name="rowCount">The row count.</param>
        /// <returns>Indicate the result of this ROP operation.</returns>
        public RopResult GetContentsTable(int serverId, int folderHandleIndex, DeleteFlags deleteFlags, out int rowCount)
        {
            RopResult result = RopResult.InvalidParameter;
            rowCount = -1;
            uint objHandle = this.handleContainer[folderHandleIndex];

            RopGetContentsTableRequest getContentsTableRequest = new RopGetContentsTableRequest();
            RopGetContentsTableResponse getContentsTableResponse = new RopGetContentsTableResponse();

            getContentsTableRequest.RopId = 0x05;
            getContentsTableRequest.LogonId = 0x00;
            getContentsTableRequest.InputHandleIndex = 0x00;
            getContentsTableRequest.OutputHandleIndex = 0x01;

            // If this bit is set, the contents table lists only the soft-deleted messages. 
            getContentsTableRequest.TableFlags = 0x20;

            getContentsTableResponse = (RopGetContentsTableResponse)this.Process(serverId, getContentsTableRequest, objHandle);
            result = (RopResult)getContentsTableResponse.ReturnValue;
            int expectedRowCount = (int)getContentsTableResponse.RowCount;

            // Add this condition to match the model logical for return result, it's better to compare.
            if (deleteFlags == DeleteFlags.SoftDeleteCheck && this.currentSoftDeleteRowCount + 1 == expectedRowCount)
            {
                rowCount = 1;
            }
            else if (deleteFlags == DeleteFlags.HardDeleteCheck && this.currentSoftDeleteRowCount == expectedRowCount)
            {
                rowCount = 0;
            }
            else if (deleteFlags == DeleteFlags.Initial)
            {
                rowCount = 0;
            }
            else if (deleteFlags == DeleteFlags.SoftDeleteCheck && this.isImportMessageMoveROP && this.currentSoftDeleteRowCount + 1 == expectedRowCount)
            {
                rowCount = 1;
            }

            this.currentSoftDeleteRowCount = expectedRowCount;
            return result;
        }
        public void MSOXCMSG_S01_TC01_RopCreateMessageAndRopSaveChangesMessage()
        {
            this.CheckMapiHttpIsSupported();
            this.ConnectToServer(ConnectionType.PrivateMailboxServer);

            #region Call RopLogon to log on a private mailbox.
            RopLogonResponse logonResponse = this.Logon(LogonType.Mailbox, out this.insideObjHandle);
            #endregion

            #region Call RopOpenFolder to open inbox folder
            uint openedFolderHandle = this.OpenSpecificFolder(logonResponse.FolderIds[4], this.insideObjHandle);
            #endregion

            #region Call RopGetContentsTable to get the contents table of inbox folder before create message.
            RopGetContentsTableRequest getContentsTableRequest = new RopGetContentsTableRequest()
            {
                RopId = (byte)RopId.RopGetContentsTable,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,
                OutputHandleIndex = CommonOutputHandleIndex,
                TableFlags = (byte)FolderTableFlags.None
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(getContentsTableRequest, openedFolderHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopGetContentsTableResponse getContentsTableResponse = (RopGetContentsTableResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, getContentsTableResponse.ReturnValue, "Call RopGetContentsTable should success.");
            uint rowCount = getContentsTableResponse.RowCount;
            #endregion

            #region Call RopCreateMessage to create new not FAI Message object.
            RopCreateMessageRequest createMessageRequest = new RopCreateMessageRequest()
            {
                RopId = (byte)RopId.RopCreateMessage,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,
                OutputHandleIndex = CommonOutputHandleIndex,
                CodePageId = 0x0FFF, // Code page of Logon object is used
                FolderId = logonResponse.FolderIds[4], // Create a message in INBOX which root is mailbox 
                AssociatedFlag = 0x00 // NOT an FAI message
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(createMessageRequest, this.insideObjHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopCreateMessageResponse createMessageResponse = (RopCreateMessageResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, createMessageResponse.ReturnValue, "Call RopCreateMessage should success.");
            uint targetMessageHandle = this.ResponseSOHs[0][createMessageResponse.OutputHandleIndex];

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R991, The HasMessageId field is {0}", createMessageResponse.HasMessageId);

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R991
            bool isVerifiedR991 = createMessageResponse.HasMessageId == 0x00 && createMessageResponse.MessageId == null;

            this.Site.CaptureRequirementIfIsTrue(
                isVerifiedR991,
                991,
                @"[In RopCreateMessage ROP Response Buffer] [HasMessageId] The value 0x00 means this is the last byte in the buffer.");
            #endregion

            #region Call RopGetContentsTable to get the contents table of inbox folder before save message.
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(getContentsTableRequest, openedFolderHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            getContentsTableResponse = (RopGetContentsTableResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, createMessageResponse.ReturnValue, "Call RopGetContents should success.");

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R339");

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R339
            this.Site.CaptureRequirementIfAreEqual<uint>(
                rowCount,
                getContentsTableResponse.RowCount,
                339,
                @"[In Receiving a RopCreateMessage ROP Request] When processing the RopCreateMessage ROP ([MS-OXCROPS] section 2.2.6.2), the server MUST NOT commit the new Message object until it [server] receives a RopSaveChangesMessage ROP request ([MS-OXCROPS] section 2.2.6.3).");
            #endregion

            #region Call RopSaveChangesMessage to commit the Message object created.
            RopSaveChangesMessageResponse saveChangesMessageResponse = this.SaveMessage(targetMessageHandle, (byte)SaveFlags.ForceSave);
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, saveChangesMessageResponse.ReturnValue, TestSuiteBase.ROPSucceedMsg);

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R728");

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R728
            this.Site.CaptureRequirementIfAreEqual<int>(
                8,
                BitConverter.GetBytes(saveChangesMessageResponse.MessageId).Length,
                728,
                @"[In RopSaveChangesMessage ROP Response Buffer] Message Id: 8 bytes containing the MID ([MS-OXCDATA] section 2.2.1.2) for the saved Message object.");

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R372, the MID in RopSaveChangesMessage Response is {0}.", saveChangesMessageResponse.MessageId);

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R372
            // Because the R728 verify the RopSaveChangesMessage ROP response contains a MID and it's length is 8 bytes.
            // So R372 will be verified directly.
            this.Site.CaptureRequirement(
                372,
                @"[In Receiving a RopSaveChangesMessage ROP Request] The response contains the MID ([MS-OXCDATA] section 2.2.1.2) of the committed message.");

            #endregion

            #region Call RopGetContentsTable to get the contents table of inbox folder after save message.
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(getContentsTableRequest, openedFolderHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            getContentsTableResponse = (RopGetContentsTableResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, createMessageResponse.ReturnValue, "Call RopGetContents should success.");
            uint contentTableHandle = this.ResponseSOHs[0][getContentsTableResponse.OutputHandleIndex];

            #region Verify MS-OXCMSG_R700, MS-OXCMSG_R687
            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R687");

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R687
            // If the e-mail in the Inbox one more than before Call RopSaveChangeMessage, then R687 will be verified.
            this.Site.CaptureRequirementIfAreEqual<uint>(
                rowCount + 1,
                getContentsTableResponse.RowCount,
                687,
                @"[In RopCreateMessage ROP] The RopCreateMessage ROP ([MS-OXCROPS] section 2.2.6.2) is used to create a new Message object.");

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R700");

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R700
            this.Site.CaptureRequirementIfAreEqual<uint>(
                rowCount + 1,
                getContentsTableResponse.RowCount,
                700,
                @"[In RopSaveChangesMessage ROP] The RopSaveChangesMessage ROP ([MS-OXCROPS] section 2.2.6.3) commits the changes made to the Message object.");
            #endregion
            #endregion

            #region Call RopSetColumns to sets the properties visible on contents table.
            PropertyTag[] propertyTags = new PropertyTag[1];

            // The PropertyTag of PidTagMid.
            propertyTags[0] = new PropertyTag(0x674A, (ushort)PropertyType.PtypInteger64);
            RopSetColumnsRequest setColumnsRequest = new RopSetColumnsRequest()
            {
                RopId = (byte)RopId.RopSetColumns,
                LogonId = CommonLogonId,

                // Set InputHandleIndex to 0x00, which specifies the location in the Server object handle table where the handle
                // for the input Server object is stored, as specified in [MS-OXCROPS].
                InputHandleIndex = CommonInputHandleIndex,
                SetColumnsFlags = (byte)AsynchronousFlags.None,
                PropertyTagCount = (ushort)propertyTags.Length,
                PropertyTags = propertyTags
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(setColumnsRequest, contentTableHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopSetColumnsResponse setColumnsResponse = (RopSetColumnsResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, setColumnsResponse.ReturnValue, "Call RopSetColumns should success.");
            #endregion

            #region Call RopQueryRows to retrieve rows from contents table.
            RopQueryRowsRequest queryRowsRequest = new RopQueryRowsRequest()
            {
                RopId = (byte)RopId.RopQueryRows,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,
                QueryRowsFlags = (byte)QueryRowsFlags.Advance,
                ForwardRead = 0x01,
                RowCount = 0x1000
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(queryRowsRequest, contentTableHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopQueryRowsResponse queryRowsResponse = (RopQueryRowsResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, setColumnsResponse.ReturnValue, "Call RopQueryRowsRequest should success.");

            ulong messageID = 0;
            foreach (PropertyRow row in queryRowsResponse.RowData.PropertyRows)
            {
                ulong actualMID = BitConverter.ToUInt64(row.PropertyValues[0].Value, 0);

                if (actualMID == saveChangesMessageResponse.MessageId)
                {
                    messageID = actualMID;
                    break;
                }
            }

            Site.Assert.AreNotEqual<ulong>(messageID, 0, "The Message ID should in the contents table of the specified Folder object");
            #endregion

            #region Call RopOpenMessage to open the specific Message object.
            RopOpenMessageRequest openMessageRequest = new RopOpenMessageRequest()
            {
                RopId = (byte)RopId.RopOpenMessage,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,
                OutputHandleIndex = CommonOutputHandleIndex,
                CodePageId = 0x0FFF, // Code page of Logon object is used
                FolderId = logonResponse.FolderIds[4],
                OpenModeFlags = 0x00,
                MessageId = messageID
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(openMessageRequest, this.insideObjHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);

            RopOpenMessageResponse openMessageResponse = (RopOpenMessageResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, setColumnsResponse.ReturnValue, "Call RopOpenMessage should success.");

            #region Verify MS-OXCMSG_R647, MS-OXCMSG_R372
            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R647");

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R647
            this.Site.CaptureRequirementIfAreEqual<uint>(
                TestSuiteBase.Success,
                openMessageResponse.ReturnValue,
                647,
                @"[In RopOpenMessage ROP] The RopOpenMessage ROP ([MS-OXCROPS] section 2.2.6.1) provides access to an existing Message object, which is identified by the message ID (MID), whose structure is specified in [MS-OXCDATA] section 2.2.1.2.<7>");

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R251");

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R251
            this.Site.CaptureRequirementIfAreEqual<uint>(
                TestSuiteBase.Success,
                openMessageResponse.ReturnValue,
                251,
                @"[In Sending a RopOpenMessage ROP Request] The MID is accessible from the contents table of the Folder object that contains the Message object by including the PidTagMid property ([MS-OXCFXICS] section 2.2.1.2.1) in a RopSetColumns ROP request ([MS-OXCROPS] section 2.2.5.1), as specified in [MS-OXCTABL] section 2.2.2.2.");
            #endregion
            #endregion

            #region Call RopRelease to release all resources
            this.ReleaseRop(targetMessageHandle);
            #endregion
        }
        public void MSOXCFOLD_S04_TC10_RopHardDeleteMessagesInPublicFolder()
        {
            this.CheckWhetherSupportTransport();
            this.Logon();
            this.PublicFolderInitialization();

            #region Step 1. The client creates a message in the root public folder.
            ulong messageId = 0;
            uint messageHandle = 0;
            this.CreateSaveMessage(this.publicRootFolderHandle, this.publicRootFolderId, ref messageId, ref messageHandle);
            #endregion

            #region Step 2. The client calls RopGetContentsTable to retrieve the contents table of the root public folder.
            RopGetContentsTableRequest getContentsTableRequestFirst = new RopGetContentsTableRequest
            {
                RopId = (byte)RopId.RopGetContentsTable,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                TableFlags = 0x00
            };

            // Get the Contents table of the opened folder.
            RopGetContentsTableResponse getContentsTableResponseFirst = this.Adapter.GetContentsTable(getContentsTableRequestFirst, this.publicRootFolderHandle, ref this.responseHandles);

            uint rowCountFirst = getContentsTableResponseFirst.RowCount;
            #endregion

            #region Step 3. The client calls RopHardDeleteMessage to delete this message in the root public folder.
            object ropResponse = null;
            ulong[] messageIds = new ulong[] { messageId };

            RopHardDeleteMessagesRequest hardDeleteMessagesRequest = new RopHardDeleteMessagesRequest();
            RopHardDeleteMessagesResponse hardDeleteMessagesResponse = new RopHardDeleteMessagesResponse();
            hardDeleteMessagesRequest.RopId = (byte)RopId.RopHardDeleteMessages;
            hardDeleteMessagesRequest.LogonId = Constants.CommonLogonId;
            hardDeleteMessagesRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            hardDeleteMessagesRequest.WantAsynchronous = 0x00;

            // The server does not generate a non-read receipt for the deleted messages.
            hardDeleteMessagesRequest.NotifyNonRead = 0x00;
            hardDeleteMessagesRequest.MessageIdCount = (ushort)messageIds.Length;
            hardDeleteMessagesRequest.MessageIds = messageIds;
            this.Adapter.DoRopCall(hardDeleteMessagesRequest, this.publicRootFolderHandle, ref ropResponse, ref this.responseHandles);
            hardDeleteMessagesResponse = (RopHardDeleteMessagesResponse)ropResponse;

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R99401");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R99401
            Site.CaptureRequirementIfAreEqual<uint>(
                Constants.SuccessCode,
                hardDeleteMessagesResponse.ReturnValue,
                99401,
                @"[In RopHardDeleteMessages ROP] This ROP [RopHardDeleteMessages] applies to both public folders [and private mailboxes].");
            #endregion

            #region Step 4. The client calls RopGetContentsTable to retrieve the contents table of the root public folder.
            RopGetContentsTableRequest getContentsTableRequestSecond = new RopGetContentsTableRequest
            {
                RopId = (byte)RopId.RopGetContentsTable,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                TableFlags = (byte)FolderTableFlags.Depth
            };

            // Get the Contents table of the opened folder.
            RopGetContentsTableResponse getContentsTableResponseSecond = this.Adapter.GetContentsTable(getContentsTableRequestSecond, this.publicRootFolderHandle, ref this.responseHandles);

            uint rowCountSecond = getContentsTableResponseSecond.RowCount;

            Assert.AreEqual<uint>(rowCountFirst - 1, rowCountSecond, "If ROP succeeds, the second RowCount value returned from server should be one less than the first one. ");
            #endregion
        }
        public void MSOXCFOLD_S04_TC12_RopGetContentsTableFromPublicFolder()
        {
            this.CheckWhetherSupportTransport();
            this.Logon();
            this.PublicFolderInitialization();

            #region Step 1. The client calls RopCreateFolder to create [MSOXCFOLDSubfolder1] under the root public folder.
            uint folderHandle1 = 0;
            ulong folderId1 = 0;
            this.CreateFolder(this.publicRootFolderHandle, Constants.Subfolder1, ref folderId1, ref folderHandle1);
            #endregion

            #region Step 2. The client creates a message in the public root folder.
            ulong messageId = 0;
            uint messageHandle = 0;
            this.CreateSaveMessage(this.publicRootFolderHandle, this.publicRootFolderId, ref messageId, ref messageHandle);
            #endregion

            #region Step 3. The client calls RopGetContentsTable retrieve the contents table for the public root folder.
            RopGetContentsTableRequest getContentsTableRequest = new RopGetContentsTableRequest
            {
                RopId = (byte)RopId.RopGetContentsTable,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                TableFlags = 0xC8
            };
            RopGetContentsTableResponse getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, this.publicRootFolderHandle, ref this.responseHandles);

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R100501");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R100501.
            Site.CaptureRequirementIfAreEqual<uint>(
                Constants.SuccessCode,
                getContentsTableResponse.ReturnValue,
                100501,
                @"[In RopGetContentsTable ROP] This ROP [RopGetContentsTable] applies to both public folders [and private mailboxes].");
            #endregion
        }
        public void MSOXCFOLD_S04_TC08_RopHardDeleteMessagesAndSubfoldersInPublicFolder()
        {
            if (!Common.IsRequirementEnabled(98301002, this.Site))
            {
                this.NeedCleanup = false;
                Site.Assert.Inconclusive("The server does not support the RopHardDeleteMessagesAndSubfolders ROP for public folders.");
            }

            this.CheckWhetherSupportTransport();
            this.Logon();
            this.PublicFolderInitialization();

            #region Step 1. The client calls RopCreateFolder to create [MSOXCFOLDSubfolder1] under the root public folder.

            RopCreateFolderRequest createFolderRequest = new RopCreateFolderRequest();
            RopCreateFolderResponse createFolderResponse = new RopCreateFolderResponse();
            createFolderRequest.RopId = (byte)RopId.RopCreateFolder;
            createFolderRequest.LogonId = Constants.CommonLogonId;
            createFolderRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            createFolderRequest.OutputHandleIndex = Constants.CommonOutputHandleIndex;
            createFolderRequest.FolderType = (byte)FolderType.Genericfolder;
            createFolderRequest.UseUnicodeStrings = 0x0;
            createFolderRequest.OpenExisting = 0x01;
            createFolderRequest.Reserved = 0x0;
            createFolderRequest.DisplayName = Encoding.ASCII.GetBytes(Constants.Subfolder1);
            createFolderRequest.Comment = Encoding.ASCII.GetBytes(Constants.Subfolder1);

            createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.publicRootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully.");
            uint subfolderHandle1 = this.responseHandles[0][createFolderResponse.OutputHandleIndex];
            #endregion

            #region Step 2. The client calls RopCreateFolder to create [MSOXCFOLDSubfolder2] under [MSOXCFOLDSubfolder1].

            createFolderRequest.DisplayName = Encoding.ASCII.GetBytes(Constants.Subfolder2);
            createFolderRequest.Comment = Encoding.ASCII.GetBytes(Constants.Subfolder2);

            createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, subfolderHandle1, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully.");
            #endregion

            #region Step 3. The client creates a message in [MSOXCFOLDSubfolder1].

            uint messageHandle = 0;
            ulong messageId = 0;
            this.CreateSaveMessage(this.publicRootFolderHandle, this.publicRootFolderId, ref messageId, ref messageHandle);

            #endregion

            #region Step 4. The client calls RopHardDeleteMessagesAndSubfolders applying to [MSOXCFOLDSubfolder1].

            object ropResponse = new object();
            RopHardDeleteMessagesAndSubfoldersRequest hardDeleteMessagesAndSubfoldersRequest = new RopHardDeleteMessagesAndSubfoldersRequest();
            RopHardDeleteMessagesAndSubfoldersResponse hardDeleteMessagesAndSubfoldersResponse;
            hardDeleteMessagesAndSubfoldersRequest.RopId = (byte)RopId.RopHardDeleteMessagesAndSubfolders;
            hardDeleteMessagesAndSubfoldersRequest.LogonId = Constants.CommonLogonId;
            hardDeleteMessagesAndSubfoldersRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            hardDeleteMessagesAndSubfoldersRequest.WantAsynchronous = 0x00;
            hardDeleteMessagesAndSubfoldersRequest.WantDeleteAssociated = 0xFF;

            this.Adapter.DoRopCall(hardDeleteMessagesAndSubfoldersRequest, subfolderHandle1, ref ropResponse, ref this.responseHandles);
            hardDeleteMessagesAndSubfoldersResponse = (RopHardDeleteMessagesAndSubfoldersResponse)ropResponse;

            Site.Assert.AreEqual<uint>(0, hardDeleteMessagesAndSubfoldersResponse.ReturnValue, "RopHardDeleteMessagesAndSubfolders ROP operation performs successfully.");
            Site.Assert.AreEqual<uint>(0, hardDeleteMessagesAndSubfoldersResponse.PartialCompletion, "If delete all subsets of targets succeeds, PartialCompletion of its response will be 0 (success)");

            #endregion

            #region Step 5. The client calls GetContentsTable to retrieve the contents table of [MSOXCFOLDSubfolder1].

            RopGetContentsTableRequest getContentsTableRequest = new RopGetContentsTableRequest
            {
                RopId = (byte)RopId.RopGetContentsTable,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                TableFlags = (byte)FolderTableFlags.None
            };

            RopGetContentsTableResponse getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, subfolderHandle1, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");

            #endregion

            #region Step 6. The client calls GetHierarchyTable to retrieve the hierarchy table of [MSOXCFOLDSubfolder1].

            RopGetHierarchyTableRequest getHierarchyTableRequest = new RopGetHierarchyTableRequest
            {
                RopId = (byte)RopId.RopGetHierarchyTable,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                TableFlags = (byte)FolderTableFlags.None
            };

            RopGetHierarchyTableResponse getHierarchyTableResponse = this.Adapter.GetHierarchyTable(getHierarchyTableRequest, subfolderHandle1, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getHierarchyTableResponse.ReturnValue, "RopGetHierarchyTable ROP operation performs successfully!");

            // Add the debug information.
            Site.Log.Add(
                LogEntryKind.Debug,
                "Verify MS-OXCFOLD_R98301002: The message count of the target folder after RopEmptyFolder is {0}, the subfolder count of the target folder after RopEmptyFolder is {1}",
                getContentsTableResponse.RowCount,
                getHierarchyTableResponse.RowCount);

            bool isVerifyR98301002 = getHierarchyTableResponse.RowCount == 0 && getContentsTableResponse.RowCount == 0;

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R98301002.
            Site.CaptureRequirementIfIsTrue(
                isVerifyR98301002,
                98301002,
                @"[In Appendix A: Product Behavior] Implementation does support the RopHardDeleteMessagesAndSubfolders ROP ([MS-OXCROPS] section 2.2.4.10) for public folders. (Microsoft Exchange Server 2007 and Microsoft Exchange Server 2010 follow this behavior.)");
            #endregion
        }
        public void MSOXCFOLD_S04_TC09_RopDeleteMessagesInPublicFolder()
        {
            this.CheckWhetherSupportTransport();
            this.Logon();
            this.PublicFolderInitialization();

            #region Step 1. The client creates a message in the root public folder.
            ulong messageId = 0;
            uint messageHandle = 0;
            this.CreateSaveMessage(this.publicRootFolderHandle, this.publicRootFolderId, ref messageId, ref messageHandle);
            #endregion

            #region Step 2. The client calls RopGetContentsTable to retrieve the contents table of the root public folder.
            RopGetContentsTableRequest getContentsTableRequestFirst = new RopGetContentsTableRequest
            {
                RopId = (byte)RopId.RopGetContentsTable,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                TableFlags = 0x00
            };

            // Get the Contents table of the opened folder.
            RopGetContentsTableResponse getContentsTableResponseFirst = this.Adapter.GetContentsTable(getContentsTableRequestFirst, this.publicRootFolderHandle, ref this.responseHandles);

            uint rowCountFirst = getContentsTableResponseFirst.RowCount;
            #endregion

            #region Step 3. The client calls RopDeleteMessages to delete this message in the root public folder.
            RopDeleteMessagesRequest deleteMessagesRequest = new RopDeleteMessagesRequest();

            // Organize the DeleteMessage request.
            ulong[] messageIdsDeleted = new ulong[1];
            messageIdsDeleted[0] = messageId;
            deleteMessagesRequest.RopId = (byte)RopId.RopDeleteMessages;
            deleteMessagesRequest.LogonId = Constants.CommonLogonId;
            deleteMessagesRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            deleteMessagesRequest.MessageIdCount = (ushort)messageIdsDeleted.Length;
            deleteMessagesRequest.MessageIds = messageIdsDeleted;
            RopDeleteMessagesResponse deleteMessagesResponse = this.Adapter.DeleteMessages(deleteMessagesRequest, this.publicRootFolderHandle, ref this.responseHandles);

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R98801");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R98801
            Site.CaptureRequirementIfAreEqual<uint>(
                Constants.SuccessCode,
                deleteMessagesResponse.ReturnValue,
                98801,
                @"[In RopDeleteMessages ROP] This ROP [RopDeleteMessages] applies to both public folders [and private mailboxes].");
            #endregion

            #region Step 4. The client calls RopGetContentsTable to retrieve the contents table of the root public folder.
            RopGetContentsTableRequest getContentsTableRequestSecond = new RopGetContentsTableRequest
            {
                RopId = (byte)RopId.RopGetContentsTable,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                TableFlags = 0x00
            };

            // Get the Contents table of the opened folder.
            RopGetContentsTableResponse getContentsTableResponseSecond = this.Adapter.GetContentsTable(getContentsTableRequestSecond, this.publicRootFolderHandle, ref this.responseHandles);
            uint rowCountSecond = getContentsTableResponseSecond.RowCount;

            Assert.AreEqual<uint>(rowCountFirst - 1, rowCountSecond, "If ROP succeeds, the second RowCount value returned from server should be one less than the first one. ");
            #endregion
        }
        public void MSOXCFOLD_S02_TC04_RopDeleteMessagesSuccess()
        {
            this.CheckWhetherSupportTransport();
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            this.GenericFolderInitialization();

            #region Step 1. Create tree message in root folder.
            uint messageHandle = 0;
            ulong messageId = 0;
            this.CreateSaveMessage(this.RootFolderHandle, this.RootFolderId, ref messageId, ref messageHandle);
            uint messageHandle2 = 0;
            ulong messageId2 = 0;
            this.CreateSaveMessage(this.RootFolderHandle, this.RootFolderId, ref messageId2, ref messageHandle2);
            uint messageHandle3 = 0;
            ulong messageId3 = 0;
            this.CreateSaveMessage(this.RootFolderHandle, this.RootFolderId, ref messageId3, ref messageHandle3);
            #endregion

            #region Step 2. Delete the message created in step 1 in root folder.
            this.OpenMessage(messageId, this.RootFolderHandle, MessageOpenModeFlags.ReadWrite);
            object ropResponse = null;
            ulong[] messageIds = new ulong[] { messageId };

            RopDeleteMessagesRequest deleteMessagesRequest = new RopDeleteMessagesRequest();
            RopDeleteMessagesResponse deleteMessagesResponse;
            deleteMessagesRequest.RopId = (byte)RopId.RopDeleteMessages;
            deleteMessagesRequest.LogonId = Constants.CommonLogonId;
            deleteMessagesRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            deleteMessagesRequest.WantAsynchronous = 0x00;

            // The server does not generate a non-read receipt for the deleted messages.
            deleteMessagesRequest.NotifyNonRead = 0x00;
            deleteMessagesRequest.MessageIdCount = (ushort)messageIds.Length;
            deleteMessagesRequest.MessageIds = messageIds;
            this.Adapter.DoRopCall(deleteMessagesRequest, this.RootFolderHandle, ref ropResponse, ref this.responseHandles);
            deleteMessagesResponse = (RopDeleteMessagesResponse)ropResponse;
            Site.Assert.AreEqual<uint>(
                0,
                deleteMessagesResponse.ReturnValue,
                "If ROP succeeds, the ReturnValue of its response is 0(success)");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1143");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1143
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(RopDeleteMessagesResponse),
                ropResponse.GetType(),
                1143,
                @"[In Processing a RopDeleteMessages ROP Request] The server responds with a RopDeleteMessages ROP response buffer.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R98802");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R98802.
            // The RopDeleteMessages ROP operation performs successfully on a private mailbox, MS-OXCFOLD_R98802 can be captured directly.
            Site.CaptureRequirement(
                98802,
                @"[In RopDeleteMessages ROP] This ROP [RopDeleteMessages] applies to [both public folders and] private mailboxes.");

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R271");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R271.
            // The WantAsynchronous was set to zero and the server responds a RopDeleteMessages ROP response indicates the ROP is processed synchronously, MS-OXCFOLD_R271 can be verified directly.
            Site.CaptureRequirement(
                271,
                @"[In RopDeleteMessages ROP Request Buffer] WantAsynchronous (1 byte): [A Boolean value that is] zero (FALSE) if the ROP is to be processed synchronously.");

            #region Verify MS-OXCFOLD_R282 and MS-OXCFOLD_R436.

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R282");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R282.
            Site.CaptureRequirementIfAreEqual<uint>(
                0,
                deleteMessagesResponse.PartialCompletion,
                282,
                "[In RopDeleteMessages ROP Response Buffer] PartialCompletion (1 byte): Otherwise [if the ROP successes for a subset of targets], the value [of PartialCompletion field] is zero (FALSE).");

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R436");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R436.
            // The RopDeleteMessage performs successfully, and MS-OXCFOLD_R282 is verified, MS-OXCFOLD_R436 can be verified directly.
            Site.CaptureRequirement(
                436,
                "[In Deleting the Contents of a Folder] To remove particular messages from a folder, the client sends [either] a RopDeleteMessages ROP request ([MS-OXCROPS] section 2.2.4.11) [or a RopHardDeleteMessages ROP request ([MS-OXCROPS] section 2.2.4.12)].");
            #endregion

            messageIds = new ulong[] { messageId2, messageId3 };
            deleteMessagesRequest.RopId = (byte)RopId.RopDeleteMessages;
            deleteMessagesRequest.LogonId = Constants.CommonLogonId;
            deleteMessagesRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            deleteMessagesRequest.WantAsynchronous = 0x00;

            // The server does not generate a non-read receipt for the deleted messages.
            deleteMessagesRequest.NotifyNonRead = 0x00;
            deleteMessagesRequest.MessageIdCount = (ushort)messageIds.Length;
            deleteMessagesRequest.MessageIds = messageIds;
            this.Adapter.DoRopCall(deleteMessagesRequest, this.RootFolderHandle, ref ropResponse, ref this.responseHandles);

            #region Verify MS-OXCFOLD_R262 and MS-OXCFOLD_R1017.

            bool allDeleted = this.IsMessageDeleted(messageId2, this.RootFolderId) && this.IsMessageDeleted(messageId3, this.RootFolderId);

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R262");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R262.
            Site.CaptureRequirementIfIsTrue(
                allDeleted,
                262,
                "[In RopDeleteMessages ROP] The RopDeleteMessages ROP ([MS-OXCROPS] section 2.2.4.11) is used to soft delete one or more messages from a folder.");

            RopGetContentsTableRequest getContentsTableRequest = new RopGetContentsTableRequest
            {
                RopId = (byte)RopId.RopGetContentsTable,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                TableFlags = (byte)FolderTableFlags.SoftDeletes
            };
            RopGetContentsTableResponse getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, this.RootFolderHandle, ref this.responseHandles);

            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");

            if (Common.IsRequirementEnabled(1017, this.Site))
            {
                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1017");

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1017
                // Method GetContentsTable succeeds and it's row count is 3, this requirement verified.
                Site.CaptureRequirementIfAreEqual<uint>(
                    3,
                    getContentsTableResponse.RowCount,
                    1017,
                    @"[In RopGetContentsTable ROP Request Buffer] If this bit [SoftDeletes] is set, the contents table lists only the messages that are soft deleted.");
            }

            #endregion

            #endregion
        }
        public void MSOXCFOLD_S02_TC11_RopMoveCopyMessagesUseSearchFolderSuccess()
        {
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            this.GenericFolderInitialization();

            #region Step 1. Call RopCreateFolder to create [MSOXCFOLDSubfolder1] under the root folder.
            ulong subfolderId1 = 0;
            uint subfolderHandle1 = 0;
            this.CreateFolder(this.RootFolderHandle, Constants.Subfolder1, ref subfolderId1, ref subfolderHandle1);
            #endregion

            #region Step 2. Create a message in the [MSOXCFOLDSubfolder1] folder created in step 1.

            uint messageHandle = 0;
            ulong messageId = 0;
            this.CreateSaveMessage(subfolderHandle1, subfolderId1, ref messageId, ref messageHandle);

            #endregion

            #region Step 3. Call RopCreateFolder to create [MSOXCFOLDSubfolder2] under the root folder.
            ulong subfolderId2 = 0;
            uint subfolderHandle2 = 0;
            this.CreateFolder(this.RootFolderHandle, Constants.Subfolder2, ref subfolderId2, ref subfolderHandle2);
            #endregion

            #region Step 4. Create a message in the [MSOXCFOLDSubfolder2] folder created in step 3.

            uint messageHandleInSubFolder2 = 0;
            ulong messageIdInSubFolder2 = 0;
            this.CreateSaveMessage(subfolderHandle2, subfolderId2, ref messageIdInSubFolder2, ref messageHandleInSubFolder2);
            #endregion

            #region Step 4. Call RopCreateFolder to create a search folder [MSOXCFOLDSearchFolder] under the root folder.
            RopCreateFolderRequest createFolderRequest = new RopCreateFolderRequest
            {
                RopId = (byte)RopId.RopCreateFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                FolderType = (byte)FolderType.Searchfolder,
                UseUnicodeStrings = 0x0,
                OpenExisting = 0x00,
                Reserved = 0x0,
                DisplayName = Encoding.ASCII.GetBytes(Constants.SearchFolder),
                Comment = Encoding.ASCII.GetBytes(Constants.SearchFolder)
            };
            RopCreateFolderResponse createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.RootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully!");
            uint searchFolderHandle = this.responseHandles[0][createFolderResponse.OutputHandleIndex];

            #endregion

            #region Step 5. The client calls RopSetSearchCriteria to establish search criteria for [MSOXCFOLDSubFolder1].

            RopSetSearchCriteriaRequest setSearchCriteriaRequest = new RopSetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopSetSearchCriteria,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex
            };
            PropertyTag propertyTag = new PropertyTag
            {
                PropertyId = (ushort)MessagePropertyId.PidTagMessageClass,
                PropertyType = (ushort)PropertyType.PtypString
            };
            ExistRestriction existRestriction = new ExistRestriction
            {
                PropTag = propertyTag
            };
            setSearchCriteriaRequest.RestrictionDataSize = (ushort)existRestriction.Size();
            setSearchCriteriaRequest.RestrictionData = existRestriction.Serialize();
            setSearchCriteriaRequest.FolderIds = new ulong[] { subfolderId1 };
            setSearchCriteriaRequest.FolderIdCount = (ushort)setSearchCriteriaRequest.FolderIds.Length;
            setSearchCriteriaRequest.SearchFlags = (uint)SetSearchFlags.ContentIndexedSearch | (uint)SetSearchFlags.StaticSearch | (uint)SetSearchFlags.RestartSearch;
            RopSetSearchCriteriaResponse setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, searchFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, setSearchCriteriaResponse.ReturnValue, "RopSearchCriteria ROP operation performs successfully!");

            #endregion

            #region Step 6. The client calls RopGetSearchCriteria to obtain the search criteria and the status of the search folder [MSOXCFOLDSubFolder1].
            RopGetSearchCriteriaRequest getSearchCriteriaRequest = new RopGetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopGetSearchCriteria,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                UseUnicode = 0x00,
                IncludeRestriction = 0x01,
                IncludeFolders = 0x01
            };
            RopGetSearchCriteriaResponse getSearchCriteriaResponse = this.Adapter.GetSearchCriteria(getSearchCriteriaRequest, searchFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getSearchCriteriaResponse.ReturnValue, "RopGetSearchCriteria ROP operation performs successfully!");

            #endregion

            #region Step 7. The client calls RopGetContentsTable to get handle of the contents table in the search folder [MSOXCFOLDSearchFolder].

            RopGetContentsTableRequest getContentsTableRequest = new RopGetContentsTableRequest();
            RopGetContentsTableResponse getContentsTableResponse;
            getContentsTableRequest.RopId = (byte)RopId.RopGetContentsTable;
            getContentsTableRequest.LogonId = Constants.CommonLogonId;
            getContentsTableRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            getContentsTableRequest.OutputHandleIndex = Constants.CommonOutputHandleIndex;
            getContentsTableRequest.TableFlags = (byte)FolderTableFlags.None;

            int count = 0;
            uint tableHandle;
            do
            {
                getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, searchFolderHandle, ref this.responseHandles);
                Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");
                tableHandle = this.responseHandles[0][getContentsTableResponse.OutputHandleIndex];
                if (getContentsTableResponse.RowCount != 1)
                {
                    Thread.Sleep(this.WaitTime);
                }
                else
                {
                    break;
                }

                count++;
            }
            while (count < this.RetryCount);

            #endregion

            #region Step 8. Sets the properties PidTagMid visible on the content table.

            RopSetColumnsRequest setColumnsRequest;
            PropertyTag[] propertyTags = new PropertyTag[1];
            propertyTags[0].PropertyId = (ushort)MessagePropertyId.PidTagMid;
            propertyTags[0].PropertyType = (ushort)PropertyType.PtypInteger64;

            setColumnsRequest.RopId = 0x12;
            setColumnsRequest.LogonId = 0x00;
            setColumnsRequest.InputHandleIndex = 0x00;
            setColumnsRequest.PropertyTagCount = (ushort)propertyTags.Length;
            setColumnsRequest.PropertyTags = propertyTags;
            setColumnsRequest.SetColumnsFlags = 0x00; // Sync

            object ropResponse = new object();
            this.Adapter.DoRopCall(setColumnsRequest, tableHandle, ref ropResponse, ref this.responseHandles);
            #endregion

            #region Step 9. Gets the message ID in the search folder [MSOXCFOLDSearchFolder].

            RopQueryRowsRequest queryRowsRequest;
            RopQueryRowsResponse queryRowsResponse;

            queryRowsRequest.RopId = 0x15;
            queryRowsRequest.LogonId = 0x00;
            queryRowsRequest.InputHandleIndex = 0x00;
            queryRowsRequest.QueryRowsFlags = 0x00;
            queryRowsRequest.ForwardRead = 0x01;
            queryRowsRequest.RowCount = 1;

            this.Adapter.DoRopCall(queryRowsRequest, tableHandle, ref ropResponse, ref this.responseHandles);
            queryRowsResponse = (RopQueryRowsResponse)ropResponse;
            ulong messageID = BitConverter.ToUInt64(queryRowsResponse.RowData.PropertyRows[0].PropertyValues[0].Value, 0);
            #endregion

            #region Step 10. Call RopMoveCopyMessages to copy the message in the [MSOXCFOLDSearchFolder] to root folder synchronously.
            ulong[] messageIds = new ulong[1];
            messageIds[0] = messageID;
            List<uint> handlelist = new List<uint>
            {
                searchFolderHandle, this.RootFolderHandle
            };

            RopMoveCopyMessagesRequest moveCopyMessagesRequest = new RopMoveCopyMessagesRequest
            {
                RopId = (byte)RopId.RopMoveCopyMessages,
                LogonId = Constants.CommonLogonId,
                SourceHandleIndex = 0x00,
                DestHandleIndex = 0x01,
                MessageIdCount = (ushort)messageIds.Length,
                MessageIds = messageIds,
                WantAsynchronous = 0x00,
                WantCopy = 0xFF
            };

            // WantCopy is nonzero (TRUE) indicates this is a copy operation.
            RopMoveCopyMessagesResponse copyMessagesFromSearchFolderResponse = this.Adapter.MoveCopyMessages(moveCopyMessagesRequest, handlelist, ref this.responseHandles);

            Site.Assert.AreEqual<uint>(0, copyMessagesFromSearchFolderResponse.ReturnValue, "The RopMoveCopyMessages ROP operation performs successfully.");
            Site.Assert.AreEqual<uint>(0, copyMessagesFromSearchFolderResponse.PartialCompletion, "The ROP successes for all subsets of targets");
            handlelist.Clear();
            #endregion

            #region Step 11. Validate the message is copied successfully in above step 9.
            uint rootFolderContentsCountActual = this.GetContentsTable(FolderTableFlags.None, this.RootFolderHandle);

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R121702.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R121702: expected contents count of the root folder is {0}, actual contents count of the root folder is {1};", 1, rootFolderContentsCountActual);

            // The source folder is a search folder, so if the message was copied successfully from MSOXCFOLDSearchFolder to root folder, R121702 can be verified.
            Site.CaptureRequirementIfAreEqual<uint>(
                1,
                rootFolderContentsCountActual,
                121702,
                @"[In RopMoveCopyMessages ROP Request Buffer] SourceHandleIndex (1 byte): [The source Server object for this operation [RopMoveCopyMessages ROP] is a Folder object that represents the folder from which the messages will be copied] This folder can be a search folder.");
            #endregion

            #region Step 12. Call RopMoveCopyMessages to move the message in the [MSOXCFOLDSearchFolder] to root folder synchronously.
            messageIds = new ulong[1];
            messageIds[0] = messageID;
            handlelist = new List<uint>
            {
                searchFolderHandle, this.RootFolderHandle
            };

            moveCopyMessagesRequest = new RopMoveCopyMessagesRequest
            {
                RopId = (byte)RopId.RopMoveCopyMessages,
                LogonId = Constants.CommonLogonId,
                SourceHandleIndex = 0x00,
                DestHandleIndex = 0x01,
                MessageIdCount = (ushort)messageIds.Length,
                MessageIds = messageIds,
                WantAsynchronous = 0x00,
                WantCopy = 0x00
            };

            // WantCopy is zero (FALSE) indicates this is a move operation.
            RopMoveCopyMessagesResponse moveMessagesFromSearchFolderResponse = this.Adapter.MoveCopyMessages(moveCopyMessagesRequest, handlelist, ref this.responseHandles);

            Site.Assert.AreEqual<uint>(0, moveMessagesFromSearchFolderResponse.ReturnValue, "The RopMoveCopyMessages ROP operation performs successfully.");
            Site.Assert.AreEqual<uint>(0, moveMessagesFromSearchFolderResponse.PartialCompletion, "The ROP successes for all subsets of targets");
            handlelist.Clear();
            #endregion

            #region Step 13. Validate the message is moved successfully in above step 12.
            rootFolderContentsCountActual = this.GetContentsTable(FolderTableFlags.None, this.RootFolderHandle);

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R121701.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R121701: expected contents count of the root folder is {0}, actual contents count of the root folder is {1};", 2, rootFolderContentsCountActual);

            // The source folder is a search folder, so if the message was moved successfully from MSOXCFOLDSearchFolder to root folder, R121701 can be verified.
            Site.CaptureRequirementIfAreEqual<uint>(
                2,
                rootFolderContentsCountActual,
                121701,
                @"[In RopMoveCopyMessages ROP Request Buffer] SourceHandleIndex (1 byte): [The source Server object for this operation [RopMoveCopyMessages ROP] is a Folder object that represents the folder from which the messages will be moved] This folder can be a search folder.");
            #endregion

            #region Step 14. Call RopMoveCopyMessages to copy the message in the [MSOXCFOLDSubfolder2] to the [MSOXCFOLDSearchFolder] synchronously.
            RopMoveCopyMessagesResponse copyMessagesToSearchFolderResponse = new RopMoveCopyMessagesResponse();
            if (Common.IsRequirementEnabled(1246, this.Site))
            {
                messageIds[0] = messageIdInSubFolder2;
                handlelist = new List<uint>
                {
                subfolderHandle2, searchFolderHandle
                };
                moveCopyMessagesRequest = new RopMoveCopyMessagesRequest
                {
                    RopId = (byte)RopId.RopMoveCopyMessages,
                    LogonId = Constants.CommonLogonId,
                    SourceHandleIndex = 0x00,
                    DestHandleIndex = 0x01,
                    MessageIdCount = (ushort)messageIds.Length,
                    MessageIds = messageIds,
                    WantAsynchronous = 0x00,
                    WantCopy = 0xFF
                };

                // WantCopy is nonzero (TRUE) indicates this is a copy operation.
                copyMessagesToSearchFolderResponse = this.Adapter.MoveCopyMessages(moveCopyMessagesRequest, handlelist, ref this.responseHandles);

                // Add the debug information
                this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R121802: the PartialCompletion in the MoveCopyMessages response is {0}", copyMessagesToSearchFolderResponse.PartialCompletion);

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R121802
                // If the ROP RopMoveCopyMessages fails to copy message, the value of PartialCompletion field is nonzero.
                this.Site.CaptureRequirementIfAreNotEqual<uint>(
                    0x00000000,
                    copyMessagesToSearchFolderResponse.ReturnValue,
                    121802,
                    @"[In RopMoveCopyMessages ROP Request Buffer] DestHandleIndex (1 byte): [The destination Server object for this operation [RopMoveCopyMessages ROP] is a Folder object that represents the folder to which the messages will be copied.] This folder cannot be a search folder.");
            }
            #endregion

            #region Step 15. Call RopMoveCopyMessages to move the message in the [MSOXCFOLDSubfolder2] to the [MSOXCFOLDSearchFolder] synchronously.
            RopMoveCopyMessagesResponse moveMessagesToSearchFolderResponse;
            if (Common.IsRequirementEnabled(1246, this.Site))
            {
                messageIds[0] = messageIdInSubFolder2;
                handlelist = new List<uint>
                {
                subfolderHandle2, searchFolderHandle
                };
                moveCopyMessagesRequest = new RopMoveCopyMessagesRequest
                {
                    RopId = (byte)RopId.RopMoveCopyMessages,
                    LogonId = Constants.CommonLogonId,
                    SourceHandleIndex = 0x00,
                    DestHandleIndex = 0x01,
                    MessageIdCount = (ushort)messageIds.Length,
                    MessageIds = messageIds,
                    WantAsynchronous = 0x00,
                    WantCopy = 0x00
                };

                // WantCopy is zero (FLASE) indicates this is a move operation.
                 moveMessagesToSearchFolderResponse = this.Adapter.MoveCopyMessages(moveCopyMessagesRequest, handlelist, ref this.responseHandles);

                // Add the debug information
                this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R121801: the PartialCompletion in the MoveCopyMessages response is {0}", moveMessagesToSearchFolderResponse.PartialCompletion);

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R121801
                // If the ROP RopMoveCopyMessages fails to move message, the value of PartialCompletion field is nonzero.
                this.Site.CaptureRequirementIfAreNotEqual<uint>(
                    0x00000000,
                    moveMessagesToSearchFolderResponse.ReturnValue,
                    121801,
                    @"[In RopMoveCopyMessages ROP Request Buffer] DestHandleIndex (1 byte): [The destination Server object for this operation [RopMoveCopyMessages ROP] is a Folder object that represents the folder to which the messages will be moved.] This folder cannot be a search folder.");

                // Add the debug information
                this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1216");

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1216
                bool isVerifiedR1216 = copyMessagesFromSearchFolderResponse.ReturnValue == 0x00000000 &&
                                    moveMessagesFromSearchFolderResponse.ReturnValue == 0x00000000 &&
                                    copyMessagesToSearchFolderResponse.ReturnValue != 0x00000000 &&
                                    moveMessagesToSearchFolderResponse.ReturnValue != 0x00000000;

                this.Site.CaptureRequirementIfIsTrue(
                    isVerifiedR1216,
                    1216,
                    @"[In RopMoveCopyMessages ROP] The source folder can be a search folder, but the destination folder cannot.");

                // Add the debug information
                this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1246: the return value is {0} when copy a message to a search folder and the return value is {1} when move a message to a search folder.", copyMessagesToSearchFolderResponse.ReturnValue, moveMessagesToSearchFolderResponse.ReturnValue);

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1246
                bool isVerifiedR1246 = copyMessagesToSearchFolderResponse.ReturnValue == 0x00000460 && moveMessagesToSearchFolderResponse.ReturnValue == 0x00000460;

                this.Site.CaptureRequirementIfIsTrue(
                    isVerifiedR1246,
                    1246,
                    @"[In Processing a RopMoveCopyMessages ROP Request] When the error code is ecSearchFolder, it indicates the destination object is a search folder. ");

                // Add the debug information
                this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1245");

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1245
                this.Site.CaptureRequirementIfAreEqual<uint>(
                    0x00000460,
                    copyMessagesToSearchFolderResponse.ReturnValue,
                    1245,
                    @"[In Processing a RopMoveCopyMessages ROP Request] The value of error code ecSearchFolder is 0x00000460.");
            }
            #endregion
        }
        /// <summary>
        /// Retrieves the contents table for a folder.
        /// </summary>
        /// <param name="ropGetContentsTableRequest">RopGetContentsTableRequest object.</param>
        /// <param name="insideObjHandle">Server object handle in RopGetContentsTable.</param>
        /// <param name="responseSOHTable">Server objects handles in RopGetContentsTableResponse.</param>
        /// <returns>RopGetContentsTableResponse object.</returns>
        public RopGetContentsTableResponse GetContentsTable(RopGetContentsTableRequest ropGetContentsTableRequest, uint insideObjHandle, ref List<List<uint>> responseSOHTable)
        {
            object temp = new object();
            RopGetContentsTableResponse ropGetContentsTableResponse;
            bool contentsTableLocked = true;
            int count = 0;
            int waitTime = int.Parse(Common.GetConfigurationPropertyValue("WaitTime", this.Site));
            int retryCount = int.Parse(Common.GetConfigurationPropertyValue("RetryCount", this.Site));
            do
            {
                this.ExcuteRopCall((ISerializable)ropGetContentsTableRequest, insideObjHandle, ref temp, ref responseSOHTable, ref this.rawData);
                ropGetContentsTableResponse = (RopGetContentsTableResponse)temp;

                // The contents table was locked by another database operation.
                if (ropGetContentsTableResponse.ReturnValue == 4294965994)
                {
                    Site.Log.Add(LogEntryKind.Comment, " JET_errTableLocked:" + ropGetContentsTableResponse.ReturnValue);
                    Thread.Sleep(waitTime);
                }
                else
                {
                    contentsTableLocked = false;
                }

                if (count > retryCount)
                {
                    break;
                }

                count++;
            }
            while (contentsTableLocked);

            #region Capture Code
            // The ReturnValue equal to 0x00000000 indicate ROP operation success
            if (0x00000000 == ropGetContentsTableResponse.ReturnValue)
            {
                this.VerifyRopGetContentsTable(ropGetContentsTableResponse);
            }
            #endregion

            return ropGetContentsTableResponse;
        }
        public void MSOXCFOLD_S03_TC02_DynamicSearchVerification()
        {
            this.CheckWhetherSupportTransport();
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            this.GenericFolderInitialization();

            #region Step 1. The client calls RopCreateFolder to create the general folder [MSOXCFOLDSubfolder1] under the root folder.

            RopCreateFolderRequest createFolderRequest = new RopCreateFolderRequest();
            createFolderRequest.RopId = (byte)RopId.RopCreateFolder;
            createFolderRequest.LogonId = Constants.CommonLogonId;
            createFolderRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            createFolderRequest.OutputHandleIndex = Constants.CommonOutputHandleIndex;
            createFolderRequest.FolderType = 0x01;
            createFolderRequest.UseUnicodeStrings = 0x0;
            createFolderRequest.OpenExisting = 0x00;
            createFolderRequest.Reserved = 0x0;
            createFolderRequest.DisplayName = Encoding.ASCII.GetBytes(Constants.Subfolder1);
            createFolderRequest.Comment = Encoding.ASCII.GetBytes(Constants.Subfolder1);
            RopCreateFolderResponse createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.RootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully!");
            uint subfolderHandle1 = this.responseHandles[0][createFolderResponse.OutputHandleIndex];
            ulong subfolderId1 = createFolderResponse.FolderId;

            #endregion

            #region Step 2. The client creates a non-FAI message under the general folder [MSOXCFOLDSubfolder1].

            uint messageNonFAIHandle1 = 0;
            ulong messageNonFAIId1 = 0;
            this.CreateSaveMessage(subfolderHandle1, subfolderId1, ref messageNonFAIId1, ref messageNonFAIHandle1);

            #endregion

            #region Step 3. The client calls RopCreateFolder to create the search folder [MSOXCFOLDSearchFolder1] under the root folder.

            createFolderRequest.FolderType = 0x02;
            createFolderRequest.DisplayName = Encoding.ASCII.GetBytes(Constants.SearchFolder);
            createFolderRequest.Comment = Encoding.ASCII.GetBytes(Constants.SearchFolder);
            createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.RootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully!");
            uint searchFolderHandle = this.responseHandles[0][createFolderResponse.OutputHandleIndex];
            #endregion

            #region Step 4. The client calls RopSetSearchCriteria to establish search criteria for [MSOXCFOLDSearchFolder1].

            RopSetSearchCriteriaRequest setSearchCriteriaRequest = new RopSetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopSetSearchCriteria,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex
            };
            PropertyTag propertyTag = new PropertyTag
            {
                PropertyId = (ushort)MessagePropertyId.PidTagMessageClass,
                PropertyType = (ushort)PropertyType.PtypString
            };
            ExistRestriction existRestriction = new ExistRestriction
            {
                PropTag = propertyTag
            };
            setSearchCriteriaRequest.RestrictionDataSize = (ushort)existRestriction.Size();
            setSearchCriteriaRequest.RestrictionData = existRestriction.Serialize();
            setSearchCriteriaRequest.FolderIds = new ulong[] { subfolderId1 };
            setSearchCriteriaRequest.FolderIdCount = (ushort)setSearchCriteriaRequest.FolderIds.Length;
            setSearchCriteriaRequest.SearchFlags = (uint)SetSearchFlags.NonContentIndexedSearch | (uint)SetSearchFlags.RestartSearch;
            RopSetSearchCriteriaResponse setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, searchFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, setSearchCriteriaResponse.ReturnValue, "RopSearchCriteria ROP operation performs successfully!");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R783");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R783
            Site.CaptureRequirementIfAreEqual<uint>(
                Constants.SuccessCode,
                setSearchCriteriaResponse.ReturnValue,
                783,
                @"[In RopSetSearchCriteria ROP Request Buffer] SearchFlags (4 bytes): NON_CONTENT_INDEXED_SEARCH (0x00020000) means that the search does not use a content-indexed search.");
            #endregion

            #region Step 5. The client calls RopGetSearchCriteria to obtain the search criteria and the status of the search folder [MSOXCFOLDSearchFolder1].

            RopGetSearchCriteriaRequest getSearchCriteriaRequest = new RopGetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopGetSearchCriteria,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                UseUnicode = 0x00,
                IncludeRestriction = 0x01,
                IncludeFolders = 0x01
            };
            RopGetSearchCriteriaResponse getSearchCriteriaResponse = this.Adapter.GetSearchCriteria(getSearchCriteriaRequest, searchFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getSearchCriteriaResponse.ReturnValue, "RopGetSearchCriteria ROP operation performs successfully!");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R785");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R785
            Site.CaptureRequirementIfAreEqual<uint>(
                (uint)GetSearchFlags.Running,
                getSearchCriteriaResponse.SearchFlags & (uint)GetSearchFlags.Running,
                785,
                @"[In RopGetSearchCriteria ROP Response Buffer] SearchFlags (4 bytes): SEARCH_RUNNING (0x00000001) means that the search is running, which means that the initial population of the search folder still being compiled.");
            #endregion

            #region Step 6. The client calls RopGetContentsTable to retrieve the contents table for the search folder [MSOXCFOLDSearchFolder1].

            RopGetContentsTableRequest getContentsTableRequest = new RopGetContentsTableRequest();
            RopGetContentsTableResponse getContentsTableResponse;
            getContentsTableRequest.RopId = (byte)RopId.RopGetContentsTable;
            getContentsTableRequest.LogonId = Constants.CommonLogonId;
            getContentsTableRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            getContentsTableRequest.OutputHandleIndex = Constants.CommonOutputHandleIndex;
            getContentsTableRequest.TableFlags = (byte)FolderTableFlags.None;

            int count = 0;
            do
            {
                getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, searchFolderHandle, ref this.responseHandles);
                Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");
                if (getContentsTableResponse.RowCount != 1)
                {
                    Thread.Sleep(this.WaitTime);
                }
                else
                {
                    break;
                }

                count++;
            }
            while (count < this.RetryCount);

            #region Verify the requirements: MS-OXCFOLD_R552, MS-OXCFOLD_R526.

            Site.Assert.AreEqual<uint>((uint)GetSearchFlags.Running, getSearchCriteriaResponse.SearchFlags & (uint)GetSearchFlags.Running, "The RopSearchCriteria ROP operation has not been complete.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R526");

            // If the client has received the success code from the server after sending a RopSetSearchCriteria request.
            // If the client has received a 'SEARCH_RUNNING' SearchFlags in the RopGetSearchCriteria response after sending a RopGetSearchCriteria response later.
            // If the client has got the messages which according to the search criteria and search scope that are specified in the RopSetSearchCriteria ROP request in the RopGetContentsTable response after sending a RopGetContentsTable request later.
            // Satisfy the above conditions, then this requirement can be verified directly.
            Site.CaptureRequirement(
                526,
                @"[In Processing a RopSetSearchCriteria ROP Request] The server can return the RopSetSearchCriteria ROP response before the search folder is fully updated.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R552");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R552
            // There should have 1 message macthed the search criteria, so the RowCount should be 1.
            Site.CaptureRequirementIfAreEqual<uint>(
                1,
                getContentsTableResponse.RowCount,
                552,
                @"[In Processing a RopSetSearchCriteria ROP Request] A dynamic search causes the search folder to be initially populated with all messages that match the search criteria at the point in time when the search is started or restarted.");
            #endregion

            #endregion

            #region Step 7. The client calls RopSetSearchCriteria without setting the SearchFlags to establish search criteria for [MSOXCFOLDSearchFolder1].

            setSearchCriteriaRequest.SearchFlags = (uint)SetSearchFlags.None;
            setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, searchFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, setSearchCriteriaResponse.ReturnValue, "RopSearchCriteria ROP operation performs successfully!");

            #endregion

            #region Step 8. The client calls RopGetSearchCriteria to obtain the search criteria and the status of the search folder [MSOXCFOLDSearchFolder1].

            getSearchCriteriaResponse = this.Adapter.GetSearchCriteria(getSearchCriteriaRequest, searchFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getSearchCriteriaResponse.ReturnValue, "RopGetSearchCriteria ROP operation performs successfully!");

            #endregion

            #region Step 9. The client calls RopGetContentsTable to retrieve the contents table for the search folder [MSOXCFOLDSearchFolder1].

            count = 0;
            do
            {
                getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, searchFolderHandle, ref this.responseHandles);
                Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");
                if (getContentsTableResponse.RowCount != 1)
                {
                    Thread.Sleep(this.WaitTime);
                }
                else
                {
                    break;
                }

                count++;
            }
            while (count < this.RetryCount);
            #endregion

            #region Step 10. The client creates a non-FAI message under the general folder [MSOXCFOLDSubfolder1].

            uint messageNonFAIHandle3 = 0;
            ulong messageNonFAIId3 = 0;
            this.CreateSaveMessage(subfolderHandle1, subfolderId1, ref messageNonFAIId3, ref messageNonFAIHandle3);

            #endregion

            #region Step 11. The client calls RopGetContentsTable to retrieve the contents table for the search folder [MSOXCFOLDSearchFolder1].
            count = 0;
            do
            {
                getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, searchFolderHandle, ref this.responseHandles);
                Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");
                if (getContentsTableResponse.RowCount != 2)
                {
                    Thread.Sleep(this.WaitTime);
                }
                else
                {
                    break;
                }

                count++;
            }
            while (count < this.RetryCount);

            #region Verify the requirements: MS-OXCFOLD_R1095, MS-OXCFOLD_R1210, MS-OXCFOLD_R1096, and MS-OXCFOLD_R1097.

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1096");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1096
            // There should have 2 messages found so the RowCount should be 2.
            Site.CaptureRequirementIfAreEqual<uint>(
                2,
                getContentsTableResponse.RowCount,
                1096,
                @"[In Processing a RopSetSearchCriteria ROP Request] For dynamic search folders, the contents of the search folder MUST continue to be updated as messages start to match or cease to match the search criteria. ");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1210");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1210
            Site.CaptureRequirementIfAreEqual<uint>(
                2,
                getContentsTableResponse.RowCount,
                1210,
                @"[In RopSetSearchCriteria ROP Request Buffer] SearchFlags (4 bytes): STATIC_SEARCH (0x00040000) means that the search is dynamic, if not set.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1095");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1095
            // There should have 2 messages found so the RowCount should be 2.
            Site.CaptureRequirementIfAreEqual<uint>(
                2,
                getContentsTableResponse.RowCount,
                1095,
                @"[In Processing a RopSetSearchCriteria ROP Request] For dynamic search folders, the contents of the search folder MUST continue to be updated as messages move around the mailbox. ");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1097");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1097
            Site.CaptureRequirementIfAreEqual<uint>(
                2,
                getContentsTableResponse.RowCount,
                1097,
                @"[In Processing a RopSetSearchCriteria ROP Request] The server continues to update the search folder with messages that enter or exit the search criteria.");

            #endregion

            #endregion
        }
        public void MSOXCFOLD_S04_TC04_RopMoveCopyMessagesInPublicFolderSuccess()
        {
            this.CheckWhetherSupportTransport();
            this.Logon();
            this.PublicFolderInitialization();

            #region Step 1. The client calls RopCreateFolder to create [MSOXCFOLDSubfolder1] under the root public folder.

            RopCreateFolderRequest createFolderRequest = new RopCreateFolderRequest
            {
                RopId = (byte)RopId.RopCreateFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                FolderType = (byte)FolderType.Genericfolder,
                UseUnicodeStrings = 0x0,
                OpenExisting = 0x01,
                Reserved = 0x0,
                DisplayName = Encoding.ASCII.GetBytes(Constants.Subfolder1),
                Comment = Encoding.ASCII.GetBytes(Constants.Subfolder1)
            };

            RopCreateFolderResponse createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.publicRootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs should successfully.");
            uint subfolderHandle1 = this.responseHandles[0][createFolderResponse.OutputHandleIndex];

            #endregion

            #region Step 2. The client creates a message in the root public folder.

            uint messageHandle = 0;
            ulong messageId = 0;
            this.CreateSaveMessage(this.publicRootFolderHandle, this.publicRootFolderId, ref messageId, ref messageHandle);

            #endregion

            #region Step 3. The client calls RopMoveCopyMessages to copy the message from the root public folder to [MSOXCFOLDSubfolder1].

            ulong[] messageIds = new ulong[] { messageId };
            List<uint> handlelist = new List<uint>
            {
                this.publicRootFolderHandle, subfolderHandle1
            };

            RopMoveCopyMessagesRequest moveCopyMessagesRequest = new RopMoveCopyMessagesRequest
            {
                RopId = (byte)RopId.RopMoveCopyMessages,
                LogonId = Constants.CommonLogonId,
                SourceHandleIndex = 0x00,
                DestHandleIndex = 0x01,
                MessageIdCount = (ushort)messageIds.Length,
                MessageIds = messageIds,
                WantAsynchronous = 0x00,
                WantCopy = 0x01
            };

            // WantCopy is non-zero (TRUE) indicates this is a copy operation.
            RopMoveCopyMessagesResponse moveCopyMessagesResponse = this.Adapter.MoveCopyMessages(moveCopyMessagesRequest, handlelist, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, moveCopyMessagesResponse.ReturnValue, "The RopMoveCopyMessages ROP operation performs should successfully.");
            handlelist.Clear();

            #endregion

            #region Step 4. The client calls RopGetContentsTable to retrieve the contents table for [MSOXCFOLDSubfolder1] with 'ConversationMembers' flag.

            RopGetContentsTableRequest getContentsTableRequest = new RopGetContentsTableRequest
            {
                RopId = (byte)RopId.RopGetContentsTable,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                TableFlags = (byte)FolderTableFlags.None
            };

            RopGetContentsTableResponse getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, this.publicRootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs should successfully.");

            #region Verify the requirement: MS-OXCFOLD_R14502 and MS-OXCFOLD_R10252.
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R10252: the return value of the getContentsTableResponse is {0}", getContentsTableResponse.ReturnValue);

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R10252
            // The'ConversationMembers' flag is seted in the getContentsTableRequest, so if the getContentsTableResponse returns success. R10252 can be verified. 
            Site.CaptureRequirementIfAreEqual<uint>(
                0,
                getContentsTableResponse.ReturnValue,
                10252,
                @"[In RopGetContentsTable ROP Request Buffer] This bit [ConversationMembers] is supported on public folders.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R14502");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R14502
            Site.CaptureRequirementIfAreEqual<uint>(
                1,
                getContentsTableResponse.RowCount,
                14502,
                @"[In RopMoveCopyMessages ROP] This ROP applies to both public folders [and private mailboxes].");
            #endregion
            #endregion
         }
        public void MSOXCFOLD_S03_TC01_StaticSearchVerification()
        {
            this.CheckWhetherSupportTransport();
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            this.GenericFolderInitialization();

            #region Step 1. The client calls RopCreateFolder to create the general folder [MSOXCFOLDSubfolder1] under the root folder.

            RopCreateFolderRequest createFolderRequest = new RopCreateFolderRequest
            {
                RopId = (byte)RopId.RopCreateFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                FolderType = (byte)FolderType.Genericfolder,
                UseUnicodeStrings = 0x0,
                OpenExisting = 0x00,
                Reserved = 0x0,
                DisplayName = Encoding.ASCII.GetBytes(Constants.Subfolder1),
                Comment = Encoding.ASCII.GetBytes(Constants.Subfolder1)
            };
            RopCreateFolderResponse createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.RootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully!");
            uint subfolderHandle1 = this.responseHandles[0][createFolderResponse.OutputHandleIndex];
            ulong subfolderId1 = createFolderResponse.FolderId;

            #endregion

            #region Step 2. The client creates two general messages under the folder [MSOXCFOLDSubfolder1].

            uint messageHandle1 = 0;
            ulong messageId1 = 0;
            this.CreateSaveMessage(subfolderHandle1, subfolderId1, ref messageId1, ref messageHandle1);

            uint messageHandle2 = 0;
            ulong messageId2 = 0;
            this.CreateSaveMessage(subfolderHandle1, subfolderId1, ref messageId2, ref messageHandle2);
            #endregion

            #region Step 3. The client calls RopCreateFolder to create the search folder [MSOXCFOLDSearchFolder2] under the root folder.

            createFolderRequest.FolderType = (byte)FolderType.Searchfolder;
            createFolderRequest.DisplayName = Encoding.ASCII.GetBytes(Constants.SearchFolder2);
            createFolderRequest.Comment = Encoding.ASCII.GetBytes(Constants.SearchFolder2);
            createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.RootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully!");
            uint searchFolderHandle2 = this.responseHandles[0][createFolderResponse.OutputHandleIndex];
            #endregion

            #region Step 4. The client calls RopSetSearchCriteria to establish search criteria for [MSOXCFOLDSearchFolder2].

            RopSetSearchCriteriaRequest setSearchCriteriaRequest = new RopSetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopSetSearchCriteria,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex
            };
            PropertyTag propertyTag = new PropertyTag
            {
                PropertyId = (ushort)MessagePropertyId.PidTagMessageClass,
                PropertyType = (ushort)PropertyType.PtypString
            };
            ExistRestriction existRestriction = new ExistRestriction
            {
                PropTag = propertyTag
            };
            setSearchCriteriaRequest.RestrictionDataSize = (ushort)existRestriction.Size();
            setSearchCriteriaRequest.RestrictionData = existRestriction.Serialize();
            setSearchCriteriaRequest.FolderIds = new ulong[] { subfolderId1 };
            setSearchCriteriaRequest.FolderIdCount = (ushort)setSearchCriteriaRequest.FolderIds.Length;
            setSearchCriteriaRequest.SearchFlags = (uint)SetSearchFlags.ContentIndexedSearch | (uint)SetSearchFlags.StaticSearch | (uint)SetSearchFlags.RestartSearch;
            RopSetSearchCriteriaResponse setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, searchFolderHandle2, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, setSearchCriteriaResponse.ReturnValue, "RopSearchCriteria ROP operation performs successfully!");

            #endregion

            #region Step 5. The client calls RopGetSearchCriteria to obtain the search criteria and the status of the search folder [MSOXCFOLDSearchFolder2].
            RopGetSearchCriteriaRequest getSearchCriteriaRequest = new RopGetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopGetSearchCriteria,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                UseUnicode = 0x00,
                IncludeRestriction = 0x01,
                IncludeFolders = 0x01
            };
            RopGetSearchCriteriaResponse getSearchCriteriaResponse = this.Adapter.GetSearchCriteria(getSearchCriteriaRequest, searchFolderHandle2, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getSearchCriteriaResponse.ReturnValue, "RopGetSearchCriteria ROP operation performs successfully!");

            #region Verify the requirements: MS-OXCFOLD_R1200 and MS-OXCFOLD_R1233.
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1200");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1200
            // SHALLOW_SEARCH bit in the RopSetSearchCriteria ROP request means the search includes only the search folder containers that are specified in the FolderIds field.
            // If the bit SEARCH_RECURSIVE in the RopGetSearchCriteria ROP response is not set means only the search folder containers that are specified in the last RopSetSearchCriteria ROP request are being searched.
            // So, if the bit SEARCH_RECURSIVE in getSearchCriteriaResponse is not set, R1200 can be verified. 
            Site.CaptureRequirementIfAreNotEqual<uint>(
                (uint)GetSearchFlags.Recursive,
                getSearchCriteriaResponse.SearchFlags & (uint)GetSearchFlags.Recursive,
                1200,
                @"[In RopSetSearchCriteria ROP Request Buffer] SearchFlags (4 bytes): If neither bit [RECURSIVE_SEARCH or SHALLOW_SEARCH] is set, the default is SHALLOW_SEARCH.");

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1233");

            List<ulong> folderIdsInGetSearchCriteriaResponse = new List<ulong>();
            folderIdsInGetSearchCriteriaResponse.AddRange(getSearchCriteriaResponse.FolderIds);

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1233
            this.Site.CaptureRequirementIfIsFalse(
                folderIdsInGetSearchCriteriaResponse.Contains(createFolderResponse.FolderId),
                1233,
                @"[In Setting Up a Search Folder] [A search folder cannot be included in its own search scope] Therefore, the FolderIds field MUST NOT include the FID of the search folder.");
            #endregion

            #endregion

            #region Step 6. The client calls RopGetContentsTable to retrieve the contents table for the search folder [MSOXCFOLDSearchFolder2].
            RopGetContentsTableRequest getContentsTableRequest = new RopGetContentsTableRequest();
            RopGetContentsTableResponse getContentsTableResponse;
            getContentsTableRequest.RopId = (byte)RopId.RopGetContentsTable;
            getContentsTableRequest.LogonId = Constants.CommonLogonId;
            getContentsTableRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            getContentsTableRequest.OutputHandleIndex = Constants.CommonOutputHandleIndex;
            getContentsTableRequest.TableFlags = (byte)FolderTableFlags.None;

            int count = 0;
            do
            {
                getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, searchFolderHandle2, ref this.responseHandles);
                Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");
                if (getContentsTableResponse.RowCount != 2)
                {
                    Thread.Sleep(this.WaitTime);
                }
                else
                {
                    break;
                }

                count++;
            }
            while (count < this.RetryCount);

            uint rowCountBeforeHardDel = getContentsTableResponse.RowCount;
            Site.Assert.AreEqual<uint>(2, rowCountBeforeHardDel, "The two general messages created in step 2 were fetched in search folder.");

            #endregion

            #region Step 7. The client calls RopHardDeleteMessage ROP operation to hard delete a message in the general folder [MSOXCFOLDSubfolder1] under the root folder.

            ulong[] messageIds = new ulong[] { messageId1 };
            RopHardDeleteMessagesRequest hardDeleteMessagesRequest = new RopHardDeleteMessagesRequest
            {
                RopId = (byte)RopId.RopHardDeleteMessages,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                WantAsynchronous = 0x00,
                NotifyNonRead = 0x00,
                MessageIdCount = (ushort)messageIds.Length,
                MessageIds = messageIds
            };
            RopHardDeleteMessagesResponse hardDeleteMessagesResponse = this.Adapter.HardDeleteMessages(hardDeleteMessagesRequest, subfolderHandle1, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, hardDeleteMessagesResponse.ReturnValue, "RopHardDeleteMessages ROP operation performs successfully!");
            Site.Assert.AreEqual<uint>(0x00, hardDeleteMessagesResponse.PartialCompletion, "RopHardDeleteMessages ROP operation is complete!");

            #endregion

            #region Step 8. The client calls RopGetContentsTable to retrieve the contents table for the search folder [MSOXCFOLDSearchFolder2].

            count = 0;
            bool searchFolderNotChange = false;
            do
            {
                getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, searchFolderHandle2, ref this.responseHandles);
                Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");
                if (getContentsTableResponse.RowCount != rowCountBeforeHardDel)
                {
                    Thread.Sleep(this.WaitTime);
                }
                else
                {
                    searchFolderNotChange = true;
                    break;
                }

                count++;
            }
            while (count < this.RetryCount);

            #region Verify the requirements: MS-OXCFOLD_R795, MS-OXCFOLD_R784, MS-OXCFOLD_R1084, MS-OXCFOLD_R549, MS-OXCFOLD_R1093, MS-OXCFOLD_R1094.

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R795");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R795
            // The search folder contents didn't change after the message has been hard deleted, it indicates the current search is static search.
            Site.CaptureRequirementIfIsTrue(
                searchFolderNotChange,
                795,
                @"[In RopGetSearchCriteria ROP Response Buffer] SearchFlags (4 bytes): SEARCH_STATIC (0x00010000) means that the search is static.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R784");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R784
            Site.CaptureRequirementIfIsTrue(
                searchFolderNotChange,
                784,
                @"[In RopSetSearchCriteria ROP Request Buffer] SearchFlags (4 bytes): STATIC_SEARCH (0x00040000) means that the search is static, if set.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1084");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1084
            Site.CaptureRequirementIfIsTrue(
                searchFolderNotChange,
                1084,
                @"[In Processing a RopSetSearchCriteria ROP Request] For static search folders, the contents of the search folder are not updated after the initial population is complete.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R549");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R549
            Site.CaptureRequirementIfIsTrue(
                searchFolderNotChange,
                549,
                @"[In Processing a RopSetSearchCriteria ROP Request] A static search causes the search folder to be populated once with all messages that match the search criteria at the point in time when the search is started or restarted.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1093");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1093
            Site.CaptureRequirementIfIsTrue(
                searchFolderNotChange,
                1093,
                @"[In Processing a RopSetSearchCriteria ROP Request] The server MUST NOT update the search folder after the initial population when new messages that match the search criteria arrive in the search scope.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1094");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1094
            Site.CaptureRequirementIfIsTrue(
                searchFolderNotChange,
                1094,
                @"[In Processing a RopSetSearchCriteria ROP Request] Or the server MUST NOT update the search folder after the initial population when existing messages that fit the search criteria are deleted.");

            #endregion

            #endregion

            #region Step 9. The client calls RopSetSearchCriteria to restart the search for [MSOXCFOLDSearchFolder2].

            setSearchCriteriaRequest.SearchFlags = (uint)SetSearchFlags.ContentIndexedSearch | (uint)SetSearchFlags.RestartSearch;
            setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, searchFolderHandle2, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, setSearchCriteriaResponse.ReturnValue, "RopSearchCriteria ROP operation performs successfully!");

            #endregion

            #region Step 10. The client calls RopGetContentsTable to retrieve the contents table for the search folder [MSOXCFOLDSearchFolder2].

            count = 0;
            do
            {
                getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, searchFolderHandle2, ref this.responseHandles);
                Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");
                if (getContentsTableResponse.RowCount != 1)
                {
                    Thread.Sleep(this.WaitTime);
                }
                else
                {
                    break;
                }

                count++;
            }
            while (count < this.RetryCount);

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R551");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R551
            // There should be 1 message found and copy to the search folder, so the RowCount should be 1.
            Site.CaptureRequirementIfAreEqual<uint>(
                1,
                getContentsTableResponse.RowCount,
                551,
                @"[In Processing a RopSetSearchCriteria ROP Request] To trigger an update, another RopSetSearchCriteria ROP request with the RESTART_SEARCH bit set in the SearchFlags field, as specified in section 2.2.1.4.1, is required.");
            #endregion

            #region Step 11. The client calls RopSetSearchCriteria to establish search criteria for [MSOXCFOLDSearchFolder2] by a new RestrictionData.

            setSearchCriteriaRequest = new RopSetSearchCriteriaRequest();
            setSearchCriteriaRequest.RopId = (byte)RopId.RopSetSearchCriteria;
            setSearchCriteriaRequest.LogonId = Constants.CommonLogonId;
            setSearchCriteriaRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            ContentRestriction contentRestriction = new ContentRestriction
            {
                FuzzyLevelLow = FuzzyLevelLowValues.FL_PREFIX,
                FuzzyLevelHigh = FuzzyLevelHighValues.FL_IGNORECASE
            };
            propertyTag = new PropertyTag
            {
                PropertyId = (ushort)MessagePropertyId.PidTagMessageClass,
                PropertyType = (ushort)PropertyType.PtypString
            };
            contentRestriction.PropertyTag = propertyTag;
            TaggedPropertyValue taggedProperty = new TaggedPropertyValue
            {
                PropertyTag = propertyTag,
                Value = Encoding.Unicode.GetBytes("IPM.Task" + Constants.StringNullTerminated)
            };
            contentRestriction.TaggedValue = taggedProperty;
            setSearchCriteriaRequest.RestrictionDataSize = (ushort)contentRestriction.Size();
            setSearchCriteriaRequest.RestrictionData = contentRestriction.Serialize();
            setSearchCriteriaRequest.FolderIds = new ulong[] { subfolderId1 };
            setSearchCriteriaRequest.FolderIdCount = (ushort)setSearchCriteriaRequest.FolderIds.Length;
            setSearchCriteriaRequest.SearchFlags = (uint)SetSearchFlags.ContentIndexedSearch | (uint)SetSearchFlags.RestartSearch | (uint)SetSearchFlags.StaticSearch;
            setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, searchFolderHandle2, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, setSearchCriteriaResponse.ReturnValue, "RopSearchCriteria ROP operation performs successfully!");

            #endregion

            #region Step 12. The client calls RopGetContentsTable to retrieve the contents table for the search folder [MSOXCFOLDSearchFolder2].

            count = 0;
            do
            {
                getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, searchFolderHandle2, ref this.responseHandles);
                Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");
                if (getContentsTableResponse.RowCount != 0)
                {
                    Thread.Sleep(this.WaitTime);
                }
                else
                {
                    break;
                }

                count++;
            }
            while (count < this.RetryCount);

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R519");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R519
            // For no message should be found so the search folder should empty, which means the RowCount is 0.
            Site.CaptureRequirementIfAreEqual<uint>(
                0,
                getContentsTableResponse.RowCount,
                519,
                @"[In Processing a RopSetSearchCriteria ROP Request] When new search criteria are applied, the server modifies the search folder to include only the messages that match the new search criteria.");
            #endregion
        }
        public void MSOXCFOLD_S04_TC07_RopEmptyPublicFolder()
        {
            if (!Common.IsRequirementEnabled(97501002, this.Site))
            {
                this.NeedCleanup = false;
                Site.Assert.Inconclusive("The server does not support the RopEmptyFolder ROP ([MS-OXCROPS] section 2.2.4.9) for public folders.");
            }

            this.CheckWhetherSupportTransport();
            this.Logon();
            this.PublicFolderInitialization();

            #region Step 1. The client calls RopCreateFolder to create [MSOXCFOLDSubfolder1] under the root public folder.

            RopCreateFolderRequest createFolderRequest = new RopCreateFolderRequest
            {
                RopId = (byte)RopId.RopCreateFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                FolderType = (byte)FolderType.Genericfolder,
                UseUnicodeStrings = 0x0,
                OpenExisting = 0x01,
                Reserved = 0x0,
                DisplayName = Encoding.ASCII.GetBytes(Constants.Subfolder1),
                Comment = Encoding.ASCII.GetBytes(Constants.Subfolder1)
            };

            RopCreateFolderResponse createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.publicRootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully.");
            uint subfolderHandle1 = this.responseHandles[0][createFolderResponse.OutputHandleIndex];
            #endregion

            #region Step 2. The client creates a message in [MSOXCFOLDSubfolder1].

            uint messageHandle = 0;
            ulong messageId = 0;
            this.CreateSaveMessage(this.publicRootFolderHandle, this.publicRootFolderId, ref messageId, ref messageHandle);

            #endregion

            #region Step 3. The client creates a subfolder in [MSOXCFOLDSubfolder1].

            createFolderRequest.DisplayName = Encoding.ASCII.GetBytes(Constants.Subfolder2);
            createFolderRequest.Comment = Encoding.ASCII.GetBytes(Constants.Subfolder2);

            createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, subfolderHandle1, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully.");
            #endregion

            #region Step 4. The client calls RopEmptyFolder to empty [MSOXCFOLDSubfolder1].

            RopEmptyFolderRequest emptyFolderRequest = new RopEmptyFolderRequest
            {
                RopId = (byte)RopId.RopEmptyFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                WantAsynchronous = 0x00,
                WantDeleteAssociated = 0x00
            };

            // Invoke RopEmptyFolder operation to soft delete Subfolder3 from Subfolder1 without deleting Subfolder1.
            RopEmptyFolderResponse emptyFolderResponse = this.Adapter.EmptyFolder(emptyFolderRequest, subfolderHandle1, ref this.responseHandles);

            Site.Assert.AreEqual<uint>(0, emptyFolderResponse.ReturnValue, "RopEmptyFolder ROP operation performs successfully on [MSOXCFOLDSubfolder1].");

            #endregion

            #region Step 5. The client calls RopGetContentsTable to retrieve the contents table of [MSOXCFOLDSubfolder1].

            RopGetContentsTableRequest getContentsTableRequest = new RopGetContentsTableRequest
            {
                RopId = (byte)RopId.RopGetContentsTable,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                TableFlags = (byte)FolderTableFlags.None
            };

            RopGetContentsTableResponse getContentsTableResponse = this.Adapter.GetContentsTable(getContentsTableRequest, subfolderHandle1, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getContentsTableResponse.ReturnValue, "RopGetContentsTable ROP operation performs successfully!");

            #endregion

            #region Step 6. The client calls RopGetHierarchyTable to retrieve the hierarchy table of [MSOXCFOLDSubfolder1].

            RopGetHierarchyTableRequest getHierarchyTableRequest = new RopGetHierarchyTableRequest
            {
                RopId = (byte)RopId.RopGetHierarchyTable,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                TableFlags = (byte)FolderTableFlags.None
            };

            RopGetHierarchyTableResponse getHierarchyTableResponse = this.Adapter.GetHierarchyTable(getHierarchyTableRequest, subfolderHandle1, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getHierarchyTableResponse.ReturnValue, "RopGetHierarchyTable ROP operation performs successfully!");

            // Add the debug information
            Site.Log.Add(
                LogEntryKind.Debug,
                "Verify MS-OXCFOLD_R97501002: The message count of the target folder after RopEmptyFolder is {0}, the subfolder count of the target folder after RopEmptyFolder is {1}",
                getContentsTableResponse.RowCount,
                getHierarchyTableResponse.RowCount);

            bool isVerifyR97501002 = getContentsTableResponse.RowCount == 0 && getHierarchyTableResponse.RowCount == 0;

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R97501002.
            Site.CaptureRequirementIfIsTrue(
                isVerifyR97501002,
                97501002,
                @"[In Appendix A: Product Behavior] Implementation does support the RopEmptyFolder ROP ([MS-OXCROPS] section 2.2.4.9) for public folders. (Microsoft Exchange Server 2007 and Microsoft Exchange Server 2010 follow this behavior.)");
            #endregion
        }
 /// <summary>
 /// Get row count of a specified folder's contents table.
 /// </summary>
 /// <param name="flags">The TableFlags parameter contains a bitmask of flags that control how information is returned in the table on folder.</param>
 /// <param name="inputHandle">The folder object handle.</param>
 /// <returns>Row count of the specified folder's contents table.</returns>
 protected uint GetContentsTable(FolderTableFlags flags, uint inputHandle)
 {
     RopGetContentsTableRequest request = new RopGetContentsTableRequest
     {
         RopId = (byte)RopId.RopGetContentsTable,
         LogonId = Constants.CommonLogonId,
         InputHandleIndex = Constants.CommonInputHandleIndex,
         OutputHandleIndex = Constants.CommonOutputHandleIndex,
         TableFlags = (byte)flags
     };
     RopGetContentsTableResponse response = this.Adapter.GetContentsTable(request, inputHandle, ref this.responseHandles);
     return response.RowCount;
 }
 /// <summary>
 /// Get the content table of specific folder.
 /// </summary>
 /// <param name="objHandle">The handle of specific folder.</param>
 /// <returns>The handle of content table.</returns>
 protected RopGetContentsTableResponse GetContentTableSuccess(uint objHandle)
 {
     RopGetContentsTableRequest getContentsTableRequest = new RopGetContentsTableRequest()
     {
         RopId = (byte)RopId.RopGetContentsTable,
         LogonId = CommonLogonId,
         InputHandleIndex = CommonInputHandleIndex,
         OutputHandleIndex = CommonOutputHandleIndex,
         TableFlags = (byte)FolderTableFlags.None
     };
     this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(getContentsTableRequest, objHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
     RopGetContentsTableResponse getContentsTableResponse = (RopGetContentsTableResponse)this.response;
     Site.Assert.AreEqual<uint>(TestSuiteBase.Success, getContentsTableResponse.ReturnValue, TestSuiteBase.ROPSucceedMsg);
     return getContentsTableResponse;
 }