tags:

views:

22

answers:

2

Hello everyone,

The following code has been giving me some troubles for the past few hours. I'm trying to write a small program (based on some tutorials from the web), that uses a WH_JOURNALRECORD windows hook to log keystrokes.

Main code:

#include "StdAfx.h"
#include <tchar.h>
#include <iostream>
#include <windows.h>

using std::cout;
using std::endl;

int _tmain(int argc, _TCHAR* argv[]) {  
    HINSTANCE hinst = LoadLibrary(_T("testdll3.dll")); 
    typedef void (*Install)();
    typedef void (*Uninstall)();
    Install install = (Install) GetProcAddress(hinst, "install");
    Uninstall uninstall = (Uninstall) GetProcAddress(hinst, "uninstall");

    install();
    int foo;
    std::cin >> foo; 

    cout << "Uninstalling" << endl;
    uninstall();
    return 0;
}

Code of the DLL:

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

HHOOK hhk;
HHOOK hhk2;


LRESULT CALLBACK journalRecordProc(int code, WPARAM wParam, LPARAM lParam) {  
    FILE * fileLog = fopen("journal.txt", "a+");
    fprintf(fileLog,"loggedJournal\n");
    fclose(fileLog);
    CallNextHookEx(hhk,code,wParam,lParam);
    return 0;
}


LRESULT CALLBACK wireKeyboardProc(int code,WPARAM wParam,LPARAM lParam) {  
 FILE * fileLog = fopen("keyboard.txt", "a+");
 fprintf(fileLog,"loggedKeyboard\n");  
 fclose(fileLog);
 CallNextHookEx(hhk,code,wParam,lParam);
 return 0;
}

extern "C" __declspec(dllexport) void install() {
    HINSTANCE thisDllInstance = LoadLibrary(_T("testdll3.dll"));
    hhk = SetWindowsHookEx(WH_JOURNALRECORD, journalRecordProc, thisDllInstance, NULL);
    hhk2 = SetWindowsHookEx(WH_KEYBOARD, wireKeyboardProc, thisDllInstance, NULL);
}
extern "C" __declspec(dllexport) void uninstall() {
    UnhookWindowsHookEx(hhk); 
    UnhookWindowsHookEx(hhk2); 
}

BOOL WINAPI DllMain(  __in  HINSTANCE hinstDLL, __in  DWORD fdwReason, __in  LPVOID lpvReserved) {
 return TRUE;
}

For some reason, the keyboard hook (SetWindowsHookEx(WH_KEYBOARD, wireKeyboardProc,..)) works (the 'keyboard.txt' file is created), but the journaling hook (SetWindowsHookEx(WH_JOURNALRECORD, journalRecordProc,...)) doesn't. That is, the callback for the journaling hook is never called (journal.txt file is never created).

I think this might have something to do with Windows' UAC (which I discovered while searching the web), but disabling UAC and running the program with administrative rights didn't help.

I'm not sure what to do now. Can anyone help me?

Thanks

Joris

Additional Info: I'm using Windows 7 + Visual Studio 2010

+1  A: 

MSDN states the following for the Journal Record hook:

Unlike most other global hook procedures, the JournalRecordProc and JournalPlaybackProc hook procedures are always called in the context of the thread that set the hook.

If you move the callback for the Journal hook to your exe, does that cause it to get called?

Also, wouldn't it be better to call GetModuleHandle() rather than LoadLibrary() in install(), since the DLL is already loaded?

Regarding UAC and administrator rights, hooks can work when executed as a normal user. The only side effect off this is that only processes that are running at that level or lower will be hooked. So if your app is running as a normal user, then any processes running as a normal user will be hooked, but those running as admin won't be hooked.

Andy
Mm, I'm not entirely sure what you mean with "If you move the callback for the Journal hook to your exe, does that cause it to get called?"I tried not calling the SetWindowsHookEx and UnhookWindowsHookEx from within the exe (Obviously, I copied the callbacks to the exe too), but when doing that no callback is called (not even the WH_KEYBOARD callback...).I also tried passing the callback as a function pointer from the exe to the dll, but that didn't work (runtime errors).Any other ideas?Thanks
Joris
What I mean is that both SetWindowsHookEx() and the callback proc should be defined in your exe, not in the dll. This is because this callback gets called in your app, not the app that got sent the message.
Andy
+1  A: 

WH_JOURNALRECORD is different then others. You don't need to put it into DLL, but you do need to have a message loop in your app to the handler could be called (within context of your app ). I posted an example some time ago on another site: http://forum.4programmers.net/viewtopic.php?p=557297#id557297, the hook catches WM_MOUSEMOVE in the example and prints results to console.

This kind of hook is expensive because every time the callback is called execution context must be switched to your application.

adf88