0

This code works well on x64 (it is windows global hook in separate thread on keyboard input event. Use it in electron program for barcode scan features), namely keyboardPoc reciever correct values in KBDLLHOOKSTRUCT struct: vkCode, scanCode and others. But on x86 isnt - there are always same value for any keypress. I thought that problem was in struct data types and changed them in different ways, but nothing helped. I tested over and over again wihtout result, so i need communities help.

const os = require("os");
const ffi = require("ffi-napi");
const ref = require("ref-napi");
const Struct = require("ref-struct-di")(ref);


const is64bit = os.arch() === "x64";

// Types
const LONG = is64bit ? ref.types.long : ref.types.int32;
const ULONG = is64bit ? ref.types.ulong : ref.types.uint32;
const INT = ref.types.int;
const UINT = ref.types.uint;
const DWORD = ref.types.uint32; // DWORD always is unsigned 32-bit
const BOOL = ref.types.bool;

const HANDLE = is64bit ? ref.types.uint64 : ref.types.uint32;
const HHOOK = HANDLE;
const HWND = HANDLE;
const HINSTANCE = HANDLE;

const WPARAM = is64bit ? ref.types.uint64 : ref.types.uint32; // typedef UINT_PTR, uint32(x86) or uint64(64)
const LPARAM = is64bit ? ref.types.int64 : ref.types.int32; // typedef LONG_PTR, int32(x86) or int64(64)
const LRESULT = is64bit ? ref.types.int64 : ref.types.int32; // typedef LONG_PTR

const HOOKPROC = "pointer";

// Structures
const POINT = Struct({
  x: LONG,
  y: LONG,
});

const MSG = Struct({
  hwnd: HWND,
  message: UINT,
  wParam: WPARAM,
  lParam: LPARAM,
  time: DWORD,
  pt: POINT,
  lPrivate: DWORD,
});

const KBDLLHOOKSTRUCT = Struct({
  vkCode: DWORD,
  scanCode: DWORD,
  flags: DWORD,
  time: DWORD,
  dwExtraInfo: ULONG,
});

// User32 bindings
const user32 = ffi.Library("user32", {
  SetWindowsHookExW: [HHOOK, [INT, HOOKPROC, HINSTANCE, DWORD]],
  UnhookWindowsHookEx: [BOOL, [HHOOK]],
  CallNextHookEx: [LRESULT, [HHOOK, INT, WPARAM, LPARAM]],
  GetMessageW: [BOOL, [MSG, HWND, UINT, UINT]],
  TranslateMessage: [BOOL, [MSG]],
  DispatchMessageW: [LRESULT, [MSG]],
});

// Constants
const WH_KEYBOARD_LL = 13;
const WM_KEYDOWN = 0x0100; // 256
// const WM_KEYUP = 0x0101; // 257
// const WM_SYSKEYDOWN = 0x0104; // 260
// const WM_SYSKEYUP = 0x0105; // 261

let hHook = 0;

// Callback for LL(low-level) hook (doesn`t require dll injection)

// LRESULT CALLBACK LowLevelKeyboardProc(
//     _In_ int    nCode,
//     _In_ WPARAM wParam,
//     _In_ LPARAM lParam
//   );

const keyboardProc = ffi.Callback(
  LRESULT,
  [INT, WPARAM, KBDLLHOOKSTRUCT],
  (nCode, wParam, lParam) => {
    console.log(
      `input event callback: ${JSON.stringify(nCode)} ${JSON.stringify(
        wParam
      )} ${JSON.stringify(lParam)}`
    );
    if (wParam === WM_KEYDOWN) {
      const message = {
        event: "key-down",
        data: {
          vkCode: lParam.vkCode,
          scanCode: lParam.scanCode,
        },
      };

    }
    return user32.CallNextHookEx(
      hHook,
      nCode,
      wParam,
      ref.address(lParam.ref())
    );
  }
);

/* Set the hook */
hHook = user32.SetWindowsHookExW(WH_KEYBOARD_LL, keyboardProc, 0, 0);

/* Message loop */
const msg = new MSG();
const res = user32.GetMessageW(msg.ref(), 0, 0, 0);
while (res) {
  user32.TranslateMessage(msg.ref());
  user32.DispatchMessageW(msg.ref());
}
Elendiar
  • 37
  • 5

1 Answers1

0

Correct types for keyboardProc must be [INT, WPARAM, ref.refType(KBDLLHOOKSTRUCT)]. Then lParam.deref() show right value. Thanks lowfront with https://stackoverflow.com/a/69688272/11492379, this helps me a lot.

Elendiar
  • 37
  • 5