15

Unfortunately, MSDN is not clear enough with it. I'm writing a program which uses a global hook, and I'm worrying about what would happen if the program terminates abnormally (crashes, killed by user, etc).

  1. Does Windows automatically unhook global hooks installed by a process when the process terminates?

  2. If not, is it possible to call UnhookWindowsHookEx() in another process to release the hook? (I'm thinking of doing this in a hooked thread, if it detects that the installer process is dead.)

  3. If the answers were no and no, isn't it dangerous to leave a global hook active when the installer process is terminated? What are the standard methods of dealing with this situation?

  4. I've read in MSDN that UnhookWindowsHookEx() doesn't free the dll loaded in other processes, but it doesn't say when will the dll be freed. This article in CodeProject seems to suggest that the dll is unmapped (in the respective process) when the first message arrives at the hooked thread, so it's about right after the UnhookWindowsHookEx() call. Is it true?

Thank you.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Gary Chang
  • 1,042
  • 12
  • 18

2 Answers2

14
  1. Yes, when a process terminates the system cleans up after it -- all handles are closed implicitly.
  2. No, it's not, and you don't need to anyway.
  3. (It's Yes and no not no and no)
  4. I don't see why there's a DLL loaded in another process involved here. (EDIT: I was originally thinking of a systemwide hook such as CBTProc -- if your hook is per-process that might be different) If you're dealing with something like the link indicated in @Hans' comment, whereby you've injected your own DLL into the target process, then you should put functionality to unload the hook inside your DLL, not tie it's correct operation to your application. (I.e. if sending the message back to your application fails inside the DLL, then your DLL should decide to unload itself) /EDIT When a DLL is loaded inside another process it's up to that process to do the freeing.
Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
  • 4
    Your point 4 isn't accurate, global hooks require the DLL with hook callback to be injected into the target process. Unhooking also involves unloading that DLL again. Key point is that this is synchronized inside the process itself through the message loop. – Hans Passant Dec 18 '10 at 17:34
  • @Hans: That depends on the kind of hook. Systemwide hooks do not inject your DLL into the target process. Obviously if you've injected a DLL into that target process, then that process is going to be the one who frees it (Which is what my second sentence above says). – Billy ONeal Dec 18 '10 at 22:06
  • 1
    No, it really doesn't work that way. Complicated, glad it's your answer and not mine :) This otherwise Just Works™. – Hans Passant Dec 18 '10 at 22:12
  • @Hans: Then how *does* it work? *Bill wants to learn if he's bein an idiot* – Billy ONeal Dec 18 '10 at 22:24
  • Doesn't really work, I know how smart you are. The linked codeproject has excellent diagnostics for what is really going on. I'm pretty sure they are accurate. Two kinds of hooks, the low-level ones and the global ones. Low-level, two of them, get the callback in-process, the global ones require a DLL injection. – Hans Passant Dec 18 '10 at 22:33
  • @Hans: What do you mean "how smart I am"? The CodeProject article is about stealing the contents of a textbox. When I heard "hook" I thought it was something like a CBTProc hook (link in my answer), which is systemwide and requires no DLL injection. I've never written other kinds of hooks. – Billy ONeal Dec 18 '10 at 22:35
  • 2
    It was a compliment, sorry I screwed that up. A CBT hook a global hook. It is indeed system wide and *does* require injection. Well, depending on the SetWindowsHookEx() call arguments, specifying the thread doesn't make it global. – Hans Passant Dec 18 '10 at 22:41
3

If your process dies, UnhookWindowsHookEx is called implicitly and your hooks are removed. The .dll is unloaded by the message processing code after a new message is received. Therefore some background processes which almost never receive any messages, may still keep the library locked long after your hook was removed. Broadcasting a WM_NULL message usually helps. I like sending it a few times after unhooking.

SendNotifyMessage(HWND_BROADCAST, WM_NULL, 0, 0);
George Valkov
  • 1,217
  • 12
  • 10