使用挂钩向 explorer.exe main window 发送消息会导致崩溃?
Sending message to explorer.exe main window with a hook causes crash?
我正在尝试使用从 WindowFromPoint
获得的 HWND
在 window 上设置一个 WH_CALLWNDPROC
挂钩,然后发送消息 WM_USER+x
。但是根据 HWND
我使用它会使 window.
崩溃
让我解释一下场景:
当通过 WindowFromPoint
函数获得 HWND
时,您有时会获得 children 之一,而不是主要的 window。
使用 spy++ 中的 Finder 工具可视化非常好
所以我简单地得到 window
wcout << "INFO: Waiting 1 second before first hwnd...\n";
this_thread::sleep_for(chrono::milliseconds(1000));
HWND targetHwnd = getHwndFromMousePos(); //Gets hwnd from mouse pos with WindowFromPoint
outHwndData(targetHwnd);
DWORD targetPID;
DWORD targetTID = GetWindowThreadProcessId(targetHwnd, &targetPID);
然后使用dll的导出函数设置钩子
hook = setHook(targetTID); //hook is the global HHOOK and setHook is a exported function in a dll
if (hook == NULL) {
cout << "ERROR: Could not set hook\n";
return 1;
}
dll里面的函数是这样的
extern "C" __declspec(dllexport) HHOOK __stdcall setHook(DWORD targetTid) {
return SetWindowsHookEx(WH_CALLWNDPROC, wmProcCallback, hInst, targetTid);
}
当 targetHwnd
是 children HWND
时,我挂机,发送消息 -> 工作正常
但是当targetHwnd
是上面的HWND
(绿色标记的那个)的时候,我挂了它,发了一条消息->它崩溃了。
所以最后 SetWindowsHookEx
有效,但我无法向找到的 window 发送任何消息,如果它是上层 HWND
(绿色标记的一个)。为什么会这样?
这个完整的演示代码将等待 1 秒钟,然后再选择 HWND
。通过将鼠标悬停在 explorer.exe window 上的标题栏上,您可以获得导致崩溃的 HWND
。
申请代码:
//This is the app
#include <Windows.h>
#include <iostream>
#include <thread>
using namespace std;
typedef HHOOK(WINAPI* DLLFUNC_SETHOOK) (DWORD);
HINSTANCE dllInstance;
DLLFUNC_SETHOOK setHook;
HHOOK hook;
HWND getHwndFromMousePos() {
POINT cursorPos;
if (GetCursorPos(&cursorPos) == FALSE) {
cout << "ERROR: Could not get Cursor position...\n";
return NULL;
}
HWND wnd = WindowFromPoint(cursorPos);
if (wnd == NULL) {
cout << "ERROR: No window found on this point\n";
return NULL;
}
return wnd;
}
int main() {
wcout << "INFO: Waiting 1 second before first hwnd...\n";
this_thread::sleep_for(chrono::milliseconds(1000));
HWND targetHwnd = getHwndFromMousePos();
wcout << targetHwnd << endl;
DWORD targetPID;
DWORD targetTID = GetWindowThreadProcessId(targetHwnd, &targetPID);
dllInstance = LoadLibrary(L"DLL1.dll");
setHook = (DLLFUNC_SETHOOK)GetProcAddress(dllInstance, "setHook");
if (dllInstance == NULL) {
cout << "ERROR: dllInstance is NULL\n";
return 1;
}
if (setHook == NULL) {
cout << "ERROR: setHook function is NULL\n";
return 1;
}
hook = setHook(targetTID);
if (hook == NULL) {
cout << "ERROR: Could not set hook\n";
return 1;
}
cout << "INFO: Hooked successfully\n";
//Works only when targetHwnd is a children
SendMessage(targetHwnd, WM_USER + 1, 0, 0); //This causes the crash
cin.ignore();
BOOL success = UnhookWindowsHookEx(hook);
if (success == FALSE) {
cout << "ERROR: Could not unhook\n";
}
else {
cout << "INFO: Unhooked hook. Exiting...\n";
}
}
DLL(DLL1):
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <fstream>
extern HINSTANCE hInst;
extern std::wofstream logfile;
extern "C" __declspec(dllexport) HHOOK __stdcall setHook(DWORD targetTid);
HINSTANCE hInst;
std::wofstream logfile;
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
hInst = hModule;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH: {
logfile.open("D:\projects\crashDemo\log.txt"); //run "Get-Content -Path "log.txt" -Wait" in Powershell for realtime logs
break;
}
case DLL_THREAD_ATTACH: break;
case DLL_THREAD_DETACH: break;
case DLL_PROCESS_DETACH: {
logfile.close();
break;
}
}
return TRUE;
}
LRESULT CALLBACK wmProcCallback(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode >= HC_ACTION) {
PCWPSTRUCT cwpStruct = (PCWPSTRUCT)lParam;
switch (cwpStruct->message) {
case WM_USER + 1:
logfile << "WM_USER+1 Message received" << std::endl;
break;
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
extern "C" __declspec(dllexport) HHOOK __stdcall setHook(DWORD targetTid) {
return SetWindowsHookEx(WH_CALLWNDPROC, wmProcCallback, hInst, targetTid);
}
编辑:我调试通过了。看起来 dll 一切正常。它加载并且 wmProcCallback
被调用了几次。
我的 WM_USER+1
也被识别,但在处理完 wmProcCallback
中的所有消息后,它会立即关闭 window 并留下以下错误消息。
所以我总共收到了 4 条错误消息:
&2.An outgoing call cannot be made since the application is dispatching an input-asynchronous call
The operation is not permitted because the calling application is not the owner of the data on the clipboard.
Unspecified error
是否有人知道其中哪些是相关的,因为我不知道这些错误中的任何一个?现在要做一些研究。如果有人可以帮助解决这个问题,那就太好了。
简单修复,不要使用 WM_USER+1 :)
我正在尝试使用从 WindowFromPoint
获得的 HWND
在 window 上设置一个 WH_CALLWNDPROC
挂钩,然后发送消息 WM_USER+x
。但是根据 HWND
我使用它会使 window.
让我解释一下场景:
当通过 WindowFromPoint
函数获得 HWND
时,您有时会获得 children 之一,而不是主要的 window。
使用 spy++ 中的 Finder 工具可视化非常好
所以我简单地得到 window
wcout << "INFO: Waiting 1 second before first hwnd...\n";
this_thread::sleep_for(chrono::milliseconds(1000));
HWND targetHwnd = getHwndFromMousePos(); //Gets hwnd from mouse pos with WindowFromPoint
outHwndData(targetHwnd);
DWORD targetPID;
DWORD targetTID = GetWindowThreadProcessId(targetHwnd, &targetPID);
然后使用dll的导出函数设置钩子
hook = setHook(targetTID); //hook is the global HHOOK and setHook is a exported function in a dll
if (hook == NULL) {
cout << "ERROR: Could not set hook\n";
return 1;
}
dll里面的函数是这样的
extern "C" __declspec(dllexport) HHOOK __stdcall setHook(DWORD targetTid) {
return SetWindowsHookEx(WH_CALLWNDPROC, wmProcCallback, hInst, targetTid);
}
当 targetHwnd
是 children HWND
时,我挂机,发送消息 -> 工作正常
但是当targetHwnd
是上面的HWND
(绿色标记的那个)的时候,我挂了它,发了一条消息->它崩溃了。
所以最后 SetWindowsHookEx
有效,但我无法向找到的 window 发送任何消息,如果它是上层 HWND
(绿色标记的一个)。为什么会这样?
这个完整的演示代码将等待 1 秒钟,然后再选择 HWND
。通过将鼠标悬停在 explorer.exe window 上的标题栏上,您可以获得导致崩溃的 HWND
。
申请代码:
//This is the app
#include <Windows.h>
#include <iostream>
#include <thread>
using namespace std;
typedef HHOOK(WINAPI* DLLFUNC_SETHOOK) (DWORD);
HINSTANCE dllInstance;
DLLFUNC_SETHOOK setHook;
HHOOK hook;
HWND getHwndFromMousePos() {
POINT cursorPos;
if (GetCursorPos(&cursorPos) == FALSE) {
cout << "ERROR: Could not get Cursor position...\n";
return NULL;
}
HWND wnd = WindowFromPoint(cursorPos);
if (wnd == NULL) {
cout << "ERROR: No window found on this point\n";
return NULL;
}
return wnd;
}
int main() {
wcout << "INFO: Waiting 1 second before first hwnd...\n";
this_thread::sleep_for(chrono::milliseconds(1000));
HWND targetHwnd = getHwndFromMousePos();
wcout << targetHwnd << endl;
DWORD targetPID;
DWORD targetTID = GetWindowThreadProcessId(targetHwnd, &targetPID);
dllInstance = LoadLibrary(L"DLL1.dll");
setHook = (DLLFUNC_SETHOOK)GetProcAddress(dllInstance, "setHook");
if (dllInstance == NULL) {
cout << "ERROR: dllInstance is NULL\n";
return 1;
}
if (setHook == NULL) {
cout << "ERROR: setHook function is NULL\n";
return 1;
}
hook = setHook(targetTID);
if (hook == NULL) {
cout << "ERROR: Could not set hook\n";
return 1;
}
cout << "INFO: Hooked successfully\n";
//Works only when targetHwnd is a children
SendMessage(targetHwnd, WM_USER + 1, 0, 0); //This causes the crash
cin.ignore();
BOOL success = UnhookWindowsHookEx(hook);
if (success == FALSE) {
cout << "ERROR: Could not unhook\n";
}
else {
cout << "INFO: Unhooked hook. Exiting...\n";
}
}
DLL(DLL1):
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <fstream>
extern HINSTANCE hInst;
extern std::wofstream logfile;
extern "C" __declspec(dllexport) HHOOK __stdcall setHook(DWORD targetTid);
HINSTANCE hInst;
std::wofstream logfile;
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
hInst = hModule;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH: {
logfile.open("D:\projects\crashDemo\log.txt"); //run "Get-Content -Path "log.txt" -Wait" in Powershell for realtime logs
break;
}
case DLL_THREAD_ATTACH: break;
case DLL_THREAD_DETACH: break;
case DLL_PROCESS_DETACH: {
logfile.close();
break;
}
}
return TRUE;
}
LRESULT CALLBACK wmProcCallback(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode >= HC_ACTION) {
PCWPSTRUCT cwpStruct = (PCWPSTRUCT)lParam;
switch (cwpStruct->message) {
case WM_USER + 1:
logfile << "WM_USER+1 Message received" << std::endl;
break;
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
extern "C" __declspec(dllexport) HHOOK __stdcall setHook(DWORD targetTid) {
return SetWindowsHookEx(WH_CALLWNDPROC, wmProcCallback, hInst, targetTid);
}
编辑:我调试通过了。看起来 dll 一切正常。它加载并且 wmProcCallback
被调用了几次。
我的 WM_USER+1
也被识别,但在处理完 wmProcCallback
中的所有消息后,它会立即关闭 window 并留下以下错误消息。
所以我总共收到了 4 条错误消息:
&2.
An outgoing call cannot be made since the application is dispatching an input-asynchronous call
The operation is not permitted because the calling application is not the owner of the data on the clipboard.
Unspecified error
是否有人知道其中哪些是相关的,因为我不知道这些错误中的任何一个?现在要做一些研究。如果有人可以帮助解决这个问题,那就太好了。
简单修复,不要使用 WM_USER+1 :)