HOOK是个很有用的东西,做很多东西都要用到它,不过对于我这么个新手来说,它实际的运行原理是什么,还真不怎么搞的清楚。
如果说,一个WH_MOUSE_LL被封装在一个DLL中,然后它被线程A调用,执行了SetWindowsHookEx命令作为一个全局钩子挂起。假设这时系统中存在一个正在执行的线程B,那么这个钩子所在的DLL就将被注入到线程B。然后当线程B的消息队列中收到了WM_LBUTTONDOWN消息,那么线程B就会调用Hook的回调函数,来处理这个消息。这个回调函数是在线程B中执行,与A无关,它占用的资源和CPU时间片都是B的,这样理解正确么?这时回调函数向线程B SendMessage会发生0x8001010D错误么?另外一个情况,当这个WH_MOUSE_LL是写在线程A的可执行模块中,而非一个DLL中,同样的它被线程A执行SetWindowsHookEx命令挂起为全局钩子,线程B还是在系统中执行,那么由于HOOK的回调函数不是写在DLL中,所以当线程B的消息队列再次接收到WH_LBUTTONDOWN消息,它就需要向线程A,SendMessage,由线程A来执行回调函数,这样理解可否?如果这时回调函数中再次向线程B SendMessage,那么就有可能造成线程A和线程B死锁,导致0x8001010D错误,是么?

解决方案 »

  1.   

    如果说,一个WH_MOUSE_LL被封装在一个DLL中,然后它被线程A调用,执行了SetWindowsHookEx命令作为一个全局钩子挂起。假设这时系统中存在一个正在执行的线程B,那么这个钩子所在的DLL就将被注入到线程B。然后当线程B的消息队列中收到了WM_LBUTTONDOWN消息,那么线程B就会调用Hook的回调函数,来处理这个消息。这个回调函数是在线程B中执行,与A无关,它占用的资源和CPU时间片都是B的,这样理解正确么?这时回调函数向线程B SendMessage会发生0x8001010D错误么?
    =======================
    应该是对的,DLL被注入到了B中,DLL就成了B的一部分了,当然也A无关了。因为DLL在B中执行,它是B的一部分,所以不会出问题。另外一个情况,当这个WH_MOUSE_LL是写在线程A的可执行模块中,而非一个DLL中,同样的它被线程A执行SetWindowsHookEx命令挂起为全局钩子,线程B还是在系统中执行,那么由于HOOK的回调函数不是写在DLL中,所以当线程B的消息队列再次接收到WH_LBUTTONDOWN消息,它就需要向线程A,SendMessage,由线程A来执行回调函数,这样理解可否?如果这时回调函数中再次向线程B SendMessage,那么就有可能造成线程A和线程B死锁,导致0x8001010D错误,是么?
    =====================================
    如果WH_MOUSE_LL钩子不是写在DLL中的话,它根本就不能被注入到B中去。换句话说,如果WH_MOUSE_LL不是写在DLL中的话,钩子只在本进程内有效
      

  2.   

    谢谢wltg2001的解答,关于前半段的解答我理解了,但是关于有半段的分析,我还是有点疑问的,我搜了一下资料,在“安装钩子一定要用dll么,可以只用exe来完成么?”http://topic.csdn.net/t/20040711/22/3165160.html的讨论中有两位曾提到
    WH_MOUSE_LL和WH_KEYBOARD_LL这两个钩子是可以在exe中完成全局钩子的安装的,就我自己的使用而言,我也的确在不写DLL的情况下成功的安装了WH_MOUSE_LL的全局钩子。
    所以我想问的是,在EXE安装钩子的情况下,这个钩子是如何工作的?
      

  3.   

    我有看过有文章说键盘钩子不用DLL,写EXE也行的,但是没有什么文章对原因解释得很清楚。
    就我的理解,之所以全局钩子要写成DLL,是因为DLL可以被注入到目标线程中去,而EXE应该不行。
    一个可能是EXE也有可能被加载到目标进程中去。
      

  4.   

        恩,那样的话,我可否这样理解,只要一个钩子按照了,那么它的回调函数所在的代码必定会被加载到被监视的线程中。
        像WH_MOUSE_LL和WH_KEYBOARD_LL这两个特殊的钩子虽然可以由EXE来安装,但是它的工作原理和DLL安装钩子是一样的。
      

  5.   

    我觉得应该是这样的,如果回调函数不被加载到被钩的线程中去,由于Win32的进程保护,它应该没办法工作。