一 何时用到钩子?(when)
Windows操做系统是创建在事件驱动的消息处理机制之上,系统各部分之间的沟通也都是经过消息的相互传递而实现的。一般状况下,应用程序只能处理当前进程的消息,若是须要对其它进程的消息进行拦截处理就必须采钩子技术。
二 什么是钩子?(what)
钩子其实是一段用以处理系统消息的程序(钩子函数),经过系统调用,将其挂入到系统。每当特定的消息发出,在没有到达目标窗口前,钩子程序就先捕获该消息,即钩子函数先获得控制权。在钩子函数中,能够加工处理(改变)该消息,也能够不做处理而继续传递该消息,还能够强制结束消息的传递。钩子函数是一个应用程序定义的回调函数,不能定义成某个类的成员函数,只能定义为普通的C函数。
三 什么是钩子链表?(what)
系统提供多种不一样类型的钩子用于处理不一样的消息。在某一时刻可能有多个进程安装了相同类型的钩子,即同一种钩子有多个不一样的钩子处理函数。这多个不一样的钩子处理函数的指针构成了钩子链表,由操做系统维护。当某种类型的消息发生时系统向该类型的钩子链表的第一个函数发送该消息,在第一函数处理完该消息后由该函数向链表中的下一个函数传递消息,依次向下。若是链中某个函数没有向下传送该消息,那么链表中后面的函数将得不到此消息。(对于某些类型的钩子,无论钩子链中的函数是否向下传递消息,与此类型钩子关联的全部钩子函数都会收到系统发送的消息)最近安装的钩子放在链的开始,而最先安装的钩子放在最后,也就是后加入的先得到控制权。系统并不要求钩子子程的卸载顺序必定得和安装顺序相反。每当有一个钩子被卸载,系统便释放其占用的内存,并更新整个钩子链表。若是应用程序安装了钩子,可是在还没有卸载钩子以前就结束了,那么系统会自动卸载钩子。
四 钩子的做用范围(where)
一共有两种范围(类型)的钩子:局部的和远程的。
1.局部钩子仅钩挂您本身进程的事件。
2.远程的钩子还能够将钩挂其它进程发生的事件。
远程的钩子又有两种:
2.1 基于线程的它将捕获其它进程中某一特定线程的事件。简言之,就是能够用来观察其它进程中的某一特定线程将发生的事件。
2.2系统范围的将捕捉系统中全部进程将发生的事件消息。
五 钩子的使用步骤(How)
1 安装钩子
SetWindowsHookEx函数能够把应用程序定义的钩子函数安装到系统中。
HHOOK SetWindowsHookEx(
int idHook ; // 指定钩子的类型
HOOKPROC lpfn; //钩子函数的地址。若是是远程钩子,钩子函数必须放在一个DLL中。
HINSTANCE hMod; // 钩子函数所在的DLL的实例句柄。局部的钩子,该参数为NULL。
DWORD dwThreadID; //指定要为哪一个线程安装钩子。若该值为0被解释成系统范围内的。
);
2 定义钩子函数
钩子函数的通常形式以下:
LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
// 处理该消息的代码 …..
Return ::CallNextHookEx(hHook,nCode,wParam,lParam);
}
HookProc是钩子函数的名称。nCode参数是Hook代码,钩子函数使用这个参数来肯定任务,它的值依赖于Hook的类型。wParam和lParam参 数的值依赖于Hook代码,可是它们典型的值是一些关于发送或者接收消息的信息。由于系统中可能会有多个钩子的存在,因此要调用那个 CallNextHookEx函数把消息传到链中下一个钩子函数。hHook参数是安装钩子时获得的钩子句柄(SetWindowsHookEx的返回值)。
3 卸载钩子
要卸载钩子,能够调用UnhookWindowsHookEx函数。
BOOL UnhookWindowsHookEx(HHOOK hhk); // hhk 为要卸载的钩子的句柄
注意:
安装钩子的代码能够在DLL模块中,也能够在主模块中,可是通常在DLL里实现它,主要是为了使程序更加模块化。
六 钩子的几个实例
七 钩子的几点总结
1.钩子是用截获系统中的消息流。利用钩子,能够处理任何感兴趣的消息,包括其余进程的消息。
2.截获消息后,用于处理消息的子程序叫作钩子函数,它是应用程序自定义的一个函数,在安装钩子时要把这个函数的地址告诉系统。
3.在操做系统中,同一时间可能有多个进程安装了同一种类型的钩子,即会有多个钩子函数,多个钩子函数在一块儿组成钩子链。因此在处理截获到的消息时,应该把消息事件传递下去,以便其余钩子函数也有机会处理这一消息。
4.钩子会使得系统变慢,由于它增长了系统对每一个消息的处理量。仅应该在必要时才安装钩子,并且在不须要时应尽快移除。
模块化