📄 20.1 hook 编程.txt
字号:
20.1 HOOK 编程
20.1.1 基本知识
首先回顾一下第一章中讲述的Windows消息传递机制。当在应用程序窗口中按下鼠标左键时,操作系统会感知到这一事件,然后产生鼠标左键按键消息,接着把此消息放到应用程序的消息队列中,应用程序通过调用GetMessage函数取出消息,然后调用 Dispatch Message函数将这条消息调度给操作系统,操作系统会调用在设计窗口类时指定的应用程序窗口过程对这一消息进行处理。这一过程就是所有运行在 Windows平台下的窗口应用程序的消息传递过程,如图20.1所示。
图 20.1 W.ndows应用程序的消息传递过程
在实际应用中,有时可能需要对某个特殊消息进行屏蔽,例如,我们开发了一个应用程序,不想让它对键盘上的回车键和空格键做出响应,就需要截获所有消息,然后进行判断,如果是回车或空格按键消息,就将这两种消息屏蔽掉,也就是说,不让这样的消息继续传递下去。另一种情况,例如,我们开发了一个安装程序,在安装过程中希望安装程序不能响应用户的鼠标和键盘的按键消息,以免影响软件的安装过程,那么也需要截获这两类消息,然后让它们不再继续向下传递。
为了实现这一功能,可以安装一个 HOOK过程,称为钩子过程。操作系统在传递消息时,将我们感兴趣的消息先传递给 HOOK过程,在此函数中进行检查,然后再决定是否放行该消息。这就好像逃犯在逃亡时可能会经过许多路段,为了抓住他,警察要在某些地方设置检查站,以便检查过往的车辆和行人。我们可以把车辆和行人看作是消息,检查站就是 HOOK过程。如果在某个检查站发现了这个逃犯,就会把他抓起来。这样就相当于阻止了逃犯的逃亡过程,让他无法再继续逃亡下去了。这个道理和钩子过程是一样的,操作系统将我们感兴趣的消息都先交给钩子过程,后者实际上就是一个函数,在此函数中进行判断,如果是我们希望屏蔽掉的消息,那么就直接处理掉,不让它再继续向下传递。如果是其他我们不感兴趣的消息,就直接放弃对它们的处理。这就好像对于那些不是逃犯的行人和车辆一样,警察将会让他们继续前进。
在程序中实现时,可以通过 SetWindowsHookEx函数来安装一个钩子过程。该函数的声明如下所示 :
HHOOK SetWindowsHookEx(
int idHook,
.
HOOKPROC lpfn,
HINSTANCE hMod,
DWORD dwThreadid
,
该函数各个参数的含义如下所述:
. idHook
指定将要安装的钩子过程的类型,此参数可以是表 20.1列出的值之一 :
表 20.1 idHook参数的取值
idHook取值 说明
WH_CALLWNDPROC 安装一个钩子过程,在操作系统将消息发送到目标窗口处理过程之前,对该消息进行监视
WH_CALLWNDPROCRET 安装一个钩子过程,它对已被目标窗口过程处理过了的消息进行监视
WH_CBT 安装一个钩子过程,接受对 CBT应用程序有用的消息
WH_DEBUG 安装一个钩子过程,以便对其他钩子过程进行调试
WH_FOREGROUNDIDLE 安装一个钩子过程,该钩子过程当应用程序的前台线程即将进入空闲状态时被调用,它有 助于在空闲时间内执行低优先级的任务
WH_GETMESSAGE 安装一个钩子过程对发送到消息队列的消息进行监视
WH_JOURNALPLAYBACK 安装一个钩子过程,对此前由 WH_JORNALRECORD钩子过程记录的消息进行发送
WH_JOURNALRECORD 安装一个钩子过程,对发送到系统消息队列的输入消息进行记录
WH KEYBOARD 安装一个钩子过程,对键盘按键消息进行监视
WH_KEYBOARDALL 此钩子过程只能在 Windows NT中安装,用来对底层的键盘输入事件进行监视
WH_MOUSE 安装一个钩子过程,对鼠标消息进行监视
WH MOUSE LL 此钩子过程只能在 Windows NT中安装,用来对底层的鼠标输入事件进行监视
WH_MSGFll-TER 安装一个钩子过程,以监视由对话框、消息框、菜单条,或滚动条中的输入事件引发的消息
WH SHELL 安装一个钩子过程,以接受对外壳应用程序有用的通知
WH SYSMSGFILTER 安装一个钩子过程,以监视囱对话框、消息框、菜单条,或滚动条中的输入事件引发的消 息。该钩子过程对系统中所有应用程序的这类消息都进行监视
.
. lpfn
指向相应的钩子过程。如果参数 dwThreadld为 0,或者指定了一个其他进程创建的线程之标识符,那么参数 lpfn必须指向一个位于某动态链接库中的钩子过程。否则,参数 lp臼可以指向当前进程相关的代码中定义的一个钩子过程。
. h岛10d
指定 lpfn指向的钩子过程所在的 DLL的句柄。如果参数 dwThreadld指定的线程由当前进程创建,并且相应的钩子过程定义于与当前进程相关的代码中,那么必须将参数恼10d设置为 NULL。
. dwThreadld
指定与钩子过程相关的线程标识。如果其值为 0,那么安装的钩子过程将与桌面上运行的所有线程都相关。
SetWindowsHookEx函数的作用是安装一个应用程序定义的钩子过程,并将其放到钩子链中。为了让读者更好地理解钩子链的概念,让我们再看看前面所举的逃犯的例子。警察在抓捕逃犯时,可以在多个地方设置检查站,逐一对车辆和行人进行排查,同样地,应用程序也可以安装多个钩子过程,对我们感兴趣的多个消息逐一进行检查。这样,多个钩子过程就形成了钩子链,要注意的是,最后安装的钩子过程总是排列在该链的前面。
如果调用成功, SetWindowsHookEx函数的返回值就是所安装的钩子过程的句柄,否则返回 NULL。另外,安装的钩子过程可以与某个特定线程相关,也可以和所有线程相关,取决于 dwThreadld这一参数的取值。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -