WINAPI's message loops drives me crazy - c++

I've been trying to implement simple low level keyhook using JNI and all went well til I figured I can't call the methods while the DLL is on infinite loop(message loop). so I decided to create new thread but somehow, after I made it so the message loop runs on its own loop the lowlevel keyhook stops responding meaning that it doesn't call the keyproc anymore, and I got no idea why is this? is there any other work around for this? I am required to be able to call the DLL's methods while the keyboard hook is still functioning.
My current code is as simple as
register keyboard hook:
keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboardProc, hInstance, 0);
start thread
HANDLE threadHandle = CreateThread(NULL, 0, ThreadProc, NULL, 0, &threadId);
my keyboard proc and threadproc are the following:
DWORD WINAPI ThreadProc(LPVOID lpVoid) {
MSG msg;
while(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK keyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
KBDLLHOOKSTRUCT keyEvent = *((KBDLLHOOKSTRUCT*)lParam);
jint vkCode = keyEvent.vkCode;
jint flags = keyEvent.flags;
jint action = wParam;
(*globalEnv).CallVoidMethod(globalObj, keyboardMethodId, vkCode, flags, action);
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
where do I go wrong?
I am sure it not the java as even if I add simple logging for the keyproc its never called. But if I stop using thread and run the message loop on main thread it works fine but DLL wont respond for method calls after it.

You need to pump the message loop on the same thread that called SetWindowsHookEx(). So just move the call to your ThreadProc(). And of course, beware that your CallVoidMethod() callback runs on that same thread as well so be careful what you do in that function. Any shared state you access needs to be protected with a lock.

You are attempting to install desktop-wide hook, which spans across all processes of the desktop. That is, your DLL is mapped into several processes with process-specific sets of global variables. You don't have valid globalEnv in other processes and you are likely to get access violations or similar errors (global vars can be created with shared data segment, see this article for details).
To install thread specific hook you will need a different type of hook (WH_KEYBOARD_LL is global only!) and non-zero last argument in SetWindowsHookEx.

Related

Unhooking a hook set with SetWindowsHookEx more than once crashes the hooked process

I am trying to hook the keyboard and mouse events of a target application.
I followed the SO question How to hook external process with SetWindowsHookEx and WH_KEYBOARD, and the hooks are installed and uninstalled correctly the first time. However, after I uninstall the hook once and then install it again, trying to uninstall the hook the second time crashes the target application. The purpose of the hook is to monitor application idle time, so that I can do some tasks when the application is idle.
I apologize for the length of the question, but I tried to put in all the details that might help
Thanks
I need to be able to install and uninstall the hooks based on menu commands from a system tray icon. I have a console application [HookApp] which calls the install and uninstall methods in a DLL [HookDLL]. The console application also creates a window to handle menu events. I use the thread of the window to actually install and uninstall the hooks, because the same thread that installed the hook must uninstall it. The Console and the window both must be invisible. Only the system tray icon and its associated menu must be visible.
I start the hooking application from the command line with the parameters
i. ProcessId of the target process
ii. Process Name
iii. Idle time [in seconds] -Idle time before starting the action in the DLL
I am wondering if the timer I start in the HookProcs is responsible for the crash.
Event Viewer Logs
Faulting application name: notepad.exe, version: 10.0.17134.1, time stamp: 0x9d4727c2
Faulting module name: HookDLL_x64.dll_unloaded, version: 0.0.0.0, time stamp: 0x5c31aabd
Exception code: 0xc0000005
Fault offset: 0x00000000000ba505
Faulting process id: 0x2bac
The exception code seems to suggest a memory access violation.
I have tried the following
I.
a. Call the SendMessageTimeout API with HWND_BROADCAST from HookApp
b. Call the SendMessageTimeout API with HWND_BROADCAST from HookDLL
based on Unloading DLL from all processes after unhooking global CBT hook
II.
a. call FreeLibraryAndExitThread API in the DLLMain method on DLL_PROCESS_DETACH AND DLL_THREAD_DETACH -both together and singly
based on http://www.rohitab.com/discuss/topic/42505-unloading-dll-crashes-exe/
III. Made the HookApp console and the window visible and hidden to see if it makes any difference
IV. Was unable to try the following because of 64 bit architecture
https://www.unknowncheats.me/forum/programming-for-beginners/73377-unload-injected-dll-thread-process.html
Other Links I referred to
a. Several programs crash when unhooking with UnhookWindowsHookEx()
b. How to correctly use SetWindowsHookEx & CallNextHookEx
c. Unloading an Injected DLL
d. FreeLibraryAndExitThread crashes program when unloading injected DLL
//Code in the DLL
extern "C" __declspec(dllexport) void install(unsigned long threadID,int _nIdleTime) {
nIdleTime = _nIdleTime;
Log(L"install proc called from app: _nIdleTime", _nIdleTime);
hhKeyboard = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, hinst, threadID);
hhMouse = SetWindowsHookEx(WH_MOUSE, MouseProc, hinst, threadID);
logger->Log("Install");
logger->Log("Keyboard", (LONG)hhKeyboard);
logger->Log("Mouse", (LONG)hhMouse);
}
//Uninstall the dll from the Target Process
DWORD WINAPI UnInjectDLLFromTarget() {
uninstall();
//DWORD_PTR dwResult = 0;
//SendMessageTimeout(HWND_BROADCAST, WM_NULL, 0, 0, SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG, 1000, &dwResult);
return TRUE;
}
LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam) {
if (code < 0) {
return CallNextHookEx(0, code, wParam, lParam);
}
StartTimer();
Beep(1000, 20);
return CallNextHookEx(hhKeyboard, code, wParam, lParam);
}
LRESULT CALLBACK MouseProc(int code, WPARAM wParam, LPARAM lParam) {
if (code < 0) {
return CallNextHookEx(0, code, wParam, lParam);
}
// StartTimer();
//Beep(1000, 20);
return CallNextHookEx(hhMouse, code, wParam, lParam);
}
BOOL WINAPI DllMain(__in HINSTANCE hinstDLL, __in DWORD fdwReason, __in LPVOID lpvReserved) {
if (fdwReason == DLL_PROCESS_DETACH || fdwReason==DLL_THREAD_DETACH) {
FreeLibraryAndExitThread(hinstDLL, 0);
return 0;
}
}
//Code in the Application [HookApp]
Similar to [But not exactly the same - It is a bit more involved because of the need to create the message pump and the menu event handling window]
HINSTANCE hinst = LoadLibrary(_T("MyDLL.dll"));
if (hinst) {
typedef void (*Install)(unsigned long);
typedef void (*Uninstall)();
Install install = (Install) GetProcAddress(hinst, "install");
Uninstall uninstall = (Uninstall) GetProcAddress(hinst, "uninstall");
install(threadID);
Sleep(20000);
uninstall();
}
SendMessageTimeout in the DLL [HookDLL] method Uninstall immediately crashes the application
SendMessageTimeout in the application [HookApp] doesnt appear to do anything useful.
FreeLibraryAndExitThread does not appear to do anything useful.
However, with 2 and 3, I think I am able to install the hook for the second time. Without them, the first unhook crashes the application.
I was unable to try the suggestion using assembly language inline because of 64 bit architecture.
Please help.
for uninstall hook and unload your dll all what you need - call UnhookWindowsHookEx for every hook handle obtained by a previous call to SetWindowsHookEx. all. you not need call FreeLibrary[AndExitThread] yourself. system auto call FreeLibrary on your hook dll after UnhookWindowsHookEx callend, when first (any) message will be received by target application thread and this thread call GetMessage or PeekMessage. so for just unload your dll after several UnhookWindowsHookEx - you need post message to thread, for which you install hook. if you do this for concrete single thread (dwThreadId) - you need PostThreadMessageW(dwThreadId, WM_NULL, 0, 0); - system yourself call FreeLibrary ( called from user32!__ClientFreeLibrary which called from ntdll!KiUserCallbackDispatcher - called inside GetMessage or PeekMessage when thread (or it window) got any message)
call FreeLibrary from dll for yourself - always error - if assume dll will be unloaded by this call - to where we return after call ? to unloaded place. call FreeLibraryAndExitThread exist sense in some cases, but only from thread, which you create yourself. call FreeLibraryAndExitThread from dll entry point at all fatal error - you kill not self thread, thread which you kill - hold critical section (loader lock) inside which called dll entry point - so fatal error. and at all absolute senseless call here - if you say receive DLL_PROCESS_DETACH this mean that dll already in unload process. DLL_THREAD_DETACH - arbitrary point, why and how many time you try call unload for self here ? exit thread while holding process wide critical section without release it. fatal error.
also because the same thread that installed the hook must uninstall it. - this is not true. another thread from also can do this.
also StartTimer(); in your code look like suspicious here. what this code is do ? are and where you cancel timer ?

