Sign in to follow this  
Jan Wassenberg

Unity Windows hooks (e.g. WH_KEYBOARD_LL) must be in DLL?

Recommended Posts

Jan Wassenberg    999
This is in reference to "Quick question about VK_SNAPSHOT" - the board doesn't seem to allow replies to old threads. OP probably doesn't care anymore, but I had the same problem and found this thread while searching. VK_SNAPSHOT apparently isn't delivered by WM_KEYDOWN or even WM_SYSKEYDOWN messages. What you need to do is register a WH_KEYBOARD_LL hook. If VK_SNAPSHOT is received there, post a corresponding WM_KEYDOWN message to your wndproc, and don't chain to the next hook; return > 0. This prevents the normal Windows copy-to-clipboard behavior. One open question is whether the hook proc really needs to be in a DLL, as documented - it would be nice to avoid, if possible. I found an article claiming it's a non-issue, but I'm not sure the author fully understood the problem. First, I RTFM:
Quote:
The LowLevelKeyboardProc hook procedure is an application-defined or library-defined callback function used with the SetWindowsHookEx function. The system calls this function every time a new keyboard input event is about to be posted into a thread input queue. The keyboard input can come from the local keyboard driver or from calls to the keybd_event function. If the input comes from a call to keybd_event, the input was "injected". However, the WH_KEYBOARD_LL hook is not injected into another process. Instead, the context switches back to the process that installed the hook and it is called in its original context. Then the context switches back to the application that generated the event.
OK. Does this mean the hook is always called in the address space of the application that issued the hook, or is this only special-cased when someone else calls keybd_event? Comment from the above article:
Quote:
this approach can ONLY be used with WH_MOUSE_LL and WH_KEYBOARD_LL [referring to dox above] That why this works so good. Try to do this with another hooks and you'll see the back of the coin.
The author replies:
Quote:
lol, that refers to something completely different, it has to do with injected events generated by API calls like keybd_event(). You seriously got it wrong, and I am so very certain about this because I already used the same code with all kinds of hooks already, and it always worked.
So, if there is no special context-switch handling, I'm not sure how global hooks are to work with this method (adding the hook proc to the export table and passing the application's module handle). Obviously the hook proc will have to be mapped into each process in whose context a hook event may be generated. The EXE will have to be loaded and the hook proc imported. Now a big problem: I don't think EXEs get a separate IAT, as would a DLL. That means one of the 2 instances has an invalid IAT => catastrophe, since they won't be mapped at the same address. Another twist: I tried it out and the keyboard hook just works, even if the proc is in my app and it's not exported. A possible explanation would be that SetWindowsHookEx calculates the RVA (proc - module_inst) and uses that instead of PE exports. Or does the fact that it's exported cause Windows to map the proc in some shared memory? It is not the case that module_inst == 0x400000 (i.e. normal executable instead of DLL) => the hook is treated as local, since the hook still fires even if other apps have the focus. To summarize, both explanations are plausible: special handling to call the hook in its app's address space, or mapping the hook proc into each app ("importing" via stored RVA). Is it therefore safe to leave out the DLL, in contradiction to the dox? I see that glfw does so without any comment. Anyone know more, or been bitten by this?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this