public void MSOXORULE_S01_TC03_AddExtendedRule_WithLargeMessageCondition() { this.CheckMAPIHTTPTransportSupported(); #region TestUser1 creates an FAI message. RopCreateMessageResponse ropCreateMessageResponse; uint extendedRuleMessageHandle = this.OxoruleAdapter.RopCreateMessage(this.InboxFolderHandle, this.InboxFolderID, Convert.ToByte(true), out ropCreateMessageResponse); Site.Assert.AreEqual<uint>(0, ropCreateMessageResponse.ReturnValue, "Creating the first FAI message should succeed."); #endregion #region TestUser1 adds the extended rule with NamedProperty successfully. string ruleConditionSubjectName = Constants.RuleConditionSubjectContainString; NamedPropertyInfo namedPropertyInfo = new NamedPropertyInfo { NoOfNamedProps = 2, PropId = new uint[2] { 0x8001, 0x8002 } }; // 0x01 means the property is identified by the name property. PropertyName testPropertyName = new PropertyName { Guid = System.Guid.NewGuid().ToByteArray(), Kind = 0x01, Name = Encoding.Unicode.GetBytes(Constants.NameOfPropertyName + "\0") }; testPropertyName.NameSize = (byte)testPropertyName.Name.Length; // 0x00 means the property is identified by the LID. PropertyName secondPropertyName = new PropertyName { Guid = System.Guid.NewGuid().ToByteArray(), Kind = 0x00, LID = 0x88888888 }; namedPropertyInfo.NamedProperty = new PropertyName[2] { testPropertyName, secondPropertyName }; namedPropertyInfo.NamedPropertiesSize = (uint)(testPropertyName.Serialize().Length + secondPropertyName.Serialize().Length); string ruleName = Common.GenerateResourceName(this.Site, Constants.ExtendRulename1); TaggedPropertyValue[] extendedRuleProperties = AdapterHelper.GenerateExtendedRuleTestData(ruleName, 0, (uint)RuleState.ST_ENABLED, Constants.PidTagRuleProvider, ActionType.OP_MARK_AS_READ, new DeleteMarkReadActionData(), ruleConditionSubjectName, namedPropertyInfo); // Set properties for extended rule FAI message. RopSetPropertiesResponse ropSetPropertiesResponse = this.OxoruleAdapter.RopSetProperties(extendedRuleMessageHandle, extendedRuleProperties); Site.Assert.AreEqual<uint>(0, ropSetPropertiesResponse.ReturnValue, "Setting property for Extended rule FAI message should succeed."); // Save changes of message. RopSaveChangesMessageResponse ropSaveChangesMessagResponse = this.OxoruleAdapter.RopSaveChangesMessage(extendedRuleMessageHandle); Site.Assert.AreEqual<uint>(0, ropSaveChangesMessagResponse.ReturnValue, "Saving Extend rule message should succeed."); // Specify the properties to be got. PropertyTag[] propertyTagArray = new PropertyTag[2]; // PidTagRuleMessageProviderData propertyTagArray[0].PropertyId = (ushort)PropertyId.PidTagRuleMessageProvider; propertyTagArray[0].PropertyType = (ushort)PropertyType.PtypString; // PidTagRuleMessageName propertyTagArray[1].PropertyId = (ushort)PropertyId.PidTagRuleMessageName; propertyTagArray[1].PropertyType = (ushort)PropertyType.PtypString; // Get the specific properties of the extended rule. RopGetPropertiesSpecificResponse ropGetPropertiesSpecificResponse = this.OxoruleAdapter.RopGetPropertiesSpecific(extendedRuleMessageHandle, propertyTagArray); Site.Assert.AreEqual<uint>(0, ropGetPropertiesSpecificResponse.ReturnValue, "Getting folder id property operation should succeed."); #region Capture Code // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R184"); // Verify MS-OXORULE requirement: MS-OXORULE_R184 string pidTagRuleMessageProviderData = AdapterHelper.PropertyValueConvertToString(ropGetPropertiesSpecificResponse.RowData.PropertyValues[0].Value); Site.CaptureRequirementIfAreEqual<string>( Constants.PidTagRuleProvider, pidTagRuleMessageProviderData, 184, @"[In PidTagRuleMessageProvider Property] This property has the same semantics as the PidTagRuleProvider property (section 2.2.1.3.1.5). [The PidTagRuleMessageProvider property identifies the client application that owns the rule (2).]"); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R164"); // Verify MS-OXORULE requirement: MS-OXORULE_R164 // The rule name set by client is "ExtendRulename1". string pidTagRuleMessageNameValue = AdapterHelper.PropertyValueConvertToString(ropGetPropertiesSpecificResponse.RowData.PropertyValues[1].Value); Site.CaptureRequirementIfAreEqual<string>( ruleName, pidTagRuleMessageNameValue, 164, @"[In PidTagRuleMessageName Property] This property has the same semantics as the PidTagRuleName property (section 2.2.1.3.1.4). [The PidTagRuleMessageName property specifies the name of the rule (2).]"); #endregion #endregion #region TestUser1 retrieves data of the new extended rule. this.OxoruleAdapter.TargetOfRop = TargetOfRop.ForExtendedRules; RopGetPropertiesAllResponse ropGetExtendRuleMessageResponse = this.OxoruleAdapter.RopGetPropertiesAll(extendedRuleMessageHandle, this.PropertySizeLimitFlag, (ushort)WantUnicode.Want); Site.Assert.AreEqual<uint>(0, ropGetExtendRuleMessageResponse.ReturnValue, "Getting all properties operation should succeed."); Site.Assert.IsTrue(ropGetExtendRuleMessageResponse.PropertyValues.Length != 0, "Extended Rule data should be found in related FAI message!"); this.OxoruleAdapter.TargetOfRop = TargetOfRop.OtherTarget; ExtendedRuleActions extendedRuleMessageActions = null; // Check the properties set on Extended Rule, and find the Extended Rule Actions. for (int i = 0; i < ropGetExtendRuleMessageResponse.PropertyValues.Length; i++) { // propertyId indicates the Id of a property set on Extended Rule. ushort propertyId = ropGetExtendRuleMessageResponse.PropertyValues[i].PropertyTag.PropertyId; if (propertyId == (ushort)PropertyId.PidTagExtendedRuleMessageActions) { byte[] propertyValue = ropGetExtendRuleMessageResponse.PropertyValues[i].Value; extendedRuleMessageActions = AdapterHelper.PropertyValueConvertToExtendedRuleActions(propertyValue); break; } } Site.Assert.AreNotEqual<ExtendedRuleActions>(null, extendedRuleMessageActions, "extendedRuleMessageActions should not be null."); // Get the Property Names saved by server in the extendedRuleMessageActions. PropertyName[] propertyNames = extendedRuleMessageActions.NamedPropertyInformation.NamedProperty; PropertyName testPropertyNameSavedOnServer = new PropertyName(); PropertyName secondPropertyNameSavedOnServer = new PropertyName(); if (propertyNames != null && propertyNames.Length > 0) { for (int i = 0; i < propertyNames.Length; i++) { // If the Kind is 0x01, it means this PropertyName is the testPropertyName. if (propertyNames[i].Kind == 0x01) { testPropertyNameSavedOnServer = propertyNames[i]; } else if (propertyNames[i].Kind == 0x00) { // If the Kind is 0x00, it means this PropertyName is the secondPropertyName. secondPropertyNameSavedOnServer = propertyNames[i]; } } } Site.Assert.IsNotNull(testPropertyNameSavedOnServer.Guid, "testPropertyNameSavedOnServer should not be null."); Site.Assert.IsNotNull(secondPropertyNameSavedOnServer.Guid, "secondPropertyNameSavedOnServer should not be null."); #endregion #region TestUser1 creates a new FAI message. extendedRuleMessageHandle = this.OxoruleAdapter.RopCreateMessage(this.InboxFolderHandle, this.InboxFolderID, Convert.ToByte(true), out ropCreateMessageResponse); Site.Assert.AreEqual<uint>(0, ropCreateMessageResponse.ReturnValue, "Creating the second FAI message should succeed."); #endregion #region TestUser1 creates an extended rule with PidTagExtendedRuleMessageCondition property value size larger than the size set by the server. propertyTagArray = new PropertyTag[1]; propertyTagArray[0].PropertyId = (ushort)PropertyId.PidTagExtendedRuleSizeLimit; propertyTagArray[0].PropertyType = (ushort)PropertyType.PtypInteger32; ropGetPropertiesSpecificResponse = this.OxoruleAdapter.RopGetPropertiesSpecific(this.LogonHandle, propertyTagArray); uint pidTagExtendedRuleSizeLimit = Common.ConvertByteArrayToUint(ropGetPropertiesSpecificResponse.RowData.PropertyValues[0].Value); // According to MS-OXCRPC, "The server SHOULD fail with the RPC status code of RPC_X_BAD_STUB_DATA (0x000006F7) if the request buffer is larger than 0x00040000 bytes in size." if (pidTagExtendedRuleSizeLimit < 0x00040000) { ruleConditionSubjectName = Constants.RuleConditionSubjectContainString; namedPropertyInfo = new NamedPropertyInfo { NoOfNamedProps = 2, PropId = new uint[2] { 0x8001, 0x8002 } }; // Generate a string value whose size lager than the one specified by the PidTagExtendedRuleSizeLimit property. StringBuilder stringByteValue = new StringBuilder("ExtentRuleSize"); stringByteValue.Append('a', (int)pidTagExtendedRuleSizeLimit); // If the value of Kind is 0x01, it means that the property is identified by the name property. testPropertyName = new PropertyName { Guid = System.Guid.NewGuid().ToByteArray(), Kind = 0x01, Name = Encoding.Unicode.GetBytes(stringByteValue + "\0") }; testPropertyName.NameSize = (byte)testPropertyName.Name.Length; // If the value of Kind is 0x00, it means that the property is identified by the LID. secondPropertyName = new PropertyName { Guid = System.Guid.NewGuid().ToByteArray(), Kind = 0x00, LID = 0x88888888 }; namedPropertyInfo.NamedProperty = new PropertyName[2] { testPropertyName, secondPropertyName }; namedPropertyInfo.NamedPropertiesSize = (uint)(testPropertyName.Serialize().Length + secondPropertyName.Serialize().Length); extendedRuleProperties = AdapterHelper.GenerateExtendedRuleTestData(Common.GenerateResourceName(this.Site, Constants.ExtendRulename1), 0, (uint)RuleState.ST_ENABLED, Constants.PidTagRuleProvider, ActionType.OP_MARK_AS_READ, new DeleteMarkReadActionData(), ruleConditionSubjectName, namedPropertyInfo); TaggedPropertyValue pidTagExtendedRuleMessageCondition = new TaggedPropertyValue(); foreach (TaggedPropertyValue propertyValue in extendedRuleProperties) { if (propertyValue.PropertyTag.PropertyId == (ushort)PropertyId.PidTagExtendedRuleMessageCondition) { pidTagExtendedRuleMessageCondition = propertyValue; break; } } uint pidTagExtendedRuleMessageConditionSize = uint.Parse(pidTagExtendedRuleMessageCondition.Value.Length.ToString()); // Set properties for extended rule FAI message. ropSetPropertiesResponse = this.OxoruleAdapter.RopSetProperties(extendedRuleMessageHandle, extendedRuleProperties); // Save changes of message. ropSaveChangesMessagResponse = this.OxoruleAdapter.RopSaveChangesMessage(extendedRuleMessageHandle); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R1016"); // Verify MS-OXORULE requirement: MS-OXORULE_R1016. if (pidTagExtendedRuleMessageConditionSize > pidTagExtendedRuleSizeLimit) { Site.CaptureRequirementIfAreNotEqual<uint>( 0x0000, ropSaveChangesMessagResponse.ReturnValue, 1016, @"[In Processing Incoming Messages to a Folder] If the PidTagExtendedRuleSizeLimit property is set and the size of the PidTagExtendedRuleMessageCondition property (section 2.2.4.1.10) exceeds the value specified by the PidTagExtendedRuleSizeLimit property, the server MUST return an error."); } else { Site.Assert.Fail("The size of the PidTagExtendedRuleMessageCondition property should exceeds the value specified by the PidTagExtendedRuleSizeLimit property."); } } #endregion }
/// <summary> /// Get the named properties value of specified Message object. /// </summary> /// <param name="longIdProperties">The list of named properties</param> /// <param name="messageHandle">The object handle of specified Message object.</param> /// <returns>Returns named property values of specified Message object.</returns> public Dictionary<PropertyNames, byte[]> GetNamedPropertyValues(List<PropertyNameObject> longIdProperties, uint messageHandle) { object response = null; byte[] rawData = null; #region Call RopGetPropertyIdsFromNames to get property ID. PropertyName[] propertyNames = new PropertyName[longIdProperties.Count]; for (int i = 0; i < longIdProperties.Count; i++) { propertyNames[i] = longIdProperties[i].PropertyName; } RopGetPropertyIdsFromNamesRequest getPropertyIdsFromNamesRequest; RopGetPropertyIdsFromNamesResponse getPropertyIdsFromNamesResponse; getPropertyIdsFromNamesRequest.RopId = (byte)RopId.RopGetPropertyIdsFromNames; getPropertyIdsFromNamesRequest.LogonId = 0x00; getPropertyIdsFromNamesRequest.InputHandleIndex = 0x00; getPropertyIdsFromNamesRequest.Flags = (byte)GetPropertyIdsFromNamesFlags.Create; getPropertyIdsFromNamesRequest.PropertyNameCount = (ushort)propertyNames.Length; getPropertyIdsFromNamesRequest.PropertyNames = propertyNames; this.DoRopCall(getPropertyIdsFromNamesRequest, messageHandle, ref response, ref rawData, GetPropertiesFlags.None); getPropertyIdsFromNamesResponse = (RopGetPropertyIdsFromNamesResponse)response; Site.Assert.AreEqual<uint>(0, getPropertyIdsFromNamesResponse.ReturnValue, "Call RopGetPropertyIdsFromNames should success."); #endregion #region Call RopGetPropertiesSpecific to get the specific properties of specific message object. // Get specific property for created message RopGetPropertiesSpecificRequest getPropertiesSpecificRequest = new RopGetPropertiesSpecificRequest(); RopGetPropertiesSpecificResponse getPropertiesSpecificResponse; getPropertiesSpecificRequest.RopId = (byte)RopId.RopGetPropertiesSpecific; getPropertiesSpecificRequest.LogonId = 0x00; getPropertiesSpecificRequest.InputHandleIndex = 0x00; getPropertiesSpecificRequest.PropertySizeLimit = 0xFFFF; PropertyTag[] tagArray = new PropertyTag[longIdProperties.Count]; for (int j = 0; j < getPropertyIdsFromNamesResponse.PropertyIds.Length; j++) { tagArray[j] = new PropertyTag { PropertyId = getPropertyIdsFromNamesResponse.PropertyIds[j].ID, PropertyType = (ushort)longIdProperties[j].PropertyType }; } getPropertiesSpecificRequest.PropertyTagCount = (ushort)tagArray.Length; getPropertiesSpecificRequest.PropertyTags = tagArray; this.DoRopCall(getPropertiesSpecificRequest, messageHandle, ref response, ref rawData, GetPropertiesFlags.None); getPropertiesSpecificResponse = (RopGetPropertiesSpecificResponse)response; Site.Assert.AreEqual<uint>(0, getPropertiesSpecificResponse.ReturnValue, "Calling RopGetPropertiesSpecific should be successful."); Dictionary<PropertyNames, byte[]> propertyList = new Dictionary<PropertyNames, byte[]>(); PropertyObj propertyObjPidLidCommonStart = null; PropertyObj propertyObjPidLidCommonEnd = null; for (int i = 0; i < getPropertiesSpecificResponse.RowData.PropertyValues.Count; i++) { PropertyObj propertyObj = new PropertyObj { PropertyName = longIdProperties[i].DisplayName, ValueType = longIdProperties[i].PropertyType }; PropertyHelper.GetPropertyObjFromBuffer(propertyObj, getPropertiesSpecificResponse.RowData.PropertyValues[i].Value); // Verify requirements related with named properties PidNameKeywords, PidNameContentBase, PidNameAcceptLanguage and PidNameContentClass. this.VerifyMessageSyntaxDataType(propertyObj); if (propertyObj.PropertyName == PropertyNames.PidLidCommonStart) { propertyObjPidLidCommonStart = propertyObj; } if (propertyObj.PropertyName == PropertyNames.PidLidCommonEnd) { propertyObjPidLidCommonEnd = propertyObj; } propertyList.Add(longIdProperties[i].DisplayName, getPropertiesSpecificResponse.RowData.PropertyValues[i].Value); } // Verify the requirements of PidLidCommonStart and PidLidCommonEnd. if (PropertyHelper.IsPropertyValid(propertyObjPidLidCommonStart) || PropertyHelper.IsPropertyValid(propertyObjPidLidCommonEnd)) { this.VerifyMessageSyntaxPidLidCommonStartAndPidLidCommonEnd(propertyObjPidLidCommonStart, propertyObjPidLidCommonEnd); } #endregion return propertyList; }
/// <summary> /// Get PropertyName from ptfconfig file. /// </summary> /// <param name="kind">The kind of PropertyName.</param> /// <returns>An instance of PropertyName.</returns> private PropertyName GetPropertyName(byte kind) { PropertyName propertyName = new PropertyName { Kind = kind }; if (propertyName.Kind == (byte)Kind.LidField) { propertyName.LID = PropertyName00Lid; propertyName.Guid = (new Guid(PropertyName00Guid)).ToByteArray(); } else if (propertyName.Kind == (byte)Kind.NameField) { propertyName.Name = Encoding.Unicode.GetBytes(PropertyName01Name + "\0"); propertyName.NameSize = (byte)propertyName.Name.Length; propertyName.Guid = (new Guid(PropertyName01Guid)).ToByteArray(); } else if (propertyName.Kind == (byte)Kind.NoAssociated) { propertyName.Guid = (new Guid(PropertyNameFFGuid)).ToByteArray(); } return propertyName; }
/// <summary> /// The method is used to query an object for all the named properties. /// </summary> /// <param name="queryFlags">Specifies QueryFlags parameter in request.</param> /// <param name="hasGuid">Indicates whether HasGuid is zero, /// If the HasGUID field is non-zero then the PropertyGUID field MUST be included in the request. /// If no PropertyGUID is specified, then properties from any GUID MUST be returned in the results.</param> /// <param name="isKind0x01Returned">True if the named properties of the response with the Kind field /// ([MS-OXCDATA] section 2.6.1) set to 0x1 was returned.</param> /// <param name="isKind0x00Returned">True if the named properties of the response with the Kind field /// ([MS-OXCDATA] section 2.6.1) set to 0x0 was returned.</param> /// <param name="isNamedPropertyGuidReturned">True if the named properties with a GUID field ([MS-OXCDATA] /// section 2.6.1) value that does not match the value of the PropertyGUID field was returned.</param> public void RopQueryNamedPropertiesMethod( QueryFlags queryFlags, bool hasGuid, out bool isKind0x01Returned, out bool isKind0x00Returned, out bool isNamedPropertyGuidReturned) { #region Initialize parameters property // The value of hasGuid in RopQueryNameProperties method. byte hasGuidRequest = 0; // The value of queryFlags in RopQueryNameProperties method. byte queryFlagRequest = Convert.ToByte(queryFlags); // The value of propertyGuid in RopQuerynameProperties method. byte[] propertyGuid = null; // Set default values for three parameters. isKind0x01Returned = false; isKind0x00Returned = false; isNamedPropertyGuidReturned = false; // When name property has GUID, set parameters. if (hasGuid) { hasGuidRequest = Convert.ToByte(true); PropertyName[] ptyName = new PropertyName[1]; ptyName[0] = this.GetPropertyName((byte)Kind.NameField); propertyGuid = ptyName[0].Guid; this.RopGetPropertyIdsFromNames(this.cprptCurrentHandle, (byte)GetPropertyIdsFromNamesFlags.Create, ptyName, true); if (this.cprptCurrentType == ServerObjectType.Message) { this.RopSaveChangesMessage(this.cprptCurrentHandle, true); } else if (this.cprptCurrentType == ServerObjectType.Attachment) { this.RopSaveChangesAttachment(this.cprptCurrentHandle, true); } } #endregion // Call RopQueryNamedProperties. RopQueryNamedPropertiesResponse queryNamePtyRes = this.RopQueryNamedProperties(this.cprptCurrentHandle, queryFlagRequest, hasGuidRequest, propertyGuid); #region Verify isKind0x00Return and isKind0x00Return // Verify if the kind of NamedProperties in RopQueryNamedPropertiesResponse is 0x01. for (int i = 0; i < queryNamePtyRes.IdCount; i++) { if (queryNamePtyRes.PropertyNames[i].Kind == (byte)Kind.NameField) { isKind0x01Returned = true; break; } } // Verify if the kind of NamedProperties in RopQueryNamedPropertiesResponse is 0x00. for (int i = 0; i < queryNamePtyRes.IdCount; i++) { if (queryNamePtyRes.PropertyNames[i].Kind == (byte)Kind.LidField) { isKind0x00Returned = true; break; } } #endregion #region Verify isNamedPropertyGuidReturn // If the PropertyGUID field presents, named properties with a GUID field value that does not match the value of the PropertyGUID field MUST NOT be returned. for (int i = 0; i < queryNamePtyRes.IdCount; i++) { if (hasGuid && Common.CompareByteArray(queryNamePtyRes.PropertyNames[i].Guid, propertyGuid)) { isNamedPropertyGuidReturned = true; } else { isNamedPropertyGuidReturned = false; break; } } #endregion // Verify RopQueryNamedProperties. this.VerifyRopQueryNamedProperties(queryFlags, propertyGuid, queryNamePtyRes, this.cprptCurrentType, true); }
/// <summary> /// Verify PropertyName structure. /// </summary> /// <param name="propertyName">The property name.</param> private void VerifyPropertyName(PropertyName propertyName) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R17, The actual value of Kind is {0}", propertyName.Kind); // Verify MS-OXCDATA requirement: MS-OXCDATA_R17. bool isVerifyR17 = propertyName.Kind == 0x00 || propertyName.Kind == 0x01 || propertyName.Kind == 0xFF; Site.CaptureRequirementIfIsTrue( isVerifyR17, "MS-OXCDATA", 17, @"[In PropertyName Structure] Kind (1 byte): The possible values [0x00, 0x01, 0xFF] for the Kind field are in the following table."); if (propertyName.Kind == 0x00) { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R25"); // Verify MS-OXCDATA requirement: MS-OXCDATA_R25. // LID is not 0 means it is present. Site.CaptureRequirementIfIsNotNull( propertyName.LID, "MS-OXCDATA", 25, @"[In PropertyName Structure] LID (optional) (4 bytes): This field is present only if the value of the Kind field is equal to 0x00."); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R26"); // Verify MS-OXCDATA requirement: MS-OXCDATA_R26. Site.CaptureRequirementIfAreEqual<Type>( typeof(uint), propertyName.LID.GetType(), "MS-OXCDATA", 26, @"[In PropertyName Structure] LID (optional) (4 bytes): An unsigned integer that identifies the named property within its property set."); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R27"); // Verify MS-OXCDATA requirement: MS-OXCDATA_R27. // NameSize!=null means NameSize present. Site.CaptureRequirementIfIsNull( propertyName.NameSize, "MS-OXCDATA", 27, @"[In PropertyName Structure] NameSize (optional) (1 byte): This field is present only if the value of the Kind field is equal to 0x01."); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R29"); // Verify MS-OXCDATA requirement: MS-OXCDATA_R29. // That Name does not equal null means Name presents. Site.CaptureRequirementIfIsNull( propertyName.Name, "MS-OXCDATA", 29, @"[In PropertyName Structure] Name (optional) (variable): This field is present only if Kind is equal to 0x01."); } else { // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R25"); // Verify MS-OXCDATA requirement: MS-OXCDATA_R25. // LID is not 0 means it is present. Site.CaptureRequirementIfIsNull( propertyName.LID, "MS-OXCDATA", 25, @"[In PropertyName Structure] LID (optional) (4 bytes): This field is present only if the value of the Kind field is equal to 0x00."); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R27"); // Verify MS-OXCDATA requirement: MS-OXCDATA_R27. // NameSize!=null means NameSize present. Site.CaptureRequirementIfIsNotNull( propertyName.NameSize, "MS-OXCDATA", 27, @"[In PropertyName Structure] NameSize (optional) (1 byte): This field is present only if the value of the Kind field is equal to 0x01."); // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R29"); // Verify MS-OXCDATA requirement: MS-OXCDATA_R29. // That Name does not equal null means Name presents. Site.CaptureRequirementIfIsNotNull( propertyName.Name, "MS-OXCDATA", 29, @"[In PropertyName Structure] Name (optional) (variable): This field is present only if Kind is equal to 0x01."); } // Add the debug information. Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R941"); // Verify MS-OXORULE requirement: MS-OXORULE_R941. // The format of the PropertyName structure has been verified by the above capture code, so R941 can be verified directly. Site.CaptureRequirement( 941, @"[In NamedPropertyInformation Structure] The format of the PropertyName structure is specified in [MS-OXCDATA] section 2.6.1."); }
/// <summary> /// This method is used to map abstract, client-defined named properties to concrete 16-bit property IDs. /// </summary> /// <param name="isTestOrder">Indicates whether to test returned PropertyNames order.</param> /// <param name="isCreateFlagSet">Indicates whether the "Create" Flags in request parameter is set.</param> /// <param name="isPropertyNameExisting">Indicates whether PropertyName is existing in object mapping.</param> /// <param name="specialPropertyName">Specifies PropertyName of request parameter</param> /// <param name="isCreatedEntryReturned">If Create Flags is set: If set, indicates that the server MUST create new /// entries for any name parameters that are not found in the existing mapping set, and return existing entries for any /// name parameters that are found in the existing mapping set.</param> /// <param name="error">Specifies the ErrorCode when server reached limit.</param> public void RopGetPropertyIdsFromNamesMethod( bool isTestOrder, bool isCreateFlagSet, bool isPropertyNameExisting, SpecificPropertyName specialPropertyName, out bool isCreatedEntryReturned, out CPRPTErrorCode error) { #region Initialize parameters // Specify whether the order in response is the same as that in request. bool isOrder = true; // Specify whether the property names and ids are mapped. bool isNamesAndIdsMapping = false; // Set default value for the out parameter. isCreatedEntryReturned = false; error = CPRPTErrorCode.None; // Set value for flags in RopGetPropertyIdsFromNames. byte flags = (byte)GetPropertyIdsFromNamesFlags.None; if (isCreateFlagSet) { flags = (byte)GetPropertyIdsFromNamesFlags.Create; } PropertyName[] propertyNames = null; if (isTestOrder) { propertyNames = new PropertyName[ConstValues.TestPropertyCount]; } else { propertyNames = new PropertyName[1]; } switch (specialPropertyName) { case SpecificPropertyName.Kind0x01: case SpecificPropertyName.NoConstraint: propertyNames[0] = this.GetPropertyName((byte)Kind.NameField); break; case SpecificPropertyName.PS_MAPIAndKind0x01: propertyNames[0] = this.GetPropertyName((byte)Kind.NameField); propertyNames[0].Guid = (new Guid(PSMAPI)).ToByteArray(); break; case SpecificPropertyName.PS_MAPIAndKind0x00: propertyNames[0] = this.GetPropertyName((byte)Kind.LidField); propertyNames[0].Guid = (new Guid(PSMAPI)).ToByteArray(); break; default: Site.Assert.Fail("Invalid SpecificPropertyName enum value {0}.", specialPropertyName); break; } if (!isPropertyNameExisting && !isCreateFlagSet) { propertyNames[0].Kind = (byte)Kind.NameField; propertyNames[0].Name = Encoding.Unicode.GetBytes(PropertyNameNotMapped + "\0"); propertyNames[0].NameSize = (byte)propertyNames[0].Name.Length; propertyNames[0].Guid = (new Guid(PropertyNameNotMappedGuid)).ToByteArray(); } // The existing property ID. ushort existId = 0; // If the property exists, create it. if (isPropertyNameExisting) { PropertyName[] propertyNameTmp = new PropertyName[1]; propertyNameTmp[0] = propertyNames[0]; RopGetPropertyIdsFromNamesResponse ptyNameExistingRes = this.RopGetPropertyIdsFromNames(this.cprptCurrentHandle, (byte)GetPropertyIdsFromNamesFlags.Create, propertyNameTmp, true); existId = ptyNameExistingRes.PropertyIds[0].ID; } // The second property ID. ushort secondId = 0; // The third property ID. ushort thirdId = 0; // If the PropertyNames order need to verify, create the second and the third properties. if (isTestOrder) { // Add second property. PropertyName[] propertyNameTmp = new PropertyName[1]; propertyNameTmp[0] = this.GetPropertyName((byte)Kind.NameField); propertyNameTmp[0].Name[0]++; propertyNameTmp[0].Guid[0]++; propertyNames[1] = propertyNameTmp[0]; RopGetPropertyIdsFromNamesResponse ptyNameExistingRes = this.RopGetPropertyIdsFromNames(this.cprptCurrentHandle, (byte)GetPropertyIdsFromNamesFlags.Create, propertyNameTmp, true); secondId = ptyNameExistingRes.PropertyIds[0].ID; // Add second property. propertyNameTmp[0] = this.GetPropertyName((byte)Kind.NameField); propertyNameTmp[0].Name[0]--; propertyNameTmp[0].Guid[0]--; propertyNames[2] = propertyNameTmp[0]; ptyNameExistingRes = this.RopGetPropertyIdsFromNames(this.cprptCurrentHandle, (byte)GetPropertyIdsFromNamesFlags.Create, propertyNameTmp, true); thirdId = ptyNameExistingRes.PropertyIds[0].ID; } #endregion RopGetPropertyIdsFromNamesResponse getPropertyIdsFromNamesResponse = this.RopGetPropertyIdsFromNames(this.cprptCurrentHandle, flags, propertyNames, false); #region When property exists, check if names and ids are mapping if (isPropertyNameExisting) { RopGetNamesFromPropertyIdsResponse getPropertyNamesFromPropertyIdsResponse = this.RopGetNamesFromPropertyIds(this.cprptCurrentHandle, getPropertyIdsFromNamesResponse.PropertyIds); // Verify whether property name and id is mapping. for (int i = 0; i < getPropertyNamesFromPropertyIdsResponse.PropertyNameCount; i++) { if (getPropertyNamesFromPropertyIdsResponse.PropertyNames[i].Kind == (byte)Kind.LidField) { if ((getPropertyNamesFromPropertyIdsResponse.PropertyNames[i].Guid.ToString() == propertyNames[i].Guid.ToString()) && (getPropertyNamesFromPropertyIdsResponse.PropertyNames[i].Kind == propertyNames[i].Kind) && (getPropertyNamesFromPropertyIdsResponse.PropertyNames[i].LID == propertyNames[i].LID)) { isNamesAndIdsMapping = true; } else { isNamesAndIdsMapping = false; break; } } else if (getPropertyNamesFromPropertyIdsResponse.PropertyNames[i].Kind == (byte)Kind.NameField) { if ((getPropertyNamesFromPropertyIdsResponse.PropertyNames[i].Guid.ToString() == propertyNames[i].Guid.ToString()) && (getPropertyNamesFromPropertyIdsResponse.PropertyNames[i].Kind == propertyNames[i].Kind) && (getPropertyNamesFromPropertyIdsResponse.PropertyNames[i].NameSize == propertyNames[i].NameSize) && (getPropertyNamesFromPropertyIdsResponse.PropertyNames[i].Name.ToString() == propertyNames[i].Name.ToString())) { isNamesAndIdsMapping = true; } else { isNamesAndIdsMapping = false; break; } } } } #endregion #region Test order if (getPropertyIdsFromNamesResponse.PropertyIds != null && propertyNames.Length == ConstValues.TestPropertyCount && getPropertyIdsFromNamesResponse.PropertyIds.Length == ConstValues.TestPropertyCount) { if (getPropertyIdsFromNamesResponse.PropertyIds[1].ID != secondId || getPropertyIdsFromNamesResponse.PropertyIds[2].ID != thirdId) { isOrder = false; } } #endregion this.VerifyRopGetPropertyIdsFromNames((ushort)propertyNames.Length, propertyNames, flags, getPropertyIdsFromNamesResponse, isOrder, this.cprptCurrentType, isPropertyNameExisting, isNamesAndIdsMapping); #region Check error and isCreateEnrtyReturned switch ((CPRPTErrorCode)getPropertyIdsFromNamesResponse.ReturnValue) { case CPRPTErrorCode.None: // Verify whether the created entry is returned. if (isCreateFlagSet) { if (isPropertyNameExisting) { isCreatedEntryReturned = false; } else if (getPropertyIdsFromNamesResponse.PropertyIds[0].ID != existId) { isCreatedEntryReturned = true; } } break; case CPRPTErrorCode.ecWarnWithErrors: error = CPRPTErrorCode.ecWarnWithErrors; break; case CPRPTErrorCode.NotEnoughMemory: error = CPRPTErrorCode.NotEnoughMemory; break; default: Site.Assert.Fail("Unexpected RopGetPropertyIdsFromNames error code.Error: 0x{0:X8}", getPropertyIdsFromNamesResponse.ReturnValue); break; } #endregion }
/// <summary> /// Verify the RopCopyTo operation related requirements. /// </summary> /// <param name="propertyNameCount">The PropertyNameCount parameter in the request buffer.</param> /// <param name="propertyNames">A list of PropertyName in the request buffer.</param> /// <param name="flags">The Flags set by client in the request buffer.</param> /// <param name="ropGetPropertyIdsFromNamesResponse">The RopCopyTo response buffer structure.</param> /// <param name="isOrdered">A boolean value which indicates whether the order of elements in request/response buffer is right.</param> /// <param name="objectType">Indicates which object type the RopGetPropertyIdsFromNames operation is acting on.</param> /// <param name="isPropertyNameExisting">A boolean value indicates whether the queried PropertyNames exists on server.</param> /// <param name="isNamesAndIdsMapping">A boolean value indicates whether the Names and the returned Ids are mapping.</param> private void VerifyRopGetPropertyIdsFromNames( ushort propertyNameCount, PropertyName[] propertyNames, byte flags, RopGetPropertyIdsFromNamesResponse ropGetPropertyIdsFromNamesResponse, bool isOrdered, ServerObjectType objectType, bool isPropertyNameExisting, bool isNamesAndIdsMapping) { // Since the RopGetPropertyIdsFromNames ROP response was parsed successfully, MS-OXCPRPT_R52502 can be captured directly. Site.CaptureRequirement( 52502, @"[In Processing RopGetPropertyIdsFromNames] The server responds with a RopGetPropertyIdsFromNames ROP response buffer."); // Since the RopGetPropertyIdsFromNames ROP response was parsed successfully, MS-OXCPRPT_R41404 can be captured directly. Site.CaptureRequirement( 41404, @"[In Getting Property IDs for Named Properties] The client provides a property set and an identifier in either integer or string form, and the server returns the property ID, which the client uses for any operations performed on that property."); if (propertyNames[0].Kind == 0x00) { Site.CaptureRequirementIfAreNotEqual<ushort>( 0x0000, ropGetPropertyIdsFromNamesResponse.PropertyIds[0].ID, 225, @"[In RopGetPropertyIdsFromNames ROP Response Buffer] PropertyIds: Reasons a name couldn't be mapped include: Use of the PS_MAPI namespace and not specifying 0x00 for the Kind field of the PropertyName structure ([MS-OXCDATA] section 2.6.1)."); } if (flags != 0x02 && isPropertyNameExisting) { Site.CaptureRequirementIfAreNotEqual<ushort>( 0x0000, ropGetPropertyIdsFromNamesResponse.PropertyIds[0].ID, 226, @"[In RopGetPropertyIdsFromNames ROP Response Buffer] PropertyIds: Reasons a name couldn't be mapped include:The name wasn't found in the mapping table and the Flags field of the ROP request buffer was not set to 0x02."); } if (ropGetPropertyIdsFromNamesResponse.ReturnValue.Equals((uint)CPRPTErrorCode.None)) { if (objectType == ServerObjectType.Message) { // If the object type this operation acting on is Message object and this operation is performed successfully, then the following requirement can be captured. Site.CaptureRequirement( 20701, @"[In RopGetPropertyIdsFromNames ROP] This operation [RopGetPropertyIdsFromNames ROP] is valid on Message objects."); } if (objectType == ServerObjectType.Attachment) { // If the object type this operation acting on is Folder object and this operation is performed successfully, then the following requirement can be captured. Site.CaptureRequirement( 20702, @"[In RopGetPropertyIdsFromNames ROP] This operation [RopGetPropertyIdsFromNames ROP] is valid on Attachment objects."); } if (objectType == ServerObjectType.Folder) { // If the object type this operation acting on is Attachment object and this operation is performed successfully, then the following requirement can be captured. Site.CaptureRequirement( 20703, @"[In RopGetPropertyIdsFromNames ROP] This operation [RopGetPropertyIdsFromNames ROP] is valid on Folder objects."); } if (objectType == ServerObjectType.Logon) { // If the object type this operation acting on is Logon object and this operation is performed successfully, then the following requirement can be captured. Site.CaptureRequirement( 20704, @"[In RopGetPropertyIdsFromNames ROP] This operation [RopGetPropertyIdsFromNames ROP] is valid on Logon objects."); } // The parser has ensured the field satisfied the format, otherwise the response cannot be received. Site.CaptureRequirement( 215, @"[In RopGetPropertyIdsFromNames ROP Response Buffer] PropertyIdCount: 2 bytes integer."); Site.CaptureRequirementIfAreEqual<ushort>( (ushort)ropGetPropertyIdsFromNamesResponse.PropertyIds.Length, ropGetPropertyIdsFromNamesResponse.PropertyIdCount, 21502, @"[In RopGetPropertyIdsFromNames ROP Response Buffer] PropertyIdCount: An integer that specifies the number of property IDs contained in the PropertyIds field. "); if (propertyNameCount != 0) { Site.CaptureRequirementIfAreEqual<ushort>( propertyNameCount, ropGetPropertyIdsFromNamesResponse.PropertyIdCount, 216, @"[In RopGetPropertyIdsFromNames ROP Response Buffer] PropertyIdCount: The value of this field MUST be equal to the value of the PropertyNameCount field of the ROP request buffer unless the value of the PropertyNameCount field is zero."); } } // Verify MS-OXCPRPT requirement: MS-OXCPRPT_R218 bool isVerifyR218 = true; for (int i = 0; i < ropGetPropertyIdsFromNamesResponse.PropertyIds.Length; i++) { // Check that every element's size in PropertyIds is 16-bit if (Marshal.SizeOf(ropGetPropertyIdsFromNamesResponse.PropertyIds[i]) != 2) { // Add the debug information Site.Log.Add( LogEntryKind.Debug, "Verify MS-OXCPRPT_R218, The actual length of PropertyId is {0}", Marshal.SizeOf(ropGetPropertyIdsFromNamesResponse.PropertyIds[i])); isVerifyR218 = false; break; } } Site.CaptureRequirementIfIsTrue( isVerifyR218, 218, @"[In RopGetPropertyIdsFromNames ROP Response Buffer] propertyIds (variable): An array of 16-bit integers. "); // Verify MS-OXCPRPT requirement: MS-OXCPRPT_R222 // The order has been verified when de-serializing the related structures and represented by the variable isOrdered Site.CaptureRequirementIfIsTrue( isOrdered, 222, @"[In RopGetPropertyIdsFromNames ROP Response Buffer] PropertyIds: The order of property IDs in this array MUST match the order of the named properties specified in the PropertyNames field of the ROP request buffer."); Site.CaptureRequirementIfIsTrue( isOrdered, 21801, @"[In RopGetPropertyIdsFromNames ROP Response Buffer] PropertyIds: Each integer is a property ID that is mapped from a named property that is specified in the PropertyNames field of the ROP request buffer"); if (!((propertyNameCount == 0) && (objectType == ServerObjectType.Logon))) { // !isPropertyNameExisting means that the propertyNames doesn't exist on server. // The property flag doesn't equal 0x02 means the Create bit in the Flags parameter is not set. if (!isPropertyNameExisting && (flags != 0x02)) { for (int i = 0; i < ropGetPropertyIdsFromNamesResponse.PropertyIds.Length; i++) { // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCPRPT_R532"); // Verify MS-OXCPRPT requirement: MS-OXCPRPT_R532 // The PropertyNames don't exist on server means the PropertyNames requested are the unfound rows. // The logon user is Administrator and the test suite will not reach the server-imposed limit on property ID // mappings, so the user always has permission to create new entries and the server-imposed limit is not reached. // Since the Flags parameter doesn't have the Create flag bit set, so the "unless" condition will be still false. Site.CaptureRequirementIfAreEqual<ushort>( 0x0000, ropGetPropertyIdsFromNamesResponse.PropertyIds[i].ID, 532, @"[In Processing RopGetPropertyIdsFromNames] [If the PropertyNameCount parameter is zero, and the RopGetPropertyIdsFromNames is acting on a Logon object, the server must enumerate all PropertyNames associated with property IDs] Otherwise, the server MUST, for each entry in the PropertyNames field of the ROP request buffer, follow this procedure: 3. For unfound rows, the returned property ID MUST be 0x0000 unless all of the following conditions are true: 1.The Flags field of the ROP request buffer is set to 0x02. 2. The user has permission to create new entries. 3. The server-imposed limit on property ID mappings specified later in this section hasn't yet been reached."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCPRPT_R220"); // Verify MS-OXCPRPT requirement: MS-OXCPRPT_R220 // The PropertyNames don't exist on server and the Flags parameter doesn't have the Create flag bit set means // the names could not be mapped. Site.CaptureRequirementIfAreEqual<ushort>( 0x0000, ropGetPropertyIdsFromNamesResponse.PropertyIds[i].ID, 220, @"[In RopGetPropertyIdsFromNames ROP Response Buffer] PropertyIds: If a named property cannot be mapped, the associated entry in the PropertyIds field MUST be 0x0000."); } } // !isPropertyNameExisting means the propertyNames don't exist on server // flags equals to 0x02 means the Flags parameter has the Create flag bit set. // The logon user is Administrator and the test suite will not reach the server-imposed limit on property ID // mappings, so the user always has permission to create new entries and the server-imposed limit is not reached. // If all of these above condition are met, it means the returned id is newly assigned. if (!isPropertyNameExisting && (flags == 0x02)) { for (int i = 0; i < ropGetPropertyIdsFromNamesResponse.PropertyIds.Length; i++) { // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCPRPT_R534"); // Verify MS-OXCPRPT requirement: MS-OXCPRPT_R534 Site.CaptureRequirementIfAreNotEqual<ushort>( 0xFFFF, ropGetPropertyIdsFromNamesResponse.PropertyIds[i].ID, 534, @"[In Processing RopGetPropertyIdsFromNames] [If the PropertyNameCount parameter is zero, and the RopGetPropertyIdsFromNames is acting on a Logon object, the server must enumerate all PropertyNames associated with property IDs] Otherwise, the server MUST, for each entry in the PropertyNames field of the ROP request buffer, follow this procedure: 4. [If the above conditions in step three are all met, a new property ID is registered for the named property.] The newly assigned property ID MUST NOT be equal to 0xFFFF."); // Verify MS-OXCPRPT requirement: MS-OXCPRPT_R535 Site.CaptureRequirementIfIsTrue( ropGetPropertyIdsFromNamesResponse.PropertyIds[i].ID > 0x8000, 535, @"[In Processing RopGetPropertyIdsFromNames] [If the PropertyNameCount parameter is zero, and the RopGetPropertyIdsFromNames is acting on a Logon object, the server must enumerate all PropertyNames associated with property IDs] Otherwise, the server MUST, for each entry in the PropertyNames field of the ROP request buffer, follow this procedure: 4. [If the above conditions in step three are all met, a new property ID is registered for the named property.] The newly assigned property ID MUST be greater than 0x8000."); } } // When the PropertyNames requested exist on the server, then the server can find the property ID associated with the PropertyName. if (isPropertyNameExisting) { // Verify MS-OXCPRPT requirement: MS-OXCPRPT_R531 // Whether the PropertyNames queried and the returned Ids are mapping has been verified and represented as the Boolean value isNameAndIdMapping. Site.CaptureRequirementIfIsTrue( isNamesAndIdsMapping, 531, @"[In Processing RopGetPropertyIdsFromNames] [If the PropertyNameCount parameter is zero, and the RopGetPropertyIdsFromNames is acting on a Logon object, the server must enumerate all PropertyNames associated with property IDs] Otherwise, the server MUST, for each entry in the PropertyNames field of the ROP request buffer, follow this procedure: 2. Find the property ID registered for the named property that matches the PropertyName structure as follows: If the Kind field is set to 0x00, the named property has a LID that matches the value of the LID field of the PropertyName structure."); for (int i = 0; i < ropGetPropertyIdsFromNamesResponse.PropertyIds.Length; i++) { if (Common.CompareByteArray(propertyNames[i].Guid, this.valuePSMAPI)) { // Verify MS-OXCPRPT requirement: MS-OXCPRPT_R642 Site.CaptureRequirementIfAreEqual<ushort>( (ushort)propertyNames[i].LID, ropGetPropertyIdsFromNamesResponse.PropertyIds[i].ID, 642, @"[In Processing RopGetPropertyIdsFromNames] [If the PropertyNameCount parameter is zero, and the RopGetPropertyIdsFromNames is acting on a Logon object, the server must enumerate all PropertyNames associated with property IDs] Otherwise, the server MUST, for each entry in the PropertyNames field of the ROP request buffer, follow this procedure: 1. If the GUID field of the PropertyName structure ([MS-OXCDATA] section 2.6.1) in the ROP request buffer specifies the PS_MAPI property set, the returned property ID is obtained from the LID field."); } } } } // The parser has ensured the field satisfied the format, otherwise the response cannot be received. Site.CaptureRequirement( 198, @"[In RopGetPropertyIdsFromNames ROP] The RopGetPropertyIdsFromNames ROP ([MS-OXCROPS] section 2.2.8.1) maps abstract, client-defined named properties to concrete 16-bit property IDs (of which 15 bits are significant)."); }
/// <summary> /// Set the value of properties identified by long ID or name in message. /// </summary> /// <param name="messageHandle">The specified message handle.</param> /// <param name="property">The PropertyName of specified property.</param> /// <param name="value">The value of specified property.</param> private void SetNamedProperty(uint messageHandle, PropertyNameObject property, byte[] value) { #region Call RopGetPropertyIdsFromNames to get property ID. PropertyName[] propertyNames = new PropertyName[1]; propertyNames[0] = property.PropertyName; RopGetPropertyIdsFromNamesRequest getPropertyIdsFromNamesRequest = new RopGetPropertyIdsFromNamesRequest() { RopId = (byte)RopId.RopGetPropertyIdsFromNames, LogonId = CommonLogonId, InputHandleIndex = CommonInputHandleIndex, Flags = (byte)GetPropertyIdsFromNamesFlags.Create, PropertyNameCount = (ushort)propertyNames.Length, PropertyNames = propertyNames, }; this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(getPropertyIdsFromNamesRequest, messageHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None); RopGetPropertyIdsFromNamesResponse getPropertyIdsFromNamesResponse = (RopGetPropertyIdsFromNamesResponse)this.response; Site.Assert.AreEqual<uint>(TestSuiteBase.Success, getPropertyIdsFromNamesResponse.ReturnValue, "Call RopGetPropertyIdsFromNames should success."); #endregion #region Set property value. List<TaggedPropertyValue> taggedPropertyValues = new List<TaggedPropertyValue>(); int valueSize = 0; PropertyTag propertyTag = new PropertyTag { PropertyId = getPropertyIdsFromNamesResponse.PropertyIds[0].ID, PropertyType = (ushort)property.PropertyType }; TaggedPropertyValue taggedPropertyValue = new TaggedPropertyValue { PropertyTag = propertyTag, Value = value }; valueSize += taggedPropertyValue.Size(); taggedPropertyValues.Add(taggedPropertyValue); RopSetPropertiesRequest rpmSetRequest = new RopSetPropertiesRequest() { RopId = (byte)RopId.RopSetProperties, LogonId = CommonLogonId, InputHandleIndex = CommonInputHandleIndex, PropertyValueCount = (ushort)taggedPropertyValues.Count, PropertyValueSize = (ushort)(valueSize + 2), PropertyValues = taggedPropertyValues.ToArray() }; this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(rpmSetRequest, messageHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None); RopSetPropertiesResponse rpmSetResponse = (RopSetPropertiesResponse)this.response; Site.Assert.AreEqual<uint>(TestSuiteBase.Success, rpmSetResponse.PropertyProblemCount, "If ROP succeeds, the PropertyProblemCount of its response is 0(success)."); #endregion }
/// <summary> /// Create propertyName array /// </summary> /// <param name="propertyNameCount">The count of propertyName</param> /// <returns>Return propertyName array</returns> private PropertyName[] CreatePropertyNameArray(int propertyNameCount) { Guid newGUID; byte[] unicodeName; int lastIndex; PropertyName[] propertyNameArray = new PropertyName[propertyNameCount]; for (int i = 0; i < propertyNameCount; i++) { newGUID = new Guid(); propertyNameArray[i] = new PropertyName { Kind = 0x01, Guid = newGUID.ToByteArray() }; // The property is identified by the Name field. // A Unicode (UTF-16) string, followed by two zero bytes as a null terminator // that identifies the property within its property set. unicodeName = Encoding.Unicode.GetBytes("ClientDefinedProperty" + i.ToString() + "x"); lastIndex = unicodeName.Length - 1; unicodeName[lastIndex] = 0; unicodeName[--lastIndex] = 0; // 2-byte null terminator ALSO counted into NameSize. propertyNameArray[i].NameSize = (byte)unicodeName.Length; propertyNameArray[i].Name = unicodeName; } return propertyNameArray; }
public void MSOXORULE_S04_TC02_AddModifyDeleteExtendedRule_OnPublicFolder() { this.CheckMAPIHTTPTransportSupported(); #region TestUser1 logs on to the public folder. RopOpenFolderResponse openFolderResponse; RopLogonResponse logonResponse; bool ret = this.OxoruleAdapter.Connect(ConnectionType.PublicFolderServer, this.User1Name, this.User1ESSDN, this.User1Password); Site.Assert.IsTrue(ret, "connect to public folder server should be successful"); uint publicFolderLogonHandler = this.OxoruleAdapter.RopLogon(LogonType.PublicFolder, this.User1ESSDN, out logonResponse); // Assert the client to log on to the public folder successfully. Site.Assert.AreEqual<uint>(0, logonResponse.ReturnValue, "Logon the public folder should be successful."); // Folder index 1 is the Interpersonal Messages subtree, and this is defined in MS-OXCSTOR. uint publicfolderHandler = this.OxoruleAdapter.RopOpenFolder(publicFolderLogonHandler, logonResponse.FolderIds[1], out openFolderResponse); // Get the store object's entry ID. this.GetStoreObjectEntryID(StoreObjectType.PublicFolder, this.Server, this.User1ESSDN); RopCreateFolderResponse createFolderResponse; string newFolderName = Common.GenerateResourceName(this.Site, Constants.FolderDisplayName); uint newFolderHandle = this.OxoruleAdapter.RopCreateFolder(publicfolderHandler, newFolderName, Constants.FolderComment, out createFolderResponse); ulong newFolderID = createFolderResponse.FolderId; Site.Assert.AreEqual<uint>(0, createFolderResponse.ReturnValue, "Creating folder operation should succeed."); #endregion #region TestUser1 creates an FAI message. RopCreateMessageResponse ropCreateMessageResponse; uint extendedRuleMessageHandle = this.OxoruleAdapter.RopCreateMessage(newFolderHandle, newFolderID, Convert.ToByte(true), out ropCreateMessageResponse); Site.Assert.AreEqual<uint>(0, ropCreateMessageResponse.ReturnValue, "Creating the first FAI message should succeed."); #endregion #region TestUser1 adds the extended rule with NamedProperty successfully. string ruleConditionSubjectNameForAdd = Constants.RuleConditionSubjectContainString; NamedPropertyInfo namedPropertyInfo = new NamedPropertyInfo { NoOfNamedProps = 2, PropId = new uint[2] { 0x8001, 0x8002 } }; PropertyName testPropertyName = new PropertyName { Guid = System.Guid.NewGuid().ToByteArray(), Kind = 0x01, Name = Encoding.Unicode.GetBytes(Constants.NameOfPropertyName + "\0") }; // 0x01 means the property is identified by the name property. testPropertyName.NameSize = (byte)testPropertyName.Name.Length; PropertyName secondPropertyName = new PropertyName { Guid = System.Guid.NewGuid().ToByteArray(), Kind = 0x00, LID = 0x88888888 }; // 0x00 means the property is identified by the LID. namedPropertyInfo.NamedProperty = new PropertyName[2] { testPropertyName, secondPropertyName }; namedPropertyInfo.NamedPropertiesSize = (uint)(testPropertyName.Serialize().Length + secondPropertyName.Serialize().Length); string ruleName = Common.GenerateResourceName(this.Site, Constants.ExtendRulename1); TaggedPropertyValue[] extendedRulePropertiesForAdd = AdapterHelper.GenerateExtendedRuleTestData(ruleName, 0, (uint)RuleState.ST_ENABLED, Constants.PidTagRuleProvider, ActionType.OP_MARK_AS_READ, new DeleteMarkReadActionData(), ruleConditionSubjectNameForAdd, namedPropertyInfo); // Set properties for extended rule FAI message. RopSetPropertiesResponse ropSetPropertiesResponse = this.OxoruleAdapter.RopSetProperties(extendedRuleMessageHandle, extendedRulePropertiesForAdd); Site.Assert.AreEqual<uint>(0, ropSetPropertiesResponse.ReturnValue, "Setting property for Extended rule FAI message should succeed."); // Save changes of message. RopSaveChangesMessageResponse ropSaveChangesMessagResponse = this.OxoruleAdapter.RopSaveChangesMessage(extendedRuleMessageHandle); Site.Assert.AreEqual<uint>(0, ropSaveChangesMessagResponse.ReturnValue, "Saving Extend rule message should succeed."); // Specify the properties to be got. PropertyTag[] propertyTagArray = new PropertyTag[1]; // PidTagRuleMessageProvider propertyTagArray[0].PropertyId = (ushort)PropertyId.PidTagRuleMessageProvider; propertyTagArray[0].PropertyType = (ushort)PropertyType.PtypString; // Get the specific properties of the extended rule. RopGetPropertiesSpecificResponse ropGetPropertiesSpecificResponse = this.OxoruleAdapter.RopGetPropertiesSpecific(extendedRuleMessageHandle, propertyTagArray); Site.Assert.AreEqual<uint>(0, ropGetPropertiesSpecificResponse.ReturnValue, "Getting specific properties operation should succeed."); string pidTagRuleMessageProviderData = AdapterHelper.PropertyValueConvertToString(ropGetPropertiesSpecificResponse.RowData.PropertyValues[0].Value); Site.Assert.AreEqual<string>(Constants.PidTagRuleProvider, pidTagRuleMessageProviderData, "The rule provider data should be RuleOrganizer."); #endregion #region Modify the created rule. ruleName = Common.GenerateResourceName(this.Site, Constants.ExtendRulename2); TaggedPropertyValue[] extendedRulePropertiesForModify = AdapterHelper.GenerateExtendedRuleTestData(ruleName, 0, (uint)RuleState.ST_ENABLED, Constants.PidTagRuleProvider, ActionType.OP_MARK_AS_READ, new DeleteMarkReadActionData(), ruleConditionSubjectNameForAdd, namedPropertyInfo); // Set properties for extended rule FAI message. ropSetPropertiesResponse = this.OxoruleAdapter.RopSetProperties(extendedRuleMessageHandle, extendedRulePropertiesForModify); Site.Assert.AreEqual<uint>(0, ropSetPropertiesResponse.ReturnValue, "Setting property for Extended rule FAI message should succeed."); // Save changes of message. ropSaveChangesMessagResponse = this.OxoruleAdapter.RopSaveChangesMessage(extendedRuleMessageHandle); Site.Assert.AreEqual<uint>(0, ropSaveChangesMessagResponse.ReturnValue, "Saving Extend rule message should succeed."); // PidTagSubject propertyTagArray[0].PropertyId = (ushort)PropertyId.PidTagRuleMessageName; propertyTagArray[0].PropertyType = (ushort)PropertyType.PtypString; // Get the specific properties of the extended rule. ropGetPropertiesSpecificResponse = this.OxoruleAdapter.RopGetPropertiesSpecific(extendedRuleMessageHandle, propertyTagArray); Site.Assert.AreEqual<uint>(0, ropGetPropertiesSpecificResponse.ReturnValue, "Getting specific properties operation should succeed."); string messageName = AdapterHelper.PropertyValueConvertToString(ropGetPropertiesSpecificResponse.RowData.PropertyValues[0].Value); Site.Assert.AreEqual<string>(ruleName, messageName, "The rule subject should be {0}.", ruleName); #endregion #region Release the created message to delete the created rule. this.OxoruleAdapter.ReleaseRop(extendedRuleMessageHandle); // Get the specific properties of the extended rule. ropGetPropertiesSpecificResponse = this.OxoruleAdapter.RopGetPropertiesSpecific(extendedRuleMessageHandle, propertyTagArray); Site.Assert.IsNull(ropGetPropertiesSpecificResponse.RowData, "The property value of the extended rule should be null!"); #endregion #region Delete the folder. RopDeleteFolderResponse deleteFolder = this.OxoruleAdapter.RopDeleteFolder(publicfolderHandler, newFolderID); Site.Assert.AreEqual<uint>(0, deleteFolder.ReturnValue, "Deleting folder should succeed."); #endregion }
/// <summary> /// RopGetPropertyIdsFromNames implementation /// </summary> /// <param name="objHandle">This index specifies the location in the Server object handle table where the handle for the input Server object is stored</param> /// <param name="flags">8-bit flags structure. These flags control the behavior of this operation</param> /// <param name="propertyNames">List of PropertyName structures. This field specifies the property names requested.</param> /// <param name="needVerify">Whether need to verify the response.</param> /// <returns>Structure of RopGetPropertyIdsFromNamesResponse</returns> private RopGetPropertyIdsFromNamesResponse RopGetPropertyIdsFromNames(uint objHandle, byte flags, PropertyName[] propertyNames, bool needVerify) { this.rawDataValue = null; this.responseValue = null; this.responseSOHsValue = null; RopGetPropertyIdsFromNamesRequest getPropertyIdsFromNamesRequest; RopGetPropertyIdsFromNamesResponse getPropertyIdsFromNamesResponse; getPropertyIdsFromNamesRequest.RopId = (byte)RopId.RopGetPropertyIdsFromNames; getPropertyIdsFromNamesRequest.LogonId = LogonId; getPropertyIdsFromNamesRequest.InputHandleIndex = (byte)HandleIndex.FirstIndex; getPropertyIdsFromNamesRequest.Flags = flags; getPropertyIdsFromNamesRequest.PropertyNames = propertyNames; if (getPropertyIdsFromNamesRequest.PropertyNames != null) { getPropertyIdsFromNamesRequest.PropertyNameCount = (ushort)propertyNames.Length; } else { // GetPropertyIdsFromNamesRequest.PropertyNames is null, so getPropertyIdsFromNamesRequest.PropertyNames is 0x00. getPropertyIdsFromNamesRequest.PropertyNameCount = 0x00; } this.responseSOHsValue = this.ProcessSingleRop(getPropertyIdsFromNamesRequest, objHandle, ref this.responseValue, ref this.rawDataValue, RopResponseType.SuccessResponse); getPropertyIdsFromNamesResponse = (RopGetPropertyIdsFromNamesResponse)this.responseValue; if (needVerify) { this.Site.Assert.AreEqual((uint)RopResponseType.SuccessResponse, getPropertyIdsFromNamesResponse.ReturnValue, string.Format("RopGetPropertyIdsFromNames Failed! Error: 0x{0:X8}", getPropertyIdsFromNamesResponse.ReturnValue)); } return getPropertyIdsFromNamesResponse; }