Alter
Alter

Reputation: 3464

How to add a hook to Keyboard (HookProc)

I was trying to make a simple keylog test, but my program doesn't work as expected and I don't know why.

In my program i had a low level keyboard hook and attach a simple process to it. The process just opens/creates a file and writes "Hello World" then closes. However it isn't creating the file, probably because my process isn't correct or because my hook wasn't established correctly.

Code:

#include<windows.h>
#include<stdio.h>
#include <iostream>
#include <fstream>

using namespace std;

LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam){
    ofstream myfile;
        myfile.open ("[PATH]/example.txt");
        myfile << "Hello world";//((KBDLLHOOKSTRUCT *)lParam)->vkCode
    myfile.close();
    return CallNextHookEx(NULL,code,wParam,lParam);
}

int main(void){
    HINSTANCE hInst = NULL;
    HHOOK hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, hInst, 0);
    printf("HHOOK is not null: %s\n", (hHook != NULL) ? "True" : "False");
    char q;
    for (cout << "q to quit\n"; q != 'q'; cin >> q);

    printf("Successfully unhooked: %s", UnhookWindowsHookEx(hHook) ? "True" : "False");
}

Solution I needed to add a message loop to the main function:

LPMSG Msg;
while(GetMessage(Msg, NULL, 0, 0) > 0)
{
    TranslateMessage(Msg);
    DispatchMessage(Msg);
}

Upvotes: 2

Views: 4627

Answers (1)

cabbi
cabbi

Reputation: 403

Thre are two kind of hooks:

Global Hooks
Global hook procedures should be placed into a separate DLL, then in your main process you load the hook dll and it's hooking procedure and set the hook.

A global hook monitors messages for all threads in the same desktop as the calling thread. A thread-specific hook monitors messages for only an individual thread. A global hook procedure can be called in the context of any application in the same desktop as the calling thread, so the procedure must be in a separate DLL module.

That said: KeyboardProc goes into a separate DLL (e.g. myhookdll.dll).
In your process you do something like this:

HOOKPROC hkprc;
static HINSTANCE hhookDLL ; 
static HHOOK hhook ; 

hhookDLL = LoadLibrary(TEXT("c:\\...\\myhookdll.dll")); 
hkprc = (HOOKPROC)GetProcAddress(hhookDLL, "KeyboardProc"); 

hhook = SetWindowsHookEx( 
                    WH_KEYBOARD,
                    hkprc,
                    hhookDLL,
                    0); 

Here a good reference: http://msdn.microsoft.com/en-us/library/windows/desktop/ms644960(v=vs.85).aspx

Thread Level Hooks
about this specific 'WH_KEYBOARD_LL' that hooks at thread level, it does not need a separate DLL.

A thread-specific hook procedure is called only in the context of the associated thread. If an application installs a hook procedure for one of its own threads, the hook procedure can be in either the same module as the rest of the application's code or in a DLL. If the application installs a hook procedure for a thread of a different application, the procedure must be in a DLL. For information, see Dynamic-Link Libraries.

But thread level hook needs a message pump:

This hook is called in the context of the thread that installed it. The call is made by sending a message to the thread that installed the hook. Therefore, the thread that installed the hook must have a message loop.

Here a basic message loop:

   while((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
   {
     if(bRet == -1)
     {
         // Handle Error
     }
     else
     {
         TranslateMessage(&msg);
         DispatchMessage(&msg);
     }
   }

Upvotes: 6

Related Questions