title: Fill struct from IntPtr received in lParam property of Window Message going across process boundaries in C#
body: <p>I posted <a href="https://stackoverflow.com/questions/7715213/receiving-windows-message-on-c-sharp-from-managed-dll-using-p-invoke">this question</a> a few days ago, and I have some follow up doubts about marshaling an IntPtr to a struct.</p>
  
  <p>The thing goes like this: 
  As stated in the question I am referencing, I make calls to asynchronous methods on a native Dll. These methods communicate their completion with Windows Messages. I receive the Windows Message correctly now and, within it, an lParam property (of type IntPrt). 
  According to the documentation I am following, this lParam points to the struct that has the results of the execution of the method. As a particular example, one of the structures I am trying to fill is defined as follows:</p>
  
  <p>Original C signature:</p>
  
  <pre><code>typedef struct _wfs_result {
      ULONG RequestID;
      USHORT hService;
      TIMESTAMP tsTimestamp;  /*Win32 SYSTEMTIME structure according to documentation*/
      LONG hResult;
      union {
          DWORD dwCommandCode;
          DWORD dwEventID;
      } u;
      LPVOID lpBuffer;
      } WFSRESULT, *LPWFSRESULT;
  </code></pre>
  
  <p>My C# definition:</p>
  
  <pre><code>[StructLayout(LayoutKind.Sequential), Serializable]
  public struct Timestamp
  {
      public ushort wYear;
      public ushort wMonth;
      public ushort wDayOfWeek;
      public ushort wDay;
      public ushort wHour;
      public ushort wMinute;
      public ushort wSecond;
      public ushort wMilliseconds;
  }
  [StructLayout(LayoutKind.Explicit), Serializable]
  public struct WFSResult
  {
      [FieldOffset(0), MarshalAs(UnmanagedType.U4)]
      public uint RequestID;
  
      [FieldOffset(4), MarshalAs(UnmanagedType.U2)]
      public ushort hService;
  
      [FieldOffset(6), MarshalAs(UnmanagedType.Struct, SizeConst = 16)]
      public Timestamp tsTimestamp;
  
      [FieldOffset(22), MarshalAs(UnmanagedType.U4)]
      public int hResult;
  
      [FieldOffset(26), MarshalAs(UnmanagedType.U4)]
      public UInt32 dwCommandCode;
  
      [FieldOffset(26), MarshalAs(UnmanagedType.U4)]
      public UInt32 dwEventID;
  
      [FieldOffset(30), MarshalAs(UnmanagedType.U4)]
      public Int32 lpBuffer;
  }
  </code></pre>
  
  <p>Now the fun part: the native Dll I am calling belongs to an independent process, FWMAIN32.EXE, which is running in the same machine (single instance). I believe the Window Message that I receive, which is application specific (above WM_USER), returns an LParam that is not really pointing to the struct I am expecting, and that the struct resides somewhere in the memory space of the FWMAIN32.EXE process.</p>
  
  <p>Initially, I tried to just Marshal.PtrToStructure (with little hope actually) and the struct got filled with garbage data. I also tried with GetLParam with same outcome. Finally, I tried to go across process boundaries with the ReadProcessMemory API, as explained in these posts:</p>
  
  <p><a href="https://stackoverflow.com/questions/4680795/c-p-invoke-reading-data-from-an-owner-drawn-list-box">C# p/invoke, Reading data from an Owner Drawn List Box</a></p>
  
  <p><a href="http://www.codeproject.com/KB/trace/minememoryreader.aspx" rel="nofollow noreferrer">http://www.codeproject.com/KB/trace/minememoryreader.aspx</a></p>
  
  <p>I get the exception code 299 (ERROR_PARTIAL_COPY: Only part of a ReadProcessMemory or WriteProcessMemory request was completed.) 
  And additionally the byte[] I get from using ReadProcessMemory is: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0</p>
  
  <p>My code:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Diagnostics;
  using System.ComponentModel;
  using System.Runtime.InteropServices;
  
  namespace XFSInteropMidleware
  {
      public class CrossBoundaryManager
      {
          [DllImport("kernel32")]
          static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Int32 bInheritHandle, UInt32 dwProcessId);
  
          [DllImport("kernel32")]
          static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] lpBuffer, UInt32 dwSize, out IntPtr lpNumberOfBytesRead);
  
          [DllImport("kernel32")]
          static extern Int32 CloseHandle(IntPtr hObject);
  
          [DllImport("kernel32")]
          static extern int GetLastError();
  
          private const string nativeProcessName = "FWMAIN32";
          private IntPtr hProcess = IntPtr.Zero;
  
          const uint PROCESS_ALL_ACCESS = (uint)(0x000F0000L | 0x00100000L | 0xFFF);
  
          static int dwSize = 34; //The size of the struct I want to fill
          byte[] lpBuffer = new byte[dwSize];
  
          public void OpenProcess()
          {
              Process[] ProcessesByName = Process.GetProcessesByName(nativeProcessName);
  
              hProcess = CrossBoundaryManager.OpenProcess(CrossBoundaryManager.PROCESS_ALL_ACCESS, 1, (uint)ProcessesByName[0].Id);
          }
  
          public byte[] ReadMemory(IntPtr lParam, ref int lastError)
          {
              try
              {
                  IntPtr ptrBytesReaded;
                  OpenProcess();
  
                  Int32 result = CrossBoundaryManager.ReadProcessMemory(hProcess, lParam, lpBuffer, (uint)lpBuffer.Length, out ptrBytesReaded);
  
                  return lpBuffer;
              }
              finally
              {
                  int processLastError = GetLastError();
  
                  if (processLastError != 0)
                  {
                      lastError = processLastError;
                  }
  
                  if (hProcess != IntPtr.Zero)
                      CloseHandle(hProcess);
              }
          }
  
          public void CloseProcessHandle()
          {
              int iRetValue;
              iRetValue = CrossBoundaryManager.CloseHandle(hProcess);
              if (iRetValue == 0)
                  throw new Exception("CloseHandle failed");
          }
      }
  }
  </code></pre>
  
  <p>And I use it like this:</p>
  
  <pre><code>protected override void WndProc(ref Message m)
  {
      StringBuilder sb = new StringBuilder();
  
      switch (m.Msg)
      {
          case OPEN_SESSION_COMPLETE:
              GCHandle openCompleteResultGCH = GCHandle.Alloc(m.LParam); //So the GC does not eat the pointer before I can use it
  
              CrossBoundaryManager manager = new CrossBoundaryManager();
  
              int lastError = 0;
              byte[] result = manager.ReadMemory(m.LParam, ref lastError);
  
              if (lastError != 0)
              {
                  txtState.Text = "Last error: " + lastError.ToString();
              }
  
              StringBuilder byteResult = new StringBuilder();
              for (int i = 0; i &lt; result.Length; i++)
              {
                  byteResult.Append(result[i].ToString() + " ");
              }
  
              sb.AppendLine("Memory Read Result: " + byteResult.ToString());
              sb.AppendLine("Request ID: " + BitConverter.ToInt32(result, 0).ToString());
              txtResult.Text += sb.ToString();
  
              manager.CloseProcessHandle();
  
              break;                
      }
      base.WndProc(ref m);
  }
  </code></pre>
  
  <p>Is it correct to go across process boundaries in this case? 
  Is it correct to use lParam as the base address for ReadProcessMemory? 
  Is the CLR turning lParam to something I cannot use?
  Why I am getting the 299 exception?
  I correctly get the process ID of FWMAIN32.EXE, but how can I be sure the lParam is pointing inside its memory space?
  Should I consider the use of "unsafe"? Could anyone recommend that approach?
  Are there any other ways to custom marshal the struct?</p>
  
  <p>Too many questions on a single post, I know, but I think they all point to resolving this issue. Thank you all for your help in advance, and sorry I had to make it so long.</p>