Get WM_INPUT from Unity window

About
I am trying to build a custom mouse input for Unity that gets the data directly from the HID. I do this because I want to try if there is any difference (when using my own custom mouse input) to the Unity API that gives me raw mouse input.
Also I need to say that everything I am doing right now does not happen within Unity. I want to build an C++ application and then pass the data to Unity (that's not a part of this question).
This link (MSDN High-Definition Mouse Movement) shows that there are three different types of messages I can use. Due to I need so called "High-Definition Mouse Movement" I need to go with WM_INPUT.
This message can be caught with the WinProc handler as the documentation says. Within that callback the raw mouse data can be accessed. This is what I want to achieve and where I need help.
My current approach
The documentation (link above) gives me this example to register the mouse:
RAWINPUTDEVICE Rid[1];
Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE;
Rid[0].dwFlags = RIDEV_INPUTSINK;
Rid[0].hwndTarget = gameWindowHandle;
regDeviceDone = RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]));
The following two lines were modified by me:
Rid[0].hwndTarget = gameWindowHandle;
There I define the Unity window as target. gameWindowHandle is set by EnumWindows.
The other line I changed is the last one due to there is a syntax error (missing parenthesis).
As far as I understood the documentation right this should be it. Now the following callback should be called when there are WM_INPUT messages sent to the Unity window.
LRESULT CALLBACK WindowProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
) {
printf("%d", uMsg);
switch (uMsg) {
case WM_INPUT:
UINT dwSize = 40;
static BYTE lpb[40];
GetRawInputData((HRAWINPUT)lParam, RID_INPUT,
lpb, &dwSize, sizeof(RAWINPUTHEADER));
RAWINPUT* raw = (RAWINPUT*)lpb;
if (raw->header.dwType == RIM_TYPEMOUSE)
{
int xPosRelative = raw->data.mouse.lLastX;
int yPosRelative = raw->data.mouse.lLastY;
printf("X: %d, Y: %d", xPosRelative, yPosRelative);
}
break;
}
return NULL;
}
My problems
The first problem I have is that calling this
regDeviceDone = RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]));
does not return true as it should. Instead it returns false and GetLastError gives me error 87 (after googling this I found out it has to do with wrong parameters).
The documentation says to do so but unfortunately it does not work the way I do it.
Another problem is how to keep the application alive. After registering the device I need to wait for the callbacks to trigger (if they would work). How can I achieve that the application does nothing than waiting for the callbacks?
Is my approach even reasonable or am I doing completely wrong and have to use different APIs?
Your approach is wrong. First, RawInput requires Window. A Window under your control with your own WndProc. Hence in your C++ library, you should define a window procedure. Start a thread. In this thread register window class with that procedure. After you succeed in registering your class, create HWND_MESSAGE window, register your devices and enter a while GetMessage... DispatchMessage loop. This should be done in a separate thread. In your window procedure you must now catch WM_INPUT messages. Enjoy.

