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> /// Verify RuleAction buffer for stand rule. /// </summary> /// <param name="ruleAction">RuleAction structure to be verified.</param> private void VerifyRuleAction(RuleAction ruleAction) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R232, The value of NoOfActions is {0}", ruleAction.NoOfActions); // Verify MS-OXORULE requirement: MS-OXORULE_R232. // NoOfActions can be either unsigned-integer or unsigned-short. uint actionsNumber = (ruleAction.NoOfActions is uint) ? ((uint)ruleAction.NoOfActions) : ((ushort)ruleAction.NoOfActions); bool isVerifyR232 = actionsNumber > 0; Site.CaptureRequirementIfIsTrue( isVerifyR232, 232, @"[In RuleAction Structure] NoOfActions (2 bytes): This number MUST be greater than zero."); foreach (ActionBlock actionBlock in ruleAction.Actions) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R236"); // Verify MS-OXORULE requirement: MS-OXORULE_R236. // There are 2 or 4 bytes of the ActionLength in the ActionBlocks, // so the cumulative length in bytes of the subsequent fields of the ActionLength must equal to the length of ActionBlock.length - lengthOfActionLength. int lengthOfActionLength = actionBlock.ActionLength is ushort ? 2 : 4; bool isVerifyR236 = (actionBlock.ActionLength is ushort ? (ushort)actionBlock.ActionLength : (uint)actionBlock.ActionLength) == (actionBlock.Serialize().Length - lengthOfActionLength); Site.CaptureRequirementIfIsTrue( isVerifyR236, 236, @"[In ActionBlock Structure] ActionLength (2 bytes): An integer that specifies the cumulative length, in bytes, of the subsequent fields in this ActionBlock structure."); // Verify MS-OXORULE requirement: MS-OXORULE_R947. bool isVerifyR947 = (byte)actionBlock.ActionType == 0x01 || (byte)actionBlock.ActionType == 0x02 || (byte)actionBlock.ActionType == 0x03 || (byte)actionBlock.ActionType == 0x04 || (byte)actionBlock.ActionType == 0x05 || (byte)actionBlock.ActionType == 0x06 || (byte)actionBlock.ActionType == 0x07 || (byte)actionBlock.ActionType == 0x08 || (byte)actionBlock.ActionType == 0x09 || (byte)actionBlock.ActionType == 0x0A || (byte)actionBlock.ActionType == 0x0B; Site.CaptureRequirementIfIsTrue( isVerifyR947, 947, @"[In RuleAction Structure] ActionBlocks (variable): An array of ActionBlock structures, each of which specifies an action (2) of the rule (2), as specified in section 2.2.5.1."); } // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R231"); // Verify MS-OXORULE requirement: MS-OXORULE_R231. Site.CaptureRequirementIfAreEqual<uint>( (uint)ruleAction.Actions.Length, actionsNumber, 231, @"[In RuleAction Structure] NoOfActions (2 bytes): Specifies the number of structures that are contained in the ActionBlocks field."); // isVerifyR274 is used to verify R274 and R272. bool isVerifyR274 = false; // isVerifyR287 is used to verify R287 and R272. bool isVerifyR287 = false; // isVerifyR879 is used to verify R879 and R272. bool isVerifyR879 = false; for (int i = 0; i < ruleAction.Actions.Length; i++) { ActionBlock actionBlock = ruleAction.Actions[i]; // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R245", "The value of the actionBlock.ActionType{0} should be one of 0x01 to 0x0b", actionBlock.ActionType); // Verify MS-OXORULE requirement: MS-OXORULE_R245. bool isVerifyR245 = (byte)actionBlock.ActionType == 0x01 || (byte)actionBlock.ActionType == 0x02 || (byte)actionBlock.ActionType == 0x03 || (byte)actionBlock.ActionType == 0x04 || (byte)actionBlock.ActionType == 0x05 || (byte)actionBlock.ActionType == 0x06 || (byte)actionBlock.ActionType == 0x07 || (byte)actionBlock.ActionType == 0x08 || (byte)actionBlock.ActionType == 0x09 || (byte)actionBlock.ActionType == 0x0A || (byte)actionBlock.ActionType == 0x0B; Site.CaptureRequirementIfIsTrue( isVerifyR245, 245, @"[In ActionBlock Structure] The valid actions (2) [of ActionType] are listed in the following table: OP_MOVE, OP_COPY, OP_REPLY, OP_OOF_REPLY, OP_DEFER_ACTION, OP_BOUNCE, OP_FORWARD, OP_DELEGATE, OP_TAG, OP_DELETE, OP_MARK_AS_READ."); if ((actionBlock.ActionType == ActionType.OP_MOVE) || (actionBlock.ActionType == ActionType.OP_COPY)) { MoveCopyActionData moveCopyActionData = (MoveCopyActionData)actionBlock.ActionDataValue; ServerEID serverEID = new ServerEID(moveCopyActionData.FolderEID); // The storeObjectEntryID structure could only verified in ExchangeServer2007, R632 also only executed in ExchangeServer2007. if (Common.IsRequirementEnabled(632, this.Site)) { StoreObjectEntryID storeObjectEntryID = new StoreObjectEntryID(); storeObjectEntryID.Deserialize(moveCopyActionData.StoreEID); this.VerifyStoreObjectEntryID(storeObjectEntryID); } // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R982: the value of Ours is {0}", serverEID.Ours); // Verify MS-OXORULE_R982. Site.CaptureRequirementIfAreEqual<ushort>( 0x01, serverEID.Ours, 982, @"[In ServerEid Structure] Ours (1 byte): This field MUST be set to 0x01."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R980"); // Verify MS-OXORULE requirement: MS-OXORULE_R980 // Verify MS-OXORULE_R982 has verified the value of Ours is 0x01, MS-OXORULE_R980 verifies the instance's type. this.Site.CaptureRequirementIfIsInstanceOfType( serverEID, typeof(ServerEID), 980, @"[In ServerEid Structure] Ours (1 byte): The value 0x01 indicates that the remaining bytes conform to this structure [ServerEid]."); if (moveCopyActionData.StoreEIDSize != 0) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R297"); // Verify MS-OXORULE_R297. Site.CaptureRequirementIfAreEqual<ushort>( (ushort)moveCopyActionData.StoreEID.Length, moveCopyActionData.StoreEIDSize, 297, @"[In OP_MOVE and OP_COPY ActionData Structure] [Buffer Format for Standard Rules] StoreEIDSize (2 bytes): An integer that specifies the size, in bytes, of the StoreEID field."); } // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R300"); // Verify MS-OXORULE_R300. Site.CaptureRequirementIfAreEqual<ushort>( (ushort)moveCopyActionData.FolderEID.Length, moveCopyActionData.FolderEIDSize, 300, @"[In OP_MOVE and OP_COPY ActionData Structure] [Buffer Format for Standard Rules] FolderEIDSize (2 bytes): An integer that specifies the size, in bytes, of the FolderEID field."); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R294"); // Verify MS-OXORULE_R294. // The structure of the OP_MOVE Action Date Buffer is verified by the requirements MS-OXORULE_R297, MS-OXORULE_R298, MS-OXORULE_R300, and MS-OXORULE_R301. Site.CaptureRequirement( 294, @"[In OP_MOVE and OP_COPY ActionData Structure] [Buffer Format for Standard Rules] The OP_MOVE ActionData structure MUST be in the following format for a standard rule. [FolderInThisStore, StoreEIDSize, StoreEID, FolderEIDSize, and FolderEID]."); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R880"); // Verify MS-OXORULE_R880. // The structure of the OP_MOVE Action Date Buffer is verified by the requirements MS-OXORULE_R297, MS-OXORULE_R298, MS-OXORULE_R300, and MS-OXORULE_R301. Site.CaptureRequirement( 880, @"[In OP_MOVE and OP_COPY ActionData Structure] [Buffer Format for Standard Rules] The OP_COPY ActionData structure MUST be in the following format for a standard rule. [FolderInThisStore, StoreEIDSize, StoreEID, FolderEIDSize, and FolderEID]."); } if (actionBlock.ActionType == ActionType.OP_COPY) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R249"); // Verify MS-OXORULE requirement: MS-OXORULE_R249. // If the ActionType of the actionBlock equals the value ActionType.OP_COPY means server could parse the ActionType 0x02. Site.CaptureRequirement( 249, @"[In ActionBlock Structure] The value of action type OP_COPY: 0x02."); } if (actionBlock.ActionType == ActionType.OP_MOVE) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R246"); // Verify MS-OXORULE requirement: MS-OXORULE_R246. // If the ActionType of the actionBlock equals the value ActionType.OP_MOVE means server could parse the ActionType 0x01. Site.CaptureRequirement( 246, @"[In ActionBlock Structure] The value of action type OP_MOVE: 0x01."); } if (actionBlock.ActionType == ActionType.OP_FORWARD) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R261"); // Verify MS-OXORULE requirement: MS-OXORULE_R261. // If the ActionType of the actionBlock equals the value ActionType.OP_FORWARD means server could parse the ActionType 0x07. Site.CaptureRequirement( 261, @"[In ActionBlock Structure] The value of action type OP_FORWARD: 0x07."); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R274, the value of ActionFlavor is {0}, the ActionFlavorsForward.x is {1}.", actionBlock.ActionFlavor, ActionFlavorsForward.x); // Verify MS-OXORULE requirement: MS-OXORULE_R274. // In ActionFlavor, the not used Flags must not be set, the used Flags can be set or all the bits are not set, it means ActionFlavor is set according to the description in this requirement. isVerifyR274 = (actionBlock.ActionFlavor & (uint)ActionFlavorsForward.x) == 0; Site.CaptureRequirementIfIsTrue( isVerifyR274, 274, @"[In Action Flavors] If the value of the ActionType field is ""OP_FORWARD"", the ActionFlavor field contains a combination of the bitwise flags [XXXX (TM) (AT) (NC) (PR) XXXXXXXXXXXXXXXXXXXXXXXXXX] specified as follows."); } if ((actionBlock.ActionType == ActionType.OP_REPLY) || (actionBlock.ActionType == ActionType.OP_OOF_REPLY)) { ReplyActionData actionData = new ReplyActionData(); actionData.Deserialize(ruleAction.Actions[0].ActionDataValue.Serialize()); if (actionBlock.ActionType == ActionType.OP_REPLY) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R287, the value of ActionFlavor is {0}, it should be one of ActionFlavorsReply.NS({1}), ActionFlavorsReply.ST({2}), or 0x00000000", actionBlock.ActionFlavor, ActionFlavorsReply.NS, ActionFlavorsReply.ST); // Verify MS-OXORULE requirement: MS-OXORULE_R287. // According to open specification, in this condition, the allowed value of ActionFlavor are NS, ST and 0x00000000. isVerifyR287 = (actionBlock.ActionFlavor == (uint)ActionFlavorsReply.NS) || (actionBlock.ActionFlavor == (uint)ActionFlavorsReply.ST) || (actionBlock.ActionFlavor == 0x00000000); Site.CaptureRequirementIfIsTrue( isVerifyR287, 287, @"[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)."); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R252"); // Verify MS-OXORULE requirement: MS-OXORULE_R252. // If the ActionType of the actionBlock equals the value ActionType.OP_REPLY means server could parse the ActionType 0x03. Site.CaptureRequirement( 252, @"[In ActionBlock Structure] The value of action type OP_REPLY: 0x03."); bool isVerifyR992 = actionData.ReplyTemplateGUID.Length != 0 && actionData.ReplyTemplateFID != 0 && actionData.ReplyTemplateMID != 0; // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R992"); // Verify MS-OXORULE requirement: MS-OXORULE_R992. // If ReplyTemplateFID, ReplyTemplateMID, ReplyTemplateGUID in the ActionData is not null, R992 can be verified. Site.CaptureRequirementIfIsTrue( isVerifyR992, 992, @"[OP_REPLY and OP_OOF_REPLY ActionData Structure] [Buffer Format for Standard Rules] The OP_REPLY ActionData structure MUST be in the following format for a standard rule. [ReplyTemplateFID, ReplyTemplateMID, ReplyTemplateGUID]"); } ReplyActionData replyActionData = (ReplyActionData)actionBlock.ActionDataValue; // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R308"); // Verify MS-OXORULE requirement: MS-OXORULE_R308. Site.CaptureRequirementIfIsTrue( Common.IsGUID(replyActionData.ReplyTemplateGUID), 308, @"[OP_REPLY and OP_OOF_REPLY ActionData Structure] [Buffer Format for Standard Rules] ReplyTemplateGUID (16 bytes): A GUID that is generated by the client in the process of creating a reply template."); if (actionBlock.ActionType == ActionType.OP_OOF_REPLY) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R879, the value of ActionFlavor is {0}", "it should be one of ActionFlavorsReply.NS({1}), ActionFlavorsReply.ST({2}), or 0x00000000", actionBlock.ActionFlavor, ActionFlavorsReply.NS, ActionFlavorsReply.ST); // Verify MS-OXORULE requirement: MS-OXORULE_R879. // According to open specification, in this condition, the allowed value of ActionFlavor are NS, ST and 0x00000000. isVerifyR879 = (actionBlock.ActionFlavor == (uint)ActionFlavorsReply.NS) || (actionBlock.ActionFlavor == (uint)ActionFlavorsReply.ST) || (actionBlock.ActionFlavor == 0x00000000); Site.CaptureRequirementIfIsTrue( isVerifyR879, 879, @"[In Action Flavors] If the ActionType field value is ""OP_OOF_REPLY"", the ActionFlavor field MUST have one of the values specified in the following table [XXXXXX (ST) (NS) XXXXXXXXXXXXXXXXXXXXXXXX] or zero (0x00000000). "); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R254"); // Verify MS-OXORULE requirement: MS-OXORULE_R254. // If the ActionType of the actionBlock equals the value ActionType. OP_OOF_REPLY means server could parse the ActionType and its value must be 0x04. Site.CaptureRequirement( 254, @"[In ActionBlock Structure] The value of action type OP_OOF_REPLY: 0x04."); bool isVerifyR993 = actionData.ReplyTemplateGUID.Length != 0 && actionData.ReplyTemplateFID != 0 && actionData.ReplyTemplateMID != 0; // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R993"); // Verify MS-OXORULE requirement: MS-OXORULE_R993. // If ReplyTemplateFID, ReplyTemplateMID, ReplyTemplateGUID in the ActionData is not null, R993 can be verified. Site.CaptureRequirementIfIsTrue( isVerifyR993, 993, @"[OP_REPLY and OP_OOF_REPLY ActionData Structure] [Buffer Format for Standard Rules] The OP_OOF_REPLY ActionData structure MUST be in the following format for a standard rule. [ReplyTemplateFID, ReplyTemplateMID, ReplyTemplateGUID]"); } FolderID folderID = new FolderID(); folderID.Deserialize(replyActionData.ReplyTemplateFID); if (folderID != null) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R2175"); // Verify MS-OXCDATA requirement: MS-OXCDATA_R2175. Site.CaptureRequirementIfAreEqual<int>( 8, folderID.Size, "MS-OXCDATA", 2175, @"[In Folder ID Structure] It [Folder ID] is an 8-byte structure."); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R2176"); // Verify MS-OXCDATA requirement: MS-OXCDATA_R2176. // "Identifying a Store object" is informative. Site.CaptureRequirementIfAreEqual<int>( 2, folderID.ReplicaId.Length, "MS-OXCDATA", 2176, @"[In Folder ID Structure] ReplicaId (2 bytes): An unsigned integer identifying a Store object."); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R2177"); // Verify MS-OXCDATA requirement: MS-OXCDATA_R2177. // "Identifying the folder within its Store object" is informative. Site.CaptureRequirementIfAreEqual<int>( 6, folderID.GlobalCounter.Length, "MS-OXCDATA", 2177, @"[In Folder ID Structure] GlobalCounter (6 bytes): An unsigned integer identifying the folder within its Store object."); } MessageID messageID = new MessageID(); messageID.Deserialize(replyActionData.ReplyTemplateMID); if (messageID != null) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R2180"); // Verify MS-OXCDATA requirement: MS-OXCDATA_R2180. Site.CaptureRequirementIfAreEqual<int>( 8, messageID.Size, "MS-OXCDATA", 2180, @"[In Message ID Structure] It [Message ID] is an 8-byte structure."); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R2181"); // Verify MS-OXCDATA requirement: MS-OXCDATA_R2181. // "Identifying a Store object" is informative. Site.CaptureRequirementIfAreEqual<int>( 2, messageID.ReplicaId.Length, "MS-OXCDATA", 2181, @"[In Message ID Structure] ReplicaId (2 bytes): An unsigned integer identifying a Store object."); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R2182"); // Verify MS-OXCDATA requirement: MS-OXCDATA_R2182. // "Identifying the message within its Store object" is informative. Site.CaptureRequirementIfAreEqual<int>( 6, messageID.GlobalCounter.Length, "MS-OXCDATA", 2182, @"[In Message ID Structure] GlobalCounter (6 bytes): An unsigned integer identifying the message within its Store object."); } } if (actionBlock.ActionType == ActionType.OP_DEFER_ACTION) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R256"); // Verify MS-OXORULE requirement: MS-OXORULE_R256. // If the ActionType of the actionBlock equals the value ActionType.OP_DEFER_ACTION means server could parse the ActionType 0x05. Site.CaptureRequirement( 256, @"[In ActionBlock Structure] The value of action type OP_DEFER_ACTION: 0x05."); } if (actionBlock.ActionType == ActionType.OP_TAG) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R265"); // Verify MS-OXORULE requirement: MS-OXORULE_R265. // If the ActionType of the actionBlock equals the value ActionType.OP_TAG means server could parse the ActionType 0x09. Site.CaptureRequirement( 265, @"[In ActionBlock Structure] The value of action type OP_TAG: 0x09."); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R739"); // Verify MS-OXORULE requirement: MS-OXORULE_R739. // If the taggedPropertyValueOP_TAG is not null means the action data buffer can be parsed by the TaggedPropertyValue. TaggedPropertyValue taggedPropertyValueOP_Tag = AdapterHelper.ReadTaggedProperty(actionBlock.ActionDataValue.Serialize()); Site.CaptureRequirementIfIsNotNull( taggedPropertyValueOP_Tag, 739, @"[In OP_TAG ActionData Structure] An OP_TAG ActionData structure is a TaggedPropertyValue structure, packaged as specified in [MS-OXCDATA] section 2.11.4."); } if ((actionBlock.ActionType == ActionType.OP_FORWARD) || (actionBlock.ActionType == ActionType.OP_REPLY) || (actionBlock.ActionType == ActionType.OP_OOF_REPLY)) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R272", "The value of the ActionFlavor is {0}, and the ActionType is {1}", actionBlock.ActionFlavor, actionBlock.ActionType); // Verify MS-OXORULE requirement: MS-OXORULE_R272. // According to open specification, the only action types that support the Action Flavor are OP_REPLY, OP_OOF_REPLY and OP_FORWARD. // The setting of ActionFlavor is verified in R274 and R287, so the condition to verify R272 is "isVerifyR274 || isVerifyR287". Site.CaptureRequirementIfIsTrue( isVerifyR274 || isVerifyR287 || isVerifyR879, 272, @"[In Action Flavors] The only ActionType field values that currently support an Action Flavor are ""OP_REPLY"", ""OP_OOF_REPLY"" and ""OP_FORWARD""."); } else { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R273"); // Verify MS-OXORULE requirement: MS-OXORULE_R273. Site.CaptureRequirementIfAreEqual<uint>( 0, actionBlock.ActionFlavor, 273, @"[In Action Flavors] The value of the ActionFlavor field MUST be 0x00000000 if the value of the ActionType field is not one of these values [OP_REPLY, OP_OOF_REPLY, and OP_FORWARD]."); } // When the AT flag in ActionFlavor is set. if ((actionBlock.ActionFlavor & (uint)ActionFlavorsForward.AT) == (uint)ActionFlavorsForward.AT) { // Verify MS-OXORULE requirement: MS-OXORULE_R280. uint otherActionFlavorFlags = (uint)ActionFlavorsForward.PR | (uint)ActionFlavorsForward.NC | (uint)ActionFlavorsForward.TM | (uint)ActionFlavorsForward.x; // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R280, the value of ActionFlavor is {0}, this value should not be combined with otherActionFlavorFlags({1}).", actionBlock.ActionFlavor, otherActionFlavorFlags); // To verify whether the other ActionFlavor Flags are 0 when the AT flag in ActionFlavor is set. bool isVerifyR280 = (actionBlock.ActionFlavor & otherActionFlavorFlags) == 0; Site.CaptureRequirementIfIsTrue( isVerifyR280, 280, @"[In Action Flavors] AT (Bitmask 0x00000004): This value MUST NOT be combined with other ActionFlavor flags."); } // When the TM flag in ActionFlavor is set. if ((actionBlock.ActionFlavor & (uint)ActionFlavorsForward.TM) == (uint)ActionFlavorsForward.TM) { // Verify MS-OXORULE requirement: MS-OXORULE_R283. uint otherActionFlavorFlags = (uint)ActionFlavorsForward.PR | (uint)ActionFlavorsForward.NC | (uint)ActionFlavorsForward.AT | (uint)ActionFlavorsForward.x; // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R283, the value of ActionFlavor is {0}, this value should not be combined with otherActionFlavorFlags({1}).", actionBlock.ActionFlavor, otherActionFlavorFlags); // To verify whether the other ActionFlavor Flags are 0 when the TM flag in ActionFlavor is set. bool isVerifyR283 = (actionBlock.ActionFlavor & otherActionFlavorFlags) == 0; Site.CaptureRequirementIfIsTrue( isVerifyR283, 283, @"[In Action Flavors] TM (Bitmask 0x00000008): This value MUST NOT be combined with other ActionFlavor flags."); } if (actionBlock.ActionType == ActionType.OP_FORWARD && Common.IsRequirementEnabled(636, this.Site)) { ForwardDelegateActionData forwardOrDelegateData = (ForwardDelegateActionData)actionBlock.ActionDataValue; // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R636"); // Verify MS-OXORULE requirement: MS-OXORULE_R636. bool isVerifyR636 = true; foreach (RecipientBlock recipientBlock in forwardOrDelegateData.RecipientsData) { // Whether the PidTagEntryId exists. bool hasPidTagEntryId = false; foreach (TaggedPropertyValue property in recipientBlock.PropertiesData) { // propertyID of PidTagEntryId is 0x0FFF. if (property.PropertyTag.PropertyId == 0x0FFF) { hasPidTagEntryId = true; } } if (!hasPidTagEntryId) { isVerifyR636 = false; break; } } Site.CaptureRequirementIfIsTrue( isVerifyR636, 636, @"[In Appendix A: Product Behavior] Implementation does require the PidTagEntryId property for action ""OP_FORWARD"". [<8> Section 2.2.5.1.2.4.1: Exchange 2003 and Exchange 2007 also require the PidTagEntryId property for action ""OP_FORWARD"".]"); } if ((actionBlock.ActionType == ActionType.OP_FORWARD) || (actionBlock.ActionType == ActionType.OP_DELEGATE)) { if (actionBlock.ActionType == ActionType.OP_DELEGATE) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R263"); // Verify MS-OXORULE requirement: MS-OXORULE_R263. // If the ActionType of the actionBlock equals the value ActionType.DELEGATE means server could parse the ActionType 0x08. Site.CaptureRequirement( 263, @"[In ActionBlock Structure] The value of action type OP_DELEGATE: 0x08."); } ForwardDelegateActionData forwardOrDelegateData = (ForwardDelegateActionData)actionBlock.ActionDataValue; // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R323, the recipient count is {0}.", forwardOrDelegateData.RecipientCount); // Verify MS-OXORULE requirement: MS-OXORULE_R323. bool isVerifyR323 = (forwardOrDelegateData.RecipientCount is ushort ? (ushort)forwardOrDelegateData.RecipientCount : (uint)forwardOrDelegateData.RecipientCount) == forwardOrDelegateData.RecipientsData.Length; Site.CaptureRequirementIfIsTrue( isVerifyR323, 323, @"[In OP_FORWARD and OP_DELEGATE ActionData Structure] RecipientCount (4 bytes): An integer that specifies the number of RecipientBlockData structures, as specified in section 2.2.5.1.2.4.1, contained in the RecipientBlocks field. "); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R324", "The value of the RecipientCount is {0}, it should greater than 0.", forwardOrDelegateData.RecipientCount); // Verify MS-OXORULE requirement: MS-OXORULE_R324. // The RecipientCount can be either unsigned-integer or unsigned-short. uint recipientCount = (forwardOrDelegateData.RecipientCount is uint) ? ((uint)forwardOrDelegateData.RecipientCount) : ((ushort)forwardOrDelegateData.RecipientCount); bool isVerifyR324 = recipientCount > 0; Site.CaptureRequirementIfIsTrue( isVerifyR324, 324, @"[In OP_FORWARD and OP_DELEGATE ActionData Structure] RecipientCount (4 bytes): This number MUST be greater than zero."); bool isVerifyR633 = true; bool isVerifyR632 = true; bool isVerifyR331 = true; foreach (RecipientBlock recipientBlock in forwardOrDelegateData.RecipientsData) { if (Common.IsRequirementEnabled(633, this.Site)) { if (recipientBlock.Reserved != 0x00) { isVerifyR633 = false; break; } } if (Common.IsRequirementEnabled(632, this.Site)) { if (recipientBlock.Reserved != 0x01) { isVerifyR632 = false; break; } } // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R330, the NoOfProperties of the RecipientBlock is {0}.", recipientBlock.NoOfProperties); // Verify MS-OXORULE requirement: MS-OXORULE_R330. bool isVerifyR330 = (recipientBlock.NoOfProperties is ushort ? (ushort)recipientBlock.NoOfProperties : (uint)recipientBlock.NoOfProperties) == (ulong)recipientBlock.PropertiesData.Length; Site.CaptureRequirementIfIsTrue( isVerifyR330, 330, @"[In RecipientBlockData Structure] NoOfProperties (4 bytes): An integer that specifies the number of structures present in the PropertyValues field."); TaggedPropertyValue[] taggedPropertyValue = recipientBlock.PropertiesData; bool isVerifyR468 = taggedPropertyValue[0].PropertyTag.PropertyId != 0 && taggedPropertyValue[0].PropertyTag.PropertyType != 0; // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R468"); // Verify MS-OXCDATA requirement: MS-OXCDATA_R468. Site.CaptureRequirementIfIsTrue( isVerifyR468, "MS-OXCDATA", 468, @"[In TaggedPropertyValue Structure] PropertyTag (4 bytes): A PropertyTag structure, as specified in section 2.9, giving the values of the PropertyId and PropertyType fields for the property."); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R469"); PropertyValue propertyValue = (PropertyValue)taggedPropertyValue[0]; // Verify MS-OXCDATA requirement: MS-OXCDATA_R469. Site.CaptureRequirementIfIsInstanceOfType( propertyValue, typeof(PropertyValue), "MS-OXCDATA", 469, @"[In TaggedPropertyValue Structure] PropertyValue (variable): A PropertyValue structure, as specified in section 2.11.2.1."); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R1008"); // Verify MS-OXORULE requirement: MS-OXORULE_R1008. // The format of the TaggedPropertyValue structure has been verified by MS-OXCDATA_R468, and MS-OXCDATA_R469. Site.CaptureRequirement( 1008, @"[In RecipientBlockData Structure] The format of the TaggedPropertyValue structure is specified in [MS-OXCDATA] section 2.11.4."); // Verify MS-OXORULE requirement: MS-OXORULE_R331. uint properties = (recipientBlock.NoOfProperties is uint) ? ((uint)recipientBlock.NoOfProperties) : ((ushort)recipientBlock.NoOfProperties); if (properties <= 0) { isVerifyR331 = false; break; } } if (Common.IsRequirementEnabled(633, this.Site)) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R633"); Site.CaptureRequirementIfIsTrue( isVerifyR633, 633, @"[[In Appendix A: Product Behavior] Implementation does set this value [Reserved (1 byte)] to 0x00. [<9> Section 2.2.5.1.2.4.1: Exchange 2010, Exchange 2013, and Exchange 2016 set this value to 0x00.]"); } if (Common.IsRequirementEnabled(632, this.Site)) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R632"); Site.CaptureRequirementIfIsTrue( isVerifyR632, 632, @"[In Appendix A: Product Behavior] Implementation does set this value [Reserved (1 byte)] to 0x01. [<9> Section 2.2.5.1.2.4.1: Exchange 2003 and Exchange 2007 set this value to 0x01.]"); } // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R331"); // Verify MS-OXORULE requirement: MS-OXORULE_R331. Site.CaptureRequirementIfIsTrue( isVerifyR331, 331, @"[In RecipientBlockData Structure] NoOfProperties (4 bytes): This number MUST be greater than zero."); if (Common.IsRequirementEnabled(895, this.Site)) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R895"); // Verify requirement: MS-OXORULE_R895. bool isVerifyR895 = true; foreach (RecipientBlock recipientBlock in forwardOrDelegateData.RecipientsData) { // Whether the PidTagDisplayName exists. bool hasPidTagDisplayName = false; // Whether the PidTagEmailAddress exists. bool hasPidTagEmailAddress = false; // Whether the PidTagRecipientType exists. bool hasPidTagRecipientType = false; foreach (TaggedPropertyValue property in recipientBlock.PropertiesData) { // propertyID of hasPidTagDisplayName is 0x3001. if (property.PropertyTag.PropertyId == 0x3001) { hasPidTagDisplayName = true; } // propertyID of PidTagEmailAddress is 0x3003. if (property.PropertyTag.PropertyId == 0x3003) { hasPidTagEmailAddress = true; } // propertyID of PidTagRecipientType is 0x0C15. if (property.PropertyTag.PropertyId == 0x0C15) { hasPidTagRecipientType = true; } } if (!(hasPidTagDisplayName && hasPidTagEmailAddress && hasPidTagRecipientType)) { isVerifyR895 = false; break; } } // Verify MS-OXORULE requirement: MS-OXORULE_R895. Site.CaptureRequirementIfIsTrue( isVerifyR895, 895, @"[In RecipientBlock Data Buffer Packet Structure] No rules (2) does require more [specify values for more properties besides the PidTagDisplayName, PidTagEmailAddress, and PidTagRecipientType in the forward/delegate ActionData buffer] on the implementation. (Exchange 2010 and above follow this behavior.)"); } } if (actionBlock.ActionType == ActionType.OP_BOUNCE) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R259"); // Verify MS-OXORULE requirement: MS-OXORULE_R259. // If the ActionType of the actionBlock equals the value ActionType.OP_COPY means server could parse the ActionType 0x06. Site.CaptureRequirement( 259, @"[In ActionBlock Structure] The value of action type OP_BOUNCE: 0x06."); BounceActionData bounceActionData = (BounceActionData)actionBlock.ActionDataValue; // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R340", "The value of the BounceCode field is {0}.", bounceActionData.Bounce); // Verify MS-OXORULE requirement: MS-OXORULE_R340. bool isVerifyR340 = (uint)bounceActionData.Bounce == 0x0000000D || (uint)bounceActionData.Bounce == 0x0000001F || (uint)bounceActionData.Bounce == 0x00000026; Site.CaptureRequirementIfIsTrue( isVerifyR340, 340, @"[In OP_BOUNCE ActionData Structure] The bounce code MUST be one of the following values. [0x0000000D, 0x0000001F, and 0x00000026]."); } if ((actionBlock.ActionType == ActionType.OP_DELETE) || (actionBlock.ActionType == ActionType.OP_MARK_AS_READ)) { if (actionBlock.ActionType == ActionType.OP_DELETE) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R267"); // If the ActionType of the actionBlock equals the value ActionType.OP_MOVE means server could parse the ActionType 0x0A. Site.CaptureRequirement( 267, @"[In ActionBlock Structure] The value of action type OP_DELETE: 0x0A."); } if (actionBlock.ActionType == ActionType.OP_MARK_AS_READ) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R269"); // If the ActionType of the actionBlock equals the value ActionType.OP_COPY means server could parse the ActionType 0x0B. Site.CaptureRequirement( 269, @"[In ActionBlock Structure] The value of action type OP_MARK_AS_READ: 0x0B."); } // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R346"); // Verify MS-OXORULE requirement: MS-OXORULE_R346. // If the Size of ActionDataValue is 0, it means these actions have no ActionData buffer. Site.CaptureRequirementIfAreEqual<int>( 0, actionBlock.ActionDataValue.Size(), 346, @"[In OP_DELETE or OP_MARK_AS_READ ActionData Structure] These actions [OP_DELETE, OP_MARK_AS_READ] (3) have no ActionData structure."); } } }