/// <summary> /// Parses a response with multiple ROPs. In this scenario, the response is designed as only containing two ROPs: RopSetColumn and RopQueryRows. /// </summary> /// <param name="rgbOutput">The raw data that contains the ROP response payload</param> /// <returns>The ROP response list which contains RopSetColumnResponse and RopQueryRawResponse</returns> private List<IDeserializable> ParseMultipleRopsResponse(byte[] rgbOutput) { int parseByteLength = 0; List<IDeserializable> multipleRopsResponse = new List<IDeserializable>(); RPC_HEADER_EXT rpcHeader = new RPC_HEADER_EXT { Version = BitConverter.ToUInt16(rgbOutput, parseByteLength) }; // Parse RPC_HEADER_EXT structure parseByteLength += sizeof(short); rpcHeader.Flags = BitConverter.ToUInt16(rgbOutput, parseByteLength); parseByteLength += sizeof(short); rpcHeader.Size = BitConverter.ToUInt16(rgbOutput, parseByteLength); parseByteLength += sizeof(short); rpcHeader.SizeActual = BitConverter.ToUInt16(rgbOutput, parseByteLength); parseByteLength += sizeof(short); // Passed 2 bytes which is size of ROP response. parseByteLength += sizeof(short); // Parse RopSetColumns response RopSetColumnsResponse setColumnsResponse = new RopSetColumnsResponse(); parseByteLength += setColumnsResponse.Deserialize(rgbOutput, parseByteLength); // Parse RopQueryRows response RopQueryRowsResponse queryRowsResponse = new RopQueryRowsResponse(); parseByteLength += queryRowsResponse.Deserialize(rgbOutput, parseByteLength); multipleRopsResponse.Add(setColumnsResponse); multipleRopsResponse.Add(queryRowsResponse); return multipleRopsResponse; }
/// <summary> /// Verify action type OP_MOVE. /// </summary> /// <param name="getFolderMailMessageContent">Message content gotten from the specified folder.</param> /// <param name="doesOriginalMessageExist">Whether the original message exists.</param> private void VerifyActionTypeOP_MOVE(RopQueryRowsResponse getFolderMailMessageContent, bool doesOriginalMessageExist) { // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R247: the message count in folder is {0}", getFolderMailMessageContent.RowCount); // Verify MS-OXORULE requirement: MS-OXORULE_R247 bool isVerifyR247 = getFolderMailMessageContent.RowCount == 1 && !doesOriginalMessageExist; Site.CaptureRequirementIfIsTrue( isVerifyR247, 247, @"[In ActionBlock Structure] The meaning of action type OP_MOVE: Moves the message to a folder."); }
/// <summary> /// Verify action type OP_COPY. /// </summary> /// <param name="mailSubject">The subject of the new mail.</param> /// <param name="getNewFolderMailMessageContent">The mail message content gotten from the new folder.</param> /// <param name="getInboxMailMessageContent">The mail message content gotten from the Inbox folder.</param> /// <param name="ruleProperties">The properties of the current rule.</param> private void VerifyActionTypeOP_COPY(string mailSubject, RopQueryRowsResponse getNewFolderMailMessageContent, RopQueryRowsResponse getInboxMailMessageContent, RuleProperties ruleProperties) { // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R250: the message count in newFolder is {0}, and in inboxFolder is {1}", getNewFolderMailMessageContent.RowCount, getInboxMailMessageContent.RowCount); // Verify MS-OXORULE requirement: MS-OXORULE_R250 bool isVerifyR250 = mailSubject.Contains(ruleProperties.ConditionSubjectName) && getNewFolderMailMessageContent.RowCount == 1; Site.CaptureRequirementIfIsTrue( isVerifyR250, 250, @"[In ActionBlock Structure] The meaning of action type OP_COPY: Copies the message to a folder."); }
/// <summary> /// Verify RopQueryRows Response /// </summary> /// <param name="queryRowsResponse">RopQueryRowsResponse structure data that needs verification</param> /// <param name="rowCountRequest">The RowCount that is specified in the request</param> private void VerifyRopQueryRowsResponse(RopQueryRowsResponse queryRowsResponse, ushort rowCountRequest) { this.VerifyRPCLayerRequirement(); if (queryRowsResponse.RowCount > 0) { // The value of the following two properties are only valid for content table. if (this.tableType == TableType.CONTENT_TABLE) { if (queryRowsResponse.RowData.PropertyRows != null) { for (int i = 0; i < queryRowsResponse.RowData.PropertyRows.Count; i++) { // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R617"); // Verify MS-OXCTABL requirement: MS-OXCTABL_R617 Site.CaptureRequirementIfAreEqual<int>( 8, queryRowsResponse.RowData.PropertyRows[i].PropertyValues[0].Value.Length, 617, @"[In PidTagInstID] Data type: PtypInteger64 ([MS-OXCDATA] section 2.11.1)."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R618"); // Verify MS-OXCTABL requirement: MS-OXCTABL_R618 Site.CaptureRequirementIfAreEqual<int>( 4, queryRowsResponse.RowData.PropertyRows[i].PropertyValues[1].Value.Length, 618, @"[In PidTagInstanceNum] Data type: PtypInteger32 ([MS-OXCDATA] section 2.11.1)."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R619"); // Verify MS-OXCTABL requirement: MS-OXCTABL_R619 Site.CaptureRequirementIfAreEqual<int>( 4, queryRowsResponse.RowData.PropertyRows[i].PropertyValues[3].Value.Length, 619, @"[In PidTagRowType] Data type: PtypInteger32 ([MS-OXCDATA] section 2.11.1)."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R620"); // Verify MS-OXCTABL requirement: MS-OXCTABL_R620 Site.CaptureRequirementIfAreEqual<int>( 4, queryRowsResponse.RowData.PropertyRows[i].PropertyValues[4].Value.Length, 620, @"[In PidTagDepth] Data type: PtypInteger32 property ([MS-OXCDATA] section 2.11.1)."); } } if (!this.areMultipleSortOrders && this.isExpanded == true) { int i = 0; uint tempRowType = 0; bool isLeafRowExist = false; for (; i < queryRowsResponse.RowData.PropertyRows.Count; i++) { tempRowType = BitConverter.ToUInt32(queryRowsResponse.RowData.PropertyRows[i].PropertyValues[3].Value, 0); if (tempRowType == 0x01) { isLeafRowExist = true; break; } } // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R15{0}", isLeafRowExist ? string.Empty : string.Format("There is no leaf row in the returned property rows!")); // Verify MS-OXCTABL requirement: MS-OXCTABL_R15 Site.CaptureRequirementIfIsTrue( isLeafRowExist, 15, @"[In PidTagRowType] When the PidTagRowType is TBL_LEAF_ROW with value 0x00000001 means the row is a row of data."); } if (this.isExpanded == true) { int i = 0; uint tempRowType = 0; bool isExpandedHeaderExist = false; for (; i < queryRowsResponse.RowData.PropertyRows.Count; i++) { tempRowType = BitConverter.ToUInt32(queryRowsResponse.RowData.PropertyRows[i].PropertyValues[3].Value, 0); if (tempRowType == 0x03) { isExpandedHeaderExist = true; break; } } // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R17{0}", isExpandedHeaderExist ? string.Empty : string.Format("There is no expanded header row in the returned property rows!")); // Verify MS-OXCTABL requirement: MS-OXCTABL_R17 Site.CaptureRequirementIfIsTrue( isExpandedHeaderExist, 17, @"[In PidTagRowType] When the PidTagRowType is TBL_EXPANDED_CATEGORY with value 0x00000003 means the row is a header row that is expanded."); } else if ((!this.areMultipleSortOrders && this.areAllSortOrdersUsedAsCategory) || (this.areMultipleSortOrders && !this.areAllSortOrdersUsedAsCategory)) { int i = 0; uint tempRowType = 0; bool isCollapsedHeaderExist = false; for (; i < queryRowsResponse.RowData.PropertyRows.Count; i++) { tempRowType = BitConverter.ToUInt32(queryRowsResponse.RowData.PropertyRows[i].PropertyValues[3].Value, 0); if (tempRowType == 0x04) { isCollapsedHeaderExist = true; break; } } // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R18{0}", isCollapsedHeaderExist ? string.Empty : string.Format("There is no collapsed header row in the returned property rows!")); // Verify MS-OXCTABL requirement: MS-OXCTABL_R18 Site.CaptureRequirementIfIsTrue( isCollapsedHeaderExist, 18, @"[In PidTagRowType] When the PidTagRowType is TBL_COLLAPSED_CATEGORY with value 0x00000004 means the row is a header row that is collapsed."); } // Since MS-OXCTABL_R15, MS-OXCTABL_R17 and MS-OXCTABL_R18 are verified, this requirement can be captured directly. // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R13"); // Verify MS-OXCTABL requirement: MS-OXCTABL_R13 Site.CaptureRequirement( 13, @"[In PidTagRowType] The PidTagRowType property ([MS-OXPROPS] section 2.931) identifies the type of the row."); if (this.areMultipleSortOrders && this.areAllSortOrdersUsedAsCategory && this.areAllCategoryExpanded) { int i = 0; uint tempDepth = 0; bool isCorrectDepth = false; // There are no more than 2 categories in the response in this test suite. for (; i < 3; i++) { tempDepth = BitConverter.ToUInt32(queryRowsResponse.RowData.PropertyRows[i].PropertyValues[4].Value, 0); if (tempDepth == i) { isCorrectDepth = true; } else { break; } } // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R19{0}", isCorrectDepth ? string.Empty : string.Format(": The no.{0} row depth is not correct and the value is {1}!", i, tempDepth)); // Verify MS-OXCTABL requirement: MS-OXCTABL_R19 Site.CaptureRequirementIfIsTrue( isCorrectDepth, 19, @"[In PidTagDepth] The PidTagDepth property ([MS-OXPROPS] section 2.664) specifies the number of nested categories in which a given row is contained."); } } } // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R110: the value of the Origin field in the response for RopQueryRows is set to {0}", queryRowsResponse.Origin); // Verify MS-OXCTABL requirement: MS-OXCTABL_R110 bool isVerifyR110 = (queryRowsResponse.Origin == 0x00) || (queryRowsResponse.Origin == 0x01) || (queryRowsResponse.Origin == 0x02); Site.CaptureRequirementIfIsTrue( isVerifyR110, 110, @"[In RopQueryRows ROP Response Buffer] This field [Origin] MUST be set to one of the predefined bookmark values[0x00,0x01,0x02] specified in section 2.2.2.1.1."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R109"); // Verify MS-OXCTABL requirement: MS-OXCTABL_R109 Site.CaptureRequirementIfAreEqual<Type>( typeof(byte), queryRowsResponse.Origin.GetType(), 109, @"[In RopQueryRows ROP Response Buffer] Origin (1 byte): An enumeration that identifies the cursor position."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R111 (This is a WORD field)"); // Verify MS-OXCTABL requirement: MS-OXCTABL_R111 Site.CaptureRequirementIfAreEqual<Type>( typeof(ushort), queryRowsResponse.RowCount.GetType(), 111, @"[In RopQueryRows ROP Response Buffer] RowCount (2 bytes): An unsigned integer that specifies the number of rows returned."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R112", rowCountRequest); // Verify MS-OXCTABL requirement: MS-OXCTABL_R112 bool isVerifyR112 = (queryRowsResponse.RowCount <= rowCountRequest) && (queryRowsResponse.RowCount >= 0x0000); Site.CaptureRequirementIfIsTrue( isVerifyR112, 112, @"[In RopQueryRows ROP Response Buffer] Its [RowCount's] value MUST be less than or equal to the RowCount field value that is specified in the request, and it MUST be greater than or equal to 0x0000."); if (queryRowsResponse.RowData.PropertyRows != null) { // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R113"); // Verify MS-OXCTABL requirement: MS-OXCTABL_R113 Site.CaptureRequirementIfAreEqual<ushort>( (ushort)queryRowsResponse.RowData.PropertyRows.Count, queryRowsResponse.RowCount, 113, @"[In RopQueryRows ROP Response Buffer] It [RowCount] MUST be equal to the number of PropertyRow objects returned in the RowData field."); // If the propertyRows count in the queryrowsResponse is not zero, this requirement can be covered if (queryRowsResponse.RowData.PropertyRows.Count > 0) { // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R114"); // Verify MS-OXCTABL requirement: MS-OXCTABL_R114 Site.CaptureRequirement( 114, @"[In RopQueryRows ROP Response Buffer] RowData (variable): A list of PropertyRow structures that contains the array of rows returned."); } for (int i = 0; i < queryRowsResponse.RowData.PropertyRows.Count; i++) { int totalSize = 0; for (int j = 0; j < queryRowsResponse.RowData.PropertyRows[i].PropertyValues.Count; j++) { if (queryRowsResponse.RowData.PropertyRows[i].PropertyValues[j].Value == null) { continue; } if (queryRowsResponse.RowData.PropertyRows[i].PropertyValues[j].Value != null) { totalSize += queryRowsResponse.RowData.PropertyRows[i].PropertyValues[j].Size(); } } bool isVerifyR121 = totalSize <= 510 * sizeof(byte); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R121", 510 * sizeof(byte)); // Verify MS-OXCTABL requirement: MS-OXCTABL_R121 Site.CaptureRequirementIfIsTrue( isVerifyR121, 121, @"[In RopQueryRows ROP Response Buffer] Every property value returned in a row MUST be less than or equal to 510 bytes in size."); } foreach (PropertyRow propertyRow in queryRowsResponse.RowData.PropertyRows) { this.VerifyPropertyRowStructure(propertyRow); } } else { // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R113"); // Verify MS-OXCTABL requirement: MS-OXCTABL_R113 Site.CaptureRequirementIfAreEqual<ushort>( 0, queryRowsResponse.RowCount, 113, @"[In RopQueryRows ROP Response Buffer] It [RowCount] MUST be equal to the number of PropertyRow objects returned in the RowData field."); } for (int i = 0; i < queryRowsResponse.RowCount; i++) { // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R115"); // Verify MS-OXCTABL requirement: MS-OXCTABL_R115 Site.CaptureRequirementIfAreEqual<Type>( typeof(PropertyRow), queryRowsResponse.RowData.PropertyRows[i].GetType(), 115, @"[In RopQueryRows ROP Response Buffer] Each row is represented by a PropertyRow object, as specified in [MS-OXCDATA] section 2.8.1."); } // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R463: the value of the RowCount field in the response for RopQueryRows is set to {0}", queryRowsResponse.RowCount); // Verify MS-OXCTABL requirement: MS-OXCTABL_R463 bool isVerifyR463 = queryRowsResponse.RowCount <= rowCountRequest; Site.CaptureRequirementIfIsTrue( isVerifyR463, 463, @"[In Processing RopQueryRows] The number of rows sent in the ROP response MUST be less than or equal to the number of rows specified in the RowCount field."); }
/// <summary> /// Verify the RopGetProperties in Rules Table. /// </summary> /// <param name="propertyTags">PropertyTag array.</param> /// <param name="quertyRowsResponse">Response of quertyRows.</param> private void VerifyPropertiesInTable(PropertyTag[] propertyTags, RopQueryRowsResponse quertyRowsResponse) { // propertyTags contains a list of PropertyTag. for (int i = 0; i < propertyTags.Length; i++) { // propertyId indicates the Id of a property. ushort propertyId = propertyTags[i].PropertyId; // propertyType indicates the Type of a property. ushort propertyType = propertyTags[i].PropertyType; // propertyValue indicates the value of a property. byte[] propertyValue = quertyRowsResponse.RowData.PropertyRows[quertyRowsResponse.RowData.PropertyRows.Count - 1].PropertyValues[i].Value; // If propertyId is 0x6674, it means the property is PidTagRuleId. if (propertyId == 0x6674) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R2699", "The length({0}) of the propertyValue should be 8 and the value of the propertyType({1}) should be 0x0014.", propertyValue.Length, propertyType); // Verify MS-OXCDATA requirement: MS-OXCDATA_R2699. bool isVerifyR2699 = propertyValue.Length == 8 && propertyType == 0x0014; Site.CaptureRequirementIfIsTrue( isVerifyR2699, "MS-OXCDATA", 2699, @"[In Property Data Types] PtypInteger64 (PT_LONGLONG, PT_I8, i8, ui8) is that 8 bytes; a 64-bit integer [MS-DTYP]: LONGLONG with Property Type Value 0x0014,%x14.00."); } // If propertyId is 0x001A, it means the property is PidTagMessageClass. if (propertyId == 0x001A) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R351"); // Verify MS-OXORULE requirement: MS-OXORULE_R351. Site.CaptureRequirementIfAreEqual<ushort>( (ushort)PropertyType.PtypString, propertyType, 351, @"[In PidTagMessageClass] Type: PtypString ([MS-OXCDATA] section 2.11.1)."); if (this.targetOfRop == TargetOfRop.ForDAM) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R352"); // Verify MS-OXORULE requirement: MS-OXORULE_R352. Site.CaptureRequirementIfAreEqual<string>( "IPC.Microsoft Exchange 4.0.Deferred Action", AdapterHelper.PropertyValueConvertToString(propertyValue), 352, @"[In PidTagMessageClass] The PidTagMessageClass property ([MS-OXCMSG] section 2.2.1.3) MUST be set to ""IPC.Microsoft Exchange 4.0.Deferred Action""."); } } // If propertyId is 0x6647, it means the property is PidTagDamBackPatched. if (propertyId == 0x6647) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R2698", "The length({0}) of the propertyValue should be 1 and the value of the propertyType({1}) should be 0x000b.", propertyValue.Length, propertyType); // Verify MS-OXCDATA requirement: MS-OXCDATA_R2698. bool isVerifyR2698 = propertyValue.Length == 1 && propertyType == 0x000B; Site.CaptureRequirementIfIsTrue( isVerifyR2698, "MS-OXCDATA", 2698, @"[In Property Data Types] PtypBoolean (PT_BOOLEAN. bool) is that 1 byte, restricted to 1 or 0 [MS-DTYP]: BOOLEAN with Property Type Value 0x000B, %x0B.00."); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R353"); // Verify MS-OXORULE requirement: MS-OXORULE_R353. Site.CaptureRequirementIfAreEqual<ushort>( (ushort)PropertyType.PtypBoolean, propertyType, 353, @"[In PidTagDamBackPatched property] Type: PtypBoolean ([MS-OXCDATA] section 2.11.1)."); } // If propertyId is 0x6646, it means the property is PidTagDamOriginalEntryId. if (propertyId == 0x6646) { if (this.targetOfRop == TargetOfRop.ForDAM) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R356"); // Verify MS-OXORULE requirement: MS-OXORULE_R356. Site.CaptureRequirementIfAreEqual<ushort>( (ushort)PropertyType.PtypBinary, propertyType, 356, @"[In PidTagDamOriginalEntryId] Type: PtypBinary ([MS-OXCDATA] section 2.11.1)."); } else if (this.targetOfRop == TargetOfRop.ForDEM) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R712"); // Verify MS-OXORULE requirement: MS-OXORULE_R712. Site.CaptureRequirementIfAreEqual<ushort>( (ushort)PropertyType.PtypBinary, propertyType, 712, @"[In PidTagDamOriginalEntryId Property] Type: PtypBinary ([MS-OXCDATA] section 2.11.1)."); } } // If propertyId is 0x6681, it means the property is PidTagRuleProvider. if (propertyId == 0x6681) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R358"); // Verify MS-OXORULE requirement: MS-OXORULE_R358. Site.CaptureRequirementIfAreEqual<ushort>( (ushort)PropertyType.PtypString, propertyType, 358, @"[In PidTagRuleProvider] Type: PtypString ([MS-OXCDATA] section 2.11.1)."); } // If propertyId is 0x6651, it means the property is PidTagRuleFolderEntryId. if (propertyId == 0x6651) { if (this.targetOfRop == TargetOfRop.ForDAM) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R360"); // Verify MS-OXORULE requirement: MS-OXORULE_R360. Site.CaptureRequirementIfAreEqual<ushort>( (ushort)PropertyType.PtypBinary, propertyType, 360, @"[In PidTagRuleFolderEntryId] Type: PtypBinary ([MS-OXCDATA] section 2.11.1)."); } else if (this.targetOfRop == TargetOfRop.ForDEM) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R714"); // Verify MS-OXORULE requirement: MS-OXORULE_R714. Site.CaptureRequirementIfAreEqual<ushort>( (ushort)PropertyType.PtypBinary, propertyType, 714, @"[In PidTagRuleFolderEntryId Property] Type: PtypBinary ([MS-OXCDATA] section 2.11.1)."); } } // If propertyId is 0x6645, it means the property is PidTagClientActions. if (propertyId == 0x6645) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R362"); // Verify MS-OXORULE requirement: MS-OXORULE_R362. Site.CaptureRequirementIfAreEqual<ushort>( (ushort)PropertyType.PtypBinary, propertyType, 362, @"[In PidTagClientActions] Type: PtypBinary ([MS-OXCDATA] section 2.11.1)."); if (this.targetOfRop == TargetOfRop.ForDAM) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R364"); // Verify MS-OXORULE requirement: MS-OXORULE_R364. // Stack has constructed the rule action buffer according to section 2.2.5. // If ruleAction is not null, it means the propertyValue of PidTagClientActions can be parsed as the RuleAction format successfully, // which indicates this buffer has been packed according to this requirement. RuleAction ruleAction = new RuleAction(); ruleAction = AdapterHelper.PropertyValueConvertToRuleAction(propertyValue); Site.CaptureRequirementIfIsNotNull( ruleAction, 364, @"[In PidTagClientActions] The buffer MUST be packed according to the RuleAction structure specified in section 2.2.5."); } } // If propertyId is 0x6675, it means the property is PidTagRuleIds. if (propertyId == 0x6675) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R367"); // Verify MS-OXORULE requirement: MS-OXORULE_R367. Site.CaptureRequirementIfAreEqual<ushort>( (ushort)PropertyType.PtypBinary, propertyType, 367, @"[In PidTagRuleIds] Type: PtypBinary ([MS-OXCDATA] section 2.11.1)."); if (this.targetOfRop == TargetOfRop.ForDAM) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R369"); // Verify MS-OXORULE requirement: MS-OXORULE_R369. bool isVerifyR369 = AdapterHelper.PropertyValueConvertToBinary(propertyValue).Length % 8 == 0; Site.CaptureRequirementIfIsTrue( isVerifyR369, 369, @"[In PidTagRuleIds] The length of this binary property[PidTagRuleIds] MUST be a multiple of 8 bytes."); } } // If propertyId is 0x6741, it means the property is PidTagDeferredActionMessageOriginalEntryId. if (propertyId == 0x6741) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R2704"); // Verify MS-OXCDATA requirement: MS-OXCDATA_R2704. Site.CaptureRequirementIfAreEqual<ushort>( 0x00FB, propertyType, "MS-OXCDATA", 2704, @"[In Property Value Types] PtypServerId (PT_SVREID) is that variable size; a 16-bit COUNT field followed by a structure specified in section 2.11.1.4. with Property Type Value 0x00FB,%xFB.00."); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R370"); // Verify MS-OXORULE requirement: MS-OXORULE_R370. Site.CaptureRequirementIfAreEqual<ushort>( (ushort)PropertyType.PtypServerId, propertyType, 370, @"[In PidTagDeferredActionMessageOriginalEntryId Property] Type: PtypServerId ([MS-OXCDATA] section 2.11.1)."); } // propertyID of PidTagHasDeferredActionMessages is 0x3FEA. if (propertyId == 0x3FEA) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R722, the propertyType of the PidTagHasDeferredActionMessages is {0}", propertyType); // Verify MS-OXORULE requirement: MS-OXORULE_R722. Site.CaptureRequirementIfAreEqual<ushort>( (ushort)PropertyType.PtypBoolean, propertyType, 722, @"[In PidTagHasDeferredActionMessages Property] Type: PtypBoolean ([MS-OXCDATA] section 2.11.1)."); } // propertyID of PidTagRwRulesStream is 0x6802. if (propertyId == 0x6802) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R1010, the propertyType of the PidTagRwRulesStream is {0}", propertyType); // Verify MS-OXORULE requirement: MS-OXORULE_R1010. Site.CaptureRequirementIfAreEqual<ushort>( (ushort)PropertyType.PtypBoolean, propertyType, 1010, @"[PidTagRwRulesStream Property] Type: PtypBinary ([MS-OXCDATA] section 2.11.1)."); } } }
/// <summary> /// Get the expected message properties included in a specific contents table after retry preconfigured times. /// </summary> /// <param name="folderHandle">Handle of a specific folder.</param> /// <param name="contentsTableHandle">Handle of a specific contents table.</param> /// <param name="propertyTagList">>Array of PropertyTag structures. This field specifies the property values that are visible in table rows.</param> /// <param name="expectedMessageIndex">The index of the specific message in the table.</param> /// <param name="expectedPropertyValue">The value of a specific property of the message to be found in the target mailbox.</param> /// <param name="expectedPropertyName">The property name of a specific property of the message to be found in the target mailbox, which type should be string. The default property name is PidTagSubject.</param> /// <returns>Response of the RopQueryRow ROP contents the expected message properties.</returns> protected RopQueryRowsResponse GetExpectedMessage(uint folderHandle, ref uint contentsTableHandle, PropertyTag[] propertyTagList, ref int expectedMessageIndex, string expectedPropertyValue, PropertyId expectedPropertyName = PropertyId.PidTagSubject) { RopQueryRowsResponse getNormalMailMessageContent = new RopQueryRowsResponse(); uint repeatTime = 0; uint rowCount = 0; bool isExpectedPropertyInPropertyList = false; // If retry time more than expected, terminates the loop while (repeatTime < this.getMessageRepeatTime) { RopGetContentsTableResponse ropGetContentsTableResponse = this.OxoruleAdapter.RopGetContentsTable(folderHandle, ContentTableFlag.None, out contentsTableHandle); Site.Assert.AreEqual<uint>(0, ropGetContentsTableResponse.ReturnValue, "Getting contents table should succeed."); rowCount = ropGetContentsTableResponse.RowCount; repeatTime++; if (rowCount > 0) { getNormalMailMessageContent = this.OxoruleAdapter.QueryPropertiesInTable(contentsTableHandle, propertyTagList); Site.Assert.AreEqual<uint>(0, getNormalMailMessageContent.ReturnValue, "Getting mail message operation should succeed."); for (int i = 0; i < propertyTagList.Length; i++) { if (propertyTagList[i].PropertyId == (ushort)expectedPropertyName) { isExpectedPropertyInPropertyList = true; for (int j = 0; j < getNormalMailMessageContent.RowData.PropertyRows.Count; j++) { string propertyValue = AdapterHelper.PropertyValueConvertToString(getNormalMailMessageContent.RowData.PropertyRows[j].PropertyValues[i].Value); if (propertyValue.Contains(expectedPropertyValue)) { expectedMessageIndex = j; return getNormalMailMessageContent; } } } } Site.Assert.IsTrue(isExpectedPropertyInPropertyList, "The property {0} to be checked should be included in the property list.", expectedPropertyName.ToString()); } if (repeatTime == this.getMessageRepeatTime) { break; } Thread.Sleep(this.WaitForTheRuleToTakeEffect); } Site.Assert.Fail("Can't find the message which has a property {0} ant its value is {1} in the target mailbox.", expectedPropertyName.ToString(), expectedPropertyValue); return getNormalMailMessageContent; }
/// <summary> /// Verify RopQueryRows Failure Response /// </summary> /// <param name="ropQueryRowsResponse">The response of RopQueryRows request</param> /// <param name="inputHandleIndex">The field of InputHandleIndex in RopQueryRows request</param> private void VerifyRopQueryRowsFailureResponse(RopQueryRowsResponse ropQueryRowsResponse, byte inputHandleIndex) { // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1193"); // Verify MS-OXCROPS requirement: MS-OXCROPS_R1193 Site.CaptureRequirementIfAreEqual<Type>( typeof(byte), ropQueryRowsResponse.RopId.GetType(), 1193, @"[In RopQueryRows ROP Failure Response Buffer] RopId (1 byte): An unsigned integer."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1195"); // Verify MS-OXCROPS requirement: MS-OXCROPS_R1195 Site.CaptureRequirementIfAreEqual<byte>( (byte)RopId.RopQueryRows, ropQueryRowsResponse.RopId, 1195, @"[In RopQueryRows ROP Failure Response Buffer] RopId (1 byte): For this operation[RopQueryRows], this field[RopId (1 byte)] is set to 0x15."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1196"); // Verify MS-OXCROPS requirement: MS-OXCROPS_R1196 Site.CaptureRequirementIfAreEqual<Type>( typeof(byte), ropQueryRowsResponse.InputHandleIndex.GetType(), 1196, @"[In RopQueryRows ROP Failure Response Buffer] InputHandleIndex (1 byte): An unsigned integer."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1197"); // Verify MS-OXCROPS requirement: MS-OXCROPS_R1197 Site.CaptureRequirementIfAreEqual<byte>( inputHandleIndex, ropQueryRowsResponse.InputHandleIndex, 1197, @"[In RopQueryRows ROP Failure Response Buffer] InputHandleIndex (1 byte): This index MUST be set to the value specified in the InputHandleIndex field in the request."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1198"); // Verify MS-OXCROPS requirement: MS-OXCROPS_R1198 Site.CaptureRequirementIfAreEqual<Type>( typeof(uint), ropQueryRowsResponse.ReturnValue.GetType(), 1198, @"[In RopQueryRows ROP Failure Response Buffer] ReturnValue (4 bytes): An unsigned integer."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1200"); // Verify MS-OXCROPS requirement: MS-OXCROPS_R1200 Site.CaptureRequirementIfAreNotEqual<uint>( SuccessReturnValue, ropQueryRowsResponse.ReturnValue, 1200, @"[In RopQueryRows ROP Failure Response Buffer] ReturnValue (4 bytes): For this response[Failure Response], this field is set to a value other than 0x00000000."); }
/// <summary> /// Verify RopQueryRows Success Response /// </summary> /// <param name="ropQueryRowsResponse">The response of RopQueryRows request</param> /// <param name="inputHandleIndex">The field of InputHandleIndex in RopQueryRows request</param> /// <param name="propertyTags">Array of PropertyTag structures specifies the property values that are visible in table rows, set by a RopSetColumns request</param> private void VerifyRopQueryRowsSuccessResponse(RopQueryRowsResponse ropQueryRowsResponse, byte inputHandleIndex, PropertyTag[] propertyTags) { // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1176"); // Verify MS-OXCROPS requirement: MS-OXCROPS_R1176 Site.CaptureRequirementIfAreEqual<Type>( typeof(byte), ropQueryRowsResponse.RopId.GetType(), 1176, @"[In RopQueryRows ROP Success Response Buffer] RopId (1 byte): An unsigned integer."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1178"); // Verify MS-OXCROPS requirement: MS-OXCROPS_R1178 Site.CaptureRequirementIfAreEqual<byte>( (byte)RopId.RopQueryRows, ropQueryRowsResponse.RopId, 1178, @"[In RopQueryRows ROP Success Response Buffer] RopId (1 byte): For this operation[RopQueryRows], this field[RopId (1 byte)] is set to 0x15."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1179"); // Verify MS-OXCROPS requirement: MS-OXCROPS_R1179 Site.CaptureRequirementIfAreEqual<Type>( typeof(byte), ropQueryRowsResponse.InputHandleIndex.GetType(), 1179, @"[In RopQueryRows ROP Success Response Buffer] InputHandleIndex (1 byte): An unsigned integer."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1180"); // Verify MS-OXCROPS requirement: MS-OXCROPS_R1180 Site.CaptureRequirementIfAreEqual<byte>( inputHandleIndex, ropQueryRowsResponse.InputHandleIndex, 1180, @"[In RopQueryRows ROP Success Response Buffer] InputHandleIndex (1 byte): This index MUST be set to the value specified in the InputHandleIndex field in the request."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1181"); // Verify MS-OXCROPS requirement: MS-OXCROPS_R1181 Site.CaptureRequirementIfAreEqual<Type>( typeof(uint), ropQueryRowsResponse.ReturnValue.GetType(), 1181, @"[In RopQueryRows ROP Success Response Buffer] ReturnValue (4 bytes): An unsigned integer."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1183"); // Verify MS-OXCROPS requirement: MS-OXCROPS_R1183 Site.CaptureRequirementIfAreEqual<uint>( SuccessReturnValue, ropQueryRowsResponse.ReturnValue, 1183, @"[In RopQueryRows ROP Success Response Buffer] ReturnValue (4 bytes): For this response[Success Response], this field is set to 0x00000000."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1184"); // Verify MS-OXCROPS requirement: MS-OXCROPS_R1184 Site.CaptureRequirementIfAreEqual<Type>( typeof(byte), ropQueryRowsResponse.Origin.GetType(), 1184, @"[In RopQueryRows ROP Success Response Buffer] Origin (1 byte): An enumeration."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1185,Origin:{0}", ropQueryRowsResponse.Origin); // Verify MS-OXCROPS requirement: MS-OXCROPS_R1185 bool isVerifyR1185 = ((ropQueryRowsResponse.Origin & (byte)Origin.Beginning) == (byte)Origin.Beginning) || ((ropQueryRowsResponse.Origin & (byte)Origin.Current) == (byte)Origin.Current) || ((ropQueryRowsResponse.Origin & (byte)Origin.End) == (byte)Origin.End); Site.CaptureRequirementIfIsTrue( isVerifyR1185, 1185, @"[In RopQueryRows ROP Success Response Buffer] Origin (1 byte): The possible values[the value of BOOKMARK_BEGINNING is 0x00, the value of BOOKMARK_CURRENT is 0x01 and the value of BOOKMARK_END is 0x02] for this enumeration are specified in [MS-OXCTABL] section 2.2.2.5.2."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1187"); // Verify MS-OXCROPS requirement: MS-OXCROPS_R1187 Site.CaptureRequirementIfAreEqual<Type>( typeof(ushort), ropQueryRowsResponse.RowCount.GetType(), 1187, @"[In RopQueryRows ROP Success Response Buffer] RowCount (2 bytes): An unsigned integer."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1189"); // Verify MS-OXCROPS requirement: MS-OXCROPS_R1189 // The class PropertyRowSet is List of PropertRow, if the type of Rows is PropertyRowSet can verify R1189 Site.CaptureRequirementIfAreEqual<Type>( typeof(PropertyRowSet), ropQueryRowsResponse.RowData.GetType(), 1189, @"[In RopQueryRows ROP Success Response Buffer] RowData (variable): A list of PropertyRow structures."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1190"); // Verify MS-OXCROPS requirement: MS-OXCROPS_R1190 Site.CaptureRequirementIfAreEqual<ushort>( ropQueryRowsResponse.RowCount, (ushort)ropQueryRowsResponse.RowData.Count, 1190, @"[In RopQueryRows ROP Success Response Buffer] RowData (variable): The number of structures contained in this field is specified by the RowCount field."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1192,RowData:{0}", ropQueryRowsResponse.RowData); // Verify MS-OXCROPS requirement: MS-OXCROPS_R1192 // Assume the result is true. If one of rows element's count is not equal to the columns count, then false. bool isVerifyR1192 = true; foreach (PropertyRow propertyRow in ropQueryRowsResponse.RowData.PropertyRows) { isVerifyR1192 = isVerifyR1192 && (propertyRow.PropertyValues.Count == propertyTags.Length); // If one row element's count is not equal to the columns count then break the iteration if (!isVerifyR1192) { break; } } Site.CaptureRequirementIfIsTrue( isVerifyR1192, 1192, @"[In RopQueryRows ROP Success Response Buffer] RowData (variable): The columns used for these rows were those previously set on this table by a RopSetColumns ROP request (section 2.2.5.1)."); }