title: Easyhook: unmanaged hooking, how to call original function / change return status?
body: <p>So I have a hook function at <code>winspool.drv!WritePrinter</code>, which is successfully hooked with unmanaged C++ remotely injected to spoolsv.exe.</p>
  
  <p>Currently, the hook seems to either replace original function, or corrupt the stack in an undetectable way: after hooking, WritePrinter calls result in no printer activity outside the hook.</p>
  
  <p>I've figured out there's at least one way to call original function, so-called <code>LhGetOldProc</code>. However, using it leads to crashes, don't sure if this is easyhook-related error or it's just bad casting.</p>
  
  <h2>So, how do I properly call original function in Easyhook unmanaged version?</h2>
  
  <p>Hook callback with <code>LhGetOldProc</code>:</p>
  
  <pre><code>UCHAR *uc = NULL;
  LhGetOldProc(hhW, &amp;uc);
  typedef BOOL (*wp)(_In_   HANDLE, _In_   LPVOID, _In_   DWORD cbBuf, _Out_  LPDWORD);
  wp my_wp = reinterpret_cast&lt;wp&gt;(reinterpret_cast&lt;long&gt;(uc)); // http://stackoverflow.com/questions/1096341/function-pointers-casting-in-c
  
  BOOL res ;
  if (my_wp == 0x0) {
   return -1;
  } else {
   res  = my_wp(hPrinter, pBuf, cbBuf, pcWritten); // crash
  }
  </code></pre>
  
  <p>Hook code:</p>
  
  <pre><code>HMODULE                 hSpoolsv = LoadLibraryA("winspool.drv");
  TRACED_HOOK_HANDLE      hHook = new HOOK_TRACE_INFO();
  NTSTATUS                NtStatus;
  UNICODE_STRING*         NameBuffer = NULL;
  HANDLE                  hRemoteThread;
  FORCE(LhInstallHook(GetProcAddress(hSpoolsv, "WritePrinter"), WritePrinterHookA, 0x0, hHook));
  ULONG ACLEntries[1] = { (ULONG) - 1 };
  FORCE(LhSetExclusiveACL(ACLEntries, 1, hHook));
  
  hhW = hHook;
  </code></pre>
  
  <hr>
  
  <p><em>TIL: in 2013, CodePlex (where EasyHook discussion list is) doesn't accept third level domains for e-mail when registering with Microsoft account. Not going to use Firebug to bypass the form.</em></p>