Exemplo n.º 1
0
        /// <summary>
        /// Open a specified message in specified folder.
        /// </summary>
        /// <param name="messageId">The specified message ID.</param>
        /// <param name="folderId">The specified folder ID.</param>
        /// <param name="openModeFlags">OpenModeFlags for RopOpenMessage.</param>
        /// <returns>The response of RopOpenMessage ROP operation.</returns>
        protected RopOpenMessageResponse OpenMessage(ulong messageId, ulong folderId, MessageOpenModeFlags openModeFlags)
        {
            RopOpenFolderRequest openFolderRequest = new RopOpenFolderRequest
            {
                RopId = (byte)RopId.RopOpenFolder,
                LogonId = Constants.CommonLogonId,
                InputHandleIndex = Constants.CommonInputHandleIndex,
                OutputHandleIndex = Constants.CommonOutputHandleIndex,
                OpenModeFlags = (byte)FolderOpenModeFlags.None,
                FolderId = folderId
            };
            RopOpenFolderResponse openFolderResponse = this.Adapter.OpenFolder(openFolderRequest, this.LogonHandle, ref this.responseHandles);
            uint folderHandle = this.responseHandles[0][openFolderResponse.OutputHandleIndex];

            RopOpenMessageRequest openMessageRequest = new RopOpenMessageRequest();
            object ropResponse = null;
            openMessageRequest.RopId = (byte)RopId.RopOpenMessage;
            openMessageRequest.LogonId = Constants.CommonLogonId;
            openMessageRequest.InputHandleIndex = Constants.CommonInputHandleIndex;
            openMessageRequest.OutputHandleIndex = Constants.CommonOutputHandleIndex;
            openMessageRequest.OpenModeFlags = (byte)openModeFlags;
            openMessageRequest.FolderId = folderId;
            openMessageRequest.MessageId = messageId;
            openMessageRequest.CodePageId = 0x0fff;
            this.Adapter.DoRopCall(openMessageRequest, folderHandle, ref ropResponse, ref this.responseHandles);
            return (RopOpenMessageResponse)ropResponse;
        }
        /// <summary>
        /// This ROP opens an existing message in a mailbox. 
        /// </summary>
        /// <param name="handle">The handle to operate</param>
        /// <param name="folderId">The parent folder of the message to be opened.</param>
        /// <param name="messageId">The identifier of the message to be opened.</param>
        /// <param name="openMessageResponse">The response of this ROP.</param>
        /// <param name="needVerify">Whether need to verify the response</param>
        /// <returns>The handle of the opened message</returns>
        private uint RopOpenMessage(uint handle, ulong folderId, ulong messageId, out RopOpenMessageResponse openMessageResponse, bool needVerify)
        {
            this.rawDataValue = null;
            this.responseValue = null;
            this.responseSOHsValue = null;

            RopOpenMessageRequest openMessageRequest = new RopOpenMessageRequest()
            {
                RopId = (byte)RopId.RopOpenMessage,
                LogonId = LogonId,
                InputHandleIndex = (byte)HandleIndex.FirstIndex,
                OutputHandleIndex = (byte)HandleIndex.SecondIndex,

                // Set CodePageId to SameAsLogonObject, which indicates it uses the same code page as the one for logon object.
                CodePageId = (ushort)CodePageId.SameAsLogonObject,
                FolderId = folderId,

                // Set OpenModeFlags to read and write for further operation.
                OpenModeFlags = (byte)MessageOpenModeFlags.ReadWrite,
                MessageId = messageId
            };

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

            return this.responseSOHsValue[0][openMessageResponse.OutputHandleIndex];
        }
        /// <summary>
        /// Get changeNmuber of a specific message object.
        /// </summary>
        /// <param name="serverId">Server id.</param>
        /// <param name="messageId">ID of the message object.</param>
        /// <param name="folderId">ID of the message's parent folder.</param>
        /// <param name="folderHandle">Handle of the message's parent folder</param>
        /// <returns>Change number.</returns>
        private byte[] GetChangeNumber(int serverId, ulong messageId, ulong folderId, uint folderHandle)
        {
            // Open message to get message handle.
            RopOpenMessageRequest openMessageRequest = new RopOpenMessageRequest();
            RopOpenMessageResponse openMessageResponse = new RopOpenMessageResponse();
            openMessageRequest.CodePageId = 0x0fff;
            openMessageRequest.FolderId = folderId;
            openMessageRequest.InputHandleIndex = 0x00;
            openMessageRequest.LogonId = 0x00;
            openMessageRequest.MessageId = messageId;
            openMessageRequest.OpenModeFlags = 0x01;
            openMessageRequest.OutputHandleIndex = 0x01;
            openMessageRequest.RopId = 0x03;
            openMessageResponse = (RopOpenMessageResponse)this.Process(serverId, openMessageRequest, folderHandle);
            uint handle = this.responseSOHs[openMessageResponse.OutputHandleIndex];

            // Get message PidTagChangeKey value.
            RopGetPropertiesSpecificRequest getPropertiesSpecificRequest = new RopGetPropertiesSpecificRequest();
            RopGetPropertiesSpecificResponse getPropertiesSpecificResponse = new RopGetPropertiesSpecificResponse();
            PropertyTag[] propertyTags = new PropertyTag[1];
            PropertyTag tag = new PropertyTag(0x65E2, 0x0102);
            propertyTags[0] = tag;

            getPropertiesSpecificRequest.RopId = 0x07;
            getPropertiesSpecificRequest.LogonId = 0x00;
            getPropertiesSpecificRequest.InputHandleIndex = 0x00;

            // Set PropertySizeLimit, which specifies the maximum size allowed for a property value returned,
            getPropertiesSpecificRequest.PropertySizeLimit = 0xFFFF;
            PropertyTag[] tagArray = propertyTags;
            getPropertiesSpecificRequest.PropertyTagCount = (ushort)tagArray.Length;
            getPropertiesSpecificRequest.PropertyTags = tagArray;

            // Send the RopGetPropertiesSpecific request
            getPropertiesSpecificResponse = (RopGetPropertiesSpecificResponse)this.Process(serverId, getPropertiesSpecificRequest, handle);

            if (getPropertiesSpecificResponse.ReturnValue == 0x0)
            {
                byte[] tempChangeNumber = new byte[getPropertiesSpecificResponse.RowData.PropertyValues[0].Value.Length - 2];
                Array.Copy(getPropertiesSpecificResponse.RowData.PropertyValues[0].Value, 2, tempChangeNumber, 0, getPropertiesSpecificResponse.RowData.PropertyValues[0].Value.Length - 2);
                return tempChangeNumber;
            }
            else
            {
                return new byte[0];
            }
        }
        public void MSOXCMSG_S01_TC01_RopCreateMessageAndRopSaveChangesMessage()
        {
            this.CheckMapiHttpIsSupported();
            this.ConnectToServer(ConnectionType.PrivateMailboxServer);

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

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

            #region Call RopGetContentsTable to get the contents table of inbox folder before create message.
            RopGetContentsTableRequest getContentsTableRequest = new RopGetContentsTableRequest()
            {
                RopId = (byte)RopId.RopGetContentsTable,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,
                OutputHandleIndex = CommonOutputHandleIndex,
                TableFlags = (byte)FolderTableFlags.None
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(getContentsTableRequest, openedFolderHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopGetContentsTableResponse getContentsTableResponse = (RopGetContentsTableResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, getContentsTableResponse.ReturnValue, "Call RopGetContentsTable should success.");
            uint rowCount = getContentsTableResponse.RowCount;
            #endregion

            #region Call RopCreateMessage to create new not FAI Message object.
            RopCreateMessageRequest createMessageRequest = new RopCreateMessageRequest()
            {
                RopId = (byte)RopId.RopCreateMessage,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,
                OutputHandleIndex = CommonOutputHandleIndex,
                CodePageId = 0x0FFF, // Code page of Logon object is used
                FolderId = logonResponse.FolderIds[4], // Create a message in INBOX which root is mailbox 
                AssociatedFlag = 0x00 // NOT an FAI message
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(createMessageRequest, this.insideObjHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopCreateMessageResponse createMessageResponse = (RopCreateMessageResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, createMessageResponse.ReturnValue, "Call RopCreateMessage should success.");
            uint targetMessageHandle = this.ResponseSOHs[0][createMessageResponse.OutputHandleIndex];

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R991, The HasMessageId field is {0}", createMessageResponse.HasMessageId);

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R991
            bool isVerifiedR991 = createMessageResponse.HasMessageId == 0x00 && createMessageResponse.MessageId == null;

            this.Site.CaptureRequirementIfIsTrue(
                isVerifiedR991,
                991,
                @"[In RopCreateMessage ROP Response Buffer] [HasMessageId] The value 0x00 means this is the last byte in the buffer.");
            #endregion

            #region Call RopGetContentsTable to get the contents table of inbox folder before save message.
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(getContentsTableRequest, openedFolderHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            getContentsTableResponse = (RopGetContentsTableResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, createMessageResponse.ReturnValue, "Call RopGetContents should success.");

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R339
            this.Site.CaptureRequirementIfAreEqual<uint>(
                rowCount,
                getContentsTableResponse.RowCount,
                339,
                @"[In Receiving a RopCreateMessage ROP Request] When processing the RopCreateMessage ROP ([MS-OXCROPS] section 2.2.6.2), the server MUST NOT commit the new Message object until it [server] receives a RopSaveChangesMessage ROP request ([MS-OXCROPS] section 2.2.6.3).");
            #endregion

            #region Call RopSaveChangesMessage to commit the Message object created.
            RopSaveChangesMessageResponse saveChangesMessageResponse = this.SaveMessage(targetMessageHandle, (byte)SaveFlags.ForceSave);
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, saveChangesMessageResponse.ReturnValue, TestSuiteBase.ROPSucceedMsg);

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R728
            this.Site.CaptureRequirementIfAreEqual<int>(
                8,
                BitConverter.GetBytes(saveChangesMessageResponse.MessageId).Length,
                728,
                @"[In RopSaveChangesMessage ROP Response Buffer] Message Id: 8 bytes containing the MID ([MS-OXCDATA] section 2.2.1.2) for the saved Message object.");

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R372, the MID in RopSaveChangesMessage Response is {0}.", saveChangesMessageResponse.MessageId);

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R372
            // Because the R728 verify the RopSaveChangesMessage ROP response contains a MID and it's length is 8 bytes.
            // So R372 will be verified directly.
            this.Site.CaptureRequirement(
                372,
                @"[In Receiving a RopSaveChangesMessage ROP Request] The response contains the MID ([MS-OXCDATA] section 2.2.1.2) of the committed message.");

            #endregion

            #region Call RopGetContentsTable to get the contents table of inbox folder after save message.
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(getContentsTableRequest, openedFolderHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            getContentsTableResponse = (RopGetContentsTableResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, createMessageResponse.ReturnValue, "Call RopGetContents should success.");
            uint contentTableHandle = this.ResponseSOHs[0][getContentsTableResponse.OutputHandleIndex];

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R687
            // If the e-mail in the Inbox one more than before Call RopSaveChangeMessage, then R687 will be verified.
            this.Site.CaptureRequirementIfAreEqual<uint>(
                rowCount + 1,
                getContentsTableResponse.RowCount,
                687,
                @"[In RopCreateMessage ROP] The RopCreateMessage ROP ([MS-OXCROPS] section 2.2.6.2) is used to create a new Message object.");

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R700
            this.Site.CaptureRequirementIfAreEqual<uint>(
                rowCount + 1,
                getContentsTableResponse.RowCount,
                700,
                @"[In RopSaveChangesMessage ROP] The RopSaveChangesMessage ROP ([MS-OXCROPS] section 2.2.6.3) commits the changes made to the Message object.");
            #endregion
            #endregion

            #region Call RopSetColumns to sets the properties visible on contents table.
            PropertyTag[] propertyTags = new PropertyTag[1];

            // The PropertyTag of PidTagMid.
            propertyTags[0] = new PropertyTag(0x674A, (ushort)PropertyType.PtypInteger64);
            RopSetColumnsRequest setColumnsRequest = new RopSetColumnsRequest()
            {
                RopId = (byte)RopId.RopSetColumns,
                LogonId = CommonLogonId,

                // Set InputHandleIndex to 0x00, which specifies the location in the Server object handle table where the handle
                // for the input Server object is stored, as specified in [MS-OXCROPS].
                InputHandleIndex = CommonInputHandleIndex,
                SetColumnsFlags = (byte)AsynchronousFlags.None,
                PropertyTagCount = (ushort)propertyTags.Length,
                PropertyTags = propertyTags
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(setColumnsRequest, contentTableHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopSetColumnsResponse setColumnsResponse = (RopSetColumnsResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, setColumnsResponse.ReturnValue, "Call RopSetColumns should success.");
            #endregion

            #region Call RopQueryRows to retrieve rows from contents table.
            RopQueryRowsRequest queryRowsRequest = new RopQueryRowsRequest()
            {
                RopId = (byte)RopId.RopQueryRows,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,
                QueryRowsFlags = (byte)QueryRowsFlags.Advance,
                ForwardRead = 0x01,
                RowCount = 0x1000
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(queryRowsRequest, contentTableHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopQueryRowsResponse queryRowsResponse = (RopQueryRowsResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, setColumnsResponse.ReturnValue, "Call RopQueryRowsRequest should success.");

            ulong messageID = 0;
            foreach (PropertyRow row in queryRowsResponse.RowData.PropertyRows)
            {
                ulong actualMID = BitConverter.ToUInt64(row.PropertyValues[0].Value, 0);

                if (actualMID == saveChangesMessageResponse.MessageId)
                {
                    messageID = actualMID;
                    break;
                }
            }

            Site.Assert.AreNotEqual<ulong>(messageID, 0, "The Message ID should in the contents table of the specified Folder object");
            #endregion

            #region Call RopOpenMessage to open the specific Message object.
            RopOpenMessageRequest openMessageRequest = new RopOpenMessageRequest()
            {
                RopId = (byte)RopId.RopOpenMessage,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,
                OutputHandleIndex = CommonOutputHandleIndex,
                CodePageId = 0x0FFF, // Code page of Logon object is used
                FolderId = logonResponse.FolderIds[4],
                OpenModeFlags = 0x00,
                MessageId = messageID
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(openMessageRequest, this.insideObjHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);

            RopOpenMessageResponse openMessageResponse = (RopOpenMessageResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, setColumnsResponse.ReturnValue, "Call RopOpenMessage should success.");

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R647
            this.Site.CaptureRequirementIfAreEqual<uint>(
                TestSuiteBase.Success,
                openMessageResponse.ReturnValue,
                647,
                @"[In RopOpenMessage ROP] The RopOpenMessage ROP ([MS-OXCROPS] section 2.2.6.1) provides access to an existing Message object, which is identified by the message ID (MID), whose structure is specified in [MS-OXCDATA] section 2.2.1.2.<7>");

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R251
            this.Site.CaptureRequirementIfAreEqual<uint>(
                TestSuiteBase.Success,
                openMessageResponse.ReturnValue,
                251,
                @"[In Sending a RopOpenMessage ROP Request] The MID is accessible from the contents table of the Folder object that contains the Message object by including the PidTagMid property ([MS-OXCFXICS] section 2.2.1.2.1) in a RopSetColumns ROP request ([MS-OXCROPS] section 2.2.5.1), as specified in [MS-OXCTABL] section 2.2.2.2.");
            #endregion
            #endregion

            #region Call RopRelease to release all resources
            this.ReleaseRop(targetMessageHandle);
            #endregion
        }
        public void MSOXCMSG_S04_TC01_GeneralPropertiesOnMessageObject()
        {
            this.CheckMapiHttpIsSupported();
            this.ConnectToServer(ConnectionType.PrivateMailboxServer);

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

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

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

            #region Call RopModifyRecipients to add recipient to message created by step2
            PropertyTag[] recipientColumns = this.CreateRecipientColumns();
            List<ModifyRecipientRow> modifyRecipientRow = new List<ModifyRecipientRow>
            {
                this.CreateModifyRecipientRow(Common.GetConfigurationPropertyValue("AdminUserName", this.Site), 0)
            };
            this.AddRecipients(modifyRecipientRow, targetMessageHandle, recipientColumns);
            #endregion

            #region Call RopGetPropertiesSpecific to get PidTagMessageFlags property for created message before save message.
            // Prepare property Tag 
            PropertyTag[] tagArray = new PropertyTag[1];
            tagArray[0] = PropertyHelper.PropertyTagDic[PropertyNames.PidTagMessageFlags];

            // Get properties for Created Message
            RopGetPropertiesSpecificRequest getPropertiesSpecificRequest = new RopGetPropertiesSpecificRequest()
            {
                RopId = (byte)RopId.RopGetPropertiesSpecific,
                LogonId = CommonLogonId, // The logonId 0x00 is associated with this operation.
                InputHandleIndex = CommonInputHandleIndex, // This index specifies the location 0x00 in the Server Object Handle Table where the handle for the input Server Object is stored. 
                PropertySizeLimit = 0xFFFF, // This value specifies the maximum number of the property
                PropertyTagCount = (ushort)tagArray.Length,
                PropertyTags = tagArray
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(getPropertiesSpecificRequest, targetMessageHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopGetPropertiesSpecificResponse getPropertiesSpecificResponse = (RopGetPropertiesSpecificResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, getPropertiesSpecificResponse.ReturnValue, TestSuiteBase.ROPSucceedMsg);

            List<PropertyObj> ps = PropertyHelper.GetPropertyObjFromBuffer(tagArray, getPropertiesSpecificResponse);

            PropertyObj pidTagMessageFlags = PropertyHelper.GetPropertyByName(ps, PropertyNames.PidTagMessageFlags);
            #endregion

            #region Call RopSetProperties to set PidTagMessageFlags property of created message.
            List<PropertyObj> propertyList = this.SetGeneralPropertiesOfMessage();
            int messageFlags = Convert.ToInt32(pidTagMessageFlags.Value) | (int)MessageFlags.MfResend;
            propertyList.Add(new PropertyObj(PropertyNames.PidTagMessageFlags, BitConverter.GetBytes(messageFlags)));
            this.SetPropertiesForMessage(targetMessageHandle, propertyList);
            #endregion

            #region Call RopSaveChangesMessage to save created message.
            RopSaveChangesMessageResponse saveChangesMessageResponse = this.SaveMessage(targetMessageHandle, (byte)SaveFlags.ForceSave);

            // The message ID of specific message created by above step.
            ulong messageId = saveChangesMessageResponse.MessageId;
            #endregion

            #region Call RopGetContentsTable to get the contents table of inbox folder before submit message.
            RopGetContentsTableResponse getContentsTableResponse = this.GetContentTableSuccess(folderHandle);
            uint contentTableHandle = this.ResponseSOHs[0][getContentsTableResponse.OutputHandleIndex];
            uint rowCountBeforeSubmit = getContentsTableResponse.RowCount;
            this.ReleaseRop(contentTableHandle);
            #endregion

            #region Call RopSubmitMessage to submit message
            RopSubmitMessageRequest submitMessageRequest = new RopSubmitMessageRequest()
            {
                RopId = (byte)RopId.RopSubmitMessage,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,
                SubmitFlags = (byte)SubmitFlags.None
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(submitMessageRequest, targetMessageHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopSubmitMessageResponse submitMessageResponse = (RopSubmitMessageResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, submitMessageResponse.ReturnValue, "Call RopSubmitMessage should success.");
            #endregion

            #region Call RopOpenMessage to open created message.
            RopOpenMessageRequest openMessageRequest = new RopOpenMessageRequest
            {
                RopId = (byte)RopId.RopOpenMessage,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,
                OutputHandleIndex = CommonOutputHandleIndex,
                CodePageId = 0x0FFF,
                FolderId = logonResponse.FolderIds[4],
                OpenModeFlags = (byte)MessageOpenModeFlags.ReadOnly,
                MessageId = messageId
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(openMessageRequest, this.insideObjHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopOpenMessageResponse openMessageResponse = (RopOpenMessageResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, openMessageResponse.ReturnValue, "Call RopOpenMessage should success.");
            targetMessageHandle = this.ResponseSOHs[0][openMessageResponse.OutputHandleIndex];

            #region Verify MS-OXCMSG_R676, MS-OXCMSG_R678 and MS-OXCMSG_R1298
            string subjectPrefixInOpenResponse = System.Text.ASCIIEncoding.ASCII.GetString(openMessageResponse.SubjectPrefix.String);

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R676
            this.Site.CaptureRequirementIfAreEqual<string>(
                TestDataOfPidTagSubjectPrefix,
                subjectPrefixInOpenResponse.Substring(0, subjectPrefixInOpenResponse.Length - 1),
                676,
                @"[In RopOpenMessage ROP Response Buffer] [SubjectPrefix] The SubjectPrefix field contains the value of the PidTagSubjectPrefix property (section 2.2.1.9).");

            string normalizedSubjectInOpenResponse = System.Text.ASCIIEncoding.ASCII.GetString(openMessageResponse.NormalizedSubject.String);

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R678
            this.Site.CaptureRequirementIfAreEqual<string>(
                TestSuiteBase.TestDataOfPidTagNormalizedSubject,
                normalizedSubjectInOpenResponse.Substring(0, normalizedSubjectInOpenResponse.Length - 1),
                678,
                @"[In RopOpenMessage ROP Response Buffer] [NormalizedSubject] The NormalizedSubject field contains the value of the PidTagNormalizedSubject property (section 2.2.1.10).");

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R1298
            this.Site.CaptureRequirementIfAreEqual<int>(
                0x10,
                openMessageResponse.RecipientRows[0].RecipientType,
                1298,
                @"[In RopOpenMessage ROP Response Buffer] [RecipientRows] The value 0x10 means when resending a previous failure, this flag indicates that this recipient (1) did not successfully receive the message on the previous attempt.");

            #endregion
            #endregion

            #region Call RopGetPropertiesAll to get all properties of created message.
            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, targetMessageHandle, ref this.response, ref this.rawData, GetPropertiesFlags.MessageProperties);
            RopGetPropertiesAllResponse getPropertiesAllResponse = (RopGetPropertiesAllResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, getPropertiesAllResponse.ReturnValue, "Call RopGetPropertiesAll should success.");
            List<PropertyObj> propertyValues = PropertyHelper.GetPropertyObjFromBuffer(getPropertiesAllResponse);

            PropertyObj pidTagImportance = PropertyHelper.GetPropertyByName(propertyValues, PropertyNames.PidTagImportance);
            PropertyObj pidTagPriority = PropertyHelper.GetPropertyByName(propertyValues, PropertyNames.PidTagPriority);
            PropertyObj pidTagSensitivity = PropertyHelper.GetPropertyByName(propertyValues, PropertyNames.PidTagSensitivity);
            PropertyObj pidTagTrustSender = PropertyHelper.GetPropertyByName(propertyValues, PropertyNames.PidTagTrustSender);
            PropertyObj pidTagSubject = PropertyHelper.GetPropertyByName(propertyValues, PropertyNames.PidTagSubject);
            PropertyObj pidTagSubjectPrefix = PropertyHelper.GetPropertyByName(propertyValues, PropertyNames.PidTagSubjectPrefix);
            PropertyObj pidTagNormalizedSubject = PropertyHelper.GetPropertyByName(propertyValues, PropertyNames.PidTagNormalizedSubject);

            #region Verify requirements
            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R1668 ,the property count is {0}.", getPropertiesAllResponse.PropertyValueCount);

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R1668
            bool isVerifiedR1668 = getPropertiesAllResponse.PropertyValueCount > 0;

            this.Site.CaptureRequirementIfIsTrue(
                isVerifiedR1668,
                1668,
                @"[In RopOpenMessage ROP Response Buffer] [HasNamedProperties] Nonzero: Named properties are defined for this Message object and can be obtained through a RopGetPropertiesAll ROP request ([MS-OXCROPS] section 2.2.8.4).");

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R72
            this.Site.CaptureRequirementIfAreEqual<int>(
                0x00000000,
                Convert.ToInt32(pidTagImportance.Value),
                72,
                @"[In PidTagImportance Property] [The value 0x00000000 indicates the level of importance assigned by the end user to the Message object is] Low importance.");

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R80
            this.Site.CaptureRequirementIfAreEqual<int>(
                -1,
                Convert.ToInt32(pidTagPriority.Value),
                80,
                @"[In PidTagPriority Property] [The value 0xFFFFFFFF indicates  the client's request for the priority is] Not urgent.");

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R86
            this.Site.CaptureRequirementIfAreEqual<int>(
                0x00000001,
                Convert.ToInt32(pidTagSensitivity.Value),
                86,
                @"[In PidTagSensitivity Property] [The value 0x00000001 indicates the sender's assessment of the sensitivity of the Message object is] Personal.");

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

                // Verify MS-OXCMSG requirement: MS-OXCMSG_R1236
                this.Site.CaptureRequirementIfAreEqual<int>(
                    0x00000001,
                    (int)pidTagTrustSender.Value,
                    1236,
                    @"[In PidTagTrustSender] The value 0x00000001 indicates that the message was delivered through a trusted transport channel.");

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

                // Verify MS-OXCMSG requirement: MS-OXCMSG_R1713
                this.Site.CaptureRequirementIfIsNotNull(
                    pidTagTrustSender.Value,
                    1713,
                    @"[In Appendix A: Product Behavior] Implementation does support the PidTagTrustSender property. (Exchange 2007 follows this behavior.)");
            }

            PropertyObj pidTagPurportedSenderDomain = PropertyHelper.GetPropertyByName(propertyValues, PropertyNames.PidTagPurportedSenderDomain);

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R1214
            this.Site.CaptureRequirementIfAreEqual<string>(
                Common.GetConfigurationPropertyValue("Domain", this.Site),
                pidTagPurportedSenderDomain.Value.ToString(),
                1214,
                @"[In PidTagPurportedSenderDomain Property] The PidTagPurportedSenderDomain property ([MS-OXPROPS] section 2.865) contains the domain name of the last sender responsible for transmitting the current message.");

            PropertyObj pidTagAlternateRecipientAllowed = PropertyHelper.GetPropertyByName(propertyValues, PropertyNames.PidTagAlternateRecipientAllowed);

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R1797
            this.Site.CaptureRequirementIfIsTrue(
                Convert.ToBoolean(pidTagAlternateRecipientAllowed.Value),
                1797,
                @"[In PidTagAlternateRecipientAllowed Property] This property [PidTagAlternateRecipientAllowed] is set to ""TRUE"" if autoforwarding is allowed.");

            PropertyObj pidTagResponsibility = PropertyHelper.GetPropertyByName(propertyValues, PropertyNames.PidTagResponsibility);

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R1198
            this.Site.CaptureRequirementIfIsTrue(
                Convert.ToBoolean(pidTagResponsibility.Value),
                1198,
                @"[In PidTagResponsibility Property] This property [PidTagResponsibility] is set to ""TRUE"" if another agent has accepted responsibility.");

            pidTagMessageFlags = PropertyHelper.GetPropertyByName(propertyValues, PropertyNames.PidTagMessageFlags);

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R515
            this.Site.CaptureRequirementIfAreEqual<int>(
                0x00000080,
                Convert.ToInt32(pidTagMessageFlags.Value) & 0x00000080,
                515,
                @"[In PidTagMessageFlags Property] [mfResend (0x00000080)] The message includes a request for a resend operation with a non-delivery report.");
            #endregion
            #endregion

            #region Call RopGetPropertiesSpecific to get the specific properties of created message.
            List<PropertyTag> propertiesOfMessage = this.GetPropertyTagListOfMessageObject();
            propertyValues = this.GetSpecificPropertiesOfMessage(logonResponse.FolderIds[4], messageId, this.insideObjHandle, propertiesOfMessage);

            // Parse property response get Property Value to verify test  case requirement
            pidTagImportance = PropertyHelper.GetPropertyByName(propertyValues, PropertyNames.PidTagImportance);
            pidTagSubjectPrefix = PropertyHelper.GetPropertyByName(propertyValues, PropertyNames.PidTagSubjectPrefix);
            pidTagNormalizedSubject = PropertyHelper.GetPropertyByName(propertyValues, PropertyNames.PidTagNormalizedSubject);
            pidTagSubject = PropertyHelper.GetPropertyByName(propertyValues, PropertyNames.PidTagSubject);
            PropertyObj pidTagRecipientDisplayName = PropertyHelper.GetPropertyByName(propertyValues, PropertyNames.PidTagRecipientDisplayName);

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R58
            this.Site.CaptureRequirementIfAreEqual<string>(
                TestDataOfPidTagSubjectPrefix,
                pidTagSubjectPrefix.Value.ToString(),
                58,
                @"[In PidTagSubjectPrefix Property] The PidTagSubjectPrefix property ([MS-OXPROPS] section 2.1096) contains the prefix for the subject of the message.");

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R64
            this.Site.CaptureRequirementIfAreEqual<string>(
                TestSuiteBase.TestDataOfPidTagNormalizedSubject,
                pidTagNormalizedSubject.Value.ToString(),
                64,
                @"[In PidTagNormalizedSubject Property] The PidTagNormalizedSubject property ([MS-OXPROPS] section 2.877) contains the normalized subject of the message, as specified in [MS-OXCMAIL] section 2.2.3.2.6.1.");

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

            string mailSubject = TestDataOfPidTagSubjectPrefix + TestDataOfPidTagNormalizedSubject;

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R1238
            this.Site.CaptureRequirementIfAreEqual<string>(
                mailSubject,
                pidTagSubject.Value.ToString(),
                1238,
                @"[In PidTagSubject Property] The PidTagSubject property ([MS-OXPROPS] section 2.1021) contains the full subject of an e-mail message.");

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R1239
            this.Site.CaptureRequirementIfAreEqual<string>(
                mailSubject,
                pidTagSubject.Value.ToString(),
                1239,
                @"[In PidTagSubject Property] The full subject is a concatenation of the subject prefix, as identified by the PidTagSubjectPrefix property (section 2.2.1.9), and the normalized subject, as identified by the PidTagNormalizedSubject property (section 2.2.1.10).");

            PropertyObj pidTagAutoForwarded = PropertyHelper.GetPropertyByName(propertyValues, PropertyNames.PidTagAutoForwarded);

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R1108
            this.Site.CaptureRequirementIfAreEqual<byte>(
                0x00,
                Convert.ToByte(pidTagAutoForwarded.Value),
                1108,
                @"[In PidTagAutoForwarded Property] If this property [PidTagAutoForwarded] is unset, a default value of 0x00 is assumed.");
            
            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R2047");
        
            // Verify MS-OXCMSG requirement: MS-OXCMSG_R2047
            this.Site.CaptureRequirementIfAreEqual<string>(
                Common.GetConfigurationPropertyValue("AdminUserName", this.Site),
                pidTagRecipientDisplayName.Value.ToString(),
                2047,
                @"[In PidTagRecipientDisplayName Property] The PidTagRecipientDisplayName property ([MS-OXPROPS] section 2.888) specifies the display name of a recipient (2).");
            #endregion
            #endregion

            #region Receive the message sent by step 9.
            bool isMessageReceived = WaitEmailBeDelivered(folderHandle, rowCountBeforeSubmit);
            Site.Assert.IsTrue(isMessageReceived, "The message should be received.");
            #endregion

            #region Call RopRelease to release all resources.
            this.ReleaseRop(targetMessageHandle);
            this.ReleaseRop(folderHandle);
            #endregion
        }
        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_TC04_OpenSoftDeletedMessage()
        {
            this.CheckMapiHttpIsSupported();
            this.ConnectToServer(ConnectionType.PrivateMailboxServer);

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

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

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

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

            this.ReleaseRop(targetMessageHandleForDelete);

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

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

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

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

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

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

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

            #region Call RopRelease to release the created message
            this.ReleaseRop(openedFolderHandle);
            #endregion
        }
        public void MSOXCMSG_S05_TC03_RopOpenMessageFailure()
        {
            this.CheckMapiHttpIsSupported();
            this.ConnectToServer(ConnectionType.PrivateMailboxServer);

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

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

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

            #region Call RopOpenMessage to open a message which does not exist.
            RopOpenMessageRequest openMessageRequest = new RopOpenMessageRequest()
            {
                RopId = (byte)RopId.RopOpenMessage,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,
                OutputHandleIndex = CommonOutputHandleIndex,
                CodePageId = 0x0FFF, // Code page of Logon object is used
                FolderId = logonResponse.FolderIds[4], // Open the message in INBOX folder in which message is created.
                OpenModeFlags = 0x00, // The message will be opened as read-only
                MessageId = targetMessageId - 1 // The specified ID does not exist. 
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(openMessageRequest, this.insideObjHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopOpenMessageResponse openMessageResponse = (RopOpenMessageResponse)this.response;

            #region Verify MS-OXCMSG_R323, MS-OXCMSG_R1477 and MS-OXCMSG_R333
            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R323");

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R323
            this.Site.CaptureRequirementIfAreNotEqual<uint>(
                TestSuiteBase.Success,
                openMessageResponse.ReturnValue,
                323,
                @"[In Receiving a RopOpenMessage ROP Request] A RopOpenMessage ROP MUST NOT succeed if a Message object with the specified ID does not exist.");

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R1477
            this.Site.CaptureRequirementIfAreEqual<uint>(
                0x8004010F,
                openMessageResponse.ReturnValue,
                1477,
                @"[In Receiving a RopOpenMessage ROP Request] [ecNotFound (0x8004010F)] The folder corresponding to the FID ([MS-OXCDATA] section 2.2.1.1) entered in the ROP request buffer does not contain a message with the entered MID.");

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R333
            this.Site.CaptureRequirementIfAreEqual<uint>(
                0x8004010F,
                openMessageResponse.ReturnValue,
                333,
                @"[In Receiving a RopOpenMessage ROP Request] [ecNotFound (0x8004010F)] The MID ([MS-OXCDATA] section 2.2.1.2) does not correspond to a message in the database.");
            #endregion
            #endregion

            #region Call RopOpenMessage to open a message and the value of the InputHandleIndex field on which this ROP was called does not refer to a Folder object or a Store object.
            openMessageRequest = new RopOpenMessageRequest()
            {
                RopId = (byte)RopId.RopOpenMessage,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonOutputHandleIndex, // the value of the InputHandleIndex field does not refer to a Folder object or a Store object.
                OutputHandleIndex = CommonOutputHandleIndex, 
                CodePageId = 0x0FFF, // Code page of Logon object is used
                FolderId = logonResponse.FolderIds[4], // Open the message in INBOX folder in which message is created.
                OpenModeFlags = 0x00, // The message will be opened as read-only
                MessageId = targetMessageId
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(openMessageRequest, this.insideObjHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            openMessageResponse = (RopOpenMessageResponse)this.response;

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R1478
            this.Site.CaptureRequirementIfAreEqual<uint>(
                0x000004b9,
                openMessageResponse.ReturnValue,
                1478,
                @"[In Receiving a RopOpenMessage ROP Request] ecNullObject (0x000004b9)] The value of the InputHandleIndex field on which this ROP was called does not refer to a Folder object or a Store object");
            #endregion
            #endregion

            #region Call RopRelease to release the created message.
            this.ReleaseRop(targetMessageHandle);
            #endregion
        }
        public void MSOXCMSG_S05_TC02_IgnoreOpenModeFlagsOnRopOpenMessage()
        {
            this.CheckMapiHttpIsSupported();
            this.ConnectToServer(ConnectionType.PrivateMailboxServer);

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

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

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

            #region Call RopOpenMessage and OpenModeFlags is 0x08 to open the created message.
            RopOpenMessageRequest openMessageRequestFirst = new RopOpenMessageRequest()
            {
                RopId = (byte)RopId.RopOpenMessage,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,
                OutputHandleIndex = CommonOutputHandleIndex,
                CodePageId = 0x0FFF, // Code page of Logon object is used
                FolderId = logonResponse.FolderIds[4], // Open the message in INBOX folder in which message is created.
                OpenModeFlags = 0x08, // The OpenModeFlags other bit are set, server should ignore this bit.
                MessageId = saveChangesMessageResponse.MessageId // Open the saved message
            };

            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(openMessageRequestFirst, this.insideObjHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopOpenMessageResponse openMessageResponseFirst = (RopOpenMessageResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, openMessageResponseFirst.ReturnValue, "Call RopOpenMessage should success.");

            uint openedMessageHandleFirst = this.ResponseSOHs[0][openMessageResponseFirst.OutputHandleIndex];
            #endregion

            #region Call RopOpenMessage and OpenModeFlags is 0x0B to open the created message.
            RopOpenMessageRequest openMessageRequestSecond = new RopOpenMessageRequest()
            {
                RopId = (byte)RopId.RopOpenMessage,
                LogonId = CommonLogonId,
                InputHandleIndex = CommonInputHandleIndex,
                OutputHandleIndex = CommonOutputHandleIndex,
                CodePageId = 0x0FFF, // Code page of Logon object is used
                FolderId = logonResponse.FolderIds[4], // Open the message in INBOX folder in which message is created.
                OpenModeFlags = 0x0B, // The OpenModeFlags other bit are set, server should ignore this bit.
                MessageId = saveChangesMessageResponse.MessageId // Open the saved message
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(openMessageRequestSecond, this.insideObjHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopOpenMessageResponse openMessageResponseSecond = (RopOpenMessageResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, openMessageResponseSecond.ReturnValue, "Call RopOpenMessage should success.");

            uint openedMessageHandleSecond = this.ResponseSOHs[0][openMessageResponseSecond.OutputHandleIndex];
            #endregion

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R1838
            this.Site.CaptureRequirementIfAreEqual<RopOpenMessageResponse>(
                openMessageResponseFirst,
                openMessageResponseSecond,
                1838,
                @"[In RopOpenMessage ROP Request Buffer] The server responses are same when OpenModeFlags are set with two different values, and the two different values are not one of 0x00, 0x01, 0x03 and 0x04.");

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R1475
            this.Site.CaptureRequirementIfAreNotEqual<uint>(
                openedMessageHandleFirst,
                openedMessageHandleSecond,
                1475,
                @"[In Receiving a RopOpenMessage ROP Request] When the server receives multiple requests to open the same Message object, it returns a different handle and maintains a separate transaction (3) for each.");
            #endregion

            #region Call RopRelease to release the created message.
            this.ReleaseRop(openedMessageHandleFirst);
            this.ReleaseRop(openedMessageHandleSecond);
            #endregion
        }
        /// <summary>
        /// Open a specific message.
        /// </summary>
        /// <param name="folderId">The folder Id of specific folder that contains specific message.</param>
        /// <param name="messageId">The message id of specific message.</param>
        /// <param name="objectHandle">A Server object handle.</param>
        /// <param name="openFlags">The OpenModeFlags value.</param>
        /// <param name="openMessageResponse">The response of RopOpenMessage.</param>
        /// <returns>A Server object handle of specific message.</returns>
        protected uint OpenSpecificMessage(ulong folderId, ulong messageId, uint objectHandle, MessageOpenModeFlags openFlags, out RopOpenMessageResponse openMessageResponse)
        {
            RopOpenMessageRequest openMessageRequest = new RopOpenMessageRequest()
            {
                RopId = (byte)RopId.RopOpenMessage,
                LogonId = CommonLogonId, // The logonId 0x00 is associated with this operation.

                InputHandleIndex = CommonInputHandleIndex, // This index specifies the location 0x00 in the Server Object Handle Table where the handle for the input Server Object is stored. 
                OutputHandleIndex = CommonOutputHandleIndex, // This index specifies the location 0x01 in the Server Object Handle Table where the handle for the output Server Object is stored. 
                CodePageId = 0x0FFF, // Code page of Logon object is used
                FolderId = folderId, // Open the message in INBOX folder in which message is created.
                OpenModeFlags = (byte)openFlags, // The message will be opened as read-only.
                MessageId = messageId // Open the saved message
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(openMessageRequest, objectHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            openMessageResponse = (RopOpenMessageResponse)this.response;
            Site.Assert.AreEqual<uint>(TestSuiteBase.Success, openMessageResponse.ReturnValue, "Call RopOpenMessage should success.");
            return this.ResponseSOHs[0][openMessageRequest.OutputHandleIndex];
        }