/// <summary> /// Parse the STAT from the response data. /// </summary> /// <param name="rawData">The response data.</param> /// <param name="startIndex">The start index.</param> /// <returns>The result of STAT.</returns> public static STAT Parse(byte[] rawData, ref int startIndex) { STAT state = new STAT(); state.SortType = BitConverter.ToUInt32(rawData, startIndex); startIndex += sizeof(uint); state.ContainerID = BitConverter.ToUInt32(rawData, startIndex); startIndex += sizeof(uint); state.CurrentRec = BitConverter.ToUInt32(rawData, startIndex); startIndex += sizeof(uint); state.Delta = BitConverter.ToInt32(rawData, startIndex); startIndex += sizeof(int); state.NumPos = BitConverter.ToUInt32(rawData, startIndex); startIndex += sizeof(uint); state.TotalRecs = BitConverter.ToUInt32(rawData, startIndex); startIndex += sizeof(uint); state.CodePage = BitConverter.ToUInt32(rawData, startIndex); startIndex += sizeof(uint); state.TemplateLocale = BitConverter.ToUInt32(rawData, startIndex); startIndex += sizeof(uint); state.SortLocale = BitConverter.ToUInt32(rawData, startIndex); startIndex += sizeof(uint); return(state); }
/// <summary> /// The NspiResolveNames method takes a set of string values in an 8-bit character set and performs ANR on those strings. /// The NspiResolveNames method taking string values in an 8-bit character set is not supported when mapi_http transport is used. /// </summary> /// <param name="reserved">A DWORD reserved for future use.</param> /// <param name="stat">A STAT block that describes a logical position in a specific address book container.</param> /// <param name="propTags">The value NULL or a reference to a PropertyTagArray_r value containing a list of the proptags of the columns /// that the client requests to be returned for each row returned.</param> /// <param name="stringArray">A StringsArray_r value. It specifies the values on which the client is requesting the server to do ANR.</param> /// <param name="mids">A PropertyTagArray_r value. On return, it contains a list of Minimal Entry IDs that match the array of strings.</param> /// <param name="rows">A reference to a PropertyRowSet_r value. /// It contains the address book container rows that the server returns in response to the request.</param> /// <param name="needRetry">A Boolean value indicates if need to retry to get an expected result. This parameter is designed to avoid meaningless retry when an error response is expected.</param> /// <returns>Status of NSPI method.</returns> public ErrorCodeValue NspiResolveNames(uint reserved, STAT stat, PropertyTagArray_r?propTags, StringsArray_r?stringArray, out PropertyTagArray_r?mids, out PropertyRowSet_r?rows, bool needRetry = true) { ErrorCodeValue result; result = this.nspiRpcAdapter.NspiResolveNames(reserved, stat, propTags, stringArray, out mids, out rows, needRetry); this.VerifyNspiResolveNames(result, mids, rows); this.VerifyTransport(); return(result); }
/// <summary> /// Parse the response data into response body. /// </summary> /// <param name="rawData">The raw data of response</param> /// <returns>The response body of the request</returns> public static ResortRestrictionResponseBody Parse(byte[] rawData) { ResortRestrictionResponseBody responseBody = new ResortRestrictionResponseBody(); int index = 0; responseBody.StatusCode = BitConverter.ToUInt32(rawData, index); index += sizeof(uint); responseBody.ErrorCode = BitConverter.ToUInt32(rawData, index); index += sizeof(uint); responseBody.HasState = BitConverter.ToBoolean(rawData, index); index += sizeof(bool); if (responseBody.HasState) { responseBody.State = STAT.Parse(rawData, ref index); } else { responseBody.State = null; } responseBody.HasMinimalIds = BitConverter.ToBoolean(rawData, index); index += sizeof(bool); List <uint> minimalIdsList = new List <uint>(); if (responseBody.HasMinimalIds) { responseBody.MinimalIdCount = BitConverter.ToUInt32(rawData, index); index += sizeof(uint); for (int i = 0; i < responseBody.MinimalIdCount; i++) { uint minId = BitConverter.ToUInt32(rawData, index); minimalIdsList.Add(minId); index += sizeof(uint); } responseBody.MinimalIds = minimalIdsList.ToArray(); } else { responseBody.MinimalIdCount = null; minimalIdsList = null; } responseBody.AuxiliaryBufferSize = BitConverter.ToUInt32(rawData, index); index += 4; responseBody.AuxiliaryBuffer = new byte[responseBody.AuxiliaryBufferSize]; Array.Copy(rawData, index, responseBody.AuxiliaryBuffer, 0, responseBody.AuxiliaryBufferSize); return(responseBody); }
/// <summary> /// The NspiGetSpecialTable method returns the rows of a special table to the client. /// </summary> /// <param name="flags">A DWORD value that contains a set of bit flags.</param> /// <param name="stat">A pointer to a STAT block that describes a logical position in a specific address book container.</param> /// <param name="version">A reference to a DWORD. On input, it holds the value of the version number of /// the address book hierarchy table that the client has. On output, it holds the version of the server's address book hierarchy table.</param> /// <param name="rows">A PropertyRowSet_r structure. On return, it holds the rows for the table that the client is requesting.</param> /// <param name="needRetry">A Boolean value indicates if need to retry to get an expected result. This parameter is designed to avoid meaningless retry when an error response is expected.</param> /// <returns>Status of NSPI method.</returns> public ErrorCodeValue NspiGetSpecialTable(uint flags, ref STAT stat, ref uint version, out PropertyRowSet_r?rows, bool needRetry = true) { ErrorCodeValue result; if (this.transport == "ncacn_http" || this.transport == "ncacn_ip_tcp") { result = this.nspiRpcAdapter.NspiGetSpecialTable(flags, ref stat, ref version, out rows, needRetry); } else { result = this.nspiMapiHttpAdapter.GetSpecialTable(flags, ref stat, ref version, out rows); } this.VerifyNspiGetSpecialTable(result, rows); this.VerifyTransport(); return(result); }
/// <summary> /// Parse the response data into response body. /// </summary> /// <param name="rawData">The raw data of response</param> /// <returns>The response body of the request</returns> public static SeekEntriesResponseBody Parse(byte[] rawData) { SeekEntriesResponseBody responseBody = new SeekEntriesResponseBody(); int index = 0; responseBody.StatusCode = BitConverter.ToUInt32(rawData, index); index += sizeof(uint); responseBody.ErrorCode = BitConverter.ToUInt32(rawData, index); index += sizeof(uint); responseBody.HasState = BitConverter.ToBoolean(rawData, index); index += sizeof(bool); if (responseBody.HasState) { responseBody.State = STAT.Parse(rawData, ref index); } else { responseBody.State = null; } responseBody.HasColumnsAndRows = BitConverter.ToBoolean(rawData, index); index += sizeof(bool); if (responseBody.HasColumnsAndRows) { responseBody.Columns = LargePropTagArray.Parse(rawData, ref index); responseBody.RowCount = BitConverter.ToUInt32(rawData, index); responseBody.RowData = new AddressBookPropertyRow[(uint)responseBody.RowCount]; index += sizeof(uint); for (int i = 0; i < responseBody.RowCount; i++) { responseBody.RowData[i] = AddressBookPropertyRow.Parse(rawData, (LargePropTagArray)responseBody.Columns, ref index); } } else { responseBody.Columns = null; responseBody.RowCount = null; responseBody.RowData = null; } responseBody.AuxiliaryBufferSize = BitConverter.ToUInt32(rawData, index); index += 4; responseBody.AuxiliaryBuffer = new byte[responseBody.AuxiliaryBufferSize]; Array.Copy(rawData, index, responseBody.AuxiliaryBuffer, 0, responseBody.AuxiliaryBufferSize); return(responseBody); }
/// <summary> /// The NspiGetProps method returns an address book row that contains a set of the properties /// and values that exist on an object. /// </summary> /// <param name="flags">A DWORD value that contains a set of bit flags.</param> /// <param name="stat">A STAT block that describes a logical position in a specific address book container.</param> /// <param name="propTags">The value NULL or a reference to a PropertyTagArray_r value. /// It contains a list of the proptags of the properties that the client wants to be returned.</param> /// <param name="rows">A nullable PropertyRow_r value. /// It contains the address book container row the server returns in response to the request.</param> /// <param name="needRetry">A Boolean value indicates if need to retry to get an expected result. This parameter is designed to avoid meaningless retry when an error response is expected.</param> /// <returns>Status of NSPI method.</returns> public ErrorCodeValue NspiGetProps(uint flags, STAT stat, PropertyTagArray_r?propTags, out PropertyRow_r?rows, bool needRetry = true) { ErrorCodeValue result; if (this.transport == "ncacn_http" || this.transport == "ncacn_ip_tcp") { result = this.nspiRpcAdapter.NspiGetProps(flags, stat, propTags, out rows, needRetry); } else { result = this.nspiMapiHttpAdapter.GetProps(flags, stat, propTags, out rows); } this.VerifyNspiGetProps(result, rows); this.VerifyTransport(); return(result); }
/// <summary> /// The NspiCompareMIds method compares the position in an address book container of two objects /// identified by Minimal Entry ID and returns the value of the comparison. /// </summary> /// <param name="reserved">A DWORD value reserved for future use. Ignored by the server.</param> /// <param name="stat">A STAT block that describes a logical position in a specific address book container.</param> /// <param name="mid1">The mid1 is a DWORD value containing a Minimal Entry ID.</param> /// <param name="mid2">The mid2 is a DWORD value containing a Minimal Entry ID.</param> /// <param name="results">A DWORD value. On return, it contains the result of the comparison.</param> /// <param name="needRetry">A Boolean value indicates if need to retry to get an expected result. This parameter is designed to avoid meaningless retry when an error response is expected.</param> /// <returns>Status of NSPI method.</returns> public ErrorCodeValue NspiCompareMIds(uint reserved, STAT stat, uint mid1, uint mid2, out int results, bool needRetry = true) { ErrorCodeValue result; if (this.transport == "ncacn_http" || this.transport == "ncacn_ip_tcp") { result = this.nspiRpcAdapter.NspiCompareMIds(reserved, stat, mid1, mid2, out results, needRetry); } else { result = this.nspiMapiHttpAdapter.CompareMIds(reserved, stat, mid1, mid2, out results); } this.VerifyNspiCompareMIds(result); this.VerifyTransport(); return(result); }
/// <summary> /// The NspiBind method initiates a session between a client and the server. /// </summary> /// <param name="flags">A DWORD value that contains a set of bit flags.</param> /// <param name="stat">A pointer to a STAT block that describes a logical position in a specific address book container.</param> /// <param name="serverGuid">The value NULL or a pointer to a GUID value that is associated with the specific server.</param> /// <param name="needRetry">A Boolean value indicates if need to retry to get an expected result. This parameter is designed to avoid meaningless retry when an error response is expected.</param> /// <returns>Status of NSPI method.</returns> public ErrorCodeValue NspiBind(uint flags, STAT stat, ref FlatUID_r?serverGuid, bool needRetry = true) { ErrorCodeValue result; if (this.transport == "ncacn_http" || this.transport == "ncacn_ip_tcp") { result = this.nspiRpcAdapter.NspiBind(flags, stat, ref serverGuid, needRetry); } else { result = this.nspiMapiHttpAdapter.Bind(flags, stat, ref serverGuid); } this.VerifyNspiBind(); this.VerifyTransport(); return(result); }
/// <summary> /// The NspiModProps method is used to modify the properties of an object in the address book. /// </summary> /// <param name="reserved">A DWORD value reserved for future use.</param> /// <param name="stat">A STAT block that describes a logical position in a specific address book container.</param> /// <param name="propTags">The value NULL or a reference to a PropertyTagArray_r. /// It contains a list of the proptags of the columns from which the client requests all the values to be removed.</param> /// <param name="row">A PropertyRow_r value. It contains an address book row.</param> /// <param name="needRetry">A Boolean value indicates if need to retry to get an expected result. This parameter is designed to avoid meaningless retry when an error response is expected.</param> /// <returns>Status of NSPI method.</returns> public ErrorCodeValue NspiModProps(uint reserved, STAT stat, PropertyTagArray_r?propTags, PropertyRow_r row, bool needRetry = true) { ErrorCodeValue result; if (this.transport == "ncacn_http" || this.transport == "ncacn_ip_tcp") { result = this.nspiRpcAdapter.NspiModProps(reserved, stat, propTags, row, needRetry); } else { result = this.nspiMapiHttpAdapter.ModProps(stat, propTags, row); } this.VerifyNspiModProps(result); this.VerifyTransport(); return(result); }
/// <summary> /// The NspiResolveNamesW method takes a set of string values in the Unicode character set and performs ANR on those strings. /// </summary> /// <param name="reserved">A DWORD value that is reserved for future use.</param> /// <param name="stat">A STAT block that describes a logical position in a specific address book container.</param> /// <param name="propTags">The value NULL or a reference to a PropertyTagArray_r containing a list of the proptags of the columns /// that the client requests to be returned for each row returned.</param> /// <param name="wstr">A WStringsArray_r value. It specifies the values on which the client is requesting the server to perform ANR.</param> /// <param name="mids">A PropertyTagArray_r value. On return, it contains a list of Minimal Entry IDs that match the array of strings.</param> /// <param name="rowOfResolveNamesW">A reference to a PropertyRowSet_r structure. It contains the address book container rows that the server returns in response to the request.</param> /// <param name="needRetry">A Boolean value indicates if need to retry to get an expected result. This parameter is designed to avoid meaningless retry when an error response is expected.</param> /// <returns>Status of NSPI method.</returns> public ErrorCodeValue NspiResolveNamesW(uint reserved, STAT stat, PropertyTagArray_r?propTags, WStringsArray_r?wstr, out PropertyTagArray_r?mids, out PropertyRowSet_r?rowOfResolveNamesW, bool needRetry = true) { ErrorCodeValue result; if (this.transport == "ncacn_http" || this.transport == "ncacn_ip_tcp") { result = this.nspiRpcAdapter.NspiResolveNamesW(reserved, stat, propTags, wstr, out mids, out rowOfResolveNamesW, needRetry); } else { result = this.nspiMapiHttpAdapter.ResolveNames(reserved, stat, propTags, wstr, out mids, out rowOfResolveNamesW); } this.VerifyNspiResolveNamesW(result, mids, rowOfResolveNamesW); this.VerifyTransport(); return(result); }
/// <summary> /// The NspiUpdateStat method updates the STAT block that represents the position in a table /// to reflect positioning changes requested by the client. /// </summary> /// <param name="reserved">A DWORD value. Reserved for future use. Ignored by the server.</param> /// <param name="stat">A pointer to a STAT block describing a logical position in a specific address book container.</param> /// <param name="delta">The value NULL or a pointer to a LONG value that indicates movement /// within the address book container specified by the input parameter stat.</param> /// <param name="needRetry">A Boolean value indicates if need to retry to get an expected result. This parameter is designed to avoid meaningless retry when an error response is expected.</param> /// <returns>Status of NSPI method.</returns> public ErrorCodeValue NspiUpdateStat(uint reserved, ref STAT stat, ref int?delta, bool needRetry = true) { ErrorCodeValue result; STAT inputStat = stat; if (this.transport == "ncacn_http" || this.transport == "ncacn_ip_tcp") { result = this.nspiRpcAdapter.NspiUpdateStat(reserved, ref stat, ref delta, needRetry); } else { result = this.nspiMapiHttpAdapter.UpdateStat(ref stat, ref delta); } this.VerifyNspiUpdateStat(result, inputStat, stat); this.VerifyTransport(); return(result); }
/// <summary> /// The NspiResortRestriction method applies to a sort order to the objects in a restricted address book container. /// </summary> /// <param name="reserved">A DWORD value reserved for future use. Ignored by the server.</param> /// <param name="stat">A reference to a STAT block describing a logical position in a specific address book container.</param> /// <param name="proInMIds">A PropertyTagArray_r value. /// It holds a list of Minimal Entry IDs that comprise a restricted address book container.</param> /// <param name="outMIds">A PropertyTagArray_r value. On return, it holds a list of Minimal Entry IDs /// that comprise a restricted address book container.</param> /// <param name="needRetry">A Boolean value indicates if need to retry to get an expected result. This parameter is designed to avoid meaningless retry when an error response is expected.</param> /// <returns>Status of NSPI method.</returns> public ErrorCodeValue NspiResortRestriction(uint reserved, ref STAT stat, PropertyTagArray_r proInMIds, ref PropertyTagArray_r?outMIds, bool needRetry = true) { ErrorCodeValue result; STAT inputStat = stat; if (this.transport == "ncacn_http" || this.transport == "ncacn_ip_tcp") { result = this.nspiRpcAdapter.NspiResortRestriction(reserved, ref stat, proInMIds, ref outMIds, needRetry); } else { result = this.nspiMapiHttpAdapter.ResortRestriction(reserved, ref stat, proInMIds, ref outMIds); } this.VerifyNspiResortRestriction(result, outMIds, inputStat, stat); this.VerifyTransport(); return(result); }
/// <summary> /// The NspiSeekEntries method searches for and sets the logical position in a specific table /// to the first entry greater than or equal to a specified value. /// </summary> /// <param name="reserved">A DWORD value that is reserved for future use. Ignored by the server.</param> /// <param name="stat">A STAT block that describes a logical position in a specific address book container.</param> /// <param name="target">A PropertyValue_r value holding the value that is being sought.</param> /// <param name="table">The value NULL or a PropertyTagArray_r value. /// It holds a list of Minimal Entry IDs that comprise a restricted address book container.</param> /// <param name="propTags">It contains a list of the proptags of the columns /// that client wants to be returned for each row returned.</param> /// <param name="rows">It contains the address book container rows the server returns in response to the request.</param> /// <param name="needRetry">A Boolean value indicates if need to retry to get an expected result. This parameter is designed to avoid meaningless retry when an error response is expected.</param> /// <returns>Status of NSPI method.</returns> public ErrorCodeValue NspiSeekEntries(uint reserved, ref STAT stat, PropertyValue_r target, PropertyTagArray_r?table, PropertyTagArray_r?propTags, out PropertyRowSet_r?rows, bool needRetry = true) { ErrorCodeValue result = 0; STAT inputStat = stat; if (this.transport == "ncacn_http" || this.transport == "ncacn_ip_tcp") { result = this.nspiRpcAdapter.NspiSeekEntries(reserved, ref stat, target, table, propTags, out rows, needRetry); } else { result = this.nspiMapiHttpAdapter.SeekEntries(reserved, ref stat, target, table, propTags, out rows); } this.VerifyNspiSeekEntries(result, rows, inputStat, stat); this.VerifyTransport(); return(result); }
/// <summary> /// The NspiGetMatches method returns an Explicit Table. /// </summary> /// <param name="reserved">A DWORD value reserved for future use.</param> /// <param name="stat">A STAT block describing a logical position in a specific address book container.</param> /// <param name="proReserved">A PropertyTagArray_r reserved for future use.</param> /// <param name="reserved2">A DWORD value reserved for future use. Ignored by the server.</param> /// <param name="filter">The value NULL or a Restriction_r value. /// It holds a logical restriction to apply to the rows in the address book container specified in the stat parameter.</param> /// <param name="propName">The value NULL or a PropertyName_r value. /// It holds the property to be opened as a restricted address book container.</param> /// <param name="requested">A DWORD value. It contains the maximum number of rows to return in a restricted address book container.</param> /// <param name="outMids">A PropertyTagArray_r value. On return, it holds a list of Minimal Entry IDs that comprise a restricted address book container.</param> /// <param name="propTags">The value NULL or a reference to a PropertyTagArray_r value. /// It contains a list of the proptags of the columns that client wants to be returned for each row returned.</param> /// <param name="rows">A reference to a PropertyRowSet_r value. It contains the address book container rows the server returns in response to the request.</param> /// <param name="needRetry">A Boolean value indicates if need to retry to get an expected result. This parameter is designed to avoid meaningless retry when an error response is expected.</param> /// <returns>Status of NSPI method.</returns> public ErrorCodeValue NspiGetMatches(uint reserved, ref STAT stat, PropertyTagArray_r?proReserved, uint reserved2, Restriction_r?filter, PropertyName_r?propName, uint requested, out PropertyTagArray_r?outMids, PropertyTagArray_r?propTags, out PropertyRowSet_r?rows, bool needRetry = true) { ErrorCodeValue result = 0; STAT inputStat = stat; if (this.transport == "ncacn_http" || this.transport == "ncacn_ip_tcp") { result = this.nspiRpcAdapter.NspiGetMatches(reserved, ref stat, proReserved, reserved2, filter, propName, requested, out outMids, propTags, out rows, needRetry); } else { result = this.nspiMapiHttpAdapter.GetMatches(reserved, ref stat, proReserved, reserved2, filter, propName, requested, out outMids, propTags, out rows); } this.VerifyNspiGetMatches(result, rows, outMids, inputStat, stat); this.VerifyTransport(); return(result); }
/// <summary> /// The NspiQueryRows method returns a number of rows from a specified table to the client. /// </summary> /// <param name="flags">A DWORD value that contains a set of bit flags.</param> /// <param name="stat">A STAT block that describes a logical position in a specific address book container.</param> /// <param name="tableCount">A DWORD value that contains the number values in the input parameter table. /// This value is limited to 100,000.</param> /// <param name="table">An array of DWORD values, representing an Explicit Table.</param> /// <param name="count">A DWORD value that contains the number of rows the client is requesting.</param> /// <param name="propTags">The value NULL or a reference to a PropertyTagArray_r value, /// containing a list of the proptags of the properties that the client requires to be returned for each row returned.</param> /// <param name="rows">A nullable PropertyRowSet_r value, it contains the address book container rows that the server returns in response to the request.</param> /// <param name="needRetry">A Boolean value indicates if need to retry to get an expected result. This parameter is designed to avoid meaningless retry when an error response is expected.</param> /// <returns>Status of NSPI method.</returns> public ErrorCodeValue NspiQueryRows(uint flags, ref STAT stat, uint tableCount, uint[] table, uint count, PropertyTagArray_r?propTags, out PropertyRowSet_r?rows, bool needRetry = true) { ErrorCodeValue result; STAT inputStat = stat; if (this.transport == "ncacn_http" || this.transport == "ncacn_ip_tcp") { result = this.nspiRpcAdapter.NspiQueryRows(flags, ref stat, tableCount, table, count, propTags, out rows, needRetry); } else { result = this.nspiMapiHttpAdapter.QueryRows(flags, ref stat, tableCount, table, count, propTags, out rows); } this.VerifyNspiQueryRows(result, rows, inputStat, stat); this.VerifyTransport(); return(result); }
/// <summary> /// Parse the response data into response body. /// </summary> /// <param name="rawData">The raw data of response</param> /// <returns>The response body of the request</returns> public static UpdateStatResponseBody Parse(byte[] rawData) { UpdateStatResponseBody responseBody = new UpdateStatResponseBody(); int index = 0; responseBody.StatusCode = BitConverter.ToUInt32(rawData, index); index += sizeof(uint); responseBody.ErrorCode = BitConverter.ToUInt32(rawData, index); index += sizeof(uint); responseBody.HasState = BitConverter.ToBoolean(rawData, index); index += sizeof(bool); if (responseBody.HasState) { responseBody.State = STAT.Parse(rawData, ref index); } else { responseBody.State = null; } responseBody.HasDelta = BitConverter.ToBoolean(rawData, index); index += sizeof(bool); if (responseBody.HasDelta) { responseBody.Delta = BitConverter.ToInt32(rawData, index); index += sizeof(int); } else { responseBody.Delta = null; } responseBody.AuxiliaryBufferSize = BitConverter.ToUInt32(rawData, index); index += 4; responseBody.AuxiliaryBuffer = new byte[responseBody.AuxiliaryBufferSize]; Array.Copy(rawData, index, responseBody.AuxiliaryBuffer, 0, responseBody.AuxiliaryBufferSize); return(responseBody); }
public static extern int NspiGetProps(IntPtr contextHandle, uint flags, ref STAT stat, IntPtr ptrPropTags, out IntPtr ptrRows);
public void MSOXNSPI_S03_TC01_ResolveNamesSuccess() { this.CheckProductSupported(); if (this.Transport == "mapi_http") { Site.Assert.Inconclusive("This case cannot run, since MAPIHTTP transport does not support ResolveNames operation for 8-bit character set string."); } #region Call NspiBind to initiate a session between the client and the server. uint flags = 0; STAT stat = new STAT(); stat.InitiateStat(); FlatUID_r guid = new FlatUID_r { Ab = new byte[16] }; FlatUID_r?serverGuid = guid; this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid); Site.Assert.AreEqual <ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiBind should return Success!"); #endregion #region Call NspiResolveNames method with a specific list of names and propertyTag value with null. StringsArray_r strArray; strArray.CValues = 5; strArray.LppszA = new string[strArray.CValues]; strArray.LppszA[0] = Common.GetConfigurationPropertyValue("User1Name", this.Site); strArray.LppszA[1] = string.Empty; strArray.LppszA[2] = Common.GetConfigurationPropertyValue("AmbiguousName", this.Site); strArray.LppszA[3] = null; strArray.LppszA[4] = Constants.UnresolvedName; PropertyTagArray_r?propTags = null; PropertyTagArray_r?mids; PropertyRowSet_r? rowOfResolveNames; this.Result = this.ProtocolAdatper.NspiResolveNames((uint)0, stat, propTags, strArray, out mids, out rowOfResolveNames); #region Capture // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1392"); // Verify MS-OXNSPI requirement: MS-OXNSPI_R1392 Site.CaptureRequirementIfAreEqual <ErrorCodeValue>( ErrorCodeValue.Success, this.Result, 1392, @"[In NspiResolveNames] [Server Processing Rules: Upon receiving message NspiResolveNames, the server MUST process the data from the message subject to the following constraints:] [Constraint 9] If no other return values have been specified by these constraints [constraints 1-8], the server MUST return the return value ""Success""."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1342"); // Verify MS-OXNSPI requirement: MS-OXNSPI_R1342 // If the mids which contains Minimal Entry ID returned from the server is not null, // it illustrates that the server must report the Minimal Entry ID that is the result of the ANR process. this.Site.CaptureRequirementIfIsNotNull( mids, 1342, @"[In NspiResolveNames] The server reports the Minimal Entry ID that is the result of the ANR process."); this.VerifyPropertyRowSetIsNotNullForNspiResolveNames(rowOfResolveNames); this.VerifyIsRESOLVEDMIDInANRMatchString(mids.Value.AulPropTag[0]); this.VerifyIsUNRESOLVEDMIDInANREmptyString(mids.Value.AulPropTag[1]); this.VerifyIsAMBIGUOUSMIDInANRAmbiguousString(mids.Value.AulPropTag[2]); this.VerifyIsUNRESOLVEDMIDInANRNullString(mids.Value.AulPropTag[3]); this.VerifyIsUNRESOLVEDMIDInANRNotFound(mids.Value.AulPropTag[4]); this.VerifyIsResultOfANRProcessIsMID(mids); // Since if the whole ANR results are verified and the NspiResolveNames is invoked, // it must take a set of string values in an 8-bit character set and perform ANR on those strings, // this requirement can be captured directly. this.Site.CaptureRequirement( 1341, @"[In NspiResolveNames] The NspiResolveNames method takes a set of string values in an 8-bit character set and performs ANR (as specified in section 3.1.4.7) on those strings."); // Since all the returned Minimal Entry IDs are verified according to the order of the input string array, this requirement can be captured directly. this.Site.CaptureRequirement( 1375, @"[In NspiResolveNames] [Server Processing Rules: Upon receiving message NspiResolveNames, the server MUST process the data from the message subject to the following constraints:] [Constraint 6] These Minimal Entry IDs [IDs which server constructs and returns to client] are those that result from applying the ANR process, as specified in section 3.1.4.7, to the strings in the input parameter paStr."); #endregion Capture #endregion #region Call NspiResolveNames method with a specific list of names and propertyTag value without null. PropertyTagArray_r propTagsWithProperties = new PropertyTagArray_r { CValues = 3, AulPropTag = new uint[3] { (uint)AulProp.PidTagEntryId, (uint)AulProp.PidTagDisplayName, (uint)AulProp.PidTagObjectType } }; this.Result = this.ProtocolAdatper.NspiResolveNames((uint)0, stat, propTagsWithProperties, strArray, out mids, out rowOfResolveNames); Site.Assert.AreEqual(ErrorCodeValue.Success, this.Result, "NspiResolveNames should return Success!"); PropertyRow_r rowValue = rowOfResolveNames.Value.ARow[0]; string resolvedName = System.Text.UnicodeEncoding.UTF8.GetString(rowValue.LpProps[1].Value.LpszA); #region Capture // Check whether MID_RESOLVED is returned. bool isMIDRESOLVEDContained = false; for (int i = 0; i < mids.Value.CValues; i++) { if (mids.Value.AulPropTag[i] == 0x0000002) { isMIDRESOLVEDContained = true; break; } } // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1343"); // Verify MS-OXNSPI requirement: MS-OXNSPI_R1343 // The rowOfResolveNames which contains a PropertyRowSet_r structure is returned from the server. If it is not null and MID_RESOLVED is returned, // it illustrates that certain property values are returned for any valid Minimal Entry IDs identified by the ANR process. this.Site.CaptureRequirementIfIsTrue( rowOfResolveNames != null && isMIDRESOLVEDContained, 1343, @"[In NspiResolveNames] Certain property values are returned for any valid Minimal Entry IDs identified by the ANR process."); // Add the debug information this.Site.Log.Add( LogEntryKind.Debug, "Verify MS-OXNSPI_R1349, the display name of the resolved address book for paStr {0} is {1}.", Common.GetConfigurationPropertyValue("User1Name", this.Site), resolvedName); // Verify MS-OXNSPI requirement: MS-OXNSPI_R1349 this.Site.CaptureRequirementIfIsTrue( resolvedName.Equals(Common.GetConfigurationPropertyValue("User1Name", this.Site), StringComparison.CurrentCultureIgnoreCase), 1349, "[In NspiResolveNames] [paStr] Specifies the values the client is requesting the server to do ANR on."); Site.Assert.AreEqual <uint>((uint)AulProp.PidTagEntryId, rowOfResolveNames.Value.ARow[0].LpProps[0].PropTag, "The first property returned should be PidTagEntryId. Now the returned property is {0}.", rowOfResolveNames.Value.ARow[0].LpProps[0].PropTag); Site.Assert.AreEqual <uint>((uint)AulProp.PidTagDisplayName, rowOfResolveNames.Value.ARow[0].LpProps[1].PropTag, "The second property returned should be PidTagDisplayName. Now the returned property is {0}.", rowOfResolveNames.Value.ARow[0].LpProps[1].PropTag); Site.Assert.AreEqual <uint>((uint)AulProp.PidTagObjectType, rowOfResolveNames.Value.ARow[0].LpProps[2].PropTag, "The third property returned should be PidTagObjectType. Now the returned property is {0}.", rowOfResolveNames.Value.ARow[0].LpProps[2].PropTag); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1347"); // Verify MS-OXNSPI requirement: MS-OXNSPI_R1347 // Since the null value of pPropTags has been set in step "Call NspiResolveNames method with a specific list of names", // and the above three asserts ensure that it is a reference to a PropertyTagArray_r value containing a list of the proptags of the columns that the client requests to be returned for each row. // So R1347 can be captured directly. this.Site.CaptureRequirement( 1347, @"[In NspiResolveNames] pPropTags: The value NULL or a reference to a PropertyTagArray_r value containing a list of the proptags of the columns that the client requests to be returned for each row returned."); #endregion Capture #endregion #region Call NspiUnbind method to destroy the context handle. uint returnValue = this.ProtocolAdatper.NspiUnbind(0); Site.Assert.AreEqual <uint>(1, returnValue, "NspiUnbind method should return 1 (Success)."); #endregion }
public static extern int NspiGetMatches(IntPtr contextHandle, uint reserved, ref STAT stat, IntPtr ptrReserved, uint reserved2, IntPtr ptrFilter, IntPtr ptrPropName, uint requested, out IntPtr ptrOutMids, IntPtr ptrPropTags, out IntPtr ptrRows);
public static extern int NspiResortRestriction(IntPtr contextHandle, uint reserved, ref STAT stat, IntPtr ptrInmids, ref IntPtr ptrOutMIds);
public static extern int NspiCompareMIds(IntPtr contextHandle, uint reserved, ref STAT stat, uint mid1, uint mid2, out int result);
public static extern int NspiSeekEntries(IntPtr contextHandle, uint reserved, ref STAT stat, IntPtr ptrTarget, IntPtr table, IntPtr ptrPropTags, out IntPtr ptrRows);
public static extern int NspiModProps(IntPtr contextHandle, uint reserved, ref STAT stat, IntPtr ptrPropTags, IntPtr ptrRow);
public void MSOXNSPI_S03_TC02_ResolveNamesWSuccess() { this.CheckProductSupported(); this.CheckMAPIHTTPTransportSupported(); #region Call NspiBind to initiate a session between the client and the server. uint flags = 0; STAT stat = new STAT(); stat.InitiateStat(); FlatUID_r guid = new FlatUID_r { Ab = new byte[16] }; FlatUID_r?serverGuid = guid; this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid); Site.Assert.AreEqual <ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiBind should return Success!"); #endregion #region Call NspiResolveNamesW method with a specific list of names and propertyTag value with null. uint reservedOfResolveNamesW = 0; WStringsArray_r wstrArray; wstrArray.CValues = 5; wstrArray.LppszW = new string[wstrArray.CValues]; wstrArray.LppszW[0] = Common.GetConfigurationPropertyValue("User1Name", this.Site); wstrArray.LppszW[1] = string.Empty; wstrArray.LppszW[2] = Common.GetConfigurationPropertyValue("AmbiguousName", this.Site); wstrArray.LppszW[3] = null; wstrArray.LppszW[4] = Constants.UnresolvedName; PropertyTagArray_r?propTags = null; PropertyTagArray_r?mids; PropertyRowSet_r? rowOfResolveNamesW; this.Result = this.ProtocolAdatper.NspiResolveNamesW(reservedOfResolveNamesW, stat, propTags, wstrArray, out mids, out rowOfResolveNamesW); #region Capture // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1443"); // Verify MS-OXNSPI requirement: MS-OXNSPI_R1443 Site.CaptureRequirementIfAreEqual <ErrorCodeValue>( ErrorCodeValue.Success, this.Result, 1443, @"[In NspiResolveNamesW] [Server Processing Rules: Upon receiving message NspiResolveNamesW, the server MUST process the data from the message subject to the following constraints:] [Constraint 9] If no other return values have been specified by these constraints [constraints 1-8], the server MUST return the return value ""Success""."); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1394"); // Verify MS-OXNSPI requirement: MS-OXNSPI_R1394 // If the mids which contains Minimal Entry ID returned from the server is not null, // it illustrates that the server must report the Minimal Entry ID that is the result of the ANR process. this.Site.CaptureRequirementIfIsNotNull( mids, 1394, @"[In NspiResolveNamesW] The server reports the Minimal Entry IDs that are the result of the ANR process."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1650"); // Verify MS-OXNSPI requirement: MS-OXNSPI_R1650 Site.CaptureRequirementIfIsNotNull( mids, 1650, "[In NspiResolveNamesW] [ppMIds] On return, contains a list of Minimal Entry IDs that match the array of strings, as specified in the input parameter paWStr."); this.VerifyPropertyRowSetIsNotNullForNspiResolveNamesW(rowOfResolveNamesW); this.VerifyIsRESOLVEDMIDInANRMatchString(mids.Value.AulPropTag[0]); this.VerifyIsUNRESOLVEDMIDInANREmptyString(mids.Value.AulPropTag[1]); this.VerifyIsAMBIGUOUSMIDInANRAmbiguousString(mids.Value.AulPropTag[2]); this.VerifyIsUNRESOLVEDMIDInANRNullString(mids.Value.AulPropTag[3]); this.VerifyIsUNRESOLVEDMIDInANRNotFound(mids.Value.AulPropTag[4]); this.VerifyIsResultOfANRProcessIsMID(mids); // Since if the whole ANR results are verified and the NspiResolveNamesW is invoked, // it must take a set of string values in an 8-bit character set and perform ANR on those strings, // this requirement can be captured directly. this.Site.CaptureRequirement( 1393, @"[In NspiResolveNamesW] The NspiResolveNamesW method takes a set of string values in the Unicode character set and performs ANR (as specified in section 3.1.4.7) on those strings."); // Since all the returned Minimal Entry IDs are verified according to the order of the input string array, this requirement can be captured directly. this.Site.CaptureRequirement( 1426, @"[In NspiResolveNamesW] [Server Processing Rules: Upon receiving message NspiResolveNamesW, the server MUST process the data from the message subject to the following constraints:] [Constraint 6] These Minimal Entry IDs are those that result from the ANR process, as specified in section 3.1.4.7, to the strings in the input parameter paWStr."); #endregion Capture #endregion #region Call NspiResolveNamesW method with a specific list of names and propertyTag value without null. PropertyTagArray_r propTagsWithProperties = new PropertyTagArray_r { CValues = 3, AulPropTag = new uint[3] { (uint)AulProp.PidTagEntryId, (uint)AulProp.PidTagDisplayName, (uint)AulProp.PidTagObjectType } }; this.Result = this.ProtocolAdatper.NspiResolveNamesW(reservedOfResolveNamesW, stat, propTagsWithProperties, wstrArray, out mids, out rowOfResolveNamesW); Site.Assert.AreEqual(ErrorCodeValue.Success, this.Result, "NspiResolveNamesW should return Success!"); Site.Assert.AreNotEqual <int>(0, rowOfResolveNamesW.Value.ARow.Length, "At least one address book object should be matched."); #region Capture // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1395"); // Verify MS-OXNSPI requirement: MS-OXNSPI_R1395 // The rowOfResolveNamesW which contains a PropertyRowSet_r structure is returned from the server. If it is not null, // it illustrates that certain property values are returned for any valid Minimal Entry IDs identified by the ANR process. this.Site.CaptureRequirementIfIsNotNull( rowOfResolveNamesW, 1395, @"[In NspiResolveNamesW] Certain property values are returned for any valid Minimal Entry IDs identified by the ANR process."); Site.Assert.AreEqual <uint>((uint)AulProp.PidTagEntryId, rowOfResolveNamesW.Value.ARow[0].LpProps[0].PropTag, "The first property returned should be PidTagEntryId. Now the returned property is {0}.", rowOfResolveNamesW.Value.ARow[0].LpProps[0].PropTag); Site.Assert.AreEqual <uint>((uint)AulProp.PidTagDisplayName, rowOfResolveNamesW.Value.ARow[0].LpProps[1].PropTag, "The second property returned should be PidTagDisplayName. Now the returned property is {0}.", rowOfResolveNamesW.Value.ARow[0].LpProps[1].PropTag); Site.Assert.AreEqual <uint>((uint)AulProp.PidTagObjectType, rowOfResolveNamesW.Value.ARow[0].LpProps[2].PropTag, "The third property returned should be PidTagObjectType. Now the returned property is {0}.", rowOfResolveNamesW.Value.ARow[0].LpProps[2].PropTag); // Add the debug information this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1399"); // Verify MS-OXNSPI requirement: MS-OXNSPI_R1399 // Since the null value of pPropTags has been set in step "Call NspiResolveNamesW method with a specific list of names", // and the above three asserts ensure that it is a reference to a PropertyTagArray_r value containing a list of the proptags of the columns that the client requests to be returned for each row. // So R1347 can be captured directly. this.Site.CaptureRequirement( 1399, @"[In NspiResolveNamesW] pPropTags: The value NULL or a reference to a PropertyTagArray_r containing a list of the proptags of the columns that the client requests to be returned for each row returned."); #endregion Capture #endregion #region Call NspiUnbind method to destroy the context handle. uint returnValue = this.ProtocolAdatper.NspiUnbind(0); Site.Assert.AreEqual <uint>(1, returnValue, "NspiUnbind method should return 1 (Success)."); #endregion }
public static extern int NspiUpdateStat(IntPtr contextHandle, uint reserved, ref STAT stat, IntPtr ptrDelta);
public static extern int NspiGetSpecialTable(IntPtr contextHandle, uint flags, ref STAT stat, ref uint version, out IntPtr ptrRows);
public static extern int NspiBind(IntPtr ptrRpc, uint flags, ref STAT stat, IntPtr ptrServerGuid, ref IntPtr contextHandle);
public void MSOXNSPI_S03_TC04_ResolveNamesWStringConversion() { this.CheckProductSupported(); this.CheckMAPIHTTPTransportSupported(); #region Call NspiBind to initiate a session between the client and the server. uint flags = 0; STAT stat = new STAT(); stat.InitiateStat(); FlatUID_r guid = new FlatUID_r { Ab = new byte[16] }; FlatUID_r?serverGuid = guid; this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid); Site.Assert.AreEqual(ErrorCodeValue.Success, this.Result, "NspiBind should return Success!"); #endregion #region Call NspiResolveNamesW to require the string properties to be different with their native type. uint reservedOfResolveNamesW = 0; WStringsArray_r wstrArray; wstrArray.CValues = 1; wstrArray.LppszW = new string[wstrArray.CValues]; wstrArray.LppszW[0] = Common.GetConfigurationPropertyValue("User2Name", this.Site); PropertyTagArray_r propTags = new PropertyTagArray_r { CValues = 2, AulPropTag = new uint[] { AdapterHelper.ConvertStringToString8((uint)AulProp.PidTagAddressBookDisplayNamePrintable), AdapterHelper.ConvertString8ToString((uint)AulProp.PidTagDisplayName) } }; PropertyTagArray_r?mids; PropertyRowSet_r? rowOfResolveNamesW; this.Result = this.ProtocolAdatper.NspiResolveNamesW(reservedOfResolveNamesW, stat, propTags, wstrArray, out mids, out rowOfResolveNamesW); Site.Assert.AreEqual(ErrorCodeValue.Success, this.Result, "NspiResolveNamesW should return Success!"); Site.Assert.IsNotNull(rowOfResolveNamesW, "PropertyRowSet_r value should not null. The row number is {0}.", rowOfResolveNamesW == null ? 0 : rowOfResolveNamesW.Value.CRows); Site.Assert.AreNotEqual <int>(0, rowOfResolveNamesW.Value.ARow.Length, "At least one address book object should be matched."); PropertyRow_r rowValue = rowOfResolveNamesW.Value.ARow[0]; string resolvedDisplayNamePrintable = System.Text.UnicodeEncoding.UTF8.GetString(rowValue.LpProps[0].Value.LpszA); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1979: The value of PidTagAddressBookDisplayNamePrintable is {0}.", resolvedDisplayNamePrintable); // Verify MS-OXNSPI requirement: MS-OXNSPI_R1979 // The field LpszA indicates an 8-bit character string value. Site.CaptureRequirementIfIsTrue( resolvedDisplayNamePrintable.StartsWith(wstrArray.LppszW[0], StringComparison.Ordinal), 1979, "[In Conversion Rules for String Values Specified by the Server to the Client] In NspiResolveNamesW method, String values can be returned in 8-bit character representation in the output parameter ppRows."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1978"); string reslovedName = System.Text.UnicodeEncoding.Unicode.GetString(rowValue.LpProps[1].Value.LpszW); // Verify MS-OXNSPI requirement: MS-OXNSPI_R1978 // The field LpszW indicates a single Unicode string value. Site.CaptureRequirementIfAreEqual <string>( wstrArray.LppszW[0].ToLower(System.Globalization.CultureInfo.CurrentCulture), reslovedName.ToLower(System.Globalization.CultureInfo.CurrentCulture), 1978, "[In Conversion Rules for String Values Specified by the Server to the Client] In NspiResolveNamesW method, String values can be returned in Unicode representation in the output parameter ppRows."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1939"); // Verify MS-OXNSPI requirement: MS-OXNSPI_R1939 // The native type of PidTagAddressBookDisplayNamePrintable is PtypString and the client has requested this property with PtypString8. Site.CaptureRequirementIfAreEqual <uint>( AdapterHelper.ConvertStringToString8((uint)AulProp.PidTagAddressBookDisplayNamePrintable), rowValue.LpProps[0].PropTag, 1939, "[In Conversion Rules for String Values Specified by the Server to the Client] [For method NspiResolveNamesW] If the native type of a property is PtypString and the client has requested that property with the type PtypString8, the server MUST convert the Unicode representation to an 8-bit character representation in the code page specified by the CodePage field of the pStat parameter prior to returning the value."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1955"); // Verify MS-OXNSPI requirement: MS-OXNSPI_R1955 // The native type of PidTagDisplayName is PtypString8 and the client has requested this property with PtypString. Site.CaptureRequirementIfAreEqual <uint>( AdapterHelper.ConvertString8ToString((uint)AulProp.PidTagDisplayName), rowValue.LpProps[1].PropTag, 1955, "[In Conversion Rules for String Values Specified by the Server to the Client] [For method NspiResolveNamesW] If the native type of a property is PtypString8 and the client has requested that property with the type PtypString, the server MUST convert the 8-bit character representation to a Unicode representation prior to returning the value."); #endregion #region Call NspiResolveNamesW to require the string properties to be the same as their native types. wstrArray.CValues = 1; wstrArray.LppszW = new string[wstrArray.CValues]; wstrArray.LppszW[0] = Common.GetConfigurationPropertyValue("User2Name", this.Site); propTags = new PropertyTagArray_r { CValues = 2, AulPropTag = new uint[] { (uint)AulProp.PidTagAddressBookDisplayNamePrintable, (uint)AulProp.PidTagDisplayName } }; this.Result = this.ProtocolAdatper.NspiResolveNamesW(reservedOfResolveNamesW, stat, propTags, wstrArray, out mids, out rowOfResolveNamesW); Site.Assert.AreEqual(ErrorCodeValue.Success, this.Result, "NspiResolveNamesW should return Success!"); Site.Assert.IsNotNull(rowOfResolveNamesW, "PropertyRowSet_r value should not null. The row number is {0}.", rowOfResolveNamesW == null ? 0 : rowOfResolveNamesW.Value.CRows); Site.Assert.AreNotEqual <int>(0, rowOfResolveNamesW.Value.ARow.Length, "At least one address book object should be matched."); rowValue = rowOfResolveNamesW.Value.ARow[0]; // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1946"); // Verify MS-OXNSPI requirement: MS-OXNSPI_R1947 // The native type of PidTagAddressBookDisplayNamePrintable is PtypString and the client has requested this property with PtypString. Site.CaptureRequirementIfAreEqual <uint>( (uint)AulProp.PidTagAddressBookDisplayNamePrintable, rowValue.LpProps[0].PropTag, 1947, "[In Conversion Rules for String Values Specified by the Server to the Client] [For method NspiResolveNamesW] If the native type of a property is PtypString and the client has requested that property with the type PtypString, the server MUST return the Unicode representation unmodified."); // Add the debug information Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1963"); // Verify MS-OXNSPI requirement: MS-OXNSPI_R1963 // The native type of PidTagDisplayName is PtypString8 and the client has requested this property with PtypString8. Site.CaptureRequirementIfAreEqual <uint>( (uint)AulProp.PidTagDisplayName, rowValue.LpProps[1].PropTag, 1963, "[In Conversion Rules for String Values Specified by the Server to the Client] [For method NspiResolveNamesW] If the native type of a property is PtypString8 and the client has requested that property with the type PtypString8, the server MUST return the 8-bit character representation unmodified."); #endregion #region Call NspiUnbind method to destroy the context handle. uint returnValue = this.ProtocolAdatper.NspiUnbind(0); Site.Assert.AreEqual <uint>(1, returnValue, "NspiUnbind method should return 1 (Success)."); #endregion }
public static extern int NspiQueryRows(IntPtr contextHandle, uint flags, ref STAT stat, uint tableCount, [Size("dwETableCount")] uint[] table, uint count, IntPtr ptrPropTags, out IntPtr ptrRows);