Search code examples
c#winformshookloadlibrarysetwindowshookex

explorer.exe crashes when global touch hook via WH_GETMESSAGE is enabled


I am working on an app that listens on touch events globally, to which I have setup a hook to retrieve WM_TOUCH messages. This message will be retrieved from a WH_GETMESSAGE hook.

The problem is that every time I run the app, explorer.exe just crashes and will take a long time to open again. Could there be someone knowledgeable in this issue? I have done this using WH_KEYBOARD_LL before and it does not do the same thing.

This, and that I still don't get any global touch events at all.

I have setup my hook as follows:

public void hook() {
            IntPtr hInstance = LoadLibrary("User32");
            hhook = SetWindowsHookEx(WH_GETMESSAGE, hookProc, hInstance, 0); // set Thread ID to 0 to listen to all threads within the same desktop
}
  • I have read information regarding setting up global hooks on MSDN here.

  • I also called the RegisterTouchWindow function to my app window to enable receiving touch events.


Solution

  • I will try to answer my question as detailed as possible for other beginners to understand what is going on.

    First of all, I followed the guide on how to create hooks from MSDN Hook Documentation, but the example shows its usage on c++. Having searched for references in using SetWindowHookEx the examples I read about dealt with hooking the low level windows hooks. These hooks, namely WH_KEYBOARD_LL and WH_MOUSE_LL, are the most common tutorials around and can be globally hooked without the need to separate their Hook Process into a dll. The rest of the WH System Events require separation if it were to be hooked globally. This is described within the documentations as well:

    You must place a global hook procedure in a DLL separate from the application installing the hook procedure. The installing application must have the handle to the DLL module before it can install the hook procedure.

    The rough idea behind is that the hook function gets injected to all of the running threads. For the case of WH_KEYBOARD_LL and WH_MOUSE_LL who uses User32.dll as their hook library, this is fine. But if you were to use it for the other system events like I did, the process could crash your whole desktop like how it happened to mine.

    My application was coded in C#, so I had to create a dll in c++, and then link it to my C# application. Also, read about pInvokes to be able to use LoadLibrary and GetProcAddress

    You can create dll files from Visual Studio Itself. You only have to modify the dllmain.cpp file. I played around with the WH_GETMESSAGE from this example

    From my C# app, all I had to do is to call the SetHook function like so:

    IntPtr hInstance = IntPtr.Zero;
    IntPtr hProc = IntPtr.Zero;
    
    private delegate void HookSetting();
    
    public void SetHook()
    {
            hInstance = LoadLibrary("Dll1");
    
            if (IntPtr.Zero == hInstance)
            {
                //do a null check
            }
            hProc = GetProcAddress(hInstance, "_SetHook@0"); // SetHook is in its "mangled" form right here
            if(IntPtr.Zero == hProc)
            {
                //do a null check
            }
    
            //Ways of starting the Hook:
            // OPTION 1: calling the SetHook function of the DLL within the C# app.
            //HookSetting hookset = (HookSetting)Marshal.GetDelegateForFunctionPointer(hProc, typeof(HookSetting));
            //hookset();
    
            // OPTION 2: Instead of using the SetHook function, call the SetwindowsHookEx directly 
            hhook = SetWindowsHookEx(WH_GETMESSAGE, hProc, hInstance, 0);
     }