Exemple #1
0
        /// <summary>
        /// This ROP opens an attachment as a message.
        /// </summary>
        /// <param name="handle">The handle to operate.</param>
        /// <param name="openEmbeddedMessageResponse">The response of this ROP.</param>
        /// <param name="needVerify">Whether need to verify the response.</param>
        /// <returns>The index of the output handle of the response.</returns>
        private uint RopOpenEmbeddedMessage(uint handle, out RopOpenEmbeddedMessageResponse openEmbeddedMessageResponse, bool needVerify)
        {
            this.rawDataValue      = null;
            this.responseValue     = null;
            this.responseSOHsValue = null;

            RopOpenEmbeddedMessageRequest openEmbeddedMessageRequest = new RopOpenEmbeddedMessageRequest()
            {
                RopId = (byte)RopId.RopOpenEmbeddedMessage,

                // The logonId 0x00 is associated with RopOpenEmbeddedMessage.
                LogonId = 0x00,

                // This index specifies the location 0x00 in the Server Object Handle Table where the handle for the input Server Object is stored.
                InputHandleIndex = (byte)HandleIndex.FirstIndex,

                // This index specifies the location 0x01 in the Server Object Handle Table where the handle for the output Server Object is stored.
                OutputHandleIndex = (byte)HandleIndex.SecondIndex,
                CodePageId        = 0x0FFF,
                OpenModeFlags     = 0x02
            };

            this.responseSOHsValue      = this.ProcessSingleRop(openEmbeddedMessageRequest, handle, ref this.responseValue, ref this.rawDataValue, RopResponseType.SuccessResponse);
            openEmbeddedMessageResponse = (RopOpenEmbeddedMessageResponse)this.responseValue;

            if (needVerify)
            {
                this.Site.Assert.AreEqual((uint)RopResponseType.SuccessResponse, openEmbeddedMessageResponse.ReturnValue, string.Format("RopOpenEmbeddedMessage Failed! Error: 0x{0:X8}", openEmbeddedMessageResponse.ReturnValue));
            }

            return(this.responseSOHsValue[0][openEmbeddedMessageResponse.OutputHandleIndex]);
        }
