Question

I've built a working keylogger and now I want to move it to class so I can re-use it whenever I want and even on different languages like c# however I encountered error because same code does not work inside a class.

main.cpp (working)

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);

void main()
{
    HINSTANCE h_instance = GetModuleHandle(NULL);
    SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, h_instance, 0); // Works here
}

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    // Populate typedChars
    return NULL;
}

KeyboardHook.cpp (not working)

class KeyboardHook
{
    stringstream typedChars;

    LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
    {
        // Populate typedChars
        return NULL;
    }

    KeyboardHook()
    {
        HINSTANCE h_instance = GetModuleHandle(NULL);
        SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, h_instance, 0); // Does not work
    }

public:
    std::string Get()
    {
        return typedChars.str();
    }

    void Clear()
    {
        typedChars.str(std::string());
        typedChars.clear();
    }
};

Error

C3867: 'KeyboardHook::KeyboardProc': function call missing argument list; use '&KeyboardHook::KeyboardProc' to create a pointer to member

So I modify it to SetWindowsHookEx(WH_KEYBOARD_LL, &KeyboardProc, h_instance, 0); and now different error occurs

C2276: '&' : illegal operation on bound member function expression

I've also tried but no success:

SetWindowsHookEx(WH_KEYBOARD_LL, (LRESULT)&KeyboardProc, h_instance, 0);
SetWindowsHookEx(WH_KEYBOARD_LL, (LRESULT)KeyboardProc, h_instance, 0);
SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHook::KeyboardProc, h_instance, 0);
SetWindowsHookEx(WH_KEYBOARD_LL, &KeyboardHook::KeyboardProc, h_instance, 0);
Was it helpful?

Solution

Assuming SetWindowsHookEx is supposed to take a function pointer (I can never understand the horrible Windows API documentation), you need to bind your pointer to member function to an object on which it should be called. If you want to bind it to the object pointed to by this (i.e. the KeyboardHook object you're creating at the time), try this:

using std::placeholders;
SetWindowsHookEx(WH_KEYBOARD_LL,
  std::bind(&KeyboardHook::KeyboardProc, this, _1, _2, _3),
  h_instance, 0);

Alternatively, KeyboardProc can be declared as a static member function, but that means it won't be able to use the typedChars member.

OTHER TIPS

You must define KeyboardProc as a static member

static LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
...
}

if it must and can be called without an object.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top