gpt4 book ai didi

c++ - WinApi:消息循环可以被异步过程调用中断吗?

转载 作者:行者123 更新时间:2023-11-30 01:41:28 24 4
gpt4 key购买 nike

以下代码注册了一个低级鼠标钩子(Hook)来全局监控鼠标事件。
这是我能得到的最简单的工作示例。
使用 VC++ 2010 编译:cl test.cpp/link/entry:mainCRTStartup/subsystem:windows

#include <windows.h>

HWND label1 ;

//THE HOOK PROCEDURE
LRESULT CALLBACK mouseHookProc(int aCode, WPARAM wParam, LPARAM lParam){
static int msgCount = 0 ;
static char str[20] ;
SetWindowText( label1, itoa(++msgCount, str, 10) ) ;
return CallNextHookEx(NULL, aCode, wParam, lParam) ;
}

int main(){
/**/// STANDARD WINDOW CREATION PART //////////////////////////////////////////////////////
/**/
/**/ WNDCLASSEX classStruct = { sizeof(WNDCLASSEX), 0, DefWindowProc, 0, 0, GetModuleHandle(NULL), NULL,
/**/ LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_BTNFACE+1), NULL, "winClass", NULL } ;
/**/ RegisterClassEx(&classStruct) ;
/**/
/**/ HWND mainWin = CreateWindow("winClass", "", 0, 200,200, 100,100, NULL, NULL, NULL, NULL) ;
/**/ ShowWindow(mainWin, SW_SHOWDEFAULT) ;
/**/
/**/ label1 = CreateWindow("static", "0", WS_CHILD, 5,5, 80,20, mainWin, NULL, NULL, NULL) ;
/**/ ShowWindow(label1, SW_SHOWNOACTIVATE) ;
/**/
/**/// END OF WINDOW CREATION PART ////////////////////////////////////////////////////////

//HOOK INSTALATION
HHOOK hookProc = SetWindowsHookEx(WH_MOUSE_LL, mouseHookProc, GetModuleHandle(NULL), 0) ;

//MESSAGE LOOP
MSG msg ;
while( GetMessage(&msg, NULL, 0, 0) ){
TranslateMessage(&msg) ;
DispatchMessage(&msg) ;
}

UnhookWindowsHookEx(hookProc) ;
}

这是基本的一个线程、一个窗口、一个消息泵示例。除了鼠标 Hook 。

我怀疑这段代码的作用与我在 SO、MSDN、论坛、博客等中反复阅读的两件事相矛盾。

  1. 全局 Hook 程序必须驻留在 DLL 中
    MSDN documentation for SetWindowsHookEx通过说来证实这一点:

    If the dwThreadId parameter is zero, the lpfn parameter MUST point to a hook procedure in a DLL

  2. GUI 线程(带有消息泵的线程)不能被中断,因为 GetMessase 的等待状态不可警报。这意味着当 GetMessage 阻塞等待更多消息时,它无法接收到中断其等待状态的信号。

但是,这里看不到任何 DLL,并且 Hook 程序必须中断线程,否则程序将无法运行,但确实如此(我假设该程序中只有一个线程)。

所以要么我完全误解了这两点,要么这段代码的工作方式与我预期的异步过程调用方法不匹配。

不管怎样,我对这里发生的事情一无所知。

请您解释一下这段代码是如何工作的。
是单线程程序吗?
钩子(Hook)程序是否中断了线程?
以上两点中有哪一点是真的吗?

最佳答案

仅当需要将钩子(Hook)注入(inject)另一个进程时,钩子(Hook)过程才必须在 DLL 中。对于 WH_MOUSE_LL

However, the WH_MOUSE_LL hook is not injected into another process. Instead, the context switches back to the process that installed the hook and it is called in its original context. Then the context switches back to the application that generated the event.

所以这里不需要DLL(what ??),钩子(Hook)程序也可以放在EXE中。

Is it a single-thread program?

一般来说是的。如果不考虑可能的系统工作线程,则所有消息和 Hook 都在第一个线程的上下文中调用

Is the hook procedure interrupting the thread?

来自 MSDN

This hook is called in the context of the thread that installed it. The call is made by sending a message to the thread that installed the hook. Therefore, the thread that installed the hook must have a message loop.

所以可以说mouseHookProc里面叫GetMessage称呼。此函数在内核中等待消息。当系统需要调用 Hook 程序时,它通过 KiUserCallbackDispatcher 执行此操作称呼。“中断线程”- 中断是什么意思?

1.) 如本例所示,这是不正确的。钩子(Hook)过程必须在 DLL 中,只有当钩子(Hook)必须在接收消息的线程的上下文中调用时,所以在任意进程上下文中 - 在这种情况下我们需要将代码注入(inject)另一个进程 - 因为这个和 DLL 需要。如果我们总是在自进程上下文中调用 - 没有注入(inject),不需要 DLL

2.) GetMessage真正等待不处于可警报状态,因此当代码在 GetMessage 中等待时,任何 APC 都无法交付,但这里的APC绝对不相关。 APC 和windows messaging 不同的特性。当然存在和相似点。对于 APC 和某些 Windows 消息传递,线程必须在内核中等待。对于处于可警报状态的 APC,对于 GetMessage 中的 Windows 消息或 PeekMessage .用于 APC 交付系统调用 KiUserApcDispatcher , 对于 Windows 消息 KiUserCallbackDispatcher .两者都是来自内核模式的回调,但它是在不同的条件下调用的


当代码执行可以在任意位置中断并且中断例程开始执行时,中断的确切含义是。从这个意义上说,中断在 Windows 用户模式下根本不存在。 APC 或 windows 消息( Hook 消息是 windows 消息的特例)永远不会在任意位置中断执行,而是使用回调机制。异常(exception)是特例。线程必须首先调用一些 api 才能进入内核空间(对于 Windows 消息传递,这是 GetMessagePeekMessage ,对于 APC - 在可警报状态函数中等待或 ZwTestAlert )。然后内核可以使用回调到用户空间来传递 APC 或 windows 消息。目前从内核到用户空间只有3个回调点存在(从win2000到win10都没有变化) KiUserApcDispatcher - 用于 APC 交付, KiUserCallbackDispatcher - 用于调用窗口过程或 Hook 过程 KiUserExceptionDispatcher - 用于异常基础设施 - 这最接近于中断,

关于c++ - WinApi:消息循环可以被异步过程调用中断吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41238354/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com