Exemple #2
0
        /// <summary>
        /// Send ROP request with single operation.
        /// </summary>
        /// <param name="ropRequest">ROP request objects.</param>
        /// <param name="insideObjHandle">Server object handle in request.</param>
        /// <param name="response">ROP response objects.</param>
        /// <param name="rawData">The ROP response payload.</param>
        /// <param name="getPropertiesFlag">The flag indicate the test cases expect to get which object type's properties(message's properties or attachment's properties).</param>
        /// <param name="returnValue">An unsigned integer value indicates the return value of call EcDoRpcExt2 method.</param>
        /// <returns>Server objects handles in response.</returns>
        public List <List <uint> > DoRopCall(ISerializable ropRequest, uint insideObjHandle, ref object response, ref byte[] rawData, GetPropertiesFlags getPropertiesFlag, out uint returnValue)
        {
            List <ISerializable> requestRops = new List <ISerializable>
            {
                ropRequest
            };

            List <uint> requestSOH = new List <uint>
            {
                insideObjHandle
            };

            if (Common.IsOutputHandleInRopRequest(ropRequest))
            {
                // Add an element for server output object handle, set default value to 0xFFFFFFFF
                requestSOH.Add(DefaultOutputHandle);
            }

            List <IDeserializable> responseRops = new List <IDeserializable>();
            List <List <uint> >    responseSOHs = new List <List <uint> >();

            // 0x10008 specifies the maximum size of the rgbOut buffer to place in Response.
            uint ret = this.oxcropsClient.RopCall(requestRops, requestSOH, ref responseRops, ref responseSOHs, ref rawData, 0x10008);

            returnValue = ret;
            if (ret == OxcRpcErrorCode.ECRpcFormat)
            {
                this.Site.Assert.Fail("Error RPC Format");
            }

            if (ret != 0)
            {
                return(responseSOHs);
            }

            if (responseRops != null)
            {
                if (responseRops.Count > 0)
                {
                    response = responseRops[0];
                }
            }
            else
            {
                response = null;
            }

            if (ropRequest.GetType() == typeof(RopReleaseRequest))
            {
                return(responseSOHs);
            }

            byte ropId = (byte)BitConverter.ToInt16(ropRequest.Serialize(), 0);

            List <PropertyObj> pts = null;

            switch (ropId)
            {
            case (byte)RopId.RopOpenMessage:
                RopOpenMessageResponse openMessageResponse = (RopOpenMessageResponse)response;

                // This check is for the open specification expectation for a particular request with some valid input parameters.
                if (openMessageResponse.ReturnValue == 0x00000000)
                {
                    this.VerifyRopOpenMessageResponse(openMessageResponse);
                }

                break;

            case (byte)RopId.RopGetPropertiesSpecific:
                // RopGetPropertiesSpecificRequest
                pts = PropertyHelper.GetPropertyObjFromBuffer(((RopGetPropertiesSpecificRequest)ropRequest).PropertyTags, (RopGetPropertiesSpecificResponse)response);

                foreach (PropertyObj pitem in pts)
                {
                    // Verify capture code for MS-OXCMSG.
                    this.VerifyMessageSyntaxDataType(pitem);
                }

                PropertyObj propertyObjPidTagSubjectPrefix     = PropertyHelper.GetPropertyByName(pts, PropertyNames.PidTagSubjectPrefix);
                PropertyObj propertyObjPidTagNormalizedSubject = PropertyHelper.GetPropertyByName(pts, PropertyNames.PidTagNormalizedSubject);

                // Verify the message of PidTagSubjectPrefixAndPidTagNormalizedSubject
                if (PropertyHelper.IsPropertyValid(propertyObjPidTagSubjectPrefix) || PropertyHelper.IsPropertyValid(propertyObjPidTagNormalizedSubject))
                {
                    this.VerifyMessageSyntaxPidTagSubjectPrefixAndPidTagNormalizedSubject(propertyObjPidTagSubjectPrefix, propertyObjPidTagNormalizedSubject);
                }

                // Verify the requirements of PidTagAttachmentLinkId and PidTagAttachmentFlags.
                PropertyObj pidTagAttachmentLinkId = PropertyHelper.GetPropertyByName(pts, PropertyNames.PidTagAttachmentLinkId);
                if (PropertyHelper.IsPropertyValid(pidTagAttachmentLinkId))
                {
                    this.VerifyMessageSyntaxPidTagAttachmentLinkIdAndPidTagAttachmentFlags(pidTagAttachmentLinkId);
                }

                PropertyObj pidTagAttachmentFlags = PropertyHelper.GetPropertyByName(pts, PropertyNames.PidTagAttachmentFlags);
                if (PropertyHelper.IsPropertyValid(pidTagAttachmentFlags))
                {
                    this.VerifyMessageSyntaxPidTagAttachmentLinkIdAndPidTagAttachmentFlags(pidTagAttachmentFlags);
                }

                // Verify the requirements of PidTagDisplayName
                PropertyObj pidTagDisplayName        = PropertyHelper.GetPropertyByName(pts, PropertyNames.PidTagDisplayName);
                PropertyObj pidTagAttachLongFilename = PropertyHelper.GetPropertyByName(pts, PropertyNames.PidTagAttachLongFilename);

                if (PropertyHelper.IsPropertyValid(pidTagDisplayName) && PropertyHelper.IsPropertyValid(pidTagAttachLongFilename))
                {
                    this.VerifyMessageSyntaxPidTagDisplayName(pidTagDisplayName, pidTagAttachLongFilename);
                }

                break;

            case (byte)RopId.RopGetPropertiesAll:
                RopGetPropertiesAllResponse getPropertiesAllResponse = (RopGetPropertiesAllResponse)response;
                pts = PropertyHelper.GetPropertyObjFromBuffer(getPropertiesAllResponse);

                foreach (PropertyObj pitem in pts)
                {
                    // Verify capture code for MS-OXCMSG.
                    this.VerifyMessageSyntaxDataType(pitem);
                }

                // Verify the requirements of PidTagArchiveDate
                PropertyObj pidTagArchiveDateObj = PropertyHelper.GetPropertyByName(pts, PropertyNames.PidTagArchiveDate);
                PropertyObj pidTagStartDateEtc   = PropertyHelper.GetPropertyByName(pts, PropertyNames.PidTagStartDateEtc);

                if (PropertyHelper.IsPropertyValid(pidTagArchiveDateObj))
                {
                    if (PropertyHelper.IsPropertyValid(pidTagStartDateEtc))
                    {
                        byte[] byteDest = new byte[8];
                        Array.Copy((byte[])pidTagStartDateEtc.Value, 6, byteDest, 0, 8);
                        this.VerifyMessageSyntaxPidTagArchiveDate(pidTagArchiveDateObj, DateTime.FromFileTimeUtc(BitConverter.ToInt64(byteDest, 0)));
                    }
                }

                PropertyObj pidTagAccessLevel = PropertyHelper.GetPropertyByName(pts, PropertyNames.PidTagAccessLevel);
                PropertyObj pidTagRecordKey   = PropertyHelper.GetPropertyByName(pts, PropertyNames.PidTagRecordKey);

                if (getPropertiesFlag == GetPropertiesFlags.MessageProperties)
                {
                    PropertyObj pidTagAccess = PropertyHelper.GetPropertyByName(pts, PropertyNames.PidTagAccess);

                    PropertyObj pidTagChangeKey            = PropertyHelper.GetPropertyByName(pts, PropertyNames.PidTagChangeKey);
                    PropertyObj pidTagCreationTime         = PropertyHelper.GetPropertyByName(pts, PropertyNames.PidTagCreationTime);
                    PropertyObj pidTagLastModificationTime = PropertyHelper.GetPropertyByName(pts, PropertyNames.PidTagLastModificationTime);
                    PropertyObj pidTagLastModifierName     = PropertyHelper.GetPropertyByName(pts, PropertyNames.PidTagLastModifierName);
                    PropertyObj pidTagSearchKey            = PropertyHelper.GetPropertyByName(pts, PropertyNames.PidTagSearchKey);

                    // Verify properties PidTagAccess, PidTagAccessLevel, PidTagChangeKey, PidTagCreationTime, PidTagLastModificationTime, PidTagLastModifierName and PidTagSearchKey exist on all Message objects.
                    this.VerifyPropertiesExistOnAllMessageObject(pidTagAccess, pidTagAccessLevel, pidTagChangeKey, pidTagCreationTime, pidTagLastModificationTime, pidTagLastModifierName, pidTagSearchKey);
                }

                if (getPropertiesFlag == GetPropertiesFlags.AttachmentProperties)
                {
                    // Verify properties PidTagAccessLevel and PidTagRecordKey exist on any Attachment object.
                    this.VerifyPropertiesExistOnAllAttachmentObject(pidTagAccessLevel, pidTagRecordKey);
                }

                break;

            case (byte)RopId.RopCreateMessage:
                RopCreateMessageResponse createMessageResponse = (RopCreateMessageResponse)response;

                // Adapter requirements related with RopCreateMessage will be verified if the response is a successful one.
                if (createMessageResponse.ReturnValue == 0x00000000)
                {
                    int hasMessageId = createMessageResponse.HasMessageId;
                    this.VerifyMessageSyntaxHasMessageId(hasMessageId);
                }

                break;

            case (byte)RopId.RopReadRecipients:
                RopReadRecipientsResponse readRecipientsResponse = (RopReadRecipientsResponse)response;

                // Adapter requirements related with RopReadRecipients will be verified if the response is a successful one.
                if (readRecipientsResponse.ReturnValue == 0x00000000)
                {
                    this.VerifyMessageSyntaxRowCount(readRecipientsResponse);
                }

                break;

            case (byte)RopId.RopSetMessageStatus:
                RopSetMessageStatusResponse setMessageStatusResponse = (RopSetMessageStatusResponse)response;

                // Adapter requirements related with RopSetMessageStatus will be verified if the response is a successful one.
                if (setMessageStatusResponse.ReturnValue == 0x00000000)
                {
                    this.VerifyMessageSyntaxMessageStatusFlags(setMessageStatusResponse);
                }

                break;

            case (byte)RopId.RopCreateAttachment:
                RopCreateAttachmentResponse createAttachmentResponse = (RopCreateAttachmentResponse)response;

                // Adapter requirements related with RopCreateAttachment will be verified if the response is a successful one.
                if (createAttachmentResponse.ReturnValue == 0x00000000)
                {
                    int id = (int)createAttachmentResponse.AttachmentID;
                    this.VerifyDataStructureRopCreateAttachmentResponse(createAttachmentResponse, id);
                }

                break;

            case (byte)RopId.RopOpenEmbeddedMessage:
                RopOpenEmbeddedMessageResponse openEmbeddedMessageResponse = (RopOpenEmbeddedMessageResponse)response;

                // Adapter requirements related with RopOpenEmbeddedMessage will be verified if the response is a successful one.
                if (openEmbeddedMessageResponse.ReturnValue == 0x00000000)
                {
                    ulong mid = openEmbeddedMessageResponse.MessageId;
                    this.VerifyDataStructureRopOpenEmbeddedMessageResponse(openEmbeddedMessageResponse, mid);
                }

                break;

            case (byte)RopId.RopSetMessageReadFlag:
                RopSetMessageReadFlagResponse setMessageReadFlagResponse = (RopSetMessageReadFlagResponse)response;

                // Adapter requirements related with RopSetMessageReadFlag will be verified if the response is a successful one.
                if (setMessageReadFlagResponse.ReturnValue == 0x00000000)
                {
                    this.VerifyMessageSyntaxReadStatusChanged(setMessageReadFlagResponse, (RopSetMessageReadFlagRequest)ropRequest);
                }

                break;

            case (byte)RopId.RopSetReadFlags:
                // Adapter requirements related with RopSetReadFlags will be verified if the response is a successful one.
                if (((RopSetReadFlagsResponse)response).ReturnValue == 0x00000000)
                {
                    this.VerifyRopSetReadFlagsResponse((RopSetReadFlagsResponse)response);
                }

                break;

            case (byte)RopId.RopGetMessageStatus:
                // Adapter requirements related with RopGetMessageStatus will be verified if the response is a successful one.
                if (((RopSetMessageStatusResponse)response).ReturnValue == 0x00000000)
                {
                    this.VerifyGetMessageStatusResponse((RopSetMessageStatusResponse)response);
                }

                break;

            default:
                break;
            }

            this.VerifyMAPITransport();

            return(responseSOHs);
        }
        public void MSOXCMSG_S09_TC01_RopOpenEmbeddedMessageSuccessfully()
        {
            this.CheckMapiHttpIsSupported();
            this.ConnectToServer(ConnectionType.PrivateMailboxServer);

            // Set property size
            int size = 0;

            TaggedPropertyValue[] taggedPropertyValueArray = this.CreateMessageTaggedPropertyValueArrays(out size, PidTagAttachMethodFlags.afEmbeddedMessage);

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

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

            #region Call RopCreateAttachment to create an embedded attachment.
            RopCreateAttachmentResponse createAttachmentResponse;
            uint attachmentId;
            uint attachmentHandle = this.CreateAttachment(targetMessageHandle, out createAttachmentResponse, out attachmentId);
            #endregion

            #region Call RopSetProperties to set PidTagAttachMethod property, that is the attachment is the embedded attachment.
            RopSetPropertiesRequest setPropertiesRequest = new RopSetPropertiesRequest()
            {
                RopId              = (byte)RopId.RopSetProperties,
                LogonId            = CommonLogonId,          // The logonId 0x00 is associated with RopSetProperties.
                InputHandleIndex   = CommonInputHandleIndex, // This index specifies the location 0x00 in the Server Object Handle Table where the handle for the input Server Object is stored.
                PropertyValueSize  = (ushort)(size + 2),
                PropertyValueCount = (ushort)taggedPropertyValueArray.Length,
                PropertyValues     = taggedPropertyValueArray
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(setPropertiesRequest, attachmentHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopSetPropertiesResponse setPropertiesResponse = (RopSetPropertiesResponse)this.response;
            Site.Assert.AreEqual <uint>(TestSuiteBase.Success, setPropertiesResponse.ReturnValue, TestSuiteBase.ROPSucceedMsg);
            #endregion

            #region Call RopGetPropertiesSpecific to get property PidTagAttachMethod of created Attachment
            List <PropertyTag> tagArray = new List <PropertyTag>
            {
                PropertyHelper.PropertyTagDic[PropertyNames.PidTagAttachMethod]
            };

            RopGetPropertiesSpecificResponse getPropertiesSpecificResponse;
            getPropertiesSpecificResponse = this.GetSpecificPropertiesOfMessage(attachmentHandle, tagArray);
            List <PropertyObj> pts = PropertyHelper.GetPropertyObjFromBuffer(tagArray.ToArray(), getPropertiesSpecificResponse);

            // Parse property response get Property Value to verify test  case requirement
            PropertyObj pidTagAttachMethod = PropertyHelper.GetPropertyByName(pts, PropertyNames.PidTagAttachMethod);
            #endregion

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R596
            this.Site.CaptureRequirementIfAreEqual <int>(
                0x00000005,
                Convert.ToInt32(pidTagAttachMethod.Value),
                596,
                @"[In PidTagAttachMethod Property] [afEmbeddedMessage (0x00000005)] The attachment is an embedded message that is accessed via the RopOpenEmbeddedMessage ROP ([MS-OXCROPS] section 2.2.6.16).");

            #region Call RopSaveChangesAttachment to save the attachment changes.
            RopSaveChangesAttachmentResponse saveChangesAttachmentResponse;
            this.SaveAttachment(attachmentHandle, out saveChangesAttachmentResponse);
            #endregion

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

            #region Call RopOpenEmbeddedMessage with OpenModeFlags set to 0x02 to create the attachment if it doesn't exist, and expect to get a successful response
            RopOpenEmbeddedMessageRequest openEmbeddedMessageRequest = new RopOpenEmbeddedMessageRequest()
            {
                RopId             = (byte)RopId.RopOpenEmbeddedMessage,
                LogonId           = CommonLogonId,           // The logonId 0x00 is associated with RopOpenEmbeddedMessage.
                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
                OpenModeFlags     = 0x02                     // Create the attachment if it does not already exist and open the message for both reading and writing
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(openEmbeddedMessageRequest, attachmentHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopOpenEmbeddedMessageResponse openEmbeddedMessageResponse = (RopOpenEmbeddedMessageResponse)this.response;
            Site.Assert.AreEqual <uint>(TestSuiteBase.Success, openEmbeddedMessageResponse.ReturnValue, TestSuiteBase.ROPSucceedMsg);
            uint embeddedMessageHandle = this.ResponseSOHs[0][openEmbeddedMessageResponse.OutputHandleIndex];
            #endregion

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

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R913
            // The embedded message hasn't been created, so MS-OXCMSG_R913 can be verified if the response of calling RopOpenEmbeddedMessage with OpenModeFlags set to 0x02 is successful.
            this.Site.CaptureRequirementIfAreEqual <uint>(
                TestSuiteBase.Success,
                openEmbeddedMessageResponse.ReturnValue,
                913,
                @"[In RopOpenEmbeddedMessage ROP Request Buffer] [OpenModeFlags] [Create (0x02)] Create the attachment if it does not already exist and open the message for both reading and writing.");

            #region Call RopRelease to release the embedded message
            this.ReleaseRop(embeddedMessageHandle);
            #endregion

            #region Call RopOpenEmbeddedMessage with OpenModeFlags set to 0x00 to open the embedded message as read-only.
            openEmbeddedMessageRequest.CodePageId    = 0x0FFF; // Code page of Logon object is used
            openEmbeddedMessageRequest.OpenModeFlags = 0x00;   // Open the message as read-only.
            this.ResponseSOHs           = this.MSOXCMSGAdapter.DoRopCall(openEmbeddedMessageRequest, attachmentHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            openEmbeddedMessageResponse = (RopOpenEmbeddedMessageResponse)this.response;
            Site.Assert.AreEqual <uint>(TestSuiteBase.Success, openEmbeddedMessageResponse.ReturnValue, TestSuiteBase.ROPSucceedMsg);
            embeddedMessageHandle = this.ResponseSOHs[0][openEmbeddedMessageResponse.OutputHandleIndex];
            #endregion

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R881
            // MS-OXCMSG_R881 can be verified when the handle returned from calling RopOpenEmbeddedMessage is not null.
            this.Site.CaptureRequirementIfIsNotNull(
                embeddedMessageHandle,
                881,
                @"[In RopOpenEmbeddedMessage ROP] The RopOpenEmbeddedMessage ROP ([MS-OXCROPS] section 2.2.6.16) retrieves a handle to a Message object from the given Attachment object.");

            #region Call RopModifyRecipients to add recipient to the read-only embedded message and expect to get the failure response
            // Initialize TestUser1
            PropertyTag[]             propertyTag        = this.CreateRecipientColumns();
            List <ModifyRecipientRow> modifyRecipientRow = new List <ModifyRecipientRow>
            {
                this.CreateModifyRecipientRow(TestUser1, 0)
            };

            RopModifyRecipientsResponse modifyRecipientsResponse;
            this.AddRecipients(modifyRecipientRow, embeddedMessageHandle, propertyTag, out modifyRecipientsResponse);
            #endregion

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

                // Verify MS-OXCMSG requirement: MS-OXCMSG_R3014
                // The response of RopModifyRecipients is not successful because the embedded message is opened as read-only, so MS-OXCMSG_R3014 can be verified.
                this.Site.CaptureRequirementIfAreNotEqual <uint>(
                    TestSuiteBase.Success,
                    modifyRecipientsResponse.ReturnValue,
                    3014,
                    @"[In Appendix A: Product Behavior] [OpenModeFlags] [ReadOnly (0x00)] Message will be opened as read only. (Exchange 2007 follows this behavior.)");
            }

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

                // Verify MS-OXCMSG requirement: MS-OXCMSG_R3013
                // The response of RopModifyRecipients is successful because the embedded message is opened as read/write, so MS-OXCMSG_R3013 can be verified.
                this.Site.CaptureRequirementIfAreEqual <uint>(
                    TestSuiteBase.Success,
                    modifyRecipientsResponse.ReturnValue,
                    3013,
                    @"[In Appendix A: Product Behavior]  [OpenModeFlags] [ReadOnly (0x00)] Message will be opened as read/write. (&lt;17&gt; Section 2.2.3.16.1:  Exchange 2010, Exchange 2013, Exchange 2016 and Exchange 2019 Preview  follow this behavior.)");
            }

            #region Call RopRelease to release the embedded message.
            this.ReleaseRop(embeddedMessageHandle);
            #endregion

            #region Call RopOpenEmbeddedMessage with OpenModeFlags set to 0x01 to open the embedded message as read/write
            openEmbeddedMessageRequest.InputHandleIndex = 0x00;
            openEmbeddedMessageRequest.OpenModeFlags    = 0x01; // Open the message for both reading and writing.
            this.ResponseSOHs           = this.MSOXCMSGAdapter.DoRopCall(openEmbeddedMessageRequest, attachmentHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            openEmbeddedMessageResponse = (RopOpenEmbeddedMessageResponse)this.response;
            embeddedMessageHandle       = this.ResponseSOHs[0][openEmbeddedMessageResponse.OutputHandleIndex];
            #endregion

            #region Call RopModifyRecipients to add recipient to the read/write embedded message and expect to get the successful response.
            this.AddRecipients(modifyRecipientRow, embeddedMessageHandle, propertyTag, out modifyRecipientsResponse);
            Site.Assert.AreEqual <uint>(TestSuiteBase.Success, modifyRecipientsResponse.ReturnValue, TestSuiteBase.ROPSucceedMsg);
            #endregion

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R912
            // The response of RopModifyRecipients is success because the embedded message is opened as read/write, so MS-OXCMSG_R912 can be verified.
            this.Site.CaptureRequirementIfAreEqual <uint>(
                TestSuiteBase.Success,
                modifyRecipientsResponse.ReturnValue,
                912,
                @"[In RopOpenEmbeddedMessage ROP Request Buffer] [OpenModeFlags] [ReadWrite (0x01)] Message will be opened for both reading and writing.");

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

            // Set property size
            int size = 0;

            TaggedPropertyValue[] taggedPropertyValueArray = this.CreateMessageTaggedPropertyValueArrays(out size, PidTagAttachMethodFlags.afEmbeddedMessage);

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

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

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

            #region Call RopOpenMessage to open the message.
            RopOpenMessageResponse openMessageResponse;
            uint openedMessageHandle = this.OpenSpecificMessage(logonResponse.FolderIds[4], saveChangesMessageResponse.MessageId, this.insideObjHandle, MessageOpenModeFlags.ReadWrite, out openMessageResponse);
            Site.Assert.AreEqual <uint>(TestSuiteBase.Success, openMessageResponse.ReturnValue, TestSuiteBase.ROPSucceedMsg);
            #endregion

            #region Call RopCreateAttachment to create an embedded attachment.
            RopCreateAttachmentResponse createAttachmentResponse;
            uint attachmentId;
            uint attachmentHandle = this.CreateAttachment(openedMessageHandle, out createAttachmentResponse, out attachmentId);
            #endregion

            #region Call RopSetProperties to set PidTagAttachMethod property, that is the attachment is the embedded attachment.
            // Setting PidTagAttachMethod property means the attachment is the embedded message
            RopSetPropertiesRequest setPropertiesRequest = new RopSetPropertiesRequest()
            {
                RopId              = (byte)RopId.RopSetProperties,
                LogonId            = CommonLogonId,          // The logonId 0x00 is associated with RopSetProperties.
                InputHandleIndex   = CommonInputHandleIndex, // This index specifies the location 0x00 in the Server Object Handle Table where the handle for the input Server Object is stored.
                PropertyValueSize  = (ushort)(size + 2),
                PropertyValueCount = (ushort)taggedPropertyValueArray.Length,
                PropertyValues     = taggedPropertyValueArray
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(setPropertiesRequest, attachmentHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopSetPropertiesResponse setPropertiesResponse = (RopSetPropertiesResponse)this.response;
            Site.Assert.AreEqual <uint>(TestSuiteBase.Success, setPropertiesResponse.ReturnValue, TestSuiteBase.ROPSucceedMsg);
            #endregion

            #region Call RopSaveChangesAttachment to save the attachment changes
            RopSaveChangesAttachmentResponse saveChangesAttachmentResponse;
            this.SaveAttachment(attachmentHandle, out saveChangesAttachmentResponse);
            #endregion

            #region Call RopOpenEmbeddedMessage with OpenModeFlags set to 0x02 to create an embedded message.
            RopOpenEmbeddedMessageRequest openEmbeddedMessageRequest = new RopOpenEmbeddedMessageRequest()
            {
                RopId             = (byte)RopId.RopOpenEmbeddedMessage,
                LogonId           = CommonLogonId,           // The logonId 0x00 is associated with RopOpenEmbeddedMessage.
                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
                OpenModeFlags     = 0x02                     // Create the attachment if it does not already exist and open the message for both reading and writing
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(openEmbeddedMessageRequest, attachmentHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopOpenEmbeddedMessageResponse openEmbeddedMessageResponse = (RopOpenEmbeddedMessageResponse)this.response;
            uint embeddedMessageHandle = this.ResponseSOHs[0][openMessageResponse.OutputHandleIndex];
            Site.Assert.AreEqual <uint>(TestSuiteBase.Success, openEmbeddedMessageResponse.ReturnValue, TestSuiteBase.ROPSucceedMsg);
            #endregion

            #region Call RopOpenEmbeddedMessage with OpenModeFlags set to 0x01 to open the embedded message which is created in step 9 and expect a failure response
            RopOpenEmbeddedMessageResponse openEmbeddedMessageResponseFirst;
            openEmbeddedMessageRequest.OpenModeFlags = 0x01; // Try to open the embedded message as read/write.
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(openEmbeddedMessageRequest, attachmentHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            openEmbeddedMessageResponseFirst = (RopOpenEmbeddedMessageResponse)this.response;
            #endregion

            #region Call RopSaveChangesMessage to save the embedded message created in step 9.
            saveChangesMessageResponse = this.SaveMessage(embeddedMessageHandle, (byte)SaveFlags.ForceSave);
            #endregion

            #region Call ReleaseRop to release the embedded message created in step 9.
            this.ReleaseRop(embeddedMessageHandle);
            #endregion

            #region Call RopOpenEmbeddedMessage with OpenModeFlags set to 0x01 to open the embedded message which is created in step 9 and expect a successful response.
            RopOpenEmbeddedMessageResponse openEmbeddedMessageResponseSecond;
            openEmbeddedMessageRequest.OpenModeFlags = 0x01; // Try to open the embedded message as read/write.
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(openEmbeddedMessageRequest, attachmentHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            openEmbeddedMessageResponseSecond = (RopOpenEmbeddedMessageResponse)this.response;
            #endregion

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMSG_R481. The return value of RopOpenEmbeddedMessage before calling RopSaveChangesMessage is {0}, the return value of RopOpenEmbeddedMessage after calling RopSaveChangesMessage is {1}.", openEmbeddedMessageResponseFirst.ReturnValue, openEmbeddedMessageResponseSecond.ReturnValue);

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R481
            bool isVerifiedR481 = openEmbeddedMessageResponseFirst.ReturnValue != TestSuiteBase.Success && openEmbeddedMessageResponseSecond.ReturnValue == TestSuiteBase.Success;

            // The server doesn't commit the Message object to the containing Attachment object until the RopSaveChangesMessage ROP is called if isVerifiedR481 is true, then MS-OXCMSG_R481 can be verified.
            this.Site.CaptureRequirementIfIsTrue(
                isVerifiedR481,
                481,
                @"[In Receiving a RopOpenEmbeddedMessage ROP Request] The server MUST NOT commit the Message object to the containing Attachment object until the RopSaveChangesMessage ROP ([MS-OXCROPS] section 2.2.6.3) is called with the Embedded Message object's handle.");

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

            // Set property size
            int size = 0;

            TaggedPropertyValue[] taggedPropertyValueArray = this.CreateMessageTaggedPropertyValueArrays(out size, PidTagAttachMethodFlags.afEmbeddedMessage);

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

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

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

            #region Call RopOpenMessage to open the message.
            RopOpenMessageResponse openMessageResponse;
            uint openedMessageHandle = this.OpenSpecificMessage(logonResponse.FolderIds[4], saveChangesMessageResponse.MessageId, this.insideObjHandle, MessageOpenModeFlags.ReadWrite, out openMessageResponse);
            Site.Assert.AreEqual <uint>(TestSuiteBase.Success, openMessageResponse.ReturnValue, TestSuiteBase.ROPSucceedMsg);
            #endregion

            #region Call RopCreateAttachment to create an embedded attachment.
            RopCreateAttachmentResponse createAttachmentResponse;
            uint attachmentId;
            uint attachmentHandle = this.CreateAttachment(openedMessageHandle, out createAttachmentResponse, out attachmentId);
            #endregion

            #region Call RopSetProperties to set PidTagAttachMethod property, that is the attachment is the embedded attachment.
            RopSetPropertiesRequest setPropertiesRequest = new RopSetPropertiesRequest()
            {
                RopId              = (byte)RopId.RopSetProperties,
                LogonId            = CommonLogonId,          // The logonId 0x00 is associated with RopSetProperties.
                InputHandleIndex   = CommonInputHandleIndex, // This index specifies the location 0x00 in the Server Object Handle Table where the handle for the input Server Object is stored.
                PropertyValueSize  = (ushort)(size + 2),
                PropertyValueCount = (ushort)taggedPropertyValueArray.Length,
                PropertyValues     = taggedPropertyValueArray
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(setPropertiesRequest, attachmentHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopSetPropertiesResponse setPropertiesResponse = (RopSetPropertiesResponse)this.response;
            Site.Assert.AreEqual <uint>(TestSuiteBase.Success, setPropertiesResponse.ReturnValue, TestSuiteBase.ROPSucceedMsg);
            #endregion

            #region Call RopSaveChangesAttachment to save the attachment changes.
            RopSaveChangesAttachmentResponse saveChangesAttachmentResponse;
            this.SaveAttachment(attachmentHandle, out saveChangesAttachmentResponse);
            #endregion

            #region Call RopOpenEmbeddedMessage with OpenModeFlags set to 0x02 to create the attachment if it doesn't exist, and expect to get a successful response
            RopOpenEmbeddedMessageRequest openEmbeddedMessageRequest = new RopOpenEmbeddedMessageRequest()
            {
                RopId             = (byte)RopId.RopOpenEmbeddedMessage,
                LogonId           = CommonLogonId,           // The logonId 0x00 is associated with RopOpenEmbeddedMessage.
                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
                OpenModeFlags     = 0x02                     // Create the attachment if it does not already exist and open the message for both reading and writing
            };
            this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(openEmbeddedMessageRequest, attachmentHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            RopOpenEmbeddedMessageResponse openEmbeddedMessageResponse = (RopOpenEmbeddedMessageResponse)this.response;
            Site.Assert.AreEqual <uint>(TestSuiteBase.Success, openEmbeddedMessageResponse.ReturnValue, TestSuiteBase.ROPSucceedMsg);
            uint embeddedMessageHandle = this.ResponseSOHs[0][openEmbeddedMessageResponse.OutputHandleIndex];
            #endregion

            #region Call RopRelease to release the embedded message
            this.ReleaseRop(embeddedMessageHandle);
            #endregion

            #region Call RopOpenEmbeddedMessage with CodePageId set to 0x000F and error code 0x000003ef is expected
            openEmbeddedMessageRequest.CodePageId = 0x000F;
            this.ResponseSOHs           = this.MSOXCMSGAdapter.DoRopCall(openEmbeddedMessageRequest, attachmentHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            openEmbeddedMessageResponse = (RopOpenEmbeddedMessageResponse)this.response;
            #endregion

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R1068
            this.Site.CaptureRequirementIfAreEqual <uint>(
                0x000003ef,
                openEmbeddedMessageResponse.ReturnValue,
                1068,
                @"[In Receiving a RopOpenEmbeddedMessage ROP Request] [ecUnknownCodePage (0x000003ef)] The code page is unknown.");

            #region Call RopOpenEmbeddedMessage with InputHandleIndex set to 0x01 to open the embedded message and expect to get the error code 0x000004B9 (ecNullObject).
            openEmbeddedMessageRequest.CodePageId       = 0x0FFF; // Code page of Logon object is used
            openEmbeddedMessageRequest.InputHandleIndex = 0x01;
            this.ResponseSOHs           = this.MSOXCMSGAdapter.DoRopCall(openEmbeddedMessageRequest, attachmentHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
            openEmbeddedMessageResponse = (RopOpenEmbeddedMessageResponse)this.response;
            #endregion

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R1525
            this.Site.CaptureRequirementIfAreEqual <uint>(
                0x000004B9,
                openEmbeddedMessageResponse.ReturnValue,
                1525,
                @"[In Receiving a RopOpenEmbeddedMessage ROP Request] [ecNullObject (0x000004B9)] The value of the InputHandleIndex field on which this ROP [RopOpenEmbeddedMessage] was called does not refer to an Attachment object.");

            #region Call RopRelease to release the embedded message.
            this.ReleaseRop(embeddedMessageHandle);
            this.ReleaseRop(targetMessageHandle);
            #endregion
        }