Intercepting Windows messages with a global hook that application does not peeks or gets

204 views Asked by At

I'm writing a global hook to listen to the Korean letter compositions. (You're not required to know how Korean letters are composed, please read through...)

The dll's code:

#include <fstream>

#include "Header.h"

#pragma data_seg("Shared")
HHOOK get_message_hook = nullptr;
#pragma data_seg()

#pragma comment(linker, "/section:Shared,rws")
HINSTANCE dll_instance = nullptr;

BOOL APIENTRY DllMain(HMODULE hModule,
                      DWORD  ul_reason_for_call,
                      LPVOID lpReserved
)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        dll_instance = hModule;
        break;

    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

LRESULT CALLBACK callback(int code, WPARAM wParam, LPARAM lParam)
{
    if (code < 0)
    {
        return CallNextHookEx(get_message_hook, code, wParam, lParam);
    }

    std::ofstream output{ /*path to a file*/, std::ios::app };

    auto* param = reinterpret_cast<MSG*>(lParam);
    if (param->message == WM_CHAR)
    {
        output << "WM_CHAR" << std::endl;
    }
    if (param->message == WM_INPUTLANGCHANGE)
    {
        output << "WM_INPUTLANGCHANGE" << std::endl;
    }
    if (param->message == WM_IME_NOTIFY)
    {
        output << "WM_IME_NOTIFY" << std::endl;
    }
    if (param->message == WM_IME_COMPOSITION)
    {
        output << "WM_IME_COMPOSITION" << std::endl;
    }
    if (param->message == WM_IME_STARTCOMPOSITION)
    {
        output << "WM_IME_STARTCOMPOSITION" << std::endl;
    }
    if (param->message == WM_IME_ENDCOMPOSITION)
    {
        output << "WM_IME_ENDCOMPOSITION" << std::endl;
    }
    if (param->message == WM_IME_CHAR)
    {
        output << "WM_IME_CHAR" << std::endl;
    }

    return CallNextHookEx(get_message_hook, code, wParam, lParam);
}

void DLL2_API set_hook()
{
    if (!get_message_hook)
    {
        get_message_hook = SetWindowsHookEx(WH_GETMESSAGE, callback, dll_instance, 0);
    }
}

void DLL2_API remove_hook()
{
    if (get_message_hook)
    {
        UnhookWindowsHookEx(get_message_hook);
        get_message_hook = nullptr;
    }
}

The main:

#include <iostream>

#include "../Dll2/Header.h"


int main()
{
    char c;
    while (std::cin >> c)
    {
        if (c == 's')
        {
            set_hook();
        }
        else if (c == 'r')
        {
            remove_hook();
        }
    }

    remove_hook();
}

It works well with most of the applications, such as Notepad, Visual Studio, Discord, etc. But when I type Korean letters on Chrome, it doesn't produce any of the messages above. I've also tried WH_CALLWNDPROC hooks but had no luck.

By reading the book Subclassing and Hooking with Visual Basic, I understand that WH_GETMESSAGE hooks are called when the application calls GetMessage or PeekMessage, and WH_CALLWNDPROC hooks are called when a message is sent directly to the application.

And by looking at the signature of the GetMessage and PeekMessage, you can filter the range of the messages you are willing to get/peek. I quickly wrote a simple program that gets only a certain range of messages and confirmed that the hooks can't get the messages other than the program listens to.

So my suspicion is that the Chrome is filtering out those messages while getting/peeking. Weird thing is, I'm not getting WM_CHAR messages either with Korean letters.

My question is,

  1. Is my suspicion correct? (That the Chrome is filtering out the messages?)
  2. Is there any way to 'intercept' messages an application is not getting or peeking?

Please note that WH_KEYBOARD_LL won't do the job since Korean typing system is not like latin alphabets.

0

There are 0 answers