Get Window Handle (HWND) of a window created by a library call

EDIT: I forgot to mention, I do not have source code for the DLL that creates window, so I can't actually change the function to return HWND.
I am creating a Win32 application, and am using a DLL that creates a window for me through one of its exported function "void X();" I call X() in my WinMain().
It does create a window for me. I want to get the HWND of the window that was created by this exported library function, as X() returns void, so I can use it for other API calls.
Can someone tell the easiest to get the HWND?
I have searched and questions answered here, but I cant somehow figure out the exact, appropriate solution. I tried EnumWIndows() and then getting the Process ID, and then comparing with the current thread process ID. But I guess there should be a far better much more efficient and a easy way to get HWND.
After all, I am in the WinMain of the process that created this window in the first place.
If I need to explain anything, that I have missed out writing here, please let me know.
I am sure that this is very basic and am missing something blatantly here. Sorry.
Thanks & Regards!
Use a tool like Spy++ or Winspector to see all of the HWNDs created by your app, in particular their class names and window titles. Then you can copy those values into your code and make a single call to FindWindow() after the DLL has created its window, eg:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// ...
X();
HWND hWnd = FindWindow("ClassNameHere", "TitleHere");
// ...
return 0;
}
The easiest way to do that is to use the function SetWindowsHookEx(WH_CBT, fun, NULL, GetCurrentThreadId()). Then the fun function, a callback defined by you, will be called when a number of events happen. The one you want is the HCBT_CREATEWND.
Somethink like that (totally untested):
HWND hDllHandle = NULL;
LRESULT CALLBACK X_CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HCBT_CREATEWND)
hDllHandle = (HWND)wParam;
return CallNextHookEx(NULL, nCode, wParam, lParam); //The first parameter is useless
}
HWND CallXAndGetHWND()
{
HHOOK hDllHook = SetWindowsHookEx(WH_CBT, X_CBTProc, NULL, GetCurrentThreadId());
X();
UnhookWindowsHookEx(hDllHook);
//hDllHandle is a global variable, so will be now you window!
return hDllHandle;
}
Note that this function is not thread-aware, but most likely you will call it just once at the beginning of your code, so it shouldn't matter.
And beware! Many functions, even Win32 API functions, create hidden windows. This code will hook all of them and return the last one to be created. Changing it to return any other, or even a list of them, if needed, should be trivial.

