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

            #region Step 1. Calls RopEmptyfolder using a logon handle rather than a folder handle.
            RopEmptyFolderRequest emptyFolderRequest = new RopEmptyFolderRequest
            {
                RopId = (byte)RopId.RopEmptyFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                WantAsynchronous = 0x00,
                WantDeleteAssociated = 0xFF
            };

            // Using a logon object handle to refer a logon object in which case is purposed to test error code ecNotSupported [0x80040102].  
            RopEmptyFolderResponse emptyFolderResponse = this.Adapter.EmptyFolder(emptyFolderRequest, this.LogonHandle, ref this.responseHandles);

            #region Verify MS-OXCFOLD_R624 and MS-OXCFOLD_R625.

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

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

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

            // The MS-OXCFOLD_R624 captured error code [ecNotSupported], capture this requirement directly.
            Site.CaptureRequirement(
                625,
                @"[In Processing a RopEmptyFolder ROP Request] When the error code is ecNotSupported, it indicates that the object that this ROP [RopEmptyFolder ROP] was called on is not a Folder object.");
            #endregion

            #endregion

            #region Step 2. 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,
                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 searchFolderHandle1 = this.responseHandles[0][createFolderResponse.OutputHandleIndex];
            #endregion

            #region Step 3. The client calls RopEmptyFolder on the search folder created in step 2.
            emptyFolderResponse = this.Adapter.EmptyFolder(emptyFolderRequest, searchFolderHandle1, ref this.responseHandles);

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R124901.
                // If the client attempt to empty a search folder, the server will return ecNotSupported in the ReturnValue.
                Site.CaptureRequirementIfAreEqual<uint>(
                    0x80040102,
                    emptyFolderResponse.ReturnValue,
                    124901,
                    @"[In Appendix A: Product Behavior] Implementation does return ecNotSupported (0x80040102) in the ReturnValue field of the RopEmptyFolder ROP response buffer, if the client attempts to empty a search folder. (Exchange 2007 and above follow this behavior.)");

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R3012.
                // If the client attempt to empty a search folder, the server will return ecNotSupported in the ReturnValue.
                // Because the error code 0x80040102 has been captured by R124901, so R3012 can be captured directly. 
                Site.CaptureRequirement(
                    3012,
                    @"[In Processing a RopEmptyFolder ROP Request] When the error code is ecNotSupported, it indicates that a folder that this ROP [RopEmptyFolder ROP] was called on is not allowed to be emptied.");
            }
            #endregion

            #region Step 4. The client calls RopOpenFolder to open the root folder.
            uint rootFolderHandle = 0;
            this.OpenFolder(this.LogonHandle, this.DefaultFolderIds[0], ref rootFolderHandle); 
            #endregion

            #region Step 5. The client calls RopEmptyFolder on the root folder.
            emptyFolderResponse = this.Adapter.EmptyFolder(emptyFolderRequest, rootFolderHandle, ref this.responseHandles);

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R124801
                this.Site.CaptureRequirementIfAreNotEqual<uint>(
                    0x80040102,
                    emptyFolderResponse.ReturnValue,
                    124801,
                    @"[In Appendix A: Product Behavior] Implementation does not return ecNotSupported when the RopEmptyFolder ROP is called on the Root folder. <18> Section 3.2.5.9: Exchange 2007 do not return ecNotSupported (0x80040102) when the RopEmptyFolder ROP ([MS-OXCROPS] section 2.2.4.9) is called on the Root folder.");
            }

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R124802
                this.Site.CaptureRequirementIfAreEqual<uint>(
                    0x80040102,
                    emptyFolderResponse.ReturnValue,
                    124802,
                    @"[In Appendix A: Product Behavior] Implementation does return ecNotSupported when the RopEmptyFolder ROP is called on the Root folder. <18> Section 3.2.5.9: Update Rollup 4 for Exchange Server 2010 Service Pack 2 (SP2), Exchange 2013 and Exchange 2016 return ecNotSupported when the RopEmptyFolder ROP is called on the Root folder.");
            }
            #endregion
        }
        /// <summary>
        /// Create a folder and return the folder handle created.
        /// </summary>
        /// <param name="serverId">A 32-bit signed integer represent the Identity of server.</param>
        /// <param name="objHandleIndex">The server object handle index.</param>
        /// <param name="folderName">The new folder's name.</param>
        /// <param name="folderIdIndex">The folder id index.</param>
        /// <param name="folderHandleIndex">The new folder's handle index.</param>
        /// <returns>Indicate the result of this ROP operation.</returns>
        public RopResult CreateFolder(int serverId, int objHandleIndex, string folderName, out int folderIdIndex, out int folderHandleIndex)
        {
            // Initialize return value.
            folderIdIndex = -1;
            folderHandleIndex = -1;
            uint objHandle = this.handleContainer[objHandleIndex];
            RopResult result = RopResult.InvalidParameter;
            byte[] getName = Encoding.ASCII.GetBytes(folderName + AdapterHelper.GetFolderNameIndex() + "\0");

            // Construct ROP request.
            RopCreateFolderRequest createFolderRequest = new RopCreateFolderRequest
            {
                RopId = 0x1C,
                LogonId = 0x00,
                InputHandleIndex = 0x00,
                OutputHandleIndex = 0x01,
                FolderType = 0x01,
                UseUnicodeStrings = 0x00,
                OpenExisting = 0x01,
                Reserved = 0x00,
                DisplayName = getName,
                Comment = getName
            };

            // Send request and get response data.
            RopCreateFolderResponse createFolderResponse = (RopCreateFolderResponse)this.Process(serverId, createFolderRequest, objHandle);
            result = (RopResult)createFolderResponse.ReturnValue;

            if (result == RopResult.Success)
            {
                folderIdIndex = AdapterHelper.GetObjectIdIndex();
                this.objectIdContainer.Add(folderIdIndex, (ulong)createFolderResponse.FolderId);
                folderHandleIndex = AdapterHelper.GetHandleIndex();
                this.handleContainer.Add(folderHandleIndex, this.responseSOHs[createFolderResponse.OutputHandleIndex]);
                result = RopResult.Success;
                return result;
            }

            return result;
        }
