How to identify the window is belong to a specific process? - windows

Win32 programs have an entry parameter HINSTANCE for the Win32 entry function WinMain(). When you create your own window, the CreateWindow() API call needs this parameter.
My first idea in my mind is that this HINSTANCE should be some unique identify to distinguish different windows belong to different processes. Until recently, in some occasions, I use this HINSTANCE. Wow! If you open the same Win32 program (EXE) twice, each process has the same HINSTANCE value.
Later I figured out, it was some resource identifier (memory address) in the process. It's a virtual address for the process which is related to its PE structure in memory.
Now, if I have the two windows' HWND handles, and I want to check whether the two windows are from the same process, what is the best choice?

You can use the GetWindowThreadProcessId function to retrieve the ID of the process that created a window, given that window's HWND.
Below is a brief C code snippet showing how. We check that the return value of each GetWindowThreadProcessId() call is not zero (see this answer or this blog by Raymond Chen), to ensure that we have passed valid HWND handles.
// win1 and win2 are both HWND handles to check...
DWORD proc1, proc2;
if (!GetWindowThreadProcessId(win1, &proc1)) { // Error (invalid HWND?)
//.. error handling
}
if (!GetWindowThreadProcessId(win2, &proc2)) {
//..
}
if (proc1 == proc2) {
// Windows created by same process
}
else {
// Windows created by different processes
}

GetWindowThreadProcessId can do the work. Record here.

An interactive way to do this would be to use Microsoft's Spy++, which lets you find the Process ID, Thread ID, and parents/children of a window by point-and-clicking its GUI.
You can also find window handles (and plenty of other window-specific data) in this way.

Related

GetWindowModuleFileNameW() get window's exe path fail with error 126? [duplicate]

I try to get the name of executable name of all of my launched windows and my problem is that:
I use the method
UINT GetWindowModuleFileName(
HWND hwnd,
LPTSTR lpszFileName,
UINT cchFileNameMax);
And I don't understand why it doesn't work.
Data which I have about a window are: -HWND AND PROCESSID
The error is:
e.g:
HWND: 00170628
ProcessId: 2336
WindowTitle: C:\test.cpp - Notepad++
GetWindowModuleFileName(): C:\test.exe
HWND: 00172138
ProcessId: 2543
WindowTitle: Firefox
GetWindowModuleFileName(): C:\test.exe
HWND: 00120358
ProcessId: 2436
WindowTitle: Mozilla Thunderbird
GetWindowModuleFileName(): C:\test.exe
Note: test.exe is the name of my executable file, but it is not the fullpath of Notepad++... and it make this for Mozilla Thunderbird too... I don't understand why
I use the function like this:
char filenameBuffer[4000];
if (GetWindowModuleFileName(hWnd, filenameBuffer, 4000) > 0)
{
std::cout << "GetWindowModuleFileName(): " << filenameBuffer << std::endl;
}
Thank you for your response.
The GetWindowModuleFileName function works for windows in the current process only.
You have to do the following:
Retrieve the window's process with GetWindowThreadProcessId.
Open the process with PROCESS_QUERY_INFORMATION and PROCESS_VM_READ access rights using OpenProcess.
Use GetModuleFileNameEx on the process handle.
If you really want to obtain the name of the module with which the window is registered (as opposed to the process executable), you can obtain the module handle with GetWindowLongPtr with GWLP_HINSTANCE. The module handle can then be passed to the aforementioned GetModuleFileNameEx.
Example:
TCHAR buffer[MAX_PATH] = {0};
DWORD dwProcId = 0;
GetWindowThreadProcessId(hWnd, &dwProcId);
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ , FALSE, dwProcId);
GetModuleFileName((HMODULE)hProc, buffer, MAX_PATH);
CloseHandle(hProc);
Aaah. I read the MSDN page at the bottom.
From http://support.microsoft.com/?id=228469 (archive.org link):
GetWindowModuleFileName and GetModuleFileName correctly retrieve information about windows and modules in the calling process. In Windows 95 and 98, they return information about windows and modules in other processes. However, in Windows NT 4.0 and Windows 2000, since module handles are no longer shared by all processes as they were on Windows 95 and 98, these APIs do not return information about windows and modules in other processes.
To get more information on Windows 2000, use the Process Status Helper set of APIs (known as PSAPI, see Psapi.h include file), available since Windows NT 4.0. APIs such as GetModuleFileNameEx and GetModuleBaseName offer equivalent functionality.
Try using GetModuleFileNameEx instead.
http://support.microsoft.com/?id=228469 (archive.org link)
The executive summary is, GetWindowModuleFileName() doesn't work for windows in other processes in NT-based Windows.
Instead, you can use QueryFullProcessImageName() once you have a handle to the process. You can get a handle to the process with OpenProcess(), which you can use once you have a process id. You can get the process id from the HWND by using GetWindowThreadProcessId()
This is an example of how get the name of executable that creates window, hope it can give you some ideas about:
while(true)
{
Sleep(250);//reduce cpu usage
CHAR __name[MAX_PATH];//name buffer
HWND hwnd;//window handle
DWORD pid;//process pid
hwnd=FindWindow(NULL,NULL);//find any window
PROCESSENTRY32 entry;//process structure containing info about processes
entry.dwSize=sizeof(PROCESSENTRY32);
HANDLE snapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);//get processes
if(hwnd!=0)
{
GetWindowThreadProcessId(hwnd,&pid);//get found window pid
}
if (Process32First(snapshot,&entry)==TRUE)//start listing processes
{
while (Process32Next(snapshot,&entry)==TRUE)
{
if (stricmp(entry.szExeFile,"explorer.exe")==0)
{
if(pid!=entry.th32ProcessID)//if found window pid is explorers one, skip it
{
HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);//open processusing PROCESS_ALL_ACCESS to get handle
if(hProcess!=NULL)
{
GetModuleFileNameEx(hProcess,NULL,__name,MAX_PATH);//get executable path
cout<<"Found: "<<__name<<endl;
}
}
}
}
}
To use GetModuleFileNameEx() you probably will need to set linker settings to link library psapi. Also include psapi.h.

