一.钩子过程就像是一个监听|侦查者,os先把消息发给钩子过程,钩子捕获消息后再决定对消息的处理
二.安装钩子过程的原型说明
HHOOK SetWindowsHookEx( int
idHook
, HOOKPROC
lpfn
,
HINSTANCE hMod, DWORD dwThreadId );
idHook是指定安装钩子过程的类型,如WH_MOUSE
lpfn是指向相应的钩子过程,若参数dwThreadId为0,或者指向其他进程创建的线程表示符号,则lpfn应该指向动态链接库中的钩子过程
hMod指向lpfn所在的dll的句柄,if dwThreadId由当前进程创建 and 钩子过程在当前进程相关代码中,hMod应该是NULL
dwThreadId 指向与钩子过程相关的进程,若为0,则钩子与桌面上运行的所有进程都相关
返回值:是所安装的钩子过程的句柄,返回非零表示已经对消息进行处理,如果返回0,则系统把消息传递给目标窗口过程
安装钩子的一个例子:
HHOOK g_hMouse=NULL;
LRESULT CALLBACK MouseProc(
int nCode, // hook code
WPARAM wParam, // message identifier
LPARAM lParam // mouse coordinates
)
{
return 1;
}
g_hMouse=SetWindowsHookEx(WH_MOUSE,MouseProc,NULL,GetCurrentThreadId() );
三。钩子链的概念:可以安装多个钩子进程形成钩子链,最后安装的钩子总在链的前面,钩子过程完成对消息的处理后可以调用LRESULT CallNextHookEx( HHOOK
hhk
,
int nCode, WPARAM wParam, LPARAM lParam );
消息传递给钩子链的下一个钩子过程
Hhk
指定当前钩子过程句柄,就是调用SetWindowsHookEx返回值
四,屏蔽组合键消息
LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
If( VK_F4==wParam && ( 1==(lParam>>29 & 1) ) )
lParam的第29位:如果alt按下,则其值为1,否则为0
五,捕获消息后重发另一个消息
在消息捕获后可以用SendMessage来发送消息
SendMessage有三个版本,分别是全局的,CWindow的,Cwnd的
钩子是全局函数,应该调用全局的sendmessage
SendMessage的第一个参数是目标窗口句柄,我们应该用一个全局变量来保存他,定义全部变量g_hWnd,在OnInitDialog中把m_hWnd赋值给g_hWnd
然后::SendMessage(g_hWnd,WM_CLOSE,0,0);
六,全局钩子,前面我们介绍的钩子全部是当前进程内的,驻于进程内存内。只能处理当前进程的消息,如果我们想屏蔽当前正在运行的所有进程的的鼠标键盘消息,那么钩子过程必须放到动态链接库中。
SetWindowsHookEx的第三个参数要求指定钩子过程所在dll模块句柄,两种方式实现,首先是用DllMain,定义全局实例g_hInst,然后在DllMain函数中保存系统传递过来的Dll模块句柄
HINSTANCE g_hInst;
BOOL WINAPI DLLMain( HINSTANCE hinstDLL,DWORD fdwReason, LPVOID lpvReserved )
{
G_hInst=hinstDLL;
}
Void SetHook()
{
g_hMouse=SetWindowHookEx( WH_MOUSE,MouseProc,g_hInst,0 );
}
另一种方法是调用GetModuleHandle函数来得到指定dll模块句柄,如果指定的模块已经被映射到当前进程中了,那么该函数返回该指定模块的句柄,模块名是.exe或者.dll
七,模块定义文件
LIBRARY Hook //指定dll内部名称
EXPORTS //指定该dll导出函数名称,从dll导出函数是有序号的,可以自己制定序号,用@ith
SetHook @2
八,dll的使用,加载dll,调用dll里的函数
把dll文件复制到客户程序目录下
在调用dll的函数之前声明
_declspec(dllimport) void SetHook();
表明SetHook是从dll的lib文件中输入的,为了能连接上Hook.dll,需要在link选项卡中输入 ???hook.lib,这样就可以调用dll中的函数了
九,钩子的卸载
UnhookWindowsHookEx(g_hMouse);
十,深入探讨
当dll被多个进程使用时,这些进程可以共享dll的代码和数据。但似乎并没有共享,如果多个进程可以共享同一份可写入数据的话是很危险的。假设dll中数据区有一个指针类型变量,如果第一个进程修改了这个变量的地址值,第二个进程如果共享这个变量的话,这个修改后的地址可能指向其他数据。
为了解决这个问题,windows采用写入时复制机制,当某进程要修改数据时,将复制一片完全一样的dll数据空间,这样你访问你的,别人访问的还是修改前的数据。