public unsafe Future <byte[]> Send(RPCMessage message, bool wantResponse) { if (_Process == null) { throw new Exception("No remote process"); } if (RemoteThreadId == 0) { throw new Exception("No remote thread"); } UInt32 messageSize = (UInt32)Marshal.SizeOf(typeof(TransportRPCMessage)); UInt32 moduleNameSize = TransportStringSize(message.ModuleName); UInt32 functionNameSize = TransportStringSize(message.FunctionName); UInt32 textSize = TransportStringSize(message.Text); Future <byte[]> result = null; UInt32 messageID = 0; if (wantResponse) { messageID = GetMessageID(); result = new Future <byte[]>(); _AwaitingResponses[messageID] = result; } using (var handle = Win32.OpenProcessHandle(ProcessAccessFlags.VMWrite | ProcessAccessFlags.VMOperation, false, _Process.Id)) { RemoteMemoryRegion region; var regionSize = messageSize + moduleNameSize + textSize + functionNameSize; var buffer = new byte[regionSize]; // leaked on purpose region = RemoteMemoryRegion.Allocate( _Process, handle, regionSize ); object transportMessage = new TransportRPCMessage { Type = message.Type, MessageId = messageID, Text = WriteTransportString(message.Text, buffer, messageSize, region.Address), FunctionName = WriteTransportString(message.FunctionName, buffer, messageSize + textSize, region.Address), ModuleName = WriteTransportString(message.ModuleName, buffer, messageSize + textSize + functionNameSize, region.Address) }; fixed(byte *pBuffer = buffer) { Marshal.StructureToPtr(transportMessage, new IntPtr(pBuffer), false); try { region.Write(handle, 0, regionSize, pBuffer); } catch { try { region.Dispose(); } catch { } throw; } } if (!Win32.PostThreadMessage(RemoteThreadId, WM_RPC_MESSAGE, region.Address, region.Size)) { var error = Win32.GetLastError(); region.Dispose(); throw new Exception(String.Format("Error posting thread message: {0:x8}", error)); } } return(result); }