GetWindowText got the window name without performing a context switch. This, apparently, means that the text for each available window is available without a context switch.
This information is stored in memory that is shared by all processes using user32.dll . You can try to find the virtual space of your process for the unicode names of other process windows.
It is mapped to the process address space during user32.dll loading. There are some kernel structures / sections: win32k!gSharedInfo , win32k!ghSectionShared , win32k!gpsi and others (which I do not know about).
In fact, the lower 16 bits of the HWND represent the index into the index information array with the base address *(&user32!gSharedInfo + 1) . The first field of this window is the kernel address of another structure, which contains all the information about the general window. Subtracting the difference between the address of the kernel of the partition and its user space mapping (which is stored in TEB!Win32ClientInfo ), you can get the relevant information.
user32!ValidateHwnd is a function that converts a window handle to this address, which can be used by internal user32 functions such as user32!DefWindowProcWorker .
The GetWindowTextW pseudo- GetWindowTextW looks (except for 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 simply analyze the structure referenced by inner_hwnd and copy the window name to buf .
text for EDITTEXT controls doesn't seem to be saved this way
I never knew all the information that was stored there, although it seems like a good choice so as not to pollute the virtual process spaces with all types of user / gdi . In addition, lower integrity processes should not receive more important process integrity information.