Example #1
0
        /// <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 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 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>
        /// <returns>Status of NSPI method.</returns>
        public ErrorCodeValue Bind(uint flags, STAT stat, ref FlatUID_r? serverGuid)
        {
            ErrorCodeValue result;
            BindRequestBody bindRequestBody = this.BuildBindRequestBody(stat, flags);
            byte[] rawBuffer = null;
            ChunkedResponse chunkedResponse = null;
            BindResponseBody bindResponseBody = null;

            // Send the execute HTTP request and get the response
            HttpWebResponse response = MapiHttpAdapter.SendMAPIHttpRequest(this.site, this.addressBookUrl, this.userName, this.domainName, this.password, bindRequestBody, RequestType.Bind.ToString(), AdapterHelper.SessionContextCookies);

            // Read the HTTP response buffer and parse the response to correct format
            rawBuffer = MapiHttpAdapter.ReadHttpResponse(response);
            result = (ErrorCodeValue)int.Parse(response.Headers["X-ResponseCode"]);
            if (result == ErrorCodeValue.Success)
            {
                chunkedResponse = ChunkedResponse.ParseChunkedResponse(rawBuffer);
                bindResponseBody = BindResponseBody.Parse(chunkedResponse.ResponseBodyRawData);
                result = (ErrorCodeValue)bindResponseBody.ErrorCode;
                if (bindResponseBody.ServerGuid != null)
                {
                    FlatUID_r newGuid = new FlatUID_r();
                    newGuid.Ab = bindResponseBody.ServerGuid.ToByteArray();
                    serverGuid = newGuid;
                }
                else
                {
                    serverGuid = null;
                }
            }

            response.GetResponseStream().Close();
            AdapterHelper.SessionContextCookies = response.Cookies;
            return result;
        }
Example #3
0
        /// <summary>
        /// Initialize Bind request body.
        /// </summary>
        /// <param name="stat">A STAT block that describes a logical position in a specific address book container.</param>
        /// <param name="flags">A set of bit flags that specify options to the server.</param>
        /// <returns>An instance of the Bind request body.</returns>
        private BindRequestBody BuildBindRequestBody(STAT stat, uint flags)
        {
            BindRequestBody bindRequestBody = new BindRequestBody();

            bindRequestBody.State    = stat;
            bindRequestBody.Flags    = flags;
            bindRequestBody.HasState = true;
            byte[] auxIn = new byte[] { };
            bindRequestBody.AuxiliaryBuffer     = auxIn;
            bindRequestBody.AuxiliaryBufferSize = (uint)auxIn.Length;

            return(bindRequestBody);
        }
Example #4
0
        /// <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>
        /// <returns>Status of NSPI method.</returns>
        public ErrorCodeValue QueryRows(uint flags, ref STAT stat, uint tableCount, uint[] table, uint count, PropertyTagArray_r?propTags, out PropertyRowSet_r?rows)
        {
            ErrorCodeValue       result;
            QueryRowsRequestBody queryRowsRequestBody = new QueryRowsRequestBody();
            LargePropTagArray    propetyTags          = new LargePropTagArray();

            if (propTags != null)
            {
                propetyTags.PropertyTagCount = propTags.Value.Values;
                propetyTags.PropertyTags     = new PropertyTag[propetyTags.PropertyTagCount];
                for (int i = 0; i < propTags.Value.Values; i++)
                {
                    propetyTags.PropertyTags[i].PropertyId   = (ushort)((propTags.Value.AulPropTag[i] & 0xFFFF0000) >> 16);
                    propetyTags.PropertyTags[i].PropertyType = (ushort)(propTags.Value.AulPropTag[i] & 0x0000FFFF);
                }

                queryRowsRequestBody.HasColumns = true;
                queryRowsRequestBody.Columns    = propetyTags;
            }

            queryRowsRequestBody.Flags              = flags;
            queryRowsRequestBody.HasState           = true;
            queryRowsRequestBody.State              = stat;
            queryRowsRequestBody.ExplicitTableCount = tableCount;
            queryRowsRequestBody.ExplicitTable      = table;
            queryRowsRequestBody.RowCount           = count;
            byte[] auxIn = new byte[] { };
            queryRowsRequestBody.AuxiliaryBuffer     = auxIn;
            queryRowsRequestBody.AuxiliaryBufferSize = (uint)auxIn.Length;

            ChunkedResponse       chunkedResponse       = this.SendAddressBookRequest(queryRowsRequestBody, RequestType.QueryRows);
            QueryRowsResponseBody queryRowsResponseBody = QueryRowsResponseBody.Parse(chunkedResponse.ResponseBodyRawData);

            result = (ErrorCodeValue)queryRowsResponseBody.ErrorCode;
            if (queryRowsResponseBody.RowCount != null)
            {
                PropertyRowSet_r newRows = AdapterHelper.ParsePropertyRowSet_r(queryRowsResponseBody.Columns.Value, queryRowsResponseBody.RowCount.Value, queryRowsResponseBody.RowData);
                rows = newRows;
            }
            else
            {
                rows = null;
            }

            if (queryRowsResponseBody.HasState)
            {
                stat = queryRowsResponseBody.State.Value;
            }

            return(result);
        }
