How can I ensure that UnhookWindowsHookEx is called even upon abnormal termination?
Asked Answered
G

2

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.

Giana answered 18/12, 2010 at 16:9 Comment(0)
H
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.
Haematoxylin answered 18/12, 2010 at 16:45 Comment(7)
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.Roundtheclock
@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).Haematoxylin
No, it really doesn't work that way. Complicated, glad it's your answer and not mine :) This otherwise Just Works™.Roundtheclock
@Hans: Then how does it work? Bill wants to learn if he's bein an idiotHaematoxylin
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.Roundtheclock
@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.Haematoxylin
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.Roundtheclock
J
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);
Jonahjonas answered 22/2, 2019 at 19:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.