TooTallNate / ref

Turn Buffer instances into "pointers"
http://tootallnate.github.com/ref
451 stars 141 forks source link

How can i convert decimal value to pointer of hWnd #96

Open waitingsong opened 6 years ago

waitingsong commented 6 years ago
    const lpszClass = Buffer.from('Vim\0', 'ucs2');
    const hWnd = user32.FindWindowExW(null, null, lpszClass, null);
    console.log(hWnd, ref.address(hWnd));  // should be like <Buffer@0x003309AA 84 c0 75 0f> 3344810
    user32.ShowWindow(hWnd, 0);  // hide vim program window succeed

  // if got the value 
  const dec = 3344810;
  user32.ShowWindow(dec, 0);   // failed
  user32.ShowWindow(Buffer.from([dec]), 0);   // failed yet

  const buf = Buffer.alloc(4);
  buf.writeUInt32LE(dec, 0);
  user32.ShowWindow(buf, 0);   // failed 
  console.log(buf);
 // <Buffer@0x0506BD88 aa 09 33 00> . so 0x003309AA is the Buffer value , not the Buffer address

How can i convert number to the typeof HANDLE ? thanks

repl-chris commented 5 years ago

Did you ever figure this out? I also need to do this - I need to send the window handle to another process....obviously I can't send the buffer, because it crashes, so I get the raw address value via ref.address(hWnd), but then how to I convert it back to a usable Buffer object in the target process?

waitingsong commented 5 years ago

@repl-chris Not yet. it seems cause crash after output hWnd as number https://github.com/waitingsong/node-win32-api/blob/master/README.md

repl-chris commented 5 years ago

Well, I've come up with something that works...

  private static bufferAtAddress(address: number): Buffer {
    if (address > Number.MAX_SAFE_INTEGER) {
      throw new Error('Address too high!');
    }
    const buff = new Buffer(8);
    buff.writeUInt32LE(address % 0x100000000, 0);
    buff.writeUInt32LE(Math.trunc(address / 0x100000000), 4);
    (buff as any).type = { ...ref.types.void, indirection: 2 };
    return ref.deref(buff);
  }

It's not ideal. I'm convinced there must be a more proper way to do this, but I can't find it. This will only work reliably for addresses <= Number.MAX_SAFE_INTEGER, so it's not a great solution for any random 64-bit address...to make it proper you can't ever call ref.address() (because a javascript number doesn't have the precision to hold any random 64bit address).....and instead use only ref.hexAddress() and then convert this method to use something like bignum. HOWEVER, that limitation probably doesn't apply to you, if you're just using it for win32 handles, like I am....because according to MSDN even on 64 bit windows all handles only contain 32-bits of significant data, so you're guaranteed they'll always be < Number.MAX_SAFE_INTEGER, so this should work just fine.

64-bit versions of Windows use 32-bit handles for interoperability. When sharing a handle between 32-bit and 64-bit applications, only the lower 32 bits are significant, so it is safe to truncate the handle (when passing it from 64-bit to 32-bit) or sign-extend the handle (when passing it from 32-bit to 64-bit). Handles that can be shared include handles to user objects such as windows (HWND), handles to GDI objects such as pens and brushes (HBRUSH and HPEN), and handles to named objects such as mutexes, semaphores, and file handles.