2024年9月6日发(作者:)
维普资讯
VC++钩子机制
徐云剑
】.湖南涉外经济学院计算机系41 0205
2长沙航空职业技术学院4l01 24
系统垒局钩子一样必须放置于动态链接库
中,但是推荐的做法仍是将其放到动志链
在Windows系统中的应用
接库中去实现 这样的处理不仅能使钩子
为系统内的多个进程所访问.同时也可以
在系统中被直接调用。对干一个只供单进
程访问的钩子.还可以将其钩子处理过程
放在安装钩子的同一个线程内
由于垒局钩子具有相当的广泛性而且
在功能上完全覆盖了线程钩子,因此下面
就主要对应用较多的垒局钩子的安装与使
用进行讨论 前面已经提过,操作系统是通
过调用钩子链表开始处的第一个钩子处理
幽数而进行消息拦截处理的。因此,为丁设
置钩子.只需将回悯函数放置于链首HI】可,
撮作系统会使其首先被调用。茌具『奉实现
时由函数SetWindowsHookEx()负责将同
调函数放置于钩子链表的开始位置
SetWindowsHookEx0荫数原型声明如F:
1 钩子机制的实质
钩子的本质足一段用以处理系统消息
的程序,通过系绕调硐.将其挂人到系
蕺。最后,用一个获取最标信息的完莹程序
统。钩子的种娄有很多.每一种钩子负责
培于说明。
虢获并处理相戍的消息。钩子机制危许应
用程序截获并处理发往指定窗口的消扈域
均干机矗I牛毒蓑与卸藏;最=赫蛐干
特定事件,其监视的窗I=_=I即可以是本进程
鞠圈—■■■啊—■■嘲
内的也可以是H1其他进程所创建的 在特
Tie levi" 揖自甘n曲 噼of‘翻∞k№c} ln鞫
定的 息发出.井在到达目的窗 之前.
and曲e Iozding d幡 & ng 0f Hovk by VC++
钩子程序先行截获此消息搏得到对其的控
 ̄nder tt'e cI ulrB铷髓of wm 0ws吣帆 肿 f g.