How does GetWindowText get the name of a window owned by another process without a syscall to read that process's memory?

I wanted to figure out what the syscalls behind GetWindowText are. I wrote a simple program to call GetWindowText with a handle to a window in a different process.
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MessageBox(0,"Attach debugger and set bp","on GetWindowTextA",0);
HWND winmine = FindWindow(NULL,"Minesweeper");
if(winmine != NULL)
{
char buf[255] = "";
GetWindowTextA(winmine, buf, 254);
MessageBox(0,buf,"Found",0);
}
else
{
MessageBox(0,"?","Found nothing",0);
}
return 0;
}
I attached a debugger and stepped through the GetWindowTextA call, manually stepping through everything except these API calls (in order):
GetWindowThreadProcessId (in GetWindowLong)
InterlockedIncrement
WCSToMBEx (which is basically WideCharToMultiByte)
InterlockedDecrement
None of these API calls seem to be able to read a string in memory not owned by the calling process. I used a usermode debugger so I certainly didn't end up in kernelmode while stepping without realizing it. This means that GetWindowText got the window name without performing a context switch. Which seems to imply that the text for every window that exists is accessible without a context switch.. and that can't be right because there's no way Windows keeps a copy of the text for every single window/control on the system, on every single process.
I have read this article. It mentions that window names are stored in quote "a special place", but does not explain how this "special place" can be accessed from a different process without a syscall/context switching.
So I'm looking for any explanations as to how this is done. Any information you can provide is greatly appreciated.
GetWindowText got the window name without performing a context switch. Which seems to imply that the text for every window that exists is accessible without a context switch.
This info is stored in memory that is shared between all the processes that use user32.dll. You may try to search virtual space of your process for unicode names of other processes' windows.
It gets mapped into the process address space during user32.dll loading. There are some kernel structures/sections involved: win32k!gSharedInfo, win32k!ghSectionShared, win32k!gpsi and others (which I don't know of).
Actually, the lower 16 bits of HWND represents index into window info array with base address *(&user32!gSharedInfo + 1). The first field of this window info is the kernel address of another structure which contains all the shared window information. Subtracting the difference between kernel address of the section and its user-space mapping (which is stored in TEB!Win32ClientInfo) you can get relevant info.
user32!ValidateHwnd is the function that converts window handle into this address which can be used by inner user32 functions like user32!DefWindowProcWorker.
Pseudocode of GetWindowTextW looks like (excluding error-handling):
GetWindowTextW(HWND hwnd, wchar_t* buf, int size)
{
inner_hwnd = ValidateHwnd(hwnd);
if (TestWindowProcess(inner_hwnd))
SendMessageWorker(inner_hwnd, WM_GETTEXT, size, buf, FALSE);
else
DefWindowProcWorker(inner_hwnd, WM_GETTEXT, size, buf, FALSE);
}
DefWindowProcWorker which is called in your case with WM_GETTEXT will just parse the structure referenced by inner_hwnd and copy window's name into buf.
it seems that the text for EDITTEXT controls are not stored in this manner
I never knew all the info that was stored in there though it seems like a good choice to not pollute processes' virtual space with all kinds of user/gdi params. Besides, lower integrity processes should not be able to get higher integrity processes sensitive information.
because there's no way Windows keeps a copy of the text for every single window
The text most certainly exists, just not as a copy. The text for a window is stored in the virtual memory of the process that owns the window. Might be in RAM, not terribly likely if the process has been dormant for a while, definitely on disk in the paging file. Which doesn't stop GetWindowText() from making a copy. On-the-fly, when you call it.
GetWindowText() is limited, it is documented to only being capable of copying the caption text of a window, so it probably uses the desktop heap for the session to retrieve the text. Not otherwise a restriction to a winapi function like SendMessage(), you can use WM_GETTEXT to obtain a gigabyte from an Edit control. That certainly crosses the process boundary.
As an operating system function, SendMessage can of course break all the rules that apply to normal processes. The OS has no trouble addressing the VM of an arbitrary process. Rules that are routinely broken, your debugger does it as well. With functions that you can use to also break the rules, ReadProcessMemory() and WriteProcessMemory().

SetWindowsHook Global not very Global

I'm playing around with SetWindowsHookEx, specifically I would like be able to find out about any window (on my desktop) thats been activated, via mouse or keyboard.
Reading through MSDN docs for SetWindowsHookEx it would appear that a WH_CBT type would do the job. I've created a dll and put all the code in there, which I control from a gui app (which also handles the unhook).
BUT I only appear to be getting the activation code when I activate my gui app though, any other app I activate is ignored.
In my dll I have the setup code and the CBTProc like so:
LRESULT WINAPI CBTProc(int Code, WPARAM W, LPARAM L) {
if(Code<0) CallN....
if (Code == HCBT_ACTIVATE) { // never get unless I activate my app
HWND a = reinterpret_cast<HWND>(W);
TRACE("this window was activated %d\n", a);
}
CallNext....
}
EXPORTED HHOOK WINAPI Setup(HWND MyWind) {
...
// gDllUInstance set in dllmain
return SetWindowsHookEx(WH_CBT, CBTProc, gDllUInstance, 0);
}
All pretty simple stuff, i've tried moving the setup out of the dll but I still get the same effect.
It would appear that the dll is getting loaded into other processes, I'm counting the number of DLL_PROCESS_ATTACHs I'm getting and can see its going up (not very scientific i know.
NOTE that this is 32 bit code running on 32bit OS - win2k3.
Are my expectations of the hooking mechanism wrong? should I only be getting the activation of my app or do I need a different type of hook?
EDIT: the trace function writes to a file telling me whats sending me activations
TIA.
Turns out its working ok, as Hans points out, i'm just not seeing the output from the debugger from the other processes, if I put in some extra tracing code - one trace file per attached process - I can see can see that things are working after all.
Many thanks for the replies.

Problems with 'cross process subclassing'

Two questions.
1) I understand this must be an expected outcome but maybe someone can tell me what I'm doing wrong; I'm trying to subclass all window classes in a global hook and it works except that I'm not able to close shop as I should and when the program initially registering the hook unregisters the hook and exits, subclassed applications start crashing.
Here's how I'm trying to do it..
// stores original wndprocs. In the hook dll, outside the shared memory.
map<HWND, WNDPROC> origWndProcs;
// in an EnumWindows callback, executed for all HWND's, also in the hook dll (UWM_REMOVE_HOOK is a registered unique message)
SendMessageTimeout(hWnd, UWM_REMOVE_HOOK, 0, 0, SMTO_ABORTIFHUNG | SMTO_NORMAL, 15000, res);
// Still in the same hook, in the subclassing wndproc..
if (msg == UWM_REMOVE_HOOK) {
if (origWndProcs.find(hwnd) != origWndProcs.end()) {
SetWindowLongPtr(hwnd, GWL_WNDPROC, (LONG_PTR)origWndProcs[hwnd]);
}
}
// clears the hook..
__declspec(dllexport) BOOL ClearHooks(HWND hWnd) {
BOOL unhooked = UnhookWindowsHookEx(hook) &&
UnhookWindowsHookEx(kb_hook) &&
UnhookWindowsHookEx(mouse_hook) &&
UnhookWindowsHookEx(cbt_hook);
if(unhooked)
hWndServer = NULL;
return unhooked;
}
In DllMain I don't do anything on DLL_PROCESS_DETACH. Instead, ClearHooks() is called from the program originally registering the hooks and there only after the hook has sent a message signalling that it has executed the EnumWindows operation (restores original wndprocs, see above).
I subclass windows in a WndProc hook; all visible windows that receive a message and whose current wndproc is not the one in the dll, are subclassed.
Basically all (as far as I can tell) applications crash on exit despite the fact that windows do seem to get the wndproc set back to what it was when it was replaced. Anyone have a clue what I might be doing wrong?
2) I need this to intercept WM_MINMAXINFO and modify window maxsize whenever a window is maximized. Unfortunately I can't do this in the dll but I have to talk with a program to get the size info. So, what's the best way to talk to that window; I need it to pass back some info so I can modify the structure that came with the original WM_MINMAXINFO message. Will a structure in WM_COPYDATA preserve it's data until the call to SendMessageTimeout returns?
Thanks
There are plenty of pain points here. You assume that no other code will subclass the window. And that such code will un-subclass it in the right order. There is no right order, your hooking is quite asynchronous from the program's execution.
But, the workaround is simple enough. You are already hooking with SetWindowsHookEx, might as well do one more. WH_CALLWNDPROC or WH_CALLWNDPROCRET, depending on what you want to do.

