/// <summary>
        /// Deletes one or more messages from a folder.
        /// </summary>
        /// <param name="ropDeleteMessagesRequest">RopDeleteMessagesRequest object.</param>
        /// <param name="insideObjHandle">Server object handle in RopDeleteMessages.</param>
        /// <param name="responseSOHTable">Server objects handles in RopDeleteMessagesResponse.</param>
        /// <returns>RopDeleteMessagesResponse object.</returns>
        public RopDeleteMessagesResponse DeleteMessages(RopDeleteMessagesRequest ropDeleteMessagesRequest, uint insideObjHandle, ref List <List <uint> > responseSOHTable)
        {
            object temp = new object();

            this.ExcuteRopCall((ISerializable)ropDeleteMessagesRequest, insideObjHandle, ref temp, ref responseSOHTable, ref this.rawData);
            RopDeleteMessagesResponse ropDeleteMessagesResponse = (RopDeleteMessagesResponse)temp;

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

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

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

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

            #endregion

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

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

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

            #endregion

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            #endregion

            #endregion

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            RopQueryRowsRequest queryRowsRequest;
            RopQueryRowsResponse queryRowsResponse;

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

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

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

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

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

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

            uint rowCountFirst = getContentsTableResponseFirst.RowCount;
            #endregion

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            #region Verify MS-OXCFOLD_R282 and MS-OXCFOLD_R436.

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

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

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

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

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

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

            #region Verify MS-OXCFOLD_R262 and MS-OXCFOLD_R1017.

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

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

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

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

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

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

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

            #endregion

            #endregion
        }
        public void MSOXCFOLD_S02_TC08_RopDeleteMessagesFailure()
        {
            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. Delete the message created in step 1 with logon object handle.

            RopDeleteMessagesRequest deleteMessagesRequest = new RopDeleteMessagesRequest
            {
                RopId = (byte)RopId.RopDeleteMessages,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                WantAsynchronous = 0x00,
                NotifyNonRead = 0x00,
                MessageIds = new ulong[]
                {
                    messageId
                }
            };
            deleteMessagesRequest.MessageIdCount = (ushort)deleteMessagesRequest.MessageIds.Length;

            // Use logon object handle to delete message is purposed to get an error code ecNotSupported [0x80040102].  
            RopDeleteMessagesResponse deleteMessagesResponse = this.Adapter.DeleteMessages(deleteMessagesRequest, this.LogonHandle, ref this.responseHandles);

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

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

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

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

            #endregion

            #endregion
        }
        /// <summary>
        /// Deletes one or more messages from a folder. 
        /// </summary>
        /// <param name="ropDeleteMessagesRequest">RopDeleteMessagesRequest object.</param>
        /// <param name="insideObjHandle">Server object handle in RopDeleteMessages.</param>
        /// <param name="responseSOHTable">Server objects handles in RopDeleteMessagesResponse.</param>
        /// <returns>RopDeleteMessagesResponse object.</returns>
        public RopDeleteMessagesResponse DeleteMessages(RopDeleteMessagesRequest ropDeleteMessagesRequest, uint insideObjHandle, ref List<List<uint>> responseSOHTable)
        {
            object temp = new object();
            this.ExcuteRopCall((ISerializable)ropDeleteMessagesRequest, insideObjHandle, ref temp, ref responseSOHTable, ref this.rawData);
            RopDeleteMessagesResponse ropDeleteMessagesResponse = (RopDeleteMessagesResponse)temp;

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

            return ropDeleteMessagesResponse;
        }
        public void MSOXCMSG_S05_TC04_OpenSoftDeletedMessage()
        {
            this.CheckMapiHttpIsSupported();
            this.ConnectToServer(ConnectionType.PrivateMailboxServer);

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

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

            #region Call RopCreateMessage to create Message object.
            uint targetMessageHandleForDelete = this.CreatedMessage(logonResponse.FolderIds[4], this.insideObjHandle);
            #endregion

            #region Call RopSaveChangesMessage to save created message.
            RopSaveChangesMessageResponse saveChangesMessageResponse = this.SaveMessage(targetMessageHandleForDelete, (byte)SaveFlags.ForceSave);
            ulong messageIdForDelete = saveChangesMessageResponse.MessageId;
            #endregion

            this.ReleaseRop(targetMessageHandleForDelete);

            #region Call RopDeleteMessages to soft delete created message.
            RopDeleteMessagesRequest deleteMessagesRequest = new RopDeleteMessagesRequest()
            {
                RopId = (byte)RopId.RopDeleteMessages,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,
                WantAsynchronous = 0x00,

                // The server does not generate a non-read receipt for the deleted messages.
                NotifyNonRead = 0x00,
                MessageIdCount = 1,
                MessageIds = new ulong[] { messageIdForDelete },
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(deleteMessagesRequest, openedFolderHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopDeleteMessagesResponse deleteMessagesResponse = (RopDeleteMessagesResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, deleteMessagesResponse.ReturnValue, "Call RopDeleteMessages should success.");
            #endregion

            #region Call RopOpenMessage which OpenModeFlags is not OpenSoftDeleted to open soft deleted message.
            RopOpenMessageRequest openMessageRequest = new RopOpenMessageRequest()
            {
                RopId = (byte)RopId.RopOpenMessage,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,
                OutputHandleIndex = CommonOutputHandleIndex,
                CodePageId = 0x0FFF, // Code page of Logon object is used
                FolderId = logonResponse.FolderIds[4], // Open the message in INBOX folder in which message is created.
                OpenModeFlags = (byte)MessageOpenModeFlags.ReadWrite,
                MessageId = messageIdForDelete // Open the saved message
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(openMessageRequest, this.insideObjHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopOpenMessageResponse openMessageResponse = (RopOpenMessageResponse)this.response;

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R335
            this.Site.CaptureRequirementIfAreEqual<uint>(
                0x8004010F,
                openMessageResponse.ReturnValue,
                335,
                @"[In Receiving a RopOpenMessage ROP Request] [ecNotFound (0x8004010F)] The message is soft deleted and the client has not specified the OpenSoftDeleted flag as part of the OpenModeFlag field.");

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R326
            this.Site.CaptureRequirementIfAreNotEqual<uint>(
                TestSuiteBase.Success,
                openMessageResponse.ReturnValue,
                326,
                @"[In Receiving a RopOpenMessage ROP Request] If the OpenSoftDeleted flag is not included, the server MUST NOT provide access to soft deleted Message objects.");
            #endregion
            #endregion

            #region Call RopRelease to release the created message
            this.ReleaseRop(openedFolderHandle);
            #endregion
        }