How to get a DLL loading process handle - c++

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;
}

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 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.

WINAPI's message loops drives me crazy

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.

Window Maximum Maximise

I am looking to create a program where I can set the maximum maximize size (as in the size the window maximises to when you hit the maximise button) and maximize position (X/Y coordinated for the maximised window) for all of the windows that are running. This is so that I can have my Rainmeter visible at all times on my secondary monitor without having to manually resize every window fit inside of it.
I have managed to do this for a simple program I wrote using MINMAXSIZE from the WinAPI. This method seems to work perfectly for my little program, but there is very little documentation on it beside 1 or 2 articles on the internet. I was wondering if this would be the best way to set the maximum maximise size, or if there is another way to do this.
They way I planned to implement this into all of the applications was going to be either DLL Injection or Hooks (neither of which I have any experience with), so I was also wondering your guys' thoughts on these methods.
I know there are a few applications out there that already do this, but I thought this could be a learning experience, and as well, all of the applications I tried do not work very well (although this could be the case with all of them due to the way Windows functions).
If any of you are still unsure about what I am talking about, MaxMax does exactly what I want (although it doesn't work so well, as I stated in my previous paragraph).
Thank you all in advance.
What you're probably looking for is the work area setting, that you can set/retrieve with the SystemParametersInfo function, called with the flags SPI_SETWORKAREA/SPI_GETWORKAREA.
What you want to do is use a global windows hook to handle WM_GETMINMAXINFO. As you may be aware, this is the message that is:
Sent to a window when the size or position of the window is about to
change. An application can use this message to override the window's
default maximized size and position, or its default minimum or maximum
tracking size.
The best way to use this to override the default maximum is to fill in the MINMAXINFO structure like so:
case WM_GETMINMAXINFO: {
DefWindowProc(hWnd, message, wParam, lParam);
MINMAXINFO* mmi = (MINMAXINFO*)lParam;
mmi->ptMaxTrackSize.x = 100;
mmi->ptMaxTrackSize.y = 100;
return 0;
}
This will allow the default values to be assigned to the sizes you don't care about (min x/y) in this case, leaving you to fiddle with the max values as you please. Your windows hook should be done with SetWindowsHookEx() and should look something like this:
SetWindowsHookEx(WH_CALLWNDPROC, hook_procedure, instance_handle, 0);
hMod (instance_handle) should only be set depending on the circumstances (check the docs for this). The dwThreadId mandates a global hook. Your CallWndProc might looks something like this:
__declspec(dllexport) LRESULT WINAPI CallWndProc(int nCode, WPARAM wParam, LPARAM lParam) {
CWPSTRUCT* cwp = (CWPSTRUCT*)lParam;
if(WM_GETMINMAXINFO == cwp->message) {
DefWindowProc(hWnd, message, wParam, lParam);
MINMAXINFO* mmi = (MINMAXINFO*)lParam;
mmi->ptMaxTrackSize.x = 100;
mmi->ptMaxTrackSize.y = 100;
return 0;
}
return CallNextHookEx(next_hook, nCode, wParam, lParam);
}
Unfortunately something you are going to have to deal with is that the only windows that will be hooked are the ones that had were existing when you made your call to SetWindowsHookEx(). I'm not aware of a clean way of getting past this, short of looping a call to SetWindowsHookEx() (ergh!).
You could potentially do this with DLL injection and effectively subclass every window with EnumWindows, EnumChildWindow and SetWindowLongPtr/SetWindowSubclass. But why go to all that trouble when you could just use SetWindowsHookEx? :)
To alter the x/y, you might have to add an override for WM_SYSCOMMAND and check for SC_MAXIMIZE then use SetWindowPos/MoveWindow to position it properly (if you don't want it on the default 0, 0).

SetWindowLongPtr doesnt work properly

I want to subclass RichEdit in my program (here is c++ code: http://dumpz.org/46182/). _native_log is a hwnd of richedit. At first all works fine and LogWindow::wndProc callback called normal, but if i set some text in RichEdit or click on them LogWindow::wndProc stops work (there no any further calls of it). Is there any thoughts what's i do wrong?
void LogWindow::replaceNativeLog(HWND native_log_handle) {
_native_log = native_log_handle;
SendMessage(_native_log, EM_GETOLEINTERFACE, 0, (LPARAM) &_rich_edit_ole);
_old_wnd_proc = (WNDPROC) SetWindowLongPtr(_native_log, GWLP_WNDPROC, (LONG) &wndProc);
}
LRESULT LogWindow::wndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
switch (Msg) {
case EM_STREAMIN:
break;
case WM_SETTEXT:
break;
};
return CallWindowProc(_old_wnd_proc, _native_log, Msg, wParam, lParam);
}
Starting with Common Controls version 6 the procedure of subclassing windows has been revised to eliminate the issues with previous versions. In particular it is no longer a problem if a control is subclassed more than once.
A comparison between subclassing pre-v6 Common Controls and the v6 way of doing things can be found at "Subclassing Controls". Instead of calling SetWindowLongPtr to replace the window procedure there is SetWindowSubclass which in addition to replacing the window procedure does all the internal bookkeeping. A consequence of the redesign is that you do not have to store a pointer to the previous window procedure either; if you need to call into the original window procedure there is DefSubclassProc at your disposal.
This of course will only help if all competing clients trying to subclass the a control all agree on using the v6 style subclassing.
Finally, I found the problem. I actually develop a plugin for Miranda IM, and there was another function trying to subclass richedit i want. So there is a kind of conflict between my and that functions. Thanks all for trying to help.