/// <summary>
        /// Overrides TestClassBase's TestCleanup()
        /// </summary>
        protected override void TestCleanup()
        {
            bool transportIsMAPI = Common.GetConfigurationPropertyValue("TransportSeq", this.Site).ToLower() == "mapi_http";
            if (!transportIsMAPI || Common.IsRequirementEnabled(1340, this.Site))
            {
                if (!this.needCleanup)
                {
                    return;
                }

                #region Hard Delete Messages and Subfolders of Inbox
                if (this.isRootFolderCreated)
                {
                    RopDeleteFolderRequest deleteFolderRequest = new RopDeleteFolderRequest();
                    RopDeleteFolderResponse deleteFolderResponse;
                    deleteFolderRequest.RopId = (byte)RopId.RopDeleteFolder;
                    deleteFolderRequest.LogonId = Constants.CommonLogonId;
                    deleteFolderRequest.InputHandleIndex = Constants.CommonInputHandleIndex;

                    // Set the DeleteFolderFlags to indicate hard delete the common generic folder,
                    // including all folders and messages under the folder.
                    deleteFolderRequest.DeleteFolderFlags = (byte)DeleteFolderFlags.DelFolders
                        | (byte)DeleteFolderFlags.DelMessages
                        | (byte)DeleteFolderFlags.DeleteHardDelete;
                    deleteFolderRequest.FolderId = this.RootFolderId;

                    int count = 0;
                    bool rootFolderCleanUpSuccess = false;
                    do
                    {
                        deleteFolderResponse = this.Adapter.DeleteFolder(deleteFolderRequest, this.inboxFolderHandle, ref this.responseHandles);
                        if (deleteFolderResponse.ReturnValue == Constants.SuccessCode && deleteFolderResponse.PartialCompletion == 0)
                        {
                            rootFolderCleanUpSuccess = true;
                        }
                        else
                        {
                            Thread.Sleep(this.WaitTime);
                        }

                        if (count > this.RetryCount)
                        {
                            break;
                        }

                        count++;
                    }
                    while (!rootFolderCleanUpSuccess);

                    Site.Assert.IsTrue(rootFolderCleanUpSuccess, "Test case cleanup should succeed.");
                }               
                #endregion

                #region  RopRelease
                RopReleaseRequest releaseRequest = new RopReleaseRequest();
                object ropResponse = null;
                releaseRequest.RopId = (byte)RopId.RopRelease;
                releaseRequest.LogonId = Constants.CommonLogonId;
                releaseRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
                this.Adapter.DoRopCall(releaseRequest, this.LogonHandle, ref ropResponse, ref this.responseHandles);
                #endregion

                this.logonHandle = 0;
                ropResponse = null;
                this.responseHandles = null;
                this.Adapter.DoDisconnect();
            }
        }
        /// <summary>
        /// Delete the specific folder.
        /// </summary>
        /// <param name="serverId">A 32-bit signed integer represent the Identity of server.</param>
        /// <param name="folderHandleIndex">The folder handle index.</param>
        /// <param name="folderIdIndex">The folder id index.</param>
        /// <returns>Indicate the result of this ROP operation.</returns>
        public RopResult DeleteFolder(int serverId, int folderHandleIndex, int folderIdIndex)
        {
            // Initialize ROP operation data.
            uint folderHandle = this.handleContainer[folderHandleIndex];
            ulong folderId = this.objectIdContainer[folderIdIndex];
            RopResult result = RopResult.InvalidParameter;

            // Construct ROP request.
            RopDeleteFolderRequest deleteFolderRequest = new RopDeleteFolderRequest
            {
                RopId = 0x1D,
                LogonId = 0x00,
                InputHandleIndex = 0x00,
                DeleteFolderFlags = 0x15,
                FolderId = folderId
            };

            // DEL_MESSAGES, DEL_FOLDERS and DELETE_HARD_DELETE.

            // Send request and get response.
            RopDeleteFolderResponse deleteFolderResponse = (RopDeleteFolderResponse)this.Process(serverId, deleteFolderRequest, folderHandle);
            result = (RopResult)deleteFolderResponse.ReturnValue;

            if (result == RopResult.Success)
            {
                this.objectIdContainer.Remove(folderIdIndex);
            }

            return result;
        }
        /// <summary>
        /// Delete the specific folder.
        /// </summary>
        /// <param name="serverId">A 32-bit signed integer represent the Identity of server.</param>
        /// <param name="folderHandle">The folder handle</param>
        /// <param name="folderId">The folder id</param>
        /// <returns>Indicate the result of this ROP operation</returns>
        public RopResult DeleteFolder(int serverId, uint folderHandle, ulong folderId)
        {
            // Initialize ROP operation data.
            RopResult result = RopResult.InvalidParameter;

            // Construct ROP request.
            RopDeleteFolderRequest deleteFolderRequest = new RopDeleteFolderRequest
            {
                RopId = 0x1D,
                LogonId = 0x00,
                InputHandleIndex = 0x00,

                // DEL_MESSAGES, DEL_FOLDERS and DELETE_HARD_DELETE.
                DeleteFolderFlags = 0x15,
                FolderId = folderId
            };

            // Send request and get response.
            RopDeleteFolderResponse deleteFolderResponse = (RopDeleteFolderResponse)this.Process(serverId, deleteFolderRequest, folderHandle);
            result = (RopResult)deleteFolderResponse.ReturnValue;
            return result;
        }
        public void MSOXCFOLD_S03_TC05_RopGetHierarchyTableSuccess()
        {
            this.CheckWhetherSupportTransport();
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            this.GenericFolderInitialization();

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

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

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

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

            #endregion

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

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

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

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

            #endregion

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

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

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

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

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

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

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

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

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

            RopGetHierarchyTableRequest getHierarchyTableRequest = new RopGetHierarchyTableRequest
            {
                RopId = (byte)RopId.RopGetHierarchyTable,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                TableFlags = (byte)FolderTableFlags.None
            };
            RopGetHierarchyTableResponse getHierarchyTableResponse = this.Adapter.GetHierarchyTable(getHierarchyTableRequest, this.RootFolderHandle, ref this.responseHandles);

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

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

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

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

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

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

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

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

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

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

            #endregion

            #endregion

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

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

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

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

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

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

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

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

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

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

            #endregion

            #endregion

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

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

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

            #endregion

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

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

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

            #endregion

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            #endregion

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

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

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

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R808");
        
            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R808
            this.Site.CaptureRequirementIfAreEqual<string>(
                Constants.Subfolder1,
                pidTagDisplayNameNoUseUnicodeFlag,
                808,
                @"[In RopGetHierarchyTable ROP Request Buffer] TableFlags (1 byte): If this bit [UseUnicode (0x40)] is not set, the string data is encoded in the code page of the Logon object.");
            #endregion
        }
        public void MSOXCFOLD_S03_TC07_GetReadOnlyProperties()
        {
            this.CheckWhetherSupportTransport();
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            this.GenericFolderInitialization();

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

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

            #endregion

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

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

            #endregion

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

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

            #endregion

            #region Step 4. The client gets the read-only properties from [MSOXCFOLDSubfolder1].

            PropertyTag[] propertyTagArray = new PropertyTag[11];

            PropertyTag propertyTag = new PropertyTag
            {
                PropertyId = (ushort)FolderPropertyId.PidTagContentCount,
                PropertyType = (ushort)PropertyType.PtypInteger32
            };
            propertyTagArray[0] = propertyTag;

            propertyTag = new PropertyTag
            {
                PropertyId = (ushort)FolderPropertyId.PidTagContentUnreadCount,
                PropertyType = (ushort)PropertyType.PtypInteger32
            };
            propertyTagArray[1] = propertyTag;

            propertyTag = new PropertyTag
            {
                PropertyId = (ushort)FolderPropertyId.PidTagDeletedOn,
                PropertyType = (ushort)PropertyType.PtypTime
            };
            propertyTagArray[2] = propertyTag;

            propertyTag = new PropertyTag
            {
                PropertyId = (ushort)FolderPropertyId.PidTagFolderId,
                PropertyType = (ushort)PropertyType.PtypInteger64
            };
            propertyTagArray[3] = propertyTag;

            propertyTag = new PropertyTag
            {
                PropertyId = (ushort)FolderPropertyId.PidTagParentEntryId,
                PropertyType = (ushort)PropertyType.PtypBinary
            };
            propertyTagArray[4] = propertyTag;

            propertyTag = new PropertyTag
            {
                PropertyId = (ushort)FolderPropertyId.PidTagHierarchyChangeNumber,
                PropertyType = (ushort)PropertyType.PtypInteger32
            };
            propertyTagArray[5] = propertyTag;

            propertyTag = new PropertyTag
            {
                PropertyId = (ushort)FolderPropertyId.PidTagSubfolders,
                PropertyType = (ushort)0x000B
            };
            propertyTagArray[6] = propertyTag;

            propertyTag = new PropertyTag
            {
                PropertyId = (ushort)FolderPropertyId.PidTagMessageSize,
                PropertyType = (ushort)PropertyType.PtypInteger32
            };
            propertyTagArray[7] = propertyTag;

            propertyTag = new PropertyTag
            {
                PropertyId = (ushort)FolderPropertyId.PidTagMessageSizeExtended,
                PropertyType = (ushort)PropertyType.PtypInteger64
            };
            propertyTagArray[8] = propertyTag;

            propertyTag = new PropertyTag
            {
                PropertyId = (ushort)FolderPropertyId.PidTagDeletedCountTotal,
                PropertyType = (ushort)PropertyType.PtypInteger32
            };
            propertyTagArray[9] = propertyTag;

            propertyTag = new PropertyTag
            {
                PropertyId = (ushort)FolderPropertyId.PidTagHierRev,
                PropertyType = (ushort)PropertyType.PtypTime
            };
            propertyTagArray[10] = propertyTag;

            RopGetPropertiesSpecificRequest getPropertiesSpecificRequest = new RopGetPropertiesSpecificRequest();
            RopGetPropertiesSpecificResponse getPropertiesSpecificResponse;
            getPropertiesSpecificRequest.RopId = (byte)RopId.RopGetPropertiesSpecific;
            getPropertiesSpecificRequest.LogonId = Constants.CommonLogonId;
            getPropertiesSpecificRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            getPropertiesSpecificRequest.PropertySizeLimit = 0xFFFF;
            getPropertiesSpecificRequest.PropertyTagCount = (ushort)propertyTagArray.Length;
            getPropertiesSpecificRequest.PropertyTags = propertyTagArray;

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

            #region Verify the requirements: MS-OXCFOLD_R10347, MS-OXCFOLD_R10345, MS-OXCFOLD_R346, MS-OXCFOLD_R10351 and MS-OXCFOLD_R1030, MS-OXCFOLD_R10027, MS-OXCFOLD_R10353, MS-OXCFOLD_R10354, MS-OXCFOLD_R352001 and MS-OXCFOLD_R352002.
            uint pidTagMessageSize = BitConverter.ToUInt32(getPropertiesSpecificResponse1.RowData.PropertyValues[7].Value, 0);
            
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R10353");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R10353
            Site.CaptureRequirementIfAreNotEqual<uint>(
                0,
                pidTagMessageSize,
                10353,
                @"[In PidTagMessageSize Property] The PidTagMessageSize property ([MS-OXPROPS] section 2.787) specifies the aggregate size of messages in the folder.");
            ulong pidTagMessageSizeExtended = BitConverter.ToUInt64(getPropertiesSpecificResponse1.RowData.PropertyValues[8].Value, 0);
            
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R10354: the 64 bit value of the pidTagMessageSize property is {0}, and the value of the pidTagMessageSizeExtended is {1}", pidTagMessageSize, pidTagMessageSizeExtended);

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R10354
            Site.CaptureRequirementIfAreEqual<ulong>(
                (ulong)pidTagMessageSize,
                pidTagMessageSizeExtended,
                10354,
                @"[In PidTagMessageSizeExtended Property] The PidTagMessageSizeExtended property ([MS-OXPROPS] section 2.788) specifies the 64-bit version of the PidTagMessageSize property (section 2.2.2.2.1.7).");

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

            // Client call RopGetPropertiesSpecific to get the PidTagMessageSizeExtended property.
            // If the value of PidTagMessageSizeExtended property can return and type of this property is ulong, then R354 will be verified.
            Site.CaptureRequirementIfIsInstanceOfType(
                pidTagMessageSizeExtended,
                typeof(ulong),
                354,
                @"[In PidTagMessageSizeExtended Property] Type: PtypInteger64 ([MS-OXCDATA] section 2.11.1)");

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

            Site.CaptureRequirementIfIsInstanceOfType(
                pidTagMessageSizeExtended,
                typeof(ulong),
                Constants.MSOXPROPS,
                7009,
                @"[In PidTagMessageSizeExtended] Data type: PtypInteger64, 0x0014.");

            // [MSOXCFOLDSubfolder1] should have no unread message.
            uint unreadMessagesCountExpect = 0;

            // The index of PidTagContentUnreadCount is 1 according to the RopGetPropertiesSpecific ROP request.
            uint unreadMessagesCountActual = BitConverter.ToUInt32(getPropertiesSpecificResponse1.RowData.PropertyValues[1].Value, 0);

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R10347.
            Site.CaptureRequirementIfAreEqual<uint>(
                unreadMessagesCountExpect,
                unreadMessagesCountActual,
                10347,
                @"[In PidTagContentUnreadCount Property] The PidTagContentUnreadCount property ([MS-OXPROPS] section 2.639) specifies the number of unread messages in a folder, as computed by the message store.");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R10345
            Site.CaptureRequirementIfAreEqual<int>(
                1,
                BitConverter.ToInt32(getPropertiesSpecificResponse1.RowData.PropertyValues[0].Value, 0),
                10345,
                @"[In PidTagContentCount Property] The PidTagContentCount property ([MS-OXPROPS] section 2.637) specifies the number of messages in a folder, as computed by the message store.");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R346
            Site.CaptureRequirementIfAreEqual<int>(
                1,
                BitConverter.ToInt32(getPropertiesSpecificResponse1.RowData.PropertyValues[0].Value, 0),
                346,
                @"[In PidTagContentCount Property] The value does not include FAI entries in the folder.");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R10351
            Site.CaptureRequirementIfAreEqual<ulong>(
                subfolderId1,
                BitConverter.ToUInt64(getPropertiesSpecificResponse1.RowData.PropertyValues[3].Value, 0),
                10351,
                @"[In PidTagFolderId Property] The PidTagFolderId property ([MS-OXPROPS] section 2.691) contains a FID structure ([MS-OXCDATA] section 2.2.1.1) that uniquely identifies a folder.");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1030
            Site.CaptureRequirementIfAreEqual<bool>(
                false,
                BitConverter.ToBoolean(getPropertiesSpecificResponse1.RowData.PropertyValues[6].Value, 0),
                1030,
                @"[In PidTagSubfolders Property] [if the folder does not have subfolders,] the value is zero otherwise.");

            uint pidTagDeletedCountTotal = BitConverter.ToUInt32(getPropertiesSpecificResponse1.RowData.PropertyValues[9].Value, 0);

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R3006");
        
            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R3006
            // Because no message has been deleted on [MSOXCFOLDSubfolder1]. So if the PidTagDeletedCountTotal property is 0, then R3006 will be verified.
            this.Site.CaptureRequirementIfAreEqual<uint>(
                0,
                pidTagDeletedCountTotal,
                3006,
                @"[In PidTagDeletedCountTotal Property] The PidTagDeletedCountTotal property ([MS-OXPROPS] section 2.660) specifies the total number of messages that have been deleted from a folder, excluding messages that have been deleted from the folder's subfolders.");
 
            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R352001");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R352001
            Site.CaptureRequirementIfAreEqual<ushort>(
                (ushort)PropertyType.PtypTime,
                propertyTagArray[10].PropertyType,
                352001,
                "[In PidTagHierRev Property] Type: PtypTime ([MS-OXCDATA] section 2.11.1)");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R352002
            // If the property value in getPropertiesSpecificResponse1 is not null, then the PidTagHierRev property is returned from server.
            this.Site.CaptureRequirementIfIsTrue(
                getPropertiesSpecificResponse1.RowData.PropertyValues[10].Value.Length > 0,
                352002,
                @"[In PidTagHierRev Property] The PidTagHierRev property ([MS-OXPROPS] section 2.712) specifies the time, in Coordinated Universal Time (UTC), to trigger the client in cached mode to synchronize the folder hierarchy.");
            #endregion

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

            uint subfolderHandle2 = 0;
            ulong subfolderId2 = 0;
            this.CreateFolder(subfolderHandle1, Constants.Subfolder2, ref subfolderId2, ref subfolderHandle2);

            #endregion

            #region Step 6. The client gets the read-only properties from [MSOXCFOLDSubfolder1] after creating [MSOXCFOLDSubfolder2] under [MSOXCFOLDSubfolder1].

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

            #endregion

            #region Verify the requirements: MS-OXCFOLD_R1029, MS-OXCFOLD_R10355.

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R1029
            Site.CaptureRequirementIfIsTrue(
                BitConverter.ToBoolean(getPropertiesSpecificResponse.RowData.PropertyValues[6].Value, 0),
                1029,
                @"[In PidTagSubfolders Property] The value of this property [PidTagSubfolders] is nonzero if the folder has subfolders.");

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

            // MS-OXCFOLD_R1029 and MS-OXCFOLD_R1030 is verified, MS-OXCFOLD_R10355 can be verified directly.
            Site.CaptureRequirement(
                10355,
                @"[In PidTagSubfolders Property] The PidTagSubfolders property ([MS-OXPROPS] section 2.1022) specifies whether the folder has any subfolders.");

            #endregion

            #region Step 7. The client calls RopDeleteFolder to delete [MSOXCFOLDSubfolder2] under [MSOXCFOLDSubfolder1].

            RopDeleteFolderRequest deleteFolderRequest = new RopDeleteFolderRequest
            {
                RopId = (byte)RopId.RopDeleteFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                DeleteFolderFlags = (byte)DeleteFolderFlags.DelFolders | (byte)DeleteFolderFlags.DelMessages,
                FolderId = subfolderId2
            };
            RopDeleteFolderResponse deleteFolderResponse = this.Adapter.DeleteFolder(deleteFolderRequest, subfolderHandle1, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(0, deleteFolderResponse.ReturnValue, "RopDeleteFolderResponse ROP operation performs successfully!");
            #endregion

            #region Step 8. The client gets the read-only properties from [MSOXCFOLDSubfolder1] after deleting [MSOXCFOLDSubfolder2] under [MSOXCFOLDSubfolder1].

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

            #region Verify the requirements: MS-OXCFOLD_R10028, MS-OXCFOLD_R352.

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R10028, the value of property PidTagHierarchyChangeNumber after getting the read-only properties from [MSOXCFOLDSubfolder1] is {0}, the value of property PidTagHierarchyChangeNumber after getting the read-only properties from [MSOXCFOLDSubfolder1] after creating [MSOXCFOLDSubfolder2] under [MSOXCFOLDSubfolder1] is {1}, the value of property PidTagHierarchyChangeNumber after getting the read-only properties from [MSOXCFOLDSubfolder1] after deleting [MSOXCFOLDSubfolder2] under [MSOXCFOLDSubfolder1] is {2}.", getPropertiesSpecificResponse1.RowData.PropertyValues[5].Value, getPropertiesSpecificResponse2.RowData.PropertyValues[5].Value, getPropertiesSpecificResponse.RowData.PropertyValues[5].Value);

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R10028
            bool changeNumberIncreased =
                BitConverter.ToInt32(getPropertiesSpecificResponse1.RowData.PropertyValues[5].Value, 0) < BitConverter.ToInt32(getPropertiesSpecificResponse2.RowData.PropertyValues[5].Value, 0) &&
                BitConverter.ToInt32(getPropertiesSpecificResponse2.RowData.PropertyValues[5].Value, 0) < BitConverter.ToInt32(getPropertiesSpecificResponse.RowData.PropertyValues[5].Value, 0);

            Site.CaptureRequirementIfIsTrue(
                changeNumberIncreased,
                10028,
                @"[In PidTagHierarchyChangeNumber Property] The PidTagHierarchyChangeNumber property ([MS-OXPROPS] section 2.711) specifies the number of subfolders in the folder.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R352, the value of property PidTagHierarchyChangeNumber after getting the read-only properties from [MSOXCFOLDSubfolder1] is {0}, the value of property PidTagHierarchyChangeNumber after getting the read-only properties from [MSOXCFOLDSubfolder1] after creating [MSOXCFOLDSubfolder2] under [MSOXCFOLDSubfolder1] is {1}, the value of property PidTagHierarchyChangeNumber after getting the read-only properties from [MSOXCFOLDSubfolder1] after deleting [MSOXCFOLDSubfolder2] under [MSOXCFOLDSubfolder1] is {2}.", getPropertiesSpecificResponse1.RowData.PropertyValues[5].Value, getPropertiesSpecificResponse2.RowData.PropertyValues[5].Value, getPropertiesSpecificResponse.RowData.PropertyValues[5].Value);

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R352.
            Site.CaptureRequirementIfIsTrue(
                changeNumberIncreased,
                352,
                @"[In PidTagHierarchyChangeNumber Property] The value of this property [PidTagHierarchyChangeNumber] monotonically increases every time a subfolder is added to or deleted from the folder.");

            #endregion
            #endregion
        }
        public void MSOXCFOLD_S05_TC05_RopDeleteFolderPermissionValidation()
        {
            this.CheckWhetherSupportTransport();
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            this.GenericFolderInitialization();
            uint pidTagMemberRights;
            uint logonHandle;

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

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

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

            #region Step 2. Create a subfolder [MSOXCFOLDSubfolder1] in the root folder and assign FolderVisible for common user on the new folder.
            uint adminSubfolderHandle1 = 0;
            ulong adminSubfolderId1 = 0;
            this.CreateFolder(this.RootFolderHandle, Constants.Subfolder1, ref adminSubfolderId1, ref adminSubfolderHandle1);

            pidTagMemberRights = (uint)PidTagMemberRightsEnum.FolderVisible;
            this.AddPermission(this.commonUserEssdn, pidTagMemberRights, adminSubfolderHandle1);
            #endregion

            #region Step 3. Create a subfolder [MSOXCFOLDSubfolder2] in the root folder and assign full permission for common user on the new folder.
            uint adminSubfolderHandle2 = 0;
            ulong adminSubfolderId2 = 0;
            this.CreateFolder(this.RootFolderHandle, Constants.Subfolder2, ref adminSubfolderId2, ref adminSubfolderHandle2);

            pidTagMemberRights = (uint)PidTagMemberRightsEnum.FullPermission;
            this.AddPermission(this.commonUserEssdn, pidTagMemberRights, adminSubfolderHandle2);
            #endregion

            #region Step 4. The common user logon the private mailbox and open the root folder and [MSOXCFOLDSubfolder1].

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

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

            // Find and open the folder named [MSOXCFOLDSubfolder1].
            ulong commonUserSubfolder1 = this.GetSubfolderIDByName(commonUserRootFolderId, logonHandle, Constants.Subfolder1);
            uint commonUserRootSubfolderHandle1 = 0;
            this.OpenFolder(logonHandle, commonUserSubfolder1, ref commonUserRootSubfolderHandle1);

            // Find and open the folder named [MSOXCFOLDSubfolder2].
            ulong commonUserSubfolder2 = this.GetSubfolderIDByName(commonUserRootFolderId, commonUserRootFolderHandle, Constants.Subfolder2);
            uint commonUserRootSubfolderHandle2 = 0;
            this.OpenFolder(logonHandle, commonUserSubfolder2, ref commonUserRootSubfolderHandle2);
            #endregion

            #region Step 5. Delete the folder [MSOXCFOLDSubfolder1], the expected error is ecAccessDenied.
            RopDeleteFolderRequest ropDeleteFolderRequest = new RopDeleteFolderRequest
            {
                RopId = 0x1D,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                DeleteFolderFlags = (byte)DeleteFolderFlags.DeleteHardDelete,
                FolderId = commonUserSubfolder1
            };
            RopDeleteFolderResponse ropDeleteFolderResponse = this.Adapter.DeleteFolder(ropDeleteFolderRequest, commonUserRootFolderHandle, ref this.responseHandles);

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R2500
                Site.CaptureRequirementIfAreEqual<uint>(
                    0x80070005,
                    ropDeleteFolderResponse.ReturnValue,
                    2500,
                    @"[In Processing a RopDeleteFolder ROP Request] The value of error code ecAccessDenied is 0x80070005.");

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R503
                Site.CaptureRequirementIfAreEqual<uint>(
                    0x80070005,
                    ropDeleteFolderResponse.ReturnValue,
                    503,
                    @"[In Processing a RopDeleteFolder ROP Request] When the error code is ecAccessDenied, it indicates the client does not have permissions to delete this folder.");
            }

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R408.
                Site.CaptureRequirementIfAreNotEqual<uint>(
                    0,
                    ropDeleteFolderResponse.PartialCompletion,
                    408,
                    @"[In Deleting a Folder] The PartialCompletion field of the ROP response, as specified in section 2.2.1.3.2, indicates whether there are any subfolders or messages that could not be deleted and, consequently, that the folder was not deleted.");
            }
            #endregion

            #region The common user delete the folder [MSOXCFOLDSubfolder2].
            ropDeleteFolderRequest = new RopDeleteFolderRequest
            {
                RopId = 0x1D,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                DeleteFolderFlags = (byte)DeleteFolderFlags.DeleteHardDelete,
                FolderId = commonUserSubfolder2
            };
            ropDeleteFolderResponse = this.Adapter.DeleteFolder(ropDeleteFolderRequest, commonUserRootFolderHandle, ref this.responseHandles);
            Site.Assert.AreEqual<uint>(Constants.SuccessCode, ropDeleteFolderResponse.ReturnValue, "RopDeleteFolder ROP operation performs successfully!");

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R405
            Site.CaptureRequirementIfAreEqual<byte>(
                0,
                ropDeleteFolderResponse.PartialCompletion,
                405,
                @"[In Deleting a Folder] To be deleted, a folder MUST exist, and the client needs the access rights to delete it.");
            #endregion
        }
        /// <summary>
        /// Overrides TestClassBase's TestCleanup()
        /// </summary>
        protected override void TestCleanup()
        {
            if (this.NeedCleanup == false)
            {
                return;
            }

            // Reinitialize to connect to the server use administrator for test cleanup.
            this.Adapter.DoDisconnect();
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            uint logonHandle = 0;
            this.Logon(LogonFlags.Private, out logonHandle);
            ulong folderId = this.GetSubfolderIDByName(this.DefaultFolderIds[this.inboxIndex], logonHandle, this.RootFolder);

            if (folderId != 0)
            {
                uint inboxFolderHandle = 0;
                this.OpenFolder(logonHandle, this.DefaultFolderIds[this.inboxIndex], ref inboxFolderHandle);

                RopDeleteFolderRequest deleteFolderRequest = new RopDeleteFolderRequest();
                RopDeleteFolderResponse deleteFolderResponse;
                deleteFolderRequest.RopId = (byte)RopId.RopDeleteFolder;
                deleteFolderRequest.LogonId = Constants.CommonLogonId;
                deleteFolderRequest.InputHandleIndex = Constants.CommonInputHandleIndex;

                // Set the DeleteFolderFlags to indicate hard delete the common generic folder,
                // including all folders and messages under the folder.
                deleteFolderRequest.DeleteFolderFlags = (byte)DeleteFolderFlags.DelFolders
                    | (byte)DeleteFolderFlags.DelMessages
                    | (byte)DeleteFolderFlags.DeleteHardDelete;
                deleteFolderRequest.FolderId = this.RootFolderId;

                int count = 0;
                bool rootFolderCleanUpSuccess = false;
                do
                {
                    deleteFolderResponse = this.Adapter.DeleteFolder(deleteFolderRequest, inboxFolderHandle, ref this.responseHandles);
                    if (deleteFolderResponse.ReturnValue == Constants.SuccessCode && deleteFolderResponse.PartialCompletion == 0)
                    {
                        rootFolderCleanUpSuccess = true;
                    }
                    else
                    {
                        Thread.Sleep(this.WaitTime);
                    }

                    if (count > this.RetryCount)
                    {
                        break;
                    }

                    count++;
                }
                while (!rootFolderCleanUpSuccess);
            }

            #region  RopRelease
            RopReleaseRequest releaseRequest = new RopReleaseRequest();
            object ropResponse = null;
            releaseRequest.RopId = (byte)RopId.RopRelease;
            releaseRequest.LogonId = Constants.CommonLogonId;
            releaseRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            this.Adapter.DoRopCall(releaseRequest, this.LogonHandle, ref ropResponse, ref this.responseHandles);
            #endregion

            this.responseHandles = null;
            this.Adapter.DoDisconnect();
            this.Adapter.Reset();
        }
        public void MSOXCFOLD_S04_TC03_RopDeletePublicFolder()
        {
            this.CheckWhetherSupportTransport();
            this.Logon();
            this.PublicFolderInitialization();

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

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

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

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

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

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

            #endregion

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

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

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

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

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

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

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

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

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

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

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

            #endregion
        }
        /// <summary>
        /// This ROP deletes a folder and its contents.
        /// </summary>
        /// <param name="handle">The handle of the folder to be deleted.</param>
        /// <param name="folderId">The Id of the folder to be deleted.</param>
        /// <returns>The response of this ROP</returns>
        private RopDeleteFolderResponse RopDeleteFolder(uint handle, ulong folderId)
        {
            this.rawDataValue = null;
            this.responseValue = null;
            this.responseSOHsValue = null;

            RopDeleteFolderRequest deleteFolderRequest = new RopDeleteFolderRequest()
            {
                RopId = (byte)RopId.RopDeleteFolder,
                LogonId = LogonId,
                InputHandleIndex = (byte)HandleIndex.FirstIndex,
                DeleteFolderFlags = 0x15,
                FolderId = folderId,
            };

            this.responseSOHsValue = this.ProcessSingleRop(deleteFolderRequest, handle, ref this.responseValue, ref this.rawDataValue, RopResponseType.SuccessResponse);
            RopDeleteFolderResponse deleteFolderResponse = (RopDeleteFolderResponse)this.responseValue;
            this.Site.Assert.IsNotNull(deleteFolderResponse, string.Format("RopDeleteFolderResponse Failed! Error: 0x{0:X8}", deleteFolderResponse.ReturnValue));
            return deleteFolderResponse;
        }
        public void MSOXCMSG_S04_TC04_RetentionAndArchivePropertiesOnFolder()
        {
            this.CheckMapiHttpIsSupported();
            this.ConnectToServer(ConnectionType.PrivateMailboxServer);

            RopLogonResponse logonResponse = this.Logon(LogonType.Mailbox, out this.insideObjHandle);

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

            #region Call RopCreateFolder to create a new folder.
            ulong folderId;
            this.CreateSubFolder(openedFolderHandle, out folderId);
            #endregion

            #region Call RopOpenFolder to open a folder create by above step.
            uint openSubfolderHandle = this.OpenSpecificFolder(folderId, this.insideObjHandle);
            #endregion

            #region Call RopSetProperties to set properties of retention and archive.
            List<PropertyObj> propertyList = new List<PropertyObj>
            {
                new PropertyObj(PropertyNames.PidTagArchiveTag, PropertyHelper.GetBinaryFromGeneral(Guid.NewGuid().ToByteArray())),
                new PropertyObj(PropertyNames.PidTagPolicyTag, PropertyHelper.GetBinaryFromGeneral(Guid.NewGuid().ToByteArray())),
                new PropertyObj(PropertyNames.PidTagRetentionPeriod, BitConverter.GetBytes(0x00000001))
            };
            List<byte> lstBytes = new List<byte>();
            lstBytes.AddRange(BitConverter.GetBytes(0x00000001));
            lstBytes.AddRange(BitConverter.GetBytes(DateTime.Parse(TestDataOfDateTime).ToFileTimeUtc()));
            propertyList.Add(new PropertyObj(PropertyNames.PidTagStartDateEtc, PropertyHelper.GetBinaryFromGeneral(lstBytes.ToArray())));
            propertyList.Add(new PropertyObj(PropertyNames.PidTagRetentionDate, BitConverter.GetBytes(DateTime.Parse(TestDataOfDateTime).ToFileTimeUtc())));
            propertyList.Add(new PropertyObj(PropertyNames.PidTagRetentionFlags, BitConverter.GetBytes(0x00000002)));
            propertyList.Add(new PropertyObj(PropertyNames.PidTagArchivePeriod, BitConverter.GetBytes(0x00000002)));
            propertyList.Add(new PropertyObj(PropertyNames.PidTagArchiveDate, BitConverter.GetBytes(DateTime.Parse(TestDataOfDateTime).ToFileTimeUtc())));

            this.SetPropertiesForMessage(openSubfolderHandle, propertyList);
            #endregion

            #region Call RopGetPropertiesAll to get all properties of the created folder.
            RopGetPropertiesAllRequest getPropertiesAllRequest = new RopGetPropertiesAllRequest()
            {
                RopId = (byte)RopId.RopGetPropertiesAll,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,

                // Set PropertySizeLimit,which specifies the maximum size allowed for a property value returned,
                // as specified in [MS-OXCROPS] section 2.2.8.4.1.
                PropertySizeLimit = 0xFFFF,
                WantUnicode = 1
            };

            // In process, call capture code to verify adapter requirement
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(getPropertiesAllRequest, openSubfolderHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopGetPropertiesAllResponse getPropertiesAllResponse = (RopGetPropertiesAllResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, getPropertiesAllResponse.ReturnValue, "Call RopGetPropertiesAll should success.");
            List<PropertyObj> ps = PropertyHelper.GetPropertyObjFromBuffer(getPropertiesAllResponse);

            #region Verify requirements
            PropertyObj pidTagArchiveTag = PropertyHelper.GetPropertyByName(ps, PropertyNames.PidTagArchiveTag);

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R1818
            this.Site.CaptureRequirementIfIsNotNull(
                pidTagArchiveTag,
                2195,
                @"[In PidTagArchiveTag Property] [In PidTagArchiveTag Property] The PidTagArchiveTag property can be present on folders.");

            PropertyObj pidTagPolicyTag = PropertyHelper.GetPropertyByName(ps, PropertyNames.PidTagPolicyTag);

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R1819
            this.Site.CaptureRequirementIfIsNotNull(
                pidTagPolicyTag,
                2114,
                @"[In PidTagPolicyTag Property] The PidTagPolicyTag property can be present on folders.");

            PropertyObj pidTagRetentionPeriod = PropertyHelper.GetPropertyByName(ps, PropertyNames.PidTagRetentionPeriod);

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R1820
            this.Site.CaptureRequirementIfIsNotNull(
                pidTagRetentionPeriod,
                2120,
                @"[In PidTagRetentionPeriod Property] The PidTagRetentionPeriod property can be present on folders.");

            PropertyObj pidTagRetentionFlags = PropertyHelper.GetPropertyByName(ps, PropertyNames.PidTagRetentionFlags);

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R1822
            this.Site.CaptureRequirementIfIsNotNull(
                pidTagRetentionFlags,
                2150,
                @"[In PidTagRetentionFlags Property] The PidTagRetentionFlags property can be present on folders.");

            PropertyObj pidTagArchivePeriod = PropertyHelper.GetPropertyByName(ps, PropertyNames.PidTagArchivePeriod);

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R1823
            this.Site.CaptureRequirementIfIsNotNull(
                pidTagArchivePeriod,
                2166,
                @"[In PidTagArchivePeriod Property] The PidTagArchivePeriod property can be present on folders.");
            #endregion
            #endregion

            #region Call RopDeleteFolder to delete the folder created by above step.
            RopDeleteFolderRequest deleteFolderRequest = new RopDeleteFolderRequest()
            {
                RopId = (byte)RopId.RopDeleteFolder,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,
                DeleteFolderFlags = (byte)DeleteFolderFlags.DeleteHardDelete | (byte)DeleteFolderFlags.DelMessages,
                FolderId = folderId // Folder to be deleted
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(deleteFolderRequest, openedFolderHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopDeleteFolderResponse deleteFolderresponse = (RopDeleteFolderResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, deleteFolderresponse.ReturnValue, "Call RopDeleteFolder should success.");
            #endregion

            #region Call RopRelease to release all resources
            this.ReleaseRop(openSubfolderHandle);
            this.ReleaseRop(openedFolderHandle);
            #endregion
        }
        /// <summary>
        /// Overrides TestClassBase's TestCleanup()
        /// </summary>
        protected override void TestCleanup()
        {
            if (this.NeedCleanup == true)
            {
                RopDeleteFolderRequest deleteFolderRequest = new RopDeleteFolderRequest
                {
                    RopId = (byte)RopId.RopDeleteFolder,
                    LogonId = Constants.CommonLogonId,
                    InputHandleIndex = Constants.CommonInputHandleIndex,
                    DeleteFolderFlags =
                        (byte)DeleteFolderFlags.DelMessages | (byte)DeleteFolderFlags.DelFolders |
                        (byte)DeleteFolderFlags.DeleteHardDelete,
                    FolderId = this.publicRootFolderId
                };
                RopDeleteFolderResponse deleteFolderResponse = this.Adapter.DeleteFolder(deleteFolderRequest, this.publicFoldersHandle, ref this.responseHandles);
                Site.Assert.AreEqual<uint>(0, deleteFolderResponse.ReturnValue, "RopDeleteFolderResponse ROP operation performs successfully!");

                #region  Roprelease
                RopReleaseRequest releaseRequest = new RopReleaseRequest();
                object ropResponse = null;
                releaseRequest.RopId = (byte)RopId.RopRelease;
                releaseRequest.LogonId = Constants.CommonLogonId;
                releaseRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
                this.Adapter.DoRopCall(releaseRequest, this.LogonHandle, ref ropResponse, ref this.responseHandles);
                #endregion

                this.publicLogonHandle = 0;
                this.responseHandles = null;
                this.Adapter.DoDisconnect();
            }
        }
        /// <summary>
        /// Test cleanup method
        /// </summary>
        protected override void TestCleanup()
        {
            if (this.isCreatePulbicFolder == true)
            {
                this.isNotNeedCleanupPrivateMailbox = true;

                #region Call RopLogon to logon the public folder.
                RopLogonResponse logonResponse = this.Logon(LogonType.PublicFolder, out this.insideObjHandle);
                #endregion

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

                #region Call RopDeleteFolder to delete the public folder created by test case
                RopDeleteFolderRequest deleteFolderRequest = new RopDeleteFolderRequest()
                {
                    RopId = (byte)RopId.RopDeleteFolder,
                    LogonId = CommonLogonId,
                    InputHandleIndex = CommonInputHandleIndex,
                    DeleteFolderFlags = 0x01, // The folder and all of the Message objects in the folder are deleted.
                    FolderId = this.publicFolderID // Folder to be deleted
                };
                this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(deleteFolderRequest, openedFolderHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
                RopDeleteFolderResponse deleteFolderResponse = (RopDeleteFolderResponse)this.response;
                Site.Assert.AreEqual<uint>(0x0000000, deleteFolderResponse.ReturnValue, "Delete Pulbic Folder should be success.");
                this.isCreatePulbicFolder = false;
                #endregion
            }

            base.TestCleanup();
        }
        /// <summary>
        /// Removes a subfolder. 
        /// </summary>
        /// <param name="ropDeleteFolderRequest">RopDeleteFolderRequest object.</param>
        /// <param name="insideObjHandle">Server object handle in RopDeleteFolderRequest.</param>
        /// <param name="responseSOHTable">Server objects handles in RopDeleteFolderResponse.</param>
        /// <returns>RopDeleteFolderResponse object.</returns>
        public RopDeleteFolderResponse DeleteFolder(RopDeleteFolderRequest ropDeleteFolderRequest, uint insideObjHandle, ref List<List<uint>> responseSOHTable)
        {
            object temp = new object();
            this.ExcuteRopCall((ISerializable)ropDeleteFolderRequest, insideObjHandle, ref temp, ref responseSOHTable, ref this.rawData);
            RopDeleteFolderResponse ropDeleteFolderResponse = (RopDeleteFolderResponse)temp;

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

            return ropDeleteFolderResponse;
        }
        public void MSOXCMSG_S05_TC08_RopOpenMessageWithoutRight()
        {
            this.CheckMapiHttpIsSupported();
            this.ConnectToServer(ConnectionType.PrivateMailboxServer);

            string commonUser = Common.GetConfigurationPropertyValue("CommonUser", Site);
            string commonUserPassword = Common.GetConfigurationPropertyValue("CommonUserPassword", Site);
            string commonUserEssdn = Common.GetConfigurationPropertyValue("CommonUserEssdn", Site);
            uint pidTagMemberRights;

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

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

            #region Call RopCreateFolder to create a new subfolder.
            ulong thirdSubfolderId;
            uint thirdSubFolderHandle = this.CreateSubFolder(openedInboxFolderHandle, out thirdSubfolderId);
            LongTermId thirdSubfolderLongTermID = this.GetLongTermIdFormID(thirdSubfolderId, this.insideObjHandle);
            #endregion

            #region Call RopCreateMessage and RopSaveChangesMessage to create a Message object in subfolder created.
            // Create a message in InBox
            this.MessageHandle = this.CreatedMessage(thirdSubfolderId, this.insideObjHandle);

            RopSaveChangesMessageResponse saveChangesMessageResponse = this.SaveMessage(this.MessageHandle, (byte)SaveFlags.KeepOpenReadWrite);
            ulong thirdMessageId = saveChangesMessageResponse.MessageId;
            LongTermId thirdMessageLongTermID = this.GetLongTermIdFormID(thirdMessageId, this.insideObjHandle);
            this.ReleaseRop(this.MessageHandle);
            #endregion

            #region Add Read permission to "CommonUser" on inbox folder.
            // Add folder visible permission for the inbox.
            pidTagMemberRights = (uint)PidTagMemberRights.FolderVisible | (uint)PidTagMemberRights.ReadAny;
            this.AddPermission(commonUserEssdn, pidTagMemberRights, openedInboxFolderHandle);
            #endregion

            #region Add Read and write permission to "CommonUser" on subfolder
            pidTagMemberRights = (uint)PidTagMemberRights.FolderVisible;
            this.AddPermission(commonUserEssdn, pidTagMemberRights, thirdSubFolderHandle);
            #endregion

            #region Call RopLogon to logon the private mailbox with "CommonUser"
            this.rawData = null;
            this.insideObjHandle = 0;
            this.response = null;
            this.ResponseSOHs = null;
            this.MSOXCMSGAdapter.RpcDisconnect();
            this.MSOXCMSGAdapter.Reset();
            this.MSOXCMSGAdapter.RpcConnect(ConnectionType.PrivateMailboxServer, commonUser, commonUserPassword, commonUserEssdn);

            string userDN = Common.GetConfigurationPropertyValue("AdminUserEssdn", this.Site) + "\0";
            RopLogonRequest logonRequest = new RopLogonRequest()
            {
                RopId = (byte)RopId.RopLogon,
                LogonId = CommonLogonId,
                OutputHandleIndex = 0x00, // This index specifies the location 0x00 in the Server Object Handle Table where the handle for the output Server Object is stored. 
                StoreState = 0,
                LogonFlags = 0x01, // Logon to a private mailbox
                OpenFlags = (uint)OpenFlags.UsePerMDBReplipMapping, // Requesting admin access to the mail box
                EssdnSize = (ushort)Encoding.ASCII.GetByteCount(userDN),
                Essdn = Encoding.ASCII.GetBytes(userDN)
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(logonRequest, this.insideObjHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            logonResponse = (RopLogonResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, logonResponse.ReturnValue, "Call RopLogon should success.");

            uint objHandle = this.ResponseSOHs[0][logonResponse.OutputHandleIndex];
            #endregion

            #region Call RopOpenMessage to open a message that the user does not have rights to the message.
            thirdSubfolderId = this.GetObjectIdFormLongTermID(thirdSubfolderLongTermID, objHandle);
            thirdMessageId = this.GetObjectIdFormLongTermID(thirdMessageLongTermID, objHandle);

            RopOpenMessageRequest openMessageRequest = new RopOpenMessageRequest()
            {
                RopId = (byte)RopId.RopOpenMessage,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,
                OutputHandleIndex = CommonOutputHandleIndex,
                CodePageId = 0x0FFF, // Code page of Logon object is used
                FolderId = thirdSubfolderId,
                OpenModeFlags = (byte)MessageOpenModeFlags.ReadWrite,
                MessageId = thirdMessageId
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(openMessageRequest, objHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopOpenMessageResponse openMessageResponse = (RopOpenMessageResponse)this.response;

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R324
            this.Site.CaptureRequirementIfAreNotEqual<uint>(
                TestSuiteBase.Success,
                openMessageResponse.ReturnValue,
                324,
                @"[in Receiving a RopOpenMessage ROP Request] RopOpenMessage MUST NOT succeed if the client has insufficient access rights to the folder in which the Message object is stored.");
            
            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R2184");
        
            // Verify MS-OXCMSG requirement: MS-OXCMSG_R2184
            this.Site.CaptureRequirementIfAreEqual<uint>(
                0x80070005,
                openMessageResponse.ReturnValue,
                2184,
                @"[In Receiving a RopOpenMessage ROP Request] [ecAccessDenied(0x80070005)] The user does not have rights to the message.");
            #endregion
            #endregion

            #region Call RopLogon to logon the private mailbox with administrator
            this.rawData = null;
            this.insideObjHandle = 0;
            this.response = null;
            this.ResponseSOHs = null;
            this.MSOXCMSGAdapter.RpcDisconnect();
            this.MSOXCMSGAdapter.Reset();
            this.ConnectToServer(ConnectionType.PrivateMailboxServer);
            logonResponse = this.Logon(LogonType.Mailbox, out this.insideObjHandle);
            openedInboxFolderHandle = this.OpenSpecificFolder(logonResponse.FolderIds[4], this.insideObjHandle);
            #endregion

            #region Call RopDeleteFolder to delete the subfolder created
            thirdSubfolderId = this.GetObjectIdFormLongTermID(thirdSubfolderLongTermID, this.insideObjHandle);
            RopDeleteFolderRequest deleteFolderRequest = new RopDeleteFolderRequest()
            {
                RopId = (byte)RopId.RopDeleteFolder,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,
                DeleteFolderFlags = (byte)DeleteFolderFlags.DeleteHardDelete | (byte)DeleteFolderFlags.DelMessages,
                FolderId = thirdSubfolderId
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(deleteFolderRequest, openedInboxFolderHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopDeleteFolderResponse deleteFolderresponse = (RopDeleteFolderResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, deleteFolderresponse.ReturnValue, "Call RopDeleteFolder should success.");
            #endregion
        }
        public void MSOXCMSG_S05_TC07_RopOpenMessageAsBestAccess()
        {
            this.CheckMapiHttpIsSupported();
            this.ConnectToServer(ConnectionType.PrivateMailboxServer);

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

            List<PropertyObj> propertyValues = new List<PropertyObj>
            {
                new PropertyObj(PropertyNames.PidTagNormalizedSubject, Common.GetBytesFromUnicodeString(TestDataOfPidTagNormalizedSubject))
            };
            string commonUser = Common.GetConfigurationPropertyValue("CommonUser", Site);
            string commonUserPassword = Common.GetConfigurationPropertyValue("CommonUserPassword", Site);
            string commonUserEssdn = Common.GetConfigurationPropertyValue("CommonUserEssdn", Site);
            uint pidTagMemberRights;
            RopSetPropertiesResponse rpmSetResponse;

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

            #region Call RopCreateFolder to create a subfolder in inbox folder.
            ulong firstSubfolderId;
            uint firstSubFolderHandle = this.CreateSubFolder(openedInboxFolderHandle, out firstSubfolderId);
            LongTermId firstSubfolderLongTermID = this.GetLongTermIdFormID(firstSubfolderId, this.insideObjHandle);
            #endregion

            #region Call RopCreateMessage and RopSaveChangesMessage to create a Message object in subfolder created by step 3.
            // Create a message in InBox
            this.MessageHandle = this.CreatedMessage(firstSubfolderId, this.insideObjHandle);

            RopSaveChangesMessageResponse saveChangesMessageResponse = this.SaveMessage(this.MessageHandle, (byte)SaveFlags.KeepOpenReadWrite);
            ulong firstMessageId = saveChangesMessageResponse.MessageId;
            LongTermId firstMessageLongTermID = this.GetLongTermIdFormID(firstMessageId, this.insideObjHandle);
            this.ReleaseRop(this.MessageHandle);
            #endregion

            #region Call RopCreateFolder to create a new subfolder.
            ulong secondSubfolderId;
            System.Threading.Thread.Sleep(1); // Sleep 1 millisecond to generate different named folder
            uint secondSubFolderHandle = this.CreateSubFolder(openedInboxFolderHandle, out secondSubfolderId);
            LongTermId secondSubfolderLongTermID = this.GetLongTermIdFormID(secondSubfolderId, this.insideObjHandle);
            #endregion

            #region Call RopCreateMessage and RopSaveChangesMessage to create a Message object in subfolder created by step 5.
            // Create a message in InBox
            this.MessageHandle = this.CreatedMessage(secondSubfolderId, this.insideObjHandle);

            saveChangesMessageResponse = this.SaveMessage(this.MessageHandle, (byte)SaveFlags.KeepOpenReadWrite);
            ulong secondMessageId = saveChangesMessageResponse.MessageId;
            LongTermId secondMessageLongTermID = this.GetLongTermIdFormID(secondMessageId, this.insideObjHandle);
            this.ReleaseRop(this.MessageHandle);
            #endregion

            #region Add Read permission to "CommonUser" on inbox folder.
            // Add folder visible permission for the inbox.
            pidTagMemberRights = (uint)PidTagMemberRights.FolderVisible | (uint)PidTagMemberRights.ReadAny;
            this.AddPermission(commonUserEssdn, pidTagMemberRights, openedInboxFolderHandle);
            #endregion

            #region Add Read permission to "CommonUser" on subfolder created by step 3.
            // Add folder visible permission for the subfolder1.
            pidTagMemberRights = (uint)PidTagMemberRights.FolderVisible | (uint)PidTagMemberRights.ReadAny;
            this.AddPermission(commonUserEssdn, pidTagMemberRights, firstSubFolderHandle);
            #endregion

            #region Add Read and write permission to "CommonUser" on subfolder by step 5
            pidTagMemberRights = (uint)PidTagMemberRights.FolderVisible | (uint)PidTagMemberRights.ReadAny | (uint)PidTagMemberRights.EditAny;
            this.AddPermission(commonUserEssdn, pidTagMemberRights, secondSubFolderHandle);
            #endregion

            #region Call RopLogon to logon the private mailbox with "CommonUser"
            this.rawData = null;
            this.insideObjHandle = 0;
            this.response = null;
            this.ResponseSOHs = null;
            this.MSOXCMSGAdapter.RpcDisconnect();
            this.MSOXCMSGAdapter.Reset();
            this.MSOXCMSGAdapter.RpcConnect(ConnectionType.PrivateMailboxServer, commonUser, commonUserPassword, commonUserEssdn);

            string userDN = Common.GetConfigurationPropertyValue("AdminUserEssdn", this.Site) + "\0";
            RopLogonRequest logonRequest = new RopLogonRequest()
            {
                RopId = (byte)RopId.RopLogon,
                LogonId = CommonLogonId,
                OutputHandleIndex = 0x00, // This index specifies the location 0x00 in the Server Object Handle Table where the handle for the output Server Object is stored. 
                StoreState = 0,
                LogonFlags = 0x01, // Logon to a private mailbox
                OpenFlags = (uint)OpenFlags.UsePerMDBReplipMapping, // Requesting admin access to the mail box
                EssdnSize = (ushort)Encoding.ASCII.GetByteCount(userDN),
                Essdn = Encoding.ASCII.GetBytes(userDN),
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(logonRequest, this.insideObjHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            logonResponse = (RopLogonResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, logonResponse.ReturnValue, "Call RopLogon should success.");

            uint objHandle = this.ResponseSOHs[0][logonResponse.OutputHandleIndex];
            #endregion

            #region Call RopOpenMessage which OpenModeFlags is BestAccess to open the message in subfolder created by step 3.
            firstSubfolderId = this.GetObjectIdFormLongTermID(firstSubfolderLongTermID, objHandle);
            firstMessageId = this.GetObjectIdFormLongTermID(firstMessageLongTermID, objHandle);

            uint openedMessageBestReadOnlyHandle = this.OpenSpecificMessage(firstSubfolderId, firstMessageId, objHandle, MessageOpenModeFlags.BestAccess);
            #endregion

            #region Call RopSetProperties to set PidTagNormalizedSubject property of message in subfolder created by step 3.
            List<TaggedPropertyValue> taggedPropertyValueList = new List<TaggedPropertyValue>();

            int valueSize = 0;
            foreach (PropertyObj propertyObj in propertyValues)
            {
                PropertyTag propertyTag = new PropertyTag
                {
                    PropertyId = (ushort)propertyObj.PropertyID,
                    PropertyType = (ushort)propertyObj.ValueTypeCode
                };

                TaggedPropertyValue taggedPropertyValue = new TaggedPropertyValue
                {
                    PropertyTag = propertyTag,
                    Value = (byte[])propertyObj.Value
                };
                valueSize += taggedPropertyValue.Size();

                taggedPropertyValueList.Add(taggedPropertyValue);
            }

            RopSetPropertiesRequest rpmSetRequest = new RopSetPropertiesRequest()
            {
                RopId = (byte)RopId.RopSetProperties,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,
                PropertyValueCount = (ushort)taggedPropertyValueList.Count,
                PropertyValueSize = (ushort)(valueSize + 2),
                PropertyValues = taggedPropertyValueList.ToArray(),
            };
            uint returnValue;
            this.response = null;
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(rpmSetRequest, openedMessageBestReadOnlyHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None, out returnValue);
            
            if(Common.IsRequirementEnabled(3009,this.Site))
            {
                rpmSetResponse = (RopSetPropertiesResponse)this.response;

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

                // Verify MS-OXCMSG requirement: MS-OXCMSG_R3009
                this.Site.CaptureRequirementIfAreEqual<uint>(
                    TestSuiteBase.Success,
                    rpmSetResponse.ReturnValue,
                    3009,
                    @"[In Appendix A: Product Behavior] BestAccess is read/write if the user don't have write permissions. (<12> Section 2.2.3.1.1:  Exchange 2010 and above follow this behavior.)");
            }

            if(Common.IsRequirementEnabled(3010,this.Site))
            {
                if (this.response == null)
                {
                    Site.Assert.AreNotEqual<uint>(0, returnValue, "Call RopSetProperties should fail.");
                }
                else
                {
                    rpmSetResponse = (RopSetPropertiesResponse)this.response;
                    Site.Assert.AreNotEqual<uint>(0, rpmSetResponse.ReturnValue, "Call RopSetProperties should fail.");
                }

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

                // Verify MS-OXCMSG requirement: MS-OXCMSG_R661
                // Because when call RopSetProperties to set property of specified Message object that opened by read-only, server will fail and return error code.
                // R661 will be verified.
                this.Site.CaptureRequirement(
                    3010,
                    @"[In Appendix A: Product Behavior] BestAccess is read-only if the user don't have write permissions. (Exchange 2007 follows this behavior.)");
            }
            #endregion

            #region Call RopRelease to release created message in subfolder created by step 3.
            this.ReleaseRop(openedMessageBestReadOnlyHandle);
            #endregion

            #region Call RopOpenMessage which OpenModeFlags is BestAccess to open the message in subfolder created by step 5.
            secondSubfolderId = this.GetObjectIdFormLongTermID(secondSubfolderLongTermID, objHandle);
            secondMessageId = this.GetObjectIdFormLongTermID(secondMessageLongTermID, objHandle);
            uint openedMessageBestReadWrietHandle = this.OpenSpecificMessage(secondSubfolderId, secondMessageId, objHandle, MessageOpenModeFlags.BestAccess);
            #endregion

            #region Call RopSetProperties to set PidTagSubjectPrefix property of message in subfolder created by step 5.
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(rpmSetRequest, openedMessageBestReadWrietHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            rpmSetResponse = (RopSetPropertiesResponse)this.response;

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R665
            this.Site.CaptureRequirementIfAreEqual<uint>(
                TestSuiteBase.Success,
                rpmSetResponse.ReturnValue,
                665,
                @"[In RopOpenMessage ROP Request Buffer] [OpenModeFlags] [BestAccess (0x03)] Open for read/write if the user has write permissions for the folder.");
            #endregion

            #region Call RopRelease to release created message in subfolder created by step 5.
            this.ReleaseRop(openedMessageBestReadWrietHandle);
            #endregion

            #region Call RopLogon to logon the private mailbox with administrator
            this.rawData = null;
            this.insideObjHandle = 0;
            this.response = null;
            this.ResponseSOHs = null;
            this.MSOXCMSGAdapter.RpcDisconnect();
            this.MSOXCMSGAdapter.Reset();
            this.ConnectToServer(ConnectionType.PrivateMailboxServer);
            logonResponse = this.Logon(LogonType.Mailbox, out this.insideObjHandle);
            openedInboxFolderHandle = this.OpenSpecificFolder(logonResponse.FolderIds[4], this.insideObjHandle);
            #endregion

            #region Call RopDeleteFolder to delete the subfolder created by 3.
            firstSubfolderId = this.GetObjectIdFormLongTermID(firstSubfolderLongTermID, this.insideObjHandle);
            RopDeleteFolderRequest deleteFolderRequest = new RopDeleteFolderRequest()
            {
                RopId = (byte)RopId.RopDeleteFolder,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,
                DeleteFolderFlags = (byte)DeleteFolderFlags.DeleteHardDelete | (byte)DeleteFolderFlags.DelMessages,
                FolderId = firstSubfolderId
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(deleteFolderRequest, openedInboxFolderHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopDeleteFolderResponse deleteFolderresponse = (RopDeleteFolderResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, deleteFolderresponse.ReturnValue, "Call RopDeleteFolder should success.");
            #endregion

            #region Call RopDeleteFolder to delete the subfolder created by 5
            secondSubfolderId = this.GetObjectIdFormLongTermID(secondSubfolderLongTermID, this.insideObjHandle);
            deleteFolderRequest.FolderId = secondSubfolderId;
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(deleteFolderRequest, openedInboxFolderHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            deleteFolderresponse = (RopDeleteFolderResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, deleteFolderresponse.ReturnValue, "Call RopDeleteFolder should success.");
            #endregion

            this.ReleaseRop(openedInboxFolderHandle);
        }
        /// <summary>
        /// Delete specific folder.
        /// </summary>
        /// <param name="objHandle">object handle .</param>
        /// <param name="folderId">ID of the folder will be deleted.</param>
        /// <returns>ROP response of RopDeleteFolder.</returns>
        public RopDeleteFolderResponse RopDeleteFolder(uint objHandle, ulong folderId)
        {
            RopDeleteFolderRequest deleteFolderRequest = new RopDeleteFolderRequest();
            RopDeleteFolderResponse deleteFolderResponse = new RopDeleteFolderResponse();
            deleteFolderRequest.RopId = 0x1D;
            deleteFolderRequest.LogonId = 0x00;
            deleteFolderRequest.InputHandleIndex = 0x00;

            // Delete all messages and subfolders
            deleteFolderRequest.DeleteFolderFlags = 0x15;

            // Folder to be deleted
            deleteFolderRequest.FolderId = folderId;
            this.responseSOHs = this.DoRPCCall(deleteFolderRequest, objHandle, ref this.response, ref this.rawData);
            deleteFolderResponse = (RopDeleteFolderResponse)this.response;
            return deleteFolderResponse;
        }