![](/img/trans.png)
[英]How Can I call a C++ Win32 DLL from another C++ win32 Console Application
[英]How to subclass another application control using DLL hook in Win32?
我正在尝试使此示例正常工作,其想法是将记事本编辑控件颜色更改为红色:
dll
#include "stdafx.h"
#include <string>
#include <commctrl.h>
#pragma comment( lib, "comctl32.lib")
#pragma data_seg("SHARED")
HWND hWndNotepad = nullptr;
#pragma data_seg()
#pragma comment(linker, "/section:SHARED,RWS")
HINSTANCE hInst;
HHOOK hGetMsgHook;
BOOL bSubclassed = FALSE;
#define WM_NOTEPADMESSAGE WM_USER + 10
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
hInst = (HINSTANCE)hModule;
}
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
{
char out[64] = { 0 };
sprintf_s(out, 63, "DLL_PROCESS_DETACH, bSubclassed: %i", (int)bSubclassed);
OutputDebugStringA(out);
if (bSubclassed)
{
RemoveWindowSubclass(hWndNotepad, SubclassProc, 0);
bSubclassed = FALSE;
hWndNotepad = nullptr;
}
}
break;
}
return TRUE;
}
extern "C" __declspec(dllexport) BOOL CALLBACK SetHook(BOOL bInstall)
{
if (bInstall)
{
hWndNotepad = FindWindowA("Notepad", NULL);
if (hWndNotepad)
{
char out[256] = { 0 };
hGetMsgHook = SetWindowsHookExA(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, hInst, 0);
if (hGetMsgHook)
{
DWORD dwThreadId = GetWindowThreadProcessId(hWndNotepad, NULL);
PostThreadMessageA(dwThreadId, WM_NOTEPADMESSAGE, 0, (LPARAM)hWndNotepad);
sprintf_s(out, 255, "hWndNotepad: %08X - Thread Id : %08X", (UINT)hWndNotepad, dwThreadId);
}
else {
sprintf_s(out, 255, "Error SetWindowsHookEx: %d", GetLastError());
}
OutputDebugStringA(out);
}
else
{
char out[] = "Notepad not found";
OutputDebugStringA(out);
return FALSE;
}
}
else
{
if (hGetMsgHook)
UnhookWindowsHookEx(hGetMsgHook);
}
return TRUE;
}
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
MSG* lpMsg;
if (nCode >= 0)
{
lpMsg = (MSG*)lParam;
if (lpMsg->message == WM_NOTEPADMESSAGE)
{
char out[128] = { 0 };
sprintf_s(out, 127, "WM_NOTEPADMESSAGE - hWndNotepad : %08X", (UINT)hWndNotepad);
OutputDebugStringA(out);
bSubclassed = SetWindowSubclass((HWND)hWndNotepad, SubclassProc, 0, 0);
if (!bSubclassed) {
sprintf_s(out, 127, "Error SetWindowSubclass : %d", GetLastError());
OutputDebugStringA(out);
}
}
}
return CallNextHookEx(hGetMsgHook, nCode, wParam, lParam);
}
LRESULT CALLBACK SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
char out[32] = { 0 };
sprintf_s(out, 31, "uMsg : %d", uMsg);
OutputDebugStringA(out);
switch (uMsg)
{
case WM_CTLCOLOREDIT:
{
SetDCBrushColor((HDC)wParam, RGB(255, 0, 0));
return (INT_PTR)GetStockObject(DC_BRUSH);
}
break;
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
主程序:
HINSTANCE hinstDLL = nullptr;
BOOL hookset = false;
typedef BOOL(*SetHookType)(BOOL);
SetHookType SetHook = nullptr;
DWORD WINAPI dllTest(LPVOID) {
char out[128] = { 0 };
sprintf_s(out, 127, "--- dllTest beg ---");
OutputDebugStringA(out);
hookset = !hookset;
if(hinstDLL == nullptr) {
#if _WIN32 || _WIN64
#if _WIN64
hinstDLL = LoadLibraryA("F:\\projects\\_dll_hook\\x64\\Release\\hook.dll");
#else
hinstDLL = LoadLibraryA("F:\\projects\\_dll_hook\\Release\\hook.dll");
#endif
#endif
sprintf_s(out, 127, "DLL loaded");
OutputDebugStringA(out);
}
if (hinstDLL == nullptr) {
sprintf_s(out, 127, "Error loading dll: #%d", GetLastError());
OutputDebugStringA(out);
return 0;
}
if (SetHook == nullptr) {
SetHook = (SetHookType)GetProcAddress(hinstDLL, "SetHook");
if (SetHook == nullptr) {
sprintf_s(out, 127, "Error getting address of dll.SetHook: #%d", GetLastError());
OutputDebugStringA(out);
return 0;
}
SetHook(hookset);
}
if (!hookset) {
FreeLibrary(hinstDLL);
hinstDLL = nullptr;
SetHook = nullptr;
sprintf_s(out, 127, "DLL freed");
OutputDebugStringA(out);
}
Sleep(10000); // <-- ONE POSSIBLE SOLUTION
sprintf_s(out, 127, "--- dllTest end ---");
OutputDebugStringA(out);
return 0;
}
我在调用 dllTest 两次后得到的 output :
[13800] --- dllTest beg ---
[13800] DLL loaded
[13800] hWndNotepad: 002B0FAC - Thread Id : 00003B30
[13800] --- dllTest end ---
[13800] DLL_PROCESS_DETACH, bSubclassed: 0
[10356] WM_NOTEPADMESSAGE - hWndNotepad : 002B0FAC
[10356] DLL_PROCESS_DETACH, bSubclassed: 1
[13800] --- dllTest beg ---
[13800] DLL_PROCESS_DETACH, bSubclassed: 0
[13800] DLL freed
[13800] --- dllTest end ---
看起来 WM_NOTEPADMESSAGE 已发送到记事本 window 但未被 GetMsgProc 捕获。 这段代码可能有什么问题以及如何使它工作?
谢谢!
首先,回调不起作用的原因是你的DLL将被注入到目标进程中,其他进程无法访问主程序中的function地址。
然后,我可以重现您的问题(记事本背景无法更改)。 主程序在SetHook
之后立即结束,系统可能会自动注销你的钩子,然后目标进程无法访问SubclassProc
地址。 尝试在主程序中添加任何延迟,例如消息循环。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.