Example #5
0
        /// <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)
        {
            ErrorCodeValue result;

            if (this.transport == "ncacn_http" || this.transport == "ncacn_ip_tcp")
            {
                result = this.nspiRpcAdapter.NspiBind(flags, stat, ref serverGuid);
            }
            else
            {
                result = this.nspiMapiHttpAdapter.Bind(flags, stat, ref serverGuid);
            }

            return(result);
        }
Example #6
0
        /// <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);
            }

            return(result);
        }
Example #7
0
        /// <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 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>
        /// <returns>Status of NSPI method.</returns>
        public ErrorCodeValue Bind(uint flags, STAT stat, ref FlatUID_r?serverGuid)
        {
            ErrorCodeValue  result;
            BindRequestBody bindRequestBody = this.BuildBindRequestBody(stat, flags);

            byte[]           rawBuffer        = null;
            ChunkedResponse  chunkedResponse  = null;
            BindResponseBody bindResponseBody = null;

            // Send the execute HTTP request and get the response
            HttpWebResponse response = MapiHttpAdapter.SendMAPIHttpRequest(this.site, this.addressBookUrl, this.userName, this.domainName, this.password, bindRequestBody, RequestType.Bind.ToString(), AdapterHelper.SessionContextCookies);

            // Read the HTTP response buffer and parse the response to correct format
            rawBuffer = MapiHttpAdapter.ReadHttpResponse(response);
            result    = (ErrorCodeValue)int.Parse(response.Headers["X-ResponseCode"]);
            if (result == ErrorCodeValue.Success)
            {
                chunkedResponse  = ChunkedResponse.ParseChunkedResponse(rawBuffer);
                bindResponseBody = BindResponseBody.Parse(chunkedResponse.ResponseBodyRawData);
                result           = (ErrorCodeValue)bindResponseBody.ErrorCode;
                if (bindResponseBody.ServerGuid != null)
                {
                    FlatUID_r newGuid = new FlatUID_r();
                    newGuid.Ab = bindResponseBody.ServerGuid.ToByteArray();
                    serverGuid = newGuid;
                }
                else
                {
                    serverGuid = null;
                }
            }

            response.GetResponseStream().Close();
            AdapterHelper.SessionContextCookies = response.Cookies;
            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 QueryRowsResponseBody Parse(byte[] rawData)
        {
            QueryRowsResponseBody responseBody = new QueryRowsResponseBody();
            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);
            }

            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);
                index += sizeof(uint);
                responseBody.RowData = new AddressBookPropertyRow[(uint)responseBody.RowCount];
                for (int i = 0; i < responseBody.RowCount; i++)
                {
                    responseBody.RowData[i] = AddressBookPropertyRow.Parse(rawData, (LargePropTagArray)responseBody.Columns, ref index);
                }
            }

            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 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);
        /// <summary>
        /// Get properties from NSPI table.
        /// </summary>
        /// <param name="server">Server address.</param>
        /// <param name="userName">The value of user name.</param>
        /// <param name="domain">The value of Domain.</param>
        /// <param name="password">Password of the user.</param>
        /// <param name="columns">PropertyTags to be query.</param>
        /// <returns>Results in PropertyRowSet format.</returns>
        public PropertyRowSet_r? GetRecipientInfo(string server, string userName, string domain, string password, PropertyTagArray_r? columns)
        {
            #region Call NspiBind method to initiate a session between the client and the server.
            uint flags = 0;
            STAT stat = new STAT();
            stat.CodePage = 0x4e4; // Set a valid code page.
            stat.TemplateLocale = 0x409; // Set a valid LCID.
            stat.SortLocale = 0x409; // Set a valid LCID.
                                     // Set value for serverGuid
            FlatUID_r guid = new FlatUID_r
            {
                Ab = new byte[16]
            };
            FlatUID_r? serverGuid = guid;


            ErrorCodeValue result = this.nspiAdapter.NspiBind(flags, stat, ref serverGuid);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, result, "NspiBind should return Success!");
            #endregion

            #region Call NspiQueryRows method to get the recipient information.
            stat.ContainerID = 0; // Set the container id to the id of default global address book container
            uint tableCount = 0;
            uint[] table = null;
            uint requestCount = 5000;
            PropertyRowSet_r? propertyRowSet = null;

            result = this.nspiAdapter.NspiQueryRows(flags, ref stat, tableCount, table, requestCount, columns, out propertyRowSet);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, result, "NspiQueryRows should return Success!");
            #endregion

            uint returnValue = this.nspiAdapter.NspiUnbind(0);
            Site.Assert.AreEqual<uint>(1, returnValue, "NspiUnbind method should return 1 (Success).");
            return propertyRowSet;
        }
        /// <summary>
        /// Initialize Bind request body.
        /// </summary>
        /// <param name="stat">A STAT block that describes a logical position in a specific address book container.</param>
        /// <param name="flags">A set of bit flags that specify options to the server.</param>
        /// <returns>An instance of the Bind request body.</returns>
        private BindRequestBody BuildBindRequestBody(STAT stat, uint flags)
        {
            BindRequestBody bindRequestBody = new BindRequestBody();
            bindRequestBody.State = stat;
            bindRequestBody.Flags = flags;
            bindRequestBody.HasState = true;
            byte[] auxIn = new byte[] { };
            bindRequestBody.AuxiliaryBuffer = auxIn;
            bindRequestBody.AuxiliaryBufferSize = (uint)auxIn.Length;

            return bindRequestBody;
        }
 public static extern int NspiUpdateStat(IntPtr contextHandle, uint reserved, ref STAT stat, IntPtr ptrDelta);
 public static extern int NspiBind(IntPtr ptrRpc, uint flags, ref STAT stat, IntPtr ptrServerGuid, ref IntPtr contextHandle);
        /// <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 bool 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)
        {
            int result;
            IntPtr ptrRows = IntPtr.Zero;
            IntPtr ptrPropTags = IntPtr.Zero;
            IntPtr ptrStat = AdapterHelper.AllocStat(stat);
            if (propTags != null)
            {
                ptrPropTags = AdapterHelper.AllocPropertyTagArray_r(propTags.Value);
            }

            int retryCount = 0;
            do
            {
                try
                {
                    result = OxnspiInterop.NspiQueryRows(this.contextHandle, flags, ref stat, tableCount, table, count, ptrPropTags, out ptrRows);
                }
                catch (SEHException e)
                {
                    result = (int)NativeMethods.RpcExceptionCode(e);
                    this.site.Log.Add(LogEntryKind.Comment, "RPC component throws exception, the error code is {0}, the error message is: {1}", result, new Win32Exception(result).ToString());
                }

                if ((ErrorCodeValue)result == ErrorCodeValue.GeneralFailure && needRetry)
                {
                    Thread.Sleep(this.waitTime);
                }
                else
                {
                    break;
                }

                retryCount++;
            }
            while ((ErrorCodeValue)result == ErrorCodeValue.GeneralFailure && retryCount < this.maxRetryCount);

            if (!Enum.IsDefined(typeof(ErrorCodeValue), (uint)result))
            {
                throw new ArgumentException(string.Format("An unknown error is returned, the error code is: {0} and the error message is: {1}", result, new Win32Exception(result).ToString()));
            }

            if (propTags != null)
            {
                Marshal.FreeHGlobal(ptrPropTags);
            }

            // Parse rows according to ptrRows.
            if (ptrRows == IntPtr.Zero)
            {
                rows = null;
            }
            else
            {
                rows = AdapterHelper.ParsePropertyRowSet_r(ptrRows);
            }

            // Free stat.
            Marshal.FreeHGlobal(ptrStat);
            return (ErrorCodeValue)result;
        }
 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 NspiQueryRows(IntPtr contextHandle, uint flags, ref STAT stat, uint tableCount, [Size("dwETableCount")] uint[] table, uint count, IntPtr ptrPropTags, out IntPtr ptrRows);
