/// <summary>
        /// Deserialize the AndRestriction data.
        /// </summary>
        /// <param name="restrictionData">The restriction data.</param>
        public override void Deserialize(byte[] restrictionData)
        {
            int index = 0;
            this.RestrictType = (RestrictType)restrictionData[index];

            if (this.RestrictType != RestrictType.ContentRestriction)
            {
                throw new ArgumentException("The restrict type is not ContentRestriction type.");
            }

            index++;

            this.FuzzyLevelLow = (FuzzyLevelLowValues)BitConverter.ToInt16(restrictionData, index);
            index += 2;

            this.FuzzyLevelHigh = (FuzzyLevelHighValues)BitConverter.ToInt16(restrictionData, index);
            index += 2;

            index += this.PropertyTag.Deserialize(restrictionData, index);

            Context.Instance.PropertyBytes = restrictionData;
            Context.Instance.CurIndex = index;
            Context.Instance.CurProperty = new Property((PropertyType)this.PropertyTag.PropertyType);
            this.TaggedValue = new TaggedPropertyValue();
            this.TaggedValue.Parse(Context.Instance);
        }
        /// <summary>
        /// A method used to compose ROP command to execute ROP call.
        /// </summary>
        /// <param name="ropType">A parameter represents the ROP Type refers to a specific ROP call.</param>
        /// <param name="inputServerObjectHandle">A parameter represents an input Server object handle.</param>
        /// <param name="propertyValue">A parameter represents a TaggedPropertyValue structure.</param>
        /// <returns>A return value represents a byte array of serialized ROP command.</returns>
        public static byte[] ComposeRgbIn(ROPCommandType ropType, uint inputServerObjectHandle, TaggedPropertyValue propertyValue)
        {
            ComposeROPCommand composeROPCommand = new ComposeROPCommand();

            switch (ropType)
            {
                case ROPCommandType.RopSynchronizationImportDeletes:
                    return composeROPCommand.ComposeRopSynchronizationImportDeletes(inputServerObjectHandle, propertyValue);

                default:
                    throw new InvalidCastException("Invalid ROP command type");
            }
        }
        /// <summary>
        /// Get a TaggedPropertyValue structure from buffer.
        /// </summary>
        /// <param name="buffer">Buffer contain TaggedPropertyValue instance.</param>
        /// <returns>A TaggedPropertyvalue structure.</returns>
        public static TaggedPropertyValue ReadTaggedProperty(byte[] buffer)
        {
            TaggedPropertyValue tagValue = new TaggedPropertyValue();
            BufferReader bufferReader = new BufferReader(buffer);

            PropertyTag newPropertyTag = new PropertyTag
            {
                PropertyType = bufferReader.ReadUInt16(),
                PropertyId = bufferReader.ReadUInt16()
            };
            tagValue.PropertyTag = newPropertyTag;
            tagValue.Value = ReadValueByType(tagValue.PropertyTag.PropertyType, bufferReader.ReadToEnd());

            return tagValue;
        }
        /// <summary>
        /// Create sample RuleData array to modify the rules associated with a folder.
        /// </summary>
        /// <returns>Return RuleData array to be used in RopModifyRules request.</returns>
        protected RuleData[] CreateSampleRuleDataArrayForAdd()
        {
            int propertyValuesCount = 4;
            PropertyValue[] propertyValues = new PropertyValue[propertyValuesCount];

            for (int i = 0; i < propertyValuesCount; i++)
            {
                propertyValues[i] = new PropertyValue();
            }

            // As specified in section 2.2.1.3.2 in [MS-OXORULE],
            // when adding a PRULE, the client MUST NOT
            // pass in PidTagRuleId, it MUST pass in PidTagRuleCondition,
            // PidTagRuleActions and PidTagRuleProvider.
            TaggedPropertyValue taggedPropertyValue = new TaggedPropertyValue();
            PropertyTag tempPropertyTag = new PropertyTag
            {
                PropertyId = 0x6676, PropertyType = 0003
            };
            taggedPropertyValue.PropertyTag = tempPropertyTag;
            byte[] value3 = { 0x00, 0x00, 0x00, 0x0a };
            taggedPropertyValue.Value = value3;
            propertyValues[3].Value = taggedPropertyValue.Serialize();

            // PidTagRuleCondition
            taggedPropertyValue = new TaggedPropertyValue();
            tempPropertyTag.PropertyId = 0x6679;
            tempPropertyTag.PropertyType = 0x00fd;
            taggedPropertyValue.PropertyTag = tempPropertyTag;
            byte[] value =
            {
                0x03, 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x37, 0x00, 0x1f, 0x00,
                0x37, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6a, 0x00, 0x65,
                0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00, 0x58, 0x00, 0x00, 0x00
            };
            taggedPropertyValue.Value = value;
            propertyValues[1].Value = taggedPropertyValue.Serialize();

            // PidTagRuleAction
            taggedPropertyValue = new TaggedPropertyValue();
            tempPropertyTag.PropertyId = 0x6680;
            tempPropertyTag.PropertyType = 0x00fe;
            taggedPropertyValue.PropertyTag = tempPropertyTag;
            byte[] value1 = { 0x01, 0x00, 0x09, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
            taggedPropertyValue.Value = value1;
            propertyValues[2].Value = taggedPropertyValue.Serialize();

            // PidTagRuleProvider
            taggedPropertyValue = new TaggedPropertyValue();
            tempPropertyTag.PropertyId = 0x6681;
            tempPropertyTag.PropertyType = 0x001f;
            taggedPropertyValue.PropertyTag = tempPropertyTag;
            byte[] value2 = Encoding.Unicode.GetBytes("RuleOrganizer\0");
            taggedPropertyValue.Value = value2;
            propertyValues[0].Value = taggedPropertyValue.Serialize();

            RuleData sampleRuleData = new RuleData
            {
                RuleDataFlags = 0x01,
                PropertyValueCount = (ushort)propertyValues.Length,
                PropertyValues = propertyValues
            };

            RuleData[] sampleRuleDataArray = new RuleData[1];
            sampleRuleDataArray[0] = sampleRuleData;

            return sampleRuleDataArray;
        }
        public void MSOXCROPS_S11_TC05_TestRopSynchronizationImportDeletes()
        {
            this.CheckTransportIsSupported();

            this.cropsAdapter.RpcConnect(
                Common.GetConfigurationPropertyValue("SutComputerName", this.Site),
                ConnectionType.PrivateMailboxServer,
                Common.GetConfigurationPropertyValue("UserEssdn", this.Site),
                Common.GetConfigurationPropertyValue("Domain", this.Site),
                Common.GetConfigurationPropertyValue("AdminUserName", this.Site),
                Common.GetConfigurationPropertyValue("PassWord", this.Site));

            // Step 1: Open folder.
            #region Open folder

            // Log on to the private mailbox.
            RopLogonResponse logonResponse = Logon(LogonType.Mailbox, this.userDN, out inputObjHandle);

            RopOpenFolderRequest openFolderRequest;
            RopOpenFolderResponse openFolderResponse;

            // Construct the RopOpenFolder request.
            openFolderRequest.RopId = (byte)RopId.RopOpenFolder;
            
            openFolderRequest.LogonId = TestSuiteBase.LogonId;
            openFolderRequest.InputHandleIndex = TestSuiteBase.InputHandleIndex0;
            openFolderRequest.OutputHandleIndex = TestSuiteBase.OutputHandleIndex1;
            openFolderRequest.FolderId = logonResponse.FolderIds[4];
            openFolderRequest.OpenModeFlags = (byte)FolderOpenModeFlags.None;

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Step 1: Begin to send the RopOpenFolder request.");

            // Send the RopOpenFolder request and verify the success response.
            this.responseSOHs = cropsAdapter.ProcessSingleRop(
                openFolderRequest,
                this.inputObjHandle,
                ref this.response,
                ref this.rawData,
                RopResponseType.SuccessResponse);
            openFolderResponse = (RopOpenFolderResponse)response;
            Site.Assert.AreEqual<uint>(
                TestSuiteBase.SuccessReturnValue,
                openFolderResponse.ReturnValue,
                "If ROP succeeds, the ReturnValue of its response is 0 (success)");

            // Get the handle of opened folder, which will be used as input handle in RopCreateFolder.
            uint openedFolderHandle = responseSOHs[0][openFolderResponse.OutputHandleIndex];

            #endregion

            // Step 2: Configure a synchronization upload context.
            #region Configure a synchronization upload context

            RopSynchronizationOpenCollectorRequest synchronizationOpenCollectorRequest;
            RopSynchronizationOpenCollectorResponse synchronizationOpenCollectorResponse;

            // Construct the RopSynchronizationOpenCollector request.
            synchronizationOpenCollectorRequest.RopId = (byte)RopId.RopSynchronizationOpenCollector;
            synchronizationOpenCollectorRequest.LogonId = TestSuiteBase.LogonId;
            synchronizationOpenCollectorRequest.InputHandleIndex = TestSuiteBase.InputHandleIndex0;
            synchronizationOpenCollectorRequest.OutputHandleIndex = TestSuiteBase.OutputHandleIndex1;
            synchronizationOpenCollectorRequest.IsContentsCollector = Convert.ToByte(TestSuiteBase.Zero);

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Step 2: Begin to send the RopSynchronizationOpenCollector request.");

            // Send the RopSynchronizationOpenCollector request and verify the success response.
            this.responseSOHs = cropsAdapter.ProcessSingleRop(
                synchronizationOpenCollectorRequest,
                openedFolderHandle,
                ref this.response,
                ref this.rawData,
                RopResponseType.SuccessResponse);
            synchronizationOpenCollectorResponse = (RopSynchronizationOpenCollectorResponse)response;
            Site.Assert.AreEqual<uint>(
                TestSuiteBase.SuccessReturnValue,
                synchronizationOpenCollectorResponse.ReturnValue,
                "If ROP succeeds, the ReturnValue of its response is 0 (success)");
            uint synchronizationUploadContextHandle = responseSOHs[0][synchronizationOpenCollectorResponse.OutputHandleIndex];

            #endregion

            // Step 3: Create message.
            #region Create message

            RopCreateMessageRequest createMessageRequest = new RopCreateMessageRequest();
            RopCreateMessageResponse createMessageResponse;

            // Construct the RopCreateMessage request.
            createMessageRequest.RopId = (byte)RopId.RopCreateMessage;
            createMessageRequest.LogonId = TestSuiteBase.LogonId;
            createMessageRequest.InputHandleIndex = TestSuiteBase.InputHandleIndex0;
            createMessageRequest.OutputHandleIndex = TestSuiteBase.OutputHandleIndex1;

            // Set CodePageId to 0x0FFF, which specified the code page of Logon object will be used.
            createMessageRequest.CodePageId = TestSuiteBase.CodePageId;

            createMessageRequest.FolderId = logonResponse.FolderIds[4];
            createMessageRequest.AssociatedFlag = Convert.ToByte(TestSuiteBase.Zero);

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Step 3: Begin to send the RopCreateMessage request.");

            // Send the RopCreateMessage request and verify the success response.
            this.responseSOHs = cropsAdapter.ProcessSingleRop(
                createMessageRequest,
                this.inputObjHandle,
                ref this.response,
                ref this.rawData,
                RopResponseType.SuccessResponse);
            createMessageResponse = (RopCreateMessageResponse)response;
            Site.Assert.AreEqual<uint>(
                TestSuiteBase.SuccessReturnValue,
                createMessageResponse.ReturnValue,
                "if ROP succeeds, the ReturnValue of its response is 0(success)");
            uint targetMessageHandle = responseSOHs[0][createMessageResponse.OutputHandleIndex];

            #endregion

            // Step 4: Save message.
            #region Save message

            RopSaveChangesMessageRequest saveChangesMessageRequest;
            RopSaveChangesMessageResponse saveChangesMessageResponse;

            // Construct the RopSaveChangesMessage request.
            saveChangesMessageRequest.RopId = (byte)RopId.RopSaveChangesMessage;
            saveChangesMessageRequest.LogonId = TestSuiteBase.LogonId;
            saveChangesMessageRequest.InputHandleIndex = TestSuiteBase.InputHandleIndex0;
            saveChangesMessageRequest.ResponseHandleIndex = TestSuiteBase.ResponseHandleIndex1;
            saveChangesMessageRequest.SaveFlags = (byte)SaveFlags.ForceSave;

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Step 4: Begin to send the RopSaveChangesMessage request.");

            // Send the RopSaveChangesMessage request and verify the success response.
            this.responseSOHs = cropsAdapter.ProcessSingleRop(
                saveChangesMessageRequest,
                targetMessageHandle,
                ref this.response,
                ref this.rawData,
                RopResponseType.SuccessResponse);
            saveChangesMessageResponse = (RopSaveChangesMessageResponse)response;
            Site.Assert.AreEqual<uint>(
                TestSuiteBase.SuccessReturnValue,
                saveChangesMessageResponse.ReturnValue,
                "If ROP succeeds, the ReturnValue of its response is 0 (success).");

            #endregion

            // Send the RopSynchronizationImportDeletes request and verify the response.
            #region RopSynchronizationImportDeletes response

            RopSynchronizationImportDeletesRequest ropSynchronizationImportDeletesRequest = new RopSynchronizationImportDeletesRequest();
            TaggedPropertyValue[] propertyValues = new TaggedPropertyValue[1];
            TaggedPropertyValue propertyValue = new TaggedPropertyValue();

            // Send the RopLongTermIdFromId request to convert a short-term ID into a long-term ID.
            #region RopLongTermIdFromId response

            RopLongTermIdFromIdRequest ropLongTermIdFromIdRequest = new RopLongTermIdFromIdRequest();
            RopLongTermIdFromIdResponse ropLongTermIdFromIdResponse;

            // Construct the RopLongTermIdFromId request.
            ropLongTermIdFromIdRequest.RopId = (byte)RopId.RopLongTermIdFromId;
            ropLongTermIdFromIdRequest.LogonId = TestSuiteBase.LogonId;
            ropLongTermIdFromIdRequest.InputHandleIndex = TestSuiteBase.InputHandleIndex0;
            ropLongTermIdFromIdRequest.ObjectId = saveChangesMessageResponse.MessageId;

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Step 4: Begin to send the RopGetPropertyIdsFromNames request.");

            // Send the RopGetPropertyIdsFromNames request.
            this.responseSOHs = cropsAdapter.ProcessSingleRop(
                ropLongTermIdFromIdRequest,
                this.inputObjHandle,
                ref this.response,
                ref this.rawData,
                RopResponseType.SuccessResponse);
            ropLongTermIdFromIdResponse = (RopLongTermIdFromIdResponse)response;

            #endregion

            byte[] sampleValue = new byte[24];
            propertyValue.PropertyTag.PropertyId = this.propertyDictionary[PropertyNames.PidTagTemplateData].PropertyId;
            propertyValue.PropertyTag.PropertyType = this.propertyDictionary[PropertyNames.PidTagTemplateData].PropertyType;

            // The combination of first two bytes (0x0016) indicates the length of value field.
            sampleValue[0] = 0x16;
            sampleValue[1] = 0x00;
            Array.Copy(ropLongTermIdFromIdResponse.LongTermId.DatabaseGuid, 0, sampleValue, 2, 16);
            Array.Copy(ropLongTermIdFromIdResponse.LongTermId.GlobalCounter, 0, sampleValue, 18, 6);

            propertyValue.Value = sampleValue;
            propertyValues[0] = propertyValue;

            // Construct the RopSynchronizationImportDeletes request.
            ropSynchronizationImportDeletesRequest.RopId = (byte)RopId.RopSynchronizationImportDeletes;
            ropSynchronizationImportDeletesRequest.InputHandleIndex = TestSuiteBase.InputHandleIndex0;
            ropSynchronizationImportDeletesRequest.LogonId = TestSuiteBase.LogonId;
            ropSynchronizationImportDeletesRequest.IsHierarchy = Convert.ToByte(TestSuiteBase.Zero);
            ropSynchronizationImportDeletesRequest.PropertyValueCount = (ushort)propertyValues.Length;
            ropSynchronizationImportDeletesRequest.PropertyValues = propertyValues;

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Step 4: Begin to send the RopSynchronizationImportDeletes request to invoke success response.");

            // Send the RopSynchronizationImportDeletes request to get the success response.
            this.responseSOHs = cropsAdapter.ProcessSingleRop(
                ropSynchronizationImportDeletesRequest,
                synchronizationUploadContextHandle,
                ref this.response,
                ref this.rawData,
                RopResponseType.SuccessResponse);

            // Send the RopSynchronizationImportDeletes request to get the failure response.
            ropSynchronizationImportDeletesRequest.InputHandleIndex = TestSuiteBase.InputHandleIndex1;

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Step 4: Begin to send the RopSynchronizationImportDeletes request to invoke failure response.");

            this.responseSOHs = cropsAdapter.ProcessSingleRop(
                ropSynchronizationImportDeletesRequest,
                synchronizationUploadContextHandle,
                ref this.response,
                ref this.rawData,
                RopResponseType.FailureResponse);

            #endregion
        }
        /// <summary>
        /// Create hierarchy value samples.
        /// </summary>
        /// <param name="parentFolderId">Parent folder id.</param>
        /// <returns>The property values of hierarchy</returns>
        private TaggedPropertyValue[] CreateSampleHierarchyValues(ulong parentFolderId)
        {
            TaggedPropertyValue[] hierarchyValues = new TaggedPropertyValue[6];
            TaggedPropertyValue propertyValue = new TaggedPropertyValue();

            // PidTagParentSourceKey
            propertyValue = new TaggedPropertyValue
            {
                PropertyTag =
                {
                    PropertyId = this.propertyDictionary[PropertyNames.PidTagParentSourceKey].PropertyId,
                    PropertyType = this.propertyDictionary[PropertyNames.PidTagParentSourceKey].PropertyType
                }
            };

            // Send RopLongTermIdFromId request to convert a short-term ID into a long-term ID.
            #region RopLongTermIdFromId response

            RopLongTermIdFromIdRequest ropLongTermIdFromIdRequest = new RopLongTermIdFromIdRequest();
            RopLongTermIdFromIdResponse ropLongTermIdFromIdResponse;

            ropLongTermIdFromIdRequest.RopId = (byte)RopId.RopLongTermIdFromId;

            ropLongTermIdFromIdRequest.LogonId = TestSuiteBase.LogonId;
            ropLongTermIdFromIdRequest.InputHandleIndex = TestSuiteBase.InputHandleIndex0;
            ropLongTermIdFromIdRequest.ObjectId = parentFolderId;

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Begin to send the RopGetLocalReplicaIds request in CreateSampleHierarchyValues method.");

            // Send RopLongTermIdFromId request.
            this.responseSOHs = cropsAdapter.ProcessSingleRop(
                ropLongTermIdFromIdRequest,
                this.inputObjHandle,
                ref this.response,
                ref this.rawData,
                RopResponseType.SuccessResponse);

            ropLongTermIdFromIdResponse = (RopLongTermIdFromIdResponse)response;
            byte[] sampleForPidTagParentSourceKey = new byte[24];

            // The combination of first two bytes (0x0016) indicates the length of value field.
            sampleForPidTagParentSourceKey[0] = 0x16;
            sampleForPidTagParentSourceKey[1] = 0x00;

            Array.Copy(ropLongTermIdFromIdResponse.LongTermId.DatabaseGuid, 0, sampleForPidTagParentSourceKey, 2, 16);
            Array.Copy(ropLongTermIdFromIdResponse.LongTermId.GlobalCounter, 0, sampleForPidTagParentSourceKey, 18, 6);

            #endregion

            propertyValue.Value = sampleForPidTagParentSourceKey;
            hierarchyValues[0] = propertyValue;

            // PidTagSourceKey
            propertyValue = new TaggedPropertyValue
            {
                PropertyTag =
                {
                    PropertyId = this.propertyDictionary[PropertyNames.PidTagSourceKey].PropertyId,
                    PropertyType = this.propertyDictionary[PropertyNames.PidTagSourceKey].PropertyType
                }
            };
            byte[] sampleForPidTagSourceKey = new byte[24];

            // The combination of first two bytes (0x0016) indicates the length of value field.
            sampleForPidTagSourceKey[0] = 0x16;
            sampleForPidTagSourceKey[1] = 0x00;

            // Send the RopGetLocalReplicaIds request to reserve a range of IDs to be used by a local replica.
            #region RopGetLocalReplicaIds response

            RopGetLocalReplicaIdsRequest ropGetLocalReplicaIdsRequest;
            RopGetLocalReplicaIdsResponse ropGetLocalReplicaIdsResponse;

            ropGetLocalReplicaIdsRequest.IdCount = 1;
            ropGetLocalReplicaIdsRequest.InputHandleIndex = TestSuiteBase.InputHandleIndex0;
            ropGetLocalReplicaIdsRequest.LogonId = TestSuiteBase.LogonId;
            ropGetLocalReplicaIdsRequest.RopId = (byte)RopId.RopGetLocalReplicaIds;

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Begin to send the RopGetLocalReplicaIds request in CreateSampleHierarchyValues method.");

            // Send RopGetLocalReplicaIds request.
            this.responseSOHs = cropsAdapter.ProcessSingleRop(
                ropGetLocalReplicaIdsRequest,
                this.inputObjHandle,
                ref this.response,
                ref this.rawData,
                RopResponseType.SuccessResponse);
            ropGetLocalReplicaIdsResponse = (RopGetLocalReplicaIdsResponse)response;

            Array.Copy(ropGetLocalReplicaIdsResponse.ReplGuid, 0, sampleForPidTagSourceKey, 2, 16);
            Array.Copy(ropGetLocalReplicaIdsResponse.GlobalCount, 0, sampleForPidTagSourceKey, 18, 6);

            #endregion

            propertyValue.Value = sampleForPidTagSourceKey;
            hierarchyValues[1] = propertyValue;

            // PidTagLastModificationTime
            propertyValue = new TaggedPropertyValue
            {
                PropertyTag =
                {
                    PropertyId = this.propertyDictionary[PropertyNames.PidTagLastModificationTime].PropertyId,
                    PropertyType = this.propertyDictionary[PropertyNames.PidTagLastModificationTime].PropertyType
                }
            };
            byte[] sampleForPidTagLastModificationTime = { 154, 148, 234, 120, 114, 202, 202, 1 };
            propertyValue.Value = sampleForPidTagLastModificationTime;
            hierarchyValues[2] = propertyValue;

            // PidTagChangeKey
            propertyValue = new TaggedPropertyValue
            {
                PropertyTag =
                {
                    PropertyId = this.propertyDictionary[PropertyNames.PidTagChangeKey].PropertyId,
                    PropertyType = this.propertyDictionary[PropertyNames.PidTagChangeKey].PropertyType
                }
            };
            byte[] sampleForPidTagChangeKey = new byte[22];
            byte[] guid = Guid.NewGuid().ToByteArray();

            // The combination of first two bytes (0x0014) indicates the length of value field.
            sampleForPidTagChangeKey[0] = 0x14;
            sampleForPidTagChangeKey[1] = 0x00;

            Array.Copy(guid, 0, sampleForPidTagChangeKey, 2, 16);
            propertyValue.Value = sampleForPidTagChangeKey;
            hierarchyValues[3] = propertyValue;

            // PidTagPredecessorChangeList
            propertyValue = new TaggedPropertyValue
            {
                PropertyTag =
                {
                    PropertyId = this.propertyDictionary[PropertyNames.PidTagPredecessorChangeList].PropertyId,
                    PropertyType = this.propertyDictionary[PropertyNames.PidTagPredecessorChangeList].PropertyType
                }
            };
            byte[] sampleForPidTagPredecessorChangeList = 
            { 
                0x17, 0x00, 0x16, 0x19, 0xD7,
                0xFB, 0x0F, 0x06, 0x16, 0xA1,
                0x41, 0xBF, 0xF6, 0x91, 0xC7,
                0x63, 0xDA, 0xA8, 0x66, 0x00,
                0x00, 0x00, 0x78, 0x4D, 0x1C 
            };
            propertyValue.Value = sampleForPidTagPredecessorChangeList;
            hierarchyValues[4] = propertyValue;

            // PidTagDisplayName
            propertyValue = new TaggedPropertyValue
            {
                PropertyTag =
                {
                    PropertyId = this.propertyDictionary[PropertyNames.PidTagDisplayName].PropertyId,
                    PropertyType = this.propertyDictionary[PropertyNames.PidTagDisplayName].PropertyType
                }
            };

            byte[] sampleForPidTagDisplayName = new byte[Encoding.Unicode.GetByteCount(DisplayNameAndCommentForNonSearchFolder + "\0")];
            Array.Copy(
                Encoding.Unicode.GetBytes(TestSuiteBase.DisplayNameAndCommentForNonSearchFolder + "\0"),
                0,
                sampleForPidTagDisplayName,
                0,
                Encoding.Unicode.GetByteCount(TestSuiteBase.DisplayNameAndCommentForNonSearchFolder + "\0"));
            propertyValue.Value = sampleForPidTagDisplayName;
            hierarchyValues[5] = propertyValue;

            return hierarchyValues;
        }
        public void MSOXORULE_S01_TC05_ModifyOrDeleteRule()
        {
            this.CheckMAPIHTTPTransportSupported();

            #region Prepare value for ruleProperties variable.
            RuleProperties ruleProperties = AdapterHelper.GenerateRuleProperties(this.Site, Constants.RuleNameForward);
            #endregion

            #region TestUser1 prepares the recipient block for Forward rules.
            RecipientBlock recipientBlock = new RecipientBlock
            {
                Reserved = 0x01,
                NoOfProperties = (ushort)0x04u
            };

            TaggedPropertyValue[] recipientProperties = AdapterHelper.GenerateRecipientPropertiesBlock(this.User2Name, this.User2ESSDN);
            recipientBlock.PropertiesData = recipientProperties;
            #endregion

            #region TestUser1 adds rule forward.
            ForwardDelegateActionData forwardActionData = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01,
                RecipientsData = new RecipientBlock[1]
                {
                    recipientBlock
                }
            };

            RuleData ruleForward = AdapterHelper.GenerateValidRuleData(ActionType.OP_FORWARD, TestRuleDataType.ForAdd, 0, RuleState.ST_ENABLED, forwardActionData, ruleProperties, null);
            RopModifyRulesResponse modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleForward });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Adding Forward rule should be success");
            #endregion

            #region TestUser1 calls RopGetRulesTable with valid TableFlags.
            RopGetRulesTableResponse ropGetRulesTableResponse;
            uint ruleTableHandle = this.OxoruleAdapter.RopGetRulesTable(this.InboxFolderHandle, TableFlags.Normal, out ropGetRulesTableResponse);
            Site.Assert.AreEqual<uint>(0, ropGetRulesTableResponse.ReturnValue, "Getting rule table should succeed.");
            #endregion

            #region TestUser1 retrieves rule information for the newly added rule.
            PropertyTag[] propertyTags = new PropertyTag[2];
            propertyTags[0].PropertyId = (ushort)PropertyId.PidTagRuleName;
            propertyTags[0].PropertyType = (ushort)PropertyType.PtypString;
            propertyTags[1].PropertyId = (ushort)PropertyId.PidTagRuleId;
            propertyTags[1].PropertyType = (ushort)PropertyType.PtypInteger64;

            // Retrieve rows from the rule table.
            RopQueryRowsResponse queryRowResponse = this.OxoruleAdapter.QueryPropertiesInTable(ruleTableHandle, propertyTags);
            Site.Assert.AreEqual<uint>(0, queryRowResponse.ReturnValue, "Retrieving rows from the rule table should succeed.");
            
            // Add one rules to the Inbox folder. If the rule table is got successfully and the rule count is 1,
            // it means that the server is returning a table with the rule added by the test suite.
            Site.Assert.IsTrue(queryRowResponse.RowCount == 1, "The rule number in the rule table is {0}", queryRowResponse.RowCount);
            ulong ruleId = BitConverter.ToUInt64(queryRowResponse.RowData.PropertyRows[0].PropertyValues[1].Value, 0);
            this.VerifyRuleTable();

            #region   Capture R127
            bool isVerifiedR127 = Encoding.Unicode.GetString(queryRowResponse.RowData.PropertyRows[0].PropertyValues[0].Value).Equals(ruleProperties.Name + "\0");
  
            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R127");

            // Verify MS-OXORULE requirement: MS-OXORULE_R127
            this.Site.CaptureRequirementIfIsTrue(
                isVerifiedR127,
                127,
                @"[In RopGetRulesTable ROP Request Buffer] [TableFlags] U: (Bitmask 0x40): This bit is set if the client is requesting that string values in the table be returned as Unicode strings.");

            #endregion
            #endregion

            #region TestUser1 prepares the recipient block for Forward rules.
            recipientBlock = new RecipientBlock
            {
                Reserved = 0x01,
                NoOfProperties = (ushort)0x04u
            };

            recipientProperties = AdapterHelper.GenerateRecipientPropertiesBlock(this.User1Name, this.User1ESSDN);
            recipientBlock.PropertiesData = recipientProperties;
            #endregion

            #region TestUser1 modifies the created rule.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameForward);
            forwardActionData = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01,
                RecipientsData = new RecipientBlock[1]
                {
                    recipientBlock
                }
            };

            ruleForward = AdapterHelper.GenerateValidRuleData(ActionType.OP_FORWARD, TestRuleDataType.ForModify, 0, RuleState.ST_ENABLED, forwardActionData, ruleProperties, ruleId);
            modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_OnExisting, new RuleData[] { ruleForward });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Adding Forward rule should be success");
            #endregion

            #region TestUser1 calls RopGetRulesTable with valid TableFlags.
            ruleTableHandle = this.OxoruleAdapter.RopGetRulesTable(this.InboxFolderHandle, TableFlags.Normal, out ropGetRulesTableResponse);
            Site.Assert.AreEqual<uint>(0, ropGetRulesTableResponse.ReturnValue, "Getting rule table should succeed.");
            #endregion

            #region TestUser1 retrieves rule information for the modified rule.
            // Retrieves rows from the rule table.
            queryRowResponse = this.OxoruleAdapter.QueryPropertiesInTable(ruleTableHandle, propertyTags);
            Site.Assert.AreEqual<uint>(0, queryRowResponse.ReturnValue, "Retrieving rows from the rule table should succeed.");

            // Only one rule added in the Inbox folder. If the rule table is got successfully and the rule count is 1,
            // it means that the server is returning a table with the rule added by the test suite.
            Site.Assert.AreEqual<uint>(1, queryRowResponse.RowCount, "The rule number in the rule table is {0}", queryRowResponse.RowCount);
            this.VerifyRuleTable();
            
            ulong ruleIdModified = BitConverter.ToUInt64(queryRowResponse.RowData.PropertyRows[0].PropertyValues[1].Value, 0);
            bool isSameRuleId = ruleId == ruleIdModified;
            Site.Assert.IsTrue(isSameRuleId, "The original rule Id is {0} and the modified rule Id is {1}", ruleId, ruleIdModified);

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

            bool isVerifiedR671 = isSameRuleId && queryRowResponse.RowCount == 1;

            // Verify MS-OXORULE requirement: MS-OXORULE_R671.
            Site.CaptureRequirementIfIsTrue(
                isVerifiedR671,
                671,
                @"[In RopModifyRules ROP Request Buffer] [ModifyRulesFlag] R (Bitmask 0x01): If this bit is not set, the rules (2) specified in this request represent changes (delete, modify, and add) to the set of rules (2) already existing in this folder.");

            #endregion

            #region TestUser1 adds rule DELEGATE.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameDelegate, 1);
            ForwardDelegateActionData delegateActionData = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01
            };

            #region Prepare the Delegate rule Recipient block
            RecipientBlock delegateRecipientBlock = new RecipientBlock
            {
                Reserved = 0x01,
                NoOfProperties = (ushort)0x05u
            };
            TaggedPropertyValue[] delegateRecipientProperties = new TaggedPropertyValue[5];

            TaggedPropertyValue[] tempArray = AdapterHelper.GenerateRecipientPropertiesBlock(this.User2Name, this.User2ESSDN);
            Array.Copy(tempArray, 0, delegateRecipientProperties, 0, tempArray.Length);

            // Add PidTagSmtpEmailAdderss.
            delegateRecipientProperties[4] = new TaggedPropertyValue();
            PropertyTag delegateRecipientPropertiesPropertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagSmtpAddress,
                PropertyType = (ushort)PropertyType.PtypString
            };
            delegateRecipientProperties[4].PropertyTag = delegateRecipientPropertiesPropertyTag;
            delegateRecipientProperties[4].Value = Encoding.Unicode.GetBytes(this.User2Name + "@" + this.Domain + "\0");

            delegateRecipientBlock.PropertiesData = delegateRecipientProperties;
            #endregion

            delegateActionData.RecipientsData = new RecipientBlock[1] { delegateRecipientBlock };
            RuleData ruleDelegate = AdapterHelper.GenerateValidRuleData(ActionType.OP_DELEGATE, TestRuleDataType.ForAdd, 1, RuleState.ST_ENABLED, delegateActionData, ruleProperties, null);
            modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_OnExisting, new RuleData[] { ruleDelegate });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Adding Delegate rule should succeed.");
            #endregion

            #region TestUser1 calls RopGetRulesTable with valid TableFlags.
            ruleTableHandle = this.OxoruleAdapter.RopGetRulesTable(this.InboxFolderHandle, TableFlags.Normal, out ropGetRulesTableResponse);
            Site.Assert.AreEqual<uint>(0, ropGetRulesTableResponse.ReturnValue, "Getting rule table should succeed.");
            #endregion

            #region TestUser1 retrieves rule information to check if two rules exist.
            // Retrieves rows from the rule table.
            queryRowResponse = this.OxoruleAdapter.QueryPropertiesInTable(ruleTableHandle, propertyTags);
            Site.Assert.AreEqual<uint>(0, queryRowResponse.ReturnValue, "Retrieving rows from the rule table should succeed.");

            // Two rules have been added to the Inbox folder, so the row count in the rule table should be 2.
            Site.Assert.AreEqual<uint>(2, queryRowResponse.RowCount, "The rule number in the rule table  should be 2.");
            bool twoRulesExistBeforeReplaceAll = queryRowResponse.RowCount == 2;
            this.VerifyRuleTable();

            #endregion

            #region TestUser1 adds another rule to replace all the existing rules.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameDelegate, 2);
            delegateActionData = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01
            };

            #region Prepare the Delegate rule Recipient block
            delegateRecipientBlock = new RecipientBlock
            {
                Reserved = 0x01,
                NoOfProperties = (ushort)0x05u
            };
            delegateRecipientProperties = new TaggedPropertyValue[5];

            tempArray = AdapterHelper.GenerateRecipientPropertiesBlock(this.User2Name, this.User2ESSDN);
            Array.Copy(tempArray, 0, delegateRecipientProperties, 0, tempArray.Length);

            // Add PidTagSmtpEmailAdderss
            delegateRecipientProperties[4] = new TaggedPropertyValue();
            delegateRecipientPropertiesPropertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagSmtpAddress,
                PropertyType = (ushort)PropertyType.PtypString
            };
            delegateRecipientProperties[4].PropertyTag = delegateRecipientPropertiesPropertyTag;
            delegateRecipientProperties[4].Value = Encoding.Unicode.GetBytes(this.User2Name + "@" + this.Domain + "\0");

            delegateRecipientBlock.PropertiesData = delegateRecipientProperties;
            #endregion

            delegateActionData.RecipientsData = new RecipientBlock[1] { delegateRecipientBlock };
            ruleDelegate = AdapterHelper.GenerateValidRuleData(ActionType.OP_DELEGATE, TestRuleDataType.ForAdd, 0, RuleState.ST_ENABLED, delegateActionData, ruleProperties, null);
            modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleDelegate });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Adding Delegate rule should succeed.");
            #endregion

            #region TestUser1 calls RopGetRulesTable with valid TableFlags.
            ruleTableHandle = this.OxoruleAdapter.RopGetRulesTable(this.InboxFolderHandle, TableFlags.Normal, out ropGetRulesTableResponse);
            Site.Assert.AreEqual<uint>(0, ropGetRulesTableResponse.ReturnValue, "Getting rule table should succeed.");
            #endregion

            #region TestUser1 retrieves rule information to check if the existing rules are replaced.
            // Retrieves rows from the rule table.
            queryRowResponse = this.OxoruleAdapter.QueryPropertiesInTable(ruleTableHandle, propertyTags);
            Site.Assert.AreEqual<uint>(0, queryRowResponse.ReturnValue, "Retrieving rows from the rule table should succeed.");

            // Only one rule exist on Inbox folder, so the row count in the rule table should be 1.
            Site.Assert.AreEqual<uint>((uint)1, queryRowResponse.RowCount, "The rule number in the rule table is {0}", queryRowResponse.RowCount);
            this.VerifyRuleTable();

            // Only one rule exist on Inbox folder, means other rules have been replaced.
            bool oneRuleExistsAfterReplaceAll = queryRowResponse.RowCount == 1;
            ruleId = BitConverter.ToUInt64(queryRowResponse.RowData.PropertyRows[0].PropertyValues[1].Value, 0);

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R669: the row count of rule table before replace is {0}, and after replace is {1}", twoRulesExistBeforeReplaceAll, oneRuleExistsAfterReplaceAll);

            // Verify MS-OXORULE requirement: MS-OXORULE_R669
            bool isVerifiedR669 = twoRulesExistBeforeReplaceAll && oneRuleExistsAfterReplaceAll;

            Site.CaptureRequirementIfIsTrue(
                isVerifiedR669,
                669,
                @"[In RopModifyRules ROP Request Buffer] [ModifyRulesFlag] R (Bitmask 0x01): If this bit is set, the rules (2) in this request are to replace the existing set of rules (2) in the folder.");
            #endregion

            #region TestUser1 deletes the last created rule.
            ruleDelegate = AdapterHelper.GenerateValidRuleData(ActionType.OP_DELEGATE, TestRuleDataType.ForRemove, 0, RuleState.ST_ENABLED, delegateActionData, ruleProperties, ruleId);
            modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_OnExisting, new RuleData[] { ruleDelegate });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Deleting the created rule should be success");
            #endregion

            #region TestUser1 calls RopGetRulesTable with valid TableFlags.
            ruleTableHandle = this.OxoruleAdapter.RopGetRulesTable(this.InboxFolderHandle, TableFlags.Normal, out ropGetRulesTableResponse);
            Site.Assert.AreEqual<uint>(0, ropGetRulesTableResponse.ReturnValue, "Getting rule table should succeed.");
            #endregion

            #region TestUser1 retrieves rule information to check if the last created rule is deleted.
            // Retrieves rows from the rule table.
            queryRowResponse = this.OxoruleAdapter.QueryPropertiesInTable(ruleTableHandle, propertyTags);
            Site.Assert.AreEqual<uint>(0, queryRowResponse.ReturnValue, "Retrieving rows from the rule table should succeed.");

            // Get rule table succeed and the rule count is 0, means the server is returning a table with no rule.
            Site.Assert.IsTrue(queryRowResponse.RowCount == 0, "The rule number in the rule table is {0}", queryRowResponse.RowCount);

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

            // Verify MS-OXORULE requirement: MS-OXORULE_R14.
            // According to above steps, this requirement can be captured directly.
            this.Site.CaptureRequirement(
                14,
                @"[In RopModifyRules ROP] The RopModifyRules ROP ([MS-OXCROPS] section 2.2.11.1) creates, modifies, or deletes rules (2) in a folder.");
            #endregion
        }
        public void MSOXORULE_S01_TC03_AddExtendedRule_WithLargeMessageCondition()
        {
            this.CheckMAPIHTTPTransportSupported();

            #region TestUser1 creates an FAI message.
            RopCreateMessageResponse ropCreateMessageResponse;
            uint extendedRuleMessageHandle = this.OxoruleAdapter.RopCreateMessage(this.InboxFolderHandle, this.InboxFolderID, Convert.ToByte(true), out ropCreateMessageResponse);
            Site.Assert.AreEqual<uint>(0, ropCreateMessageResponse.ReturnValue, "Creating the first FAI message should succeed.");
            #endregion

            #region TestUser1 adds the extended rule with NamedProperty successfully.
            string ruleConditionSubjectName = Constants.RuleConditionSubjectContainString;
            NamedPropertyInfo namedPropertyInfo = new NamedPropertyInfo
            {
                NoOfNamedProps = 2,
                PropId = new uint[2]
                {
                    0x8001, 0x8002
                }
            };

            // 0x01 means the property is identified by the name property.
            PropertyName testPropertyName = new PropertyName
            {
                Guid = System.Guid.NewGuid().ToByteArray(),
                Kind = 0x01,
                Name = Encoding.Unicode.GetBytes(Constants.NameOfPropertyName + "\0")
            };
            testPropertyName.NameSize = (byte)testPropertyName.Name.Length;

            // 0x00 means the property is identified by the LID.
            PropertyName secondPropertyName = new PropertyName
            {
                Guid = System.Guid.NewGuid().ToByteArray(),
                Kind = 0x00,
                LID = 0x88888888
            };
            namedPropertyInfo.NamedProperty = new PropertyName[2] { testPropertyName, secondPropertyName };
            namedPropertyInfo.NamedPropertiesSize = (uint)(testPropertyName.Serialize().Length + secondPropertyName.Serialize().Length);
            string ruleName = Common.GenerateResourceName(this.Site, Constants.ExtendRulename1);
            TaggedPropertyValue[] extendedRuleProperties = AdapterHelper.GenerateExtendedRuleTestData(ruleName, 0, (uint)RuleState.ST_ENABLED, Constants.PidTagRuleProvider, ActionType.OP_MARK_AS_READ, new DeleteMarkReadActionData(), ruleConditionSubjectName, namedPropertyInfo);

            // Set properties for extended rule FAI message.
            RopSetPropertiesResponse ropSetPropertiesResponse = this.OxoruleAdapter.RopSetProperties(extendedRuleMessageHandle, extendedRuleProperties);
            Site.Assert.AreEqual<uint>(0, ropSetPropertiesResponse.ReturnValue, "Setting property for Extended rule FAI message should succeed.");

            // Save changes of message.
            RopSaveChangesMessageResponse ropSaveChangesMessagResponse = this.OxoruleAdapter.RopSaveChangesMessage(extendedRuleMessageHandle);
            Site.Assert.AreEqual<uint>(0, ropSaveChangesMessagResponse.ReturnValue, "Saving Extend rule message should succeed.");

            // Specify the properties to be got. 
            PropertyTag[] propertyTagArray = new PropertyTag[2];

            // PidTagRuleMessageProviderData
            propertyTagArray[0].PropertyId = (ushort)PropertyId.PidTagRuleMessageProvider;
            propertyTagArray[0].PropertyType = (ushort)PropertyType.PtypString;

            // PidTagRuleMessageName
            propertyTagArray[1].PropertyId = (ushort)PropertyId.PidTagRuleMessageName;
            propertyTagArray[1].PropertyType = (ushort)PropertyType.PtypString;

            // Get the specific properties of the extended rule.
            RopGetPropertiesSpecificResponse ropGetPropertiesSpecificResponse = this.OxoruleAdapter.RopGetPropertiesSpecific(extendedRuleMessageHandle, propertyTagArray);
            Site.Assert.AreEqual<uint>(0, ropGetPropertiesSpecificResponse.ReturnValue, "Getting folder id property operation should succeed.");

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

            // Verify MS-OXORULE requirement: MS-OXORULE_R184
            string pidTagRuleMessageProviderData = AdapterHelper.PropertyValueConvertToString(ropGetPropertiesSpecificResponse.RowData.PropertyValues[0].Value);
            Site.CaptureRequirementIfAreEqual<string>(
                Constants.PidTagRuleProvider,
                pidTagRuleMessageProviderData,
                184,
                @"[In PidTagRuleMessageProvider Property] This property has the same semantics as the PidTagRuleProvider property (section 2.2.1.3.1.5). [The PidTagRuleMessageProvider property identifies the client application that owns the rule (2).]");

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

            // Verify MS-OXORULE requirement: MS-OXORULE_R164
            // The rule name set by client is "ExtendRulename1".
            string pidTagRuleMessageNameValue = AdapterHelper.PropertyValueConvertToString(ropGetPropertiesSpecificResponse.RowData.PropertyValues[1].Value);
            Site.CaptureRequirementIfAreEqual<string>(
                 ruleName,
                 pidTagRuleMessageNameValue,
                 164,
                 @"[In PidTagRuleMessageName Property] This property has the same semantics as the PidTagRuleName property (section 2.2.1.3.1.4). [The PidTagRuleMessageName property specifies the name of the rule (2).]");
            #endregion
            #endregion

            #region TestUser1 retrieves data of the new extended rule.
            this.OxoruleAdapter.TargetOfRop = TargetOfRop.ForExtendedRules;
            RopGetPropertiesAllResponse ropGetExtendRuleMessageResponse = this.OxoruleAdapter.RopGetPropertiesAll(extendedRuleMessageHandle, this.PropertySizeLimitFlag, (ushort)WantUnicode.Want);
            Site.Assert.AreEqual<uint>(0, ropGetExtendRuleMessageResponse.ReturnValue, "Getting all properties operation should succeed.");
            Site.Assert.IsTrue(ropGetExtendRuleMessageResponse.PropertyValues.Length != 0, "Extended Rule data should be found in related FAI message!");
            this.OxoruleAdapter.TargetOfRop = TargetOfRop.OtherTarget;

            ExtendedRuleActions extendedRuleMessageActions = null;

            // Check the properties set on Extended Rule, and find the Extended Rule Actions.
            for (int i = 0; i < ropGetExtendRuleMessageResponse.PropertyValues.Length; i++)
            {
                // propertyId indicates the Id of a property set on Extended Rule.
                ushort propertyId = ropGetExtendRuleMessageResponse.PropertyValues[i].PropertyTag.PropertyId;
                if (propertyId == (ushort)PropertyId.PidTagExtendedRuleMessageActions)
                {
                    byte[] propertyValue = ropGetExtendRuleMessageResponse.PropertyValues[i].Value;
                    extendedRuleMessageActions = AdapterHelper.PropertyValueConvertToExtendedRuleActions(propertyValue);
                    break;
                }
            }

            Site.Assert.AreNotEqual<ExtendedRuleActions>(null, extendedRuleMessageActions, "extendedRuleMessageActions should not be null.");

            // Get the Property Names saved by server in the extendedRuleMessageActions.
            PropertyName[] propertyNames = extendedRuleMessageActions.NamedPropertyInformation.NamedProperty;
            PropertyName testPropertyNameSavedOnServer = new PropertyName();
            PropertyName secondPropertyNameSavedOnServer = new PropertyName();
            if (propertyNames != null && propertyNames.Length > 0)
            {
                for (int i = 0; i < propertyNames.Length; i++)
                {
                    // If the Kind is 0x01, it means this PropertyName is the testPropertyName.
                    if (propertyNames[i].Kind == 0x01)
                    {
                        testPropertyNameSavedOnServer = propertyNames[i];
                    }
                    else if (propertyNames[i].Kind == 0x00)
                    {
                        // If the Kind is 0x00, it means this PropertyName is the secondPropertyName.
                        secondPropertyNameSavedOnServer = propertyNames[i];
                    }
                }
            }

            Site.Assert.IsNotNull(testPropertyNameSavedOnServer.Guid, "testPropertyNameSavedOnServer should not be null.");
            Site.Assert.IsNotNull(secondPropertyNameSavedOnServer.Guid, "secondPropertyNameSavedOnServer should not be null.");
            #endregion

            #region TestUser1 creates a new FAI message.
            extendedRuleMessageHandle = this.OxoruleAdapter.RopCreateMessage(this.InboxFolderHandle, this.InboxFolderID, Convert.ToByte(true), out ropCreateMessageResponse);
            Site.Assert.AreEqual<uint>(0, ropCreateMessageResponse.ReturnValue, "Creating the second FAI message should succeed.");
            #endregion

            #region TestUser1 creates an extended rule with PidTagExtendedRuleMessageCondition property value size larger than the size set by the server.
            propertyTagArray = new PropertyTag[1];
            propertyTagArray[0].PropertyId = (ushort)PropertyId.PidTagExtendedRuleSizeLimit;
            propertyTagArray[0].PropertyType = (ushort)PropertyType.PtypInteger32;

            ropGetPropertiesSpecificResponse = this.OxoruleAdapter.RopGetPropertiesSpecific(this.LogonHandle, propertyTagArray);
            uint pidTagExtendedRuleSizeLimit = Common.ConvertByteArrayToUint(ropGetPropertiesSpecificResponse.RowData.PropertyValues[0].Value);
            
            // According to MS-OXCRPC, "The server SHOULD fail with the RPC status code of RPC_X_BAD_STUB_DATA (0x000006F7) if the request buffer is larger than 0x00040000 bytes in size."
            if (pidTagExtendedRuleSizeLimit < 0x00040000)
            {
                ruleConditionSubjectName = Constants.RuleConditionSubjectContainString;
                namedPropertyInfo = new NamedPropertyInfo
                {
                    NoOfNamedProps = 2,
                    PropId = new uint[2]
                    {
                        0x8001, 0x8002
                    }
                };

                // Generate a string value whose size lager than the one specified by the PidTagExtendedRuleSizeLimit property.
                StringBuilder stringByteValue = new StringBuilder("ExtentRuleSize");
                stringByteValue.Append('a', (int)pidTagExtendedRuleSizeLimit);

                // If the value of Kind is 0x01, it means that the property is identified by the name property.
                testPropertyName = new PropertyName
                {
                    Guid = System.Guid.NewGuid().ToByteArray(),
                    Kind = 0x01,
                    Name = Encoding.Unicode.GetBytes(stringByteValue + "\0")
                };

                testPropertyName.NameSize = (byte)testPropertyName.Name.Length;

                // If the value of Kind is 0x00, it means that the property is identified by the LID.
                secondPropertyName = new PropertyName
                {
                    Guid = System.Guid.NewGuid().ToByteArray(),
                    Kind = 0x00,
                    LID = 0x88888888
                };

                namedPropertyInfo.NamedProperty = new PropertyName[2] { testPropertyName, secondPropertyName };
                namedPropertyInfo.NamedPropertiesSize = (uint)(testPropertyName.Serialize().Length + secondPropertyName.Serialize().Length);
                extendedRuleProperties = AdapterHelper.GenerateExtendedRuleTestData(Common.GenerateResourceName(this.Site, Constants.ExtendRulename1), 0, (uint)RuleState.ST_ENABLED, Constants.PidTagRuleProvider, ActionType.OP_MARK_AS_READ, new DeleteMarkReadActionData(), ruleConditionSubjectName, namedPropertyInfo);
                TaggedPropertyValue pidTagExtendedRuleMessageCondition = new TaggedPropertyValue();
                foreach (TaggedPropertyValue propertyValue in extendedRuleProperties)
                {
                    if (propertyValue.PropertyTag.PropertyId == (ushort)PropertyId.PidTagExtendedRuleMessageCondition)
                    {
                        pidTagExtendedRuleMessageCondition = propertyValue;
                        break;
                    }
                }

                uint pidTagExtendedRuleMessageConditionSize = uint.Parse(pidTagExtendedRuleMessageCondition.Value.Length.ToString());

                // Set properties for extended rule FAI message.
                ropSetPropertiesResponse = this.OxoruleAdapter.RopSetProperties(extendedRuleMessageHandle, extendedRuleProperties);

                // Save changes of message.
                ropSaveChangesMessagResponse = this.OxoruleAdapter.RopSaveChangesMessage(extendedRuleMessageHandle);

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

                // Verify MS-OXORULE requirement: MS-OXORULE_R1016.
                if (pidTagExtendedRuleMessageConditionSize > pidTagExtendedRuleSizeLimit)
                {
                    Site.CaptureRequirementIfAreNotEqual<uint>(
                        0x0000,
                        ropSaveChangesMessagResponse.ReturnValue,
                        1016,
                        @"[In Processing Incoming Messages to a Folder] If the PidTagExtendedRuleSizeLimit property is set and the size of the PidTagExtendedRuleMessageCondition property (section 2.2.4.1.10) exceeds the value specified by the PidTagExtendedRuleSizeLimit property, the server MUST return an error.");
                }
                else
                {
                    Site.Assert.Fail("The size of the PidTagExtendedRuleMessageCondition property should exceeds the value specified by the PidTagExtendedRuleSizeLimit property.");
                }
            }
            #endregion
        }
        public void MSOXORULE_S01_TC11_AddExtendedRule_OP_OOF_REPLY()
        {
            this.CheckMAPIHTTPTransportSupported();

            #region Prepare value for ruleProperties variable
            RuleProperties ruleProperties = AdapterHelper.GenerateRuleProperties(this.Site, Constants.RuleNameOOFReply);
            #endregion

            #region Create a reply template in the TestUser1's Inbox folder.
            ulong replyTemplateMessageId;
            uint replyTemplateMessageHandler;
            string replyTemplateSubject = Common.GenerateResourceName(this.Site, Constants.ReplyTemplateSubject);

            TaggedPropertyValue[] replyTemplateProperties = new TaggedPropertyValue[1];
            replyTemplateProperties[0] = new TaggedPropertyValue();
            PropertyTag replyTemplatePropertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagBody,
                PropertyType = (ushort)PropertyType.PtypString
            };
            replyTemplateProperties[0].PropertyTag = replyTemplatePropertyTag;
            replyTemplateProperties[0].Value = Encoding.Unicode.GetBytes(Constants.ReplyTemplateBody + "\0");

            byte[] guidByte = this.OxoruleAdapter.CreateReplyTemplate(this.InboxFolderHandle, this.InboxFolderID, true, replyTemplateSubject, replyTemplateProperties, out replyTemplateMessageId, out replyTemplateMessageHandler);
            #endregion

            #region TestUser1 gets the reply template.
            #region Step1: TestUser1 gets a table of the messages.
            uint contentsTableHandleOfFAIMessage;
            RopGetContentsTableResponse ropGetContentsTableResponseOfFAIMessage = this.OxoruleAdapter.RopGetContentsTable(this.InboxFolderHandle, ContentTableFlag.Associated, out contentsTableHandleOfFAIMessage);
            Site.Assert.AreEqual<uint>(0, ropGetContentsTableResponseOfFAIMessage.ReturnValue, "Getting DAF contents table should succeed");
            #endregion

            #region Step2: TestUser1 sets the interested columns of the message table.

            // Here are 2 interested columns listed as below.
            PropertyTag[] propertyTagOfFAIMessage = new PropertyTag[2];
            PropertyTag pidTagMessageSubject = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagSubject,
                PropertyType = (ushort)PropertyType.PtypString
            };
            propertyTagOfFAIMessage[0] = pidTagMessageSubject;
            PropertyTag pidTagReplyTemplateId = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagReplyTemplateId,
                PropertyType = (ushort)PropertyType.PtypBinary
            };
            propertyTagOfFAIMessage[1] = pidTagReplyTemplateId;

            // Query rows which include the property values of the interested columns. 
            RopQueryRowsResponse ropQueryRowsResponseOfFAIMessage = this.OxoruleAdapter.QueryPropertiesInTable(contentsTableHandleOfFAIMessage, propertyTagOfFAIMessage);
            Site.Assert.AreNotEqual<ushort>(0, ropQueryRowsResponseOfFAIMessage.RowCount, "There should be message generated in TestUser1's Inbox folder");
            byte[] replyTemplateId = null;
            for (int i = 0; i < ropQueryRowsResponseOfFAIMessage.RowCount; i++)
            {
                string messageSubject = AdapterHelper.PropertyValueConvertToString(ropQueryRowsResponseOfFAIMessage.RowData.PropertyRows[i].PropertyValues[0].Value);
                if (messageSubject.Equals(replyTemplateSubject, StringComparison.CurrentCultureIgnoreCase))
                {
                    replyTemplateId = ropQueryRowsResponseOfFAIMessage.RowData.PropertyRows[i].PropertyValues[1].Value;
                }
            }

            byte[] pidTagReplyTemplateIdValue = new byte[replyTemplateId.Length - 2];
            Array.Copy(replyTemplateId, 2, pidTagReplyTemplateIdValue, 0, replyTemplateId.Length - 2);
            #endregion
            #endregion

            #region TestUser1 gets the message entry ID and the Inbox folder's entry ID.
            byte[] messageEntryId = this.OxoruleAdapter.GetMessageEntryId(this.InboxFolderHandle, this.InboxFolderID, replyTemplateMessageHandler, replyTemplateMessageId);
            #endregion

            #region Prepare rules' data
            ReplyActionDataOfExtendedRule ruleActionData = new ReplyActionDataOfExtendedRule();
            ruleActionData.MessageEIDSize = 0x46;
            ruleActionData.ReplyTemplateMessageEID = messageEntryId;
            ruleActionData.ReplyTemplateGUID = guidByte;
            #endregion

            #region TestUser1 creates an FAI message for the OP_OOF_REPLY extended rule.
            RopCreateMessageResponse ropCreateMessageResponse;
            uint extendedRuleMessageHandle1 = this.OxoruleAdapter.RopCreateMessage(this.InboxFolderHandle, this.InboxFolderID, Convert.ToByte(true), out ropCreateMessageResponse);
            Site.Assert.AreEqual<uint>(0, ropCreateMessageResponse.ReturnValue, "Creating the FAI message should succeed.");

            NamedPropertyInfo namedPropertyInfo1 = new NamedPropertyInfo
            {
                NoOfNamedProps = 0
            };
            TaggedPropertyValue[] extendedRuleProperties1 = AdapterHelper.GenerateExtendedRuleTestData(ruleProperties.Name, 0, (uint)RuleState.ST_ENABLED, Constants.PidTagRuleProvider, ActionType.OP_OOF_REPLY, ruleActionData, ruleProperties.ConditionSubjectName, namedPropertyInfo1);

            // Set properties for extended rule FAI message.
            RopSetPropertiesResponse ropSetPropertiesResponse = this.OxoruleAdapter.RopSetProperties(extendedRuleMessageHandle1, extendedRuleProperties1);
            Site.Assert.AreEqual<uint>(0, ropSetPropertiesResponse.ReturnValue, "Setting property for Extended rule FAI message should succeed.");

            // Save changes of message.
            RopSaveChangesMessageResponse ropSaveChangesMessagResponse = this.OxoruleAdapter.RopSaveChangesMessage(extendedRuleMessageHandle1);
            Site.Assert.AreEqual(0, (int)ropSaveChangesMessagResponse.ReturnValue, "Saving Extend rule message should succeed.");
            #endregion

            #region TestUser1 gets the OP_OOF_REPLY extended rule.
            #region Step1: TestUser1 gets a table of all messages which are placed in the Inbox folder.

            ropGetContentsTableResponseOfFAIMessage = this.OxoruleAdapter.RopGetContentsTable(this.InboxFolderHandle, ContentTableFlag.Associated, out contentsTableHandleOfFAIMessage);
            Site.Assert.AreEqual<uint>(0, ropGetContentsTableResponseOfFAIMessage.ReturnValue, "Getting DAF contents table should succeed");
            #endregion

            #region Step2: TestUser1 sets the interested columns of the message table in the Inbox folder.

            // Here are 6 interested columns listed as below.
            propertyTagOfFAIMessage = new PropertyTag[6];
            PropertyTag pidTagRuleMessageNameTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagRuleMessageName,
                PropertyType = (ushort)PropertyType.PtypString
            };
            propertyTagOfFAIMessage[0] = pidTagRuleMessageNameTag;
            PropertyTag pidTagMessageClassTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagMessageClass,
                PropertyType = (ushort)PropertyType.PtypString
            };
            propertyTagOfFAIMessage[1] = pidTagMessageClassTag;
            PropertyTag pidTagRuleMessageStatePropertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagRuleMessageState,
                PropertyType = (ushort)PropertyType.PtypInteger32
            };
            propertyTagOfFAIMessage[2] = pidTagRuleMessageStatePropertyTag;
            PropertyTag pidTagRuleMessageProviderPropertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagRuleMessageProvider,
                PropertyType = (ushort)PropertyType.PtypString
            };
            propertyTagOfFAIMessage[3] = pidTagRuleMessageProviderPropertyTag;
            PropertyTag pidTagExtendedRuleMessageActionsPropertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagExtendedRuleMessageActions,
                PropertyType = (ushort)PropertyType.PtypBinary
            };
            propertyTagOfFAIMessage[4] = pidTagExtendedRuleMessageActionsPropertyTag;
            PropertyTag pidTagExtendedRuleMessageConditionPropertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagExtendedRuleMessageCondition,
                PropertyType = (ushort)PropertyType.PtypBinary
            };
            propertyTagOfFAIMessage[5] = pidTagExtendedRuleMessageConditionPropertyTag;

            // Query rows which include the property values of the interested columns. 
            ropQueryRowsResponseOfFAIMessage = this.OxoruleAdapter.QueryPropertiesInTable(contentsTableHandleOfFAIMessage, propertyTagOfFAIMessage);
            Site.Assert.AreEqual<uint>(0, ropQueryRowsResponseOfFAIMessage.ReturnValue, "Querying Rows Response of FAI Message should succeed, the actual returned value is {0}", ropQueryRowsResponseOfFAIMessage.ReturnValue);
            ExtendedRuleActions extendedRuleAction = new ExtendedRuleActions();
            ReplyActionDataOfExtendedRule replyActionData = new ReplyActionDataOfExtendedRule();
            for (int i = 0; i < ropQueryRowsResponseOfFAIMessage.RowCount; i++)
            {
                // Since the PidTagMessageClass property of Extended rule MUST have a value of "IPM.ExtendedRule.Message", use PidTagMessageClass property to get the extended rule data.
                System.Text.UnicodeEncoding converter = new UnicodeEncoding();
                string messageClass = converter.GetString(ropQueryRowsResponseOfFAIMessage.RowData.PropertyRows.ToArray()[i].PropertyValues[1].Value);
                if (messageClass == "IPM.ExtendedRule.Message" + "\0")
                {
                    byte[] extendedRuleMessageActionBinary = ropQueryRowsResponseOfFAIMessage.RowData.PropertyRows[i].PropertyValues[4].Value;
                    byte[] extendedRuleMessageActionBuffer = new byte[extendedRuleMessageActionBinary.Length - 2];

                    // Remove the two length bytes to get the extended rule action data.
                    Array.Copy(extendedRuleMessageActionBinary, 2, extendedRuleMessageActionBuffer, 0, extendedRuleMessageActionBinary.Length - 2);
                    extendedRuleAction.Deserialize(extendedRuleMessageActionBuffer);
                    replyActionData.Deserialize(extendedRuleAction.RuleActionBuffer.Actions[0].ActionDataValue.Serialize());
                    break;
                }
            }
            #endregion

            #region Capture Code

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R998: the Message EntryID is {0}, and the ReplyTemplateMessageEID in the action data is {1}", messageEntryId, replyActionData.ReplyTemplateMessageEID);

            bool isVerifiedR998 = Common.CompareByteArray(ruleActionData.ReplyTemplateMessageEID, replyActionData.ReplyTemplateMessageEID);

            // Verify MS-OXORULE requirement: MS-OXORULE_R998.
            Site.CaptureRequirementIfIsTrue(
                isVerifiedR998,
                998,
                @"[OP_REPLY and OP_OOF_REPLY ActionData Structure] [Buffer Format for Extended Rules] ReplyTemplateMessageEID (70 bytes): A Message EntryID structure, as specified in [MS-OXCDATA] section 2.2.4.2, that contains the entry ID of the reply template.");

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

            bool isVerifiedR1000 = Common.CompareByteArray(ruleActionData.ReplyTemplateGUID, replyActionData.ReplyTemplateGUID);

            // Verify MS-OXORULE requirement: MS-OXORULE_R1000.
            // IF the value of the ReplyTemplateGUID field in OP_OOF_REPLY action data is equal to the value of the PidTagReplyTemplateId property that is set on the reply template, R1000 can be verified.
            Site.CaptureRequirementIfIsTrue(
                isVerifiedR1000,
                1000,
                @"[OP_REPLY and OP_OOF_REPLY ActionData Structure] [Buffer Format for Extended Rules] ReplyTemplateGUID (16 bytes): A GUID that is generated by the client in the process of creating a reply template.");

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R1002: the value of PidTagReplyTemplateId property is {0}, and the ReplyTemplateGUID in the action data is {1}", pidTagReplyTemplateIdValue, replyActionData.ReplyTemplateGUID);

            bool isVerifiedR1002 = isVerifiedR998 && isVerifiedR1000 && replyActionData.MessageEIDSize == ruleActionData.MessageEIDSize;

            // Verify MS-OXORULE requirement: MS-OXORULE_R1002.
            Site.CaptureRequirementIfIsTrue(
                isVerifiedR1002,
                1002,
                @"[OP_REPLY and OP_OOF_REPLY ActionData Structure] [Buffer Format for Extended Rules] The value of the ReplyTemplateGUID field in OP_OOF_REPLY action data is equal to the value of the PidTagReplyTemplateId property that is set on the reply template.");
            #endregion
            #endregion
        }
        /// <summary>
        /// Set the specific object's property value.
        /// </summary>
        /// <param name="serverId">A 32-bit signed integer represent the Identity of server.</param>
        /// <param name="handleindex">Server object handle index.</param>
        /// <param name="taggedPropertyValueArray">The list of property values.</param>
        /// <returns>Indicate the result of this ROP operation.</returns>
        public RopResult SetProperties(int serverId, int handleindex, Sequence<string> taggedPropertyValueArray)
        {
            // Initialize ROP data.
            TaggedPropertyValue[] taggedPropertyValueArrays = new TaggedPropertyValue[taggedPropertyValueArray.Count];

            // Set a large property to test TransferStatus (Partial and NoRoom)
            for (int i = 0; i < taggedPropertyValueArray.Count; i++)
            {
                if (taggedPropertyValueArray[i] == "PidTagPolicyTag")
                {
                    // Set the property PidTagPolicyTag
                    taggedPropertyValueArrays[i] = new TaggedPropertyValue
                    {
                        PropertyTag = new PropertyTag(0x3019, 0x0102)
                    };
                    string value = string.Empty;
                    for (int j = 0; j < 30000; j++)
                    {
                        value += "a";
                    }

                    taggedPropertyValueArrays[i].Value = Common.AddInt16LengthBeforeBinaryArray(Encoding.ASCII.GetBytes(value));
                }
                else
                {
                    taggedPropertyValueArrays[i] = this.taggedPropertyValuesDictionary[taggedPropertyValueArray[i]];
                }
            }

            uint setPropertiesHandle = this.handleContainer[handleindex];
            RopResult result = RopResult.InvalidParameter;

            // Construct ROP request.
            RopSetPropertiesRequest setPropertiesRequest = new RopSetPropertiesRequest
            {
                RopId = 0x0A,
                LogonId = 0x00,
                InputHandleIndex = 0x00
            };
            int arraySize = 0;
            for (int i = 0; i < taggedPropertyValueArrays.Length; i++)
            {
                arraySize += taggedPropertyValueArrays[i].Size();
            }

            // This value specifies the number of bytes used for the PropertyValueCount field and the PropertyValues field.
            setPropertiesRequest.PropertyValueSize = (ushort)(arraySize + 2);
            setPropertiesRequest.PropertyValueCount = (ushort)taggedPropertyValueArrays.Length;
            setPropertiesRequest.PropertyValues = taggedPropertyValueArrays;

            // Send the RopSetProperties request 
            RopSetPropertiesResponse setPropertiesResponse = (RopSetPropertiesResponse)this.Process(serverId, setPropertiesRequest, setPropertiesHandle);
            result = (RopResult)setPropertiesResponse.ReturnValue;
            if (result == RopResult.Success)
            {
                this.lastChangeMadeByServer = true;
            }

            return result;
        }
        /// <summary>
        /// Imports deletions of messages or folders into the server replica.
        /// </summary>
        /// <param name="serverId">A 32-bit signed integer represent the Identity of server</param>
        /// <param name="uploadcontextHandleIndex">Synchronization upload context handle</param>
        /// <param name="objIdIndexes">more object id</param>
        /// <param name="importDeleteFlag">Deletions type</param>
        /// <returns>Indicate the result of this ROP operation.</returns>
        public RopResult SynchronizationImportDeletes(int serverId, int uploadcontextHandleIndex, Sequence<int> objIdIndexes, byte importDeleteFlag)
        {
            // Initialize ROP data.
            uint synchronizationImportDeletesHandle = this.handleContainer[uploadcontextHandleIndex];
            RopResult result = RopResult.InvalidParameter;

            RopSynchronizationImportDeletesRequest synchronizationImportDeletesRequest = new RopSynchronizationImportDeletesRequest();
            RopSynchronizationImportDeletesResponse synchronizationImportDeletesResponse = new RopSynchronizationImportDeletesResponse();

            // Construct the RopSynchronizationImportDeletes request.
            synchronizationImportDeletesRequest.RopId = 0x74;
            synchronizationImportDeletesRequest.InputHandleIndex = 0x00;
            synchronizationImportDeletesRequest.LogonId = 0x00;
            synchronizationImportDeletesRequest.IsHierarchy = (byte)importDeleteFlag;
            this.importDelFlag = importDeleteFlag;
            synchronizationImportDeletesRequest.PropertyValueCount = (ushort)objIdIndexes.Count;
            TaggedPropertyValue[] propertyValues = new TaggedPropertyValue[objIdIndexes.Count];
            for (int i = 0; i < propertyValues.Length; i++)
            {
                TaggedPropertyValue propertyValue = new TaggedPropertyValue();
                PropertyTag[] tagArray = new PropertyTag[1];
                byte[] deleteGidValue = new byte[sizeof(int) + sizeof(short) + GidLength];
                propertyValue.PropertyTag = new PropertyTag(0x0000, 0x1102);

                // The combination of first two bytes (0x0016) indicates the length of value field.
                // The amount of id
                int index = 0;
                Array.Copy(BitConverter.GetBytes(tagArray.Length), 0, deleteGidValue, 0, sizeof(int));
                index += sizeof(int);
                Array.Copy(BitConverter.GetBytes((short)GidLength), 0, deleteGidValue, index, sizeof(short));
                index += sizeof(short);
                ulong gid = this.objectIdContainer[objIdIndexes[i]];
                this.delObjId = gid;
                byte[] longTermId = this.GetLongTermIdByte(serverId, gid);
                Array.Copy(longTermId, 0, deleteGidValue, index, longTermId.Length);
                propertyValue.Value = deleteGidValue;
                propertyValues[i] = propertyValue;
            }

            synchronizationImportDeletesRequest.PropertyValues = propertyValues;

            // Send the RopSynchronizationImportDeletes request to get the success response.
            synchronizationImportDeletesResponse = (RopSynchronizationImportDeletesResponse)this.Process(serverId, synchronizationImportDeletesRequest, synchronizationImportDeletesHandle);
            result = (RopResult)synchronizationImportDeletesResponse.ReturnValue;

            if (result == RopResult.Success)
            {
                this.isNonImportMessageChangeOperation = true;
                this.hasExecuteSynchronizationImportDeletes = true;
            }

            // Verify ROP SynchronizationImportDeletes
            this.VerifyRopSynchronizationImportDeletes(synchronizationImportDeletesRequest, synchronizationImportDeletesResponse);

            return result;
        }
        public void MSOXORULE_S02_TC04_ServerExecuteRule_Action_OP_REPLY_PidTagAutoResponseSuppress()
        {
            this.CheckMAPIHTTPTransportSupported();

            #region Prepare value for ruleProperties variable
            RuleProperties ruleProperties = AdapterHelper.GenerateRuleProperties(this.Site, Constants.RuleNameReply);
            #endregion

            #region Create a reply template in the TestUser1's Inbox folder.
            ulong replyTemplateMessageId;
            uint replyTemplateMessageHandler;
            TaggedPropertyValue[] replyTemplateProperties = new TaggedPropertyValue[1];
            replyTemplateProperties[0] = new TaggedPropertyValue();
            PropertyTag replyTemplatePropertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagBody,
                PropertyType = (ushort)PropertyType.PtypString
            };
            replyTemplateProperties[0].PropertyTag = replyTemplatePropertyTag;
            replyTemplateProperties[0].Value = Encoding.Unicode.GetBytes(Constants.ReplyTemplateBody + "\0");

            string replyTemplateSubject = Common.GenerateResourceName(this.Site, Constants.ReplyTemplateSubject);
            byte[] guidBytes = this.OxoruleAdapter.CreateReplyTemplate(this.InboxFolderHandle, this.InboxFolderID, false, replyTemplateSubject, replyTemplateProperties, out replyTemplateMessageId, out replyTemplateMessageHandler);
            #endregion

            #region TestUser1 adds a reply rule with 0x00000000 action flavor to TestUser1's Inbox folder.
            ReplyActionData replyActionData = new ReplyActionData
            {
                ReplyTemplateGUID = new byte[guidBytes.Length]
            };
            Array.Copy(guidBytes, 0, replyActionData.ReplyTemplateGUID, 0, guidBytes.Length);
            replyActionData.ReplyTemplateFID = this.InboxFolderID;
            replyActionData.ReplyTemplateMID = replyTemplateMessageId;

            RuleData ruleForReply = AdapterHelper.GenerateValidRuleDataWithFlavor(ActionType.OP_REPLY, 0, RuleState.ST_ENABLED, replyActionData, 0x00000000, ruleProperties);
            RopModifyRulesResponse ropModifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleForReply });
            Site.Assert.AreEqual<uint>(0, ropModifyRulesResponse.ReturnValue, "Adding reply rule with actionFlavor set to 0x00000000 should succeed.");
            #endregion

            #region TestUser2 sends a mail to TestUser1 with PidTagAutoResponseSuppress set to 0x00000020.
            // Let TestUser2 log on to the server.
            this.LogonMailbox(TestUser.TestUser2);

            TaggedPropertyValue autoResponseSuppressProperty = new TaggedPropertyValue();
            PropertyTag autoResponseSuppressPropertyPropertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagAutoResponseSuppress,
                PropertyType = (ushort)PropertyType.PtypInteger32
            };
            autoResponseSuppressProperty.PropertyTag = autoResponseSuppressPropertyPropertyTag;
            autoResponseSuppressProperty.Value = BitConverter.GetBytes(0x00000020);

            string subject = Common.GenerateResourceName(this.Site, ruleProperties.ConditionSubjectName + "Title");
            this.DeliverMessageToTriggerRule(this.User1Name, this.User1ESSDN, subject, new TaggedPropertyValue[1] { autoResponseSuppressProperty });
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);
            #endregion

            #region TestUser2 verifies the server doesn't send a reply to normal user.
            uint contentsTableHandle = 0;
            int expectedMessageIndex = 0;

            // Specify the message properties to be got.
            PropertyTag[] propertyTagarray = new PropertyTag[1];

            // PidTagSubject
            propertyTagarray[0].PropertyId = (ushort)PropertyId.PidTagSubject;
            propertyTagarray[0].PropertyType = (ushort)PropertyType.PtypString;
            bool doesUnexpectedMessageExist = this.CheckUnexpectedMessageExist(this.InboxFolderHandle, ref contentsTableHandle, propertyTagarray, replyTemplateSubject);

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

            // Verify MS-OXORULE requirement: MS-OXORULE_R526.
            // This test case is designed based on the PidTagAutoResponseSuppress property on the message that has the 0x00000020 bit set.
            // TestUser2 has sent a message to TestUser1. If TestUser2 doesn't get the replied message, this requirement can be verified.
            Site.CaptureRequirementIfIsFalse(
                doesUnexpectedMessageExist,
                526,
                @"[In Processing Incoming Messages to a Folder] [Following is a description of what the server does when it executes each action (2) type, as specified in section 2.2.5.1.1, for an incoming message] ""OP_REPLY"": The server MUST NOT send a reply if the PidTagAutoResponseSuppress property ([MS-OXOMSG] section 2.2.1.77) on the message that has the 0x00000020 bit set.");

            #endregion

            #region TestUser1 verifies there are messages which are the sent message in the Inbox folder.
            // Let TestUser1 logon to the server
            this.LogonMailbox(TestUser.TestUser1);

            PropertyTag[] propertyTags = new PropertyTag[1];
            propertyTags[0].PropertyId = (ushort)PropertyId.PidTagSubject;
            propertyTags[0].PropertyType = (ushort)PropertyType.PtypString;

            expectedMessageIndex = 0;
            RopQueryRowsResponse mailMessageContentInUser1 = this.GetExpectedMessage(this.InboxFolderHandle, ref contentsTableHandle, propertyTags, ref expectedMessageIndex, subject);
            Site.Assert.AreEqual<uint>(0, mailMessageContentInUser1.ReturnValue, "Getting mail message operation should succeed.");
            #endregion
        }
        public void MSOXORULE_S02_TC03_ServerExecuteRule_Action_OP_REPLY_ActionFlavor_NS()
        {
            this.CheckMAPIHTTPTransportSupported();

            #region Prepare value for ruleProperties variable
            RuleProperties ruleProperties = AdapterHelper.GenerateRuleProperties(this.Site, Constants.RuleNameReply);
            #endregion

            #region Create a reply template in the TestUser1's Inbox folder.
            ulong replyTemplateMessageId;
            uint replyTemplateMessageHandler;

            TaggedPropertyValue[] replyTemplateProperties;

            // Add recipient information .
            TaggedPropertyValue[] temp = AdapterHelper.GenerateRecipientPropertiesBlock(this.User2Name, this.User2ESSDN);
            replyTemplateProperties = new TaggedPropertyValue[4];
            replyTemplateProperties[0] = new TaggedPropertyValue();
            PropertyTag propertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagBody,
                PropertyType = (ushort)PropertyType.PtypString
            };
            replyTemplateProperties[0].PropertyTag = propertyTag;
            replyTemplateProperties[0].Value = Encoding.Unicode.GetBytes(Constants.ReplyTemplateBody + "\0");
            Array.Copy(temp, 0, replyTemplateProperties, 1, temp.Length - 1);

            string replyTemplateSubject = Common.GenerateResourceName(this.Site, Constants.ReplyTemplateSubject);
            byte[] guidBytes = this.OxoruleAdapter.CreateReplyTemplate(this.InboxFolderHandle, this.InboxFolderID, false, replyTemplateSubject, replyTemplateProperties, out replyTemplateMessageId, out replyTemplateMessageHandler);
            #endregion

            #region TestUser1 adds a reply rule with actionFlavor set to NS(0x00000001).
            ReplyActionData replyActionDataWithFlavor = new ReplyActionData
            {
                ReplyTemplateGUID = new byte[guidBytes.Length]
            };
            Array.Copy(guidBytes, 0, replyActionDataWithFlavor.ReplyTemplateGUID, 0, guidBytes.Length);

            replyActionDataWithFlavor.ReplyTemplateFID = this.InboxFolderID;
            replyActionDataWithFlavor.ReplyTemplateMID = replyTemplateMessageId;
            uint actionFlavor_NS = (uint)ActionFlavorsReply.NS;

            RuleData ruleForReplyWithFlavor = AdapterHelper.GenerateValidRuleDataWithFlavor(ActionType.OP_REPLY, 0, RuleState.ST_ENABLED, replyActionDataWithFlavor, actionFlavor_NS, ruleProperties);
            RopModifyRulesResponse ropModifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleForReplyWithFlavor });
            Site.Assert.AreEqual<uint>(0, ropModifyRulesResponse.ReturnValue, "Adding rule with actionFlavor set to NS should succeed.");
            #endregion

            #region TestUser2 delivers a message to TestUser1 to trigger these rules.
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);

            // TestUser2 delivers a message to trigger the rules.
            string mailSubject = Common.GenerateResourceName(this.Site, ruleProperties.ConditionSubjectName + "Title");
            this.SUTAdapter.SendMailToRecipient(this.User2Name, this.User2Password, this.User1Name, mailSubject);
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);
            #endregion

            #region TestUser1 gets the message sent by TestUser2.
            uint inboxFolderContentsTableHandle = 0;
            PropertyTag[] propertyTags = new PropertyTag[1];
            propertyTags[0].PropertyId = (ushort)PropertyId.PidTagSubject;
            propertyTags[0].PropertyType = (ushort)PropertyType.PtypString;

            uint rowCount = 0;
            RopQueryRowsResponse getInboxMailMessageContent = this.GetExpectedMessage(this.InboxFolderHandle, ref inboxFolderContentsTableHandle, propertyTags, ref rowCount, 1, mailSubject);
            Site.Assert.AreEqual<uint>(0, getInboxMailMessageContent.ReturnValue, "Getting the message should succeed.");
            #endregion

            #region TestUser2 verifies there is no new message in the Inbox folder.
            // Let TestUser2 log on to the server.
            this.LogonMailbox(TestUser.TestUser2);

            // Specify the message properties to be got.
            PropertyTag[] propertyTagList = new PropertyTag[1];
            propertyTagList[0].PropertyId = (ushort)PropertyId.PidTagSubject;
            propertyTagList[0].PropertyType = (ushort)PropertyType.PtypString;

            uint contentsTableHandle = 0;
            bool doesUnexpectedMessageExist = this.CheckUnexpectedMessageExist(this.InboxFolderHandle, ref contentsTableHandle, propertyTagList, replyTemplateSubject);

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

            // Verify MS-OXORULE requirement: MS-OXORULE_R288.
            // TestUser2 has sent a message to TestUser1. If TestUser2 doesn't get the replied message, this requirement can be verified.
            Site.CaptureRequirementIfIsFalse(
                doesUnexpectedMessageExist,
                288,
                @"[In Action Flavors] NS (Bitmask 0x00000001): [OP_REPLY ActionType] Do not send the message to the message sender.");

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

            // Verify MS-OXORULE requirement: MS-OXORULE_R663
            // The recipients (2) information is added in the reply template when it is created. Since the rule works as expected, this requirement can be captured.
            Site.CaptureRequirement(
                663,
                @"[In Action Flavors] NS (Bitmask 0x00000001): [OP_REPLY ActionType] The reply template MUST contain recipients (2) in this case [if the NS flag is set].");

            #endregion
            #endregion
        }
        public void MSOXORULE_S02_TC20_ServerExecuteRule_Action_OP_REPLY_AutoGeneratedMsg()
        {
            this.CheckMAPIHTTPTransportSupported();
            Site.Assume.IsTrue(Common.IsRequirementEnabled(5281, this.Site), "This test case only runs when implementation does not avoid sending replies to automatically generated messages to avoid generating endless autoreply loops for \"OP_REPLY\"");

            #region Prepare value for ruleProperties variable
            RuleProperties ruleProperties = AdapterHelper.GenerateRuleProperties(this.Site, Constants.RuleNameReply);
            #endregion

            #region Create a reply template in the TestUser1's Inbox folder.
            ulong replyTemplateMessageId;
            uint replyTemplateMessageHandler;
            string replyTemplateSubject = Common.GenerateResourceName(this.Site, Constants.ReplyTemplateSubject);

            TaggedPropertyValue[] replyTemplateProperties = new TaggedPropertyValue[1];
            replyTemplateProperties[0] = new TaggedPropertyValue();
            PropertyTag replyTemplatePropertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagBody,
                PropertyType = (ushort)PropertyType.PtypString
            };
            replyTemplateProperties[0].PropertyTag = replyTemplatePropertyTag;
            replyTemplateProperties[0].Value = Encoding.Unicode.GetBytes(Constants.ReplyTemplateBody + "\0");

            byte[] guidBytes = this.OxoruleAdapter.CreateReplyTemplate(this.InboxFolderHandle, this.InboxFolderID, false, replyTemplateSubject, replyTemplateProperties, out replyTemplateMessageId, out replyTemplateMessageHandler);
            #endregion

            #region TestUser1 adds a reply rule to TestUser1's Inbox folder.
            ReplyActionData replyActionData = new ReplyActionData
            {
                ReplyTemplateGUID = new byte[guidBytes.Length]
            };
            Array.Copy(guidBytes, 0, replyActionData.ReplyTemplateGUID, 0, guidBytes.Length);

            replyActionData.ReplyTemplateFID = this.InboxFolderID;
            replyActionData.ReplyTemplateMID = replyTemplateMessageId;

            RuleData ruleForReply = AdapterHelper.GenerateValidRuleDataWithFlavor(ActionType.OP_REPLY, 0, RuleState.ST_ENABLED, replyActionData, 0x00000000, ruleProperties);
            RopModifyRulesResponse ropModifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleForReply });
            Site.Assert.AreEqual<uint>(0, ropModifyRulesResponse.ReturnValue, "Adding rule with actionFlavor set to 0x00000000 should succeed.");
            #endregion

            #region TestUser2 sends a mail with PidTagAutoForwarded setting to true to the TestUser1 to trigger this rule.
            // Sleep enough time to wait for the rule to take effect.
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);

            // Let TestUser2 log on to the server
            this.LogonMailbox(TestUser.TestUser2);

            TaggedPropertyValue autoForwarded = new TaggedPropertyValue();
            PropertyTag autoForwardedTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagAutoForwarded,
                PropertyType = (ushort)PropertyType.PtypBoolean
            };
            autoForwarded.PropertyTag = autoForwardedTag;
            autoForwarded.Value = BitConverter.GetBytes(true);
            string subject = Common.GenerateResourceName(this.Site, ruleProperties.ConditionSubjectName);
            this.DeliverMessageToTriggerRule(this.User1Name, this.User1ESSDN, subject, new TaggedPropertyValue[1] { autoForwarded });

            // Sleep enough time to wait for the rule to be executed on the delivered message.
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);
            #endregion

            #region TestUser2 verifies there are reply messages in the specific folder.
            PropertyTag[] propertyTagList1 = new PropertyTag[3];
            propertyTagList1[0].PropertyId = (ushort)PropertyId.PidTagSubject;
            propertyTagList1[0].PropertyType = (ushort)PropertyType.PtypString;
            propertyTagList1[1].PropertyId = (ushort)PropertyId.PidTagBody;
            propertyTagList1[1].PropertyType = (ushort)PropertyType.PtypString;
            propertyTagList1[2].PropertyId = (ushort)PropertyId.PidTagReceivedByEmailAddress;
            propertyTagList1[2].PropertyType = (ushort)PropertyType.PtypString;

            uint contentTableHandler = 0;
            int expectedMessageIndex = 0;
            RopQueryRowsResponse getNormalMailMessageContent = this.GetExpectedMessage(this.InboxFolderHandle, ref contentTableHandler, propertyTagList1, ref expectedMessageIndex, replyTemplateSubject);

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

            // Verify MS-OXORULE requirement: MS-OXORULE_R5281.
            Site.CaptureRequirementIfAreEqual<int>(
                1,
                getNormalMailMessageContent.RowData.PropertyRows.Count,
                5281,
                @"[In Appendix A: Product Behavior] Implementation does not avoid sending replies to automatically generated messages to avoid generating endless autoreply loops for ""OP_REPLY"". (Exchange 2003 and above follow this behavior.)");
            #endregion
            #endregion
        }
        public void MSOXORULE_S02_TC02_ServerExecuteRule_Action_OP_REPLY()
        {
            this.CheckMAPIHTTPTransportSupported();

            #region Prepare value for ruleProperties variable
            RuleProperties ruleProperties = AdapterHelper.GenerateRuleProperties(this.Site, Constants.RuleNameReply);
            #endregion

            #region Create a reply template in the TestUser1's Inbox folder.
            ulong replyTemplateMessageId;
            uint replyTemplateMessageHandler;
            string replyTemplateSubject = Common.GenerateResourceName(this.Site, Constants.ReplyTemplateSubject);

            TaggedPropertyValue[] replyTemplateProperties = new TaggedPropertyValue[1];
            replyTemplateProperties[0] = new TaggedPropertyValue();
            PropertyTag replyTemplatePropertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagBody,
                PropertyType = (ushort)PropertyType.PtypString
            };
            replyTemplateProperties[0].PropertyTag = replyTemplatePropertyTag;
            replyTemplateProperties[0].Value = Encoding.Unicode.GetBytes(Constants.ReplyTemplateBody + "\0");

            byte[] guidBytes = this.OxoruleAdapter.CreateReplyTemplate(this.InboxFolderHandle, this.InboxFolderID, false, replyTemplateSubject, replyTemplateProperties, out replyTemplateMessageId, out replyTemplateMessageHandler);
            #endregion

            #region TestUser1 adds a reply rule with 0x00000000 action flavor to TestUser1's Inbox folder.
            ReplyActionData replyActionData = new ReplyActionData
            {
                ReplyTemplateGUID = new byte[guidBytes.Length]
            };
            Array.Copy(guidBytes, 0, replyActionData.ReplyTemplateGUID, 0, guidBytes.Length);

            replyActionData.ReplyTemplateFID = this.InboxFolderID;
            replyActionData.ReplyTemplateMID = replyTemplateMessageId;

            RuleData ruleForReply = AdapterHelper.GenerateValidRuleDataWithFlavor(ActionType.OP_REPLY, 0, RuleState.ST_ENABLED, replyActionData, 0x00000000, ruleProperties);
            RopModifyRulesResponse ropModifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleForReply });
            Site.Assert.AreEqual<uint>(0, ropModifyRulesResponse.ReturnValue, "Adding rule with actionFlavor set to 0x00000000 should succeed.");
            #endregion

            #region TestUser2 sends a mail to the TestUser1 to trigger this rule.
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);

            // TestUser2 deliver a message to trigger these rules
            string mailSubject = Common.GenerateResourceName(this.Site, ruleProperties.ConditionSubjectName + "Title");
            this.SUTAdapter.SendMailToRecipient(this.User2Name, this.User2Password, this.User1Name, mailSubject);
            Thread.Sleep(this.WaitForTheRuleToTakeEffect);
            #endregion

            #region TestUser1 verifies there are messages in the specific folder then get the sentRepresentingEmailAddress.
            // Specify the message properties to be got.
            PropertyTag[] propertyTagList = new PropertyTag[4];
            propertyTagList[0].PropertyId = (ushort)PropertyId.PidTagSubject;
            propertyTagList[0].PropertyType = (ushort)PropertyType.PtypString;
            propertyTagList[1].PropertyId = (ushort)PropertyId.PidTagBody;
            propertyTagList[1].PropertyType = (ushort)PropertyType.PtypString;
            propertyTagList[2].PropertyId = (ushort)PropertyId.PidTagSentRepresentingEmailAddress;
            propertyTagList[2].PropertyType = (ushort)PropertyType.PtypString;
            propertyTagList[3].PropertyId = (ushort)PropertyId.PidTagHasDeferredActionMessages;
            propertyTagList[3].PropertyType = (ushort)PropertyType.PtypBoolean;

            uint contentTableHandler = 0;
            int expectedMessageIndex = 0;
            RopQueryRowsResponse getNormalMailMessageContentOnFlavorRule = this.GetExpectedMessage(this.InboxFolderHandle, ref contentTableHandler, propertyTagList, ref expectedMessageIndex, mailSubject);

            string sentRepresentingEmailAddress = AdapterHelper.PropertyValueConvertToString(getNormalMailMessageContentOnFlavorRule.RowData.PropertyRows[expectedMessageIndex].PropertyValues[2].Value);

            // Get the value of PidTagHasDeferredActionMessages.
            byte[] pidTagHasDeferredActionMessagesOfMessageInInboxFolder = getNormalMailMessageContentOnFlavorRule.RowData.PropertyRows[expectedMessageIndex].PropertyValues[3].Value;

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

            // Verify MS-OXORULE requirement: MS-OXORULE_R886.
            // If a rule has no DAM, its pidTagHasDeferredActionMessages property is false or not existing.
            // So if check whether this property exists and its value is false (0x00) or it does not exist (the value is 0x8004010f), it means the rule has no DAM.
            bool isVerifyR886 = Common.CompareByteArray(pidTagHasDeferredActionMessagesOfMessageInInboxFolder, new byte[] { 0x00 }) ||
                             Common.CompareByteArray(pidTagHasDeferredActionMessagesOfMessageInInboxFolder, new byte[] { 0x0f, 0x01, 0x04, 0x80 });

            Site.CaptureRequirementIfIsTrue(
                isVerifyR886,
                886,
                @"[In PidTagHasDeferredActionMessages Property] This property MUST be set to ""false"" if a message has no associated DAM.");
            #endregion

            #region TestUser2 verifies there are reply messages in the specific folder.
            // Let TestUser2 log on to the server.
            this.LogonMailbox(TestUser.TestUser2);

            PropertyTag[] propertyTagList1 = new PropertyTag[3];
            propertyTagList1[0].PropertyId = (ushort)PropertyId.PidTagSubject;
            propertyTagList1[0].PropertyType = (ushort)PropertyType.PtypString;
            propertyTagList1[1].PropertyId = (ushort)PropertyId.PidTagBody;
            propertyTagList1[1].PropertyType = (ushort)PropertyType.PtypString;
            propertyTagList1[2].PropertyId = (ushort)PropertyId.PidTagReceivedByEmailAddress;
            propertyTagList1[2].PropertyType = (ushort)PropertyType.PtypString;

            expectedMessageIndex = 0;
            getNormalMailMessageContentOnFlavorRule = this.GetExpectedMessage(this.InboxFolderHandle, ref contentTableHandler, propertyTagList1, ref expectedMessageIndex, replyTemplateSubject);

            #region Capture Code
            // Subject, bodyText and originalMessageSender are the properties set by the server on the replied message.
            string subject = AdapterHelper.PropertyValueConvertToString(getNormalMailMessageContentOnFlavorRule.RowData.PropertyRows[expectedMessageIndex].PropertyValues[0].Value);
            string bodyText = AdapterHelper.PropertyValueConvertToString(getNormalMailMessageContentOnFlavorRule.RowData.PropertyRows[expectedMessageIndex].PropertyValues[1].Value);
            string receivedByEmailAddress = AdapterHelper.PropertyValueConvertToString(getNormalMailMessageContentOnFlavorRule.RowData.PropertyRows[expectedMessageIndex].PropertyValues[2].Value);

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R525: the actual value of property PidTagSubject and PidTagReceivedByEmailAddress separately is {0}, {1}", subject, receivedByEmailAddress.ToUpperInvariant());

            // Verify MS-OXORULE requirement: MS-OXORULE_R525.
            // Subject is the property from the reply template, ReceivedByEmailAddress is the property from the original message's SentRepresentingEmailAddress property, message body is the text in the reply template.
            // The message class property is set to IPM.Note in sutcontrolAdapter when being sent.
            bool isVerifyR525 = subject == replyTemplateSubject && receivedByEmailAddress.ToUpperInvariant() == sentRepresentingEmailAddress.ToUpperInvariant() && bodyText.ToUpperInvariant() == Constants.ReplyTemplateBody.ToUpperInvariant();

            Site.CaptureRequirementIfIsTrue(
                isVerifyR525,
                525,
                @"[In Processing Incoming Messages to a Folder] Following is a description of what the server does when it executes each action (2) type, as specified in section 2.2.5.1.1, for an incoming message: ""OP_REPLY"": The server MUST use properties from the reply template and from the original message to create a reply to the message and then send the reply.");

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R253: the actual value of the PidTagSubject is {0}, and the name of the template is {1}", subject, replyTemplateSubject);

            // Verify MS-OXORULE requirement: MS-OXORULE_R253.
            // Subject is the property from the reply template, and the name of the template is replyTemplateSubject,
            // if they are same with each other this requirement can be verified.
            bool isVerifyR253 = subject == replyTemplateSubject;

            Site.CaptureRequirementIfIsTrue(
                isVerifyR253,
                253,
                @"[In ActionBlock Structure] The meaning of action type OP_REPLY: Replies to the message.");

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R952: the actual value of the PidTagSubject is {0}, and the name of the template is {1}", subject, replyTemplateSubject);
            bool isVerifiedR952 = subject == replyTemplateSubject && bodyText.ToUpperInvariant() == Constants.ReplyTemplateBody.ToUpperInvariant();

            // Verify MS-OXORULE requirement: MS-OXORULE_R952.
            // The ActionFlavor is set to zero in the OP_REPLY rule, so if the messages template is the same with the reply template, means this reply is not use server-defined text in the reply message, and it's a standard reply. 
            Site.CaptureRequirementIfIsTrue(
                isVerifiedR952,
                952,
                @"[In Action Flavors] [If the ActionType field value is ""OP_REPLY"", the ActionFlavor field MUST have one of the values specified in the following table [XXXXXX (ST) (NS) XXXXXXXXXXXXXXXXXXXXXXXX] or zero (0x00000000)] A value of zero (0x00000000) indicates standard reply behavior, as specified in section 3.1.4.2.5).");
            #endregion
            #endregion
        }
        public void MSOXORULE_S01_TC07_AddForwardAndDelegateRules()
        {
            this.CheckMAPIHTTPTransportSupported();

            #region TestUser1 prepares value for rule properties variable.
            RuleProperties ruleProperties = AdapterHelper.GenerateRuleProperties(this.Site, Constants.RuleNameForward);
            #endregion

            #region TestUser1 prepares the recipient block for Forward rules.
            RecipientBlock recipientBlock = new RecipientBlock
            {
                Reserved = 0x01,
                NoOfProperties = (ushort)0x04u
            };

            TaggedPropertyValue[] recipientProperties = AdapterHelper.GenerateRecipientPropertiesBlock(this.User2Name, this.User2ESSDN);
            recipientBlock.PropertiesData = recipientProperties;
            #endregion

            #region TestUser1 adds rule forward with ActionFlavor set to PR and NC.
            ForwardDelegateActionData forwardActionData = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01,
                RecipientsData = new RecipientBlock[1]
                {
                    recipientBlock
                }
            };
            uint actionForwardFlavorNC_PR = (uint)ActionFlavorsForward.NC | (uint)ActionFlavorsForward.PR;

            RuleData ruleForward = AdapterHelper.GenerateValidRuleDataWithFlavor(ActionType.OP_FORWARD, 100, RuleState.ST_ENABLED, forwardActionData, actionForwardFlavorNC_PR, ruleProperties);
            RopModifyRulesResponse modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleForward });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Adding Forward rule should be success");

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

            // Verify MS-OXORULE requirement: MS-OXORULE_R276.
            // If the ReturnValue of modifyRulesResponse response is 0x00000000, it means PR can be combined with the NC ActionFlavor flag.
            Site.CaptureRequirementIfAreEqual<uint>(
                0x00000000,
                modifyRulesResponse.ReturnValue,
                276,
                @"[In Action Flavors] PR (Bitmask 0x00000001): Can be combined with the NC ActionFlavor flag.");
            #endregion

            #region TestUser1 adds rule forward with ActionFlavor set to AT.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameForwardAT);
            ForwardDelegateActionData forwardActionDataAT = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01,
                RecipientsData = new RecipientBlock[1]
                {
                    recipientBlock
                }
            };
            RuleData ruleForwardAT = AdapterHelper.GenerateValidRuleDataWithFlavor(ActionType.OP_FORWARD, 100, RuleState.ST_ENABLED, forwardActionDataAT, (uint)ActionFlavorsForward.AT, ruleProperties);
            modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_OnExisting, new RuleData[] { ruleForwardAT });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Adding Forward rule should be success");
            #endregion

            #region TestUser1 adds rule forward with ActionFlavor set to TM.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameForwardTM);
            ForwardDelegateActionData forwardActionDataTM = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01,
                RecipientsData = new RecipientBlock[1]
                {
                    recipientBlock
                }
            };
            RuleData ruleForwardTM = AdapterHelper.GenerateValidRuleDataWithFlavor(ActionType.OP_FORWARD, 100, RuleState.ST_ENABLED, forwardActionDataTM, (uint)ActionFlavorsForward.TM, ruleProperties);
            modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_OnExisting, new RuleData[] { ruleForwardTM });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Adding Forward rule should be success");
            #endregion

            #region TestUser1 adds rule DELEGATE.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameDelegate);
            ForwardDelegateActionData delegateActionData = new ForwardDelegateActionData
            {
                RecipientCount = (ushort)0x01
            };

            #region Prepare the Delegate rule Recipient block.
            RecipientBlock delegateRecipientBlock = new RecipientBlock
            {
                Reserved = 0x01,
                NoOfProperties = (ushort)0x05u
            };
            TaggedPropertyValue[] delegateRecipientProperties = new TaggedPropertyValue[5];

            TaggedPropertyValue[] tempArray = AdapterHelper.GenerateRecipientPropertiesBlock(this.User2Name, this.User2ESSDN);
            Array.Copy(tempArray, 0, delegateRecipientProperties, 0, tempArray.Length);

            // Add PidTagSmtpEmailAdderss
            delegateRecipientProperties[4] = new TaggedPropertyValue();
            PropertyTag delegateRecipientPropertiesPropertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagSmtpAddress,
                PropertyType = (ushort)PropertyType.PtypString
            };
            delegateRecipientProperties[4].PropertyTag = delegateRecipientPropertiesPropertyTag;
            delegateRecipientProperties[4].Value = Encoding.Unicode.GetBytes(this.User2Name + "@" + this.Domain + "\0");

            delegateRecipientBlock.PropertiesData = delegateRecipientProperties;
            #endregion

            delegateActionData.RecipientsData = new RecipientBlock[1] { delegateRecipientBlock };
            RuleData ruleDelegate = AdapterHelper.GenerateValidRuleData(ActionType.OP_DELEGATE, TestRuleDataType.ForAdd, 1, RuleState.ST_ENABLED, delegateActionData, ruleProperties, null);
            modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_OnExisting, new RuleData[] { ruleDelegate });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Adding Delegate rule should succeed.");
            #endregion

            #region TestUser1 gets ruleActions of the four rules.
            RopGetRulesTableResponse ropGetRulesTableResponse;
            uint ruleTableHandle = this.OxoruleAdapter.RopGetRulesTable(this.InboxFolderHandle, TableFlags.Normal, out ropGetRulesTableResponse);
            Site.Assert.AreEqual<uint>(0, ropGetRulesTableResponse.ReturnValue, "Getting rule table should succeed.");

            PropertyTag actionsTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagRuleActions,
                PropertyType = (ushort)PropertyType.PtypRuleAction
            };

            // Set the query target to standardardRules.
            this.OxoruleAdapter.TargetOfRop = TargetOfRop.ForStandardRules;

            RopQueryRowsResponse getAllActionsResponse = this.OxoruleAdapter.QueryPropertiesInTable(ruleTableHandle, new PropertyTag[1] { actionsTag });
            Site.Assert.AreEqual<uint>(0, getAllActionsResponse.ReturnValue, "Getting the rule actions should succeed.");

            // Four rules have been added to the Inbox folder, so the row count in the rule table should be 4.
            Site.Assert.AreEqual<uint>(4, getAllActionsResponse.RowCount, "The rule number in the rule table is {0}", getAllActionsResponse.RowCount);
            this.VerifyRuleTable();

            // Clear the status of the adapter.
            this.OxoruleAdapter.TargetOfRop = TargetOfRop.OtherTarget;
            #endregion
        }
        public void MSOXORULE_S01_TC08_AddReplyAndOOF_ReplyRules()
        {
            this.CheckMAPIHTTPTransportSupported();

            #region TestUser1 prepares value for rule properties variable.
            RuleProperties ruleProperties = AdapterHelper.GenerateRuleProperties(this.Site, Constants.RuleNameOOFReply);
            #endregion

            #region Create a Reply template.
            RopCreateMessageResponse ropCreateMessageResponse;
            uint replyTemplateMessageHandler = this.OxoruleAdapter.RopCreateMessage(this.InboxFolderHandle, this.InboxFolderID, Convert.ToByte(true), out ropCreateMessageResponse);
            Site.Assert.AreEqual<uint>(0, ropCreateMessageResponse.ReturnValue, "Creating FAI message should succeed.");

            TaggedPropertyValue[] replyTemplateProperties = new TaggedPropertyValue[3];

            // PidTagMessageClass
            replyTemplateProperties[0] = new TaggedPropertyValue();
            PropertyTag pidTagMessageClassPropertyTag1 = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagMessageClass,
                PropertyType = (ushort)PropertyType.PtypString
            };
            replyTemplateProperties[0].PropertyTag = pidTagMessageClassPropertyTag1;
            replyTemplateProperties[0].Value = Encoding.Unicode.GetBytes(Constants.ReplyTemplate + "\0");

            // PidTagReplyTemplateId
            replyTemplateProperties[1] = new TaggedPropertyValue();
            PropertyTag pidTagReplyTemplateIdPropertyTag1 = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagReplyTemplateId,
                PropertyType = (ushort)PropertyType.PtypBinary
            };
            replyTemplateProperties[1].PropertyTag = pidTagReplyTemplateIdPropertyTag1;
            Guid newReplyTemplateGuid = System.Guid.NewGuid();
            replyTemplateProperties[1].Value = Common.AddInt16LengthBeforeBinaryArray(newReplyTemplateGuid.ToByteArray());

            // PidTagSubject
            replyTemplateProperties[2] = new TaggedPropertyValue();
            PropertyTag pidTagSubjectPropertyTag1 = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagSubject,
                PropertyType = (ushort)PropertyType.PtypString
            };
            replyTemplateProperties[2].PropertyTag = pidTagSubjectPropertyTag1;
            replyTemplateProperties[2].Value = Encoding.Unicode.GetBytes(Common.GenerateResourceName(this.Site, Constants.ReplyTemplateSubject) + "\0");

            RopSetPropertiesResponse ropSetPropertiesResponse = this.OxoruleAdapter.RopSetProperties(replyTemplateMessageHandler, replyTemplateProperties);
            Site.Assert.AreEqual<uint>(0, ropSetPropertiesResponse.ReturnValue, "Setting property for Extended rule FAI message should succeed.");

            // Save changes of message.
            RopSaveChangesMessageResponse ropSaveChangesMessagResponseReply = this.OxoruleAdapter.RopSaveChangesMessage(replyTemplateMessageHandler);
            Site.Assert.AreEqual(0, (int)ropSaveChangesMessagResponseReply.ReturnValue, "Saving Extend rule message should succeed.");

            // Get the newly created message's folder ID.
            PropertyTag fidTagReplyTemplate = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagFolderId,
                PropertyType = (ushort)PropertyType.PtypInteger64
            };
            RopGetPropertiesSpecificResponse ropGetPropertiesSpecificResponseReply = this.OxoruleAdapter.RopGetPropertiesSpecific(replyTemplateMessageHandler, new PropertyTag[1] { fidTagReplyTemplate });
            Site.Assert.AreEqual<uint>(0, ropGetPropertiesSpecificResponseReply.ReturnValue, "Getting folder id operation should succeed.");

            // Get the reply template's guid.
            PropertyTag fidTagOOFReply = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagReplyTemplateId,
                PropertyType = (ushort)PropertyType.PtypBinary
            };
            RopGetPropertiesSpecificResponse ropGetGuid = this.OxoruleAdapter.RopGetPropertiesSpecific(replyTemplateMessageHandler, new PropertyTag[1] { fidTagOOFReply });
            Site.Assert.AreEqual<uint>(0, ropGetGuid.ReturnValue, "Getting guid property operation should succeed.");
            #endregion

            #region TestUser1 adds rule OOF_REPLY.
            ReplyActionData oofReplyActionData = new ReplyActionData
            {
                ReplyTemplateGUID = new byte[ropGetGuid.RowData.PropertyValues[0].Value.Length - 2]
            };
            Array.Copy(ropGetGuid.RowData.PropertyValues[0].Value, 2, oofReplyActionData.ReplyTemplateGUID, 0, ropGetGuid.RowData.PropertyValues[0].Value.Length - 2);
            oofReplyActionData.ReplyTemplateFID = BitConverter.ToUInt64(ropGetPropertiesSpecificResponseReply.RowData.PropertyValues[0].Value, 0);
            oofReplyActionData.ReplyTemplateMID = ropSaveChangesMessagResponseReply.MessageId;
            RuleData ruleForOOFReply = AdapterHelper.GenerateValidRuleData(ActionType.OP_OOF_REPLY, TestRuleDataType.ForAdd, 100, RuleState.ST_ONLY_WHEN_OOF, oofReplyActionData, ruleProperties, null);

            RopModifyRulesResponse modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleForOOFReply });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Adding OOF_REPLY rule should succeed.");
            #endregion

            #region TestUser1 adds rule REPLY.
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameReply);
            ReplyActionData replyActionData = new ReplyActionData
            {
                ReplyTemplateGUID = new byte[ropGetGuid.RowData.PropertyValues[0].Value.Length - 2]
            };
            Array.Copy(ropGetGuid.RowData.PropertyValues[0].Value, 2, replyActionData.ReplyTemplateGUID, 0, ropGetGuid.RowData.PropertyValues[0].Value.Length - 2);
            replyActionData.ReplyTemplateFID = BitConverter.ToUInt64(ropGetPropertiesSpecificResponseReply.RowData.PropertyValues[0].Value, 0);
            replyActionData.ReplyTemplateMID = ropSaveChangesMessagResponseReply.MessageId;
            RuleData ruleForReply = AdapterHelper.GenerateValidRuleData(ActionType.OP_REPLY, TestRuleDataType.ForAdd, 0, RuleState.ST_ENABLED, replyActionData, ruleProperties, null);
            modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(this.InboxFolderHandle, ModifyRuleFlag.Modify_OnExisting, new RuleData[] { ruleForReply });
            Site.Assert.AreEqual<uint>(0, modifyRulesResponse.ReturnValue, "Adding Reply rule should succeed.");
            #endregion

            #region TestUser1 gets ruleActions of the two rules.
            RopGetRulesTableResponse ropGetRulesTableResponse;
            uint ruleTableHandle = this.OxoruleAdapter.RopGetRulesTable(this.InboxFolderHandle, TableFlags.Normal, out ropGetRulesTableResponse);
            Site.Assert.AreEqual<uint>(0, ropGetRulesTableResponse.ReturnValue, "Getting rule table should succeed.");

            PropertyTag[] propertyTags = new PropertyTag[2];

            // PidTagRuleName
            propertyTags[0].PropertyId = (ushort)PropertyId.PidTagRuleName;
            propertyTags[0].PropertyType = (ushort)PropertyType.PtypString;

            // PidTagRuleActions
            propertyTags[1].PropertyId = (ushort)PropertyId.PidTagRuleActions;
            propertyTags[1].PropertyType = (ushort)PropertyType.PtypRuleAction;

            // Set the query target to standardardRules.
            this.OxoruleAdapter.TargetOfRop = TargetOfRop.ForStandardRules;

            RopQueryRowsResponse getAllActionsResponse = this.OxoruleAdapter.QueryPropertiesInTable(ruleTableHandle, propertyTags);
            Site.Assert.AreEqual<uint>(0, getAllActionsResponse.ReturnValue, "Getting the rule actions should succeed.");

            // Two rules have been added to the Inbox folder, so the row count in the rule table should be 2.
            Site.Assert.AreEqual<uint>(2, getAllActionsResponse.RowCount, "The rule number in the rule table is {0}", getAllActionsResponse.RowCount);
            this.VerifyRuleTable();

            RuleAction ruleActionForReply = new RuleAction();
            ReplyActionData actionDataForReply = new ReplyActionData();
            RuleAction ruleActionForOOFReply = new RuleAction();
            ReplyActionData actionDataForOOFReply = new ReplyActionData();
            bool hasActionDataForReply = false;
            bool hasActionDataForOOFReply = false;
            for (int i = 0; i < getAllActionsResponse.RowCount; i++)
            {
                System.Text.UnicodeEncoding converter = new UnicodeEncoding();
                string ruleName = converter.GetString(getAllActionsResponse.RowData.PropertyRows[i].PropertyValues[0].Value);
                if (ruleName.Contains(Constants.RuleNameReply) && !hasActionDataForReply)
                {
                    ruleActionForReply.Deserialize(getAllActionsResponse.RowData.PropertyRows[i].PropertyValues[1].Value);
                    actionDataForReply.Deserialize(ruleActionForReply.Actions[0].ActionDataValue.Serialize());
                    hasActionDataForReply = true;
                }

                if (ruleName.Contains(Constants.RuleNameOOFReply) && !hasActionDataForOOFReply)
                {
                    ruleActionForOOFReply.Deserialize(getAllActionsResponse.RowData.PropertyRows[i].PropertyValues[1].Value);
                    actionDataForOOFReply.Deserialize(ruleActionForOOFReply.Actions[0].ActionDataValue.Serialize());
                    hasActionDataForOOFReply = true;
                }

                if (hasActionDataForReply && hasActionDataForOOFReply)
                {
                    break;
                }
            }

            // Add a variable to verify R727 and R928.
            bool isPidTagReplyTemplateIdEqualtemplateGUIDForOOFReply = false;

            if (Common.CompareByteArray(newReplyTemplateGuid.ToByteArray(), actionDataForOOFReply.ReplyTemplateGUID))
            {
                isPidTagReplyTemplateIdEqualtemplateGUIDForOOFReply = true;
            }

            // Add a variable to verify R309
            bool isPidTagReplyTemplateIdEqualtemplateGUIDForReply = false;
            if (Common.CompareByteArray(newReplyTemplateGuid.ToByteArray(), actionDataForReply.ReplyTemplateGUID))
            {
                isPidTagReplyTemplateIdEqualtemplateGUIDForReply = true;
            }

            #region Capture Code
            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R727: the actual value of PidTagReplyTemplateId property is {0}", BitConverter.ToString(actionDataForOOFReply.ReplyTemplateGUID));

            // Verify MS-OXORULE requirement: MS-OXORULE_R727.
            // ReplyTemplateGUID of the actionDataForOOFReply is the value of PidTagReplyTemplateId property, and newGuidOOFReplyGUID is the GUID of the reply template.
            bool isVerifyR727 = isPidTagReplyTemplateIdEqualtemplateGUIDForOOFReply;

            Site.CaptureRequirementIfIsTrue(
                isVerifyR727,
                727,
                @"[In PidTagReplyTemplateId Property] The PidTagReplyTemplateId property ([MS-OXPROPS] section 2.909) specifies the GUID for the reply template.");

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R928: the actual value of PidTagReplyTemplateId property is {0}", BitConverter.ToString(actionDataForOOFReply.ReplyTemplateGUID));

            // Verify MS-OXORULE requirement: MS-OXORULE_R928.
            // ReplyTemplateGUID of the actionDataForOOFReply is the value of PidTagReplyTemplateId property, and newGuidOOFReplyGUID is the GUID of the reply template.
            bool isVerifyR928 = isPidTagReplyTemplateIdEqualtemplateGUIDForOOFReply;

            Site.CaptureRequirementIfIsTrue(
                isVerifyR928,
                928,
                @"[OP_REPLY and OP_OOF_REPLY ActionData Structure] [Buffer Format for Standard Rules] The value of the ReplyTemplateGUID field in OP_OOF_REPLY action data is equal to the value of the PidTagReplyTemplateId property (section 2.2.9.2) that is set on the reply template.");

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R309: the actual value of PidTagReplyTemplateId property is {0}", BitConverter.ToString(actionDataForReply.ReplyTemplateGUID));

            // Verify MS-OXORULE requirement: MS-OXORULE_R309.
            // ReplyTemplateGUID of the actionDataForReply is the value of PidTagReplyTemplateId property, and newGuidOOFReplyGUID is the GUID of the reply template.
            bool isVerifyR309 = isPidTagReplyTemplateIdEqualtemplateGUIDForReply;

            Site.CaptureRequirementIfIsTrue(
                isVerifyR309,
                309,
                @"[OP_REPLY and OP_OOF_REPLY ActionData Structure] [Buffer Format for Standard Rules] The value of the ReplyTemplateGUID field in OP_REPLY action data is equal to the value of the PidTagReplyTemplateId property (section 2.2.9.2) that is set on the reply template.");

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R305, the folder ID which contains the reply template is {0}, and actually the value is {1} in the actionDataForReply, and the value is {2} in actionDataForOOFReply", replyActionData.ReplyTemplateFID, actionDataForReply.ReplyTemplateFID, actionDataForOOFReply.ReplyTemplateFID);
            bool isVerifiedR305 = replyActionData.ReplyTemplateFID == actionDataForReply.ReplyTemplateFID && replyActionData.ReplyTemplateFID == actionDataForOOFReply.ReplyTemplateFID;

            // Verify MS-OXORULE requirement: MS-OXORULE_R305.
            // ReplyTemplateFID in the replyActionData is set to the folder ID that contains the reply template, so if the value in the rule actionData is the same as it, R305 can be verified.
            Site.CaptureRequirementIfIsTrue(
                isVerifiedR305,
                305,
                @"[OP_REPLY and OP_OOF_REPLY ActionData Structure] [Buffer Format for Standard Rules] ReplyTemplateFID (8 bytes): A Folder ID structure, as specified in [MS-OXCDATA] section 2.2.1.1, that identifies the folder that contains the reply template.");

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R307, the Message ID which is used as the reply template is {0}, and actually the value is {1} in the actionDataForReply, and the value is {2} in the actionDataForOOFReply", replyActionData.ReplyTemplateMID, actionDataForReply.ReplyTemplateMID, actionDataForOOFReply.ReplyTemplateMID);
            bool isVerifiedR307 = replyActionData.ReplyTemplateMID == actionDataForReply.ReplyTemplateMID && replyActionData.ReplyTemplateMID == actionDataForOOFReply.ReplyTemplateMID;
            
            // Verify MS-OXORULE requirement: MS-OXORULE_R307.
            // ReplyTemplateMID in the replyActionData is set to the message ID which is used as the reply template, so if the value in the rule actionData is the same as it, R307 can be verified.
            Site.CaptureRequirementIfIsTrue(
                isVerifiedR307,
                307,
                @"[OP_REPLY and OP_OOF_REPLY ActionData Structure] [Buffer Format for Standard Rules] ReplyTemplateMID (8 bytes): A Message ID structure, as specified in [MS-OXCDATA] section 2.2.1.2, that identifies the FAI message being used as the reply template.");
            #endregion

            // Clear the status of the adapter.
            this.OxoruleAdapter.TargetOfRop = TargetOfRop.OtherTarget;
            #endregion
        }
        /// <summary>
        /// Modifies the permissions associated with a folder.
        /// </summary>
        /// <param name="serverId">The server id</param>
        /// <param name="folderHandleIndex">index of folder handle in container</param>
        /// <param name="permissionLevel">The permission level</param>
        /// <returns>Indicate the result of this ROP operation.</returns>
        public RopResult ModifyPermissions(int serverId, int folderHandleIndex, PermissionLevels permissionLevel)
        {
            // Initialize ROP data.
            RopResult result = RopResult.InvalidParameter;
            uint folderHandle = this.handleContainer[folderHandleIndex];

            // Add Administrator user into permission list of the specific folder.
            TaggedPropertyValue[] taggedProperties = new TaggedPropertyValue[2];

            // EntryId
            TaggedPropertyValue propertyValueEntryId = new TaggedPropertyValue
            {
                PropertyTag = new PropertyTag(0x0FFF, 0x0102)
            };
            string userDN = Common.GetConfigurationPropertyValue("AdminUserESSDN", this.Site);
            AddressBookEntryId addressEntryId = new AddressBookEntryId(userDN);
            propertyValueEntryId.Value = Common.AddInt16LengthBeforeBinaryArray(addressEntryId.Serialize());
            taggedProperties[0] = propertyValueEntryId;

            // PidTagMemberRights
            TaggedPropertyValue propertyValueMemberRight = new TaggedPropertyValue
            {
                PropertyTag = new PropertyTag(0x6673, 0x0003),
                Value = BitConverter.GetBytes((uint)permissionLevel)
            };

            // Set permission.
            taggedProperties[1] = propertyValueMemberRight;
            PermissionData[] permissionsDataArray = new PermissionData[1];

            // Add row
            permissionsDataArray[0].PermissionDataFlags = (byte)0x01;
            permissionsDataArray[0].PropertyValueCount = (ushort)taggedProperties.Length;
            permissionsDataArray[0].PropertyValues = taggedProperties;

            // Construct ROP request.
            RopModifyPermissionsRequest modifyPermission = new RopModifyPermissionsRequest
            {
                RopId = 0x40,
                LogonId = 0x00,
                InputHandleIndex = 0x00,
                ModifyFlags = (byte)ModifyFlags.IncludeFreeBusy,
                ModifyCount = 0x01,
                PermissionsData = permissionsDataArray
            };

            // Send request and get response.
            RopModifyPermissionsResponse modifyPermissionresponse = (RopModifyPermissionsResponse)this.Process(serverId, modifyPermission, folderHandle);
            result = (RopResult)modifyPermissionresponse.ReturnValue;
            if (result == RopResult.Success)
            {
                this.currentPermission = permissionLevel;
                if (permissionLevel == PermissionLevels.None)
                {
                    // If the specific folder's permission is None, set existNoPermissionFolder as true to make client has no permission to access this folder now
                    this.existNoPermissionFolder = true;
                }
            }

            return result;
        }
        /// <summary>
        /// Get the bytes value of one property from a list of properties.
        /// </summary>
        /// <param name="propertyName">The property need to get value.</param>
        /// <param name="propertyRow">The property row.</param>
        /// <param name="propertyTags">The properties tags.</param>
        /// <returns>The bytes value of the property.</returns>
        private byte[] GetPropertyFromList(PropertyId propertyName, PropertyRow propertyRow, PropertyTag[] propertyTags)
        {
            byte[] value = new byte[0];
            TaggedPropertyValue[] allProperties = null;
            if (propertyRow != null && propertyRow.PropertyValues != null && propertyRow.PropertyValues.Count > 0)
            {
                allProperties = new TaggedPropertyValue[propertyTags.Length];
                for (int i = 0; i < propertyTags.Length; i++)
                {
                    allProperties[i] = new TaggedPropertyValue
                    {
                        PropertyTag = propertyTags[i],
                        Value = propertyRow.PropertyValues[i].Value
                    };
                }
            }

            foreach (TaggedPropertyValue taggedValue in allProperties)
            {
                if (taggedValue.PropertyTag.PropertyId == (ushort)propertyName)
                {
                    value = taggedValue.Value;
                    break;
                }
            }

            return value;
        }
        /// <summary>
        /// Import new folders, or changes with conflict to existing folders, into the server replica.
        /// </summary>
        /// <param name="serverId">A 32-bit signed integer represent the Identity of server.</param>
        /// <param name="uploadContextHandleIndex">Upload context handle.</param>
        /// <param name="parentFolderHandleIndex">Parent folder handle index.</param>
        /// <param name="properties">Properties to be set.</param>
        /// <param name="localFolderIdIndex">Local folder id index</param>
        /// <param name="folderIdIndex">The folder object id index.</param>
        /// <param name="conflictType">The conflict type will import.</param>
        /// <returns>Indicate the result of this ROP operation.</returns>
        public RopResult SynchronizationImportHierarchyChangeWithConflict(int serverId, int uploadContextHandleIndex, int parentFolderHandleIndex, Set<string> properties, int localFolderIdIndex, out int folderIdIndex, ConflictTypes conflictType)
        {
            // Initialize ROP data.
            uint uploadContextHandle = this.handleContainer[uploadContextHandleIndex];
            RopResult result = RopResult.InvalidParameter;
            folderIdIndex = -1;
            ulong folderId;

            // Construct ROP request.
            RopSynchronizationImportHierarchyChangeRequest synchronizationImportHierarchyChangeRequest;

            // Construct the RopSynchronizationImportHierarchyChange request.
            synchronizationImportHierarchyChangeRequest.RopId = 0x73;
            synchronizationImportHierarchyChangeRequest.LogonId = 0x00;
            synchronizationImportHierarchyChangeRequest.InputHandleIndex = 0x00;

            // Get the folder property value.
            TaggedPropertyValue[] taggedPropertyValueArrays = new TaggedPropertyValue[properties.Count];
            int index = 0;
            foreach (string tempProperty in properties)
            {
                taggedPropertyValueArrays[index++] = this.taggedPropertyValuesDictionary[tempProperty];
            }

            TaggedPropertyValue[] hierarchyValues = this.CreateSampleHierarchyValues(serverId, localFolderIdIndex, parentFolderHandleIndex, out folderId, conflictType);
            synchronizationImportHierarchyChangeRequest.HierarchyValueCount = (ushort)hierarchyValues.Length;
            synchronizationImportHierarchyChangeRequest.HierarchyValues = hierarchyValues;
            synchronizationImportHierarchyChangeRequest.PropertyValueCount = (ushort)taggedPropertyValueArrays.Length;
            synchronizationImportHierarchyChangeRequest.PropertyValues = taggedPropertyValueArrays;

            // Send request and get response.
            RopSynchronizationImportHierarchyChangeResponse synchronizationImportHierarchyChangeResponse = (RopSynchronizationImportHierarchyChangeResponse)this.Process(serverId, synchronizationImportHierarchyChangeRequest, uploadContextHandle);
            result = (RopResult)synchronizationImportHierarchyChangeResponse.ReturnValue;

            if (result == RopResult.Success)
            {
                if (!this.objectIdContainer.ContainsKey(localFolderIdIndex))
                {
                    folderIdIndex = AdapterHelper.GetObjectIdIndex();
                    this.objectIdContainer.Add(folderIdIndex, folderId);
                }

                // Verify ROP SynchronizationImportHierarchyChange
                this.VerifyRopSynchronizationImportHierarchyChange(synchronizationImportHierarchyChangeResponse);
            }

            return result;
        }
        public void MSOXORULE_S01_TC01_AddMark_as_ReadAndDeleteRule()
        {
            this.CheckMAPIHTTPTransportSupported();

            #region TestUser1 prepares value for rule properties variable.
            RuleProperties ruleProperties = AdapterHelper.GenerateRuleProperties(this.Site, Constants.RuleNameMarkAsRead);
            #endregion

            #region TestUser1 creates a new folder in the Inbox folder.
            RopCreateFolderResponse createFolderResponse;
            string testFolderName = Common.GenerateResourceName(this.Site, Constants.FolderDisplayName);
            uint newFolderHandle = this.OxoruleAdapter.RopCreateFolder(this.InboxFolderHandle, testFolderName, Constants.FolderComment, out createFolderResponse);
            #endregion

            #region TestUser1 gets the value of PidTagHasRules of the newly created folder before adding a new rule.
            PropertyTag pidTagHasRules = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagHasRules,
                PropertyType = (ushort)PropertyType.PtypBoolean
            };
            RopGetPropertiesSpecificResponse getPropertiesSpecificResponse = this.OxoruleAdapter.RopGetPropertiesSpecific(newFolderHandle, new PropertyTag[] { pidTagHasRules });
            Site.Assert.AreEqual<uint>(0, getPropertiesSpecificResponse.ReturnValue, "Getting PidTagHasRules property should succeed.");

            // Use a variable to note whether the newly created folder has rules before adding the new rule to it.
            bool pidTagHasRulesBeforeAdd = false;
            if (getPropertiesSpecificResponse.RowData.PropertyValues != null && getPropertiesSpecificResponse.RowData.PropertyValues.Count > 0)
            {
                // The flag field set to 0x00 means all the queried property values are present and without error as specified in MS-OXCDATA section 2.8.1.1.
                if (getPropertiesSpecificResponse.RowData.Flag == 0x00)
                {
                    pidTagHasRulesBeforeAdd = BitConverter.ToBoolean(getPropertiesSpecificResponse.RowData.PropertyValues[0].Value, 0);
                }
            }

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

                // Verify MS-OXORULE requirement: MS-OXORULE_8851.
                // There are no rules for the newly created folder before adding rule to it, so the pidtaghasrules property must be false
                Site.CaptureRequirementIfIsFalse(
                    pidTagHasRulesBeforeAdd,
                    8851,
                    @"[[In Appendix A: Product Behavior] Implementation does set PidTagHasRules to ""FALSE"" if no rule (2) is set on a folder. (Exchange 2007, Exchange 2010 and Exchange 2016 follow this behavior.)");
            }
            #endregion

            #region TestUser1 generates test RuleData.
            RuleData ruleForMarkRead = AdapterHelper.GenerateValidRuleData(ActionType.OP_MARK_AS_READ, TestRuleDataType.ForAdd, 1, RuleState.ST_ENABLED, new DeleteMarkReadActionData(), ruleProperties, null);
            ruleProperties.Name = Common.GenerateResourceName(this.Site, Constants.RuleNameDelete);

            // Add rule for delete without rule Provider Data.
            ruleProperties.ProviderData = string.Empty;
            RuleData ruleForDelete = AdapterHelper.GenerateValidRuleData(ActionType.OP_DELETE, TestRuleDataType.ForAdd, 0, RuleState.ST_ENABLED, new DeleteMarkReadActionData(), ruleProperties, null);
            #endregion

            #region TestUser1 adds OP_MARK_AS_READ and OP_DELETE rules to the newly created folder.
            RopModifyRulesResponse modifyRulesResponse = this.OxoruleAdapter.RopModifyRules(newFolderHandle, ModifyRuleFlag.Modify_ReplaceAll, new RuleData[] { ruleForDelete, ruleForMarkRead });

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

            // Verify MS-OXORULE requirement: MS-OXORULE_R596.
            // If the return value of the RopModifyRules ROP is 0x00000000, it means server parses the request successfully, and this requirement can be verified.
            Site.CaptureRequirementIfAreEqual<uint>(
                0x00000000,
                modifyRulesResponse.ReturnValue,
                596,
                @"[In Receiving a RopModifyRules ROP Request] If the server successfully parses the data in the request buffer and is able to process all requests for adding, modifying, and deleting rules (2) present in the request buffer, the server MUST return 0x00000000 as the value of the ReturnValue field in the response buffer.");
            #endregion

            #region TestUser1 gets the value of PidTagHasRules of the newly created folder after adding rules.
            if (Common.IsRequirementEnabled(7202, this.Site))
            {
                getPropertiesSpecificResponse = this.OxoruleAdapter.RopGetPropertiesSpecific(newFolderHandle, new PropertyTag[] { pidTagHasRules });
                Site.Assert.AreEqual<uint>(0, getPropertiesSpecificResponse.ReturnValue, "Getting PidTagHasRules property should succeed.");

                // Use a variable to note whether the newly created folder has rules after add two rules to it.
                bool pidTagHasRulesAfterAdd = false;
                if (getPropertiesSpecificResponse.RowData.PropertyValues != null && getPropertiesSpecificResponse.RowData.PropertyValues.Count > 0)
                {
                    pidTagHasRulesAfterAdd = BitConverter.ToBoolean(getPropertiesSpecificResponse.RowData.PropertyValues[0].Value, 0);
                }

                // Add the debug information.
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R7202");
                Site.CaptureRequirementIfIsTrue(
                    pidTagHasRulesAfterAdd,
                    7202,
                    @"[[In Appendix A: Product Behavior] Implementation does set PidTagHasRules to ""TRUE"" if any rules (2) are set on a folder. (Exchange 2007, Exchange 2010 and Exchange 2016 follow this behavior.)");
            }
            #endregion

            #region TestUser1 calls RopGetRulesTable to get the rules table.
            RopGetRulesTableResponse ropGetRulesTableResponse;
            uint ruleTableHandle = this.OxoruleAdapter.RopGetRulesTable(newFolderHandle, TableFlags.Normal, out ropGetRulesTableResponse);
            Site.Assert.AreEqual<uint>(0, ropGetRulesTableResponse.ReturnValue, "RopGetRulesTable operation should success.");

            #region Capture Code

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

            // Verify MS-OXORULE requirement: MS-OXORULE_R133.
            Site.CaptureRequirementIfAreEqual<uint>(
                0x00000000,
                ropGetRulesTableResponse.ReturnValue,
                133,
                @"[In RopGetRulesTable ROP Response Buffer] ReturnValue (4 bytes): To indicate success, the server returns 0x00000000.");

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

            // Verify MS-OXORULE requirement: MS-OXORULE_R611.
            Site.CaptureRequirementIfAreEqual<uint>(
                0x00000000,
                ropGetRulesTableResponse.ReturnValue,
                611,
                @"[In Receiving a RopGetRulesTable ROP Request] If the server successfully parses the data in the ROP request buffer, it MUST return 0x00000000 as the value of the ReturnValue field in the response buffer.");
            #endregion
            #endregion

            #region TestUser1 retrieves rule information for the newly added rule.
            PropertyTag[] propertyTags = this.GenerateRuleInfoProperties();

            // Retrieves rows from the rule table.
            RopQueryRowsResponse queryRowResponse = this.OxoruleAdapter.QueryPropertiesInTable(ruleTableHandle, propertyTags);
            Site.Assert.AreEqual<uint>(0, queryRowResponse.ReturnValue, "Retrieving rows from the rule table should succeed.");

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R612, the return table handle actual is:{0}", ruleTableHandle.ToString());

            // Verify MS-OXORULE requirement: MS-OXORULE_R612.
            // There are only two rules on the newly created folder added by the test suite.
            // If the value of the RowCount field is 2, it means that when using the table handle returned from the server to get the rules, the rules can be got.
            // So the returned table handle is a valid handle, and this requirement can be verified.
            Site.CaptureRequirementIfAreEqual<uint>(
                2,
                queryRowResponse.RowCount,
                612,
                @"[In Receiving a RopGetRulesTable ROP Request] If the server successfully parses the data in the ROP request buffer, it MUST return a valid table handle through which the client can access the folder rules (2) using table specific ROPs defined in [MS-OXCTABL].");

            // Get PidTagRuleName's value from the specific RuleData.
            TaggedPropertyValue ruleNameProperty = new TaggedPropertyValue();
            foreach (PropertyValue value in ruleForMarkRead.PropertyValues)
            {
                if (((TaggedPropertyValue)value).PropertyTag.PropertyId == (ushort)PropertyId.PidTagRuleName)
                {
                    ruleNameProperty = (TaggedPropertyValue)value;
                    break;
                }
            }

            // Get the property row of the specific rule.
            PropertyRow propertyRow = null;
            if (queryRowResponse.RowData.PropertyRows != null)
            {
                foreach (PropertyRow propRow in queryRowResponse.RowData.PropertyRows)
                {
                    if (Common.CompareByteArray(propRow.PropertyValues[0].Value, ruleNameProperty.Value))
                    {
                        propertyRow = propRow;
                        break;
                    }
                }
            }

            // Get the rule's rule ID.
            byte[] byteRuleIDValue = this.GetPropertyFromList(PropertyId.PidTagRuleId, propertyRow, propertyTags);
            ulong ruleIDForMarkRead = BitConverter.ToUInt64(byteRuleIDValue, 0);

            // Get the rule's Provider data.
            byte[] byteRuleProviderData = this.GetPropertyFromList(PropertyId.PidTagRuleProviderData, propertyRow, propertyTags);

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

            // Verify MS-OXORULE requirement: MS-OXORULE_R100.
            // If the property value of PidTagRuleProviderData is equal to the value saved in Util.cs file, it means that the server has preserved the RuleProviderData.
            bool isVerifyR100 = Common.GetStringFromBinary(byteRuleProviderData, true).Equals(Constants.PidTagRuleProviderData, StringComparison.CurrentCultureIgnoreCase);

            Site.CaptureRequirementIfIsTrue(
                isVerifyR100,
                100,
                @"[In PidTagRuleProviderData Property] The server is to preserve this value [is contained by PidTagRuleUserFlags Property] if set by the client.");

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

            // Verify MS-OXORULE requirement: MS-OXORULE_R122.
            // queryRowResponse will return all the rules in the table. Here will return two rules that has been added above.
            // So if the value of RowCount is 0x0002, it means the server has returned all the standard rules associated with the given folder.
            Site.CaptureRequirementIfAreEqual<uint>(
                0x0002,
                queryRowResponse.RowCount,
                122,
                @"[In RopGetRulesTable ROP] The table returned by the server is required to contain all standard rules associated with a given folder.");

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R123, the RowCount is {0}", queryRowResponse.RowData.Count);

            // Verify MS-OXORULE requirement: MS-OXORULE_R123.
            // If the value of RowData in queryRowResponse is not null and the count of the RowData is equal to RowCount, it means each row represents one rule.
            bool isVerifyR123 = queryRowResponse.RowData != null && queryRowResponse.RowData.Count == queryRowResponse.RowCount;

            Site.CaptureRequirementIfIsTrue(
                isVerifyR123,
                123,
                @"[In RopGetRulesTable ROP] Each row in the table MUST represent one rule (2).");

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R597, the rule id is:{0}", ruleIDForMarkRead.ToString());

            // Verify MS-OXORULE requirement: MS-OXORULE_R597.
            bool isVerifyR597 = ruleIDForMarkRead != 0x0000000000000000;

            Site.CaptureRequirementIfIsTrue(
                isVerifyR597,
                597,
                @"[In Receiving a RopModifyRules ROP Request] The server MUST assign a value for the PidTagRuleId property (section 2.2.7.8) for each rule (2) that has been added by the RopModifyRules ROP request.");

            byte[] valueRuleUserFlagsRetrieved = this.GetPropertyFromList(PropertyId.PidTagRuleUserFlags, propertyRow, propertyTags);

            // BitConverter.ToInt32() is used to convert a byte array to a int value from the byte array index of 0.
            int ruleUserFlagsRetrieved = BitConverter.ToInt32(valueRuleUserFlagsRetrieved, 0);

            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R96 , the rule flag set is :{0}, the rule flag get is:{1}", ruleProperties.UserFlag, Convert.ToString(ruleUserFlagsRetrieved));

            // Verify MS-OXORULE requirement: MS-OXORULE_R96.
            // UserFlag represents the PidTagRuleUserFlags set by the client, and ruleUserFlagsRetrieved represents 
            // the PidTagRuleUserFlags set by the server. If they are equal to each other, it means the server preserves this value. 
            Site.CaptureRequirementIfAreEqual<string>(
                ruleProperties.UserFlag,
                Convert.ToString(ruleUserFlagsRetrieved),
                96,
                @"[In PidTagRuleUserFlags Property] The server is to preserve this value [is contained by PidTagRuleUserFlags Property] if set by the client.");
            #endregion
            #endregion

            #region TestUser1 gets ruleActions of the two rules.
            ruleTableHandle = this.OxoruleAdapter.RopGetRulesTable(newFolderHandle, TableFlags.Normal, out ropGetRulesTableResponse);
            Site.Assert.AreEqual<uint>(0, ropGetRulesTableResponse.ReturnValue, "Getting rule table should succeed.");

            PropertyTag actionsTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagRuleActions,
                PropertyType = (ushort)PropertyType.PtypRuleAction
            };

            // Set the query target to standardardRules.
            this.OxoruleAdapter.TargetOfRop = TargetOfRop.ForStandardRules;

            RopQueryRowsResponse getAllActionsResponse = this.OxoruleAdapter.QueryPropertiesInTable(ruleTableHandle, new PropertyTag[1] { actionsTag });
            Site.Assert.AreEqual<uint>(0, getAllActionsResponse.ReturnValue, "Getting the rule actions should succeed.");

            // Two rules have been added to the newly created folder, so the row count in the rule table should be 2.
            Site.Assert.AreEqual<uint>(2, getAllActionsResponse.RowCount, "The rule number in the rule table is {0}", getAllActionsResponse.RowCount);
            this.VerifyRuleTable();
            #endregion

            #region Delete the created folder and clear the status of the adapter.
            RopDeleteFolderResponse deleteFolder = this.OxoruleAdapter.RopDeleteFolder(this.InboxFolderHandle, createFolderResponse.FolderId);
            Site.Assert.AreEqual<uint>(0, deleteFolder.ReturnValue, "Deleting folder should succeed.");

            // Clear the status of the adapter.
            this.OxoruleAdapter.TargetOfRop = TargetOfRop.OtherTarget;
            #endregion
        }
        /// <summary>
        /// Initialize the taggedPropertyValuesDictionary.
        /// </summary>
        private void InitialTaggedPropertyValuesDictionary()
        {
            TaggedPropertyValue propertyvalue = new TaggedPropertyValue
            {
                PropertyTag = new PropertyTag(0x3001, 0x001F),
                Value = Encoding.Unicode.GetBytes("TestDisplayName" + "\0")
            };

            // PidTagDisplayName
            this.taggedPropertyValuesDictionary.Add("PidTagDisplayName", propertyvalue);

            // PidTagMessageClass
            propertyvalue = new TaggedPropertyValue
            {
                PropertyTag = new PropertyTag(0x001A, 0x001F),
                Value = Encoding.Unicode.GetBytes("IPM.Note" + "\0")
            };
            this.taggedPropertyValuesDictionary.Add("PidTagMessageClass", propertyvalue);

            // PidTagAccess
            propertyvalue = new TaggedPropertyValue
            {
                PropertyTag = new PropertyTag(0x0FF4, 0x0003)
            };
            int propertyValue = 0x02;
            propertyvalue.Value = BitConverter.GetBytes(propertyValue);
            this.taggedPropertyValuesDictionary.Add("PidTagAccess", propertyvalue);

            // PidTagAccessLevel
            propertyvalue = new TaggedPropertyValue
            {
                PropertyTag = new PropertyTag(0x0FF7, 0x0003)
            };

            propertyValue = 0x00;
            propertyvalue.Value = BitConverter.GetBytes(propertyValue);
            this.taggedPropertyValuesDictionary.Add("PidTagAccessLevel", propertyvalue);

            // PidTagCreationTime
            propertyvalue = new TaggedPropertyValue
            {
                PropertyTag = new PropertyTag(0x3007, 0x0040),
                Value = BitConverter.GetBytes(DateTime.UtcNow.ToFileTimeUtc())
            };
            this.taggedPropertyValuesDictionary.Add("PidTagCreationTime", propertyvalue);

            // PidTagBody
            propertyvalue = new TaggedPropertyValue
            {
                PropertyTag = new PropertyTag(0x1000, 0x001F),
                Value = Encoding.Unicode.GetBytes("hello" + "\0")
            };

            this.taggedPropertyValuesDictionary.Add("PidTagBody", propertyvalue);

            // PidTagFolderType
            propertyvalue = new TaggedPropertyValue
            {
                PropertyTag = new PropertyTag(0x3601, 0x0003),
                Value = new byte[]
                {
                    0x01, 0x00, 0x00, 0x00
                }
            };

            // FOLDER_GENERIC
            this.taggedPropertyValuesDictionary.Add("PidTagFolderType", propertyvalue);
        }
        /// <summary>
        /// Create property value samples.
        /// </summary>
        /// <returns>A property value array.</returns>
        private TaggedPropertyValue[] CreateSamplePropertyValues()
        {
            // Step 1: Send the RopGetLocalReplicaIds request to reserve a range of IDs to be used by a local replica.
            #region RopGetLocalReplicaIds

            TaggedPropertyValue[] propertyValues = new TaggedPropertyValue[4];
            TaggedPropertyValue propertyValue;

            // PidTagSourceKey
            propertyValue = new TaggedPropertyValue
            {
                PropertyTag =
                {
                    PropertyId = this.propertyDictionary[PropertyNames.PidTagSourceKey].PropertyId,
                    PropertyType = this.propertyDictionary[PropertyNames.PidTagSourceKey].PropertyType
                }
            };

            byte[] sample = new byte[24];
            
            // The combination of first two bytes (0x0016) indicates the length of value field.
            sample[0] = 0x16;
            sample[1] = 0x00;

            RopGetLocalReplicaIdsRequest ropGetLocalReplicaIdsRequest;
            RopGetLocalReplicaIdsResponse ropGetLocalReplicaIdsResponse;

            ropGetLocalReplicaIdsRequest.IdCount = 2;
            ropGetLocalReplicaIdsRequest.InputHandleIndex = TestSuiteBase.InputHandleIndex0;
            ropGetLocalReplicaIdsRequest.LogonId = TestSuiteBase.LogonId;
            ropGetLocalReplicaIdsRequest.RopId = (byte)RopId.RopGetLocalReplicaIds;

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Step 1: Begin to send the RopGetLocalReplicaIds request in CreateSamplePropertyValues method.");

            // Send the RopGetLocalReplicaIds request to reserve a range of IDs to be used by a local replica.
            this.responseSOHs = cropsAdapter.ProcessSingleRop(
                ropGetLocalReplicaIdsRequest,
                this.inputObjHandle,
                ref this.response,
                ref this.rawData,
                RopResponseType.SuccessResponse);
            ropGetLocalReplicaIdsResponse = (RopGetLocalReplicaIdsResponse)response;

            #endregion

            // Step 2: Construct the property value samples.
            #region Construct the property value samples

            Array.Copy(ropGetLocalReplicaIdsResponse.ReplGuid, 0, sample, 2, 16);
            Array.Copy(ropGetLocalReplicaIdsResponse.GlobalCount, 0, sample, 18, 6);
            propertyValue.Value = sample;
            propertyValues[0] = propertyValue;

            // PidTagLastModificationTime
            propertyValue = new TaggedPropertyValue();
            byte[] sampleForPidTagLastModificationTime = { 154, 148, 234, 120, 114, 202, 202, 1 };

            propertyValue.PropertyTag.PropertyId = this.propertyDictionary[PropertyNames.PidTagLastModificationTime].PropertyId;
            propertyValue.PropertyTag.PropertyType = this.propertyDictionary[PropertyNames.PidTagLastModificationTime].PropertyType;
            propertyValue.Value = sampleForPidTagLastModificationTime;
            propertyValues[1] = propertyValue;
            propertyValue = new TaggedPropertyValue
            {
                PropertyTag =
                {
                    PropertyId = this.propertyDictionary[PropertyNames.PidTagChangeKey].PropertyId,
                    PropertyType = this.propertyDictionary[PropertyNames.PidTagChangeKey].PropertyType
                }
            };

            byte[] sampleForPidTagChangeKey = new byte[22];
            byte[] guid = Guid.NewGuid().ToByteArray();

            // The combination of first two bytes (0x0014) indicates the length of value field.
            sampleForPidTagChangeKey[0] = 0x14;
            sampleForPidTagChangeKey[1] = 0x00;

            Array.Copy(guid, 0, sampleForPidTagChangeKey, 2, 16);
            propertyValue.Value = sampleForPidTagChangeKey;

            propertyValues[2] = propertyValue;

            // PidTagPredecessorChangeList
            propertyValue = new TaggedPropertyValue
            {
                PropertyTag =
                {
                    PropertyId = this.propertyDictionary[PropertyNames.PidTagPredecessorChangeList].PropertyId,
                    PropertyType = this.propertyDictionary[PropertyNames.PidTagPredecessorChangeList].PropertyType
                }
            };

            byte[] sampleForPidTagPredecessorChangeList = 
            { 
                0x17, 0x00, 0x16, 0x19, 0xD7,
                0xFB, 0x0F, 0x06, 0x16, 0xA1,
                0x41, 0xBF, 0xF6, 0x91, 0xC7,
                0x63, 0xDA, 0xA8, 0x66, 0x00,
                0x00, 0x00, 0x78, 0x4D, 0x1C 
            };
            propertyValue.Value = sampleForPidTagPredecessorChangeList;
            propertyValues[3] = propertyValue;
            return propertyValues;

            #endregion
        }
        /// <summary>
        /// Create values for SynchronizationImportHierarchyChange.
        /// </summary>
        /// <param name="serverId">server id.</param>
        /// <param name="folderIdIndex">Folder id index.</param>
        /// <param name="parentFolderHandleIndex">Parent folder handle index.</param>
        /// <param name="folderId">Folder id.</param>
        /// <param name="conflictType">Conflict type </param>
        /// <returns>Return the constructed hierarchy values.</returns>
        private TaggedPropertyValue[] CreateSampleHierarchyValues(int serverId, int folderIdIndex, int parentFolderHandleIndex, out ulong folderId, ConflictTypes conflictType)
        {
            folderId = 0;
            TaggedPropertyValue[] hierarchyValues = new TaggedPropertyValue[6];
            TaggedPropertyValue propertyValue = new TaggedPropertyValue();
            byte[] currentChangeNumber = new byte[6];

            // PidTagParentSourceKey equal to the PidTagSourceKey of the parent folder
            propertyValue = new TaggedPropertyValue
            {
                PropertyTag = new PropertyTag(0x65E1, 0x0102)
            };

            Sequence<string> propertyTag = new Sequence<string>("PidTagSourceKey");
            this.GetPropertiesSpecific(serverId, parentFolderHandleIndex, propertyTag);
            propertyValue.Value = this.propertyValuesSpecific["PidTagSourceKey"];
            hierarchyValues[0] = propertyValue;

            if (conflictType == ConflictTypes.NONE)
            {
                // Whether the hierarchy already exists.
                if (this.objectIdContainer.ContainsKey(folderIdIndex))
                {
                    // Construct PidTagSourceKey value.
                    propertyValue = new TaggedPropertyValue
                    {
                        PropertyTag = new PropertyTag(0x65E0, 0x0102)
                    };

                    byte[] sampleForPidTagSourceKey = this.propertyValuesSpecific["PidTagSourceKey"];
                    propertyValue.Value = sampleForPidTagSourceKey;
                    hierarchyValues[1] = propertyValue;

                    folderId = this.objectIdContainer[folderIdIndex];

                    // Construct PidTagLastModificationTime value.
                    propertyValue = new TaggedPropertyValue
                    {
                        PropertyTag = new PropertyTag(0x3008, 0x0040)
                    };

                    byte[] sampleForPidTagLastModificationTime = BitConverter.GetBytes(DateTime.Now.ToFileTimeUtc());
                    propertyValue.Value = sampleForPidTagLastModificationTime;
                    hierarchyValues[2] = propertyValue;

                    // Construct PidTagChangeKey value.
                    propertyValue = new TaggedPropertyValue
                    {
                        PropertyTag = new PropertyTag(0x65E2, 0x0102)
                    };

                    byte[] sampleForPidTagChangeKey = this.propertyValuesSpecific["PidTagChangeKey"];

                    // Modify ChangeKey to generate a new ChangeKey.
                    byte[] temp = new byte[4];
                    Array.Copy(sampleForPidTagChangeKey, sampleForPidTagChangeKey.Length - 4, temp, 0, 4);
                    Array.Reverse(temp);
                    int add = BitConverter.ToInt32(temp, 0);

                    // Modify the changeNumber to a newer version.
                    add++;
                    temp = BitConverter.GetBytes(add);
                    Array.Reverse(temp);
                    Array.Copy(temp, 0, sampleForPidTagChangeKey, sampleForPidTagChangeKey.Length - 4, 4);
                    propertyValue.Value = sampleForPidTagChangeKey;
                    hierarchyValues[3] = propertyValue;

                    // Construct PidTagPredecessorChangeList value
                    propertyValue = new TaggedPropertyValue
                    {
                        PropertyTag = new PropertyTag(0x65E3, 0x0102)
                    };

                    byte[] sampleForPidTagPredecessorChangeList = new byte[this.propertyValuesSpecific["PidTagPredecessorChangeList"].Length + sampleForPidTagChangeKey.Length];
                    Array.Copy(this.propertyValuesSpecific["PidTagPredecessorChangeList"], 0, sampleForPidTagPredecessorChangeList, 0, this.propertyValuesSpecific["PidTagPredecessorChangeList"].Length);
                    Array.Copy(sampleForPidTagChangeKey, 0, sampleForPidTagPredecessorChangeList, this.propertyValuesSpecific["PidTagPredecessorChangeList"].Length, sampleForPidTagChangeKey.Length);
                    propertyValue.Value = sampleForPidTagPredecessorChangeList;
                    hierarchyValues[4] = propertyValue;
                }
                else if (folderIdIndex == 0)
                {
                    // Get a local id from the id set given by server.
                    byte[] sub = new byte[4];
                    byte[] currentLocalId = this.localId;
                    Array.Copy(currentLocalId, 2, sub, 0, currentLocalId.Length - 2);
                    Array.Reverse(sub);
                    int totalNum = BitConverter.ToInt32(sub, 0);
                    totalNum += this.localIdOffSet;
                    sub = BitConverter.GetBytes(totalNum);
                    Array.Reverse(sub);
                    Array.Copy(sub, 0, currentLocalId, 2, currentLocalId.Length - 2);
                    this.localIdOffSet++;

                    // Construct PidTagSourceKey value.
                    propertyValue = new TaggedPropertyValue
                    {
                        PropertyTag = new PropertyTag(0x65E0, 0x0102)
                    };

                    byte[] sampleForPidTagSourceKey = new byte[24];
                    int length = 0;
                    int index = 0;

                    // The combination of first two bytes indicates the length of value field.
                    length = (short)(this.serverReplicaGuid.ToByteArray().Length + currentLocalId.Length);
                    Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagSourceKey, 0, sizeof(short));
                    index += sizeof(short);
                    Array.Copy(this.serverReplicaGuid.ToByteArray(), 0, sampleForPidTagSourceKey, index, this.serverReplicaGuid.ToByteArray().Length);
                    index += this.serverReplicaGuid.ToByteArray().Length;
                    Array.Copy(currentLocalId, 0, sampleForPidTagSourceKey, index, currentLocalId.Length);
                    Array.Copy(currentLocalId, 0, currentChangeNumber, 0, currentLocalId.Length);
                    propertyValue.Value = sampleForPidTagSourceKey;
                    hierarchyValues[1] = propertyValue;

                    // Convert long term id to id .
                    LongTermId longTermId = new LongTermId
                    {
                        DatabaseGuid = this.serverReplicaGuid.ToByteArray(),
                        GlobalCounter = currentLocalId
                    };
                    folderId = this.GetIdFromLongTerm(serverId, longTermId);

                    // Construct PidTagLastModificationTime value.
                    propertyValue = new TaggedPropertyValue
                    {
                        PropertyTag = new PropertyTag(0x3008, 0x0040)
                    };

                    byte[] sampleForPidTagLastModificationTime = BitConverter.GetBytes(DateTime.Now.ToFileTimeUtc());
                    propertyValue.Value = sampleForPidTagLastModificationTime;
                    hierarchyValues[2] = propertyValue;

                    // Construct PidTagChangeKey value.
                    propertyValue = new TaggedPropertyValue
                    {
                        PropertyTag = new PropertyTag(0x65E2, 0x0102)
                    };

                    byte[] sampleForPidTagChangeKey = new byte[24];
                    index = 0;
                    length = 0;
                    length = (short)GidLength;

                    // The combination of first two bytes indicates the length of value field.
                    Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagChangeKey, 0, sizeof(short));
                    index += sizeof(short);
                    Array.Copy(this.localReplicaGuid.ToByteArray(), 0, sampleForPidTagChangeKey, index, this.localReplicaGuid.ToByteArray().Length);
                    index += this.localReplicaGuid.ToByteArray().Length;
                    Array.Copy(currentChangeNumber, 0, sampleForPidTagChangeKey, index, currentChangeNumber.Length);
                    propertyValue.Value = sampleForPidTagChangeKey;
                    hierarchyValues[3] = propertyValue;

                    // Construct PidTagPredecessorChangeList value
                    propertyValue = new TaggedPropertyValue
                    {
                        PropertyTag = new PropertyTag(0x65E3, 0x0102)
                    };

                    byte[] sampleForPidTagPredecessorChangeList = new byte[25];
                    index = 0;
                    length = 0;
                    length = (short)(GidLength + 1);
                    Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagPredecessorChangeList, 0, sizeof(short));
                    index += sizeof(short);
                    sampleForPidTagPredecessorChangeList[2] = Convert.ToByte(this.localReplicaGuid.ToByteArray().Length + currentChangeNumber.Length); // 16
                    index += 1;
                    Array.Copy(this.localReplicaGuid.ToByteArray(), 0, sampleForPidTagPredecessorChangeList, index, this.localReplicaGuid.ToByteArray().Length);
                    index += this.localReplicaGuid.ToByteArray().Length;
                    Array.Copy(currentChangeNumber, 0, sampleForPidTagPredecessorChangeList, index, currentChangeNumber.Length);
                    propertyValue.Value = sampleForPidTagPredecessorChangeList;
                    hierarchyValues[4] = propertyValue;
                }
            }
            else
            {
                // Get a local id from the id set given by server.
                byte[] sub = new byte[4];
                byte[] currentLocalId = this.localId;
                Array.Copy(currentLocalId, 2, sub, 0, currentLocalId.Length - 2);
                Array.Reverse(sub);
                int totalNum = BitConverter.ToInt32(sub, 0);
                totalNum += this.localIdOffSet;
                sub = BitConverter.GetBytes(totalNum);
                Array.Reverse(sub);
                Array.Copy(sub, 0, currentLocalId, 2, currentLocalId.Length - 2);
                this.localIdOffSet++;

                // Construct PidTagSourceKey value.
                propertyValue = new TaggedPropertyValue
                {
                    PropertyTag = new PropertyTag(0x65E0, 0x0102)
                };

                byte[] sampleForPidTagSourceKey = new byte[24];
                int length = 0;
                int index = 0;

                // The combination of first two bytes indicates the length of value field.
                length = (short)(this.serverReplicaGuid.ToByteArray().Length + currentLocalId.Length);
                Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagSourceKey, 0, sizeof(short));
                index += sizeof(short);
                Array.Copy(this.serverReplicaGuid.ToByteArray(), 0, sampleForPidTagSourceKey, index, this.serverReplicaGuid.ToByteArray().Length);
                index += this.serverReplicaGuid.ToByteArray().Length;
                Array.Copy(currentLocalId, 0, sampleForPidTagSourceKey, index, currentLocalId.Length);
                Array.Copy(currentLocalId, 0, currentChangeNumber, 0, currentLocalId.Length);
                propertyValue.Value = sampleForPidTagSourceKey;
                hierarchyValues[1] = propertyValue;

                // Convert long term id to id .
                LongTermId longTermId = new LongTermId
                {
                    DatabaseGuid = this.serverReplicaGuid.ToByteArray(),
                    GlobalCounter = currentLocalId
                };
                folderId = this.GetIdFromLongTerm(serverId, longTermId);

                // Construct PidTagLastModificationTime value.
                propertyValue = new TaggedPropertyValue
                {
                    PropertyTag = new PropertyTag(0x3008, 0x0040)
                };

                byte[] sampleForPidTagLastModificationTime = BitConverter.GetBytes(DateTime.Now.ToFileTimeUtc());
                propertyValue.Value = sampleForPidTagLastModificationTime;
                hierarchyValues[2] = propertyValue;

                // Construct PidTagChangeKey value.
                propertyValue = new TaggedPropertyValue
                {
                    PropertyTag = new PropertyTag(0x65E2, 0x0102)
                };

                byte[] sampleForPidTagChangeKey = new byte[24];
                index = 0;
                length = 0;
                length = (short)GidLength;

                // The combination of first two bytes indicates the length of value field.
                Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagChangeKey, 0, sizeof(short));
                index += sizeof(short);
                Array.Copy(this.localReplicaGuid.ToByteArray(), 0, sampleForPidTagChangeKey, index, this.localReplicaGuid.ToByteArray().Length);
                index += this.localReplicaGuid.ToByteArray().Length;
                Array.Copy(currentChangeNumber, 0, sampleForPidTagChangeKey, index, currentChangeNumber.Length);
                propertyValue.Value = sampleForPidTagChangeKey;
                hierarchyValues[3] = propertyValue;

                // Construct PidTagPredecessorChangeList value
                propertyValue = new TaggedPropertyValue
                {
                    PropertyTag = new PropertyTag(0x65E3, 0x0102)
                };

                byte[] sampleForPidTagPredecessorChangeList;

                if (conflictType == ConflictTypes.AINCLUDEB)
                {
                    sampleForPidTagPredecessorChangeList = new byte[25];
                    index = 0;
                    length = 0;
                    length = (short)(GidLength + 1);

                    Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagPredecessorChangeList, 0, sizeof(short));
                    index += sizeof(short);
                    sampleForPidTagPredecessorChangeList[2] = Convert.ToByte(this.localReplicaGuid.ToByteArray().Length + currentChangeNumber.Length); // 16
                    index += 1;
                    Array.Copy(this.localReplicaGuid.ToByteArray(), 0, sampleForPidTagPredecessorChangeList, index, this.localReplicaGuid.ToByteArray().Length);
                    index += this.localReplicaGuid.ToByteArray().Length;
                    Array.Copy(currentChangeNumber, 0, sampleForPidTagPredecessorChangeList, index, currentChangeNumber.Length);

                    this.lastConflictInfo.PCLB = sampleForPidTagPredecessorChangeList;
                    sampleForPidTagPredecessorChangeList[24] += 1;
                    this.lastConflictInfo.PCLA = sampleForPidTagPredecessorChangeList;
                    this.lastConflictInfo.PCLXFromMath = sampleForPidTagPredecessorChangeList;
                    this.lastConflictInfo.DetectedResult = conflictType;

                    propertyValue.Value = sampleForPidTagPredecessorChangeList;
                    hierarchyValues[4] = propertyValue;
                }
                else if (conflictType == ConflictTypes.BINCLUDEA)
                {
                    sampleForPidTagPredecessorChangeList = new byte[25];
                    index = 0;
                    length = 0;
                    length = (short)(GidLength + 1);

                    Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagPredecessorChangeList, 0, sizeof(short));
                    index += sizeof(short);
                    sampleForPidTagPredecessorChangeList[2] = Convert.ToByte(this.localReplicaGuid.ToByteArray().Length + currentChangeNumber.Length); // 16
                    index += 1;
                    Array.Copy(this.localReplicaGuid.ToByteArray(), 0, sampleForPidTagPredecessorChangeList, index, this.localReplicaGuid.ToByteArray().Length);
                    index += this.localReplicaGuid.ToByteArray().Length;
                    Array.Copy(currentChangeNumber, 0, sampleForPidTagPredecessorChangeList, index, currentChangeNumber.Length);

                    this.lastConflictInfo.PCLB = sampleForPidTagPredecessorChangeList;
                    this.lastConflictInfo.PCLXFromMath = sampleForPidTagPredecessorChangeList;
                    sampleForPidTagPredecessorChangeList[24] -= 1;
                    this.lastConflictInfo.PCLA = sampleForPidTagPredecessorChangeList;
                    this.lastConflictInfo.DetectedResult = conflictType;

                    propertyValue.Value = sampleForPidTagPredecessorChangeList;
                    hierarchyValues[4] = propertyValue;
                }

                if (conflictType == ConflictTypes.CONFLICT)
                {
                    // If the versions from client and server are in conflict, the value of PidTagPredecessorChangeList property in client should not include 
                    // the one in server. And the changelist value in server should not include or be equal to the one in client, which means the changelist value in client 
                    // should be different with server, just like the second example in section 4.6.2.
                    sampleForPidTagPredecessorChangeList = new byte[25];
                    index = 0;
                    length = 0;
                    length = (short)(GidLength + 1);
                    Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagPredecessorChangeList, 0, sizeof(short));
                    index += sizeof(short);
                    sampleForPidTagPredecessorChangeList[2] = Convert.ToByte(this.localReplicaGuid.ToByteArray().Length + currentChangeNumber.Length); // 16
                    index += 1;
                    Array.Copy(this.localReplicaGuid.ToByteArray(), 0, sampleForPidTagPredecessorChangeList, index, this.localReplicaGuid.ToByteArray().Length);
                    index += this.localReplicaGuid.ToByteArray().Length;
                    Array.Copy(currentChangeNumber, 0, sampleForPidTagPredecessorChangeList, index, currentChangeNumber.Length);
                    this.lastConflictInfo.PCLB = sampleForPidTagPredecessorChangeList;

                    // The parameter change is used to save the changelist value in client.
                    byte[] change = new byte[48];
                    Array.Copy(BitConverter.GetBytes(46), 0, change, 0, sizeof(short));
                    Array.Copy(sampleForPidTagPredecessorChangeList, 2, change, 2, 23);
                    Array.Copy(BitConverter.GetBytes(22), 0, change, 25, sizeof(short));

                    // Modify the value of PidTagPredecessorChangeList property in client via adding one in GUID field and adding one in GLOBCNT field.
                    byte[] namespaceGuidPartValue = new byte[8];
                    Array.Copy(sampleForPidTagPredecessorChangeList, 10, namespaceGuidPartValue, 2, namespaceGuidPartValue.Length - 2);
                    Array.Reverse(namespaceGuidPartValue);
                    long namespaceGuidPartValueInt = BitConverter.ToInt64(namespaceGuidPartValue, 0);
                    namespaceGuidPartValueInt += 1;
                    namespaceGuidPartValue = BitConverter.GetBytes(namespaceGuidPartValueInt);
                    Array.Reverse(namespaceGuidPartValue);
                    Array.Copy(namespaceGuidPartValue, 2, sampleForPidTagPredecessorChangeList, 10, namespaceGuidPartValue.Length - 2);
                    Array.Copy(sampleForPidTagPredecessorChangeList, 3, change, 26, 22);
                    change[47] += 1;

                    this.lastConflictInfo.PCLA = change;
                    this.lastConflictInfo.PCLXFromMath = change;
                    this.lastConflictInfo.DetectedResult = conflictType;

                    propertyValue.Value = change;
                    hierarchyValues[4] = propertyValue;
                }
            }

            // Construct PidTagDisplayName value.
            propertyValue = new TaggedPropertyValue
            {
                PropertyTag = new PropertyTag(0x3001, 0x001F)
            };

            byte[] sampleForPidTagDisplayName = new byte[Encoding.Unicode.GetByteCount("TestFolder" + "\0")];
            Array.Copy(
                Encoding.Unicode.GetBytes("TestFolder" + "\0"),
                0,
                sampleForPidTagDisplayName,
                0,
                Encoding.Unicode.GetByteCount("TestFolder" + "\0"));
            propertyValue.Value = sampleForPidTagDisplayName;
            hierarchyValues[5] = propertyValue;

            return hierarchyValues;
        }
        /// <summary>
        /// Create property values for a folder.
        /// </summary>
        /// <returns>A property value array.</returns>
        private TaggedPropertyValue[] CreateSampleFolderPropertyValues()
        {
            TaggedPropertyValue[] folderPropertyValues = new TaggedPropertyValue[1];
            TaggedPropertyValue taggedPropertyValue;

            // PidTagFolderType
            taggedPropertyValue = new TaggedPropertyValue
            {
                PropertyTag =
                {
                    PropertyId = this.propertyDictionary[PropertyNames.PidTagFolderType].PropertyId,
                    PropertyType = this.propertyDictionary[PropertyNames.PidTagFolderType].PropertyType
                }
            };

            // FOLDER_GENERIC
            byte[] sample = { 0x01, 0x00, 0x00, 0x00 };
            taggedPropertyValue.Value = sample;
            folderPropertyValues[0] = taggedPropertyValue;

            return folderPropertyValues;
        }
        /// <summary>
        /// Create values for SynchronizationImportMessageChange
        /// </summary>
        /// <param name="messageIndex">Index of Message ID.</param>
        /// <returns>Message property value of message change.</returns>
        private TaggedPropertyValue[] CreateSamplePropertyValues(int messageIndex)
        {
            byte[] changeNumber = new byte[6];
            short length = 0;
            int index = 0;

            // Send the RopGetLocalReplicaIds request to reserve a range of IDs to be used by a local replica.
            TaggedPropertyValue[] propertyValues = new TaggedPropertyValue[4];
            TaggedPropertyValue propertyValue;
            byte[] currentLocalGloabalCount = this.localId;

            // Set the message property that the message has been already existed.
            if (this.objectIdContainer.ContainsKey(messageIndex))
            {
                propertyValue = new TaggedPropertyValue
                {
                    // Construct PidTagSourceKey value.
                    PropertyTag = new PropertyTag(0x65E0, 0x0102)
                };

                byte[] sample = this.propertyValuesSpecific["PidTagSourceKey"];
                propertyValue.Value = sample;
                propertyValues[0] = propertyValue;

                // Construct PidTagLastModificationTime value.
                propertyValue = new TaggedPropertyValue();
                byte[] sampleForPidTagLastModificationTime = BitConverter.GetBytes(DateTime.Now.ToFileTimeUtc());
                propertyValue.PropertyTag = new PropertyTag(0x3008, 0x0040);

                propertyValue.Value = sampleForPidTagLastModificationTime;
                propertyValues[1] = propertyValue;

                // Construct PidTagChangeKey value.
                propertyValue = new TaggedPropertyValue
                {
                    PropertyTag = new PropertyTag(0x65E2, 0x0102)
                };

                byte[] sampleForPidTagChangeKey = this.propertyValuesSpecific["PidTagChangeKey"];

                // Modify change key
                byte[] temp = new byte[4];
                Array.Copy(sampleForPidTagChangeKey, sampleForPidTagChangeKey.Length - 4, temp, 0, 4);
                Array.Reverse(temp);
                int add = BitConverter.ToInt32(temp, 0);

                // Add change key to newer version.
                add++;
                temp = BitConverter.GetBytes(add);
                Array.Reverse(temp);
                Array.Copy(temp, 0, sampleForPidTagChangeKey, sampleForPidTagChangeKey.Length - 4, 4);
                propertyValue.Value = sampleForPidTagChangeKey;
                Array.Copy(propertyValue.Value, 2, this.importPidTagChangeKeyValue, 0, propertyValue.Value.Length - 2);
                propertyValues[2] = propertyValue;

                // Construct PidTagPredecessorChangeList value.
                byte[] tempSampleForPidTagChangeKey = new byte[sampleForPidTagChangeKey.Length - 1];
                tempSampleForPidTagChangeKey[0] = sampleForPidTagChangeKey[0];
                Array.Copy(sampleForPidTagChangeKey, 2, tempSampleForPidTagChangeKey, 1, sampleForPidTagChangeKey.Length - 2);
                propertyValue = new TaggedPropertyValue
                {
                    PropertyTag = new PropertyTag(0x65E3, 0x0102)
                };

                byte[] sampleForPidTagPredecessorChangeList = new byte[this.propertyValuesSpecific["PidTagPredecessorChangeList"].Length + tempSampleForPidTagChangeKey.Length];
                Array.Copy(this.propertyValuesSpecific["PidTagPredecessorChangeList"], 0, sampleForPidTagPredecessorChangeList, 0, this.propertyValuesSpecific["PidTagPredecessorChangeList"].Length);
                Array.Copy(tempSampleForPidTagChangeKey, 0, sampleForPidTagPredecessorChangeList, this.propertyValuesSpecific["PidTagPredecessorChangeList"].Length, tempSampleForPidTagChangeKey.Length);

                // Modify length.
                byte[] tempLength = new byte[2];
                Array.Copy(sampleForPidTagPredecessorChangeList, 0, tempLength, 0, 2);
                short lengthofData = BitConverter.ToInt16(tempLength, 0);
                lengthofData += (short)tempSampleForPidTagChangeKey.Length;
                tempLength = BitConverter.GetBytes(lengthofData);
                Array.Copy(tempLength, 0, sampleForPidTagPredecessorChangeList, 0, 2);
                propertyValue.Value = sampleForPidTagPredecessorChangeList;
                propertyValues[3] = propertyValue;
            }
            else if (messageIndex == 0)
            {
                // Construct PidTagSourceKey value.
                byte[] sub = new byte[4];
                Array.Copy(currentLocalGloabalCount, 2, sub, 0, currentLocalGloabalCount.Length - 2);
                Array.Reverse(sub);
                int totalNum = BitConverter.ToInt32(sub, 0);

                // Generate a new local id from id set got from server.
                totalNum += this.localIdOffSet;
                sub = BitConverter.GetBytes(totalNum);
                Array.Reverse(sub);
                Array.Copy(sub, 0, currentLocalGloabalCount, 2, currentLocalGloabalCount.Length - 2);
                this.localIdOffSet++;

                propertyValue = new TaggedPropertyValue
                {
                    PropertyTag = new PropertyTag(0x65E0, 0x0102)
                };

                byte[] sample = new byte[24];

                // The combination of first two bytes (0x0016) indicates the length of value field.
                length = (short)(this.serverReplicaGuid.ToByteArray().Length + currentLocalGloabalCount.Length);
                Array.Copy(BitConverter.GetBytes(length), 0, sample, index, sizeof(short));
                index += sizeof(short);
                Array.Copy(this.serverReplicaGuid.ToByteArray(), 0, sample, index, this.serverReplicaGuid.ToByteArray().Length);
                index += this.serverReplicaGuid.ToByteArray().Length;
                Array.Copy(currentLocalGloabalCount, 0, sample, index, currentLocalGloabalCount.Length);
                Array.Copy(currentLocalGloabalCount, 0, changeNumber, 0, currentLocalGloabalCount.Length);
                propertyValue.Value = sample;
                propertyValues[0] = propertyValue;
                length = 0;
                index = 0;

                // Construct PidTagLastModificationTime value.
                propertyValue = new TaggedPropertyValue();
                byte[] sampleForPidTagLastModificationTime = BitConverter.GetBytes(DateTime.Now.ToFileTimeUtc());
                propertyValue.PropertyTag = new PropertyTag(0x3008, 0x0040);
                propertyValue.Value = sampleForPidTagLastModificationTime;
                propertyValues[1] = propertyValue;

                // Construct PidTagChangeKey value.
                propertyValue = new TaggedPropertyValue
                {
                    PropertyTag = new PropertyTag(0x65E2, 0x0102)
                };
                byte[] sampleForPidTagChangeKey = new byte[24];

                // The combination of first two bytes (0x0014) indicates the length of value field.
                length = (short)(this.localReplicaGuid.ToByteArray().Length + changeNumber.Length);
                Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagChangeKey, 0, sizeof(short));
                index += sizeof(short);
                Array.Copy(this.localReplicaGuid.ToByteArray(), 0, sampleForPidTagChangeKey, index, this.localReplicaGuid.ToByteArray().Length);
                index += this.localReplicaGuid.ToByteArray().Length;
                Array.Copy(changeNumber, 0, sampleForPidTagChangeKey, index, changeNumber.Length);
                propertyValue.Value = sampleForPidTagChangeKey;
                propertyValues[2] = propertyValue;
                Array.Copy(propertyValue.Value, 2, this.importPidTagChangeKeyValue, 0, propertyValue.Value.Length - 2);
                length = 0;
                index = 0;

                if (this.propertyValuesSpecific.ContainsKey("LastImportPidTagChangekey"))
                {
                    this.propertyValuesSpecific["LastImportPidTagChangekey"] = sampleForPidTagChangeKey;
                }
                else
                {
                    this.propertyValuesSpecific.Add("LastImportPidTagChangekey", sampleForPidTagChangeKey);
                }

                // Construct PidTagPredecessorChangeList value.
                propertyValue = new TaggedPropertyValue
                {
                    PropertyTag = new PropertyTag(0x65E3, 0x0102)
                };

                byte[] sampleForPidTagPredecessorChangeList = new byte[25];
                length = (short)(this.localReplicaGuid.ToByteArray().Length + changeNumber.Length + 1);
                Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagPredecessorChangeList, 0, sizeof(short));
                index += sizeof(short);
                sampleForPidTagPredecessorChangeList[index++] = Convert.ToByte(this.localReplicaGuid.ToByteArray().Length + changeNumber.Length);
                Array.Copy(this.localReplicaGuid.ToByteArray(), 0, sampleForPidTagPredecessorChangeList, index, this.localReplicaGuid.ToByteArray().Length);
                index += this.localReplicaGuid.ToByteArray().Length;
                Array.Copy(changeNumber, 0, sampleForPidTagPredecessorChangeList, index, changeNumber.Length);
                propertyValue.Value = sampleForPidTagPredecessorChangeList;
                propertyValues[3] = propertyValue;
            }
            else if (messageIndex == -1)
            {
                // Construct PidTagSourceKey value.
                byte[] sub = new byte[4];
                Array.Copy(currentLocalGloabalCount, 2, sub, 0, currentLocalGloabalCount.Length - 2);
                Array.Reverse(sub);
                int totalNum = BitConverter.ToInt32(sub, 0);

                // Generate a new local id from id set got from server.
                totalNum += this.localIdOffSet;
                sub = BitConverter.GetBytes(totalNum);
                Array.Reverse(sub);
                Array.Copy(sub, 0, currentLocalGloabalCount, 2, currentLocalGloabalCount.Length - 2);
                this.localIdOffSet++;

                propertyValue = new TaggedPropertyValue
                {
                    PropertyTag = new PropertyTag(0x65E0, 0x0102)
                };

                byte[] sample = new byte[24];

                // The combination of first two bytes (0x0016) indicates the length of value field.
                length = (short)(this.serverReplicaGuid.ToByteArray().Length + currentLocalGloabalCount.Length);
                Array.Copy(BitConverter.GetBytes(length), 0, sample, index, sizeof(short));
                index += sizeof(short);
                Array.Copy(this.serverReplicaGuid.ToByteArray(), 0, sample, index, this.serverReplicaGuid.ToByteArray().Length);
                index += this.serverReplicaGuid.ToByteArray().Length;
                Array.Copy(currentLocalGloabalCount, 0, sample, index, currentLocalGloabalCount.Length);
                Array.Copy(currentLocalGloabalCount, 0, changeNumber, 0, currentLocalGloabalCount.Length);
                propertyValue.Value = sample;
                propertyValues[0] = propertyValue;
                length = 0;
                index = 0;

                // Construct PidTagLastModificationTime value.
                propertyValue = new TaggedPropertyValue();
                byte[] sampleForPidTagLastModificationTime = BitConverter.GetBytes(DateTime.Now.ToFileTimeUtc());
                propertyValue.PropertyTag = new PropertyTag(0x3008, 0x0040);
                propertyValue.Value = sampleForPidTagLastModificationTime;
                propertyValues[1] = propertyValue;

                // Construct PidTagChangeKey value.
                propertyValue = new TaggedPropertyValue
                {
                    PropertyTag = new PropertyTag(0x65E2, 0x0102)
                };
                byte[] sampleForPidTagChangeKey = new byte[24];

                // The combination of first two bytes (0x0014) indicates the length of value field.
                length = (short)(this.localReplicaGuid.ToByteArray().Length + changeNumber.Length);
                Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagChangeKey, 0, sizeof(short));
                index += sizeof(short);
                Array.Copy(this.localReplicaGuid.ToByteArray(), 0, sampleForPidTagChangeKey, index, this.localReplicaGuid.ToByteArray().Length);
                index += this.localReplicaGuid.ToByteArray().Length;
                Array.Copy(changeNumber, 0, sampleForPidTagChangeKey, index, changeNumber.Length);

                // The parameter localIDs is used to save the LocalId value of the PidTagChangeKey value. 
                byte[] localIDs = new byte[8];
                Array.Copy(sampleForPidTagChangeKey, 18, localIDs, 2, localIDs.Length - 2);
                Array.Reverse(localIDs);
                long localIDsInt = BitConverter.ToInt64(localIDs, 0);
                localIDsInt += 1;
                localIDs = BitConverter.GetBytes(localIDsInt);
                Array.Reverse(localIDs);
                Array.Copy(localIDs, 2, sampleForPidTagChangeKey, 18, localIDs.Length - 2);

                propertyValue.Value = sampleForPidTagChangeKey;
                propertyValues[2] = propertyValue;
                Array.Copy(propertyValue.Value, 2, this.importPidTagChangeKeyValue, 0, propertyValue.Value.Length - 2);
                length = 0;
                index = 0;

                // Construct PidTagPredecessorChangeList value.
                propertyValue = new TaggedPropertyValue
                {
                    PropertyTag = new PropertyTag(0x65E3, 0x0102)
                };

                byte[] sampleForPidTagPredecessorChangeList = new byte[25];
                index = 0;
                length = 0;
                length = (short)(GidLength + 1);
                Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagPredecessorChangeList, 0, sizeof(short));
                index += sizeof(short);
                sampleForPidTagPredecessorChangeList[2] = Convert.ToByte(this.localReplicaGuid.ToByteArray().Length + changeNumber.Length); // 16
                index += 1;
                Array.Copy(this.localReplicaGuid.ToByteArray(), 0, sampleForPidTagPredecessorChangeList, index, this.localReplicaGuid.ToByteArray().Length);
                index += this.localReplicaGuid.ToByteArray().Length;
                Array.Copy(changeNumber, 0, sampleForPidTagPredecessorChangeList, index, changeNumber.Length);

                this.lastConflictInfo.PCLB = sampleForPidTagPredecessorChangeList;
                sampleForPidTagPredecessorChangeList[24] += 1;
                this.lastConflictInfo.PCLA = sampleForPidTagPredecessorChangeList;
                this.lastConflictInfo.PCLXFromMath = sampleForPidTagPredecessorChangeList;
                this.lastConflictInfo.DetectedResult = ConflictTypes.AINCLUDEB;

                propertyValue.Value = sampleForPidTagPredecessorChangeList;
                propertyValues[3] = propertyValue;
            }
            else if (messageIndex == -2)
            {
                byte[] sub = new byte[4];
                Array.Copy(currentLocalGloabalCount, 2, sub, 0, currentLocalGloabalCount.Length - 2);
                Array.Reverse(sub);
                int totalNum = BitConverter.ToInt32(sub, 0);

                // Generate a new local id from id set got from server.
                totalNum += this.localIdOffSet;
                sub = BitConverter.GetBytes(totalNum);
                Array.Reverse(sub);
                Array.Copy(sub, 0, currentLocalGloabalCount, 2, currentLocalGloabalCount.Length - 2);
                this.localIdOffSet++;

                propertyValue = new TaggedPropertyValue
                {
                    PropertyTag = new PropertyTag(0x65E0, 0x0102)
                };

                byte[] sample = new byte[24];

                // The combination of first two bytes (0x0016) indicates the length of value field.
                length = (short)(this.serverReplicaGuid.ToByteArray().Length + currentLocalGloabalCount.Length);
                Array.Copy(BitConverter.GetBytes(length), 0, sample, index, sizeof(short));
                index += sizeof(short);
                Array.Copy(this.serverReplicaGuid.ToByteArray(), 0, sample, index, this.serverReplicaGuid.ToByteArray().Length);
                index += this.serverReplicaGuid.ToByteArray().Length;
                Array.Copy(currentLocalGloabalCount, 0, sample, index, currentLocalGloabalCount.Length);
                Array.Copy(currentLocalGloabalCount, 0, changeNumber, 0, currentLocalGloabalCount.Length);
                propertyValue.Value = sample;
                propertyValues[0] = propertyValue;
                length = 0;
                index = 0;

                // Construct PidTagLastModificationTime value.
                propertyValue = new TaggedPropertyValue();
                byte[] sampleForPidTagLastModificationTime = BitConverter.GetBytes(DateTime.Now.ToFileTimeUtc());
                propertyValue.PropertyTag = new PropertyTag(0x3008, 0x0040);
                propertyValue.Value = sampleForPidTagLastModificationTime;
                propertyValues[1] = propertyValue;

                // Construct PidTagChangeKey value.
                propertyValue = new TaggedPropertyValue
                {
                    PropertyTag = new PropertyTag(0x65E2, 0x0102)
                };
                byte[] sampleForPidTagChangeKey = new byte[24];

                // The combination of first two bytes (0x0014) indicates the length of value field.
                length = (short)(this.localReplicaGuid.ToByteArray().Length + changeNumber.Length);
                Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagChangeKey, 0, sizeof(short));
                index += sizeof(short);
                Array.Copy(this.localReplicaGuid.ToByteArray(), 0, sampleForPidTagChangeKey, index, this.localReplicaGuid.ToByteArray().Length);
                index += this.localReplicaGuid.ToByteArray().Length;
                Array.Copy(changeNumber, 0, sampleForPidTagChangeKey, index, changeNumber.Length);

                // The parameter localIDs is used to save the LocalId value of the PidTagChangeKey value. 
                byte[] localIDs = new byte[8];
                Array.Copy(sampleForPidTagChangeKey, 18, localIDs, 2, localIDs.Length - 2);
                Array.Reverse(localIDs);
                long localIDsInt = BitConverter.ToInt64(localIDs, 0);
                localIDsInt += 1;
                localIDs = BitConverter.GetBytes(localIDsInt);
                Array.Reverse(localIDs);
                Array.Copy(localIDs, 2, sampleForPidTagChangeKey, 18, localIDs.Length - 2);
                propertyValue.Value = sampleForPidTagChangeKey;
                propertyValues[2] = propertyValue;
                Array.Copy(propertyValue.Value, 2, this.importPidTagChangeKeyValue, 0, propertyValue.Value.Length - 2);
                length = 0;
                index = 0;

                // Construct PidTagPredecessorChangeList value.
                propertyValue = new TaggedPropertyValue
                {
                    PropertyTag = new PropertyTag(0x65E3, 0x0102)
                };

                byte[] sampleForPidTagPredecessorChangeList = new byte[25];
                index = 0;
                length = 0;
                length = (short)(GidLength + 1);
                Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagPredecessorChangeList, 0, sizeof(short));
                index += sizeof(short);
                sampleForPidTagPredecessorChangeList[2] = Convert.ToByte(this.localReplicaGuid.ToByteArray().Length + changeNumber.Length); // 16
                index += 1;
                Array.Copy(this.localReplicaGuid.ToByteArray(), 0, sampleForPidTagPredecessorChangeList, index, this.localReplicaGuid.ToByteArray().Length);
                index += this.localReplicaGuid.ToByteArray().Length;
                Array.Copy(changeNumber, 0, sampleForPidTagPredecessorChangeList, index, changeNumber.Length);

                this.lastConflictInfo.PCLB = sampleForPidTagPredecessorChangeList;

                byte[] change = new byte[48];
                Array.Copy(BitConverter.GetBytes(46), 0, change, 0, sizeof(short));
                Array.Copy(sampleForPidTagPredecessorChangeList, 2, change, 2, 23);
                Array.Copy(BitConverter.GetBytes(22), 0, change, 25, sizeof(short));
                Array.Copy(Guid.NewGuid().ToByteArray(), 0, change, 26, 16);

                this.lastConflictInfo.PCLA = change;
                this.lastConflictInfo.PCLXFromMath = change;

                propertyValue.Value = change;
                propertyValues[3] = propertyValue;
            }

            return propertyValues;
        }
        /// <summary>
        /// Verify whether server supports passing the flag HardDelete (0x02) in the Flags field of a RopSynchronizationImportDeletes request.
        /// </summary>
        /// <param name="pcxh">A unique value to be used as a session context handle.</param>
        /// <returns>Whether the server supports this ROP method with specific value passed in. True means yes, false means no.</returns>
        private bool TryRopSynchronizationImportDeletes(IntPtr pcxh)
        {
            #region Logon to mailbox
            this.rgbIn = AdapterHelper.ComposeRgbIn(ROPCommandType.RopLogon, 0, (ulong)OpenFlags.UsePerMDBReplipMapping);
            this.pcbOut = ConstValues.ValidpcbOut;
            this.pcbAuxOut = ConstValues.ValidpcbAuxOut;

            this.returnValue = this.oxcrpcAdapter.EcDoRpcExt2(
                ref pcxh,
                PulFlags.NoCompression | PulFlags.NoXorMagic,
                this.rgbIn,
                ref this.pcbOut,
                null,
                ref this.pcbAuxOut,
                out this.response,
                ref this.responseSOHTable);

            Site.Assert.AreEqual<uint>(0, this.returnValue, "EcDoRpcExt2 should succeed and 0 is expected to be returned. The returned value is {0}.", this.returnValue);
            RopLogonResponse logonResponse = (RopLogonResponse)this.response;
            Site.Assert.AreEqual<uint>(0, logonResponse.ReturnValue, "RopLogon should succeed and 0 is expected to be returned. The returned value is {0}.", logonResponse.ReturnValue);

            // The element whose index is 0 indicates this ROP command response handle
            this.objHandle = this.responseSOHTable[0][logonResponse.OutputHandleIndex];
            #endregion

            #region OpenFolder
            this.rgbIn = AdapterHelper.ComposeRgbIn(ROPCommandType.RopOpenFolder, this.objHandle, logonResponse.FolderIds[(int)FolderIds.InterpersonalMessage]);
            this.pcbOut = ConstValues.ValidpcbOut;
            this.pcbAuxOut = ConstValues.ValidpcbAuxOut;
            this.responseSOHTable = new List<List<uint>>();

            this.returnValue = this.oxcrpcAdapter.EcDoRpcExt2(
                ref pcxh,
                PulFlags.NoXorMagic,
                this.rgbIn,
                ref this.pcbOut,
                null,
                ref this.pcbAuxOut,
                out this.response,
                ref this.responseSOHTable);

            Site.Assert.AreEqual<uint>(0, this.returnValue, "EcDoRpcExt2 should succeed and 0 is expected to be returned. The returned value is {0}.", this.returnValue);
            RopOpenFolderResponse openFolderResponse = (RopOpenFolderResponse)this.response;
            Site.Assert.AreEqual<uint>(0, openFolderResponse.ReturnValue, "RopOpenFolder should succeed and 0 is expected to be returned. The returned value is {0}.", openFolderResponse.ReturnValue);
            uint openObjHandle = this.responseSOHTable[0][openFolderResponse.OutputHandleIndex];
            #endregion

            #region Configure a synchronization upload context
            this.rgbIn = AdapterHelper.ComposeRgbIn(ROPCommandType.RopSynchronizationOpenCollector, openObjHandle, 0);
            this.pcbOut = ConstValues.ValidpcbOut;
            this.pcbAuxOut = ConstValues.ValidpcbAuxOut;
            this.responseSOHTable = new List<List<uint>>();

            this.returnValue = this.oxcrpcAdapter.EcDoRpcExt2(
                ref pcxh,
                PulFlags.NoXorMagic,
                this.rgbIn,
                ref this.pcbOut,
                null,
                ref this.pcbAuxOut,
                out this.response,
                ref this.responseSOHTable);

            Site.Assert.AreEqual<uint>(0, this.returnValue, "EcDoRpcExt2 should succeed and 0 is expected to be returned. The returned value is {0}.", this.returnValue);
            RopSynchronizationOpenCollectorResponse openCollectorResponse = (RopSynchronizationOpenCollectorResponse)this.response;
            Site.Assert.AreEqual<uint>(0, openCollectorResponse.ReturnValue, "RopSynchronizationOpenCollector should succeed and 0 is expected to be returned. The returned value is {0}.", openCollectorResponse.ReturnValue);
            uint synchronizationUploadContextHandle = this.responseSOHTable[0][openCollectorResponse.OutputHandleIndex];
            #endregion

            #region RopCreateMessage
            this.rgbIn = AdapterHelper.ComposeRgbIn(ROPCommandType.RopCreateMessage, openObjHandle, logonResponse.FolderIds[(int)FolderIds.Inbox]);
            this.pcbOut = ConstValues.ValidpcbOut;
            this.pcbAuxOut = ConstValues.ValidpcbAuxOut;
            this.responseSOHTable = new List<List<uint>>();

            this.returnValue = this.oxcrpcAdapter.EcDoRpcExt2(
                ref pcxh,
                PulFlags.NoCompression | PulFlags.NoXorMagic,
                this.rgbIn,
                ref this.pcbOut,
                null,
                ref this.pcbAuxOut,
                out this.response,
                ref this.responseSOHTable);

            Site.Assert.AreEqual<uint>(0, this.returnValue, "EcDoRpcExt2 should succeed and 0 is expected to be returned. The returned value is {0}.", this.returnValue);
            RopCreateMessageResponse createMessageResponse = (RopCreateMessageResponse)this.response;
            Site.Assert.AreEqual<uint>(0, createMessageResponse.ReturnValue, "RopCreateMessage should succeed and 0 is expected to be returned. The returned value is {0}.", createMessageResponse.ReturnValue);
            uint objCreateMessageHandle = this.responseSOHTable[0][createMessageResponse.OutputHandleIndex];
            #endregion

            #region RopSaveChangesMessage
            this.rgbIn = AdapterHelper.ComposeRgbIn(ROPCommandType.RopSaveChangesMessage, objCreateMessageHandle, logonResponse.FolderIds[(int)FolderIds.InterpersonalMessage]);
            this.pcbOut = ConstValues.ValidpcbOut;
            this.pcbAuxOut = ConstValues.ValidpcbAuxOut;
            this.responseSOHTable = new List<List<uint>>();

            this.returnValue = this.oxcrpcAdapter.EcDoRpcExt2(
                ref pcxh,
                PulFlags.NoCompression | PulFlags.NoXorMagic,
                this.rgbIn,
                ref this.pcbOut,
                null,
                ref this.pcbAuxOut,
                out this.response,
                ref this.responseSOHTable);

            Site.Assert.AreEqual<uint>(0, this.returnValue, "EcDoRpcExt2 should succeed and 0 is expected to be returned. The returned value is {0}.", this.returnValue);
            RopSaveChangesMessageResponse saveChangesMessageResponse = (RopSaveChangesMessageResponse)this.response;
            Site.Assert.AreEqual<uint>(0, saveChangesMessageResponse.ReturnValue, "RopSaveChangesMessage should succeed and 0 is expected to be returned. The returned value is {0}.", saveChangesMessageResponse.ReturnValue);
            #endregion

            #region RopSynchronizationImportDeletes

            #region RopLongTermIdFromIdRequest
            // Call RopLongTermIdFromIdRequest to convert the short-term ID into a long-term ID for RopSynchronizationImportDeletes.
            this.rgbIn = AdapterHelper.ComposeRgbIn(ROPCommandType.RopLongTermIdFromId, this.objHandle, saveChangesMessageResponse.MessageId);
            this.pcbOut = ConstValues.ValidpcbOut;
            this.pcbAuxOut = ConstValues.ValidpcbAuxOut;
            this.responseSOHTable = new List<List<uint>>();

            this.returnValue = this.oxcrpcAdapter.EcDoRpcExt2(
                ref pcxh,
                PulFlags.NoXorMagic,
                this.rgbIn,
                ref this.pcbOut,
                null,
                ref this.pcbAuxOut,
                out this.response,
                ref this.responseSOHTable);

            Site.Assert.AreEqual<uint>(0, this.returnValue, "EcDoRpcExt2 should succeed and 0 is expected to be returned. The returned value is {0}.", this.returnValue);
            RopLongTermIdFromIdResponse longTermIdFromIdResponse = (RopLongTermIdFromIdResponse)this.response;
            Site.Assert.AreEqual<uint>(0, longTermIdFromIdResponse.ReturnValue, "RopLongTermIdFromId should succeed and 0 is expected to be returned. The returned value is {0}.", longTermIdFromIdResponse.ReturnValue);

            // PropertyValues for RopSynchronizationImportDeletes.
            byte[] importdeletesPropertyValues = new byte[sizeof(int) + sizeof(short) + ConstValues.GidLength];
            PropertyTag[] tagArray = new PropertyTag[1];

            TaggedPropertyValue propertyValue = new TaggedPropertyValue();
            PropertyTag propertyTag = new PropertyTag
            {
                PropertyId = 0x0000,
                PropertyType = 0x1102
            };

            int index = 0;
            Array.Copy(BitConverter.GetBytes(tagArray.Length), 0, importdeletesPropertyValues, 0, sizeof(int));
            index += sizeof(int);
            Array.Copy(BitConverter.GetBytes(22), 0, importdeletesPropertyValues, index, sizeof(short));
            index += sizeof(short);
            byte[] longTermByte = new byte[longTermIdFromIdResponse.LongTermId.DatabaseGuid.Length + longTermIdFromIdResponse.LongTermId.GlobalCounter.Length];
            Array.Copy(longTermIdFromIdResponse.LongTermId.DatabaseGuid, 0, longTermByte, 0, longTermIdFromIdResponse.LongTermId.DatabaseGuid.Length);
            Array.Copy(longTermIdFromIdResponse.LongTermId.GlobalCounter, 0, longTermByte, longTermIdFromIdResponse.LongTermId.DatabaseGuid.Length, longTermIdFromIdResponse.LongTermId.GlobalCounter.Length);

            Array.Copy(longTermByte, 0, importdeletesPropertyValues, index, longTermByte.Length);
            propertyValue.PropertyTag = propertyTag;
            propertyValue.Value = importdeletesPropertyValues;
            #endregion

            // HardDelete (0x02) is written in method ComposeRopSynchronizationImportDeletes
            this.rgbIn = AdapterHelper.ComposeRgbIn(ROPCommandType.RopSynchronizationImportDeletes, synchronizationUploadContextHandle, propertyValue);
            this.pcbOut = ConstValues.ValidpcbOut;
            this.pcbAuxOut = ConstValues.ValidpcbAuxOut;
            this.responseSOHTable = new List<List<uint>>();

            this.returnValue = this.oxcrpcAdapter.EcDoRpcExt2(
                ref pcxh,
                PulFlags.NoXorMagic,
                this.rgbIn,
                ref this.pcbOut,
                null,
                ref this.pcbAuxOut,
                out this.response,
                ref this.responseSOHTable);

            Site.Assert.AreEqual<uint>(0, this.returnValue, "EcDoRpcExt2 should succeed and 0 is expected to be returned. The returned value is {0}.", this.returnValue);
            RopSynchronizationImportDeletesResponse synchronizationImportDeletesResponse = (RopSynchronizationImportDeletesResponse)this.response;
            Site.Assert.AreEqual<uint>(0, synchronizationImportDeletesResponse.ReturnValue, "RopSynchronizationImportDeletes should succeed and 0 is expected to be returned. The returned value is {0}.", synchronizationImportDeletesResponse.ReturnValue);
            #endregion

            return this.returnValue == 0;
        }
        /// <summary>
        /// Overrides TestClassBase's TestCleanup()
        /// </summary>
        protected override void TestCleanup()
        {
            string transport = Common.GetConfigurationPropertyValue("TransportSeq", this.Site);
            if ((!this.transportByMAPIOrNot && (transport.ToLower() != "ncacn_ip_tcp")) 
                || (this.transportByMAPIOrNot && Common.IsRequirementEnabled(300000001, this.Site))
                || ((transport.ToLower() == "ncacn_ip_tcp") && Common.IsRequirementEnabled(1911, this.Site)))
            {
                switch (TestContext.TestName)
                {
                    case "MSOXCSTOR_S01_TC01_TestLogonToPrivateMailBox":
                    case "MSOXCSTOR_S01_TC10_TestOperationsOnReadWriteProperties":
                        PropertyTag propertyPidTagOutOfOfficeState;
                        TaggedPropertyValue pidTagOutOfOfficeState = new TaggedPropertyValue();

                        // According to the Open Specification MS-OXPROPS, PidTagOutOfOfficeState's id is 0x661D
                        const ushort PropertyIdForPidTagOutOfOfficeState = 0x661D;

                        propertyPidTagOutOfOfficeState.PropertyId = PropertyIdForPidTagOutOfOfficeState;

                        // According to [MS-OXPROPS], PidTagOutOfOfficeState's data type is 0x000B
                        propertyPidTagOutOfOfficeState.PropertyType = 0x000B;
                        pidTagOutOfOfficeState.PropertyTag = propertyPidTagOutOfOfficeState;
                        pidTagOutOfOfficeState.Value = new byte[1];
                        pidTagOutOfOfficeState.Value[0] = 0x00;

                        this.TrySetLogonProperty(pidTagOutOfOfficeState);
                        break;
                    case "MSOXCSTOR_S01_TC11_TestRopLogonErrorCodes":
                        if (!this.transportByMAPIOrNot)
                        {
                            this.oxcstorAdapter.DisconnectEx();

                            if (Common.IsRequirementEnabled(193, this.Site)
                                || Common.IsRequirementEnabled(1268001, this.Site))
                            {
                                string userForDisableMailbox = Common.GetConfigurationPropertyValue(ConstValues.UserForDisableMailbox, this.Site);
                                string essdn = this.sutControlAdapter.GetUserDN(this.server1Name, userForDisableMailbox);

                                // Enable the disabled mailbox
                                if (string.IsNullOrEmpty(essdn))
                                {
                                    string status = this.sutControlAdapter.EnableMailbox(userForDisableMailbox);
                                    if (status.Equals("success", StringComparison.OrdinalIgnoreCase))
                                    {
                                        int sleepSeconds = int.Parse(Common.GetConfigurationPropertyValue(ConstValues.SleepSecondsAfterEnableMailbox, this.Site));
                                        Thread.Sleep(sleepSeconds * 1000);
                                    }
                                    else
                                    {
                                        Site.Assert.Fail("The mailbox of {0} is not enabled. Error: {1}.", userForDisableMailbox, status);
                                    }
                                }
                            }
                        }

                        return;
                    case "MSOXCSTOR_S01_TC04_TestRopGetStoreState":
                        RopOpenFolderRequest openFolderRequest;
                        RopOpenFolderResponse openFolderResponse;

                        openFolderRequest.RopId = 0x02;
                        openFolderRequest.LogonId = 0x0;
                        openFolderRequest.InputHandleIndex = 0x0;
                        openFolderRequest.OutputHandleIndex = 0x01;
                        openFolderRequest.FolderId = this.logonResponse.FolderIds[4]; // Inbox folder
                        openFolderRequest.OpenModeFlags = 0x0; // opening an existing folder

                        this.oxcstorAdapter.DoRopCall(openFolderRequest, this.outObjHandle, ROPCommandType.Others, out this.outputBuffer);

                        openFolderResponse = (RopOpenFolderResponse)this.outputBuffer.RopsList[0];
                        Site.Assert.AreEqual<uint>(
                            0x00000000,
                            openFolderResponse.ReturnValue,
                            "0 indicates the ROP succeeds, other value indicates error occurs.");
                        uint openedFolderHandle = this.outputBuffer.ServerObjectHandleTable[openFolderRequest.OutputHandleIndex];

                        RopHardDeleteMessagesAndSubfoldersRequest deleteSubfoldersOfInboxRequest = new RopHardDeleteMessagesAndSubfoldersRequest
                        {
                            RopId = 0x92,
                            InputHandleIndex = 0x00,
                            WantAsynchronous = 0x00,
                            WantDeleteAssociated = 0xff
                        };
                        this.oxcstorAdapter.DoRopCall(deleteSubfoldersOfInboxRequest, openedFolderHandle, ROPCommandType.Others, out this.outputBuffer);

                        RopHardDeleteMessagesAndSubfoldersResponse deleteSubfoldersOfInboxResponse = (RopHardDeleteMessagesAndSubfoldersResponse)this.outputBuffer.RopsList[0];
                        Site.Assert.AreEqual<uint>(
                            0x00000000,
                            deleteSubfoldersOfInboxResponse.ReturnValue,
                            "0 indicates the ROP succeeds, other value indicates error occurs.");
                        break;
                    default:
                        break;
                }

            this.oxcstorAdapter.DisconnectEx();
            }
        }
        /// <summary>
        /// Create Sample RuleData Array For Add.
        /// </summary>
        /// <returns>Return RuleData array</returns>
        private RuleData[] CreateSampleRuleDataArrayForAdd()
        {
            // Count of PropertyValues.
            int length = 4;
            TaggedPropertyValue[] propertyValues = new TaggedPropertyValue[length];

            for (int i = 0; i < length; i++)
            {
                propertyValues[i] = new TaggedPropertyValue();
            }

            TaggedPropertyValue taggedPropertyValue;

            // MS-OXORULE 2.2.1.3.2
            // When adding a rule, the client MUST NOT pass in PidTagRuleId, it MUST pass in PidTagRuleCondition,
            // PidTagRuleActions and PidTagRuleProvider.

            // PidTagRuleSequence
            taggedPropertyValue = new TaggedPropertyValue
            {
                PropertyTag =
                {
                    PropertyId = this.propertyDictionary[PropertyNames.PidTagRuleSequence].PropertyId,
                    PropertyType = this.propertyDictionary[PropertyNames.PidTagRuleSequence].PropertyType
                }
            };
            byte[] value3 = { 0x00, 0x00, 0x00, 0x0a };
            taggedPropertyValue.Value = value3;
            propertyValues[3] = taggedPropertyValue;

            // PidTagRuleCondition
            taggedPropertyValue = new TaggedPropertyValue
            {
                PropertyTag =
                {
                    PropertyId = this.propertyDictionary[PropertyNames.PidTagRuleCondition].PropertyId,
                    PropertyType = this.propertyDictionary[PropertyNames.PidTagRuleCondition].PropertyType
                }
            };
            byte[] value = 
            {
                0x03, 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x37, 0x00, 0x1f, 0x00,
                0x37, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6a, 0x00, 0x65,
                0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00, 0x58, 0x00, 0x00, 0x00
            };
            taggedPropertyValue.Value = value;
            propertyValues[1] = taggedPropertyValue;

            // PidTagRuleActions
            taggedPropertyValue = new TaggedPropertyValue
            {
                PropertyTag =
                {
                    PropertyId = this.propertyDictionary[PropertyNames.PidTagRuleActions].PropertyId,
                    PropertyType = this.propertyDictionary[PropertyNames.PidTagRuleActions].PropertyType
                }
            };
            byte[] value1 = { 0x01, 0x00, 0x09, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
            taggedPropertyValue.Value = value1;
            propertyValues[2] = taggedPropertyValue;

            // PidTagRuleProvider
            taggedPropertyValue = new TaggedPropertyValue
            {
                PropertyTag =
                {
                    PropertyId = this.propertyDictionary[PropertyNames.PidTagRuleProvider].PropertyId,
                    PropertyType = this.propertyDictionary[PropertyNames.PidTagRuleProvider].PropertyType
                }
            };
            byte[] value2 = Encoding.Unicode.GetBytes("RuleOrganizerContoso\0");
            taggedPropertyValue.Value = value2;
            propertyValues[0] = taggedPropertyValue;

            RuleData sampleRuleData = new RuleData
            {
                RuleDataFlags = (byte)RuleDataFlags.RowAdd,
                PropertyValueCount = (ushort)propertyValues.Length,
                PropertyValues = propertyValues
            };

            RuleData[] sampleRuleDataArray = new RuleData[1];
            sampleRuleDataArray[0] = sampleRuleData;

            return sampleRuleDataArray;
        }
        /// <summary>
        /// This method is used to send the ROP of RopSetPropertiesRequest to set the specific property.
        /// </summary>
        /// <param name="propValue">The new property value</param>
        /// <returns>0 indicates success, others indicates error occurs.</returns>
        protected uint TrySetLogonProperty(TaggedPropertyValue propValue)
        {
            uint retValue = 0;
            TaggedPropertyValue[] tags = new TaggedPropertyValue[1];
            tags[0] = propValue;

            #region Construct the request buffer
            RopSetPropertiesRequest setPropertiesRequest = new RopSetPropertiesRequest
            {
                RopId = 0x0A,
                LogonId = 0x0,
                InputHandleIndex = 0x0,
                PropertyValueSize = (ushort)(tags[0].Size() + 2),
                PropertyValueCount = (ushort)tags.Length,
                PropertyValues = tags
            };

            #endregion

            this.oxcstorAdapter.DoRopCall(setPropertiesRequest, this.outObjHandle, ROPCommandType.RopSetProperties, out this.outputBuffer);
            RopSetPropertiesResponse setPropertiesResponse = (RopSetPropertiesResponse)this.outputBuffer.RopsList[0];

            #region Check the response
            if (setPropertiesResponse.ReturnValue == 0x00)
            {
                // The return value is 0 to indicate that the method invoking successfully.
                if (setPropertiesResponse.PropertyProblems != null
                && setPropertiesResponse.PropertyProblems.Length > 0)
                {
                    retValue = setPropertiesResponse.PropertyProblems[0].ErrorCode;
                }
            }
            else
            {
                retValue = setPropertiesResponse.ReturnValue;
            }
            #endregion

            return retValue;
        }