Пример #3
0
        /// <summary>
        /// Initialize a generic folder under inbox as a root folder for test.
        /// </summary>
        protected void GenericFolderInitialization()
        {
            RopLogonResponse logonResponse = this.Logon(LogonFlags.Private, out this.logonHandle);

            #region Open the inbox folder.
            RopOpenFolderRequest openFolderRequest = new RopOpenFolderRequest
            {
                RopId = (byte)RopId.RopOpenFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                FolderId = logonResponse.FolderIds[Constants.InboxIndex],
                OpenModeFlags = (byte)FolderOpenModeFlags.OpenSoftDeleted
            };

            // Use the logon object as input handle here.
            RopOpenFolderResponse openFolderResponse = this.Adapter.OpenFolder(openFolderRequest, this.LogonHandle, ref this.responseHandles);
            this.inboxFolderHandle = this.responseHandles[0][openFolderResponse.OutputHandleIndex];
            #endregion

            #region Create a generic folder for test.
            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 = 0x01;
            createFolderRequest.UseUnicodeStrings = 0x0;
            createFolderRequest.OpenExisting = 0x01;
            createFolderRequest.Reserved = 0x0;
            createFolderRequest.DisplayName = Encoding.ASCII.GetBytes(this.RootFolder);
            createFolderRequest.Comment = Encoding.ASCII.GetBytes(this.RootFolder);
            createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.inboxFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, createFolderResponse.ReturnValue, "Creating Folder should succeed.");
            this.rootFolderHandle = this.responseHandles[0][createFolderResponse.OutputHandleIndex];
            this.rootFolderId = createFolderResponse.FolderId;
            this.isRootFolderCreated = true;
            #endregion
        }
        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_S03_TC03_RopSetSearchCriteriaSuccess()
        {
            this.CheckWhetherSupportTransport();
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            this.GenericFolderInitialization();

            #region Step 1. The client create a non-FAI message under the root folder.

            ulong messageId = 0;
            uint messageHandle = 0;
            this.CreateSaveMessage(this.RootFolderHandle, this.RootFolderId, ref messageId, ref messageHandle);

            #endregion

            #region Step 2. The client calls RopCreateFolder to create a 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 = 0x02,
                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 3. The client calls RopSetSearchCriteria to establish search criteria for [MSOXCFOLDSearchFolder1].

            ulong[] folderIds = new ulong[]
            {
                this.DefaultFolderIds[0]
            };
            RopSetSearchCriteriaRequest setSearchCriteriaRequest = new RopSetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopSetSearchCriteria,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                RestrictionDataSize = 0x0005
            };
            byte[] restrictionData = { 0x08, 0x1f, 0x00, 0x1a, 0x00 };
            setSearchCriteriaRequest.RestrictionData = restrictionData;
            setSearchCriteriaRequest.FolderIdCount = (ushort)folderIds.Length;
            setSearchCriteriaRequest.FolderIds = folderIds;
            setSearchCriteriaRequest.SearchFlags = (uint)SetSearchFlags.RestartSearch;

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

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

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

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R98
            Site.CaptureRequirementIfAreEqual<uint>(
                Constants.SuccessCode,
                setSearchCriteriaResponse.ReturnValue,
                98,
                @"[In RopSetSearchCriteria ROP] The RopSetSearchCriteria ROP ([MS-OXCROPS] section 2.2.4.4) establishes search criteria for a search folder.");

            #region Verify the requirements: MS-OXCFOLD_R766, MS-OXCFOLD_R409, and MS-OXCFOLD_R47.

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R766
            Site.CaptureRequirementIfAreEqual<uint>(
                Constants.SuccessCode,
                setSearchCriteriaResponse.ReturnValue,
                766,
                @"[In RopSetSearchCriteria ROP Request Buffer] SearchFlags (4 bytes): RESTART_SEARCH (0x00000002) means that the search is initiated, if this is the first RopSetSearchCriteria ROP request.");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R409
            Site.CaptureRequirementIfAreEqual<uint>(
                Constants.SuccessCode,
                setSearchCriteriaResponse.ReturnValue,
                409,
                @"[In Setting Up a Search Folder] The client creates a search folder by using the RopCreateFolder ROP ([MS-OXCROPS] section 2.2.4.2) with the FolderType field set to the value 2, as specified in section 2.2.1.2.1.");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R47
            Site.CaptureRequirementIfAreEqual<uint>(
                Constants.SuccessCode,
                setSearchCriteriaResponse.ReturnValue,
                47,
                @"[InRopCreateFolder ROP Request Buffer] FolderType (1 byte): The value 2 indicates the folder type is Search folder.");

            #endregion

            #endregion

            #region Step 4. 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_R1200, MS-OXCFOLD_R772.

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1200
            Site.CaptureRequirementIfAreEqual<ushort>(
                (ushort)folderIds.Length,
                getSearchCriteriaResponse.FolderIdCount,
                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
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R772");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R772
            Site.CaptureRequirementIfAreEqual<ushort>(
                (ushort)folderIds.Length,
                getSearchCriteriaResponse.FolderIdCount,
                772,
                @"[In RopSetSearchCriteria ROP Request Buffer] SearchFlags (4 bytes): SHALLOW_SEARCH (0x00000008) means that the search includes only the search folder containers that are specified in the FolderIds field.");

            #endregion
            #endregion

            #region Step 5. The client calls RopSetSearchCriteria with no folder ID specified for search folder [MSOXCFOLDSearchFolder1] which is initialized in previous request.
            setSearchCriteriaRequest = new RopSetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopSetSearchCriteria,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                RestrictionData = restrictionData,
                SearchFlags = (uint)SetSearchFlags.RestartSearch,
                FolderIdCount = 0,
                FolderIds = null
            };
            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 [MSOXCFOLDSearchFolder1].

            getSearchCriteriaRequest = new RopGetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopGetSearchCriteria,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                UseUnicode = 0x00,
                IncludeRestriction = 0x01,
                IncludeFolders = 0x01
            };

            RopGetSearchCriteriaResponse getSearchCriteriaResponseForNoFolderID = 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
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1241");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1241
            this.Site.CaptureRequirementIfIsTrue(
                this.CompareFolderIDs(getSearchCriteriaResponse.FolderIds, getSearchCriteriaResponseForNoFolderID.FolderIds),
                1241,
                @"[In Processing a RopSetSearchCriteria ROP Request] If the client does not specify FIDs in a subsequent RopSetSearchCriteria ROP request, the server uses the FIDs that were specified in the previous request.");
            #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_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_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_S04_TC01_PublicFolderNonGhostedFolderValidation()
        {
            this.CheckWhetherSupportTransport();
            this.Logon();
            this.PublicFolderInitialization();

            RopCreateFolderRequest createFolderRequest;
            RopCreateFolderResponse createFolderResponse;

            #region Step 1. The client calls RopCreateFolder to create a search folder named [MSOXCFOLDSearchFolder1] under the root public folder.
            createFolderRequest = new RopCreateFolderRequest()
            {
                RopId = (byte)RopId.RopCreateFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                FolderType = (byte)FolderType.Searchfolder,
                UseUnicodeStrings = 0x0,
                OpenExisting = 0x01,
                Reserved = 0x0,
                DisplayName = Encoding.ASCII.GetBytes(Constants.SearchFolder),
                Comment = Encoding.ASCII.GetBytes(Constants.SearchFolder)
            };
            object response = null;
            uint result = this.Adapter.DoRopCall(createFolderRequest, this.publicRootFolderHandle, ref response, ref this.responseHandles);

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R10660201
                Site.CaptureRequirementIfAreEqual<uint>(
                    0x80004005,
                    result,
                    10660201,
                    @"[In Appendix A: Product Behavior] If the ROP was called to create a search folder on a public folders message store, the implemetation does return ecError <12> Section 3.2.5.2:  Exchange 2010 and Exchange 2007 return ecError.");
            }

            if (Common.IsRequirementEnabled(10660202, this.Site))
            {
                createFolderResponse = (RopCreateFolderResponse)response;

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R10660202
                Site.CaptureRequirementIfAreEqual<uint>(
                    0x80040102,
                    createFolderResponse.ReturnValue,
                    10660202,
                    @"[In Appendix A: Product Behavior] If the ROP was called to create a search folder on a public folders message store, the implemetation does return ecNotSupported. <12> Exchange 2013 and Exchange 2016 return ecNotSupported.");
            }
            #endregion

            #region Step 2. The client calls RopCreateFolder to create a generic folder named [MSOXCFOLDSubfolder1].

            uint subfolderHandle1 = 0;
            ulong subfolderId1 = 0;
            createFolderResponse = this.CreateFolder(this.publicRootFolderHandle, Constants.Subfolder1, ref subfolderId1, ref subfolderHandle1);

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R3802
            Site.CaptureRequirementIfAreEqual<uint>(
                Constants.SuccessCode,
                createFolderResponse.ReturnValue,
                3802,
                @"[In RopCreateFolder ROP] The folder can be either a public folder [or a private mailbox folder].");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R61.
            Site.CaptureRequirementIfAreEqual<byte>(
                0x00,
                createFolderResponse.IsExistingFolder,
                61,
                @"[RopCreateFolder ROP Response Buffer] IsExistingFolder (1 byte): The value is zero (FALSE) if a public folder with that name does not exist.");

            byte isExistingFolder = createFolderResponse.IsExistingFolder;
            bool isHasRulesInExistingFolder = createFolderResponse.HasRules == null;
            bool isIsGhostedInExistingFolder = createFolderResponse.IsGhosted == null;
            #endregion

            #region Step 3. The client calls RopOpenFolder to open folder named [MSOXCFOLDSubfolder1].
            RopOpenFolderRequest openFolderRequest = new RopOpenFolderRequest
            {
                RopId = (byte)RopId.RopOpenFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                OpenModeFlags = (byte)FolderOpenModeFlags.None,
                FolderId = subfolderId1
            };
            RopOpenFolderResponse openFolderResponse = this.Adapter.OpenFolder(openFolderRequest, this.publicLogonHandle, ref this.responseHandles);

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R90002
            Site.CaptureRequirementIfAreEqual<uint>(
                Constants.SuccessCode,
                openFolderResponse.ReturnValue,
                90002,
                @"[In RopOpenFolder ROP] The folder can be either a public folder [or a private mailbox folder].");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R30
            Site.CaptureRequirementIfIsNotNull(
                openFolderResponse.IsGhosted,
                30,
                @"[In RopOpenFolder ROP Response Buffer] IsGhosted (1 byte): This field [IsGhosted] is present only for folders that are in a public store.");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R29.
            Site.CaptureRequirementIfAreEqual<byte?>(
                0x00,
                openFolderResponse.IsGhosted,
                29,
                @"[In RopOpenFolder ROP Response Buffer] IsGhosted (1 byte): otherwise [If the server hosts an active replica of the folder], this field [IsGhosted] is set to zero (FALSE).");
            #endregion

            #region Step 4. The client calls RopCreateFolder to create [MSOXCFOLD_PublicFolderMailEnabled] which is an existing folder with 'OpeningExisting' flag set to non-zero.

            string folderDisplayName = Common.GetConfigurationPropertyValue("MailEnabledPublicFolder", this.Site) + Constants.StringNullTerminated;
            createFolderRequest = new RopCreateFolderRequest()
            {
                RopId = (byte)RopId.RopCreateFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                FolderType = (byte)FolderType.Genericfolder,
                UseUnicodeStrings = 0x1,
                OpenExisting = 0x01,
                Reserved = 0x0,
                DisplayName = Encoding.Unicode.GetBytes(folderDisplayName),
                Comment = Encoding.Unicode.GetBytes(folderDisplayName)
            };

            // Invoke the CreateFolder operation with valid parameters, use root folder handle to indicate that the new folder will be created under the root folder.
            createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.publicFoldersHandle, ref this.responseHandles);

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

            subfolderHandle1 = this.responseHandles[0][createFolderResponse.OutputHandleIndex];
 
            if (Common.IsRequirementEnabled(60001, this.Site))
            {
                // Regardless of the existence of the named public folder, if the IsExistingFolder in response is always set to zero, R60001 can be verified.
                bool isR60001Verified = isExistingFolder == 0 && createFolderResponse.IsExistingFolder == 0;
                
                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R60001, regardless of the existence of the public folder, the IsExistingFolder in response should be always set to {0}, actually, when public folder exists the IsExistingFolder in response is {1}, when public folder does not exist the IsExistingFolder in response is {2}.", 0, createFolderResponse.IsExistingFolder, isExistingFolder);

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R60001
                Site.CaptureRequirementIfIsTrue(
                    isR60001Verified,
                    60001,
                    @"[In Appendix A: Product Behavior] Implementation does return zero (FALSE) in the IsExistingFolder field regardless of the existence of the named public folder. <3> Section 2.2.1.2.2: Exchange 2010 Exchange 2013 and Exchange 2016 always return zero (FALSE) in the IsExistingFolder field regardless of the existence of the named public folder.");
            }

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R60002.
                Site.CaptureRequirementIfAreNotEqual<byte>(
                    0x00,
                    createFolderResponse.IsExistingFolder,
                    60002,
                    @"[In Appendix A: Product Behavior] If a public folder with the name given by the DisplayName field of the request buffer already exists, implementation does set a nonzero (TRUE) value to IsExistingFolder field. (Microsoft Exchange Server 2007 follows this behavior.)");

                bool isHasRules = createFolderResponse.HasRules != null;
                bool isIsGhosted = createFolderResponse.IsGhosted != null;
                bool isR926Verified = isHasRules && isHasRulesInExistingFolder;
                bool isR931Verified = isIsGhosted && isIsGhostedInExistingFolder;

                // Add the debug information.
                Site.Log.Add(
                    LogEntryKind.Debug,
                    @"Verify MS-OXCFOLD_R926: When the IsExistingFolder field is set to a zero, the compare result of HasRules and null is {0}; When the IsExistingFolder field is set to a nonzero, the compare result of HasRules and null is {1}",
                    isHasRulesInExistingFolder,
                    isHasRules);

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R926.
                Site.CaptureRequirementIfIsTrue(
                    isR926Verified,
                    926,
                    @"[In RopCreateFolder ROP Response Buffer] This field [HasRules] is present only if the IsExistingFolder field is set to a nonzero (TRUE) value.");

                // Add the debug information.
                Site.Log.Add(
                    LogEntryKind.Debug,
                    @"Verify MS-OXCFOLD_R931: When the IsExistingFolder field is set to a zero, the compare result of IsGhosted and null is {0}; When the IsExistingFolder field is set to a nonzero, the compare result of IsGhosted and null is {1}",
                    isIsGhostedInExistingFolder,
                    isIsGhosted);

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R931.
                Site.CaptureRequirementIfIsTrue(
                    isR931Verified,
                    931,
                    @"[In RopCreateFolder ROP Response Buffer] This field [IsGhosted] is present only if the IsExistingFolder field is set to a nonzero (TRUE) value and only for folders that are in a public message store.");

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R68.
                Site.CaptureRequirementIfAreEqual<byte?>(
                    0x00,
                    createFolderResponse.IsGhosted,
                    68,
                    @"[In RopCreateFolder ROP Response Buffer] IsGhosted (1 byte): otherwise [If the server hosts an active replica of the folder], this field [IsGhosted] is set to zero (FALSE).");
            }
            #endregion

            #region Step 5. The client gets the PidTagAddressBookEntryId property of the [MSOXCFOLD_PublicFolderMailEnabled].
            if (Common.IsRequirementEnabled(350002, this.Site))
            {
                PropertyTag[] propertyTagArray = new PropertyTag[1];
                PropertyTag propertyTag = new PropertyTag
                {
                    PropertyId = (ushort)FolderPropertyId.PidTagAddressBookEntryId,
                    PropertyType = (ushort)PropertyType.PtypBinary
                };
                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!");

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R350002.
                // The property value is returned if Flag value is 0x00.
                Site.CaptureRequirementIfAreEqual<byte>(
                    0x00,
                    getPropertiesSpecificResponse.RowData.Flag,
                    350002,
                    @"[In Appendix A: Product Behavior] The implementation does support the PidTagAddressBookEntryId property. (Exchange 2007 and Exchange 2010 follow this behavior).");

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R350.
                // The property value is returned if Flag value is 0x00.
                Site.CaptureRequirementIfAreEqual<byte>(
                    0x00,
                    getPropertiesSpecificResponse.RowData.Flag,
                    350,
                    @"[In PidTagAddressBookEntryId Property] This property is set only for public folders.");
            }
            #endregion

            #region Step 6. The client calls RopGetPropertiesAll on [MSOXCFOLD_PublicFolderGhosted].
            RopGetPropertiesAllResponse getAllPropertiesResponse = this.Adapter.GetFolderPropertiesAll(subfolderHandle1, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, getAllPropertiesResponse.ReturnValue, "RopGetPropertiesAllResponse ROP operation performs successfully!");
            #endregion
        }
        public void MSOXCFOLD_S04_TC02_PublicFolderGhostedFolderValidation()
        {
            this.CheckWhetherSupportTransport();
            this.Logon();
            this.PublicFolderInitialization();
            string ghostedPublicFolder = Common.GetConfigurationPropertyValue("GhostedPublicFolder", this.Site) + Constants.StringNullTerminated;

            // The ghosted folder is only supported when the 2nd SUT exists.
            if (Common.GetConfigurationPropertyValue("Sut2ComputerName", this.Site) == string.Empty)
            {
                Site.Assert.Inconclusive("This case runs only when the second system under test exists.");
            }
            else
            {
                #region Step 1. The client calls OpenFolder to open the ghosted public folder.
                ulong ghostedFolderId = this.GetSubfolderIDByName(this.DefaultFolderIds[1], this.publicLogonHandle, ghostedPublicFolder);

                RopOpenFolderRequest openFolderRequest = new RopOpenFolderRequest
                {
                    RopId = 0x02,
                    LogonId = Constants.CommonLogonId,
                    InputHandleIndex = Constants.CommonInputHandleIndex,
                    OutputHandleIndex = Constants.CommonOutputHandleIndex,
                    FolderId = ghostedFolderId
                };
                RopOpenFolderResponse openFolderResponse = this.Adapter.OpenFolder(openFolderRequest, this.publicLogonHandle, ref this.responseHandles);
                Site.Assert.AreEqual<uint>(0, openFolderResponse.ReturnValue, "The open folder operation should succeed.");

                #region Verify requirements.

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R907
                Site.CaptureRequirementIfAreNotEqual<byte?>(
                    0x00,
                    openFolderResponse.IsGhosted,
                    907,
                    @"[In RopOpenFolder ROP Response Buffer] If the server does not host an active replica of the folder, this field [IsGhosted] is set to a nonzero (TRUE) value.");

                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R909, the value of ServerCount is {0}.", openFolderResponse.ServerCount);

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R909.
                // MS-OXCFOLD_R907 was verified and the IsGhosted field is set to a nonzero (TRUE) value, if the ServerCount is not null, MS-OXCFOLD_R909 can be verified.
                Site.CaptureRequirementIfIsNotNull(
                    openFolderResponse.ServerCount,
                    909,
                    @"[In RopOpenFolder ROP Response Buffer] This field [ServerCount] is present only if the IsGhosted field is set to a nonzero (TRUE) value.");

                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R912, the value of CheapServerCount is {0}.", openFolderResponse.CheapServerCount);

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R912
                // The CheapServerCount is not null indicates that it presents.
                Site.CaptureRequirementIfIsNotNull(
                    openFolderResponse.CheapServerCount,
                    912,
                    @"[In RopOpenFolder ROP Response Buffer] This field [CheapServerCount] is present only if the IsGhosted field is set to a nonzero (TRUE) value.");

                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R915, the count of Servers is {0}.", openFolderResponse.Servers.Length);

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R915
                // The Servers is not null indicates that it presents.
                Site.CaptureRequirementIfIsNotNull(
                    openFolderResponse.Servers,
                    915,
                    @"[In RopOpenFolder ROP Response Buffer] This field [Servers] is present only if the IsGhosted field is set to a nonzero (TRUE) value.");

                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R913: The server that has a replica of the folder {0} is {1}", ghostedPublicFolder.Trim(Constants.StringNullTerminated.ToCharArray()), openFolderResponse.Servers[0].Trim(Constants.StringNullTerminated.ToCharArray()));

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R913.
                // The RopOpenFolder ROP response deserialized successfully, MS-OXCFOLD_R913 can be verified directly.
                Site.CaptureRequirement(
                    913,
                    @"[In RopOpenFolder ROP Response Buffer] Servers (variable): An array of null-terminated ASCII strings, each of which specifies a server that has a replica of the folder.");

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R908.
                Site.CaptureRequirementIfAreEqual<int>(
                    openFolderResponse.Servers.Length,
                    (int)openFolderResponse.ServerCount,
                    908,
                    @"[In RopOpenFolder ROP Response Buffer] ServerCount (2 bytes): An integer that specifies the number of servers that have a replica of the folder.");
                #endregion
                #endregion

                #region Step 2. The client calls RopCreateFolder to create a ghosted public folder under the root folder.

                // IsGhosted filed is present only if the IsExistingFolder field is set to a nonzero (TRUE) value and only for folders that are in a public store.
                // If implementation return zero (FALSE) in the IsExistingFolder field when the named folder already exists,
                // IsGhosted field related requirements can't be verified.
                if (Common.IsRequirementEnabled(60002, this.Site))
                {
                    RopCreateFolderRequest createFolderRequest = new RopCreateFolderRequest
                    {
                        RopId = (byte)RopId.RopCreateFolder,
                        LogonId = Constants.CommonLogonId,
                        InputHandleIndex = Constants.CommonInputHandleIndex,
                        OutputHandleIndex = Constants.CommonOutputHandleIndex,
                        FolderType = (byte)FolderType.Genericfolder,
                        UseUnicodeStrings = 0x0,
                        OpenExisting = 0xff,
                        Reserved = 0x0,
                        DisplayName = Encoding.ASCII.GetBytes(ghostedPublicFolder),
                        Comment = Encoding.ASCII.GetBytes(ghostedPublicFolder)
                    };
                    RopCreateFolderResponse createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.publicFoldersHandle, ref this.responseHandles);
                    Site.Assert.AreEqual<uint>(0, createFolderResponse.ReturnValue, "The open folder operation should succeed.");

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

                    // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R929.
                    Site.CaptureRequirementIfAreNotEqual<byte?>(
                        0x00,
                        createFolderResponse.IsGhosted,
                        929,
                        @"[In RopCreateFolder ROP Response Buffer] If the server does not host an active replica of the folder, this field [IsGhosted] is set to a nonzero (TRUE) value.");

                    // Add the debug information
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R933, the value of ServerCount is {0}.", createFolderResponse.ServerCount);

                    // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R933.
                    // MS-OXCFOLD_R929 was verified and the IsGhosted field is set to a nonzero (TRUE) value, if the ServerCount is not null, MS-OXCFOLD_R933 can be verified.
                    Site.CaptureRequirementIfIsNotNull(
                        createFolderResponse.ServerCount,
                        933,
                        @"[In RopCreateFolder ROP Response Buffer] This field [ServerCount] is present only if the IsGhosted field is set to a nonzero (TRUE) value.");

                    // Add the debug information
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R938, the value of CheapServerCount is {0}.", createFolderResponse.CheapServerCount);

                    // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R938.
                    // MS-OXCFOLD_R929 was verified and the IsGhosted field is set to a nonzero (TRUE) value, if the ServerCount is not null, MS-OXCFOLD_R933 can be verified.
                    Site.CaptureRequirementIfIsNotNull(
                        createFolderResponse.CheapServerCount,
                        938,
                        @"[In RopCreateFolder ROP Response Buffer] This field [CheapServerCount] is present only if the IsGhosted field is set to a nonzero (TRUE) value.");

                    // Add the debug information
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R941, the count of Servers is {0}.", createFolderResponse.Servers.Length);

                    // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R941
                    // The Servers is not null indicates that it presents.
                    Site.CaptureRequirementIfIsNotNull(
                        createFolderResponse.Servers,
                        941,
                        @"[In RopCreateFolder ROP Response Buffer] This field [Servers] is present only if the IsGhosted field is set to a nonzero (TRUE) value.");

                    // Add the debug information
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R939: The server that has a replica of the folder {0} is {1}", ghostedPublicFolder.Trim(Constants.StringNullTerminated.ToCharArray()), createFolderResponse.Servers[0].Trim(Constants.StringNullTerminated.ToCharArray()));

                    // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R939.
                    // The RopCreateFolder ROP response deserialized successfully, MS-OXCFOLD_R939 can be verified directly.
                    Site.CaptureRequirement(
                        939,
                        @"[In RopCreateFolder ROP Response Buffer] Servers (variable): An array of null-terminated ASCII strings, each of which specifies a server that has a replica of the folder.");

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

                    // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R932.
                    Site.CaptureRequirementIfAreEqual<int>(
                        createFolderResponse.Servers.Length,
                        (int)createFolderResponse.ServerCount,
                        932,
                        @"[In RopCreateFolder ROP Response Buffer] ServerCount (2 bytes): An integer that specifies the number of servers that have a replica of the folder.");
                    #endregion
                }
                #endregion
            }
        }
        public void MSOXCFOLD_S04_TC03_RopDeletePublicFolder()
        {
            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.");
            ulong subfolderId1 = createFolderResponse.FolderId;
            #endregion

            #region Step 2. The client calls RopDeleteFolder to hard-delete [MSOXCFOLDSubfolder1].

            RopDeleteFolderRequest deleteFolderRequest = new RopDeleteFolderRequest
            {
                RopId = (byte)RopId.RopDeleteFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                DeleteFolderFlags =
                    (byte)DeleteFolderFlags.DelMessages | (byte)DeleteFolderFlags.DelFolders |
                    (byte)DeleteFolderFlags.DeleteHardDelete,
                FolderId = subfolderId1
            };

            RopDeleteFolderResponse deleteFolderResponse = this.Adapter.DeleteFolder(deleteFolderRequest, this.publicRootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, deleteFolderResponse.ReturnValue, "RopDeleteFolder ROP operation performs should successfully.");

            #endregion

            #region Step 3. The client calls RopGetHierarchyTable to retrieve the hierarchy table for the root public folder.

            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, this.publicRootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getHierarchyTableResponse.ReturnValue, "RopGetHierarchyTable ROP operation performs should successfully.");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R94402
            Site.CaptureRequirementIfAreEqual<uint>(
                0,
                getHierarchyTableResponse.RowCount,
                94402,
                @"[In RopDeleteFolder ROP] The folder can be either a public folder [or a private mailbox folder]. ");
            #endregion

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

            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)
            };

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

            #region Step 5. The client calls RopDeleteFolder to soft-delete [MSOXCFOLDSubfolder2].

            deleteFolderRequest = new RopDeleteFolderRequest
            {
                RopId = (byte)RopId.RopDeleteFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                DeleteFolderFlags = (byte)DeleteFolderFlags.None,
                FolderId = subfolderId2
            };

            deleteFolderResponse = this.Adapter.DeleteFolder(deleteFolderRequest, this.publicRootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, deleteFolderResponse.ReturnValue, "RopDeleteFolder ROP operation performs successfully.");

            #endregion
        }
        /// <summary>
        /// Initialize a generic folder under the Inbox folder as a root folder for test.
        /// </summary>
        private void PublicFolderInitialization()
        {
            #region Open the public folder.
            RopOpenFolderRequest openFolderRequest = new RopOpenFolderRequest
            {
                RopId = (byte)RopId.RopOpenFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                FolderId = this.logonResponse.FolderIds[Constants.PublicFolderIndex],
                OpenModeFlags = (byte)FolderOpenModeFlags.None
            };

            // Use the logon object as input handle here.
            RopOpenFolderResponse openFolderResponse = this.Adapter.OpenFolder(openFolderRequest, this.publicLogonHandle, ref this.responseHandles);
            this.publicFoldersHandle = this.responseHandles[0][openFolderResponse.OutputHandleIndex];
            #endregion

            #region Create a generic folder for test.
            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(this.RootFolder),
                Comment = Encoding.ASCII.GetBytes(this.RootFolder)
            };
            RopCreateFolderResponse createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.publicFoldersHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, createFolderResponse.ReturnValue, "Creating Folder should succeed.");
            this.publicRootFolderHandle = this.responseHandles[0][createFolderResponse.OutputHandleIndex];
            this.publicRootFolderId = createFolderResponse.FolderId;
            #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_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
        }
        public void MSOXCFOLD_S03_TC11_RopSetSearchCriteriaFailure()
        {
            this.CheckWhetherSupportTransport();
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            this.GenericFolderInitialization();

            #region Step 1. The client calls RopSetSearchCriteria to establish search criteria for the root folder which is a generic folder rather a search folder.

            ulong[] folderIds = new ulong[]
                {
                    this.DefaultFolderIds[0],
                    this.DefaultFolderIds[1],
                    this.DefaultFolderIds[3],
                    this.DefaultFolderIds[4],
                    this.DefaultFolderIds[5],
                    this.DefaultFolderIds[6],
                    this.DefaultFolderIds[7],
                    this.DefaultFolderIds[8],
                    this.DefaultFolderIds[9],
                    this.DefaultFolderIds[10],
                    this.DefaultFolderIds[11],
                };

            RopSetSearchCriteriaRequest setSearchCriteriaRequest = new RopSetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopSetSearchCriteria,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                RestrictionDataSize = 0x0005
            };
            byte[] restrictionData = { 0x08, 0x1f, 0x00, 0x1a, 0x00 };
            setSearchCriteriaRequest.RestrictionData = restrictionData;
            setSearchCriteriaRequest.FolderIdCount = (ushort)folderIds.Length;
            setSearchCriteriaRequest.FolderIds = folderIds;
            setSearchCriteriaRequest.SearchFlags = (uint)SetSearchFlags.StopSearch;
            RopSetSearchCriteriaResponse setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, this.RootFolderHandle, ref this.responseHandles);

            #region Verify requirements: MS-OXCFOLD_R569, MS-OXCFOLD_R570, and MS-OXCFOLD_R46.

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R569
            Site.CaptureRequirementIfAreEqual<uint>(
                0x00000461,
                setSearchCriteriaResponse.ReturnValue,
                569,
                @"[In Processing a RopSetSearchCriteria ROP Request]The value of error code ecNotSearchFolder is 0x00000461.");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R570
            Site.CaptureRequirementIfAreEqual<uint>(
                0x00000461,
                setSearchCriteriaResponse.ReturnValue,
                570,
                @"[In Processing a RopSetSearchCriteria ROP Request] When the error code is ecNotSearchFolder, it indicates the object is not a search folder.");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R46
            Site.CaptureRequirementIfAreNotEqual<uint>(
                Constants.SuccessCode,
                setSearchCriteriaResponse.ReturnValue,
                46,
                @"[InRopCreateFolder ROP Request Buffer] FolderType (1 byte): The value 1 indicates the folder type is Generic folder.");

            #endregion

            #endregion

            #region Step 2. The client calls RopSetSearchCriteria with a logon object handle rather a search folder handle.

            // Use logon object handle in which case is purposed to get error code ecNotSupported [0x80040102].  
            setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, this.LogonHandle, ref this.responseHandles);

            #region Verify requirement: MS-OXCFOLD_R573, MS-OXCFOLD_R574.

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

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

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

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

            #endregion

            #endregion

            #region Step 3. The client calls RopCreateFolder to create a search folder named [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);
            uint searchFolderHandle = this.responseHandles[0][createFolderResponse.OutputHandleIndex];
            ulong searchFolderID = createFolderResponse.FolderId;
            #endregion

            #region Step 4. The client calls RopSetSearchCriteria use the handle of [MSOXCFOLDSearchFolder1] and a SearchFlags with invalid bit.

            setSearchCriteriaRequest = new RopSetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopSetSearchCriteria,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                RestrictionData = restrictionData,
                SearchFlags = uint.MaxValue,
                FolderIdCount = (ushort)folderIds.Length,
                FolderIds = folderIds
            };
            setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, searchFolderHandle, ref this.responseHandles);

            #region Verify the requirements: MS-OXCFOLD_R116001, MS-OXCFOLD_R1091, MS-OXCFOLD_R1092, and MS-OXCFOLD_R116002.

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R116001
                Site.CaptureRequirementIfAreEqual<uint>(
                    0x80070057,
                    setSearchCriteriaResponse.ReturnValue,
                    116001,
                    @"[In Appendix A: Product Behavior] If the client sets an invalid bit in the SearchFlags field, implementation does fail the RopSetSearchCriteria ROP operation with ecInvalidParam (0x80070057). (Microsoft Exchange 2010 and above follow this behavior.)");

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

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

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1092
                Site.CaptureRequirementIfAreEqual<uint>(
                    0x80070057,
                    setSearchCriteriaResponse.ReturnValue,
                    1092,
                    @"[In Processing a RopSetSearchCriteria ROP Request] When the error code is ecInvalidParam, it indicates the SearchFlags field contains an invalid value.");
            }

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R116002
                Site.CaptureRequirementIfAreNotEqual<uint>(
                    0x80070057,
                    setSearchCriteriaResponse.ReturnValue,
                    116002,
                    @"[In Appendix A: Product Behavior] If the client sets an invalid bit in the SearchFlags field, implementation does not fail the RopSetSearchCriteria ROP operation with ecInvalidParam (0x80070057). <17> Section 3.2.5.4: Exchange 2007 silently ignores invalid bits and does not return the ecInvalidParam error code.");
            }

            #endregion

            #endregion

            #region Step 5. The client calls RopSetSearchCriteria with no folder ID specified for search folder [MSOXCFOLDSearchFolder1] which is not initialized.
            setSearchCriteriaRequest = new RopSetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopSetSearchCriteria,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                RestrictionData = restrictionData,
                SearchFlags = (uint)SetSearchFlags.RestartSearch,
                FolderIdCount = 0,
                FolderIds = null
            };
            setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, searchFolderHandle, ref this.responseHandles);

            #region Verify the requirements: MS-OXCFOLD_R565, MS-OXCFOLD_R566 and MS-OXCFOLD_R1240.

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R565.
            Site.CaptureRequirementIfAreEqual<uint>(
                0x80040605,
                setSearchCriteriaResponse.ReturnValue,
                565,
                @"[In Processing a RopSetSearchCriteria ROP Request] The value of error code ecNotInitialized is 0x80040605.");

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1240: the return value of RopSetSearchCriteria request with no FIDs is {0}", setSearchCriteriaResponse.ReturnValue);

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1240.
            Site.CaptureRequirementIfAreEqual<uint>(
                0x80040605,
                setSearchCriteriaResponse.ReturnValue,
                1240,
                @"[In Processing a RopSetSearchCriteria ROP Request] If the client does not specify FIDs, as specified in ([MS-OXCDATA] section 2.2.1.1), in the initial RopSetSearchCriteria ROP request, the server fails the ROP with ecNotInitialized (0x80040605).");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R566.
            // The clients call RopSetSearchCriteria ROP on a not initialized search folder without setting folder IDs, and the error code 0x80040605 was captured, MS-OXCFOLD_R566 can be verified directly.
            Site.CaptureRequirement(
                566,
                @"[In Processing a RopSetSearchCriteria ROP Request] When the error code is ecNotInitialized, it indicates that no FIDs were specified for this search folder.");
            #endregion
            #endregion

            #region Step 6. The client calls RopSetSearchCriteria with [MSOXCFOLDSearchFolder1] was included in its own search scope.

            setSearchCriteriaRequest = new RopSetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopSetSearchCriteria,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                RestrictionDataSize = 0x0005,
                RestrictionData = restrictionData,
                SearchFlags = (uint)SetSearchFlags.RestartSearch,
                FolderIds = new ulong[] { searchFolderID },
                FolderIdCount = 1,
            };
            #region Verify the requirements: MS-OXCFOLD_R124201, MS-OXCFOLD_R124202, MS-OXCFOLD_R1243 and MS-OXCFOLD_R1244.

            if (Common.IsRequirementEnabled(124201, this.Site))
            {
                setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, searchFolderHandle, ref this.responseHandles);

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R124201
                Site.CaptureRequirementIfAreEqual<uint>(
                    0x00000490,
                    setSearchCriteriaResponse.ReturnValue,
                    124201,
                    @"[In Appendix A: Product Behavior] Implementation does fail the ROP with ecSearchFolderScopeViolation (0x00000490), if the client sets the search scope to include the search folder itself. (Exchange 2013 and above follows this behavior.)");
                
                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1243: the return value of the RopSetSearchCriteria is {0}", setSearchCriteriaResponse.ReturnValue);

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1243
                Site.CaptureRequirementIfAreEqual<uint>(
                    0x00000490,
                    setSearchCriteriaResponse.ReturnValue,
                    1243,
                    @"[In Processing a RopSetSearchCriteria ROP Request] The value of error code ecSearchFolderScopeViolation is 0x00000490.");

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1244
                // The client calls RopSetSearchCriteria with [MSOXCFOLDSearchFolder1] was included in its own search scope, so if the return value is ecSearchFolderScopeViolation, R1244 can be verified.
                Site.CaptureRequirementIfAreEqual<uint>(
                    0x00000490,
                    setSearchCriteriaResponse.ReturnValue,
                    1244,
                    @"[In Processing a RopSetSearchCriteria ROP Request] When the error code is ecSearchFolderScopeViolation, it indicates the search folder was included in its own search scope.");
            }

            if (Common.IsRequirementEnabled(124202, this.Site))
            {
                setSearchCriteriaResponse = this.Adapter.SetSearchCriteria(setSearchCriteriaRequest, searchFolderHandle, ref this.responseHandles);

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R124202
                Site.CaptureRequirementIfAreEqual<uint>(
                    0,
                    setSearchCriteriaResponse.ReturnValue,
                    124202,
                    @"[In Appendix A: Product Behavior] Implementation does not fail the RopSetSearchCriteria ROP when the search folder is included in its own search scope. <16> Section 3.2.5.4:  Exchange 2007, and Exchange 2010 do not fail the RopSetSearchCriteria ROP when the search folder is included in its own search scope.");
            }
            #endregion
            #endregion
        }
        public void MSOXCFOLD_S04_TC05_RopMovePublicFolder()
        {
            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 calls RopCreateFolder to create [MSOXCFOLDSubfolder2] under the root public folder.

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

            createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.publicRootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs should successfully.");
            ulong subfolderId2 = createFolderResponse.FolderId;

            #endregion

            #region Step 3. The client calls RopMoveFolder to move the [MSOXCFOLDSubfolder2] from root public folder to [MSOXCFOLDSubfolder1].
            // Initialize a list of server object handles.
            List<uint> handleList = new List<uint>
            {
                // Add the source folder handle to the list of server object handles, and its index value is 0x00.
                // Add the destination folder handle to the server object handle table, and its index value is 0x01.
                this.publicRootFolderHandle, subfolderHandle1
            };

            RopMoveFolderRequest moveFolderRequest = new RopMoveFolderRequest
            {
                RopId = (byte)RopId.RopMoveFolder,
                LogonId = Constants.CommonLogonId,
                SourceHandleIndex = 0x00,
                DestHandleIndex = 0x01,
                WantAsynchronous = 0x00,
                UseUnicode = 0x01,
                FolderId = subfolderId2,
                NewFolderName = Encoding.Unicode.GetBytes(Constants.Subfolder3)
            };

            RopMoveFolderResponse moveFolderResponse = this.Adapter.MoveFolder(moveFolderRequest, handleList, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, moveFolderResponse.ReturnValue, "The RopMoveFolder operation performs should successfully.");
            handleList.Clear();

            #endregion

            #region Step 4. The client calls RopGetHierarchyTable to retrieve the hierarchy table of the root public folder.

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

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

            #endregion

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

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

            // Add the debug information
            Site.Log.Add(
                LogEntryKind.Debug,
                "Verify MS-OXCFOLD_R17102: The subfolder count of target folder before RopMoveFolder was {0}, The subfolder count of source folder after RopMoveFolder was {1}.",
                getHierarchyTableResponse1.RowCount,
                getHierarchyTableResponse.RowCount);

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R17102
            bool isVerifyR17102 = getHierarchyTableResponse1.RowCount == 2 && getHierarchyTableResponse.RowCount == 1;

            Site.CaptureRequirementIfIsTrue(
                isVerifyR17102,
                17102,
                @"[In RopMoveFolder ROP] The move can be within [a private mailbox] or a public folder, [or between a private mailbox and a public folder].");
            #endregion
        }
        public void MSOXCFOLD_S03_TC13_RestrictionDataValidation()
        {
            this.CheckWhetherSupportTransport();
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            this.GenericFolderInitialization();

            #region Step 1. The client calls RopCreateFolder to create [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 = 0x01,
                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!");
            ulong folderId = createFolderResponse.FolderId;
            uint folderHandle = this.responseHandles[0][createFolderResponse.OutputHandleIndex];

            #endregion

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

            ulong messageId1 = 0;
            uint messageHandle1 = 0;
            this.CreateSaveMessage(folderHandle, folderId, ref messageId1, ref messageHandle1);

            #endregion

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

            createFolderRequest = new RopCreateFolderRequest
            {
                RopId = (byte)RopId.RopCreateFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                FolderType = (byte)FolderType.Searchfolder,
                UseUnicodeStrings = 0x0,
                OpenExisting = 0x01,
                Reserved = 0x0,
                DisplayName = Encoding.ASCII.GetBytes(Constants.SearchFolder),
                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].

            ulong[] folderIds = new ulong[]
            {
                folderId
            };
            RopSetSearchCriteriaRequest 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 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;

            NotRestriction notRestriction = new NotRestriction
            {
                Restricts = contentRestriction
            };

            setSearchCriteriaRequest.RestrictionDataSize = (ushort)notRestriction.Size();
            byte[] restrictionData = notRestriction.Serialize();
            setSearchCriteriaRequest.RestrictionData = restrictionData;
            setSearchCriteriaRequest.FolderIdCount = (ushort)folderIds.Length;
            setSearchCriteriaRequest.FolderIds = folderIds;
            setSearchCriteriaRequest.SearchFlags = (uint)SetSearchFlags.RestartSearch;

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

            #endregion

            #region Step 5. The client calls RopGetSearchCriteria with the UseUnicode field set to 0x01 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 = 0x01,
                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!");
            Restriction restrictTemp = RestrictsFactory.Deserialize(getSearchCriteriaResponse.RestrictionData);
            NotRestriction notRestrictionTemp = (NotRestriction)restrictTemp;
            ContentRestriction contentRestrictionTemp = (ContentRestriction)notRestrictionTemp.Restricts;
            contentRestrictionTemp = (ContentRestriction)notRestrictionTemp.Restricts;
            string str = Encoding.Unicode.GetString(contentRestrictionTemp.TaggedValue.Value);

            #region Verify the requirements: MS-OXCFOLD_R127, MS-OXCFOLD_R137.

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R127
            Site.CaptureRequirementIfAreEqual<string>(
                "IPM.Task" + Constants.StringNullTerminated,
                str,
                127,
                @"[In RopGetSearchCriteria ROP Request Buffer] UseUnicode (1 byte): A Boolean value that is nonzero (TRUE) if the value of the RestrictionData field of the ROP response is to be in Unicode format.");

            #endregion

            #endregion

            #region Step 6. The client calls RopGetSearchCriteria with the UseUnicode field set to 0x00 to obtain the search criteria and the status of the search folder [MSOXCFOLDSearchFolder1].

            getSearchCriteriaRequest.UseUnicode = 0x00;

            getSearchCriteriaResponse = this.Adapter.GetSearchCriteria(getSearchCriteriaRequest, searchFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getSearchCriteriaResponse.ReturnValue, "RopGetSearchCriteria ROP operation performs successfully!");
            restrictTemp = RestrictsFactory.Deserialize(getSearchCriteriaResponse.RestrictionData);
            notRestrictionTemp = (NotRestriction)restrictTemp;
            contentRestrictionTemp = (ContentRestriction)notRestrictionTemp.Restricts;
            str = Encoding.Unicode.GetString(contentRestrictionTemp.TaggedValue.Value);

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R128
            Site.CaptureRequirementIfAreNotEqual<string>(
                "IPM.Task" + Constants.StringNullTerminated,
                str,
                128,
                @"[In RopGetSearchCriteria ROP Request Buffer] UseUnicode (1 byte): [A Boolean value that is] zero (FALSE) otherwise [if the value of the RestrictionData field of the ROP response is not to be in Unicode format].");
            #endregion

            #region Step 7. The client calls RopSetSearchCriteria to restart searching criteria for [MSOXCFOLDSearchFolder1].

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

            #endregion

            #region Step 8. The client calls RopGetSearchCriteria with the UseUnicode field set to 0x00 to obtain the search criteria and the status of the search folder [MSOXCFOLDSearchFolder1].

            getSearchCriteriaRequest.UseUnicode = 0x01;

            getSearchCriteriaResponse = this.Adapter.GetSearchCriteria(getSearchCriteriaRequest, searchFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getSearchCriteriaResponse.ReturnValue, "RopGetSearchCriteria ROP operation performs successfully!");
            restrictTemp = RestrictsFactory.Deserialize(getSearchCriteriaResponse.RestrictionData);
            notRestrictionTemp = (NotRestriction)restrictTemp;
            contentRestrictionTemp = (ContentRestriction)notRestrictionTemp.Restricts;
            str = Encoding.Unicode.GetString(contentRestrictionTemp.TaggedValue.Value);

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

            // Get the portion information of RestrictionData field is this data is same as the data set by the previous RopSetSearchCriteria request, this requirement can be verified. 
            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R105
            Site.CaptureRequirementIfAreEqual<string>(
                "IPM.Task" + Constants.StringNullTerminated,
                str,
                105,
                @"[In RopSetSearchCriteria ROP Request Buffer] RestrictionDataSize (2 bytes): If the value of the RestrictionDataSize field is zero, the search criteria that were used most recently for the search folder container are used again.");
            #endregion
        }
        public void MSOXCFOLD_S04_TC06_RopCopyPublicFolder()
        {
            if (!Common.IsRequirementEnabled(19702002, this.Site))
            {
                this.NeedCleanup = false;
                Site.Assert.Inconclusive("The server does not support the RopCopyFolder ROP ([MS-OXCROPS] section 2.2.4.8) 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 should successfully.");
            uint subfolderHandle1 = this.responseHandles[0][createFolderResponse.OutputHandleIndex];

            #endregion

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

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

            createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.publicRootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs should successfully.");
            ulong subfolderId2 = createFolderResponse.FolderId;

            #endregion

            #region Step 3. The client calls RopCopyFolder to copy the [MSOXCFOLDSubfolder2] from the root public folder to [MSOXCFOLDSubfolder1].
            // Initialize a server object handle table.
            List<uint> handleList = new List<uint>
            {
                this.publicRootFolderHandle, subfolderHandle1
            };

            RopCopyFolderRequest copyFolderRequest = new RopCopyFolderRequest
            {
                RopId = (byte)RopId.RopCopyFolder,
                LogonId = Constants.CommonLogonId,
                SourceHandleIndex = 0x00,
                DestHandleIndex = 0x01,
                WantAsynchronous = 0x00,
                UseUnicode = 0x00,
                WantRecursive = 0xFF,
                FolderId = subfolderId2,
                NewFolderName = Encoding.ASCII.GetBytes(Constants.Subfolder3)
            };

            RopCopyFolderResponse copyFolderResponse = this.Adapter.CopyFolder(copyFolderRequest, handleList, ref this.responseHandles);

            Site.Assert.AreEqual<uint>(Constants.SuccessCode, copyFolderResponse.ReturnValue, "RopCopyFolder ROP operation performs successful!");
            handleList.Clear();

            #endregion

            #region Step 4. 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_R19702002");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R19702002
            Site.CaptureRequirementIfAreEqual<uint>(
                1,
                getHierarchyTableResponse.RowCount,
                19702002,
                @"[In Appendix A: Product Behavior] Implementation does support the  RopCopyFolder ROP ([MS-OXCROPS] section 2.2.4.8) for public folders. (Microsoft Exchange Server 2007 and Microsoft Exchange Server 2010 follow this behavior.)");

            #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_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
        }
        public void MSOXCFOLD_S03_TC17_RopSetSearchCriteriaRegardlessOfSTATIC_SEARCH()
        {
            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] without setting STATIC_SEARCH bit.

            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;
            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!");

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1238001
                Site.CaptureRequirementIfAreEqual<uint>(
                    (uint)GetSearchFlags.Static,
                    getSearchCriteriaResponse.SearchFlags & (uint)GetSearchFlags.Static,
                    1238001,
                    @"[In Appendix A: Product Behavior] Implementation does be regardless of the value of the STATIC_SEARCH bit in the RopSetSearchCriteria ROP request. <14> Section 3.2.5.4:  A content-indexed search is always static on the initial release version of Exchange 2010 and Exchange 2007 regardless of the value of the STATIC_SEARCH bit in the RopSetSearchCriteria request.");
            }

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1238002
                Site.CaptureRequirementIfAreNotEqual<uint>(
                    (uint)GetSearchFlags.Static,
                    getSearchCriteriaResponse.SearchFlags & (uint)GetSearchFlags.Static,
                    1238002,
                    @"[In Appendix A: Product Behavior] Implementation does not be regardless of the value of the STATIC_SEARCH bit in the RopSetSearchCriteria ROP request.(Exchange 2013 and above follow this hebavior).");
            }

            #endregion
        }