Attach window to running application

I have customer that uses older, custom built ERP application for which they don't have source code and company that developed it does not exist any more. Application is developed in 2000 and it's built with Delphi. Since last executable is from 2003, it could be D6 or D7.
On one important form there are some fields where customer would like to display additional data from other databases and asked me if it's possible to "duct tape" data over existing form.
First idea I got is to build application that will:
browse list of windows target application creates and find controls on form
attach "some" event when to get notified when target form is displayed
attach "some" event when to get notified when field on target form is changed
display additional information in small window overlaying target form
Are there any examples on how to do something like this. I searched google with variations of this question title, but without success.
Note - rewriting of ERP application is not planned.
About language - I can do it with C# or Delphi.
I'm going to answer this from a purely C & Win32 point of view, because I don't know Delphi or its libraries. Converting this to C# can be accomplished via p/invoke, but some parts may/will need to be unmanaged.
First off, no guarantees. If the target application is doing windows-less controls (if there isn't an HWND under every on-screen control) you're pretty much out of luck. This isn't all that uncommon, so yeah...
Step 1, register a window hook listening for new windows created by the target process*:
//dllHMod is an HMODULE that refers to the DLL containing ShellHookProc
HHOOK hook = SetWindowsHookEx(WH_SHELL, ShellHookProc, dllHMod, 0);
// error handling, stashing hook away for unregistering later, etc...
LRESULT CALLBACK ShellHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(nCode < 0) return CallNextHookEx(NULL, nCode, wParam, lParam);
if(nCode == HSHELL_WINDOWCREATED)
{
WindowCreate((HWND)wParam);
}
return 0;
}
WindowCreated(HWND) should stash the HWND away if the correct process (determined via GetWindowThreadProcessId) owns it. At this point, you'll be able to get every top-level window owned by the target process. Note that registering a global hook carries a notable performance penalty, not that it really matters in your case but you should expect it.
Now for the fun part. There's no reliable way to tell when a window is fully constructed, or when its done rendering (there are ways to tell when it STARTS rendering, but that doesn't really help). My advice, guess. Just throw some arbitrary wait in there and then try and enumerate all the child windows.
To enumerate child windows (if you know enough about the target window, there are better ways to do this; but I'm assuming a search is easiest):
//targetHWND is an HWND of one of the top-level windows you've found
EnumChildWindows(targetHWND, ChildWindowCallback, NULL);
//more code...
BOOL ChildWindowCallback(HWND window, LPARAM ignored)
{
if(IsTargetWindow(window)) { /* Do something */ }
return TRUE;
}
Implementing IsTargetWindow is another tricky part. Hopefully you'll find some reliable test for doing so (like checking the class name, window name, style, something; look at GetWindowInfo).
Once you have the window you want to monitor, you can use SetWindowLongPtr and GWLP_WNDPROC to watch all messages it receives. This will require code injection (and thus unmanaged code) and is awfully low level. I'd advise against it if you could possibly avoid it, but lacking the source...
I think this answers is a decent starting point, but once again this is going to be incredibly painful if its even possible at all. Good luck.
*Alternatively, if you know that the target app doesn't create windows except at startup (or at detectable/predictable points in time) you can use EnumWindows.

Resources