When does EnumDisplayMonitor return?

I am using EnumDisplayMonitor to retrieve information about the displays connected to a system. Calling EnumDisplayMonitor requires that a callback function is provided which is then invoked to receive details of each enumerated monitor. My question is when does EnumDisplayMonitor return? Is it immediately or does it block until the callback has been called for each enumerated monitor? I want to process a data structure that will have been altered by the callbacks and I need to know if it's safe to do it immediately after the EnumDisplayMonitor call. If the call doesn't block is there a way to check that the callback has finished being called? This might be a general question about callbacks....
e.g.
BOOL CALLBACK MonitorEnumProc(
__in HMONITOR hMonitor,
__in HDC hdcMonitor,
__in LPRECT lprcMonitor,
__in LPARAM dwData)
{
// Alter something here - e.g. Add lprcMonitor to a list.
}
int main()
{
EnumDisplayMonitor(NULL, NULL, MonitorEnumProc, 0);
// Can I rely on EnumDisplayMonitor to have finished making calls to
// MonitorEnumProc at this point?
}
I've checked the MSDN entry and it does not help in this respect and I would confirm by experiment but I don't have enough monitors to test it reliably.
It returns when it has finished calling your callback functions. So the sequence of events looks like this:
Enter: EnumDisplayMonitor
Callback: MonitorEnumProc
Callback: MonitorEnumProc
Callback: MonitorEnumProc
...
Leave: EnumDisplayMonitor
All the Windows API routines of this ilk behave this way, e.g. EnumProcess, EnumWindows etc.
Code has to run in the context of a thread and if such an enumeration routine were to return immediately and call the callbacks asynchronously, it would have to spawn a thread to do so. You can apply the principle of least surprise here!

How to get a DLL loading process handle

I'm trying to get the handle to the process which loaded a dll from the dll.
My approach is:
in DLL_PROCESS_ATTACH I call EnumWindows(EnumWindowsProc,NULL);
my EnumWindowsProc implementation is the following:
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) {
if(GetCurrentProcessId() == GetWindowThreadProcessId(hWnd,NULL)){
MessageBox(hWnd,L"I loaded your dll!",L"it's me",MB_OK);
return TRUE;
}
return FALSE;
}
the problem is that GetCurrentProcessId() == GetWindowThreadProcessId(hWnd,NULL) is never true (if i place the messagebox call outside the if block everything works but it gets called once for every listed window).
Is there any other way to get to the point? Is this approach totally wrong or am I just missing something?
Thanx in advance
Use GetCurrentProcess, which returns a pseudo-handle to the current process. If you need a real handle, pass in the pseudo-handle to DuplicateHandle.
Note that it is very dangerous to do too much in DllMain. Calling anything other than KERNEL32 functions is quite dangerous, and even then there are some KERNEL32 functions that you shouldn't be calling. See the DllMain documentation, this document, and several blog posts from Microsoft developers recommending against doing too much in DllMain.
Easiest way would be to simply use GetCurrentProcess whenever you need the handle.
Try calling GetProcessHandleFromHwnd().
You made a mistake:
GetWindowThreadProcessId does not return the process ID but the thread ID.
Your program must be written like this:
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) {
DWORD process;
GetWindowThreadProcessId(hWnd,&process);
if(GetCurrentProcessId() == process){
MessageBox(hWnd,L"I loaded your dll!",L"it's me",MB_OK);
return TRUE;
}
return FALSE;
}