Example #18
0
        /// <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)
        {
            int result;

            IntPtr ptrServerGuid = IntPtr.Zero;
            IntPtr ptrStat       = AdapterHelper.AllocStat(stat);

            if (serverGuid.HasValue && serverGuid.Value.Ab != null)
            {
                ptrServerGuid = AdapterHelper.AllocFlatUID_r(serverGuid.Value);
            }

            int retryCount = 0;

            do
            {
                try
                {
                    result = OxnspiInterop.NspiBind(this.rpcBinding, flags, ref stat, ptrServerGuid, ref this.contextHandle);
                }
                catch (SEHException e)
                {
                    result = (int)NativeMethods.RpcExceptionCode(e);
                    this.site.Log.Add(LogEntryKind.Comment, "RPC component throws exception, the error code is {0}, the error message is: {1}", result, new Win32Exception(result).ToString());
                }

                if ((ErrorCodeValue)result == ErrorCodeValue.GeneralFailure && needRetry)
                {
                    Thread.Sleep(this.waitTime);
                }
                else
                {
                    break;
                }

                retryCount++;
            }while ((ErrorCodeValue)result == ErrorCodeValue.GeneralFailure && retryCount < this.maxRetryCount);

            if (!Enum.IsDefined(typeof(ErrorCodeValue), (uint)result))
            {
                throw new ArgumentException(string.Format("An unknown error is returned, the error code is: {0} and the error message is: {1}", result, new Win32Exception(result).ToString()));
            }

            // Parse ServerGuid from ptrServerGuid.
            if (ptrServerGuid == IntPtr.Zero)
            {
                serverGuid = null;
            }
            else
            {
                serverGuid = AdapterHelper.ParseFlatUID_r(ptrServerGuid);
            }

            // Free allocated memory for serverGuid.
            if (serverGuid.HasValue)
            {
                if (serverGuid.Value.Ab != null)
                {
                    Marshal.FreeHGlobal(ptrServerGuid);
                }
            }

            // Free allocated memory for stat.
            Marshal.FreeHGlobal(ptrStat);
            return((ErrorCodeValue)result);
        }
        /// <summary>
        /// Parse a STAT structure instance from pointer.
        /// </summary>
        /// <param name="ptr">Pointer points to the memory.</param>
        /// <returns>A STAT structure.</returns>
        public static STAT ParseStat(IntPtr ptr)
        {
            STAT stat = new STAT();
            int offset = 0;

            stat.SortType = (uint)Marshal.ReadInt32(ptr, offset);
            offset += sizeof(int);

            stat.ContainerID = (uint)Marshal.ReadInt32(ptr, offset);
            offset += sizeof(int);

            stat.CurrentRec = (uint)Marshal.ReadInt32(ptr, offset);
            offset += sizeof(int);

            stat.Delta = Marshal.ReadInt32(ptr, offset);
            offset += sizeof(int);

            stat.NumPos = (uint)Marshal.ReadInt32(ptr, offset);
            offset += sizeof(int);

            stat.TotalRecs = (uint)Marshal.ReadInt32(ptr, offset);
            offset += sizeof(int);

            stat.CodePage = (uint)Marshal.ReadInt32(ptr, offset);
            offset += sizeof(int);

            stat.TemplateLocale = (uint)Marshal.ReadInt32(ptr, offset);
            offset += sizeof(int);

            stat.SortLocale = (uint)Marshal.ReadInt32(ptr, offset);

            return stat;
        }
        /// <summary>
        /// Allocate memory for stat instance.
        /// </summary>
        /// <param name="stat">The stat instance.</param>
        /// <returns>The pointer points to the allocated memory.</returns>
        public static IntPtr AllocStat(STAT stat)
        {
            IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(stat));
            int offset = 0;
            Marshal.WriteInt32(ptr, offset, (int)stat.SortType);
            offset += sizeof(int);
            Marshal.WriteInt32(ptr, offset, (int)stat.ContainerID);
            offset += sizeof(int);
            Marshal.WriteInt32(ptr, offset, (int)stat.CurrentRec);
            offset += sizeof(int);
            Marshal.WriteInt32(ptr, offset, stat.Delta);
            offset += sizeof(int);
            Marshal.WriteInt32(ptr, offset, (int)stat.NumPos);
            offset += sizeof(int);
            Marshal.WriteInt32(ptr, offset, (int)stat.TotalRecs);
            offset += sizeof(int);
            Marshal.WriteInt32(ptr, offset, (int)stat.CodePage);
            offset += sizeof(int);
            Marshal.WriteInt32(ptr, offset, (int)stat.TemplateLocale);
            offset += sizeof(int);
            Marshal.WriteInt32(ptr, offset, (int)stat.SortLocale);

            return ptr;
        }
        /// <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)
        {
            int result;

            IntPtr ptrServerGuid = IntPtr.Zero;
            IntPtr ptrStat = AdapterHelper.AllocStat(stat);

            if (serverGuid.HasValue && serverGuid.Value.Ab != null)
            {
                ptrServerGuid = AdapterHelper.AllocFlatUID_r(serverGuid.Value);
            }

            int retryCount = 0;
            do
            {
                try
                {
                    result = OxnspiInterop.NspiBind(this.rpcBinding, flags, ref stat, ptrServerGuid, ref this.contextHandle);
                }
                catch (SEHException e)
                {
                    result = (int)NativeMethods.RpcExceptionCode(e);
                    this.site.Log.Add(LogEntryKind.Comment, "RPC component throws exception, the error code is {0}, the error message is: {1}", result, new Win32Exception(result).ToString());
                }

                if ((ErrorCodeValue)result == ErrorCodeValue.GeneralFailure && needRetry)
                {
                    Thread.Sleep(this.waitTime);
                }
                else
                {
                    break;
                }

                retryCount++;
            }
            while ((ErrorCodeValue)result == ErrorCodeValue.GeneralFailure && retryCount < this.maxRetryCount);

            if (!Enum.IsDefined(typeof(ErrorCodeValue), (uint)result))
            {
                throw new ArgumentException(string.Format("An unknown error is returned, the error code is: {0} and the error message is: {1}", result, new Win32Exception(result).ToString()));
            }

            // Parse ServerGuid from ptrServerGuid.
            if (ptrServerGuid == IntPtr.Zero)
            {
                serverGuid = null;
            }
            else
            {
                serverGuid = AdapterHelper.ParseFlatUID_r(ptrServerGuid);
            }

            // Free allocated memory for serverGuid.
            if (serverGuid.HasValue)
            {
                if (serverGuid.Value.Ab != null)
                {
                    Marshal.FreeHGlobal(ptrServerGuid);
                }
            }

            // Free allocated memory for stat.
            Marshal.FreeHGlobal(ptrStat);
            return (ErrorCodeValue)result;
        }