Пример #22
0
        /// <summary>
        /// This ROP creates a new subfolder. 
        /// </summary>
        /// <param name="handle">The handle to operate.</param>
        /// <param name="createFolderResponse">The response of this ROP.</param>
        /// <param name="displayName">The name of the created folder. </param>
        /// <param name="comment">The folder comment that is associated with the created folder.</param>
        /// <param name="needVerify">Whether need to verify the response.</param>
        /// <returns>The handle of new folder.</returns>
        private uint RopCreateFolder(uint handle, out RopCreateFolderResponse createFolderResponse, string displayName, string comment, bool needVerify)
        {
            this.rawDataValue = null;
            this.responseValue = null;
            this.responseSOHsValue = null;

            RopCreateFolderRequest createFolderRequest = new RopCreateFolderRequest()
            {
                RopId = (byte)RopId.RopCreateFolder,
                LogonId = LogonId,
                InputHandleIndex = (byte)HandleIndex.FirstIndex,
                OutputHandleIndex = (byte)HandleIndex.SecondIndex,
                FolderType = (byte)FolderType.Genericfolder,
                UseUnicodeStrings = Convert.ToByte(false),
                OpenExisting = Convert.ToByte(true),
                Reserved = ReservedValue,
                DisplayName = Encoding.ASCII.GetBytes(displayName + "\0"),
                Comment = Encoding.ASCII.GetBytes(comment + "\0")
            };

            this.responseSOHsValue = this.ProcessSingleRop(createFolderRequest, handle, ref this.responseValue, ref this.rawDataValue, RopResponseType.SuccessResponse);
            createFolderResponse = (RopCreateFolderResponse)this.responseValue;
            if (needVerify)
            {
                this.Site.Assert.AreEqual((uint)RopResponseType.SuccessResponse, createFolderResponse.ReturnValue, string.Format("RopCreateFolder Failed! Error: 0x{0:X8}", createFolderResponse.ReturnValue));
            }

            return this.responseSOHsValue[0][createFolderResponse.OutputHandleIndex];
        }
        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_S05_TC01_CreateFolderNoCreateSubfolderPermission()
        {
            this.CheckWhetherSupportTransport();
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            this.GenericFolderInitialization();
            uint pidTagMemberRights;

            #region Step 1. Assign access permission for common user on the inbox and the root folder.
            uint inboxHandle = 0;
            this.OpenFolder(this.LogonHandle, this.DefaultFolderIds[this.inboxIndex], ref inboxHandle);

            // Add folder visible permission for the inbox.
            pidTagMemberRights = (uint)PidTagMemberRightsEnum.FolderVisible | (uint)PidTagMemberRightsEnum.ReadAny;
            this.AddPermission(this.commonUserEssdn, pidTagMemberRights, inboxHandle);

            // Add folder visible permission for the root folder.
            pidTagMemberRights = (uint)PidTagMemberRightsEnum.FolderVisible | (uint)PidTagMemberRightsEnum.ReadAny;
            this.AddPermission(this.commonUserEssdn, pidTagMemberRights, this.RootFolderHandle);
            #endregion

            #region Step 2. Use the common user to logon the private mailbox.
            this.Adapter.DoDisconnect();
            this.Adapter.DoConnect(this.sutServer, ConnectionType.PrivateMailboxServer, this.commonUserEssdn, this.domain, this.commonUser, this.commonUserPassword);
            uint logonHandle;
            this.Logon(LogonFlags.Private, out logonHandle, (uint)OpenFlags.UsePerMDBReplipMapping);
            #endregion

            #region Step 3. The common user open the root folder.

            // Find and open the root folder.
            ulong commonUserRootFolderId = this.GetSubfolderIDByName(this.DefaultFolderIds[this.inboxIndex], logonHandle, this.RootFolder);
            uint commonUserRootFolderHandle = 0;
            this.OpenFolder(logonHandle, commonUserRootFolderId, ref commonUserRootFolderHandle);
            #endregion

            #region Step 4. The common user creates [MSOXCFOLDSubfolder1] in the root folder.
            RopCreateFolderRequest createFolderRequest = new RopCreateFolderRequest
            {
                RopId = 0x1C,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                FolderType = 0x01,
                UseUnicodeStrings = 0x0,
                OpenExisting = 0x01,
                Reserved = 0x0,
                DisplayName = Encoding.ASCII.GetBytes(Constants.Subfolder1),
                Comment = Encoding.ASCII.GetBytes(Constants.Subfolder1)
            };
            RopCreateFolderResponse createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, commonUserRootFolderHandle, ref this.responseHandles);

            #region Verify ecNoCreateSubfolderRight.
            if (Common.IsRequirementEnabled(106602, this.Site))
            {
                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R106602");

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R106602.
                Site.CaptureRequirementIfAreEqual<uint>(
                    0x00000502,
                    createFolderResponse.ReturnValue,
                    106602,
                    @"[In Appendix A: Product Behavior] Implementation returns ecNoCreateSubfolderRight if the client does not have permissions to create the folder. <11> Section 3.2.5.2: Exchange 2010 returns ecNoCreateSubfolderRight.");

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1074.
                // MS-OXCFOLD_R106602 captured error code '0x00000502', MS-OXCFOLD_R1074 can be captured directly.
                Site.CaptureRequirement(
                    1074,
                    @"[In Processing a RopCreateFolder ROP Request] The value of error code ecNoCreateSubfolderRight is 0x00000502.");

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1075.
                // MS-OXCFOLD_R106602 captured error code '0x00000502', MS-OXCFOLD_R1075 can be captured directly.
                Site.CaptureRequirement(
                    1075,
                    "[In Processing a RopCreateFolder ROP Request] When the error code is ecNoCreateSubfolderRight, it indicates the client does not have access rights to create the folder.");
            }
            #endregion

            #region Verify error code ecAccessdenied.
            if (Common.IsRequirementEnabled(106601, this.Site))
            {
                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R106601");

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R106601.
                Site.CaptureRequirementIfAreEqual<uint>(
                    0x80070005,
                    createFolderResponse.ReturnValue,
                    106601,
                    @"[In Appendix A: Product Behavior] Implementation returns ecAccessdenied if the client does not have permissions to create the folder. <11> Section 3.2.5.2: Exchange 2007, Exchange 2013 and Exchange 2016 return ecAccessdenied.");

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1071.
                // MS-OXCFOLD_R106601 captured error code '0x80070005', MS-OXCFOLD_R1071 can be captured directly.
                Site.CaptureRequirement(
                    1071,
                    @"[In Processing a RopCreateFolder ROP Request] The value of error code ecAccessdenied is 0x80070005.");

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R489.
                // MS-OXCFOLD_R106601 captured error code '0x80070005', MS-OXCFOLD_R489 can be captured directly.
                Site.CaptureRequirement(
                    489,
                    "[In Processing a RopCreateFolder ROP Request] When the error code is ecAccessDenied, it indicates the client does not have permissions to create the folder.");
            }
            #endregion
            #endregion
        }
        public void MSOXCFOLD_S03_TC04_RopGetSearchCriteriaSuccess()
        {
            this.CheckWhetherSupportTransport();
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            this.GenericFolderInitialization();

            #region Step 1. The client calls RopCreateFolder to create a 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 = 0x02,
                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 2. The client calls RopSetSearchCriteria to establish search criteria for [MSOXCFOLDSearchFolder1].

            ulong[] folderIds = new ulong[]
            {
                this.DefaultFolderIds[0],
                this.DefaultFolderIds[1],
                this.DefaultFolderIds[3],
                this.DefaultFolderIds[4],
                this.DefaultFolderIds[5],
                this.DefaultFolderIds[6],
                this.DefaultFolderIds[7],
                this.DefaultFolderIds[8],
                this.DefaultFolderIds[9],
                this.DefaultFolderIds[10],
                this.DefaultFolderIds[11],
            };
            byte[] restrictionData = { 0x08, 0x1f, 0x00, 0x1a, 0x00 };
            RopSetSearchCriteriaRequest setSearchCriteriaRequest = new RopSetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopSetSearchCriteria,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                RestrictionDataSize = 0x0005,
                RestrictionData = restrictionData,
                FolderIdCount = (ushort)folderIds.Length,
                FolderIds = folderIds,
                SearchFlags = (uint)SetSearchFlags.RestartSearch
            };

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

            #endregion

            #region Step 3. 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!");
            RopGetSearchCriteriaResponse getSearchCriteriaResponse1 = getSearchCriteriaResponse;

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1100.
            // The method GetSearchCriteria succeeds indicates that the server responds with a RopGetSearchCriteria ROP response buffer.
            Site.CaptureRequirement(
                1100,
                @"[In Processing a RopGetSearchCriteria ROP Request] The server responds with a RopGetSearchCriteria ROP response buffer.");

            #region Verify the requirements: MS-OXCFOLD_R129, MS-OXCFOLD_R131, MS-OXCFOLD_R959, MS-OXCFOLD_R2141, MS-OXCFOLD_R1103, and MS-OXCFOLD_R1104.

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R129
            Site.CaptureRequirementIfIsTrue(
                getSearchCriteriaResponse1.RestrictionData != null && getSearchCriteriaResponse1.RestrictionData.Length > 0,
                129,
                @"[In RopGetSearchCriteria ROP Request Buffer] IncludeRestriction (1 byte): A Boolean value that is nonzero (TRUE) if the restriction data is required in the response.");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R131
            Site.CaptureRequirementIfIsTrue(
                getSearchCriteriaResponse1.FolderIds != null && getSearchCriteriaResponse1.FolderIds.Length > 0,
                131,
                @"[In RopGetSearchCriteria ROP Request Buffer] IncludeFolders (1 byte): A Boolean value that is nonzero (TRUE) if the list of folders being searched is required in the response.");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1103
            Site.CaptureRequirementIfIsTrue(
                getSearchCriteriaResponse1.RestrictionData != null && getSearchCriteriaResponse1.RestrictionData.Length > 0,
                1103,
                @"[In Processing a RopGetSearchCriteria ROP Request] The server returns the search criteria only if the IncludeRestriction field of the ROP [RopGetSearchCriteria] request buffer is set to nonzero (TRUE), as specified in section 2.2.1.5.1.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1104, the count of folders that are being searched is {0}.", getSearchCriteriaResponse1.FolderIds.Length);

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1104
            bool isVerifyR1104 = getSearchCriteriaResponse1.FolderIds.Length > 0;

            Site.CaptureRequirementIfIsTrue(
                isVerifyR1104,
                1104,
                @"[In Processing a RopGetSearchCriteria ROP Request] The server returns a list of the folders that are being searched only if the IncludeFolders field of the ROP [RopGetSearchCriteria] request buffer is set to nonzero (TRUE).");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R959, field RestrictionData is {0}, the value of the RestrictionDataSize field is {1}.", getSearchCriteriaResponse1.RestrictionData, getSearchCriteriaResponse1.RestrictionDataSize);

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R959
            bool isVerifyR959 = getSearchCriteriaResponse1.RestrictionDataSize != 0 && getSearchCriteriaResponse1.RestrictionData != null && getSearchCriteriaResponse1.RestrictionData.Length > 0;

            Site.CaptureRequirementIfIsTrue(
                isVerifyR959,
                959,
                @"[In RopGetSearchCriteria ROP Response Buffer] This field [RestrictionData] is present only if the value of the RestrictionDataSize field is nonzero (TRUE).");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R2141, the field FolderIds is {0}, the value of the FolderIdCount field is {1}.", getSearchCriteriaResponse1.FolderIds, getSearchCriteriaResponse1.FolderIdCount);

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R2141
            bool isVerifyR2141 = getSearchCriteriaResponse1.FolderIdCount != 0 && getSearchCriteriaResponse1.FolderIds != null && getSearchCriteriaResponse1.FolderIds.Length > 0;

            Site.CaptureRequirementIfIsTrue(
                isVerifyR2141,
                2141,
                @"[InRopGetSearchCriteria ROP Response Buffer] This field [FolderIds] is present only if the value of the FolderIdCount field is nonzero (TRUE).");

            #endregion

            #endregion

            #region Step 4. The client calls RopGetSearchCriteria to obtain the search criteria and the status of the search folder [MSOXCFOLDSearchFolder1] without setting IncludeRestriction and IncludeFolders.

            getSearchCriteriaRequest.IncludeRestriction = 0x00;
            getSearchCriteriaRequest.IncludeFolders = 0x00;

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

            #region Verify the requirements: MS-OXCFOLD_R130, MS-OXCFOLD_R132, MS-OXCFOLD_R136, and MS-OXCFOLD_R139.

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R130
            Site.CaptureRequirementIfIsNull(
                getSearchCriteriaResponse2.RestrictionData,
                130,
                @"[In RopGetSearchCriteria ROP Request Buffer] IncludeRestriction (1 byte): [A Boolean value that is] zero (FALSE) otherwise [if the restriction data is not required in the response].");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R132
            Site.CaptureRequirementIfIsNull(
                getSearchCriteriaResponse2.FolderIds,
                132,
                @"[In RopGetSearchCriteria ROP Request Buffer] IncludeFolders (1 byte): [A Boolean value that is] zero (FALSE) otherwise [if the list of folders being searched is not required in the response].");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R136
            Site.CaptureRequirementIfAreEqual<ushort>(
                0,
                getSearchCriteriaResponse2.RestrictionDataSize,
                136,
                @"[InRopGetSearchCriteria ROP Response Buffer] RestrictionDataSize (2 bytes): If the IncludeRestriction field of the request buffer was set to zero (FALSE), the value of RestrictionDataSize will be 0.");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R139
            Site.CaptureRequirementIfAreEqual<ushort>(
                0,
                getSearchCriteriaResponse2.FolderIdCount,
                139,
                @"[InRopGetSearchCriteria ROP Response Buffer] FolderIdCount (2 bytes): If the IncludeFolders field of the request buffer was set to zero (FALSE), the FolderIdCount field will be set to 0.");

            #endregion

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

            #region Step 1. The client calls RopCreateFolder to create [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];

            #endregion

            #region Step 2. The client calls RopCreateFolder to create [MSOXCFOLDSubfolder2] folder 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>(Constants.SuccessCode, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully!");
            uint subfolderHandle2 = this.responseHandles[0][createFolderResponse.OutputHandleIndex];

            #endregion

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

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

            createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, subfolderHandle2, ref this.responseHandles);

            Site.Assert.AreEqual<uint>(Constants.SuccessCode, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully!");
            ulong subfolderId3 = createFolderResponse.FolderId;
            #endregion

            #region Step 4. The client calls RopCreateFolder to create [MSOXCFOLDSubfolder4] folder under root folder.

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

            createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.RootFolderHandle, ref this.responseHandles);

            Site.Assert.AreEqual<uint>(Constants.SuccessCode, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully!");
            #endregion

            #region Step 5. The client calls RopGetHierarchyTable to retrieve the hierarchy table for the root folder with 'TableFlags' set as 'None'.

            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, this.RootFolderHandle, 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_R1160");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1160.
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(RopGetHierarchyTableResponse),
                getHierarchyTableResponse.GetType(),
                1160,
                @"[In Processing a RopGetHierarchyTable ROP Request] The server responds with a RopGetHierarchyTable ROP response buffer.");

            #region Verify the requirements: MS-OXCFOLD_R802, MS-OXCFOLD_R318, and MS-OXCFOLD_R1163.

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R318
            // There has 2 folders directly under the root folder, so the RowCount should be 2.
            Site.CaptureRequirementIfAreEqual<uint>(
                0x00000002,
                getHierarchyTableResponse.RowCount,
                318,
                @"[In RopGetHierarchyTable ROP Response Buffer] RowCount (4 bytes): An integer that specifies the number of rows in the hierarchy table.");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R802
            // There has 2 folders directly under the root folder, so the RowCount should be 2.
            Site.CaptureRequirementIfAreEqual<uint>(
                0x00000002,
                getHierarchyTableResponse.RowCount,
                802,
                @"[In RopGetHierarchyTable ROP Request Buffer] TableFlags (1 byte): If this bit [Depth (0x04)] is not set, the hierarchy table lists only the folder's immediate child folders.");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1163
            Site.CaptureRequirementIfAreEqual<uint>(
                0x00000002,
                getHierarchyTableResponse.RowCount,
                1163,
                @"[In Processing a RopGetHierarchyTable ROP Request] The server returns a hierarchy table on which table operations can be performed.");

            #endregion

            #endregion

            #region Step 6. The client calls RopGetHierarchyTable to retrieve the hierarchy table for the root folder with 'TableFlags' set as 'Depth'.

            getHierarchyTableRequest.TableFlags = (byte)FolderTableFlags.Depth;
            getHierarchyTableResponse = this.Adapter.GetHierarchyTable(getHierarchyTableRequest, this.RootFolderHandle, ref this.responseHandles);

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

            #region Verify the requirements: MS-OXCFOLD_R648, MS-OXCFOLD_R801 and MS-OXCFOLD_R100002.

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R801
            // There has total 4 folders under the root folder, so the RowCount should be 4. 
            Site.CaptureRequirementIfAreEqual<uint>(
                0x00000004,
                getHierarchyTableResponse.RowCount,
                801,
                @"[In RopGetHierarchyTable ROP Request Buffer] TableFlags (1 byte): If this bit [Depth (0x04)] is set, the hierarchy table lists folders from all levels under the folder.");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R100002
            Site.CaptureRequirementIfAreEqual<uint>(
                Constants.SuccessCode,
                getHierarchyTableResponse.ReturnValue,
                100002,
                @"[In RopGetHierarchyTable ROP] The folder can be either [a public folder or] a private mailbox folder.");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R648.
            // MS-OXCFOLD_R801 is verified, the current user is the owner of the root folder and its subfolders, MS-OXCFOLD_R648 can be verified directly.
            Site.CaptureRequirement(
                648,
                @"[In Processing a RopGetHierarchyTable ROP Request]The Table object that is returned MUST allow access to the subfolders of the Folder object on which the RopGetHierarchyTable ROP is executed.");

            #endregion

            #endregion

            #region Step 7. The client calls RopGetHierarchyTable to retrieve the hierarchy table for the [MSOXCFOLDSubfolder2].

            getHierarchyTableRequest.TableFlags = (byte)FolderTableFlags.SoftDeletes | (byte)FolderTableFlags.Depth;
            getHierarchyTableResponse = this.Adapter.GetHierarchyTable(getHierarchyTableRequest, subfolderHandle2, ref this.responseHandles);

            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getHierarchyTableResponse.ReturnValue, "RopGetHierarchyTable ROP operation performs successfully!");
            Site.Assert.AreEqual<uint>(0x0000, getHierarchyTableResponse.RowCount, "Cannot get any folder if the folder has not been soft-deleted.");

            #endregion

            #region Step 8. The client calls RopDeleteFolder to soft-delete [MSOXCFOLDSubfolder3] under the root folder.

            RopDeleteFolderRequest deleteFolderRequest = new RopDeleteFolderRequest
            {
                RopId = (byte)RopId.RopDeleteFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                DeleteFolderFlags = (byte)DeleteFolderFlags.DelFolders | (byte)DeleteFolderFlags.DelMessages,
                FolderId = subfolderId3
            };
            RopDeleteFolderResponse deleteFolderResponse = this.Adapter.DeleteFolder(deleteFolderRequest, subfolderHandle2, ref this.responseHandles);

            Site.Assert.AreEqual<uint>(0, deleteFolderResponse.ReturnValue, "RopDeleteFolder ROP operation performs successfully!");
            Site.Assert.AreEqual<byte>(0x00, deleteFolderResponse.PartialCompletion, "RopDeleteFolder ROP operation is complete.");

            #endregion

            #region Step 9. The client calls RopGetHierarchyTable to retrieve the hierarchy table for the [MSOXCFOLDSubfolder2] after it has been soft-deleted.

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

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R806.
                // There has 1 folder softed deleted, so the RowCount should be 1.
                Site.CaptureRequirementIfAreEqual<uint>(
                    0x0001,
                    getHierarchyTableResponse.RowCount,
                    806,
                    @"[In RopGetHierarchyTable ROP Request Buffer] TableFlags (1 byte): If this bit [SoftDeletes (0x20)] is set, the hierarchy table lists only the folders that are soft deleted.");
            }
            #endregion

            #region Step 10. The client calls RopGetHierarchyTable with setting the 'UseUnicode' TableFlags to retrieve the hierarchy table for the root folder.

            getHierarchyTableRequest.TableFlags = (byte)FolderTableFlags.Depth | (byte)FolderTableFlags.UseUnicode;
            getHierarchyTableResponse = this.Adapter.GetHierarchyTable(getHierarchyTableRequest, this.RootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getHierarchyTableResponse.ReturnValue, "RopGetHierarchyTable ROP operation performs successfully!");
            uint getHierarchyTableHandle1 = this.responseHandles[0][getHierarchyTableResponse.OutputHandleIndex];

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1219");
        
            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1219
            // There left 3 folders under the root folder, so the RowCount should be 3.
            this.Site.CaptureRequirementIfAreEqual<uint>(
                0x00000003,
                getHierarchyTableResponse.RowCount,
                1219,
                @"[In RopGetHierarchyTable ROP Request Buffer] TableFlags (1 byte): If this bit [SoftDeletes (0x20)] is not set, the hierarchy table lists only the existing folders.");
            #endregion

            #region Step 11. The client get the properties information from the rows of the table.

            PropertyTag propertyTag = new PropertyTag
            {
                PropertyId = (ushort)FolderPropertyId.PidTagDisplayName,
                PropertyType = (ushort)PropertyType.PtypString
            };
            PropertyTag[] propertyTags = new PropertyTag[] { propertyTag };
            List<PropertyRow> propertyRows = this.GetTableRowValue(getHierarchyTableHandle1, (ushort)getHierarchyTableResponse.RowCount, propertyTags);
            Site.Assert.IsNotNull(propertyRows, "The PidTagDisplayName property value could not be retrieved from the hierarchy table object of the [MSOXCFOLDRootFolder].");

            string pidTagDisplayNameUseUnicode = Encoding.Unicode.GetString(propertyRows[0].PropertyValues[0].Value);

            #region Verify the requirement: MS-OXCFOLD_R807 and MS-OXCFOLD_R311.

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R807
            Site.CaptureRequirementIfAreEqual<string>(
                Constants.Subfolder1,
                pidTagDisplayNameUseUnicode,
                807,
                @"[In RopGetHierarchyTable ROP Request Buffer] TableFlags (1 byte): If this bit [UseUnicode (0x40)] is set, the columns that contain string data are returned in Unicode format.");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R311.
            // The PidTagDisplayName property value was get successfully by the table object handle get from step 10, MS-OXCFOLD_R311 can be verified directly.
            Site.CaptureRequirement(
                311,
                @"[In RopGetHierarchyTable ROP Request Buffer] OutputHandleIndex (1 byte): The output Server object for this operation [RopGetHierarchyTable ROP] is a Table object that represents the hierarchy table.");
            #endregion
            #endregion

            #region Step 12. The client calls RopGetHierarchyTable with setting the 'UseUnicode' TableFlags to retrieve the hierarchy table for the root folder.

            getHierarchyTableRequest.TableFlags = (byte)FolderTableFlags.Depth;
            getHierarchyTableResponse = this.Adapter.GetHierarchyTable(getHierarchyTableRequest, this.RootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, getHierarchyTableResponse.ReturnValue, "RopGetHierarchyTable ROP operation performs successfully!");
            uint getHierarchyTableHandle = this.responseHandles[0][getHierarchyTableResponse.OutputHandleIndex];

            #endregion

            #region Step 13. The client get the properties information from the rows of the table.

            propertyTag = new PropertyTag
            {
                PropertyId = (ushort)FolderPropertyId.PidTagDisplayName,
                PropertyType = (ushort)PropertyType.PtypString8
            };
            propertyTags = new PropertyTag[] { propertyTag };
            propertyRows = this.GetTableRowValue(getHierarchyTableHandle, (ushort)getHierarchyTableResponse.RowCount, propertyTags);
            Site.Assert.IsNotNull(propertyRows, "The PidTagDisplayName property value could not be retrieved from the hierarchy table object of the [MSOXCFOLDRootFolder].");

            string pidTagDisplayNameNoUseUnicodeFlag = Encoding.ASCII.GetString(propertyRows[0].PropertyValues[0].Value);

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R808");
        
            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R808
            this.Site.CaptureRequirementIfAreEqual<string>(
                Constants.Subfolder1,
                pidTagDisplayNameNoUseUnicodeFlag,
                808,
                @"[In RopGetHierarchyTable ROP Request Buffer] TableFlags (1 byte): If this bit [UseUnicode (0x40)] is not set, the string data is encoded in the code page of the Logon object.");
            #endregion
        }
