SetWindowsHookEx process-wide instead of system-wide - c++

I'd like to use SetWindowHookEx to catch WM_CREATE (or HCBT_CREATEWND) messages in a process before a creation of a window.
Using the hMod and dwThreadId it is possible to define whether the hook will be system-wide (by setting hMod to be the gInstance of the DLL and dwThreadId to 0), it is also possible to use it to monitor a SINGLE thread in a process (hMod = 0, and dwThreadId = ThreadToMonitorId).
However, I'd like to monitor multiple threads. Is it possible? I guess I can simply call SetWindowHookEx for multiple threads but I'd rather not as it would make things more complex. Are there other alternatives?
Thanks!

You could hook all processes and only process WM_CREATE for the current process. As the hook is called in the context of the process itself, you can simply compare GetProcessId() to the desired process id.

It is very unusual for a process to create more than one thread that owns a UI window. Sometimes it is a interop window which is intentionally hidden, unlikely that you'd want to know about it. Verify your assumptions with Spy++, the owner thread ID is shown in the window properties, Process tab.
If it does have more than one thread creating windows that you want to know about then you'll want to set separate hooks.

Related

Window procedure and CreateWindowEx function

Does the Window Procedure specified as lpfnWndProc by window class during registration runs in a separate thread ?
There is an important concept in windows called the message loop.
It is usually inside the main function (aka: WinMain) and can be characterized in the following manner:
while (true) {
// blocks until there's a new message to process
GetMessage()
TranslateMessage()
// ends up calling the propper WndProc callback
DispatchMessage()
}
Update: When you create a window, the thread on which the window is created owns the windows (and the its message queue). Therefor, it must provide the message loop process. This is usually done in the application's main thread but, as other user stated, it can also be done in a separate thread.
The function DispatchMessage takes care of executing the WindowProc procedure of the window targeted by the message (as specified by the message's hwnd parameter).
So, when you create a window, the lpfnWndProc parameter specifies where you want to be notified for events (mouse clicks, keyboard presses, etc). And it is always called in the same thread (the application's main thread or the one which owns the window).
A word of advice: If you need to perform a potentially long operation as the result of an event, you must create a new thread (aka background worker) for the task, and perform some kind of IPC to notify the main thread when the function is finished.
You can find instructions about how to write a windows procedure here. Also, there is some info about the main loop in this wikipedia page.
Does the Window Procedure specified as lpfnWndProc by window class during registration runs in a separate thread ?
No, it is called (as a callback) when events (aka messages) are dispatched by your message loop. In this way - the so-called 'event-driven' model - your program is able to react to user input as and when it happens without having to deal with any multi-threading or re-entrancy issues.
You might have more than one thread, but if it has windows associated with it (i.e. CreateWindowEx was called by that thread) then it would need to have its own message loop.

Get notified when a Window closes (or it's owning thread disappears)

I have a hwnd, which my process does not own, and I want to be notified when it disappears so that my code can perform cleanup actions. What's the best way to do this?
To detect when the HWND's owning process disappears, you can get the HWND's process ID from GetWindowThreadProcessId(), then get a HANDLE to the process using OpenProcess(), and then use WaitForSingleObject() or other related wait function. A process handle is signaled when the process exits.
To detect when just the HWND disappears, get the HWND's thread ID from GetWindowThreadProcessId() and then use SetWindowsHookEx() to hook the message queue of that thread so you can intercept WM_DESTROY and WM_NCDESTROY messages for all HWNDs belonging to that thread, looking for the particular HWND that you are interested in. Note that your hook must be implemented in a DLL when hooking another process, so you will have to use an inter-process communication mechanism of your choosing to notify your main app when the HWND is destroyed.

Setting a HWND's lpfnWndProc from another process

I have a win32 main application that spawns a child process.
At the moment I use CreateWindowEx to create a HWND in the main application followed by spawning a child process. The child process then looks up the HWND using FindWindow. I would like to handle the Window messages (e.g. WM_SIZE, WM_SETFOCUS etc) for this HWND in the child process, therefore I tried setting the GWLP_WNDPROC attribute in the child process but I'm getting an access denied error, which is reasonable.
I thought about creating a HWND directly in the child process instead but when the window is clicked on, the main application loses focus which is not acceptable for my use case.
Does anyone have a suggestion on what to do to keep the focus on the main application, while having the child process handling the messages?
Use SetWindowsHookEx with one of the windows message hooks (e.g. WH_CALLWNDPROC) to intercept the messages going to other windows, then filter by the HWND of the window in question.
In your child process you can call ShowWindow with WS_NOACTIVATE. When calling CreateProcess function you can specify STARTUPINFO as follows:
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNOACTIVATE;
You can even explicitly give back focus in your child application to main window.
I suppose you want to have similar design to what chromium does. If you look closely at their design docs:
http://www.chromium.org/developers/design-documents/inter-process-communication
you will see that they do implement IPC between processes but they do not have single message processing function in main process.
As last hint - not related to question, read on jobs under windows - this mechanism allows to take a closer control on child processes.

Are Win32 windows thread safe?

I'd like to create a window on one thread, and then have that HWND migrate to one of any number of threads on which it will execute. My program will have multiple such windows. Is this possible or was the Win32 API not designed for this?
Yes, to a certain extent.
You can send and post messages to an HWND from any thread.
http://msdn.microsoft.com/en-us/library/ms644944(v=VS.85).aspx
Attempting to configure the UI (e.g. add controls) from another thread will end badly. However, if you send your window a message, you can be sure that the message will be processed on the creating thread.
No, this is not possible. The thread that a window uses for its message loop (what you refer to as "executing on") is defined at the time the window is created. You can create multiple threads and start message loops from them (and thus create windows on them), but this is generally regarded as dangerous.
There are two important calls that must be called from the same thread: CreateWindow and GetMessage (or their respective equivalents). Your solution wouldn't, so it's wrong.
You may call PostMessage in any thread. SendMessage is somewhat dangerous because it blocks in cross-thread scenario's, and could deadlock.
No, there is no concurrency checking on those calls.

WINAPI: Look at messages from other process

I'm quite new to the Windows API and would like to know how to peek at messages another process receives. As an example, I would like to get the HWND of, say, notepad and peek at all messages that are sent to this window. I code in C/C++.
Thank you
You can use SetWindowsHookEx function, with WH_CALLWNDPROC or some other type of hook, and here is an example.
The WH_CBT can give you great opportunities because you can get a HCBT_CREATEWND code from it and it's sent to you right before a window is created, thus giving you a possibility to provide your own window proc instead of the real one and then be able to get all messages possible with it.
Remember though, greater possibilities also mean greater responsibility. Say you "subclassed" some window, providing your window proc, if your application that set a hook exits, next thing you'll see is the application, whose messages you were peeking at, crashes if you didn't put the address of the original window proc back to where it belongs. The benefit of this kind of hooking is the ability to wait for a certain window (say with a certain window class, or name) to be created and get into that process before any window you're interested in would even be created.
You want to look into SetWindowsHookEx
You are looking for Windows Hooks .
http://msdn.microsoft.com/en-us/library/ms997537.aspx
You can trap SendMessage in the target process using CallWndProc hook procedure.