我想编一个截获一个特定窗口键盘消息的HOOK,我把钩子函数放在一个
DLL里面,DLL的代码:#include <windows.h>
#include "hookdll.h"#pragma data_seg ("shared")
HHOOK oldhook=NULL;
#pragma data_seg()
#pragma comment(linker,"/SECTION:shared,RWS")int WINAPI DllMain(HINSTANCE hInstance,DWORD fdwReason,PVOID pvReserved)
{
return true;
}EXPORT LRESULT CALLBACK MyProcKey(int nCode, WPARAM wParam, LPARAM lParam)
{
        //我在这儿什么也没做,只是把消息传递到下一个钩子
return CallNextHookEx(oldhook,nCode,wParam,lParam);
}EXPORT void CALLBACK SetHook(HHOOK hhk)
{
oldhook=hhk;
}我在主程序的WM_CREATE消息中调用了设置钩子的函数:
hk=::SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)MyProcKey,::GetModuleHandle("hookdll.dll"),::GetWindowThreadProcessId(hookwnd,NULL));
然后调用DLL里面的SETHOOK函数,把DLL中的全局变量赋值为hk,既SETWINDOWSHOOK的返回值但是当我运行程序的时候,每当我按下键盘,被 截获消息的窗口就出错
调式了一下,发现,这个被截获消息的窗口每当收到WM_KEYDOWN消息的时候就发生
violation,
请问高手,这是为什么,我哪儿编错了?

解决方案 »

  1.   

    把SetWindowsHookEx放到Dll裏面去調用,不要再EXE中調用。
      

  2.   

    这是由于挂钩是作为一种共享资源使用的,安装挂钩指定的线程ID很有可能是本进程以外的线程,所以挂钩的时候就要求挂钩函数必须在库(DLL)中使用。
    由于Win32进程的虚拟性,如果你把挂钩函数放在EXE之中,那么它肯定无法突破本进程的限制,也就无法挂在别的进程上了。
      

  3.   

    哦,原来是这样,
    那下面这段代码是必要的吗?
    #pragma data_seg ("shared")
    HHOOK oldhook=NULL;
    #pragma data_seg()
    #pragma comment(linker,"/SECTION:shared,RWS")
    也就是说,我可不可以不使用共享内存,而使用普通的全局变量来保存钩子句柄?
      

  4.   

    还有,如果我在EXE程序中加载钩子的话,可以响应DESTROY消息把钩子去掉,如果在DLL中
    我该怎么去掉这个钩子呢?在DLL里面加一个UNHOOK的函数?还是另外有办法?
      

  5.   

    SetWindowsHookEx
    UnhookWindowsHookEx
    放在DLL中,上面代碼是必要的,進程閒共享數據
      

  6.   

    UnhookWindowsHookEx
    具体在什么时候调用呢?是不是要在DLLMAIN里面判断调用的条件啊?
      

  7.   

    关于共享段的问题,你可以参考
    http://home.ncust.edu.cn/~titilima/readarticle.php?id=23
      

  8.   

    是在结束DLL进程的时候释放,还是在DLL里面专门写个函数来释放?
      

  9.   

    有你自由选择,不过有一点是一定的——UnhookWindowsHookEx一定要写在DLL中。
      

  10.   

    哦,谢谢.
    To 李马 :
           上次看到一篇关于QQ病毒的文章,请问,那个程序在什么时候设置钩子呢?设置钩子要一个窗口句柄,只有在一个发送消息的窗口出现的时候才有这个句柄.是不是要在程序中陷入死循环,直到找到那个窗口句柄?这种方法类似查询方式,有没有其他方法,类似中断方式的?