Parsing the organization of Windows NT/2000 window objects (http://webcrazy.yeah.net /)

Source: Internet
Author: User
Parse Windows NT/2000 window Object Organization
WebSphere (http://webcrazy.yeah.net /)

Microsoft spy provided by Microsoft Visual Studio has a very intuitive display of Windows window organizations. In the Windows view, window properties can display a lot of window content or properties. This article describes the underlying organization of these important structures in Windows NT/2000 from the Windows NT/2000 kernel.
Start with window organization. We know that enumeration windows can be implemented through enumwindows, enumdesktopwindows, enumchildwindows, and other APIs. After I really want to understand the details of implementing these APIs in Windows NT/2000, I should be able to find many internal executions in Windows NT/2000. So I carefully studied these Apis, the following is an analysis of the enumwindows API in Windows 2000 Server build 2195:

1. For enumwindows under user32.dll, call internalenumwindows under user32.dll, and internalenumwindows call buildhwndlist (user32.dll ).
2. buildhwndlist calls ntuserbuildhwndlist, which is also in the user32.dll module.
3. ntuserbuildhwndlist only calls the int 2E command, and then uses the system service with ID 0x0000e, that is, ntuserbuildhwndlist in the win32k. SYS module. For details, see Windows 2000 system services list. From this point on, the user State enters the core state.
4. ntuserbuildhwndlist in win32k. sys continues to call buildhwndlist in win32k. SYS. Note that these two routines have the same name as the corresponding ones in user32.dll above, which is why I have always stressed the module name. Buildhwndlist finally calls internalbuildhwndlist (win32k. sys). This routine is what we are really interested in. Internalbuildhwndlist is a recursive routine to implement window enumeration under specific parameters (such as enumdestopwindows API call, enumdestopwindows will eventually call internalbuildhwndlist.

This analysis only illustrates the execution process of Apis such as enumwindows. The real details are still worth looking at the code. Windows NT/2000 windows are associated with a specific thread, that is, each thread can have a window. The most typical example is Windows Explorer (Windows resource manager ), each time an Explorer window is opened, the explorer process establishes a Thread associated with these windows. For this reason, Microsoft stores the window structure in the kernel-state ETHREAD (kteb) (Windows NT early versions of Win32 subsystem are in the user State, which is not described here ), these structures are specified by the win32thread member in ETHREAD. The position of win32thread in ETHREAD can be found by the following command of windbg:

>! Kdex2x86. ETHREAD
Structure ETHREAD (size: 0x240) member offsets:
+ 0000 TCB (kthread struct)
+ 0000 header (dispatcher_header struct)
.
.
.
+ 0124 win32thread
.
.
.

Note that the win32thread member is displayed as a service table in SoftICE 4.05 for Windows NT. To make it easier for user-state code to obtain win32thread values, Windows NT/2000 also accesses the win32thread pointer in thread Teb, in Windows 2000 Server build 2195, the location is located at the last 0x40 of Teb. User32.dll gets the value of win32thread from the following functions (i386kd output ):

Kd> X USER32! Pticurrent
77df3686 USER32! Pticurrent

Kd> U USER32! Pticurrent
USER32! Pticurrent:
77df3686 64a118000000 mov eax, FS: [00000018]
77df1_c 83784000 cmp dword ptr [eax + 0x40], 0x0
77df3690 0f8425700200 je USER32! Pticurrent + 0xc (77e1a728)
77df3166 64a118000000 mov eax, FS: [00000018]
77df1_c 8b4040 mov eax, [eax + 0x40]
77df1_f C3 RET

The following is the code that I implement to enumerate windows owned by a specific thread (I obtain win32thread from kteb ):

//------------------------------------------------------------
//
// Buildhwndlist -- Enum thread windows (SoftICE hwnd command)
// Only test on Windows 2000 Server build 2195 Chinese edition
// Build 2195 (free )! Programmed by webcrazy
// (Tsu00@263.net) on 11-25-2000!
// Welcome to http://webcrazy.yeah.net to get more information
//
//------------------------------------------------------------

# Define win32thread_offset 0x124
# Define hwndlist_offset 0xb8
# Define hwndhandle_offset 0x0
# Define hwndnext_offset 0x2c
# Define hwndparent_offset 0x30
# Define hwndrect_offset 0x3c
# Define hwndproc_offset 0x5c

// Rect: copied from windef. h
Typedef struct tagrect
{
Long left;
Long top;
Long right;
Long bottom;
} Rect, * prect;

Typedef struct taghwndrect {
Rect windowrect;
Rect clientrect;
} Hwndrect, * phwndrect;

Void buildhwndlist (void * kteb)
{
Pvoid win32thread;
Pvoid hwndlist;
Phwndrect;

If (ushort) ntbuildnumber )! = 2195 ){
Dbuplint ("only test on Windows 2000 Server build 2195! /N ");
Return;
}

Win32thread = (pvoid) (* (Pulong) (char *) kteb + win32thread_offset ));
If (! Win32thread ){
Dbuplint ("kteb: % 08x isn't a Win32 thread! /N ", kteb );
Return;
}

Hwndlist = (pvoid) (* (Pulong) (char *) win32thread + hwndlist_offset ));
If (! Hwndlist ){
Dbuplint ("kteb: % 08x isn't a hwnd list! /N ", kteb );
Return;
}