Пример #27
0
        /// <summary>
        /// Create the active search folder in Inbox folder.
        /// </summary>
        /// <param name="folderName">The search folder name</param>
        /// <param name="searchFolderHandle">The search folder handle</param>
        /// <param name="searchFolderId">The created search folder ID</param>
        protected void CreateSearchFolder(string folderName, out uint searchFolderHandle, out ulong searchFolderId)
        {
            #region Open Inbox folder
            RopOpenFolderRequest openFolderRequest;
            RopOpenFolderResponse openFolderResponse;

            openFolderRequest.RopId = 0x02;
            openFolderRequest.LogonId = 0x0;
            openFolderRequest.InputHandleIndex = 0x0;
            openFolderRequest.OutputHandleIndex = 0x01;
            openFolderRequest.FolderId = this.logonResponse.FolderIds[4]; // Inbox folder
            openFolderRequest.OpenModeFlags = 0x0; // opening an existing folder

            this.oxcstorAdapter.DoRopCall(openFolderRequest, this.outObjHandle, ROPCommandType.Others, out this.outputBuffer);

            openFolderResponse = (RopOpenFolderResponse)this.outputBuffer.RopsList[0];
            Site.Assert.AreEqual<uint>(
                0x00000000,
                openFolderResponse.ReturnValue,
                "0 indicates the ROP succeeds, other value indicates error occurs.");
            uint openedFolderHandle = this.outputBuffer.ServerObjectHandleTable[openFolderResponse.OutputHandleIndex];

            // Create a general folder
            RopCreateFolderRequest createFolderRequest = new RopCreateFolderRequest
            {
                RopId = (byte)RopId.RopCreateFolder,
                LogonId = 0x00,
                InputHandleIndex = 0x00,
                OutputHandleIndex = 0x01,
                FolderType = 0x01,
                UseUnicodeStrings = 0x0,
                OpenExisting = 0x00,
                Reserved = 0x0
            };

            string generalFolder = Common.GenerateResourceName(Site, "Folder") + "\0";
            createFolderRequest.DisplayName = Encoding.ASCII.GetBytes(generalFolder);
            createFolderRequest.Comment = Encoding.ASCII.GetBytes(generalFolder);
            this.oxcstorAdapter.DoRopCall(createFolderRequest, openedFolderHandle, ROPCommandType.Others, out this.outputBuffer);
            RopCreateFolderResponse createFolderResponse = (RopCreateFolderResponse)this.outputBuffer.RopsList[0];
            Site.Assert.AreEqual<uint>(0, createFolderResponse.ReturnValue, "0 indicates the ROP succeeds, other value indicates error occurs.");
            ulong subfolderId1 = createFolderResponse.FolderId;

            #endregion

            #region Call RopCreateFolder to create the search folder under the Inbox folder.
            string folderNameWithNull = folderName + "\0";
            createFolderRequest.FolderType = 0x02;
            createFolderRequest.DisplayName = Encoding.ASCII.GetBytes(folderNameWithNull);
            createFolderRequest.Comment = Encoding.ASCII.GetBytes(folderNameWithNull);
            this.oxcstorAdapter.DoRopCall(createFolderRequest, openedFolderHandle, ROPCommandType.Others, out this.outputBuffer);
            createFolderResponse = (RopCreateFolderResponse)this.outputBuffer.RopsList[0];
            Site.Assert.AreEqual<uint>(0, createFolderResponse.ReturnValue, "0 indicates the ROP succeeds, other value indicates error occurs.");
            searchFolderHandle = this.outputBuffer.ServerObjectHandleTable[createFolderResponse.OutputHandleIndex];
            searchFolderId = createFolderResponse.FolderId;

            #endregion

            #region Call RopSetSearchCriteria to establish search criteria for created general folder.

            RopSetSearchCriteriaRequest setSearchCriteriaRequest = new RopSetSearchCriteriaRequest
            {
                RopId = (byte)RopId.RopSetSearchCriteria,
                LogonId = 0x00,
                InputHandleIndex = 0x00
            };
            byte[] restrictData = new byte[] { 0x08, 0x1F, 0x00, 0x1A, 0x00 };
            setSearchCriteriaRequest.RestrictionDataSize = (ushort)restrictData.Length;
            setSearchCriteriaRequest.RestrictionData = restrictData;
            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;
            this.oxcstorAdapter.DoRopCall(setSearchCriteriaRequest, searchFolderHandle, ROPCommandType.Others, out this.outputBuffer);
            RopSetSearchCriteriaResponse setSearchCriteriaResponse = (RopSetSearchCriteriaResponse)this.outputBuffer.RopsList[0];
            Site.Assert.AreEqual<uint>(0, setSearchCriteriaResponse.ReturnValue, "0 indicates the ROP succeeds, other value indicates error occurs.");

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

            #region Step 1. The client calls RopCreateFolder to create [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 = 0x1,
                OpenExisting = 0x00,
                Reserved = 0x0,
                DisplayName = Encoding.Unicode.GetBytes(Constants.Subfolder1),
                Comment = Encoding.Unicode.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!");
            ulong subfolderId1 = createFolderResponse.FolderId;
            uint subfolderHandle1 = this.responseHandles[0][createFolderResponse.OutputHandleIndex];

            #endregion

            #region Step 2. The client calls RopCreateFolder to create [MSOXCFOLDSubfolder2] under the root folder.

            createFolderRequest.FolderType = 0x02;
            createFolderRequest.DisplayName = Encoding.Unicode.GetBytes(Constants.Subfolder2);
            createFolderRequest.Comment = Encoding.Unicode.GetBytes(Constants.StringNullTerminated);

            createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, this.RootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, createFolderResponse.ReturnValue, "RopCreateFolder ROP operation performs successfully!");
            uint subfolderHandle2 = this.responseHandles[0][createFolderResponse.OutputHandleIndex];

            #endregion

            #region Step 3. The client creates a Non-FAI message and saves it in [MSOXCFOLDSubfolder1].

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

            #endregion

            #region Step 4. The client create a FAI message and saves it in [MSOXCFOLDSubfolder2].

            uint messageHandle2 = 0;
            ulong messageId2 = 0;
            this.CreateSaveMessage(subfolderHandle2, subfolderId1, 0x01, ref messageId2, ref messageHandle2);

            #endregion

            #region Step 5. The client get the properties from the [MSOXCFOLDSubfolder1] under the root folder.

            PropertyTag[] tags = new PropertyTag[7];
            PropertyTag tag;

            tag.PropertyId = (ushort)FolderPropertyId.PidTagAttributeHidden;
            tag.PropertyType = (ushort)PropertyType.PtypBoolean;
            tags[0] = tag;

            tag.PropertyId = (ushort)FolderPropertyId.PidTagComment;
            tag.PropertyType = (ushort)PropertyType.PtypString;
            tags[1] = tag;

            tag.PropertyId = (ushort)FolderPropertyId.PidTagContainerClass;
            tag.PropertyType = (ushort)PropertyType.PtypString;
            tags[2] = tag;

            tag.PropertyId = (ushort)FolderPropertyId.PidTagDisplayName;
            tag.PropertyType = (ushort)PropertyType.PtypString;
            tags[3] = tag;

            tag.PropertyId = (ushort)FolderPropertyId.PidTagFolderType;
            tag.PropertyType = (ushort)PropertyType.PtypInteger32;
            tags[4] = tag;

            tag.PropertyId = (ushort)FolderPropertyId.PidTagRights;
            tag.PropertyType = (ushort)PropertyType.PtypInteger32;
            tags[5] = tag;

            tag.PropertyId = (ushort)FolderPropertyId.PidTagAccessControlListData;
            tag.PropertyType = (ushort)PropertyType.PtypBinary;
            tags[6] = tag;

            RopGetPropertiesSpecificRequest getPropertiesSpecificRequest = new RopGetPropertiesSpecificRequest();
            RopGetPropertiesSpecificResponse getPropertiesSpecificResponse = new RopGetPropertiesSpecificResponse();
            getPropertiesSpecificRequest.RopId = (byte)RopId.RopGetPropertiesSpecific;
            getPropertiesSpecificRequest.LogonId = Constants.CommonLogonId;
            getPropertiesSpecificRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            getPropertiesSpecificRequest.PropertySizeLimit = 0xFFFF;
            getPropertiesSpecificRequest.PropertyTagCount = (ushort)tags.Length;
            getPropertiesSpecificRequest.PropertyTags = tags;
            getPropertiesSpecificRequest.WantUnicode = 0x01;
            getPropertiesSpecificResponse = this.Adapter.GetFolderObjectSpecificProperties(getPropertiesSpecificRequest, subfolderHandle1, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, getPropertiesSpecificResponse.ReturnValue, "RopGetPropertiesSpecific ROP operation performs successfully!");
            RopGetPropertiesSpecificResponse getPropertiesSpecificResponse1 = getPropertiesSpecificResponse;

            #region Verify the requirements: MS_OXCFOLD_R1033, MS-OXCFOLD_R10359, and MS-OXCFOLD_R811.

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1033.
            Site.CaptureRequirementIfAreEqual<byte>(
                0,
                getPropertiesSpecificResponse.RowData.PropertyValues[0].Value[0],
                1033,
                @"[In PidTagAttributeHidden Property] The value is zero otherwise [If the folder is not hidden].");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R10359
            Site.CaptureRequirementIfAreEqual<string>(
                Constants.Subfolder1,
                Encoding.Unicode.GetString(getPropertiesSpecificResponse.RowData.PropertyValues[1].Value),
                10359,
                @"[In PidTagComment Property] The PidTagComment property ([MS-OXPROPS] section 2.628) contains a comment about the purpose or content of the folder.");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R811
            Site.CaptureRequirementIfAreEqual<int>(
                1,
                BitConverter.ToInt32(getPropertiesSpecificResponse.RowData.PropertyValues[4].Value, 0),
                811,
                @"[In PidTagFolderType Property] FOLDER_GENERIC (1): A generic folder that contains messages and other folders.");
            #endregion

            #endregion

            #region Step 6. The client set the read/write properties for the folder.

            TaggedPropertyValue[] taggedPropertyValueArray = new TaggedPropertyValue[6];
            PropertyTag tempPropertyTag = new PropertyTag();
            int size = 0;

            // Set PidTagAttributeHidden property for the folder.
            taggedPropertyValueArray[0] = new TaggedPropertyValue();
            tempPropertyTag.PropertyId = (ushort)FolderPropertyId.PidTagAttributeHidden;
            tempPropertyTag.PropertyType = (ushort)PropertyType.PtypBoolean;
            taggedPropertyValueArray[0].PropertyTag = tempPropertyTag;
            taggedPropertyValueArray[0].Value = new byte[1] { 0x01 };

            // Set PidTagComment property for the folder.
            taggedPropertyValueArray[1] = new TaggedPropertyValue();
            tempPropertyTag.PropertyId = (ushort)FolderPropertyId.PidTagComment;
            tempPropertyTag.PropertyType = (ushort)PropertyType.PtypString;
            taggedPropertyValueArray[1].PropertyTag = tempPropertyTag;
            taggedPropertyValueArray[1].Value = Encoding.Unicode.GetBytes(Constants.Subfolder3);

            // Set PidTagContainerClass property for the folder.
            taggedPropertyValueArray[2] = new TaggedPropertyValue();
            tempPropertyTag.PropertyId = (ushort)FolderPropertyId.PidTagContainerClass;
            tempPropertyTag.PropertyType = (ushort)PropertyType.PtypString;
            taggedPropertyValueArray[2].PropertyTag = tempPropertyTag;
            taggedPropertyValueArray[2].Value = Encoding.Unicode.GetBytes("IPF.Note\0");

            // Set PidTagDisplayName property for the folder.
            taggedPropertyValueArray[3] = new TaggedPropertyValue();
            tempPropertyTag.PropertyId = (ushort)FolderPropertyId.PidTagDisplayName;
            tempPropertyTag.PropertyType = (ushort)PropertyType.PtypString;
            taggedPropertyValueArray[3].PropertyTag = tempPropertyTag;
            taggedPropertyValueArray[3].Value = Encoding.Unicode.GetBytes(Constants.Subfolder3);

            // Set PidTagFolderType property for the folder.
            taggedPropertyValueArray[4] = new TaggedPropertyValue();
            tempPropertyTag.PropertyId = (ushort)FolderPropertyId.PidTagFolderType;
            tempPropertyTag.PropertyType = (ushort)PropertyType.PtypInteger32;
            taggedPropertyValueArray[4].PropertyTag = tempPropertyTag;
            taggedPropertyValueArray[4].Value = BitConverter.GetBytes(0x00000001);

            // Set PidTagRights property for the folder.
            taggedPropertyValueArray[5] = new TaggedPropertyValue();
            tempPropertyTag.PropertyId = (ushort)FolderPropertyId.PidTagRights;
            tempPropertyTag.PropertyType = (ushort)PropertyType.PtypInteger32;
            taggedPropertyValueArray[5].PropertyTag = tempPropertyTag;
            taggedPropertyValueArray[5].Value = BitConverter.GetBytes(0x00000400);

            for (int i = 0; i < taggedPropertyValueArray.Length; i++)
            {
                size += taggedPropertyValueArray[i].Size();
            }

            RopSetPropertiesRequest setPropertiesRequest = new RopSetPropertiesRequest
            {
                RopId = (byte)RopId.RopSetProperties,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                PropertyValueSize = (ushort)(size + 2),
                PropertyValueCount = (ushort)taggedPropertyValueArray.Length,
                PropertyValues = taggedPropertyValueArray
            };

            RopSetPropertiesResponse setPropertiesResponse = this.Adapter.SetFolderObjectProperties(setPropertiesRequest, subfolderHandle1, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, setPropertiesResponse.ReturnValue, "RopSetProperties ROP operation performs successfully!");

            #endregion

            #region Step 7. The client get the properties from the [MSOXCFOLDSubfolder1] under the root folder after execute the RopSetProperties operation.

            getPropertiesSpecificResponse = this.Adapter.GetFolderObjectSpecificProperties(getPropertiesSpecificRequest, subfolderHandle1, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, getPropertiesSpecificResponse.ReturnValue, "RopGetPropertiesSpecific ROP operation performs successfully!");

            #region Verify the requirements: MS_OXCFOLD_R1032, MS-OXCFOLD_R10356.

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1032.
            Site.CaptureRequirementIfAreNotEqual<byte>(
                0,
                getPropertiesSpecificResponse.RowData.PropertyValues[0].Value[0],
                1032,
                @"[In PidTagAttributeHidden Property] The value of this property [PidTagAttributeHidden] is nonzero if the folder is hidden.");

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

            // MS-OXCFOLD_R1032 and MS-OXCFOLD_R1033 were verified, MS-OXCFOLD_R10356 can be verified directly.
            Site.CaptureRequirement(
                10356,
                @"[In PidTagAttributeHidden Property] The PidTagAttributeHidden property ([MS-OXPROPS] section 2.602) specifies whether the folder is hidden.");

            string pidTagContainerClass = System.Text.Encoding.Unicode.GetString(getPropertiesSpecificResponse.RowData.PropertyValues[2].Value);
            
            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1038: the PidTagContainerClass property value is {0}", pidTagContainerClass.Replace("\0", string.Empty));
        
            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1038
            this.Site.CaptureRequirementIfIsTrue(
                pidTagContainerClass.StartsWith("IPF."),
                1038,
                @"[In PidTagContainerClass Property] The value of this property [PidTagContainerClass] MUST begin with ""IPF."".");

            // According to step above, the folder object includes the PidTagContainerClass property and the value of the PidTagContainerClass property follow the definition in Open Specification.
            // So R10036 will be verfied.
            this.Site.CaptureRequirement(
                10036,
                @"[In PidTagContainerClass Property] The PidTagContainerClass property ([MS-OXPROPS] section 2.633) specifies the type of Message object that the folder contains.");
            #endregion

            #endregion

            #region Step 8. The client get the properties from the [MSOXCFOLDSubfolder2] under the root folder.

            getPropertiesSpecificResponse = this.Adapter.GetFolderObjectSpecificProperties(getPropertiesSpecificRequest, subfolderHandle2, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, getPropertiesSpecificResponse.ReturnValue, "RopGetPropertiesSpecific ROP operation performs successfully!");
            RopGetPropertiesSpecificResponse getPropertiesSpecificResponse3 = getPropertiesSpecificResponse;

            #region Verify the requirement: MS-OXCFOLD_R812 and  MS-OXCFOLD_R1034.

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R812
            Site.CaptureRequirementIfAreEqual<int>(
                2,
                BitConverter.ToInt32(getPropertiesSpecificResponse.RowData.PropertyValues[4].Value, 0),
                812,
                @"[In PidTagFolderType Property] FOLDER_SEARCH (2): A folder that contains the results of a search, in the form of links to messages that meet search criteria.");

            bool isVerifyR1034 = Encoding.Unicode.GetString(getPropertiesSpecificResponse1.RowData.PropertyValues[1].Value) == Constants.Subfolder1 &&
                Encoding.Unicode.GetString(getPropertiesSpecificResponse3.RowData.PropertyValues[1].Value) == Constants.StringNullTerminated;

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R1034, the property [PidTagComment] is present {0} only if the client sets it.", isVerifyR1034 ? string.Empty : "not");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1034.
            Site.CaptureRequirementIfIsTrue(
                isVerifyR1034,
                1034,
                @"[In PidTagComment Property] This property [PidTagComment] is present only if the client sets it when the folder is created.");

            #endregion

            #endregion

            #region Step 8. The client set the same read/write properties for the [MSOXCFOLDSubfolder2] as [MSOXCFOLDSubfolder1].
            taggedPropertyValueArray = new TaggedPropertyValue[1];
            tempPropertyTag = new PropertyTag();

            // Set PidTagDisplayName property for the folder.
            taggedPropertyValueArray[0] = new TaggedPropertyValue();
            tempPropertyTag.PropertyId = (ushort)FolderPropertyId.PidTagDisplayName;
            tempPropertyTag.PropertyType = (ushort)PropertyType.PtypString;
            taggedPropertyValueArray[0].PropertyTag = tempPropertyTag;
            taggedPropertyValueArray[0].Value = Encoding.Unicode.GetBytes(Constants.Subfolder3);

            setPropertiesRequest = new RopSetPropertiesRequest
            {
                RopId = (byte)RopId.RopSetProperties,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                PropertyValueSize = (ushort)(taggedPropertyValueArray[0].Size() + 2),
                PropertyValueCount = (ushort)taggedPropertyValueArray.Length,
                PropertyValues = taggedPropertyValueArray
            };
            setPropertiesResponse = this.Adapter.SetFolderObjectProperties(setPropertiesRequest, subfolderHandle2, ref this.responseHandles);

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

            // Only set one property in RopSetProperties ROP request, use 0 as index here.
            int expectedIndex = 0;
            bool isVerifiedR1039 = false;
            if (setPropertiesResponse.PropertyProblems != null)
            {
                Site.Log.Add(
                    LogEntryKind.Debug,
                    "The PropertyProblems of index {0} in RopSetProperties ROP response return value is: {1}",
                    expectedIndex,
                    setPropertiesResponse.PropertyProblems[expectedIndex].ErrorCode);
                isVerifiedR1039 = setPropertiesResponse.PropertyProblems[expectedIndex].ErrorCode != Constants.SuccessCode;
            }
            else
            {
                Site.Log.Add(LogEntryKind.Debug, "The RopSetProperties ROP response return value is: {0}", setPropertiesResponse.ReturnValue);
                isVerifiedR1039 = setPropertiesResponse.ReturnValue != Constants.SuccessCode;
            }

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1039.
            Site.CaptureRequirementIfIsTrue(
                isVerifiedR1039,
                1039,
                @"[In PidTagDisplayName Property] Sibling folders MUST have unique display names.");
            #endregion

            #region Step 9. The client calls RopOpenFolder to get the Root folder handle.

            RopOpenFolderRequest openFolderRequest = new RopOpenFolderRequest
            {
                RopId = (byte)RopId.RopOpenFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                FolderId = this.DefaultFolderIds[0],
                OpenModeFlags = (byte)FolderOpenModeFlags.OpenSoftDeleted
            };

            RopOpenFolderResponse openFolderResponse = this.Adapter.OpenFolder(openFolderRequest, this.LogonHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, openFolderResponse.ReturnValue, "RopOpenFolder ROP operation performs successfully!");
            uint rootFolderHandle = this.responseHandles[0][openFolderResponse.OutputHandleIndex];

            #endregion

            #region Step 10. The client get the properties from the Root folder.

            getPropertiesSpecificResponse = this.Adapter.GetFolderObjectSpecificProperties(getPropertiesSpecificRequest, rootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, getPropertiesSpecificResponse.ReturnValue, "RopGetPropertiesSpecific ROP operation performs successfully!");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R810.
            Site.CaptureRequirementIfAreEqual<int>(
                0,
                BitConverter.ToInt32(getPropertiesSpecificResponse.RowData.PropertyValues[4].Value, 0),
                810,
                @"[In PidTagFolderType Property] FOLDER_ROOT (0): The Root folder of the folder hierarchy table; that is, a folder that has no parent folder.");

            RopGetPropertiesAllResponse getPropertiesAllResponse = this.Adapter.GetFolderPropertiesAll(this.RootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, getPropertiesAllResponse.ReturnValue, "RopGetPropertiesAllResponse ROP operation performs successfully!");
            #endregion

            #region Step 11. The client get property PidTagAddressBookEntryId
            if (Common.IsRequirementEnabled(350002, this.Site))
            {
                PropertyTag[] propertyTagArray = new PropertyTag[1];
                PropertyTag propertyTag = new PropertyTag
                {
                    PropertyId = (ushort)FolderPropertyId.PidTagAddressBookEntryId,
                    PropertyType = (ushort)PropertyType.PtypBinary
                };
                propertyTagArray[0] = propertyTag;

                getPropertiesSpecificRequest = new RopGetPropertiesSpecificRequest();
                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!");

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R350.
                // Flag value 0x01 indicates there is error.
                Site.CaptureRequirementIfAreEqual<byte>(
                    0x01,
                    getPropertiesSpecificResponse.RowData.Flag,
                    350,
                    @"[In PidTagAddressBookEntryId Property] This property is set only for public folders.");
            }
            #endregion
        }