Example #22
0
        /// <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 bool 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)
        {
            int    result;
            IntPtr ptrRows     = IntPtr.Zero;
            IntPtr ptrPropTags = IntPtr.Zero;
            IntPtr ptrStat     = AdapterHelper.AllocStat(stat);

            if (propTags != null)
            {
                ptrPropTags = AdapterHelper.AllocPropertyTagArray_r(propTags.Value);
            }

            int retryCount = 0;

            do
            {
                try
                {
                    result = OxnspiInterop.NspiQueryRows(this.contextHandle, flags, ref stat, tableCount, table, count, ptrPropTags, out ptrRows);
                }
                catch (SEHException e)
                {
                    result = (int)NativeMethods.RpcExceptionCode(e);
                    this.site.Log.Add(LogEntryKind.Comment, "RPC component throws exception, the error code is {0}, the error message is: {1}", result, new Win32Exception(result).ToString());
                }

                if ((ErrorCodeValue)result == ErrorCodeValue.GeneralFailure && needRetry)
                {
                    Thread.Sleep(this.waitTime);
                }
                else
                {
                    break;
                }

                retryCount++;
            }while ((ErrorCodeValue)result == ErrorCodeValue.GeneralFailure && retryCount < this.maxRetryCount);

            if (!Enum.IsDefined(typeof(ErrorCodeValue), (uint)result))
            {
                throw new ArgumentException(string.Format("An unknown error is returned, the error code is: {0} and the error message is: {1}", result, new Win32Exception(result).ToString()));
            }

            if (propTags != null)
            {
                Marshal.FreeHGlobal(ptrPropTags);
            }

            // Parse rows according to ptrRows.
            if (ptrRows == IntPtr.Zero)
            {
                rows = null;
            }
            else
            {
                rows = AdapterHelper.ParsePropertyRowSet_r(ptrRows);
            }

            // Free stat.
            Marshal.FreeHGlobal(ptrStat);
            return((ErrorCodeValue)result);
        }
 public static extern int NspiGetProps(IntPtr contextHandle, uint flags, ref STAT stat, IntPtr ptrPropTags, out IntPtr ptrRows);
 public static extern int NspiCompareMIds(IntPtr contextHandle, uint reserved, ref STAT stat, uint mid1, uint mid2, out int result);
 public static extern int NspiGetProps(IntPtr contextHandle, uint flags, ref STAT stat, IntPtr ptrPropTags, out IntPtr ptrRows);
 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);
 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 NspiSeekEntries(IntPtr contextHandle, uint reserved, ref STAT stat, IntPtr ptrTarget, IntPtr table, 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 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 NspiModProps(IntPtr contextHandle, uint reserved, ref STAT stat, IntPtr ptrPropTags, IntPtr ptrRow);
 public static extern int NspiResortRestriction(IntPtr contextHandle, uint reserved, ref STAT stat, IntPtr ptrInmids, ref IntPtr ptrOutMIds);
 public static extern int NspiGetSpecialTable(IntPtr contextHandle, uint flags, ref STAT stat, ref uint version, out IntPtr ptrRows);
 public static extern int NspiCompareMIds(IntPtr contextHandle, uint reserved, ref STAT stat, uint mid1, uint mid2, out int 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>
        /// <returns>Status of NSPI method.</returns>
        public ErrorCodeValue QueryRows(uint flags, ref STAT stat, uint tableCount, uint[] table, uint count, PropertyTagArray_r? propTags, out PropertyRowSet_r? rows)
        {
            ErrorCodeValue result;
            QueryRowsRequestBody queryRowsRequestBody = new QueryRowsRequestBody();
            LargePropTagArray propetyTags = new LargePropTagArray();
            if (propTags != null)
            {
                propetyTags.PropertyTagCount = propTags.Value.Values;
                propetyTags.PropertyTags = new PropertyTag[propetyTags.PropertyTagCount];
                for (int i = 0; i < propTags.Value.Values; i++)
                {
                    propetyTags.PropertyTags[i].PropertyId = (ushort)((propTags.Value.AulPropTag[i] & 0xFFFF0000) >> 16);
                    propetyTags.PropertyTags[i].PropertyType = (ushort)(propTags.Value.AulPropTag[i] & 0x0000FFFF);
                }

                queryRowsRequestBody.HasColumns = true;
                queryRowsRequestBody.Columns = propetyTags;
            }

            queryRowsRequestBody.Flags = flags;
            queryRowsRequestBody.HasState = true;
            queryRowsRequestBody.State = stat;
            queryRowsRequestBody.ExplicitTableCount = tableCount;
            queryRowsRequestBody.ExplicitTable = table;
            queryRowsRequestBody.RowCount = count;
            byte[] auxIn = new byte[] { };
            queryRowsRequestBody.AuxiliaryBuffer = auxIn;
            queryRowsRequestBody.AuxiliaryBufferSize = (uint)auxIn.Length;

            ChunkedResponse chunkedResponse = this.SendAddressBookRequest(queryRowsRequestBody, RequestType.QueryRows);
            QueryRowsResponseBody queryRowsResponseBody = QueryRowsResponseBody.Parse(chunkedResponse.ResponseBodyRawData);
            result = (ErrorCodeValue)queryRowsResponseBody.ErrorCode;
            if (queryRowsResponseBody.RowCount != null)
            {
                PropertyRowSet_r newRows = AdapterHelper.ParsePropertyRowSet_r(queryRowsResponseBody.Columns.Value, queryRowsResponseBody.RowCount.Value, queryRowsResponseBody.RowData);
                rows = newRows;
            }
            else
            {
                rows = null;
            }

            if (queryRowsResponseBody.HasState)
            {
                stat = queryRowsResponseBody.State.Value;
            }

            return result;
        }
 public static extern int NspiModProps(IntPtr contextHandle, uint reserved, ref STAT stat, IntPtr ptrPropTags, IntPtr ptrRow);
 public static extern int NspiBind(IntPtr ptrRpc, uint flags, ref STAT stat, IntPtr ptrServerGuid, ref IntPtr contextHandle);
        /// <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;
        }