public extern static RPC_STATUS RpcAsyncInitializeHandle( /* PRPC_ASYNC_STATE pAsync*/ ref RPC_ASYNC_STATE pAsync, /* unsigned int Size*/ ushort Size );
public static IntPtr RpcAsyncGetCallHandle(IntPtr pAsyncStat) { RPC_ASYNC_STATE asyncState = (RPC_ASYNC_STATE)Marshal.PtrToStructure(pAsyncStat, typeof(RPC_ASYNC_STATE)); return(asyncState.RuntimeInfo); }
private static void InvokeRpcAsync(RpcHandle handle, Guid iid, byte[] input, APICallback callback) { Log.Verbose("InvokeRpcAsync on {0}, sending {1} bytes", handle.Handle, input.Length); Ptr <MIDL_STUB_DESC> pStub; if (!handle.GetPtr(out pStub)) { pStub = handle.CreatePtr(new MIDL_STUB_DESC( handle, handle.Pin(new RPC_CLIENT_INTERFACE(iid)), RpcApi.TYPE_FORMAT, false)); } int cbOutput = 0; var pcbOutput = new Ptr <int>(cbOutput); IntPtr result = IntPtr.Zero; IntPtr output = IntPtr.Zero; var pOutput = new Ptr <IntPtr>(output); using (Ptr <byte[]> pInputBuffer = new Ptr <byte[]>(input)) { AsyncCallback cbRountine = (IntPtr pAsync, IntPtr pContext, RpcAsyncEvent _event) => { RPC_ASYNC_STATE async = (RPC_ASYNC_STATE)Marshal.PtrToStructure(pAsync, typeof(RPC_ASYNC_STATE)); var myCallback = (APICallback)Marshal.GetDelegateForFunctionPointer(async.UserInfo, typeof(APICallback)); RpcError hr = RpcApi.RpcAsyncCompleteCall(pAsync, ref result); if (RpcError.RPC_S_OK == hr) { if (RpcError.RPC_S_OK == (RpcError)result.ToInt32()) { ExecuteAsyncResponse response; try { cbOutput = pcbOutput.Data; byte[] _output = new byte[cbOutput]; Marshal.Copy(pOutput.Data, _output, 0, cbOutput); response.result = RpcError.RPC_S_OK; response.response = _output; } catch (Exception e) { response.result = RpcError.RPC_E_FAIL; response.response = null; } finally { RpcApi.Free(pOutput.Data); } myCallback(response); } else { ExecuteAsyncResponse response; response.result = (RpcError)result.ToInt32(); response.response = null; myCallback(response); } } else { ExecuteAsyncResponse response; response.result = hr; response.response = null; myCallback(response); } }; var pCallbackRoutine = new FunctionPtr <AsyncCallback>(cbRountine); RPC_ASYNC_STATE asyncState = new RPC_ASYNC_STATE(); var _pAsyncState = new Ptr <RPC_ASYNC_STATE>(asyncState); RpcApi.RpcAsyncInitializeHandle(_pAsyncState.Handle, Marshal.SizeOf(typeof(RPC_ASYNC_STATE))); asyncState.Event = _pAsyncState.Data.Event; asyncState.Flags = _pAsyncState.Data.Flags; asyncState.Lock = _pAsyncState.Data.Lock; asyncState.RuntimeInfo = _pAsyncState.Data.RuntimeInfo; asyncState.Signature = _pAsyncState.Data.Signature; asyncState.Size = _pAsyncState.Data.Size; asyncState.StubInfo = _pAsyncState.Data.StubInfo; asyncState.NotificationType = RpcNotificationTypes.RpcNotificationTypeCallback; asyncState.u.NotificationRoutine = pCallbackRoutine.Handle; var ptrCB = Marshal.GetFunctionPointerForDelegate(callback); asyncState.UserInfo = ptrCB; var pAsyncState = new Ptr <RPC_ASYNC_STATE>(asyncState); if (RpcApi.Is64BitProcess) { try { result = RpcApi.NdrAsyncClientCallx64(pStub.Handle, RpcApi.ASYNC_FUNC_FORMAT_PTR.Handle, pAsyncState.Handle, handle.Handle, input.Length, pInputBuffer.Handle, out cbOutput, out output); } catch (SEHException ex) { RpcException.Assert(ex.ErrorCode); throw; } } else { using (Ptr <Int32[]> pStack32 = new Ptr <Int32[]>(new Int32[7])) { pStack32.Data[0] = pAsyncState.Handle.ToInt32(); pStack32.Data[1] = handle.Handle.ToInt32(); pStack32.Data[2] = input.Length; pStack32.Data[3] = pInputBuffer.Handle.ToInt32(); pStack32.Data[4] = pcbOutput.Handle.ToInt32(); pStack32.Data[5] = pOutput.Handle.ToInt32(); pStack32.Data[6] = 0; //reserved try { result = RpcApi.NdrAsyncClientCallx86(pStub.Handle, RpcApi.ASYNC_FUNC_FORMAT_PTR.Handle, pStack32.Handle); } catch (SEHException ex) { Log.Verbose("exception on {0}", ex); RpcException.Assert(ex.ErrorCode); throw; } } } GC.KeepAlive(pInputBuffer); } RpcException.Assert(result.ToInt32()); Log.Verbose("InvokeRpc.InvokeRpc response on {0}", handle.Handle); }