Exemple #1
0
        /// <summary>
        /// Find a folder ID in the specified folder and with specified display name.
        /// </summary>
        /// <param name="parentFolderId">ID of the parent Folder.</param>
        /// <param name="logonHandle">The logon object handle.</param>
        /// <param name="folderName">The folder display name.</param>
        /// <returns>The folder ID.</returns>
        protected ulong GetSubfolderIDByName(ulong parentFolderId, uint logonHandle, string folderName)
        {
            ulong folderId           = 0;
            uint  parentFolderHandle = 0;

            this.OpenFolder(logonHandle, parentFolderId, ref parentFolderHandle);

            RopGetHierarchyTableRequest getHierarchyTableRequest = new RopGetHierarchyTableRequest
            {
                RopId             = (byte)RopId.RopGetHierarchyTable,
                LogonId           = Constants.CommonLogonId,
                InputHandleIndex  = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                TableFlags        = (byte)FolderTableFlags.Depth
            };
            RopGetHierarchyTableResponse getHierarchyTableResponse = this.Adapter.GetHierarchyTable(getHierarchyTableRequest, parentFolderHandle, ref this.responseHandles);
            uint tableHandle = this.responseHandles[0][getHierarchyTableResponse.OutputHandleIndex];

            PropertyTag[] properties = new PropertyTag[]
            {
                new PropertyTag()
                {
                    PropertyId   = (ushort)FolderPropertyId.PidTagDisplayName,
                    PropertyType = (ushort)PropertyType.PtypString
                },
                new PropertyTag()
                {
                    PropertyId   = (ushort)FolderPropertyId.PidTagFolderId,
                    PropertyType = (ushort)PropertyType.PtypInteger64
                }
            };
            List <PropertyRow> propertyRows = this.GetTableRowValue(tableHandle, (ushort)getHierarchyTableResponse.RowCount, properties);

            if (propertyRows != null)
            {
                foreach (PropertyRow propertyRow in propertyRows)
                {
                    byte[] displayNameInBytes = propertyRow.PropertyValues[0].Value;
                    string displayName        = Encoding.Unicode.GetString(displayNameInBytes, 0, displayNameInBytes.Length);
                    if (displayName.Equals(folderName, StringComparison.CurrentCultureIgnoreCase))
                    {
                        byte[] folderIdInBytes = propertyRow.PropertyValues[1].Value;
                        folderId = (ulong)BitConverter.ToInt64(folderIdInBytes, 0);
                        break;
                    }
                }
            }

            return(folderId);
        }
        /// <summary>
        /// Retrieves the hierarchy table for a folder.
        /// </summary>
        /// <param name="ropGetHierarchyTableRequest">RopGetHierarchyTableRequest object.</param>
        /// <param name="insideObjHandle">Server object handle RopGetHierarchyTable.</param>
        /// <param name="responseSOHTable">Server objects handles in RopGetHierarchyTableResponse.</param>
        /// <returns>RopGetHierarchyTableResponse object.</returns>
        public RopGetHierarchyTableResponse GetHierarchyTable(RopGetHierarchyTableRequest ropGetHierarchyTableRequest, uint insideObjHandle, ref List <List <uint> > responseSOHTable)
        {
            object temp = new object();

            this.ExcuteRopCall((ISerializable)ropGetHierarchyTableRequest, insideObjHandle, ref temp, ref responseSOHTable, ref this.rawData);
            RopGetHierarchyTableResponse ropGetHierarchyTableResponse = (RopGetHierarchyTableResponse)temp;

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

            return(ropGetHierarchyTableResponse);
        }
        /// <summary>
        /// Find a folder ID in the specified folder and with specified display name.
        /// </summary>
        /// <param name="parentFolderId">ID of the parent Folder.</param>
        /// <param name="logonHandle">The logon object handle.</param>
        /// <param name="folderName">The folder display name.</param>
        /// <returns>The folder ID.</returns>
        protected ulong GetSubfolderIDByName(ulong parentFolderId, uint logonHandle, string folderName)
        {
            ulong folderId = 0;
            uint parentFolderHandle = 0;
            this.OpenFolder(logonHandle, parentFolderId, ref parentFolderHandle);

            RopGetHierarchyTableRequest getHierarchyTableRequest = new RopGetHierarchyTableRequest
            {
                RopId = (byte)RopId.RopGetHierarchyTable,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                TableFlags = (byte)FolderTableFlags.Depth
            };
            RopGetHierarchyTableResponse getHierarchyTableResponse = this.Adapter.GetHierarchyTable(getHierarchyTableRequest, parentFolderHandle, ref this.responseHandles);
            uint tableHandle = this.responseHandles[0][getHierarchyTableResponse.OutputHandleIndex];

            PropertyTag[] properties = new PropertyTag[]
            {
                new PropertyTag()
                {
                    PropertyId = (ushort)FolderPropertyId.PidTagDisplayName,
                    PropertyType = (ushort)PropertyType.PtypString
                },
                new PropertyTag()
                {
                    PropertyId = (ushort)FolderPropertyId.PidTagFolderId,
                    PropertyType = (ushort)PropertyType.PtypInteger64
                }
            };
            List<PropertyRow> propertyRows = this.GetTableRowValue(tableHandle, (ushort)getHierarchyTableResponse.RowCount, properties);

            if (propertyRows != null)
            {
                foreach (PropertyRow propertyRow in propertyRows)
                {
                    byte[] displayNameInBytes = propertyRow.PropertyValues[0].Value;
                    string displayName = Encoding.Unicode.GetString(displayNameInBytes, 0, displayNameInBytes.Length);
                    if (displayName.Equals(folderName, StringComparison.CurrentCultureIgnoreCase))
                    {
                        byte[] folderIdInBytes = propertyRow.PropertyValues[1].Value;
                        folderId = (ulong)BitConverter.ToInt64(folderIdInBytes, 0);
                        break;
                    }
                }
            }

            return folderId;
        }
        /// <summary>
        /// Find a folder ID in the specified folder and with specified display name.
        /// </summary>
        /// <param name="openedFolderHandle">Handle of the parent folder.</param>
        /// <param name="folderName">The folder display name.</param>
        /// <returns>The folder ID.</returns>
        protected ulong GetSubfolderIDByName(uint openedFolderHandle, string folderName)
        {
            RopGetHierarchyTableRequest getHierarchyTableRequest = new RopGetHierarchyTableRequest();
            RopGetHierarchyTableResponse getHierarchyTableResponse = new RopGetHierarchyTableResponse();
            getHierarchyTableRequest.RopId = (byte)RopId.RopGetHierarchyTable;
            getHierarchyTableRequest.LogonId = TestSuiteBase.LogonId;
            getHierarchyTableRequest.InputHandleIndex = TestSuiteBase.InputHandleIndex0;
            getHierarchyTableRequest.OutputHandleIndex = TestSuiteBase.OutputHandleIndex1;
            getHierarchyTableRequest.TableFlags = (byte)FolderTableFlags.Depth;
            this.responseSOHs = this.cropsAdapter.ProcessSingleRop(
                getHierarchyTableRequest,
                openedFolderHandle,
                ref this.response,
                ref this.rawData,
                RopResponseType.SuccessResponse);
            getHierarchyTableResponse = (RopGetHierarchyTableResponse)this.response;
            uint tableHandle = this.responseSOHs[0][getHierarchyTableResponse.OutputHandleIndex];

            PropertyTag[] properties = new PropertyTag[]
            {
                new PropertyTag()
                {
                    PropertyId = this.propertyDictionary[PropertyNames.PidTagDisplayName].PropertyId,
                    PropertyType = (ushort)PropertyType.PtypString
                },
                new PropertyTag()
                {
                    PropertyId = (ushort)this.propertyDictionary[PropertyNames.PidTagFolderId].PropertyId,
                    PropertyType = (ushort)PropertyType.PtypInteger64
                }
            };
            List<PropertyRow> propertyRows = this.GetTableRowValue(tableHandle, (ushort)getHierarchyTableResponse.RowCount, properties);

            ulong folderId = 0;
            foreach (PropertyRow propertyRow in propertyRows)
            {
                byte[] displayNameInBytes = propertyRow.PropertyValues[0].Value;
                string displayName = Encoding.Unicode.GetString(displayNameInBytes, 0, displayNameInBytes.Length);
                if (displayName.ToLower() == folderName.ToLower())
                {
                    byte[] folderIdInBytes = propertyRow.PropertyValues[1].Value;
                    folderId = (ulong)BitConverter.ToInt64(folderIdInBytes, 0);
                    break;
                }
            }

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

            RopGetHierarchyTableRequest getHierarchyTableRequest = new RopGetHierarchyTableRequest();
            RopGetHierarchyTableResponse getHierarchyTableResponse = new RopGetHierarchyTableResponse();

            getHierarchyTableRequest.RopId = 0x04;
            getHierarchyTableRequest.LogonId = 0x00;
            getHierarchyTableRequest.InputHandleIndex = 0x00;
            getHierarchyTableRequest.OutputHandleIndex = 0x01;

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

            getHierarchyTableResponse = (RopGetHierarchyTableResponse)this.Process(serverId, getHierarchyTableRequest, objHandle);
            result = (RopResult)getHierarchyTableResponse.ReturnValue;
            int expectedRowCount = (int)getHierarchyTableResponse.RowCount;

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

            this.currentSoftDeleteRowCount = expectedRowCount;
            return result;
        }
        public void MSOXCFOLD_S03_TC09_RopGetHierarchyTableFailure()
        {
            this.CheckWhetherSupportTransport();
            this.Adapter.DoConnect(ConnectionType.PrivateMailboxServer);
            this.GenericFolderInitialization();

            #region Step 1. The client calls RopGetHierarchyTable with a logon object handle rather than a folder handle.

            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.LogonHandle, ref this.responseHandles);

            #region Verify the requirements: MS-OXCFOLD_R657, MS-OXCFOLD_R658.

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

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

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

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

            #endregion

            #endregion

            #region Step 2. The client calls RopGetHierarchyTable with invalid 'TableFlags'.

            getHierarchyTableRequest.TableFlags = 0x03;
            getHierarchyTableResponse = this.Adapter.GetHierarchyTable(getHierarchyTableRequest, this.RootFolderHandle, ref this.responseHandles);

            #region Verify the requirements: MS-OXCFOLD_R314002, MS-OXCFOLD_R314001.

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

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R314002
                Site.CaptureRequirementIfAreEqual<uint>(
                    0x80040102,
                    getHierarchyTableResponse.ReturnValue,
                    314002,
                    @"[In Appendix A: Product Behavior] If the client sets an invalid bit in the TableFlags field, implementation fails the ROP[RopGetHierarchyTable] with an error code of ecNotSupported(0x80040102). (Microsoft Exchange 2010 and above follow this behavior.)");
            }

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

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

            #endregion

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

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

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

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

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

            #endregion

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

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

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

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

            #endregion

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            #endregion

            #endregion

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

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

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

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

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

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

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

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

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

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

            #endregion

            #endregion

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

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

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

            #endregion

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

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

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

            #endregion

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            #endregion

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

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

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

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R808");
        
            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R808
            this.Site.CaptureRequirementIfAreEqual<string>(
                Constants.Subfolder1,
                pidTagDisplayNameNoUseUnicodeFlag,
                808,
                @"[In RopGetHierarchyTable ROP Request Buffer] TableFlags (1 byte): If this bit [UseUnicode (0x40)] is not set, the string data is encoded in the code page of the Logon object.");
            #endregion
        }
        public void MSOXCFOLD_S04_TC07_RopEmptyPublicFolder()
        {
            if (!Common.IsRequirementEnabled(97501002, this.Site))
            {
                this.NeedCleanup = false;
                Site.Assert.Inconclusive("The server does not support the RopEmptyFolder ROP ([MS-OXCROPS] section 2.2.4.9) for public folders.");
            }

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

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

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

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

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

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

            #endregion

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

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

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

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

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

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

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

            #endregion

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

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

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

            #endregion

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

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

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

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

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R97501002.
            Site.CaptureRequirementIfIsTrue(
                isVerifyR97501002,
                97501002,
                @"[In Appendix A: Product Behavior] Implementation does support the RopEmptyFolder ROP ([MS-OXCROPS] section 2.2.4.9) for public folders. (Microsoft Exchange Server 2007 and Microsoft Exchange Server 2010 follow this behavior.)");
            #endregion
        }
        public void MSOXCFOLD_S04_TC06_RopCopyPublicFolder()
        {
            if (!Common.IsRequirementEnabled(19702002, this.Site))
            {
                this.NeedCleanup = false;
                Site.Assert.Inconclusive("The server does not support the RopCopyFolder ROP ([MS-OXCROPS] section 2.2.4.8) for public folders.");
            }

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

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

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

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

            #endregion

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

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

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

            #endregion

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

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

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

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

            #endregion

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

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

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

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

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

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

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

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

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

            #endregion

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

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

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

            #endregion

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

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

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

            #endregion

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

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

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

            #endregion

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

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

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

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

            Site.CaptureRequirementIfIsTrue(
                isVerifyR17102,
                17102,
                @"[In RopMoveFolder ROP] The move can be within [a private mailbox] or a public folder, [or between a private mailbox and a public folder].");
            #endregion
        }
        public void MSOXCFOLD_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
        }
        public void MSOXCFOLD_S04_TC11_RopGetHierarchyTableFromPublicFolderSuccess()
        {
            this.CheckWhetherSupportTransport();
            this.Logon();
            this.PublicFolderInitialization();

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

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

            #region Step 3. The client calls RopGetHierarchyTable retrieve the hierarchy table for the public root folder.
            RopGetHierarchyTableRequest getHierarchyTableRequest = new RopGetHierarchyTableRequest
            {
                RopId = (byte)RopId.RopGetHierarchyTable,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                TableFlags = 0x04
            };
            RopGetHierarchyTableResponse getHierarchyTableResponse = this.Adapter.GetHierarchyTable(getHierarchyTableRequest, this.publicRootFolderHandle, ref this.responseHandles);

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R100001.
            Site.CaptureRequirementIfAreEqual<uint>(
                Constants.SuccessCode,
                getHierarchyTableResponse.ReturnValue,
                100001,
                @"[In RopGetHierarchyTable ROP] The folder can be either a public folder [or a private mailbox folder].");
            #endregion
        }
        public void MSOXCFOLD_S04_TC08_RopHardDeleteMessagesAndSubfoldersInPublicFolder()
        {
            if (!Common.IsRequirementEnabled(98301002, this.Site))
            {
                this.NeedCleanup = false;
                Site.Assert.Inconclusive("The server does not support the RopHardDeleteMessagesAndSubfolders ROP for public folders.");
            }

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

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

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

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

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

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

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

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

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

            #endregion

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

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

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

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

            #endregion

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

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

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

            #endregion

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

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

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

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

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

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R98301002.
            Site.CaptureRequirementIfIsTrue(
                isVerifyR98301002,
                98301002,
                @"[In Appendix A: Product Behavior] Implementation does support the RopHardDeleteMessagesAndSubfolders ROP ([MS-OXCROPS] section 2.2.4.10) for public folders. (Microsoft Exchange Server 2007 and Microsoft Exchange Server 2010 follow this behavior.)");
            #endregion
        }
        /// <summary>
        /// Retrieves the hierarchy table for a folder. 
        /// </summary>
        /// <param name="ropGetHierarchyTableRequest">RopGetHierarchyTableRequest object.</param>
        /// <param name="insideObjHandle">Server object handle RopGetHierarchyTable.</param>
        /// <param name="responseSOHTable">Server objects handles in RopGetHierarchyTableResponse.</param>
        /// <returns>RopGetHierarchyTableResponse object.</returns>
        public RopGetHierarchyTableResponse GetHierarchyTable(RopGetHierarchyTableRequest ropGetHierarchyTableRequest, uint insideObjHandle, ref List<List<uint>> responseSOHTable)
        {
            object temp = new object();
            this.ExcuteRopCall((ISerializable)ropGetHierarchyTableRequest, insideObjHandle, ref temp, ref responseSOHTable, ref this.rawData);
            RopGetHierarchyTableResponse ropGetHierarchyTableResponse = (RopGetHierarchyTableResponse)temp;

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

            return ropGetHierarchyTableResponse;
        }