Dbuplint ("@ kteb % 08x first hwndlist at % 08x/N", kteb, hwndlist );
Dbuplint ("hwndlist hwnd parent Window Proc window (client) rect/N ");
Dbuplint ("-------- ----------- -------------------/N ");

Do {
Phwndrect = (phwndrect) (char *) hwndlist + hwndrect_offset );
Dbuplint ("% 08x % 08x % 08x % 08x % d, % d (% d, % d)/n ",
Hwndlist,
* (Pulong) (char *) hwndlist + hwndhandle_offset ),
* (Pulong) (char *) hwndlist + hwndparent_offset )),
* (Pulong) (char *) hwndlist + hwndproc_offset ),
Phwndrect-> windowrect. Left, phwndrect-> windowrect. Top,
Phwndrect-> windowrect. Right, phwndrect-> windowrect. Bottom,
Phwndrect-> clientrect. Left, phwndrect-> clientrect. Top,
Phwndrect-> clientrect. Right, phwndrect-> clientrect. Bottom );

Hwndlist = (pvoid) (* (Pulong) (char *) hwndlist + hwndnext_offset ));
} While (hwndlist );
}

Run an instance and output the following content:

@ Kteb ff7bb020 first hwndlist at a0312da8
Hwndlist hwnd parent Window Proc window (client) rect
------------------------------------------------------
A0312da8 0001002a 0001000c 77dff0df, 0, 0 (0, 0, 0)
A0310d50 00010022 0001000c 775331c4)
A03176b8 0002004a 0001000c 77dff0df 0, 0, 0 (0, 0, 0)
A031a500 00010082 0001000c 76621ac6 44,44, 812,581 (808,577)
A0318fa8 00010062 0001000c 775676f4 1024,768, 1024,768)

Next I will talk about window class. When talking about class, you can think of many things, such as C ++ classes. As for window class, I think I should refer to the Microsoft document for explanation:

A window class is a set of attributes that the system uses as a template to create a window. Every
Window is a member of a window class. All window classes are process specific.

