public void MSOXCFOLD_S05_TC02_MessageDeletePartialCompleteValidation()
        {
            this.CheckWhetherSupportTransport();
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            uint logonHandle = 0;
            uint pidTagMemberRights = 0;

            this.GenericFolderInitialization();

            #region Step 1. Add permission entry for the user configured by "CommonUser" 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 | (uint)PidTagMemberRightsEnum.EditOwned | (uint)PidTagMemberRightsEnum.Create | (uint)PidTagMemberRightsEnum.CreateSubFolder | (uint)PidTagMemberRightsEnum.DeleteOwned;
            this.AddPermission(this.commonUserEssdn, pidTagMemberRights, this.RootFolderHandle);
            #endregion

            #region Step 2. Create message and subfolder in the root folder.
            ulong messageId = 0;
            uint messageHandle = 0;
            this.CreateSaveMessage(this.RootFolderHandle, this.RootFolderId, ref messageId, ref messageHandle);

            uint subfolderHandle = 0;
            ulong subfolderId = 0;
            this.CreateFolder(this.RootFolderHandle, Constants.Subfolder1, ref subfolderId, ref subfolderHandle);
            #endregion

            #region Step 3. Logon the user configured by "CommonUser".
            this.Adapter.DoDisconnect();
            this.Adapter.DoConnect(this.sutServer, ConnectionType.PrivateMailboxServer, this.commonUserEssdn, this.domain, this.commonUser, this.commonUserPassword);
            this.Logon(LogonFlags.Private, out logonHandle, (uint)OpenFlags.UsePerMDBReplipMapping);
            #endregion

            #region Step 4. The "CommonUser" opens the root folder.
            this.OpenFolder(logonHandle, this.DefaultFolderIds[this.inboxIndex], ref inboxHandle);

            ulong rootFolderId = this.GetSubfolderIDByName(this.DefaultFolderIds[this.inboxIndex], logonHandle, this.RootFolder);
            uint rootFolderHandle = 0;
            RopOpenFolderResponse openFolderResponse = this.OpenFolder(logonHandle, rootFolderId, ref rootFolderHandle);

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R46202
            Site.CaptureRequirementIfAreEqual<uint>(
                Constants.SuccessCode,
                openFolderResponse.ReturnValue,
                46202,
                @"[In Processing a RopOpenFolder ROP Request] If the folder with the specified ID actually exists and the client has sufficient access rights to view the folder, the RopOpenFolder ROP performs successfully.");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R394.
            // MS-OXCFOLD_R462 was verified, MS-OXCFOLD_R462 can be verified directly.
            Site.CaptureRequirement(
                394,
                @"[In Opening a Folder] The client MUST have sufficient access rights to the folder for this operation to succeed.");

            ulong commonUserMessageId = 0;
            uint commonUserMessageHandle = 0;
            this.CreateSaveMessage(rootFolderHandle, rootFolderId, ref commonUserMessageId, ref commonUserMessageHandle);

            uint commonUserSubfolderHandle = 0;
            ulong commonUserSubfolderId = 0;
            this.CreateFolder(rootFolderHandle, Constants.Subfolder2, ref commonUserSubfolderId, ref commonUserSubfolderHandle);
            #endregion

            #region Step 5. The client calls RopDeleteMessages to delete the message created in step 2.

            ulong[] messageIds = new ulong[] { messageId, commonUserMessageId };
            RopDeleteMessagesRequest deleteMessagesRequest = new RopDeleteMessagesRequest();
            RopDeleteMessagesResponse deleteMessagesResponse = new RopDeleteMessagesResponse();
            deleteMessagesRequest.RopId = (byte)RopId.RopDeleteMessages;
            deleteMessagesRequest.LogonId = Constants.CommonLogonId;
            deleteMessagesRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            deleteMessagesRequest.WantAsynchronous = 0x00;

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

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R991
            Site.CaptureRequirementIfAreNotEqual<byte>(
                0,
                deleteMessagesResponse.PartialCompletion,
                991,
                @"[In RopDeleteMessages ROP Response Buffer] PartialCompletion (1 byte): If the ROP [RopDeleteMessages] fails for a subset of targets, the value of this field is nonzero (TRUE).");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1147
            Site.CaptureRequirementIfAreNotEqual<uint>(
                0,
                deleteMessagesResponse.PartialCompletion,
                1147,
                @"[In Processing a RopDeleteMessages ROP Request] If the server fails to delete any messages, it sets the PartialCompletion field of the RopDeleteMessages ROP response buffer to nonzero (TRUE), as specified in section 2.2.1.11.2.");
            #endregion

            #region Step 6. The client calls RopHardDeleteMessages to delete the message created in step 2.
            RopHardDeleteMessagesRequest hardDeleteMessagesRequest = new RopHardDeleteMessagesRequest
            {
                RopId = 0x91,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                WantAsynchronous = 0x00,
                NotifyNonRead = 0x00,
                MessageIdCount = (ushort)messageIds.Length,
                MessageIds = messageIds
            };
            RopHardDeleteMessagesResponse hardDeleteMessagesResponse = this.Adapter.HardDeleteMessages(hardDeleteMessagesRequest, rootFolderHandle, ref this.responseHandles);

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R997.
            Site.CaptureRequirementIfAreNotEqual<byte>(
                0,
                hardDeleteMessagesResponse.PartialCompletion,
                997,
                @"[In RopHardDeleteMessages ROP Response Buffer] If the ROP [RopHardDeleteMessages] fails for a subset of targets, the value of this field is nonzero (TRUE).");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R115602
            Site.CaptureRequirementIfAreNotEqual<byte>(
                0,
                hardDeleteMessagesResponse.PartialCompletion,
                115602,
                @"[In Processing a RopHardDeleteMessages ROP Request] In the server behavior, if the server fails to delete any messages, it sets the PartialCompletion field of the RopDeleteMessages ROP response buffer to nonzero (TRUE), as specified in section 2.2.1.11.2.");
            #endregion

            #region Step 7. The client calls RopHardDeleteMessagesAndSubfolders to delete the message created in step 2.
            RopHardDeleteMessagesAndSubfoldersRequest hardDeleteMessagesAndSubfoldersRequest = new RopHardDeleteMessagesAndSubfoldersRequest
            {
                RopId = (byte)RopId.RopHardDeleteMessagesAndSubfolders,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                WantAsynchronous = 0x00,
                WantDeleteAssociated = 0xFF
            };
            RopHardDeleteMessagesAndSubfoldersResponse hardDeleteMessagesAndSubfoldersResponse = this.Adapter.HardDeleteMessagesAndSubfolders(hardDeleteMessagesAndSubfoldersRequest, rootFolderHandle, ref this.responseHandles);
            
            if (Common.IsRequirementEnabled(2721, this.Site))
            {
                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R2721");

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R2721
                Site.CaptureRequirementIfAreNotEqual<byte>(
                    0,
                    hardDeleteMessagesAndSubfoldersResponse.PartialCompletion,
                    2721,
                    @"[In RopHardDeleteMessagesAndSubfolders ROP Response Buffer] PartialCompletion (1 byte): If the ROP [RopHardDeleteMessagesAndSubfolders] fails for a subset of targets, the value of this field is nonzero (TRUE).");

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R113803.
                Site.CaptureRequirement(
                    113803,
                    @"[In Processing a RopHardDeleteMessagesAndSubfolders ROP Request] In the server behavior, if the server fails to delete any message or subfolder, it sets the PartialCompletion field of the RopHardDeleteMessagesAndSubfolders ROP response buffer to nonzero (TRUE), as specified in section 2.2.1.10.2.");
            }
            #endregion

            #region Step 8. The client calls RopMoveCopyMessages to move the message from the root folder to the inbox.
            List<uint> handleList = new List<uint>
            {
                rootFolderHandle, inboxHandle
            };

            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 moveCopyMessagesResponse = this.Adapter.MoveCopyMessages(moveCopyMessagesRequest, handleList, ref this.responseHandles);

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R10163.
                Site.CaptureRequirementIfAreNotEqual<byte>(
                    0,
                    moveCopyMessagesResponse.PartialCompletion,
                    10163,
                    @"[In RopMoveCopyMessages ROP Response Buffer] PartialCompletion (1 byte): If the ROP fails for a subset of targets, the value of this field is nonzero (TRUE).");

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R586.
                // MS-OXCFOLD_R10163 is verified, MS-OXCFOLD_R586 can be verified directly.
                Site.CaptureRequirement(
                    586,
                    @"[In Processing a RopMoveCopyMessages ROP Request] If the server fails to move or copy any message, it sets the PartialCompletion field of the RopMoveCopyMessages ROP response buffer to nonzero (TRUE), as specified in section 2.2.1.6.2.");
            }
            #endregion
        }
        public void MSOXCFOLD_S03_TC01_StaticSearchVerification()
        {
            this.CheckWhetherSupportTransport();
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            this.GenericFolderInitialization();

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

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

            #endregion

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

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

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

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

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

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

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

            #endregion

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

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

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

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

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

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

            #endregion

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

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

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

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

            #endregion

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

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

            #endregion

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            #endregion

            #endregion

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

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

            #endregion

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

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

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

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

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

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

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

            #endregion

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

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

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

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R519
            // For no message should be found so the search folder should empty, which means the RowCount is 0.
            Site.CaptureRequirementIfAreEqual<uint>(
                0,
                getContentsTableResponse.RowCount,
                519,
                @"[In Processing a RopSetSearchCriteria ROP Request] When new search criteria are applied, the server modifies the search folder to include only the messages that match the new search criteria.");
            #endregion
        }
        public void MSOXCFOLD_S04_TC10_RopHardDeleteMessagesInPublicFolder()
        {
            this.CheckWhetherSupportTransport();
            this.Logon();
            this.PublicFolderInitialization();

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

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

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

            uint rowCountFirst = getContentsTableResponseFirst.RowCount;
            #endregion

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

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

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

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

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

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

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

            uint rowCountSecond = getContentsTableResponseSecond.RowCount;

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

            #region Step 1. Create message in the root folder.
            uint normalMessageHandle = 0;
            ulong normalMmessageId = 0;
            this.CreateSaveMessage(this.RootFolderHandle, this.RootFolderId, ref normalMmessageId, ref normalMessageHandle);
            #endregion

            #region Step 2. Call RopHardDeleteMessage ROP operation to hard delete the message in the root folder.

            ulong[] messageIds = new ulong[] { normalMmessageId };
            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, this.RootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(
                0,
                hardDeleteMessagesResponse.ReturnValue,
                "If ROP succeeds, the ReturnValue of its response is 0(success)");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1153.
            // The return value in RopHardDeleteMessages is zero indicates the client get the RopHardDeleteMessages ROP response successfully, MS-OXCFOLD_R1153 can be verified directly.
            Site.CaptureRequirement(
                1153,
                @"[In Processing a RopHardDeleteMessages ROP Request] The server responds with a RopHardDeleteMessages ROP response buffer.");

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

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

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

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

            #region Verify MS-OXCFOLD_R304 and MS-OXCFOLD_R437.

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R304
            Site.CaptureRequirementIfAreEqual<byte>(
                0,
                hardDeleteMessagesResponse.PartialCompletion,
                304,
                @"[In RopHardDeleteMessages ROP Response Buffer] PartialCompletion (1 byte): Otherwise [if the ROP successes for a subset of targets], the value [of PartialCompletion field] is zero (FALSE).");
  
            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R437");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R437
            // The RopHardDeleteMessages ROP operation performs successfully on a private mailbox, MS-OXCFOLD_R437 can be verified directly.
            Site.CaptureRequirement(
                437,
                @"[In Deleting the Contents of a Folder] To remove particular messages from a folder, the client sends [either a RopDeleteMessages ROP request ([MS-OXCROPS] section 2.2.4.11) or] a RopHardDeleteMessages ROP request ([MS-OXCROPS] section 2.2.4.12).");
            #endregion

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

            #region Step 1. Create a message in the root folder.
            uint messageHandle = 0;
            ulong messageId = 0;
            this.CreateSaveMessage(this.RootFolderHandle, this.RootFolderId, ref messageId, ref messageHandle);
            #endregion

            #region Step 2. Hard delete the message created in step 1 with a logon object handle.
            ulong[] messageIds = new ulong[] { messageId };

            RopHardDeleteMessagesRequest hardDeleteMessagesRequest = new RopHardDeleteMessagesRequest
            {
                RopId = (byte)RopId.RopHardDeleteMessages,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                WantAsynchronous = 0x00,
                NotifyNonRead = 0x00,
                MessageIdCount = (ushort)messageIds.Length,
                MessageIds = messageIds
            };

            // Use logon object handle to hard-delete message is purposed to get error code ecNotSupported [0x80040102].  
            RopHardDeleteMessagesResponse hardDeleteMessagesResponse = this.Adapter.HardDeleteMessages(hardDeleteMessagesRequest, this.LogonHandle, ref this.responseHandles);

            #region Verify MS-OXCFOLD_R644 and MS-OXCFOLD_R645.

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

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

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

            // The MS-OXCFOLD_R644 captured error code [ecNotSupported], capture this requirement directly.
            Site.CaptureRequirement(
                645,
                @"[In Processing a RopHardDeleteMessages ROP Request] When the error code is ecNotSupported, it indicates that the object that this ROP [RopHardDeleteMessages ROP] was called on is not a Folder object.");
            #endregion
            #endregion
        }
        /// <summary>
        /// Hard deletes one or more messages that are listed in the request buffer. 
        /// </summary>
        /// <param name="ropHardDeleteMessagesRequest">RopHardDeleteMessagesRequest object.</param>
        /// <param name="insideObjHandle">Server object handle in RopHardDeleteMessages.</param>
        /// <param name="responseSOHTable">Server objects handles in RopHardDeleteMessagesResponse.</param>
        /// <returns>RopHardDeleteMessagesResponse object.</returns>
        public RopHardDeleteMessagesResponse HardDeleteMessages(RopHardDeleteMessagesRequest ropHardDeleteMessagesRequest, uint insideObjHandle, ref List<List<uint>> responseSOHTable)
        {
            object temp = new object();
            this.ExcuteRopCall((ISerializable)ropHardDeleteMessagesRequest, insideObjHandle, ref temp, ref responseSOHTable, ref this.rawData);
            RopHardDeleteMessagesResponse ropHardDeleteMessagesResponse = (RopHardDeleteMessagesResponse)temp;

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

            return ropHardDeleteMessagesResponse;
        }
        public void MSOXCSTOR_S01_TC06_TestRopLongTermIdFromIdAndRopIdFromLongTermId()
        {
            this.CheckTransportIsSupported();

            #region Step 1: Connect the server via user configured by "AdminUserName".
            this.returnStatus = this.oxcstorAdapter.ConnectEx(ConnectionType.PrivateMailboxServer);
            Site.Assert.IsTrue(this.returnStatus, "Connection is successful");
            #endregion

            #region Step 2: Logon to a private mailbox.
            this.oxcstorAdapter.DoRopCall(this.logonRequestForPrivateMailBox, this.insideObjHandle, ROPCommandType.RopLogonPrivateMailbox, out this.outputBuffer);
            this.logonResponse = (RopLogonResponse)this.outputBuffer.RopsList[0];
            this.outObjHandle = this.outputBuffer.ServerObjectHandleTable[0];

            Site.Assert.AreEqual<uint>(
                0x00000000,
                this.logonResponse.ReturnValue,
                "0 indicates the ROP succeeds, other value indicates error occurs.");
            #endregion

            #region Step 3: Call RopLongTermIdFromId ROP to get the LongTermId of the inbox.

            this.longTermIdFromIdRequest.ObjectId = this.logonResponse.FolderIds[4];
            this.oxcstorAdapter.DoRopCall(this.longTermIdFromIdRequest, this.outObjHandle, ROPCommandType.RopLongTermIdFromId, out this.outputBuffer);
            this.longTermIdFromIdResponse = (RopLongTermIdFromIdResponse)this.outputBuffer.RopsList[0];
            LongTermId longTermIdForInbox = this.longTermIdFromIdResponse.LongTermId;

            #region Capture MS-OXCSTOR_R449, MS-OXCSTOR_R1243, MS-OXCSTOR_R450 and MS-OXCSTOR_R944.

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

            // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R449
            Site.CaptureRequirementIfAreEqual<uint>(
                0,
                this.longTermIdFromIdResponse.ReturnValue,
                449,
                @"[In Receiving a RopLongTermIdFromId ROP Request] The error code ecNone: Its value is 0x00000000.");

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

            // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R1243.
            // The ROP RopLongTermIdFromId performs successfully, this requirement can be verified directly.
            Site.CaptureRequirement(
                1243,
                @"[In Receiving a RopLongTermIdFromId ROP Request] After obtaining the REPLGUID from the REPLID and REPLGUID to-and-from mapping table, the server uses the REPLGUID to construct the 192-bit LongTermID, as specified in [MS-OXCDATA] section 2.2.1.3.1, which is returned in the LongTermId field.");

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

            // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R450
            Site.CaptureRequirementIfAreEqual<uint>(
                0,
                this.longTermIdFromIdResponse.ReturnValue,
                450,
                @"[In Receiving a RopLongTermIdFromId ROP Request] The error code ecNone: Success.");

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

            // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R944.
            // The ROP RopLongTermIdFromId performs successfully, MS-OXCSTOR_R944 can be verified directly.
            Site.CaptureRequirement(
                944,
                @"[In Receiving a RopLongTermIdFromId ROP Request] The server searches the REPLID and REPLGUID to-and-from mapping table for the replica ID (REPLID) portion of the given Folder ID or Message ID, as specified in [MS-OXCDATA] sections 2.2.1.1 or 2.2.1.2.");
            #endregion
            #endregion

            #region Step 4: Call RopIdFromLongTermId by the LongTermID get in step 3.

            this.getIdFromLongTermIdRequest.LongTermId.DatabaseGuid = this.longTermIdFromIdResponse.LongTermId.DatabaseGuid;
            this.getIdFromLongTermIdRequest.LongTermId.GlobalCounter = this.longTermIdFromIdResponse.LongTermId.GlobalCounter;
            this.oxcstorAdapter.DoRopCall(this.getIdFromLongTermIdRequest, this.outObjHandle, ROPCommandType.RopIdFromLongTermId, out this.outputBuffer);
            this.getIdFromLongTermIdResponse = (RopIdFromLongTermIdResponse)this.outputBuffer.RopsList[0];

            Site.Assert.AreEqual<uint>(
                0,
                this.longTermIdFromIdResponse.ReturnValue,
                "0 indicates the ROP succeeds, other value indicates error occurs.");

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

            // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R1252.
            Site.CaptureRequirementIfAreEqual<ulong>(
                this.logonResponse.FolderIds[4],
                this.getIdFromLongTermIdResponse.ObjectId,
                1252,
                @"[In Receiving a RopIdFromLongTermId ROP Request] After obtaining the REPLID from the REPLID and REPLGUID to-and-from mapping table, the server uses the REPLID to construct the 64-bit Folder ID or Message ID, as specified in [MS-OXCDATA] sections 2.2.1.1 or 2.2.1.2, which is returned in the ObjectId field.");

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

            // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R59718.
            Site.CaptureRequirementIfAreEqual<ulong>(
                this.logonResponse.FolderIds[4],
                this.getIdFromLongTermIdResponse.ObjectId,
                59718,
                @"[In RopLongTermIdFromId ROP Success Response Buffer] That [LongTermId] is mapped from the given Folder ID as specified in[MS-OXCDATA] sections 2.2.4.1 or 2.2.4.2, that is contained in the ObjectID field (section 2.2.1.8.1).");

            #region Capture MS-OXCSTOR_R466, MS-OXCSTOR_R467, MS-OXCSTOR_R454 and MS-OXCSTOR_R952.
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCSTOR_R466");

            // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R466.
            Site.CaptureRequirementIfAreEqual<uint>(
                0,
                this.getIdFromLongTermIdResponse.ReturnValue,
                466,
                @"[In Receiving a RopIdFromLongTermId ROP Request] The error code ecNone: Its value is 0x00000000.");

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

            // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R467.
            Site.CaptureRequirementIfAreEqual<uint>(
                0,
                this.getIdFromLongTermIdResponse.ReturnValue,
                467,
                @"[In Receiving a RopIdFromLongTermId ROP Request] The error code ecNone: Success.");

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

            // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R454.
            Site.CaptureRequirementIfAreEqual<ulong>(
                this.logonResponse.FolderIds[4],
                this.getIdFromLongTermIdResponse.ObjectId,
                454,
                @"[In RopIdFromLongTermId ROP Request Buffer] LongTermId: Contains the LongTermID, as specified in [MS-OXCDATA] section 2.2.1.3.1, to be mapped to the Folder ID, as specified in [MS-OXCDATA] sections 2.2.1.1.");

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

            // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R952.
            Site.CaptureRequirementIfAreEqual<ulong>(
                this.logonResponse.FolderIds[4],
                this.getIdFromLongTermIdResponse.ObjectId,
                952,
                @"[In Receiving a RopIdFromLongTermId ROP Request] The server MUST map the same REPLGUID to the same REPLID every time it is queried.");
            #endregion
            #endregion

            #region Step 5: Call RopLongTermIdFromId with the folder id get in step 4.

            this.longTermIdFromIdRequest.ObjectId = this.getIdFromLongTermIdResponse.ObjectId;
            this.oxcstorAdapter.DoRopCall(this.longTermIdFromIdRequest, this.outObjHandle, ROPCommandType.RopLongTermIdFromId, out this.outputBuffer);
            RopLongTermIdFromIdResponse longTermIdFromIdResponse1 = (RopLongTermIdFromIdResponse)this.outputBuffer.RopsList[0];

            Site.Assert.AreEqual<uint>(
                0,
                this.longTermIdFromIdResponse.ReturnValue,
                "0 indicates the ROP succeeds, other value indicates error occurs.");

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

            // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R947.
            Site.CaptureRequirementIfIsTrue(
                longTermIdFromIdResponse1.LongTermId.DatabaseGuid.SequenceEqual(longTermIdForInbox.DatabaseGuid),
                947,
                @"[In Receiving a RopLongTermIdFromId ROP Request] The server MUST map the same REPLID to the same replica GUID (REPLGUID) every time it is queried.");
            #endregion

            #region Step 6: Call RopIdFromLongTermId with a non-existent LongTermId.

            // Create a long term id that does not exist.
            LongTermId notExistlongTermId;
            notExistlongTermId.DatabaseGuid = new byte[longTermIdFromIdResponse.LongTermId.DatabaseGuid.Length];
            notExistlongTermId.GlobalCounter = new byte[longTermIdFromIdResponse.LongTermId.GlobalCounter.Length];
            Array.Copy(this.longTermIdFromIdResponse.LongTermId.DatabaseGuid, notExistlongTermId.DatabaseGuid, notExistlongTermId.DatabaseGuid.Length);
            Array.Copy(this.longTermIdFromIdResponse.LongTermId.GlobalCounter, notExistlongTermId.GlobalCounter, notExistlongTermId.GlobalCounter.Length);
            notExistlongTermId.DatabaseGuid[0] = 0xFF;
            notExistlongTermId.GlobalCounter[0] = 0xFF;
            this.getIdFromLongTermIdRequest.LongTermId.DatabaseGuid = notExistlongTermId.DatabaseGuid;
            this.getIdFromLongTermIdRequest.LongTermId.GlobalCounter = notExistlongTermId.GlobalCounter;
            this.oxcstorAdapter.DoRopCall(this.getIdFromLongTermIdRequest, this.outObjHandle, ROPCommandType.RopIdFromLongTermId, out this.outputBuffer);
            RopIdFromLongTermIdResponse fromLongTermIdResponse1 = (RopIdFromLongTermIdResponse)this.outputBuffer.RopsList[0];
            #endregion

            #region Step 7: Call RopLongTermIdFromId with the invalid object ID get from step 6.

            this.longTermIdFromIdRequest.ObjectId = fromLongTermIdResponse1.ObjectId;
            this.oxcstorAdapter.DoRopCall(this.longTermIdFromIdRequest, this.outObjHandle, ROPCommandType.RopLongTermIdFromId, out this.outputBuffer);
            this.longTermIdFromIdResponse = (RopLongTermIdFromIdResponse)this.outputBuffer.RopsList[0];
            Site.Assert.AreEqual<uint>(0, this.longTermIdFromIdResponse.ReturnValue, "0 indicates the ROP succeeds, other value indicates error occurs.");

            #region Capture MS-OXCSTOR_R950 and MS-OXCSTOR_R1246.
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCSTOR_R950");

            // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R950.
            // Create a nonexistent LongTermId, so the row must be found. 
            // If succeed to get the LongTermId by using Id, 
            // it indicates the row that contains the REPLGUID and a newly assigned REPLID value is added into the table.
            Site.CaptureRequirementIfIsTrue(
                notExistlongTermId.DatabaseGuid.SequenceEqual(this.longTermIdFromIdResponse.LongTermId.DatabaseGuid) && notExistlongTermId.GlobalCounter.SequenceEqual(this.longTermIdFromIdResponse.LongTermId.GlobalCounter),
                950,
                @"[In Receiving a RopIdFromLongTermId ROP Request] If the REPLGUID is not found, the server adds a new entry consisting of the REPLGUID portion of the LongTermID.");

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

            // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R1246
            // Create a nonexistent LongTermId, so the row must be found. 
            // If succeed to get the LongTermId by using Id, 
            // it indicates the row that contains the REPLGUID and a newly assigned REPLID value is added into the table.
            Site.CaptureRequirementIfIsTrue(
                notExistlongTermId.DatabaseGuid.SequenceEqual(this.longTermIdFromIdResponse.LongTermId.DatabaseGuid) && notExistlongTermId.GlobalCounter.SequenceEqual(this.longTermIdFromIdResponse.LongTermId.GlobalCounter),
                1246,
                @"[In Receiving a RopIdFromLongTermId ROP Request] If the REPLGUID is not found, the server adds a newly assigned replica ID (REPLID).");

            #endregion
            #endregion

            #region Step 8: Call RopLongTermIdFromId with setting object ID to zero.

            this.longTermIdFromIdRequest.ObjectId = 0;
            this.oxcstorAdapter.DoRopCall(this.longTermIdFromIdRequest, this.outObjHandle, ROPCommandType.RopLongTermIdFromId, out this.outputBuffer);
            this.longTermIdFromIdResponse = (RopLongTermIdFromIdResponse)this.outputBuffer.RopsList[0];

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

                // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R1337.
                Site.CaptureRequirementIfAreEqual<uint>(
                    0,
                    this.longTermIdFromIdResponse.ReturnValue,
                    1337,
                    @"[In Appendix A: Product Behavior] Implementation does not fail the operation [RopLongTermIdFromId] with 0x8004010F, but ecNone. <43> Section 3.2.5.8: If the ObjectId field is set to zero, Exchange 2013 and Exchange 2016 returns ecNone.");
            }

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

                // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R1355.
                Site.CaptureRequirementIfAreEqual<uint>(
                    0x8004010F,
                    this.longTermIdFromIdResponse.ReturnValue,
                    1355,
                    @"[In Appendix A: Product Behavior] Implementation does fail the operation with 0x8004010F if the REPLID is not in the REPLID and REPLGUID to-and-from mapping table [when the server receiving a RopLongTermIdFromId ROP Request]. (Exchange 2010 and below follow this behavior.)");
            }
            #endregion

            #region Step 9: Create a message in the inbox.
            RopOpenFolderRequest openFolderRequest;
            RopOpenFolderResponse openFolderResponse;
            openFolderRequest.RopId = 0x02;
            openFolderRequest.LogonId = 0x0;
            openFolderRequest.InputHandleIndex = 0x0;
            openFolderRequest.OutputHandleIndex = 0x01;
            openFolderRequest.FolderId = this.logonResponse.FolderIds[4];
            openFolderRequest.OpenModeFlags = 0x0;
            this.oxcstorAdapter.DoRopCall(openFolderRequest, this.outObjHandle, ROPCommandType.Others, out this.outputBuffer);
            openFolderResponse = (RopOpenFolderResponse)this.outputBuffer.RopsList[0];
            this.outObjHandle = this.outputBuffer.ServerObjectHandleTable[openFolderResponse.OutputHandleIndex];

            uint messageHandle = 0;
            ulong messageId = 0;
            messageId = this.CreateMessage(this.logonResponse.FolderIds[4], out messageHandle);

            this.longTermIdFromIdRequest.ObjectId = messageId;
            this.oxcstorAdapter.DoRopCall(this.longTermIdFromIdRequest, this.outObjHandle, ROPCommandType.RopLongTermIdFromId, out this.outputBuffer);
            this.longTermIdFromIdResponse = (RopLongTermIdFromIdResponse)this.outputBuffer.RopsList[0];

            Site.Assert.AreEqual<uint>(
                0,
                this.longTermIdFromIdResponse.ReturnValue,
                "0 indicates the ROP succeeds, other value indicates error occurs.");

            this.getIdFromLongTermIdRequest.LongTermId.DatabaseGuid = this.longTermIdFromIdResponse.LongTermId.DatabaseGuid;
            this.getIdFromLongTermIdRequest.LongTermId.GlobalCounter = this.longTermIdFromIdResponse.LongTermId.GlobalCounter;
            this.oxcstorAdapter.DoRopCall(this.getIdFromLongTermIdRequest, this.outObjHandle, ROPCommandType.RopIdFromLongTermId, out this.outputBuffer);
            this.getIdFromLongTermIdResponse = (RopIdFromLongTermIdResponse)this.outputBuffer.RopsList[0];

            Site.Assert.AreEqual<uint>(
                0,
                this.longTermIdFromIdResponse.ReturnValue,
                "0 indicates the ROP succeeds, other value indicates error occurs.");

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

            // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R59799.
            Site.CaptureRequirementIfAreEqual<ulong>(
                messageId,
                this.getIdFromLongTermIdResponse.ObjectId,
                59799,
                @"[In RopLongTermIdFromId ROP Success Response Buffer] That  [LongTermId] is mapped from the MessageID as specified in[MS-OXCDATA] sections 2.2.4.1 or 2.2.4.2, that is contained in the ObjectID field (section 2.2.1.8.1).");

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

            // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R59724.
            Site.CaptureRequirementIfAreEqual<ulong>(
                messageId,
                this.getIdFromLongTermIdResponse.ObjectId,
                59724,
                @"[In RopIdFromLongTermId ROP Request Buffer] LongTermId: Contains the LongTermID, as specified in [MS-OXCDATA] section 2.2.1.3.1, to be mapped to the Message ID, as specified in [MS-OXCDATA] sections 2.2.1.2.");

            // Delete the created message
            RopHardDeleteMessagesRequest deleteMessageRequest = new RopHardDeleteMessagesRequest
            {
                RopId = (byte)RopId.RopHardDeleteMessages,
                LogonId = 0x00,
                InputHandleIndex = 0x00,
                NotifyNonRead = 0x00,
                MessageIds = new ulong[1]
            };
            deleteMessageRequest.MessageIds[0] = messageId;
            deleteMessageRequest.MessageIdCount = 1;
            this.oxcstorAdapter.DoRopCall(deleteMessageRequest, this.outObjHandle, ROPCommandType.Others, out this.outputBuffer);
            #endregion

            #region Step 10: Disconnect.
            this.returnStatus = this.oxcstorAdapter.DisconnectEx();
            Site.Assert.IsTrue(this.returnStatus, "Disconnection  is successful");
            #endregion

            #region Step 11: Connect the server via user configured by "AdminUserName".
            this.returnStatus = this.oxcstorAdapter.ConnectEx(ConnectionType.PrivateMailboxServer);
            Site.Assert.IsTrue(this.returnStatus, "Connection is successful");
            #endregion

            #region Step 12: Logon to the private mailbox.
            this.oxcstorAdapter.DoRopCall(this.logonRequestForPrivateMailBox, this.insideObjHandle, ROPCommandType.RopLogonPrivateMailbox, out this.outputBuffer);
            RopLogonResponse logonResponse2 = (RopLogonResponse)this.outputBuffer.RopsList[0];
            this.outObjHandle = this.outputBuffer.ServerObjectHandleTable[0];
            Site.Assert.AreEqual<uint>(
                0x00000000,
                logonResponse2.ReturnValue,
                "0 indicates the ROP succeeds, other value indicates error occurs.");
            #endregion

            #region Step 13: Call RopLongTermIdFromId with successful response.

            this.longTermIdFromIdRequest.ObjectId = logonResponse2.FolderIds[4];
            this.oxcstorAdapter.DoRopCall(this.longTermIdFromIdRequest, this.outObjHandle, ROPCommandType.RopLongTermIdFromId, out this.outputBuffer);
            this.longTermIdFromIdResponse = (RopLongTermIdFromIdResponse)this.outputBuffer.RopsList[0];
            LongTermId longTermIdForInbox2 = this.longTermIdFromIdResponse.LongTermId;

            Site.Assert.AreEqual<uint>(
                0,
                this.longTermIdFromIdResponse.ReturnValue,
                "0 indicates the ROP succeeds, other value indicates error occurs.");

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

            bool isVerifyR1242 = longTermIdForInbox2.DatabaseGuid.SequenceEqual(longTermIdForInbox.DatabaseGuid);

            // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R1242.
            Site.CaptureRequirementIfIsTrue(
                isVerifyR1242,
                1242,
                @"[In Receiving a RopLongTermIdFromId ROP Request] But each server MUST map any particular REPLID to the same REPLGUID every time it is queried");

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

            bool isVerifyR1251 = longTermIdForInbox2.DatabaseGuid.SequenceEqual(longTermIdForInbox.DatabaseGuid);

            // Verify MS-OXCSTOR requirement: MS-OXCSTOR_R1251.
            Site.CaptureRequirementIfIsTrue(
                isVerifyR1251,
                1251,
                @"[In Receiving a RopIdFromLongTermId ROP Request] [Other servers can map a particular REPLGUID to a different REPLID,] But each server MUST map any particular REPLGUID to the same REPLID every time it is queried.");

            #endregion
        }