Revieve Windows messages with WH_GETMESSAGE

  c++, hook, winapi, windows

I am trying to get all the Windows messages of a specific programm.
To do that i am calling SetWindowsHookEx() and passing a prior loaded DLL and a function, which is used as a callback. But the problem is, that the callback function is never called.

The code of the programm that calls SetWindowsHookEx() is the following:

#include <string>
#include <iostream>
#include <vector>
#include <Windows.h>
#include <tlhelp32.h>

const std::wstring targetProgramm = L"notepad.exe";;
const std::wstring dllPath = L"myDll.dll";
const std::string dllMessageCallback = "[email protected]";
std::vector<HHOOK> hooks;

struct handle_data {
    unsigned long process_id;
    HWND window_handle;
};

std::vector<DWORD> getProcessIdsOfProgramm(const std::wstring& programm);
HWND getWindowHandleFromProcessId(DWORD pid);
BOOL CALLBACK enum_windows_callback(HWND handle, LPARAM lparam);
BOOL WINAPI ConsoleHandler(DWORD CEvent);

int main() {
    // Console handler to detect, when console is closed
    if (SetConsoleCtrlHandler(
        (PHANDLER_ROUTINE)ConsoleHandler, TRUE) == FALSE) {
        std::cout << "Unable to install console handler" << std::endl;
        return -1;
    }

    HMODULE dll = LoadLibrary(dllPath.c_str());
    if (dll == NULL) {
        std::cout << "The DLL could not be found" << std::endl;
        return -1;
    }

    HOOKPROC addr = (HOOKPROC)GetProcAddress(dll, dllMessageCallback.c_str());
    if (addr == NULL) {
        std::cout << "The Callback function could not be found" << std::endl;
        return -1;
    }

    std::vector<DWORD> pids = getProcessIdsOfProgramm(targetProgramm);
    if (pids.size() != 0) {
        for (auto pid : pids) {
            HWND window = getWindowHandleFromProcessId(pid);
            if (window == nullptr) {
                std::cout << "Window Handle from process with id: " << pid << " could not be found" << std::endl;
                continue;
            }
            DWORD tid = GetWindowThreadProcessId(window, &pid);

            //HHOOK hook = SetWindowsHookEx(WH_KEYBOARD, addr, dll, tid);
            HHOOK hook = SetWindowsHookEx(WH_GETMESSAGE, addr, dll, tid);
            if (hook != NULL) 
                hooks.push_back(hook);
            else 
                std::cout << "process with id: " << pid << " could not be hooked" << std::endl;
        }
    }
    else {
        std::cout << "process could not be found" << std::endl;
        return -1;
    }

    // keep programm running with message queue
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

BOOL WINAPI ConsoleHandler(DWORD CEvent)
{
    char mesg[128];

    switch (CEvent)
    {
    case CTRL_CLOSE_EVENT:
        for (auto hook : hooks) {
            UnhookWindowsHookEx(hook);
        }
        break;
    }
    return TRUE;
}

std::vector<DWORD> getProcessIdsOfProgramm(const std::wstring& programm) {
    std::vector<DWORD> pids;
    HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    PROCESSENTRY32W entry;
    entry.dwSize = sizeof entry;

    if (!Process32FirstW(snap, &entry))
        return pids;

    do {
        if (std::wstring(entry.szExeFile) == targetProgramm) {
            pids.push_back(entry.th32ProcessID); //name matches; add to list
        }
    } while (Process32NextW(snap, &entry)); //keep going until end of snapshot

    return pids;
}

HWND getWindowHandleFromProcessId(DWORD pid) {
    handle_data data{};

    data.process_id = pid;
    data.window_handle = nullptr;
    EnumWindows(enum_windows_callback, reinterpret_cast<LPARAM>(&data));

    return data.window_handle;
}

BOOL CALLBACK enum_windows_callback(HWND handle, LPARAM lparam) {
    auto& data = *reinterpret_cast<handle_data*>(lparam);

    unsigned long process_id = 0;
    GetWindowThreadProcessId(handle, &process_id);

    if (data.process_id != process_id) {
        return TRUE;
    }
    data.window_handle = handle;
    return FALSE;
}

The code of the Dll is the following:

#include <iostream>
#include <Windows.h>

extern "C" __declspec(dllexport) LRESULT  __stdcall MsgProc(int code, WPARAM wParam, LPARAM lParam) {
    std::cout << "got message123" << std::endl;
    return CallNextHookEx(0, code, wParam, lParam);
}

The function MsgProc is never called, even when i press buttons while having the program in focus or resize the window.

What i find especially puzzling is that, i am able the recieve all keyboard inputs, if i replace:

HHOOK hook = SetWindowsHookEx(WH_GETMESSAGE, addr, dll, tid);

with:

HHOOK hook = SetWindowsHookEx(WH_KEYBOARD, addr, dll, tid);

but when i use: WH_GETMESSAGE, MsgProc never gets called.

What am i doing wrong?

Source: Windows Questions

LEAVE A COMMENT