制权。此时庄钩子函数巾就可以埘截获的
T ey a 恤d 甘 entre 0ce%。f曲喇n
消息进行备种修改处理.拄至强行终止该
咖u静 龆啦l酶妇 .
消息的继续传递
嘲■圜●■●雹霾■——●■童
任f.7-一个钩子都由系统米维护一个指
H M }嘲n;鲰埘: n4-删融氐呻艄t”咄
针列表(钩子链表),其指针指向钩子的
各个处理函数 蛀近安装的钩子放在裢的
开始,最早安装 寸钩于别放在最后.当钩
子监视的消息出现时,操作系统调用链表
开始处的翁一个钩子处理函数进行处理.
引言
也就是说最后加入的钩子优先获得控制
Windows操作器唬是建立在事件骓动
帆制之上的,系统各舒分之间的沟通也部
权 芷这里提到的钩子处理函数必须是一
cal尬ack function),而且
是通过消息的相互传递而实现的,但在通
十回调函数(
雨能定义为粪成员丽数 必须定义为普通
常情况下,应用程序只能处理米自进程内
部的消息或是从其他进程发过来的消息,
的C嫡数。
2
钩子的安装与卸载
女n果需要对在进程外传造的消息避行世截
钩 根据其对消座.监视范围的不同而
处理就必须采取一种被称为HOOK(钩
)的技术。钩子是Windows操作系统
舒为系统垒局钩子和线程局部钩子两大
中非常重要的一种系统接口.用它可以轻
类,其巾线程局部钩子只能监视本进程中
橙截获井处理在其他应用程序之间传递的
某个指定的线程.而垒局钩子则 对在当
消息.蚌由此可以完成一些普通应用程序 前系统下运行的所有线程进行监观。显
难以实现的特殊功能 甚于钩子在消息拦
然.线程钩子可以看作是垒局钩子的一个
戡处理中的强大功能,本文目 以Vc+斗6.
子集.垒局钩予虽然功能强大但同时实现
0为编程背景耐钩子的基本概念及其实现
起来也比较烦琐:其钩子函数的实现必须
过程展开讨论。为方便理解,和文章最后诬
封装在独立的动忐链接库中 匐 被各种
给出r一个简单的有荚鼠标钩于的应用示
相关联的应用程序所使用。
虽然对于线程局部钩子并不要求其象
例
机制的概念以礁甩Vct一宪现钩子的安装与卸
,
HHOOK SetWindowsHookEx cint
1look
HOoKPROC lDfn{
HINSTANCE hMod。
DWORD dwThreadld)l
其中:参毅idHook指定了钩子的类
型,总共有如下l 3种:
WH—cALLw DPR0C系统将消息
发送到指定窗口之前的 钩子”
wH—CALLWNDPROCRET消息已
经在窗口中处理的”钩子’
wH CBT基于计算机培 的钩子
WH_r3EBUG差错”钩子’
wH—FOREGROUNDIDLE前台空闲
窗口”钩子”
WHlGETMESSAGE剖殳消息投递的
”钩于’
W L』0URNAL1)r.AYBACK回放以
前通过WH—JOURNA1 RECORD”钩子”
记录的输人消息
WH
TOURN^LREcORD输人消息
记录”钩子”
wH KEYBOARD键盘消息 钩子”
wH—MoUSE鼠标消息”钩子”
wH—MSGFlLTER对话框、消启.
艋、菜单或滚动条辅人消息”钩子
WH SIIELL外壳”钩子
wH—SYsMsGFILTER系统消息”钩
.
子
参数l pfn为指向钩子处理函数附指
针 即回调函数的首地址 参数hMod则
标识了钩子处理函数所处模块的句柄t第
阳个参数dwThreadld指定被监视的线
程.如果明确指定丁某个线程的II)就只监
视该线程.此时的钩子即为线程钩子t如
果该参数被设置为0,则表示此钩子为监
视系统所有线程的垒局钩子。此函数在执
维普资讯
行完后将返回一个钩子句柄。
def文件将其属性设置为读写共享:
茸pragnna data seg(”TestData’ )
虽然对于线程钩子并不要求其象全局
HWND alhPrevTarWnd=NULL;/
钩1J一样必须放置十动态链接库中,但是
推荐其也在动态链接库巾实现。 为这样
/窗口句柄
HWND glhHook=NULL;//鼠标
的处理不仅可使钩子可为系统内的多个进
程访问,也可以在系统中被直接调用,而且
钩子句柄
HINSTANCE glhInstance-NULL:/
对于一个只供单进程访问的钩子,还可以
I 实例句柄
将其钩子处理过程放在安装钩子的同一个
/DI
拄pragma data
seg()
线程内,此时SetWindowsHookEx()函数
的第 个参数也就是该线程的实例句柄。
char szCaption【1 00];
//取目标窗口标题
GetWindowText(glhTargetWnd
s ̄Caption,100);
【
J
1
r
//继续传递消息
return CallNextHookEx((HHOOK)
存SetWindowsHookEx()f,i数完成对
钩1J的安装后,如果被监视的事件发生,系
统屿上会调用位于相应钩子链表开始处的
钩子处理函数进行处理,每一 个钩子处理
函数在进行相应的处理时都要考虑是否需
要把事件传递给下一个钩子处理函数。如
果要传递,就通过函数CallNestHookEx()
来解决。尽管如此,在实际使用时还是强烈
推荐无论是否需要事件传递都在过程的最
后渊用一次CallNextHookEx()函数,否
则将会引起一些无法预知的系统行为或是
系统锁定。该函数将返回位十钩子链表中
的卜一个钩子处理过程的地址,至十具体
的返回值类型则要视所设置的钩子类型而
定。该函数的原型声明如 :
I RESULT CallNextHOOkEX
(HHOOK hhk;int nCode;WPARAM
wParam;LPARAM 1Param);
其中,参数h h k 为由
SetWindowsHookEx()函数返回的当前钩
了句柄;参数nCode为传给钩子过程的事
件代码;参数wParam和1Param则为传
给钩子处理函数的参数值,其具体含义同
设置的钩子类型有关。
最后,由于安装钩子对系统的性能肯
一
定的影响,所以在钩子使用完毕后应及
时将其卸载以释放其所占资源。释放钩子
的函数为UnhookWindowsHookEx(),该
函数比较简单只有一个参数用于指定此前
由SetWindowsHookEx()函数所返回的钩
子句柄,原型声明如下:
BOOL UnhookWindowsHookEx
(HHOOK htlf ̄);
3
、
鼠标钩子的简单示例
最后,为更清楚展示H00K技术住
VC编程中的应用,给出一个有关鼠标钩
子使用的简单示例。住钩子设置时采用的
是全局钩子。下面就对鼠标钩子的安装、
使用以及卸载等过程的实现进行讲述:
由于本例程需要使用全局钩子,因此
首先构造全局钩子的载体 动态链接库。
考虑到win32 DLL与win16 DLL存在
的差别,住Win32环境下要在多个进程问
共享数据,就必须采取一些措施将待共享
的数据提取到一个独立的数据段,并通过
SECTIONS//def文件中将数据段
glhHook,nCode,wParam,1Param);
TestData设置为读写共享
TestData READ WRITE SHARED
在安装全局鼠标钩子时使用函数
SetWindowsHookEx(),并设定鼠标钩子
最 后 , 调 用
的处理函数为MouseProc(),安装函数返
UnhookWindowsHookEx()函数完成对钩
回的钩了.句柄保存于变量glhHook中:
子的卸载:
void Start}took(HWND hWnd)
g l h H O O k一(I{W N D) ……
SetWindowsHookEx(WH MOUSE, UnhookWindowsHookEx((HHOOK)
MouscProc,glh[nstance,0); glhHook);
鼠标钩子安装好后,住移动、点击 现在完成的是鼠标钩子的动态链接
鼠标时将会发出鼠标消启、,这些消启、均经
库,经过编译后需要经应用程序的调用才
过消息处理函数MouseProc()的拦截处理。
能实现对当前系统下各线程间鼠标消启、的
在此,每当捕获到系统各线程发出的任何
拦截处理。这部分同普通动态链接库的使
鼠标消息后首先获取当前鼠标所在位置下 用没有任何区别,在将其加载到进程后,
的窗口句柄, 并进一步通过
首先调用动态链接库的StartHook()lN数安
GetWindowText()函数获取到窗口标题。
装好钩子,此时即可对系统下的鼠标消息
在处理函数完成后, 通过
实施拦截处理,在动态链接库被卸载即终
CallNextHookEx()函数将事件传递到钩子 止鼠标钩子时通过动态链接库中的
列表中的下・个钩子处理函数:
StopHook()函数卸载鼠标钩子。
I.RESU LT WINAPI MouseProc(int
经上述编程,在安装好鼠标钩子后,
nCode.WPARAM wParam.LPARAM
鼠标在移动到系统任意窗口上时,马上就
1Param)
会通过对鼠标消息、的拦截处理而获取到当
前窗口的标题。实验证明此鼠标钩子的安
L P M O U S E H O O K S T R U C T
装、使用和卸载过程是正确的。
pMouseHook-(MOUSEHOOKSTRU CT
FAR )1Param:
if(nCode>=0)
毒镑哮 ;E豫 萼鼍蘸 。 。l 毒 ≯ 磊
H W N D
[1]张元良,李世强,浅谈Win:32系统钩子机
hTargetWnd=pMouseHook一>hwnd;
制 [J].计算机应用2001.4
[2]汪小龙.Visual c++与Windows编程[M].
//取目标窗口句柄
HWND ParentWnd=glhTargetWnd;
南京大学出版社
[5]辛长安,梅林.vc++编程技术与难点剖
While(ParentWnd!=NULL)
f
析 .清华大学出版社
t
glhTargetWnd—ParentWnd
佧薰 誊鞠 妊喜慕 。
//取应用程序主窗口句柄
徐云剑(1 977--),男湖南益阳人,湖南
涉外经济学院计算机系助教,湖南师范
P a r e n t W n d—G e t P a r e n t
(glhTargetWnd);
大学物理与信息学院在读研究生,研究
方向:计算机软件与理论。
if(glhTargetWnd!一glhPrevTarWnd)
l47
本文发布于:2024-09-06 21:14:43,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/1725628483362998.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |