Geoff Chappell, Software Analyst
The PROCDESKHEAD structure is the header for user objects that can be owned by a process and are specific to a desktop. It begins the CALLPROCDATA and MENU structures.
The PROCDESKHEAD is not documented. Type information for the structure is present in the public symbol files for WIN32K.SYS from Windows 7—but not before and not since.
In the absence of definitive detail from Microsoft, even the introduction of the PROCDESKHEAD cannot be dated with certainty. It is here dated from version 5.0, but it is version 4.0 that first has the (ancient) WIN32K routine that allocates handles for user objects and finds memory for them provide for a DESKTOP pointer at a common offset in all types of object. This first provision, however, is a base such that subsequent members differentiate whether the object is owned by a process or a thread. In version 5.0 and higher, this differentiation is established first:
Offset (x86) | Offset (x64) | Definition | Versions |
---|---|---|---|
0x00 | 0x00 |
PROCOBJHEAD; |
5.0 and higher |
0x0C | 0x18 |
DESKTOP *rpdesk; |
5.0 and higher |
0x10 | 0x20 |
BYTE *pSelf; |
55.0 and higher |
See that because the PROCOBJHEAD and THROBJHEAD have the same size and alignment, rpdesk and pSelf have the same offsets in both the PROCDESKHEAD and THRDESKHEAD, with the benefit of allowing that both structures can have these members set by the same code.
See also that rpdesk and pSelf are kernel-mode addresses. The DESKTOP that is pointed to from the object’s rpdesk is not visible in user mode, but the object itself is visible in user mode in all processes that share the desktop. Of course, the object may—indeed, typically will—have a different user-mode address in each such process. So too may structures that are pointed to from the object. All such pointers hold kernel-mode addresses too. By themselves they are equally meaningless to user-mode code in all processes. The key to interpreting them is that pSelf is a kernel-mode address of the object itself. Each process has its user-mode address for the object. Their difference can then be applied to other kernel-mode addresses (of anything in the same view) to convert them to user-mode addresses for that process.