private uint RpcEntryPoint(IntPtr clientHandle, uint szInput, IntPtr input, out uint szOutput, out IntPtr output) { output = IntPtr.Zero; szOutput = 0; try { byte[] bytesIn = new byte[szInput]; Marshal.Copy(input, bytesIn, 0, bytesIn.Length); byte[] bytesOut; using (RpcCallInfo call = new RpcCallInfo(clientHandle)) { bytesOut = Execute(call, bytesIn); } if (bytesOut == null) { return((uint)RPC_STATUS.RPC_S_NOT_LISTENING); } szOutput = (uint)bytesOut.Length; output = RpcRuntime.Alloc(szOutput); Marshal.Copy(bytesOut, 0, output, bytesOut.Length); return((uint)RPC_STATUS.RPC_S_OK); } catch (Exception ex) { RpcRuntime.Free(output); output = IntPtr.Zero; szOutput = 0; RpcTrace.Error(ex); return((uint)RPC_STATUS.RPC_E_FAIL); } }
private static byte[] InvokeRpc(RpcHandle handle, Guid iid, byte[] input) { RpcTrace.Verbose("InvokeRpc 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(ClientInterfaceFactory.CreatExplicitBytesClient(iid)), RpcRuntime.TYPE_FORMAT, false)); } int szResponse = 0; IntPtr response, result; using (Ptr <byte[]> pInputBuffer = new Ptr <byte[]>(input)) { if (RpcRuntime.Is64BitProcess) { try { result = NativeMethods.NdrClientCall2x64(pStub.Handle, RpcRuntime.FUNC_FORMAT_PTR.Handle, handle.Handle, input.Length, pInputBuffer.Handle, out szResponse, out response); } catch (SEHException ex) { RpcTrace.Error(ex); Guard.Assert(ex.ErrorCode); throw; } } else { using (Ptr <Int32[]> pStack32 = new Ptr <Int32[]>(new Int32[10])) { pStack32.Data[0] = handle.Handle.ToInt32(); pStack32.Data[1] = input.Length; pStack32.Data[2] = pInputBuffer.Handle.ToInt32(); pStack32.Data[3] = pStack32.Handle.ToInt32() + (sizeof(int) * 6); pStack32.Data[4] = pStack32.Handle.ToInt32() + (sizeof(int) * 8); pStack32.Data[5] = 0; //reserved pStack32.Data[6] = 0; //output: int dwSizeResponse pStack32.Data[8] = 0; //output: byte* lpResponse try { result = NativeMethods.NdrClientCall2x86(pStub.Handle, RpcRuntime.FUNC_FORMAT_PTR.Handle, pStack32.Handle); } catch (SEHException ex) { RpcTrace.Error(ex); Guard.Assert(ex.ErrorCode); throw; } szResponse = pStack32.Data[6]; response = new IntPtr(pStack32.Data[8]); } } GC.KeepAlive(pInputBuffer); } // on local machine // if 32 bit server just throws Exception in server side handler // then 32 bits client can see "-2147467259" debug view of pointer result // then 64 bits client can see "2147500037" debug view of pointer result // then 32 bits client can do ToInt32 and things work fine // then 64 bits client can do ToInt32 and get arithmetic overflow exception // hence using ToInt64 for 64 bits client if (IntPtr.Size == 8) { Guard.Assert(result.ToInt64()); } else { Guard.Assert(result.ToInt32()); } RpcTrace.Verbose("InvokeRpc.InvokeRpc response on {0}, received {1} bytes", handle.Handle, szResponse); byte[] output = new byte[szResponse]; if (szResponse > 0 && response != IntPtr.Zero) { Marshal.Copy(response, output, 0, output.Length); } RpcRuntime.Free(response); return(output); }