/// <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];
            }
        }
        /// <summary>
        /// Verify the property of HasNamedProperties 
        /// </summary>
        /// <param name="openMessageResponse"> The response of RopOpenMessage.</param>
        private void VerifyRopOpenMessageResponse(RopOpenMessageResponse openMessageResponse)
        {
            int hasNamedProperties = openMessageResponse.HasNamedProperties;

            bool isVerifyR672 = false;
            if (hasNamedProperties >= 0 && hasNamedProperties <= 0xFF)
            {
                isVerifyR672 = true;
            }

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R672
            Site.CaptureRequirementIfIsTrue(
                isVerifyR672,
                672,
                @"[In RopOpenMessage ROP Response Buffer] HasNamedProperties: 1 byte.");

            bool isVerifyR684 = false;
            if (openMessageResponse.RowCount <= openMessageResponse.RecipientCount)
            {
                isVerifyR684 = true;
            }

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R684
            Site.CaptureRequirementIfIsTrue(
                isVerifyR684,
                684,
                @"[In RopOpenMessage ROP Response Buffer] [RowCount] The value MUST be less than or equal to the RecipientCount field.");

            if (openMessageResponse.RecipientRows == null)
            {
                return;
            }

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R685
            this.Site.CaptureRequirementIfAreEqual<int>(
                (int)openMessageResponse.RowCount,
                openMessageResponse.RecipientRows.Length,
                685,
                @"[In RopOpenMessage ROP Response Buffer] RecipientRows: An array of OpenRecipientRow structures whose number is equal to the value of the RowCount field.");

            // All the reserved fields are set to 0x0000. Take the first recipient row as a sample to validate the format and capture the relevant requirements. 
            OpenRecipientRow openRecipientRow = openMessageResponse.RecipientRows[0];

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R686
            bool isVerifyR686 = ((openRecipientRow.RecipientType & 0x0F) == 0x00 ||
                   (openRecipientRow.RecipientType & 0x0F) == 0x01 ||
                   (openRecipientRow.RecipientType & 0x0F) == 0x02 ||
                   (openRecipientRow.RecipientType & 0x0F) == 0x03) &&
                   ((openRecipientRow.RecipientType & 0xF0) == 0x00
                   || ((openRecipientRow.RecipientType & 0xF0) | (0x10 | 0x80)) == (0x10 | 0x80));

            Site.CaptureRequirementIfIsTrue(
                isVerifyR686,
                686,
                @"[In RopOpenMessage ROP Response Buffer] [RecipientRows] The value of the RecipientType field specified in [MS-OXCROPS] section 2.2.6.1.2.1 is a bitwise OR of zero or one value [0x01, 0x02, 0x03] from the Types table with zero or more values [0x10, 0x80] from the flags table.");

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R680
            Site.CaptureRequirementIfAreEqual<int>(
                openMessageResponse.RecipientColumns.Length,
                openMessageResponse.ColumnCount,
                680,
                @"[In RopOpenMessage ROP Response Buffer] ColumnCount: A 2-BYTE unsigned integer containing the number of elements in the RecipientColumns field.");

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R681
            Site.CaptureRequirementIfAreEqual<int>(
                openMessageResponse.ColumnCount,
                openMessageResponse.RecipientColumns.Length,
                681,
                @"[In RopOpenMessage ROP Response Buffer] RecipientColumns: An array of PropertyTag structures ([MS-OXCDATA] section 2.9) with the number of elements specified in the ColumnCount field.");

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

            // Verify MS-OXCMSG requirement: MS-OXCMSG_R683
            this.Site.CaptureRequirementIfAreEqual<byte>(
                (byte)openMessageResponse.RecipientRows.Length,
                openMessageResponse.RowCount,
                683,
                @"[In RopOpenMessage ROP Response Buffer] RowCount: A 1-byte unsigned integer containing the number of rows in the RecipientRows field.");

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R489. The value of SubjectPrefix is {0}.", openMessageResponse.SubjectPrefix);

            // Verify MS-OXCDATA requirement: MS-OXCDATA_R489
            bool isVerifiedR489 = openMessageResponse.SubjectPrefix.StringType == 0x00
                || openMessageResponse.SubjectPrefix.StringType == 0x01
                || openMessageResponse.SubjectPrefix.StringType == 0x02
                || openMessageResponse.SubjectPrefix.StringType == 0x03
                || openMessageResponse.SubjectPrefix.StringType == 0x04;

            this.Site.CaptureRequirementIfIsTrue(
                isVerifiedR489,
                CdataShortName,
                489,
                @"[In TypedString Structure] StringType (1 byte): The value MUST be one of the following: [0x00, 0x01, 0x02, 0x03, 0x04].");

            if (openMessageResponse.SubjectPrefix.StringType == 0x00)
            {
                // Add the debug information
                this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R490. The value of SubjectPrefix is {0}.", openMessageResponse.SubjectPrefix);

                // Verify MS-OXCDATA requirement: MS-OXCDATA_R490
                this.Site.CaptureRequirementIfIsNull(
                    openMessageResponse.SubjectPrefix.String,
                    CdataShortName,
                    490,
                    @"[In TypedString Structure] StringType (1 byte): 0x00: No string is present.");

                // Add the debug information
                this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R499. The value of SubjectPrefix is {0}.", openMessageResponse.SubjectPrefix);

                // Verify MS-OXCDATA requirement: MS-OXCDATA_R499
                this.Site.CaptureRequirementIfIsNull(
                    openMessageResponse.SubjectPrefix.String,
                    CdataShortName,
                    499,
                    @"[In TypedString Structure] String (optional) (4 bytes): Otherwise [If the StringType field is not set to 0x02, 0x03, or 0x04] this field MUST NOT be present.");
            }
        }
        /// <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>
        /// Verify RopOpenMessage Failure Response
        /// </summary>
        /// <param name="ropOpenMessageResponse">The response of RopOpenMessage request</param>
        /// <param name="outputHandleIndex">The field of OutputHandleIndex in RopOpenMessage request</param>
        private void VerifyRopOpenMessageFailureResponse(RopOpenMessageResponse ropOpenMessageResponse, byte outputHandleIndex)
        {
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1736");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1736
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(byte),
                ropOpenMessageResponse.RopId.GetType(),
                1736,
                @"[In RopOpenMessage ROP Failure Response Buffer]RopId (1 byte): An unsigned integer.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1738
            Site.CaptureRequirementIfAreEqual<byte>(
                (byte)RopId.RopOpenMessage,
                ropOpenMessageResponse.RopId,
                1738,
                @"[In RopOpenMessage ROP Failure Response Buffer,RopId (1 byte)] For this[RopOpenMessage] operation, this field is set to 0x03.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1739
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(byte),
                ropOpenMessageResponse.OutputHandleIndex.GetType(),
                1739,
                @"[In RopOpenMessage ROP Failure Response Buffer]OutputHandleIndex (1 byte): An unsigned integer.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1740
            Site.CaptureRequirementIfAreEqual<byte>(
                outputHandleIndex,
                ropOpenMessageResponse.OutputHandleIndex,
                1740,
                @"[In RopOpenMessage ROP Failure Response Buffer,OutputHandleIndex (1 byte)]This index MUST be set to the value specified in the OutputHandleIndex field in the request.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1742
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(uint),
                ropOpenMessageResponse.ReturnValue.GetType(),
                1742,
                @"[In RopOpenMessage ROP Failure Response Buffer]ReturnValue (4 bytes): An unsigned integer.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1744
            Site.CaptureRequirementIfAreNotEqual<uint>(
                SuccessReturnValue,
                ropOpenMessageResponse.ReturnValue,
                1744,
                @"[In RopOpenMessage ROP Failure Response Buffer,ReturnValue (4 bytes)]For this[Failure Response] response, this field is set to a value other than 0x00000000.");
        }
        /// <summary>
        /// Verify RopOpenMessage Success Response
        /// </summary>
        /// <param name="ropOpenMessageResponse">The response of RopOpenMessage request</param>
        /// <param name="outputHandleIndex">The field of OutputHandleIndex in RopOpenMessage request</param>
        private void VerifyRopOpenMessageSuccessResponse(RopOpenMessageResponse ropOpenMessageResponse, byte outputHandleIndex)
        {
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1692");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1692
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(byte),
                ropOpenMessageResponse.RopId.GetType(),
                1692,
                @"[In RopOpenMessage ROP Success Response Buffer]RopId (1 byte): An unsigned integer.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1694
            Site.CaptureRequirementIfAreEqual<byte>(
                (byte)RopId.RopOpenMessage,
                ropOpenMessageResponse.RopId,
                1694,
                @"[In RopOpenMessage ROP Success Response Buffer,RopId (1 byte)]For this operation[RopOpenMessage], this field[RopId (1 byte)] is set to 0x03.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1695
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(byte),
                ropOpenMessageResponse.OutputHandleIndex.GetType(),
                1695,
                @"[In RopOpenMessage ROP Success Response Buffer]OutputHandleIndex (1 byte): An unsigned integer.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1696
            Site.CaptureRequirementIfAreEqual<byte>(
                outputHandleIndex,
                ropOpenMessageResponse.OutputHandleIndex,
                1696,
                @"[In RopOpenMessage ROP Success Response Buffer,OutputHandleIndex (1 byte)]This index MUST be set to the value specified in the OutputHandleIndex field in the request.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1698
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(uint),
                ropOpenMessageResponse.ReturnValue.GetType(),
                1698,
                @"[In RopOpenMessage ROP Success Response Buffer]ReturnValue (4 bytes): An unsigned integer.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1702
            Site.CaptureRequirementIfAreEqual<uint>(
                SuccessReturnValue,
                ropOpenMessageResponse.ReturnValue,
                1702,
                @"[In RopOpenMessage ROP Success Response Buffer,ReturnValue (4 bytes)]For this[Success Response Buffer] response, this field is set to 0x00000000.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1703,HasNamedProperties:{0}", ropOpenMessageResponse.HasNamedProperties);

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1703
            // If HasNamedProperties is byte type and can be boolean type representation, then verify R1703
            bool isVerifyR1703 = (typeof(byte) == ropOpenMessageResponse.HasNamedProperties.GetType()) &&
                                 ((Convert.ToBoolean(ropOpenMessageResponse.HasNamedProperties) == true) ||
                                 (Convert.ToBoolean(ropOpenMessageResponse.HasNamedProperties) == false));

            Site.CaptureRequirementIfIsTrue(
                isVerifyR1703,
                1703,
                @"[In RopOpenMessage ROP Success Response Buffer]HasNamedProperties (1 byte): A Boolean.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1705
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(TypedString),
                ropOpenMessageResponse.SubjectPrefix.GetType(),
                1705,
                @"[In RopOpenMessage ROP Success Response Buffer]SubjectPrefix (variable): A TypedString structure.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1708
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(TypedString),
                ropOpenMessageResponse.NormalizedSubject.GetType(),
                1708,
                @"[In RopOpenMessage ROP Success Response Buffer]NormalizedSubject (variable): TypedString structure.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1711
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(ushort),
                ropOpenMessageResponse.RecipientCount.GetType(),
                1711,
                @"[In RopOpenMessage ROP Success Response Buffer]RecipientCount (2 bytes): An unsigned integer.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1713
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(ushort),
                ropOpenMessageResponse.ColumnCount.GetType(),
                1713,
                @"[In RopOpenMessage ROP Success Response Buffer]ColumnCount (2 bytes): An unsigned integer.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1715
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(PropertyTag[]),
                ropOpenMessageResponse.RecipientColumns.GetType(),
                1715,
                @"[In RopOpenMessage ROP Success Response Buffer]RecipientColumns (variable): An array of PropertyTag structures.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1716
            Site.CaptureRequirementIfAreEqual<ushort>(
                ropOpenMessageResponse.ColumnCount,
                (ushort)ropOpenMessageResponse.RecipientColumns.Length,
                1716,
                @"[In RopOpenMessage ROP Success Response Buffer,RecipientColumns (variable)]The number of structures contained in this field[RecipientColumns (variable)] is specified by the ColumnCount field.");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1718
            // Assume the result is true. If RecipientColumns specifies property values don't be included in each row that is specified in the RecipientRows field, then false.
            // Check the number of property values in each row that is specified in the RecipientRows whether equal to the RecipientColumns count.
            bool isVerifyR1718 = true;
            foreach (OpenRecipientRow openRecipientRow in ropOpenMessageResponse.RecipientRows)
            {
                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1718, the actual count of PropertyValues is {0} and length of RecipientColumns is {1}", openRecipientRow.RecipientRow.RecipientProperties.PropertyValues.Count, ropOpenMessageResponse.RecipientColumns.Length);
                isVerifyR1718 = isVerifyR1703 &&
                                (openRecipientRow.RecipientRow.RecipientProperties.PropertyValues.Count == ropOpenMessageResponse.RecipientColumns.Length);

                // If one row of RecipientRows don't include property values that is specified in RecipientColumns then break iteration
                if (!isVerifyR1718)
                {
                    break;
                }
            }

            Site.CaptureRequirementIfIsTrue(
                isVerifyR1718,
                1718,
                @"[In RopOpenMessage ROP Success Response Buffer,RecipientColumns (variable)]This field specifies the property values that can be included in each row that is specified in the RecipientRows field.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1719
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(byte),
                ropOpenMessageResponse.RowCount.GetType(),
                1719,
                @"[In RopOpenMessage ROP Success Response Buffer]RowCount (1 byte): An unsigned integer.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1722
            Site.CaptureRequirementIfAreEqual<byte>(
                ropOpenMessageResponse.RowCount,
                (byte)ropOpenMessageResponse.RecipientRows.Length,
                1722,
                @"[In RopOpenMessage ROP Success Response Buffer,RecipientRows (variable)]The number of structures contained in this field is specified by the RowCount field.");

            // RecipientRows is array of OpenRecipientRow if it has element can get the first element as instance of OpenRecipientRow to verify OpenRecipientRow structure
            if (ropOpenMessageResponse.RecipientRows.Length > 0)
            {
                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1724");

                // Verify MS-OXCROPS requirement: MS-OXCROPS_R1724
                // RecipientRows is array of OpenRecipientRow, in the precondition statement RecipientRows has element.
                // Get the first element as instance of OpenRecipientRow to verify OpenRecipientRow structure
                Site.CaptureRequirementIfAreEqual<Type>(
                    typeof(byte),
                    ropOpenMessageResponse.RecipientRows[0].RecipientType.GetType(),
                    1724,
                    @"[In OpenRecipientRow structure]RecipientType (1 byte): An enumeration.");

                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1725,RecipientType:{0}", ropOpenMessageResponse.RecipientRows[0].RecipientType);

                // Verify MS-OXCROPS requirement: MS-OXCROPS_R1725
                // RecipientRows is array of OpenRecipientRow, in the precondition statement RecipientRows has element.
                // Get the first element as instance of OpenRecipientRow to verify OpenRecipientRow structure
                bool isVerifyR1725 = ((ropOpenMessageResponse.RecipientRows[0].RecipientType & ((byte)RecipientType.PrimaryRecipient)) == ((byte)RecipientType.PrimaryRecipient))
                                     || ((ropOpenMessageResponse.RecipientRows[0].RecipientType & ((byte)RecipientType.CcRecipient)) == ((byte)RecipientType.CcRecipient))
                                     || ((ropOpenMessageResponse.RecipientRows[0].RecipientType & ((byte)RecipientType.BccRecipient)) == ((byte)RecipientType.BccRecipient));

                Site.CaptureRequirementIfIsTrue(
                    isVerifyR1725,
                    1725,
                    @"[In OpenRecipientRow structure,RecipientType (1 byte)]The possible values[0x01, 0x02 and 0x03] for this enumeration are specified in [MS-OXCMSG] section 2.2.3.1.2.");

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

                // Verify MS-OXCROPS requirement: MS-OXCROPS_R1727
                // RecipientRows is array of OpenRecipientRow, in the precondition statement RecipientRows has element.
                // Get the first element as instance of OpenRecipientRow to verify OpenRecipientRow structure
                Site.CaptureRequirementIfAreEqual<int>(
                    2,
                    Marshal.SizeOf(ropOpenMessageResponse.RecipientRows[0].CodePageId),
                    1727,
                    @"[In OpenRecipientRow structure]CodePageId (2 bytes): An identifier.");

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

                // Verify MS-OXCROPS requirement: MS-OXCROPS_R1729
                // RecipientRows is array of OpenRecipientRow, in the precondition statement RecipientRows has element.
                // Get the first element as instance of OpenRecipientRow to verify OpenRecipientRow structure
                Site.CaptureRequirementIfAreEqual<int>(
                    2,
                    Marshal.SizeOf(ropOpenMessageResponse.RecipientRows[0].Reserved),
                    1729,
                    @"[In OpenRecipientRow structure]Reserved (2 bytes): Reserved.");

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

                // Verify MS-OXCROPS requirement: MS-OXCROPS_R1730
                // RecipientRows is array of OpenRecipientRow, in the precondition statement RecipientRows has element.
                // Get the first element as instance of OpenRecipientRow to verify OpenRecipientRow structure
                Site.CaptureRequirementIfAreEqual<ushort>(
                    ReservedTwoBytes,
                    ropOpenMessageResponse.RecipientRows[0].Reserved,
                    1730,
                    @"[In OpenRecipientRow structure,Reserved (2 bytes)]The server MUST set this field[Reserved (2 bytes)] to 0x0000.");

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

                // Verify MS-OXCROPS requirement: MS-OXCROPS_R1731
                // RecipientRows is array of OpenRecipientRow, in the precondition statement RecipientRows has element.
                // Get the first element as instance of OpenRecipientRow to verify OpenRecipientRow structure
                Site.CaptureRequirementIfAreEqual<Type>(
                    typeof(ushort),
                    ropOpenMessageResponse.RecipientRows[0].RecipientRowSize.GetType(),
                    1731,
                    @"[In OpenRecipientRow structure]RecipientRowSize (2 bytes): An unsigned integer.");

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

                // Verify MS-OXCROPS requirement: MS-OXCROPS_R1733
                // RecipientRows is array of OpenRecipientRow, in the precondition statement RecipientRows has element.
                // Get the first element as instance of OpenRecipientRow to verify OpenRecipientRow structure
                Site.CaptureRequirementIfAreEqual<Type>(
                    typeof(RecipientRow),
                    ropOpenMessageResponse.RecipientRows[0].RecipientRow.GetType(),
                    1733,
                    @"[In OpenRecipientRow structure]RecipientRow (variable): A RecipientRow structure.");

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

                // Verify MS-OXCROPS requirement: MS-OXCROPS_R1735
                // RecipientRows is array of OpenRecipientRow, in the precondition statement RecipientRows has element.
                // Get the first element as instance of OpenRecipientRow to verify OpenRecipientRow structure
                Site.CaptureRequirementIfAreEqual<ushort>(
                    ropOpenMessageResponse.RecipientRows[0].RecipientRowSize,
                    (ushort)ropOpenMessageResponse.RecipientRows[0].RecipientRow.Size(),
                    1735,
                    @"[In OpenRecipientRow structure,RecipientRow (variable)]The size of this field, in bytes, is specified by the RecipientRowSize field.");

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

                // Verify MS-OXCROPS requirement: MS-OXCROPS_R1721
                Site.CaptureRequirementIfAreEqual<Type>(
                    ropOpenMessageResponse.RecipientRows.GetType(),
                    typeof(OpenRecipientRow[]),
                    1721,
                    @"[In RopOpenMessage ROP Success Response Buffer]RecipientRows (variable): A List of OpenRecipientRow structures.");

                foreach (OpenRecipientRow openRecipientRow in ropOpenMessageResponse.RecipientRows)
                {
                    this.VerifyRecipientRowStructure(openRecipientRow.RecipientRow);
                }
            }
        }
        /// <summary>
        /// Compare the information of Message object from RopOpenMessageResponse and RopReloadCachedInformationResponse.
        /// </summary>
        /// <param name="openResp">The response of RopOpenMessage.</param>
        /// <param name="reloadResp">The response of RopReloadCachedInformation.</param>
        /// <returns>A Boolean indicates whether the information is same.</returns>
        private bool CompareResponseOfOpenMessageAndRopReloadCachedInformation(RopOpenMessageResponse openResp, RopReloadCachedInformationResponse reloadResp)
        {
            if (openResp.HasNamedProperties != reloadResp.HasNamedProperties)
            {
                return false;
            }

            if (!openResp.SubjectPrefix.Equals(reloadResp.SubjectPrefix))
            {
                return false;
            }

            if (!openResp.NormalizedSubject.Equals(reloadResp.NormalizedSubject))
            {
                return false;
            }

            if (!openResp.RecipientCount.Equals(reloadResp.RecipientCount))
            {
                return false;
            }

            if (!openResp.ColumnCount.Equals(reloadResp.ColumnCount))
            {
                return false;
            }

            if (!openResp.RowCount.Equals(reloadResp.RowCount))
            {
                return false;
            }

            if ((openResp.RecipientColumns == null && reloadResp.RecipientColumns != null) || (openResp.RecipientColumns != null && reloadResp.RecipientColumns == null))
            {
                return false;
            }

            if (openResp.RecipientColumns != null && reloadResp.RecipientColumns != null)
            {
                if (openResp.RecipientColumns.Length != reloadResp.RecipientColumns.Length)
                {
                    return false;
                }

                for (int i = 0; i < openResp.RecipientColumns.Length; i++)
                {
                    if (!openResp.RecipientColumns[i].Equals(reloadResp.RecipientColumns[i]))
                    {
                        return false;
                    }
                }
            }

            if ((openResp.RecipientRows == null && reloadResp.RecipientRows != null) || (openResp.RecipientRows != null && reloadResp.RecipientRows == null))
            {
                return false;
            }

            if (openResp.RecipientRows != null && reloadResp.RecipientRows != null)
            {
                if (openResp.RecipientRows.Length != reloadResp.RecipientRows.Length)
                {
                    return false;
                }

                for (int i = 0; i < openResp.RecipientRows.Length; i++)
                {
                    if (!openResp.RecipientRows[i].Equals(reloadResp.RecipientRows[i]))
                    {
                        return false;
                    }
                }
            }

            return true;
        }
        /// <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];
        }
        /// <summary>
        /// This ROP opens an existing message in a mailbox. 
        /// </summary>
        /// <param name="handle">Handle to operate.</param>
        /// <param name="folderId">64-bit identifier. This value identifies the parent folder of the message to be opened.</param>
        /// <param name="messageId">64-bit identifier. This value identifies the message to be opened.</param>
        /// <param name="openMessageResponse">Response of this ROP.</param>
        /// <returns>Handle of the open message.</returns>
        public uint RopOpenMessage(uint handle, ulong folderId, ulong messageId, out RopOpenMessageResponse openMessageResponse)
        {
            this.rawData = null;
            this.response = null;
            this.responseSOHs = null;

            RopOpenMessageRequest req;
            req.RopId = 0x03;
            req.LogonId = 0;
            req.InputHandleIndex = 0;
            req.OutputHandleIndex = 1;

            // Use the same codepage as logon object used
            req.CodePageId = 0x0fff;
            req.FolderId = folderId;

            // Read and write
            req.OpenModeFlags = 0x01;
            req.MessageId = messageId;

            this.responseSOHs = this.DoRPCCall(req, handle, ref this.response, ref this.rawData);
            openMessageResponse = (RopOpenMessageResponse)this.response;

            return this.responseSOHs[0][openMessageResponse.OutputHandleIndex];
        }