Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to correctly use SetWindowsHookEx & CallNextHookEx

I can correctly setup up a windows hook, but I get confused by the line in MSDN that says "Calling the CallNextHookEx function to chain to the next hook procedure is optional, but it is highly recommended; otherwise, other applications that have installed hooks will not receive hook notifications and may behave incorrectly as a result. You should call CallNextHookEx unless you absolutely need to prevent the notification from being seen by other applications.".

I want to be a good programming citizen and call the next hook. But, my hook procedure looks like this:

LRESULT CALLBACK CBTProc(int code, WPARAM wp, LPARAM lp)
{
    if (code != HCBT_CREATEWND)
        {
                // What do I do here? It's not the event I requested so how do I pass it on?
        return 0;
    }

    // It's the code we want (create window)
        CallNextHookEx(...);
        ...
}

So, what happens in the hook procedure if the code isn't the one I'm interested in? How do I call the next hook?

Edit: The main problem is that a HHOOK is returned from the SetWindowsHookEx, and that needs to be passed to the CallNextHookEx function.

Update: It seems the hook parameter is ignored on the NT platforms:
http://msdn.microsoft.com/en-us/library/ms644974.aspx
http://www.klenotic.com/pl/null_hhook/

like image 620
Mark Ingram Avatar asked Oct 17 '08 22:10

Mark Ingram


People also ask

How does SetWindowsHookEx work?

The SetWindowsHookEx function will install the hook routine into the hook chain of the victim.exe process, which will be invoked whenever certain event is triggered. In our case, the event that needs to be triggered is the action that we've inputted into the SetWindowsHookEx function.

What is Wh_cbt?

The WH_CBT hook is intended primarily for computer-based training (CBT) applications. For more information, see the CBTProc callback function. For information, see WinEvents.


1 Answers

According to the docs, the proper thing to do is pass the arguments you received directly to CallNextHookEx, exactly as you received them. You should also call CallNextHookEx regardless of whether you decided to handle the hook message.

According to MSDN, the first parameter to CallNextHookEx is ignored on on NT/XP/2003, and for older Win95-based operating systems it should be the HHOOK you received when you registered your hook with SetWindowsHookEx. The docs don't specify a value for Windows 2000, but since it's part of the NT family, a reasonable guess is that it's ignored there as well.

Given all that, a good way to code the method for NT-family operating systems might be this:

LRESULT CALLBACK CBTProc( int code, WPARAM wp, LPARAM lp )
{
    if( code == HCBT_CREATEWND )
        ProcessCreateWnd( wp, lp );
    return CallNextHookEx( 0, code, wp, lp );
}

void ProcessCreateWnd( WPARAM wp, LPARAM lp )
{
    // my code here
}

This makes sure that you always call the hook at the end of your processing, and makes it hard to accidentally add a return that will bypass CallNextHookEx.

like image 82
Charlie Avatar answered Sep 20 '22 15:09

Charlie