Setting up and Removing Hooks and Some Hook Functions

Setting up the hook is done with a function named SetWindowsHookEx, which takes four arguments. They are an integer telling the type of the hook, a pointer to the function containing the hook, the module handle and the ID for the thread being hooked. In case of systemwide hooks the instance handle is the DllMain HINSTANCE parameter and thread ID 0 tells Windows that a system wide hook accessing multiple processes and threads is to be installed. The return value is a handle to HHOOK which should be saved to later use. In the example application a CBT hook is installed as follows:

hCbtHook = SetWindowsHookEx(WH_CBT, cbtHookFunction, hDllInstance, 0);

UnhookWindowsHook is the function used to remove a Windows hook whose single parameter is the handle saved on creating the hook. In principle, the return value should tell whether removing the hook succeeded. However, according to the Microsoft hook article, the return value is currently always true. A CBT-hook gets removed in the example app like this:

UnhookWindowsHookEx(hCbtHook);

If two or more applications install hooks that are of similar type, the hooks make up a chain. SetWindowsHookEx adds the most recently added hook in front of the hook chain. In other words, the most recently added hook gets the hooked message first. Hooks don't, apart from the WH_DEBUG hook, know that any other hooks are necessarily present. That's why it is possible for a certain hook to filter out messages so that the other hooks behind it never get the messages. You must be especially careful with system wide hooking in general.

The second parameter to SetWindowsHookEx is the address of the function in which the real action takes place. The prototype for a hook function is identical in all hook types and resembles a window procedure quite a bit in terms of parameters. The return value is of the same type and the last two of the three parameters are typed wParam and lParam just like in a window procedure. The first parameter is a hook code telling the meaning of the further two parameters (compare this to the message parameter of a window procedure). Usually the hook code is positive but negative values indicate that for some reason the system has requested hook functions to ignore this message.

Windows doesn't automatically pass on the hooked messages to the hooks in the chain, in stead the author of the hook function is responsible for this. A message is passed to the next hook with the function CallNextHookEx, whose three last parameters are analogous to the hook function parameters. The first one is the handle returned when setting up the hook. The return value for a hook must additionally be the value gotten from CallNextHhookEx. This hook function contract dictates the generic outline of a hook function as follows:

LRESULT CALLBACK hookFunction(int ncode, WPARAM wParam, LPARAM lParam)
{
	if(ncode >= 0)
	{
	    // handle this event.
	} // if
	return CallNextHookEx(setHookRetval, ncode, wParam, lParam);
} // hookFunction

Back to the Contents