WH_JOURNALRECORD hook in Windows (C++) - Callback never called.
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
Edit: It turned out that this was indeed related to access rights. That is, in since Windows Vista, the journal hooks (WH_JOURNALRECORD) are disabled for security reasons (see also this website). In the end, we used a totally different approach to provide similar functionality in our application (which I won't go into detail here, as I'm editing this question 1.5 years after I asked this question and I don't recall all the details of our solution).
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.
The answer, as per the link in the edited question:
http://www.wintellect.com/CS/blogs/jrobbins/archive/2008/08/30/so-you-want-to-set-a-windows-journal-recording-hook-on-vista-it-s-not-nearly-as-easy-as-you-think.aspx
- The application needs to run with administrative privileges.
- The application must be run from (a subdir of)
c:\program files
- To disable the UAC dialog the app must be digitally signed.
Note that with UAC active Windows (Vista and above) will not allow the exe to be debugged.
Or... You can disable UAC (useful when debugging).
Here's the settings dialog for Visual Studio, will check to see if I can get the manifest file in XML format
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.
精彩评论