5

I defined a global hook on WM_MOUSE that works perfectly for some time. It post a message to a specific window each time the mouse move.

After some random time the hook stop sending messages. If I unregister and register the hook it works again. I suppose some specific thing happening in Windows cause the hook to stop, but I can't find what.

Any ideas ?

Edit: I attached a debugger to other processes when the hook is not active anymore, and I observed that the dll is not loaded anymore.

What could cause a hook dll to unload ?

Edit2 : I find out that a crash in MouseHookProc the dll in any process unload the hook dll from every process it's loaded in. I can't find a cause to a crash in my code. Might be some race condition or something ? Here is the hook dll code :

#include "stdafx.h"

// define a data segment
#pragma data_seg(".SHARED")
HWND  hwnd=0;
HHOOK hHook=0;
#pragma data_seg()

// tell the linker to share the segment
#pragma comment(linker, "/section:.SHARED,RWS")

#define WM_MOUSEHOOK            WM_USER+0x100

HINSTANCE hInstance=0;


// this allow to build a very small executable without any extra libraries
// (probably not the problem, the bug still occurs without this )
#ifndef _DEBUG
void *__cdecl operator new(unsigned int bytes)
{
    return HeapAlloc(GetProcessHeap(), 0, bytes);
}

void __cdecl operator delete(void *ptr)
{
    if(ptr) HeapFree(GetProcessHeap(), 0, ptr);
}

extern "C" int __cdecl __purecall(void)
{
    return 0;
}
#endif