From the above description, we can see that window class is associated with a specific process. The window is associated with the thread, so its structure is stored in ETHREAD (kteb), and the corresponding windows class structure is stored in eprocess (kpeb. The window structure is specified by win32thread, and the window class is specified by win32process. The position of win32process in eprocess can also be seen by windbg:

>! Kdextx86.processfields
Eprocess structure offsets:
.
.
.
Win32process: 0x214
.
.
.

Below is the code to enumerate the window class of a specific process:

//----------------------------------------------------------------------
//
// Buildwindowclasslist -- Enum process window class (SoftICE class command)
// Only test on Windows 2000 Server build 2195 Chinese edition
// Build 2195 (free )! Programmed by webcrazy (tsu00@263.net) on 11-25-2000!
// Welcome to http://webcrazy.yeah.net to get more information
//
//----------------------------------------------------------------------

# Define win32process_offset 0x214
# Define winprivateclass_offset 0x38
# Define winglobalclass_offset 0x3c

# Define class_classstyle_offset 0x2c
# Define class_windowproc_offset 0x30
# Define class_modulebase_offset 0x3c
# Define class_classname_offset 0x50

Void buildwindowclasslist (void * kpeb)
{
Psingle_list_entry pprivateclasslist, pglobalclasslist;
Pvoid win32process;
Pchar pclassname;

Win32process = (pvoid) (* (Pulong) (char *) kpeb + win32process_offset ));
If (! Win32process ){
Dbuplint ("kpeb: % 08x isn't a Win32 process! /N ", kpeb );
Return;
}

Pprivateclasslist = (psingle_list_entry) (* (Pulong) (char *) win32process + winprivateclass_offset ));
If (pprivateclasslist ){
Dbuplint ("application (kpeb: % 08x) private class list:/N", kpeb );
Dbuplint ("%-35 shandle modbase winproc styles/N", "Class Name ");
Dbuplint ("%-35 s --------/N ","----------");

Do {

Pclassname = (pchar) (* (Pulong) (char *) pprivateclasslist + class_classname_offset ));
Dbuplint ("%-35 S % 08x % 08x % 08x % 08x/N", pclassname, pprivateclasslist,
* (Pulong) (char *) pprivateclasslist + class_modulebase_offset ),
* (Pulong) (char *) pprivateclasslist + class_windowproc_offset ),
* (Pulong) (char *) pprivateclasslist + class_classstyle_offset ));

Pprivateclasslist = pprivateclasslist-> next;
} While (pprivateclasslist );
}

Pglobalclasslist = (psingle_list_entry) (* (Pulong) (char *) win32process + winglobalclass_offset ));
If (pglobalclasslist ){
Dbuplint ("application (kpeb: % 08x) Global class list:/N", kpeb );
Dbuplint ("%-35 shandle modbase winproc styles/N", "Class Name ");
Dbuplint ("%-35 s --------/N ","----------");

Do {

Pclassname = (pchar) (* (Pulong) (char *) pglobalclasslist + class_classname_offset ));
Dbuplint ("%-35 S % 08x % 08x % 08x % 08x/N", pclassname, pglobalclasslist,
* (Pulong) (char *) pglobalclasslist + class_modulebase_offset ),
* (Pulong) (char *) pglobalclasslist + class_windowproc_offset ),
* (Pulong) (char *) pglobalclasslist + class_classstyle_offset ));

Pglobalclasslist = pglobalclasslist-> next;
} While (pglobalclasslist );
}
}

The result of a running instance is as follows:

Application (kpeb: ff5ba3c0) private class list:
Class Name handle modbase winproc styles
------------------------------------------
Consoleimeclass a031f938 01000000 0100152e 00000000
Ddemlunicodeserver a031f8a8 77df0000 77e2e2f9 00000000.
Ddemlansiserver a031f820 77df0000 77e2e2f9 00000000
Ddemlunicodeclient a031f790 77df0000 77e2e14d 00000000
Ddemlansiclient a031f708 77df0000 77e2e14d 00000000
Ddemlmom a031f688 77df0000 77dfd316 00000000
Application (kpeb: ff5ba3c0) Global class list:
Class Name handle modbase winproc styles
------------------------------------------
Static a031f610 77df0000 77e000f9 00004088
IME a031f5a0 77df0000 77dff0df 00004000
.
.
.

The preceding two code segments implement the hwnd and class commands in SoftICE. After analyzing these two commands, we can further analyze the message mechanism in Windows NT/2000, which is the basis for implementing Windows GUI. It seems that more and more things can be mined.

References:
1. David solomom inside Windows NT, 2nd Edition

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.