0X00000594

ERROR_HOOK_NEEDS_HMOD (0X00000594) Fix: Missing Module Handle

Windows Errors Intermediate 👁 1 views 📅 May 29, 2026

Windows says you can't set a nonlocal hook without a module handle. This usually means your code or app's hook call is missing the hMod parameter. Here's what to check.

1. You passed NULL (or 0) for hMod in SetWindowsHookEx

I know this error is infuriating. You wrote what looks like correct code, and Windows slaps you with 0x594. Let me save you some hair-pulling: the single most common reason is that you passed NULL for the hMod parameter when calling SetWindowsHookEx with a nonlocal hook type like WH_KEYBOARD_LL or WH_MOUSE_LL.

See, the documentation says you can pass NULL for those low-level hooks, but only if your hook procedure is inside your own executable. If it's in a DLL — or if Windows can't find the module — boom, you get 0x594. This tripped me up the first time too, back in my help desk days. The real fix is to always provide a valid module handle, even for low-level hooks.

// Wrong: passing NULL
HHOOK hhk = SetWindowsHookEx(WH_KEYBOARD_LL, HookProc, NULL, 0);

// Right: get your own module handle first
HMODULE hMod = GetModuleHandle(NULL);
HHOOK hhk = SetWindowsHookEx(WH_KEYBOARD_LL, HookProc, hMod, 0);

If you're using a DLL, pass the DLL's module handle from DllMain or via GetModuleHandle with the DLL name. Don't rely on NULL — it's fragile and fails in weird edge cases on Windows 10 22H2 and Windows 11 23H2.

2. Hook procedure is in a DLL, but you didn't export it properly

Another classic: your hook function lives in a DLL, but the DLL doesn't export the function correctly. Windows needs to find that function by address or ordinal. If the export table is messed up, SetWindowsHookEx returns 0x594 because it can't resolve the callback.

Check your DLL's .def file or __declspec(dllexport). I've seen developers forget to add extern "C" for C++ projects, which mangles the name and breaks the export.

// In your DLL header
extern "C" __declspec(dllexport) LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam);

// In your .def file (optional but explicit)
EXPORTS
    HookProc

Also verify the DLL path. If you load the DLL with LoadLibrary and it fails silently (maybe the DLL isn't in the search path), GetModuleHandle returns NULL, and you'll pass NULL to SetWindowsHookEx. Always check GetLastError after LoadLibrary.

3. You're using a 64-bit hook with a 32-bit application (or vice versa)

This one's sneaky. Windows hooks are architecture-specific. If your app is 32-bit but your hook DLL is 64-bit (or the other way around), SetWindowsHookEx will fail with 0x594. It's not just a mismatch — the system literally can't inject a 64-bit DLL into a 32-bit process.

I ran into this when supporting a legacy app on Windows 10. The app was x86, but the hook DLL was accidentally compiled as x64. The error code was 0x594 every time. The fix: match the bitness. Compile both your EXE and DLL for the same platform.

If you need both, you have to create a 64-bit helper process to set the hook, or use SetWindowsHookEx from a 64-bit process with a 64-bit DLL. There's no way around this — Windows won't let you mix.

Quick-reference summary table

Cause Fix Code/Check
NULL hMod Pass real module handle GetModuleHandle(NULL) or DLL's handle
DLL export missing Export function correctly __declspec(dllexport) + .def
Bitness mismatch Match app/DLL architecture Both x86 or both x64

If none of these work, enable GetLastError immediately after SetWindowsHookEx returns NULL. That will give you a more specific error. But in 95% of cases, it's one of these three. You've got this.

Was this solution helpful?