孙鑫VC++深入详解(11):HOOK过程

时间:2022-06-12 21:12:06

1、

钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。即钩子机制允许应用程序截获处理其它进程的window消息或特定事件,比如鼠标消息、键盘消息、对话框或菜单栏或滚动条中输入事件。

SetWindowsHookEx用来安装一个钩子过程。
HHOOK WINAPI SetWindowsHookEx(
_In_  int idHook,
_In_  HOOKPROC lpfn,
_In_  HINSTANCE hMod,
_In_  DWORD dwThreadId
);
idHook:钩子过程的类型:

WH_CALLWNDPROC:安装一个挂钩处理过程,在系统将消息发送至目标窗口处理过程之前,对该消息进行监视,详情参见CallWndProc钩子过程.

WH_MOUSE:安装一个挂钩处理过程,对鼠标消息进行监视. 详情参见MouseProc钩子过程.

WH_KEYBOARD:安装一个挂钩处理过程对击键消息进行监视. 详情参见KeyboardProc钩子过程.

WH_MSGFILTER: 安装一个挂钩处理过程,以监视由对话框、消息框、菜单条、或滚动条中的输入事件引发的消息.详情参见MessagePorc钩子过程.

WH_CALLWNDPROCRET:安装一个挂钩处理过程,它对已被目标窗口处理过程处理过了的消息进行监视,详情参见CallWndRetProc 挂钩处理过程.

WH_CBT:安装一个挂钩处理过程,接受对CBT应用程序有用的消息,详情参见CBTProc 挂钩处理过程.

WH_DEBUG:安装一个挂钩处理过程以便对其他挂钩处理过程进行调试, 详情参见DebugProc挂钩处理过程.

WH_FOREGROUNDIDLE:安装一个挂钩处理过程,该挂钩处理过程当应用程序的前台线程即将进入空闲状态时被调用,它有助于在空闲时间内执行低优先级的任务.

WH_GETMESSAGE:安装一个挂钩处理过程对寄送至消息队列的消息进行监视,详情参见GetMsgProc 挂钩处理过程.

WH_JOURNALPLAYBACK:安装一个挂钩处理过程,对此前由WH_JOURNALRECORD 挂钩处理过程纪录的消息进行寄送.详情参见JournalPlaybackProc挂钩处理过程.

WH_JOURNALRECORD:安装一个挂钩处理过程,对寄送至系统消息队列的输入消息进行纪录.详情参见JournalRecordProc挂钩处理过程.

WH_KEYBOARD_LL:此挂钩只能在Windows NT中被安装,用来对底层的键盘输入事件进行监视.详情参见LowLevelKeyboardProc挂钩处理过程.

WH_MOUSE_LL:此挂钩只能在Windows NT中被安装,用来对底层的鼠标输入事件进行监视.详情参见LowLevelMouseProc挂钩处理过程.

WH_MSGFILTER:安装一个挂钩处理过程,以监视由对话框、消息框、菜单条、或滚动条中的输入事件引发的消息.详情参见MessageProc挂钩处理过程.

WH_SHELL:安装一个挂钩处理过程以接受对外壳应用程序有用的通知, 详情参见ShellProc挂钩处理过程.

WH_SYSMSGFILTER:安装一个挂钩处理过程,以监视由对话框、消息框、菜单条、或滚动条中的输入事件引发的消息.这个挂钩处理过程对系统中所有应用程序的这类消息都进行监视.详情参见SysMsgProc挂钩处理过程.

lpfn:函数指针,指向钩子过程,如MouseProcCallWndProc

hMod:钩子过程所在的DLL的句柄。如果第四个参数dwThreadId指定的线程由当前进程创建,且钩子过程定义在当前进程相关的代码中则hMod必须为NULL。

dwThreadId:与钩子过程相关的线程ID。为0即为安装的钩子过程与桌面上运行的所有线程相关。

函数调用成功返回所安装的钩子过程的句柄,否则返回NULL。

可以安装过个钩子过程,后安装的钩子过程总是在前面。

程序退出的时候最好调用UnhookWindowsHookEx(HOOK hhk),移除安装的钩子过程,函数参数为安装的钩子过程的句柄,即SetWindowsHookEx()的返回值。

钩子过程的声明形式如下:

LRESULT CALLBACK HookProc
(
   int nCode,
   WPARAM wParam,
   LPARAM lParam
);

HookProc是回调函数名即钩子过程名。
nCode参数是Hook代码,Hook子程使用这个参数来确定任务。这个参数的值依赖于Hook类型,每一种Hook都有自己的Hook代码特征字符集。
wParam和lParam参数的值依赖于Hook代码,但是它们的典型值是包含了关于发送或者接收消息的信息。
例如:

孙鑫VC++深入详解(11):HOOK过程

孙鑫VC++深入详解(11):HOOK过程

在钩子过程中对消息处理完成后,可以调用CallNextHookEx()把消息传递给下一个钩子过程。

LRESULT WINAPI CallNextHookEx(HHOOK hhk,  int nCode, WPARAM wParam,  LPARAM lParam);

其第一个参数为当前钩子过程句柄,即SetWindowHookEx()的返回值,其余三个参数与钩子过程参数相同。

如果钩子过程返回非0值,表示已经对当前消息进行了处理,这样,这个消息就不会再传递给目标窗口了。因此,如果钩子过程中对消息进行了处理,就应返回一个非0值,否则建议调用CallNextHookEx()并返回该函数的返回值。

2、

屏蔽所有鼠标消息:

HHOOK g_hMouse = NULL;

LRESULT CALLBACK MouseProc(
int nCode,
WPARAM wParam,
LPARAM lParam
)
{
return 1;
}

BOOL CDlgDlg::OnInitDialog()
{
......

g_hMouse = SetWindowsHookEx(WH_MOUSE, MouseProc, NULL, GetCurrentThreadId());

return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
仅屏蔽ESC键:

HHOOK g_hKeyboard = NULL;

LRESULT CALLBACK KeyboardProc(
int code,
WPARAM wParam,
LPARAM lParam
)
{
if(VK_ESC == wParam)
return 1;
else
return CallNextHookEx(g_hKeyboard, code, wParam, lParam);
}

BOOL CDlgDlg::OnInitDialog()
{
......

g_hKeyboard = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, NULL, GetCurrentThreadId());

return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
屏蔽Alt+F4组合键:
HHOOK g_hKeyboard = NULL;

LRESULT CALLBACK KeyboardProc(
int code,
WPARAM wParam,
LPARAM lParam
)
{
if(VK_F4==wParam && (1==(lParam>>29&1)))
return 1;
else
return CallNextHookEx(g_hKeyboard, code, wParam, lParam);
}

BOOL CDlgDlg::OnInitDialog()
{
g_hKeyboard = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, NULL, GetCurrentThreadId());

return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
3、

如果想要处理其他进程的消息,即安装一个全局钩子,那么安装钩子过程的代码必须放到动态链接库(DLL)中实现,且将SetWindowsHookEx()的第三个参数指定为安装钩子过程的代码所在的DLL的句柄,将第四个参数设为0。