0

I have written an application to hook some procedure onto a new process to monitor mouse down events and to disable mouse down events on the new process. As of now, I am able to capture to mouse down events coming to this process and I am trying to disable all mouse down events as a POC. This is what I am doing currently in the hook procedure.

extern "C" __declspec(dllexport) LRESULT  __stdcall meconnect(int code, WPARAM wParam, LPARAM lParam) {

    if (code >= 0) {
        LPMSG msg = (LPMSG)lParam;

        if (msg->message == WM_LBUTTONDOWN) {

            OutputDebugString(L"Mouse down event happened \n");

            return false;

        }

    }

    return(CallNextHookEx(NULL, code, wParam, lParam));

}

When I perform mouse down event, I am getting the log message that I have written. But I also expect that click event to be blocked since I am returning false. but it does not happen so and click event proceed as a normal click. How could I disable mouse down event. Thanks in advance for any help on this

This is how I call setWindowsHookEx

HHOOK handle = SetWindowsHookEx(WH_GETMESSAGE, addr, dll, threadID);
KItis
  • 5,476
  • 19
  • 64
  • 112
  • What kind of hook are you using, i.e., what is the first argument to `SetWindowsHookEx` ? – Harry Johnston Mar 13 '17 at 03:52
  • @HarryJohnston This is how I call SetWindowsHookEx HHOOK handle = SetWindowsHookEx(WH_GETMESSAGE, addr, dll, threadID); – KItis Mar 13 '17 at 03:52
  • The documentation for `GetMsgProc` doesn't say that returning zero will cause the message to be blocked. Is this documented somewhere else? – Harry Johnston Mar 13 '17 at 04:03
  • 1
    Looks like the correct way to do this is to [change the message to `WM_NULL`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms632637(v=vs.85).aspx). – Harry Johnston Mar 13 '17 at 04:07
  • @HarryJohnston, Did you mean if (msg->message == WM_NULL) { – KItis Mar 13 '17 at 04:11
  • @HarryJohnston, No , it was not based on documentation, I thought that If I don't call CallNextHookEx, it won't proceed to next step. – KItis Mar 13 '17 at 04:12
  • 1
    That prevents other hooks from seeing the message. It doesn't affect the original message queue. And I mean `msg->message = WM_NULL;` – Harry Johnston Mar 13 '17 at 04:13
  • I have done the change you suggested, then it does not come inside the if condition. – KItis Mar 13 '17 at 04:31
  • Huh? The change should be *inside* the `if` condition, instead of `return false;` since that's what was wrong. Did you read the link I posted? – Harry Johnston Mar 13 '17 at 09:33
  • @HarryJohnston, yes , it worked, Thank you so much, If you could post it as an answer , I will give up vote and accept your answer. Thanks again. – KItis Mar 13 '17 at 15:25

1 Answers1

3

The reason you are supposed to call CallNextHookEx during your hook routine is so that the message can be passed on to any other hooks that might be installed. Failing to do so does not prevent the message from being seen by the application that received it.

The documentation for WM_NULL explains how to block the message:

For example, if an application has installed a WH_GETMESSAGE hook and wants to prevent a message from being processed, the GetMsgProc callback function can change the message number to WM_NULL so the recipient will ignore it.

The corrected code should therefore look something like this:

extern "C" __declspec(dllexport) LRESULT  __stdcall meconnect(int code, WPARAM wParam, LPARAM lParam) {

    if (code >= 0) {

        LPMSG msg = (LPMSG)lParam;

        if (msg->message == WM_LBUTTONDOWN) {

            OutputDebugString(L"Mouse down event happened \n");

            msg->message = WM_NULL;

            return false;

        }

    }

    return(CallNextHookEx(NULL, code, wParam, lParam));

}

However, this may cause inconsistent behaviour if other hooks are present, because whether another hook sees WM_LBUTTONDOWN or WM_NULL will depend on the order of the hook chain, which is unpredictable. It might be preferable to try something like this:

extern "C" __declspec(dllexport) LRESULT  __stdcall meconnect(int code, WPARAM wParam, LPARAM lParam) {

    if (code >= 0) {

        LPMSG msg = (LPMSG)lParam;

        int result = CallNextHookEx(NULL, code, wParam, lParam);

        if (msg->message == WM_LBUTTONDOWN) {

            OutputDebugString(L"Mouse down event happened \n");

            msg->message = WM_NULL;

        }

        return result;

    }

    return(CallNextHookEx(NULL, code, wParam, lParam));

}
Harry Johnston
  • 35,639
  • 6
  • 68
  • 158
  • The second code can be shortened by moving the `CallNextHookEx()` above the first `if` and moving the `return result` to the end of the function. `int result = CallNextHookEx(NULL, code, wParam, lParam); if (code >= 0) { LPMSG msg = (LPMSG)lParam; if (msg->message == WM_LBUTTONDOWN) { OutputDebugString(L"Mouse down event happened \n"); msg->message = WM_NULL; } } return result; }` – Remy Lebeau Mar 13 '17 at 21:23