/// <summary> /// Initialize the client and server and build the transport tunnel between client and server. /// </summary> private void InitializeRPC() { string serverName = Common.GetConfigurationPropertyValue("SutComputerName", this.site); string userName = Common.GetConfigurationPropertyValue("AdminUserName", this.site); string domainName = Common.GetConfigurationPropertyValue("Domain", this.site); string password = Common.GetConfigurationPropertyValue("AdminUserPassword", this.site); // Create identity for the user to connect to the server. OxnspiInterop.CreateIdentity( domainName, userName, password); MapiContext rpcContext = MapiContext.GetDefaultRpcContext(this.site); // Create Service Principal Name (SPN) string for the user to connect to the server. string userSpn = string.Empty; userSpn = Regex.Replace(rpcContext.SpnFormat, @"\[ServerName\]", serverName, RegexOptions.IgnoreCase); // Bind the client to RPC server. uint status = OxnspiInterop.BindToServer(serverName, rpcContext.AuthenLevel, rpcContext.AuthenService, rpcContext.TransportSequence, rpcContext.RpchUseSsl, rpcContext.RpchAuthScheme, userSpn, null, rpcContext.SetUuid); this.site.Assert.AreEqual <uint>(0, status, "Create binding handle with server {0} should success!", serverName); this.rpcBinding = OxnspiInterop.GetBindHandle(); this.site.Assert.AreNotEqual <IntPtr>(IntPtr.Zero, this.rpcBinding, "A valid RPC Binding handle is needed!"); }
/// <summary> /// The NspiUnbind method destroys the context handle. No other action is taken. /// </summary> /// <param name="reserved">A DWORD [MS-DTYP] value reserved for future use. This property is ignored by the server.</param> /// <param name="contextHandle">The RPC context handle.</param> /// <returns>A DWORD value that specifies the return status of the method.</returns> public uint NspiUnbind(uint reserved, ref IntPtr contextHandle) { uint result; try { result = OxnspiInterop.NspiUnbind(ref this.contextHandle, reserved); contextHandle = this.contextHandle; } catch (SEHException e) { result = 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((int)result).ToString()); } this.site.Assert.AreEqual <uint>((uint)1, result, "NspiUnbind method should return 1 (Success)."); 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) { 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> /// 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); }