You can see the old MSDN application Hooks32, which still works on my OS (Windows 10, 1909)
I had re-compiled it with VS 2015 : Hooks32 Source
How to record/output other programs messages from a hooked DLL in Win32?
I have a Win32 GUI app where a thread starts upon pressing a button like so:
switch (wmId)
{
case int(BTN::Test) :
CreateThread(NULL, 0, dllTest, &hWnd, 0, NULL);
...
HHOOK hhookSysMsg = nullptr;
HINSTANCE hinstDLL = nullptr;
DWORD WINAPI dllTest(LPVOID) {
HOOKPROC hkprcSysMsg;
hinstDLL = LoadLibraryA("xxx\\_dll_hook\\x64\\Release\\hook.dll");
if (hinstDLL == NULL) {
prnt("Error loading dll: #%d", PV, GetLastError());
return 0;
}
hkprcSysMsg = (HOOKPROC)GetProcAddress(hinstDLL, "SysMessageProc");
if (hkprcSysMsg == NULL) {
prnt("Error getting address of dll.SysMessageProc: #%d", PV, GetLastError());
return 0;
}
hhookSysMsg = SetWindowsHookExA(
WH_CALLWNDPROC,
hkprcSysMsg,
hinstDLL,
0);
if (hhookSysMsg == NULL) {
prnt("Error hooking dll.SysMessageProc: #%d", PV, GetLastError());
return 0;
}
S leep(5000);
UnhookWindowsHookEx(hhookSysMsg);
FreeLibrary(hinstDLL);
return 0;
}
and here is the DLL code:
std::unordered_map<int, std::string> map;
void loadMsg() {
std::fstream stream("xxx\\msg.txt");
if (stream.is_open()) {
std::string line;
while (std::getline(stream, line)) {
auto index = line.find(' ');
if (index != std::string::npos)
map.insert(std::make_pair(std::stoi(line.substr(0, index)), line.substr(index + 1)));
}
stream.close();
}
}
INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved) {
switch (Reason) {
case DLL_PROCESS_ATTACH:
OutputDebugStringA("DLL attach function called");
loadMsg();
break;
case DLL_PROCESS_DETACH:
OutputDebugStringA("DLL detach function called");
break;
case DLL_THREAD_ATTACH:
OutputDebugStringA("DLL thread attach function called");
break;
case DLL_THREAD_DETACH:
OutputDebugStringA("DLL thread detach function called");
break;
}
return TRUE;
}
extern "C" __declspec(dllexport) LRESULT CALLBACK SysMessageProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode < 0) return CallNextHookEx(NULL, nCode, wParam, lParam);
if (nCode == HC_ACTION) {
CWPSTRUCT* pCWP = (CWPSTRUCT*)lParam;
HWND hWnd = pCWP->hwnd;
char wclass[256]; wclass[0] = 0;
if (GetClassNameA(hWnd, wclass, 255) != 0) {
std::string msg = map[pCWP->message];
if (1) // || strcmp(wclass, "SysHeader32") == 0 || strcmp(wclass, "SysListView32") == 0 || msg == "WM_NOTIFY") {
char out[256]; out[0] = 0;
sprintf_s(out, 255, "class: '%s', msg: %s %08X\n", wclass, msg.c_str(), pCWP->message);
OutputDebugStringA(out);
}
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
This code works but it never prints out (in DebugView or MSVS Debug Output) messages sent for other open programs, only this program own messages.
If I replace OutputDebugStringA with an output to a file, the target program (like Notepad where I open menus or type text) and explorer.exe often crash or the target program freezes. But then if I look at the file, I can see that messages for different programs were recorded there before crash.
So why it might be happening and what is the right way to record messages in this case, so it's fast and captures messages for other programs, like it's done in Spy++ ?
-
Castorix31 84,471 Reputation points
2021-01-08T09:41:39.24+00:00