Пример #29
0
 /// <summary>
 /// Creates a new Folder.
 /// </summary>
 /// <param name="parentFolderHandle">The parent folder under which the new folder will be created.</param>
 /// <param name="folderName">Folder Name which will be created.</param>
 /// <param name="folderId">Folder Id which will be returned by server.</param>
 /// <param name="folderHandle">Folder Handle which will be returned by server.</param>
 /// <returns>The RopCreateFolder ROP response buffer.</returns>
 protected RopCreateFolderResponse CreateFolder(uint parentFolderHandle, string folderName, ref ulong folderId, ref uint folderHandle)
 {
     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(folderName),
         Comment = Encoding.ASCII.GetBytes(folderName)
     };
     RopCreateFolderResponse createFolderResponse = this.Adapter.CreateFolder(createFolderRequest, parentFolderHandle, ref this.responseHandles);
     Site.Assert.AreEqual<uint>(0, createFolderResponse.ReturnValue, "Creating Folder should succeed.");
     folderHandle = this.responseHandles[0][createFolderResponse.OutputHandleIndex];
     folderId = createFolderResponse.FolderId;
     return createFolderResponse;
 }
        /// <summary>
        /// Get Created Folder Handle.
        /// </summary>
        /// <param name="openedFolderHandle">The opened folder handle</param>
        /// <param name="tempFolderIndex">The temp folder's index</param>
        /// <returns>Return created Folder Handle</returns>
        private uint GetCreatedFolderHandle(uint openedFolderHandle, int tempFolderIndex)
        {
            RopCreateFolderRequest createFolderRequest = new RopCreateFolderRequest();
            RopCreateFolderResponse createFolderResponse;

            createFolderRequest.RopId = (byte)RopId.RopCreateFolder;
            createFolderRequest.LogonId = TestSuiteBase.LogonId;
            createFolderRequest.InputHandleIndex = TestSuiteBase.InputHandleIndex0;
            createFolderRequest.OutputHandleIndex = TestSuiteBase.OutputHandleIndex1;
            createFolderRequest.FolderType = (byte)FolderType.Genericfolder;
            createFolderRequest.UseUnicodeStrings = Convert.ToByte(TestSuiteBase.Zero);
            createFolderRequest.OpenExisting = TestSuiteBase.NonZero;
            createFolderRequest.Reserved = TestSuiteBase.Reserved;

            // Set DisplayName, which specifies the name of the created folder.
            createFolderRequest.DisplayName = Encoding.ASCII.GetBytes(TestSuiteBase.DisplayNameAndCommentForNonSearchFolder + tempFolderIndex + "\0");

            // Set Comment, which specifies the folder comment that is associated with the created folder.
            createFolderRequest.Comment = Encoding.ASCII.GetBytes(TestSuiteBase.DisplayNameAndCommentForNonSearchFolder + tempFolderIndex + "\0");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Begin to send the RopCreateFolder request in GetCreatedFolderHandle method.");

            // Send the RopCreateFolder request to create folder.
            this.responseSOHs = cropsAdapter.ProcessSingleRop(
                createFolderRequest,
                openedFolderHandle,
                ref this.response,
                ref this.rawData,
                RopResponseType.SuccessResponse);
            createFolderResponse = (RopCreateFolderResponse)response;

            Site.Assert.AreEqual<uint>(
                TestSuiteBase.SuccessReturnValue,
                createFolderResponse.ReturnValue,
                "if ROP succeeds, ReturnValue of its response will be 0 (success)");

            // Get the handle of the created folder.
            uint createdFolderHandle = responseSOHs[0][createFolderResponse.OutputHandleIndex];
            return createdFolderHandle;
        }