public void MSOXORULE_S01_TC09_AddExtendedRuleForThreeTimes() { this.CheckMAPIHTTPTransportSupported(); Site.Assume.IsTrue(Common.IsRequirementEnabled(646, this.Site), "This case runs only when the server supports processing more than two extended rules it encounters per folder."); #region TestUser1 creates an FAI message for the first 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 first FAI message should succeed."); NamedPropertyInfo namedPropertyInfo1 = new NamedPropertyInfo { NoOfNamedProps = 0 }; TaggedPropertyValue[] extendedRuleProperties1 = AdapterHelper.GenerateExtendedRuleTestData(Common.GenerateResourceName(this.Site, Constants.ExtendRulename1), 0, (uint)RuleState.ST_ENABLED, Constants.PidTagRuleProvider, ActionType.OP_MARK_AS_READ, new DeleteMarkReadActionData(), Constants.ExtendRuleCondition1, 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 retrieves data of the extended rule. this.OxoruleAdapter.TargetOfRop = TargetOfRop.ForExtendedRules; RopGetPropertiesAllResponse ropGetExtendRuleMessageResponse = this.OxoruleAdapter.RopGetPropertiesAll(extendedRuleMessageHandle1, 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 = new ExtendedRuleActions(); // 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; } } // Get the Property Names saved by server in the extendedRuleMessageActions. PropertyName[] propertyNames = extendedRuleMessageActions.NamedPropertyInformation.NamedProperty; uint[] propertyIds = extendedRuleMessageActions.NamedPropertyInformation.PropId; Site.Assert.AreEqual<uint>(0, extendedRuleMessageActions.NamedPropertyInformation.NoOfNamedProps, "The property NoOfNamedProps of NamedPropertyInformation should be zero!"); #region Capture Code // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R696."); // NoOfNamedProps set to 0, it means no named properties are used in the structure that follows the Named Property Information buffer. // So if NamedProperty of NamedPropertyInformation in the extendedRuleMessageActions is null. This requirement can be verified. bool isVerifyR696 = propertyNames == null; Site.CaptureRequirementIfIsTrue( isVerifyR696, 696, @"[In NamedPropertyInformation Structure] NoOfNamedProps (2 bytes): If no named properties are used in the structure that follows the NamedPropertyInformation structure, the value of this field MUST be 0x0000."); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R936"); // NoOfNamedProps set to 0, it means no named properties are used in the structure that follows the Named Property Information buffer. // So if NamedProperty, PropIds of NamedPropertyInformation in the extendedRuleMessageActions is null. This requirement can be verified. bool isVerifyR936 = propertyNames == null && propertyIds == null; Site.CaptureRequirementIfIsTrue( isVerifyR936, 936, @"[In NamedPropertyInformation Structure] [If no named properties are used in the structure that follows the NamedPropertyInformation structure] no other fields [except NoOfNamedProps] are present."); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R697"); // When NoOfNamedProps is set to 0, NamedPropertyInformation in ExtendedRuleActions reduces to a 2-byte WORD value of NoOfNamedProps. Site.CaptureRequirement( 697, @"[In NamedPropertyInformation Structure] Note that if there are no named properties to be listed, the NamedPropertyInformation structure reduces to a 2-byte value of 0x0000."); #endregion #endregion #region TestUser2 delivers a message to TestUser1 to trigger the rule. Thread.Sleep(this.WaitForTheRuleToTakeEffect); // TestUser2 delivers a message to TestUser1 to trigger the rule. string mailSubject1 = Common.GenerateResourceName(this.Site, Constants.ExtendRuleCondition1); this.SUTAdapter.SendMailToRecipient(this.User2Name, this.User2Password, this.User1Name, mailSubject1); Thread.Sleep(this.WaitForTheRuleToTakeEffect); PropertyTag[] propertyTagList = new PropertyTag[2]; propertyTagList[0].PropertyId = (ushort)PropertyId.PidTagSubject; propertyTagList[0].PropertyType = (ushort)PropertyType.PtypString; propertyTagList[1].PropertyId = (ushort)PropertyId.PidTagMessageFlags; propertyTagList[1].PropertyType = (ushort)PropertyType.PtypInteger32; int messageFlag1 = 1; uint contentTableHandle1 = 0; int expectedMessageIndex1 = 0; RopQueryRowsResponse getMailMessageContent1 = this.GetExpectedMessage(this.InboxFolderHandle, ref contentTableHandle1, propertyTagList, ref expectedMessageIndex1, mailSubject1); mailSubject1 = AdapterHelper.PropertyValueConvertToString(getMailMessageContent1.RowData.PropertyRows[expectedMessageIndex1].PropertyValues[0].Value); messageFlag1 = BitConverter.ToInt32(getMailMessageContent1.RowData.PropertyRows[expectedMessageIndex1].PropertyValues[1].Value, 0); #endregion #region TestUser1 creates an FAI message for the second extended rule. uint extendedRuleMessageHandle2 = 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 the second extended rule with no NamedProperty. NamedPropertyInfo namedPropertyInfo2 = new NamedPropertyInfo(); namedPropertyInfo1.NoOfNamedProps = 0; TaggedPropertyValue[] extendedRuleProperties2 = AdapterHelper.GenerateExtendedRuleTestData(Common.GenerateResourceName(this.Site, Constants.ExtendRulename2), 0, (uint)RuleState.ST_ENABLED, Constants.PidTagRuleProvider, ActionType.OP_MARK_AS_READ, new DeleteMarkReadActionData(), Constants.ExtendRuleCondition2, namedPropertyInfo2); // Set properties for extended rule FAI message. ropSetPropertiesResponse = this.OxoruleAdapter.RopSetProperties(extendedRuleMessageHandle2, extendedRuleProperties2); Site.Assert.AreEqual<uint>(0, ropSetPropertiesResponse.ReturnValue, "Setting property for Extended rule FAI message should succeed."); // Save changes of message. ropSaveChangesMessagResponse = this.OxoruleAdapter.RopSaveChangesMessage(extendedRuleMessageHandle2); Site.Assert.AreEqual(0, (int)ropSaveChangesMessagResponse.ReturnValue, "Saving Extend rule message should succeed."); #endregion #region TestUser2 delivers a message to TestUser1 to trigger the rule. Thread.Sleep(this.WaitForTheRuleToTakeEffect); // TestUser2 delivers a message to TestUser1 to trigger the rule. string mailSubject2 = Common.GenerateResourceName(this.Site, Constants.ExtendRuleCondition2); this.SUTAdapter.SendMailToRecipient(this.User2Name, this.User2Password, this.User1Name, mailSubject2); Thread.Sleep(this.WaitForTheRuleToTakeEffect); int messageFlag2 = 1; uint contentTableHandle2 = 0; int expectedMessageIndex2 = 0; RopQueryRowsResponse getMailMessageContent2 = this.GetExpectedMessage(this.InboxFolderHandle, ref contentTableHandle2, propertyTagList, ref expectedMessageIndex2, mailSubject2); mailSubject2 = AdapterHelper.PropertyValueConvertToString(getMailMessageContent2.RowData.PropertyRows[expectedMessageIndex2].PropertyValues[0].Value); messageFlag2 = BitConverter.ToInt32(getMailMessageContent2.RowData.PropertyRows[expectedMessageIndex2].PropertyValues[1].Value, 0); #endregion #region TestUser1 creates an FAI message for the third extended rule. uint extendedRuleMessageHandle3 = 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 the third extended rule with no NamedProperty. NamedPropertyInfo namedPropertyInfo3 = new NamedPropertyInfo(); namedPropertyInfo1.NoOfNamedProps = 0; TaggedPropertyValue[] extendedRuleProperties3 = AdapterHelper.GenerateExtendedRuleTestData(Common.GenerateResourceName(this.Site, Constants.ExtendRulename3), 0, (uint)RuleState.ST_ENABLED, Constants.PidTagRuleProvider, ActionType.OP_MARK_AS_READ, new DeleteMarkReadActionData(), Constants.ExtendRuleCondition3, namedPropertyInfo3); // Set properties for extended rule FAI message. ropSetPropertiesResponse = this.OxoruleAdapter.RopSetProperties(extendedRuleMessageHandle3, extendedRuleProperties3); Site.Assert.AreEqual<uint>(0, ropSetPropertiesResponse.ReturnValue, "Setting property for Extended rule FAI message should succeed."); // Save changes of the message. ropSaveChangesMessagResponse = this.OxoruleAdapter.RopSaveChangesMessage(extendedRuleMessageHandle3); Site.Assert.AreEqual(0, (int)ropSaveChangesMessagResponse.ReturnValue, "Saving Extend rule message should succeed."); #endregion #region TestUser2 delivers a message to TestUser1 to trigger the rule. Thread.Sleep(this.WaitForTheRuleToTakeEffect); // TestUser2 delivers a message to TestUser1 to trigger the rule. string mailSubject3 = Common.GenerateResourceName(this.Site, Constants.ExtendRuleCondition3); this.SUTAdapter.SendMailToRecipient(this.User2Name, this.User2Password, this.User1Name, mailSubject3); Thread.Sleep(this.WaitForTheRuleToTakeEffect); int messageFlag3 = 1; uint contentTableHandle3 = 0; int expectedMessageIndex3 = 0; RopQueryRowsResponse getMailMessageContent3 = this.GetExpectedMessage(this.InboxFolderHandle, ref contentTableHandle3, propertyTagList, ref expectedMessageIndex3, mailSubject3); mailSubject3 = AdapterHelper.PropertyValueConvertToString(getMailMessageContent3.RowData.PropertyRows[expectedMessageIndex3].PropertyValues[0].Value); messageFlag3 = BitConverter.ToInt32(getMailMessageContent3.RowData.PropertyRows[expectedMessageIndex3].PropertyValues[1].Value, 0); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R646: the third message is {0} marked as read.", (messageFlag3 & 0x00000001) == 0x00000001 ? string.Empty : "not"); // Verify MS-OXORULE requirement: MS-OXORULE_R646. // 0x00000001 is the flag which represents the message has been read. If messageFlag doesn't set this flag, it means the incoming message // isn't marked as read, which indicates the server doesn't evaluate the third rule. bool isVerifyR646 = (messageFlag3 & 0x00000001) == 0x00000000 && (messageFlag2 & 0x00000001) == 0x00000001 && (messageFlag1 & 0x00000001) == 0x00000001; Site.CaptureRequirementIfIsTrue( isVerifyR646, 646, @"[In Appendix A: Product Behavior] Implementation does process the standard rule for a message but does only process the first two extended rules it encounters per folder. [<15> Section 3.2.4.1: Exchange 2007 by default will process the standard rule for a message but will only process the first two extended rules it encounters per folder.]"); #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 }
public void MSOXORULE_S02_TC16_ServerExecuteExtendedRule_Action_OP_COPY() { this.CheckMAPIHTTPTransportSupported(); #region Prepare value for ruleProperties variable. RuleProperties ruleProperties = AdapterHelper.GenerateRuleProperties(this.Site, Constants.RuleNameMoveOne); #endregion #region TestUser1 creates folder1 in server store. RopCreateFolderResponse createFolderResponse; uint newFolderHandle = this.OxoruleAdapter.RopCreateFolder(this.InboxFolderHandle, Common.GenerateResourceName(this.Site, "User1Folder01"), "TestForOP_COPY", out createFolderResponse); ulong newFolderId = createFolderResponse.FolderId; Site.Assert.AreEqual<uint>(0, createFolderResponse.ReturnValue, "Creating folder operation should succeed."); #endregion #region Prepare rules' data MoveCopyActionDataOfExtendedRule copyActionData = new MoveCopyActionDataOfExtendedRule(); // Get the created folder1 entry id. byte[] folder1EId = this.OxoruleAdapter.GetFolderEntryId(StoreObjectType.Mailbox, newFolderHandle, newFolderId); // Get the store object's entry id byte[] storeEId = this.GetStoreObjectEntryID(StoreObjectType.Mailbox, this.Server, this.User1ESSDN); copyActionData.FolderEID = folder1EId; copyActionData.StoreEID = storeEId; copyActionData.FolderEIDSize = (uint)folder1EId.Length; copyActionData.StoreEIDSize = (uint)storeEId.Length; #endregion #region TestUser1 creates an FAI message for the 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_COPY, copyActionData, 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 extended rule. #region Step1: TestUser1 gets a table of all messages which are placed in the Inbox folder. uint contentsTableHandleOfFAIMessage; RopGetContentsTableResponse ropGetContentsTableResponseOfFAIMessage = this.OxoruleAdapter.RopGetContentsTable(this.InboxFolderHandle, ContentTableFlag.Associated, out contentsTableHandleOfFAIMessage); Site.Assert.AreEqual<uint>(0, ropGetContentsTableResponseOfFAIMessage.ReturnValue, "Getting contents table should succeed, the actual returned value is {0}", ropGetContentsTableResponseOfFAIMessage.ReturnValue); #endregion #region Step2: TestUser1 sets the interested columns of the message table in the Inbox folder. // Here are 6 interested columns listed as below. PropertyTag[] 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. RopQueryRowsResponse 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); MoveCopyActionDataOfExtendedRule copyActionDataOfQueryRowsResponse = new MoveCopyActionDataOfExtendedRule(); for (int i = 0; i < ropQueryRowsResponseOfFAIMessage.RowCount; i++) { System.Text.UnicodeEncoding converter = new UnicodeEncoding(); string messageName = converter.GetString(ropQueryRowsResponseOfFAIMessage.RowData.PropertyRows.ToArray()[i].PropertyValues[0].Value); if (messageName == ruleProperties.Name + "\0") { byte[] extendedRuleMessageActionBinary = ropQueryRowsResponseOfFAIMessage.RowData.PropertyRows.ToArray()[i].PropertyValues[4].Value; byte[] extendedRuleMessageActionBuffer = new byte[extendedRuleMessageActionBinary.Length - 2]; Array.Copy(extendedRuleMessageActionBinary, 2, extendedRuleMessageActionBuffer, 0, extendedRuleMessageActionBinary.Length - 2); ExtendedRuleActions extendedRuleActions = new ExtendedRuleActions(); extendedRuleActions.Deserialize(extendedRuleMessageActionBuffer); copyActionDataOfQueryRowsResponse.Deserialize(extendedRuleActions.RuleActionBuffer.Actions[0].ActionDataValue.Serialize()); } } // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R977"); bool isVerifiedR977 = Common.CompareByteArray(folder1EId, copyActionDataOfQueryRowsResponse.FolderEID); // Verify MS-OXORULE requirement: MS-OXORULE_R977 this.Site.CaptureRequirementIfIsTrue( isVerifiedR977, 977, @"[In OP_MOVE and OP_COPY ActionData Structure] [Buffer Format for Extended Rules] FolderEID (variable): A Folder EntryID structure, as specified in [MS-OXCDATA] section 2.2.4.1, [In OP_COPY action data] identifies the destination folder."); #endregion #endregion #region TestUser2 delivers a message to TestUser1 to trigger the rule. // 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); // Wait for the mail to be received and the rule to take effect. Thread.Sleep(this.WaitForTheRuleToTakeEffect); #endregion #region TestUser1 gets the message content to verify the rule evaluation. uint inboxFolderContentsTableHandle = 0; PropertyTag[] propertyTagList = new PropertyTag[1]; propertyTagList[0].PropertyId = (ushort)PropertyId.PidTagSubject; propertyTagList[0].PropertyType = (ushort)PropertyType.PtypString; uint rowCount = 0; RopQueryRowsResponse getInboxMailMessageContent = this.GetExpectedMessage(this.InboxFolderHandle, ref inboxFolderContentsTableHandle, propertyTagList, ref rowCount, 1, mailSubject); uint newFolder1ContentsTableHandle = 0; rowCount = 0; RopQueryRowsResponse getNewFolder1MailMessageContent = this.GetExpectedMessage(newFolderHandle, ref newFolder1ContentsTableHandle, propertyTagList, ref rowCount, 1, mailSubject); Site.Assert.AreEqual<uint>(0, getNewFolder1MailMessageContent.ReturnValue, "getNewFolder1MailMessageContent should succeed."); #region Capture code this.VerifyActionTypeOP_COPY(mailSubject, getNewFolder1MailMessageContent, getInboxMailMessageContent, ruleProperties); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R969, since the destination folder is created in the user's mailbox, try to verify the message was copy to the folder"); // Verify MS-OXORULE requirement: MS-OXORULE_R969 bool isVerifiedR969 = getInboxMailMessageContent.RowCount != 0 && getNewFolder1MailMessageContent.RowCount != 0; this.Site.CaptureRequirementIfIsTrue( isVerifiedR969, 969, @"[In OP_MOVE and OP_COPY ActionData Structure] [Buffer Format for Extended Rules] The destination folder for a Copy action in an extended rule MUST be in the user's mailbox."); #endregion #endregion #region Delete the newly created folder. RopDeleteFolderResponse deleteFolder = this.OxoruleAdapter.RopDeleteFolder(this.InboxFolderHandle, newFolderId); Site.Assert.AreEqual<uint>(0, deleteFolder.ReturnValue, "Deleting folder should succeed."); #endregion }
/// <summary> /// This method help to convert the property value, which is of variable bytes, to ExtendedRuleActions structure. /// </summary> /// <param name="byteArray">The byte array to be converted.</param> /// <returns>Return the ExtendedRuleActions structure.</returns> public static ExtendedRuleActions PropertyValueConvertToExtendedRuleActions(byte[] byteArray) { // The first 2 bytes of byteArray only indicates the total number of subsequent bytes, // byteArrayTobeConvert is the actual bytes used to convert to the ExtendedRuleActions structure, // which should not include the first 2 bytes of byteArray. byte[] byteArrayTobeConvert = new byte[byteArray.Length - 2]; Array.Copy(byteArray, 2, byteArrayTobeConvert, 0, byteArray.Length - 2); // De-serialize the byte array into the ExtendedRuleActions structure. ExtendedRuleActions extendedRuleActions = new ExtendedRuleActions(); extendedRuleActions.Deserialize(byteArrayTobeConvert); return extendedRuleActions; }
/// <summary> /// Generate test data for creating extended rule. /// </summary> /// <param name="rulename">The rule name.</param> /// <param name="ruleSequence">The rule sequence.</param> /// <param name="ruleState">The rule state.</param> /// <param name="provider">The rule provider.</param> /// <param name="actionType">The rule action Type.</param> /// <param name="actionData">The rule action data.</param> /// <param name="contentRestrictSubjectName">The subject name of the rule content restriction.</param> /// <param name="namedPropertyInfo">The namedPropertyInfo that needed for construct the rule data.</param> /// <returns>An array of TaggedPropertyValue of an extended rule.</returns> public static TaggedPropertyValue[] GenerateExtendedRuleTestData(string rulename, int ruleSequence, uint ruleState, string provider, ActionType actionType, IActionData actionData, string contentRestrictSubjectName, NamedPropertyInfo namedPropertyInfo) { List<TaggedPropertyValue> propList = new List<TaggedPropertyValue>(); TaggedPropertyValue pidTagRuleMessageName = new TaggedPropertyValue(); PropertyTag pidTagRuleMessageNameTag = new PropertyTag { PropertyId = (ushort)PropertyId.PidTagRuleMessageName, PropertyType = (ushort)PropertyType.PtypString }; pidTagRuleMessageName.PropertyTag = pidTagRuleMessageNameTag; pidTagRuleMessageName.Value = Encoding.Unicode.GetBytes(rulename + "\0"); propList.Add(pidTagRuleMessageName); TaggedPropertyValue pidTagMessageClass = new TaggedPropertyValue(); PropertyTag pidTagMessageClassTag = new PropertyTag { PropertyId = (ushort)PropertyId.PidTagMessageClass, PropertyType = (ushort)PropertyType.PtypString }; pidTagMessageClass.PropertyTag = pidTagMessageClassTag; pidTagMessageClass.Value = Encoding.Unicode.GetBytes(Constants.ExtendedRuleMessageClass + "\0"); propList.Add(pidTagMessageClass); TaggedPropertyValue pidTagRuleMessageSequence = new TaggedPropertyValue(); PropertyTag pidTagRuleMessageSequencePropertyTag = new PropertyTag { PropertyId = (ushort)PropertyId.PidTagRuleMessageSequence, PropertyType = (ushort)PropertyType.PtypInteger32 }; pidTagRuleMessageSequence.PropertyTag = pidTagRuleMessageSequencePropertyTag; pidTagRuleMessageSequence.Value = BitConverter.GetBytes(ruleSequence); propList.Add(pidTagRuleMessageSequence); TaggedPropertyValue pidTagRuleMessageState = new TaggedPropertyValue(); PropertyTag pidTagRuleMessageStatePropertyTag = new PropertyTag { PropertyId = (ushort)PropertyId.PidTagRuleMessageState, PropertyType = (ushort)PropertyType.PtypInteger32 }; pidTagRuleMessageState.PropertyTag = pidTagRuleMessageStatePropertyTag; pidTagRuleMessageState.Value = BitConverter.GetBytes(ruleState); propList.Add(pidTagRuleMessageState); TaggedPropertyValue pidTagRuleMessageLevel = new TaggedPropertyValue(); PropertyTag pidTagRuleMessageLevelPropertyTag = new PropertyTag { PropertyId = (ushort)PropertyId.PidTagRuleMessageLevel, PropertyType = (ushort)PropertyType.PtypInteger32 }; pidTagRuleMessageLevel.PropertyTag = pidTagRuleMessageLevelPropertyTag; pidTagRuleMessageLevel.Value = BitConverter.GetBytes(Constants.ExtendedRuleMessageLevel); propList.Add(pidTagRuleMessageLevel); TaggedPropertyValue pidTagRuleMessageProvider = new TaggedPropertyValue(); PropertyTag pidTagRuleMessageProviderPropertyTag = new PropertyTag { PropertyId = (ushort)PropertyId.PidTagRuleMessageProvider, PropertyType = (ushort)PropertyType.PtypString }; pidTagRuleMessageProvider.PropertyTag = pidTagRuleMessageProviderPropertyTag; pidTagRuleMessageProvider.Value = Encoding.Unicode.GetBytes(provider + "\0"); propList.Add(pidTagRuleMessageProvider); ExtendedRuleActions extendedRuleActions = new ExtendedRuleActions { NamedPropertyInformation = namedPropertyInfo }; extendedRuleActions.RuleVersion = Constants.ExtendedRuleVersion; extendedRuleActions.RuleActionBuffer = GetRuleAction(actionType, CountByte.FourBytesCount, actionData, Constants.CommonActionFlavor, Constants.RuleActionFlags); TaggedPropertyValue pidTagExtendedRuleMessageActions = new TaggedPropertyValue(); PropertyTag pidTagExtendedRuleMessageActionsPropertyTag = new PropertyTag { PropertyId = (ushort)PropertyId.PidTagExtendedRuleMessageActions, PropertyType = (ushort)PropertyType.PtypBinary }; pidTagExtendedRuleMessageActions.PropertyTag = pidTagExtendedRuleMessageActionsPropertyTag; pidTagExtendedRuleMessageActions.Value = Common.AddInt16LengthBeforeBinaryArray(extendedRuleActions.Serialize()); propList.Add(pidTagExtendedRuleMessageActions); TaggedPropertyValue pidTagExtendedRuleMessageCondition = new TaggedPropertyValue(); PropertyTag pidTagExtendedRuleMessageConditionPropertyTag = new PropertyTag { PropertyId = (ushort)PropertyId.PidTagExtendedRuleMessageCondition, PropertyType = (ushort)PropertyType.PtypBinary }; pidTagExtendedRuleMessageCondition.PropertyTag = pidTagExtendedRuleMessageConditionPropertyTag; TaggedPropertyValue taggedProperty = new TaggedPropertyValue(); PropertyTag taggedPropertyPropertyTag = new PropertyTag { PropertyId = (ushort)PropertyId.PidTagSubject, PropertyType = (ushort)PropertyType.PtypString }; taggedProperty.PropertyTag = taggedPropertyPropertyTag; taggedProperty.Value = Encoding.Unicode.GetBytes(contentRestrictSubjectName + "\0"); ContentRestriction contentRestriction = new ContentRestriction { FuzzyLevelLow = ContentRestriction.FuzzyLevelLowValue.FL_SUBSTRING, FuzzyLevelHigh = ContentRestriction.FuzzyLevelHighValue.FL_IGNORECASE, PropertyTag = taggedProperty.PropertyTag, TaggedValue = taggedProperty }; ExtendedRuleCondition extendedRuleCondition = new ExtendedRuleCondition { NamedPropertyInformation = namedPropertyInfo, RuleRestriction = contentRestriction }; pidTagExtendedRuleMessageCondition.Value = Common.AddInt16LengthBeforeBinaryArray(extendedRuleCondition.Serialize()); propList.Add(pidTagExtendedRuleMessageCondition); return propList.ToArray(); }
/// <summary> /// Verify ExtendedRuleActions buffer. /// </summary> /// <param name="extendeRuleActions">ExtendedRuleActions structure to be verified.</param> private void VerifyExtendedRuleMessageActions(ExtendedRuleActions extendeRuleActions) { // Get all of the Named Properties contained in the action buffer. PropertyName[] propertyNames = extendeRuleActions.NamedPropertyInformation.NamedProperty; // If the propertyNames exists, check whether the names' value contained in this structure are all in Unicode format. if (propertyNames != null) { // isContainNameValue is used to indicate whether exist nameValue in the PropertyName array. bool isContainNameValue = false; bool isVerifyR192 = true; // Check whether every name value contained in the PropertyName structure is in Unicode format. for (int i = 0; i < propertyNames.Length; i++) { // Get the name value contained in the action buffer. byte[] nameValue = propertyNames[i].Name; if (nameValue != null) { isContainNameValue = true; // If the nameValue cannot be converted to a Unicode string, it means the name value is not in Unicode format. if (Encoding.Unicode.GetString(nameValue) == null) { isVerifyR192 = false; break; } } } if (isContainNameValue) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R192"); // Verify MS-OXORULE requirement: MS-OXORULE_R192. Site.CaptureRequirementIfIsTrue( isVerifyR192, 192, @"[In PidTagExtendedRuleMessageActions Property] All string values contained in any part of the RuleAction structure MUST be in Unicode format."); } } // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R208."); // Verify MS-OXORULE requirement: MS-OXORULE_R208. Site.CaptureRequirementIfAreEqual<uint>( 0x00000001, extendeRuleActions.RuleVersion, 208, @"[In PidTagExtendedRuleMessageActions Property] RuleVersion (4 bytes): This document defines version 1, and thus this value MUST be set to 0x00000001."); // Verify the requirement related to the NamedPropertyInformation. this.VerifyNamedPropertyInformation(extendeRuleActions.NamedPropertyInformation); // Verify the requirement related to the RuleAction. this.VerifyExtendRuleAction(extendeRuleActions.RuleActionBuffer); // Add the debug information. // The format of the PidTagExtendedRuleMessageActions property: NamedPropertyInformation, RuleVersion, RuleActionsBuffer has been verified by above capture code, so R194 can be verified directly. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R194"); // Verify MS-OXORULE requirement: MS-OXORULE_R194. Site.CaptureRequirement( 194, @"[In PidTagExtendedRuleMessageActions Property] The format of the PidTagExtendedRuleMessageActions property is as follows: NamedPropertyInformation, RuleVersion, RuleActionsBuffer."); }
/// <summary> /// Query properties in contents table. /// </summary> /// <param name="tableHandle">Handle of a specific contents table.</param> /// <param name="propertyTags">Array of PropertyTag structures. This field specifies the property values that are visible in table rows.</param> /// <returns>Response of this query rows.</returns> public RopQueryRowsResponse QueryPropertiesInTable(uint tableHandle, PropertyTag[] propertyTags) { // Set the properties in propertyTags to be visible. RopSetColumnsResponse setColumnsResponse = this.RopSetColumns(tableHandle, 0x00, propertyTags); // Query properties values specified in propertyTags. RopQueryRowsResponse queryRowsResponse = this.RopQueryRows(tableHandle, 0x00, 0x01, 1000); // That the two Rops are successful means that the propertyTags in request is correct if (setColumnsResponse.ReturnValue == 0 && queryRowsResponse.ReturnValue == 0 && queryRowsResponse.RowData.PropertyRows != null) { // Verify PropertyTags this.VerifyPropertiesInTable(propertyTags, queryRowsResponse); for (int i = 0; i < propertyTags.Length; i++) { // If the property queried is PidTagRuleActions if (propertyTags[i].PropertyId == (ushort)PropertyId.PidTagRuleActions) { for (int j = 0; j < queryRowsResponse.RowData.PropertyRows.Count; j++) { // Verify structure RuleAction RuleAction ruleAction = new RuleAction(); ruleAction.Deserialize(queryRowsResponse.RowData.PropertyRows[j].PropertyValues[i].Value); this.VerifyRuleAction(ruleAction); } } // If the property queried is PidTagExtendedRuleMessageActions if (propertyTags[i].PropertyId == (ushort)PropertyId.PidTagExtendedRuleMessageActions) { for (int j = 0; j < queryRowsResponse.RowData.PropertyRows.Count; j++) { if (BitConverter.ToUInt32(queryRowsResponse.RowData.PropertyRows[j].PropertyValues[i].Value, 0) != (uint)ErrorCodeValue.NotFound) { // Verify structure RuleAction ExtendedRuleActions ruleAction = new ExtendedRuleActions(); byte[] extendedRuleMessageActionBuffer = new byte[queryRowsResponse.RowData.PropertyRows[j].PropertyValues[i].Value.Length - 2]; Array.Copy(queryRowsResponse.RowData.PropertyRows[j].PropertyValues[i].Value, 2, extendedRuleMessageActionBuffer, 0, queryRowsResponse.RowData.PropertyRows[j].PropertyValues[i].Value.Length - 2); ruleAction.Deserialize(extendedRuleMessageActionBuffer); this.VerifyExtendRuleAction(ruleAction.RuleActionBuffer); } } } } } return queryRowsResponse; }