BOOL APIENTRY DllMain( HINSTANCE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{    
    hInstance=hModule;
    return TRUE;
}

LRESULT CALLBACK MouseHookProc(int nCode, WORD wParam, DWORD lParam)
{
    if(nCode==HC_ACTION && (wParam==WM_MOUSEMOVE || wParam==WM_NCMOUSEMOVE))
    {            
        MSLLHOOKSTRUCT *mhs=(MSLLHOOKSTRUCT*)lParam;        
        PostMessage(hwnd, WM_MOUSEHOOK, wParam, 0);
    }
    return CallNextHookEx(hHook,nCode,wParam,lParam);
}

extern "C" __declspec(dllexport) HHOOK InitializeWindowsHook(char *title)
{
    hwnd=FindWindow(0, title);
    if(hwnd)
        hHook=SetWindowsHookEx(WH_MOUSE, (HOOKPROC)MouseHookProc, hInstance, 0);
    return hHook;
}

extern "C" __declspec(dllexport) BOOL DeinitializeWindowsHook()
{
    if(hHook) {
        BOOL b=UnhookWindowsHookEx(hHook);
        hHook=0;
        return b;
    }
    return FALSE;
}
Emmanuel Caradec
  • 2,302
  • 1
  • 19
  • 38
  • Are you propagating the messages to other hooks in the chain? – rpg Oct 05 '09 at 12:19
  • I noticed that while you have a `WH_MOUSE` hook you use `MSLLHOOKSTRUCT` instead of `MOUSEHOOKSTRUCT` structure. – Nick Dandoulakis Oct 08 '09 at 21:37
  • Actually you declare `*mhs` but you don't use it. – Nick Dandoulakis Oct 08 '09 at 21:41
  • Yep, I tried LL hooks too. I didn't want to edit the code too much by fear to remove something meaninful to the bug. Of course mhs is useless, but I can't see how it could cause a crash or a misbehavior. – Emmanuel Caradec Oct 09 '09 at 06:34
  • Are you on Windows 7? I found this thread: http://social.msdn.microsoft.com/Forums/en/windowsgeneraldevelopmentissues/thread/56093d14-c1bc-4d0a-a915-57fef0695191 that discusses a similar issue. I am having the same trouble myself; if the CPU is busy, the hook (apparently) times out and never gets called again. – Thomas Mar 10 '10 at 21:29
  • Hello, We encountered the same issue but with LL keyboard hook. Did you find out solution for this issue? – sam Oct 14 '10 at 04:34
  • We've found something in the form that the values in the shared segment loaded in other processes wasn't the correct values. It was values from a precedent launch. It seems to be caused by the crash of our executable followed by it's immediate reload by the watchdog (the hook dll should be unloaded then reloaded but that doesn't happen. We're not sure why, but reload speed seems to be the culprit. ) – Emmanuel Caradec Oct 14 '10 at 16:25

6 Answers6

3

Did you check, if the hook is still installed when its not called any more (i.e. check the return value from BOOL UnhookWindowsHook)?

Possibly another hook is installed that does not preserve your hook, not calling CallNextHookEx().

RED SOFT ADAIR
  • 12,032
  • 10
  • 54
  • 92
  • As you can see I do a CallNextHookEx in every cases. UnhookWindowsHook is most likely to have return ok because I've some logs there is nothing was logged. – Emmanuel Caradec Oct 08 '09 at 16:49
  • *You* call CallNextHookEx, but my assumption was that somewhere else a different hook is installed, that does not call CallNextHookEx. I dont know if this is a large project, where you maybe collaborate within a team. If so, scan all code for SetWindowsHookEx. – RED SOFT ADAIR Oct 09 '09 at 10:01
1

Try using WH_MOUSE_LL instead.

Edit: about LowLevelMouseProc Function

The hook procedure should process a message in less time than the data entry specified in the LowLevelHooksTimeout value in the following registry key:

HKEY_CURRENT_USER\Control Panel\Desktop

The value is in milliseconds. If the hook procedure does not return during this interval, the system will pass the message to the next hook.

Nick Dandoulakis
  • 42,588
  • 16
  • 104
  • 136
  • I tried it but it fire so often that it slow down all applications and would it solve anything ? – Emmanuel Caradec Sep 23 '09 at 11:20
  • 1
    @Emmanuel Caradec, you should not do *heavy* work inside the hook procedure (there is a time limit). Notify some other routine to do the job (perhaps through posting a message) and return immediately. – Nick Dandoulakis Sep 23 '09 at 11:25
  • Actually the only thing I do is sending a message to a already know hwnd. I didn't investigate a lot with wh_mouse_ll since wm_mouse worked for me. What's the problem with wh_mouse ? – Emmanuel Caradec Sep 23 '09 at 11:50
  • I tried to lock wm_mouse for a very long time, but it didn't unload the dll. It makes the PC run slowly but that's expected. – Emmanuel Caradec Oct 06 '09 at 12:38
1

I assume that the hook function is implemented in a DLL? Maybe something decreased the reference count on that DLL, so Windows unloads it, which stops your hook function.

I suggest that the first thing you do inside your DLL is to call LoadLibrary on yourself, so that the reference count of the DLL which contains the hook function is increased by one. Make sure not to call FreeLibrary to test this theory.

Frerich Raabe
  • 90,689
  • 19
  • 115
  • 207
1

You should CloseHandle your hook handle btw.

The only thing i can think of that would cause a crash is if your hook handle has been destroyed. Can you trap the exception? Have you tried break on exception to break when the exception that is occurring occurs? If you don't know what exception is occurring have you tried added a __try/__finally block around your code?

Goz
  • 61,365
  • 24
  • 124
  • 204
  • I'll add a __try/__finally block today. I suppose there is a crash because that would cause the exact same behavior. I tried dereferencing a null pointer and this cause the unloading of every loaded hook dll. Windows probably add a __try,__finally block around hooks to unload them if they behave badly. – Emmanuel Caradec Oct 09 '09 at 06:51
  • When should I do a closehandle ? After the unhookwindowsex ? – Emmanuel Caradec Oct 09 '09 at 09:19
  • Exactly. For every handle you "create" then you should close it. I'm pretty sure FindWindow only returns you a pre-existing handle so it doesn't need to be closed. I believe that confusion is why COM introduced the whole addref/release thing :) – Goz Oct 09 '09 at 10:31
0

Is the essential data for your hook in a shared segment? At a minimum this would be the HHOOK and the HWND of the target window that receives notification messages.

Bob Moore
  • 6,788
  • 3
  • 29
  • 42
0

Coming late to the party but I also faced same issue and solved by creating a new Thread to execute my tasks and return from procedure asap. Hope this helps someone.

pgcan
  • 1,199
  • 14
  • 24