Geoff Chappell, Software Analyst
The PROCESSINFO (formally tagPROCESSINFO) is the most of what WIN32K.SYS keeps about a process. A portion at its start is reproduced as a W32PROCESS (formally _W32PROCESS), apparently as an unnamed member. It is not clear what governs the separation.
Under either name, the PROCESSINFO is not documented. Structural details from type information in symbol files are known to have been disclosed in public only for WIN32K.SYS from Windows 7—not before and not since. Or so I wrote in 2017, having not yet caught up with Windows 10 updates. Symbol files for 1607 and higher have type information for the W32PROCESS. Thus does a little more “official” detail dribble out.
For some early WIndows versions, Microsoft’s names for some, and even all, members of both structures are known with varying confidence from the output of one or another debugger command as implemented in the USEREXTS.DLL or USERKDX.DLL debugger extensions which Microsoft published with one or another Device Driver Kit (DDK). Nobody would sensibly count this as documentation. It does show, however, that Microsoft understood for a while that knowledge of the PROCESSINFO may help programmers in the depths of debugging what they’re doing with Windows!
Not only is the PROCESSINFO highly variable between versions, and not only is there the complication of what part of it is the W32PROCESS, but in the one version for which type information is publicly available it’s immediately plain that the PROCESSINFO as described therein is not the full story. The memory block it is created in is larger than is declared for the structure and the additional space is accessed as if for members of a larger structure. It could be that the PROCESSINFO is itself a reduction, but close inspection shows something more interesting: the PROCESSINFO as described by type information in the symbol file for WIN32K in Windows 7 is not the PROCESSINFO that the matching WIN32K executable actually uses. Even the following table just of changing sizes is therefore not just more than usually complex but more than usually uncertain.
Version | W32PROCESS | PROCESSINFO | Remarks | ||
---|---|---|---|---|---|
Size (x86) | Size (x64) | SIze (x86) | Size (x64) | ||
3.10 | 0xE4 | ||||
3.51 | 0x0120 | ||||
4.0 | 0x30 | 0x012C | |||
5.0 | 0x2C | 0x013C | |||
5.1 | 0x2C | 0x0144 | |||
5.2 | 0x78 | 0xD0 | 0x018C | 0x02C0 | |
6.0 | 0x80 | 0xE0 | 0x01A8 | 0x02E8 | |
6.1 | 0x90 | 0x0100 | 0x01C8 | 0x0320 | symbol files have 0x01B0 and 0x0300 for PROCESSINFO size |
6.2 | 0x9C | 0x0128 | 0x01D8 | 0x0358 | |
6.3 | 0x9C | 0x0128 | 0x01DC | 0x0360 | |
10.0 | 0x9C | 0x0128 | 0x0250 | 0x03E8 | |
1511 | 0x9C | 0x0128 | 0x0248 | 0x03D8 | |
1607 | 0xA0 | 0x0120 | 0x0250 | 0x03D8 | |
1703 | 0xA0 | 0x0120 | 0x0268 | 0x03F8 | |
1709 | 0xA8 | 0x0128 | 0x0280 | 0x0410 | |
1803 | 0xA8 | 0x0128 | 0x028C | 0x0420 |
In version 4.0, memory for the PROCESSINFO is allocated by the kernel, the required size having been communicated by WIN32K as an argument to the undocumented (and highly variable) PsEstablishWin32Callouts function. Version 5.0 redistributed the work, such that the PROCESSINFO is instead created by WIN32K. Either way, the size of the PROCESSINFO is easily seen in code—indeed, in Windows 10, with WIN32K split into three, it’s immediately visible in data, exported as W32ProcessSize—but how much of the PROCESSINFO is the W32PROCESS can only be guessed.
Even for the first part of the PROCESSINFO, Microsoft’s names and types are known with the certainty of type information from public symbol files only for version 6.1 and now for some releases of version 10.0. For versions 4.0 and 5.0, offsets and Microsoft’s names, but not types, are known with good confidence from the output of the debugger’s !dso command as supported by the USEREXTS.DLL debugger extensions for these versions. For almost all Windows versions, everything that’s presented here of the layout is necessarily the result of deduction, inference and outright guesswork from inspection of executables.
Strictly speaking, it’s also a guess that the W32PROCESS does not exist as a separate structure before version 4.0. In this version—before which the PROCESSINFO was a user-mode creation of WINSRV.DLL—three members that had been very nearly at the end at the PROCESSINFO move to very near the start, which is here taken as a reorganisation that defined the W32PROCESS. Conspicuous among these moved members is the dword of flags. Compare with similar flags in the THREADINFO which didn’t move to the W32THREAD.
Offset (x86) | Offset (x64) | Definition | Versions | Remarks |
---|---|---|---|---|
0x00 | 0x00 |
EPROCESS *Process; |
4.0 and higher | |
0x04 | 0x08 |
ULONG RefCount; |
5.0 and higher | |
0x04 (4.0); 0x08 |
0x0C |
ULONG W32PF_Flags; |
4.0 and higher | previously at 0xF4 |
0x08 (4.0); 0x0C |
0x10 |
KEVENT *InputIdleEvent; |
4.0 and higher | |
0x0C (4.0); 0x10 |
0x18 |
ULONG StartCursorHideTime; |
4.0 and higher | previously at 0xFC |
0x10 (4.0); 0x14 |
0x20 |
W32PROCESS *NextStart; |
4.0 and higher | previously at 0x0108 as ppiCalcNext |
0x14 (4.0); 0x18 |
0x28 |
PVOID pDCAttrList; |
4.0 and higher | |
0x18 (4.0); 0x1C |
0x30 |
PVOID pBrushAttrList; |
4.0 and higher | |
0x1C (4.0); 0x20 |
0x38 |
ULONG W32Pid; |
4.0 and higher | |
0x20 (4.0) |
<unknown-type> pidHandleTrack; |
4.0 only | last W32PROCESS member in 4.0 | |
0x24 | 0x3C |
LONG GDIHandleCount; |
5.0 and higher | |
0x28 | 0x40 |
ULONG GDIHandleCountPeak; |
6.1 and higher | |
0x28 (5.0 to 6.0); 0x2C |
0x40 (5.2 to 6.0); 0x44 |
LONG UserHandleCount; |
5.0 and higher | last W32PROCESS member in 5.0; last W32PROCESS member in 5.1 |
0x2C (5.2 to 6.0) | 0x44 (5.2 to 6.0) | unaccounted four bytes | 5.2 to 6.0 | |
0x30 | 0x48 |
ULONG UserHandleCountPeak; |
6.1 and higher | |
0x34 | 0x50 |
EX_PUSH_LOCK GDIPushLock; |
6.1 and higher | |
0x30 (5.2 to 6.0); 0x38 |
0x48 (5.2 to 6.0); 0x58 |
RTL_AVL_TABLE GDIEngUserMemAllocTable; |
5.2 and higher | |
0x68 (5.2 to 6.0); 0x70 |
0xB0 (5.2 to 6.0); 0xC0 |
LIST_ENTRY GDIDcAttrFreeList; |
5.2 and higher | |
0x70 (5.2 to 6.0); 0x78 |
0xC0 (5.2 to 6.0); 0xD0 |
LIST_ENTRY GDIBrushAttrFreeList; |
5.2 and higher | last W32PROCESS member in 5.2 |
0x80 | 0xE0 |
LIST_ENTRY GDIW32PIDLockedBitmaps; |
6.1 and higher | |
0x78 (6.0); 0x88 |
0xD0 (6.0); 0xF0 |
PVOID hSecureGdiSharedHandleTable; |
6.0 and higher | |
0x7C (6.0); 0x8C |
0xD8 (6.0); 0xF8 |
PVOID DxProcess; |
6.0 and higher | last W32PROCESS member in 6.0; last W32PROCESS member in 6.1 |
0x90 | 0x0100 |
PVOID DCompositionProcess; |
6.2 and higher | |
0x94 | 0x0108 |
ULONG UMPDSandboxingEnabled; |
6.2 and higher | |
0x98 | 0x0110 |
PVOID pWakeReference; |
6.2 and higher | last W32PROCESS member in 6.2 (x86); last W32PROCESS member in 6.3 (x86); last W32PROCESS member in 10.0 to 1511 (x86) |
0x0118 (6.2 to 1511) | unknown 64-bit count of references | 6.2 to 1511 | ||
00x0120 (6.2 to 1511) | unknown 64-bit count of dereferences | 6.2 to 1511 | last W32PROCESS member in 6.2 (x64); last W32PROCESS member in 6.3 (x64); last W32PROCESS member in 10.0 to 1511 (x64) |
|
0x9C | 0x0118 |
ULONG defaultDpiContext; |
1607 and higher | last W32PROCESS member in 1607 and 1703 |
0xA0 | 0x011C |
USHORT Dpi; |
1709 and higher | |
0xA4 | 0x0120 |
BOOL bChangedGdiGammaRamp; |
1709 and higher | last W32PROCESS member in 1709 |
0xA8 | 0x0124 |
UINT GdiInitializeCalloutExecuted : 1; |
1803 and higher | last W32PROCESS member in 1803 |
The InputIdleEvent is, of course, what the documented API function WaitForInputIdle waits on. As a kernel-mode structure, the PROCESSINFO can have pointers directly to such things as event objects—and ideally would, since access through handles for kernel-mode use alone is wholly avoidable overhead. In the early history, however, the InputIdleEvent is necessarily a HANDLE. See below, as hEventInputIdle, the different name being suggested by the output of the Windows NT 3.51 debugger’s !dpi command. Version 3.51 introduced some logic with special meaning for INVALID_HANDLE_VALUE as distinct from NULL, which is retained even after the change to a pointer and is remarkable for persisting even to Windows 10.
The W32Pid in version 4.0 is just the low 16 bits of the usual process ID. Later versions save a ULONG but explicitly clear the lowest two bits.
Version 4.0 does track a GDIHandleCount at offset 0x24 but apparently in some structure (0x10 bytes at offset 0x20) that I have little interest in investigating. There is only so much trouble I can care to take for the pre-history!
For the PROCESSINFO beyond the W32PROCESS, Microsoft’s names and types are known with the certainty of type information from public symbol files only for version 6.1. For versions 4.0 and 5.0, offsets and Microsoft’s names are known with good confidence from the output of the debugger’s !dso command as supported by the USERKDX debugger extensions for these versions. For version 3.51, the output of the !dpi command as supported by the USEREXTS debugger extension suggests names that very likely are Microsoft’s.
Offset (x86) | Offset (x64) | Definition | Versions | Remarks |
---|---|---|---|---|
0x00 (3.10 to 3.51); 0x30 (4.0) |
PROCESSINFO *ppiNext; |
3.10 to 4.0 | next at 0x44 | |
0x04 (3.10 to 3.51) |
DWORD idProcessClient; |
3.10 to 3.51 | ||
0x08 (3.10 to 3.51) |
DWORD idSequence; |
3.10 to 3.51 | ||
0x0C (3.10 to 3.51) |
HANDLE hEventInputIdle; |
3.10 to 3.51 | ||
0x2C (5.0 to 5.1); 0x78 (5.2); 0x80 (6.0); 0x90 (6.1); 0x9C (6.2 to 1511); 0xA0 (1607 to 1703); 0xA8 (1709); 0xAC |
0xD0 (5.2); 0xE0 (6.0); 0x0100 (6.1); 0x0128 (6.2 to 1511); 0x0120 (1607 to 1703); 0x0128 |
THREADINFO *ptiList; |
5.0 and higher | previously at 0x0108 |
0x10 (3.10 to 3.51); 0x34 (4.0); 0x30 (5.0 to 5.1); 0x7C (5.2); 0x84 (6.0); 0x94 (6.1); 0xA0 (6.2 to 1511); 0xA4 (1607 to 1703); 0xAC (1709); 0xB0 |
0xD8 (5.2); 0xE8 (6.0); 0x0108 (6.1); 0x0130 (6.2 to 1511); 0x0128 (1607 to 1703); 0x0130 |
THREADINFO *ptiMainThread; |
all | |
0x14 (3.10 to 3.51); 0x38 (4.0) |
UINT cThreads; |
3.10 to 4.0 | next at 0x4C | |
0x18 (3.10 to 3.51); 0x3C (4.0); 0x34 (5.0 to 5.1); 0x80 (5.2); 0x88 (6.0); 0x98 (6.1); 0xA4 (6.2 to 1511); 0xA8 (1607 to 1703); 0xB0 (1709); 0xB4 |
0xE0 (5.2); 0xF0 (6.0); 0x0110 (6.1); 0x0138 (6.2 to 1511); 0x0130 (1607 to 1703); 0x0138 |
DESKTOP *spdeskStartup; |
3.10 to 3.51 | |
DESKTOP *rpdeskStartup; |
4.0 and higher | |||
0x1C (3.51); 0x40 (4.0) |
HDESK hdeskStartup; |
3.51 to 4.0 | next at 0x50 | |
0x1C (3.10); 0x20 (3.51); 0x44 (4.0); 0x38 (5.0 to 5.1); 0x84 (5.2); 0x8C (6.0); 0x9C (6.1); 0xA8 (6.2 to 1511); 0xAC (1607 to 1703); 0xB4 (1709); 0xB8 |
0xE8 (5.2); 0xF8 (6.0); 0x0118 (6.1); 0x0140 (6.2 to 1511); 0x0138 (1607 to 1703); 0x0140 |
CLS *pclsPrivateList; |
all | |
0x20 (3.10); 0x24 (3.51); 0x48 (4.0); 0x3C (5.0 to 5.1); 0x88 (5.2); 0x90 (6.0); 0xA0 (6.1); 0xAC (6.2 to 1511); 0xB0 (1607 to 1703); 0xB8 (1709); 0xBC |
0xF0 (5.2); 0x0100 (6.0); 0x0120 (6.1); 0x0148 (6.2 to 1511); 0x0140 (1607 to 1703); 0x0148 |
CLS *pclsPublicList; |
all | |
0x40 (5.0 to 5.1); 0x8C (5.2); 0x94 (6.0); 0xA4 (6.1); 0xB0 (6.2 to 1511); 0xB4 (1607 to 1703); 0xBC (1709); 0xC0 |
0xF8 (5.2); 0x0108 (6.0); 0x0128 (6.1); 0x0150 (6.2 to 1511); 0x0148 (1607 to 1703); 0x0150 |
WOWPROCESSINFO *pwpi; |
5.0 and higher | previously at 0x0104 |
0x44 (5.0 to 5.1); 0x90 (5.2); 0x98 (6.0); 0xA8 (6.1); 0xB4 (6.2 to 1511); 0xB8 (1607 to 1703); 0xC0 (1709); 0xC4 |
0x0100 (5.2); 0x0110 (6.0); 0x0130 (6.1); 0x0158 (6.2 to 1511); 0x0150 (1607 to 1703); 0x0158 |
PROCESSINFO *ppiNext; |
5.0 and higher | previously at 0x30 |
0x48 (5.0 to 5.1); 0x94 (5.2); 0x9C (6.0); 0xAC (6.1); 0xB8 (6.2 to 1511); 0xBC (1607 to 1703); 0xC4 (1709); 0xC8 |
0x0108 (5.2); 0x0118 (6.0); 0x0138 (6.1); 0x0160 (6.2 to 1511); 0x0158 (1607 to1703); 0x0160 |
PROCESSINFO *ppiNextRunning; |
5.0 and higher | |
0x4C (5.0 to 5.1); 0x98 (5.2); 0xA0 (6.0); 0xB0 (6.1); 0xBC (6.2 to 1511); 0xC0 (1607 to 1703); 0xC8 (1709); 0xCC |
0x0110 (5.2); 0x0120 (6.0); 0x0140 (6.1); 0x0168 (6.2 to 1511); 0x0160 (1607 to 1703); 0x0168 |
UINT cThreads; |
5.0 and higher | previously at 0x38 |
0x50 (5.0 to 5.1); 0x9C (5.2); 0xA4 (6.0); 0xB4 (6.1); 0xC0 (6.2 to 1511); 0xC4 (1607 to 1703); 0xCC (1709); 0xD0 |
0x0118 (5.2); 0x0128 (6.0); 0x0148 (6.1); 0x0170 (6.2 to 1511); 0x0168 (1607 to 1703); 0x0170 |
HDESK hdeskStartup; |
5.0 and higher | previously at 0x40 |
0x4C (4.0); 0x54 (5.0 to 5.1); 0xA0 (5.2); 0xA8 (6.0); 0xB8 (6.1); 0xC4 (6.2 to 1511); 0xC8 (1607 to 1703); 0xD0 (1709); 0xD4 |
0x0120 (5.2); 0x0130 (6.0); 0x0150 (6.1); 0x0178 (6.2 to 1511); 0x0170 (1607 to 1703); 0x0178 |
UINT cSysExpunge; |
4.0 and higher | |
0x50 (4.0); 0x58 (5.0 to 5.1); 0xA4 (5.2); 0xAC (6.0); 0xBC (6.1); 0xC8 (6.2 to 1511); 0xCC (1607 to 1703); 0xD4 (1709); 0xD8 |
0x0124 (5.2); 0x0134 (6.0); 0x0154 (6.1); 0x017C (6.2 to 1511); 0x0174 (1607 to 1703); 0x017C |
DWORD dwhmodLibLoadedMask; |
4.0 and higher | |
0x24 (3.10); 0x28 (3.51); 0x54 (4.0); 0x5C (5.0 to 5.1); 0xA8 (5.2); 0xB0 (6.0); 0xC0 (6.1); 0xCC (6.2 to 1511); 0xD0 (1607 to 1703); 0xD8 (1709); 0xDC |
0x0128 (5.2); 0x0138 (6.0); 0x0158 (6.1); 0x0180 (6.2 to 1511); 0x0178 (1607 to 1703); 0x0180 |
PVOID ahmodLibLoaded [0x20]; |
all | |
0xA8 3.51) | unknown array of two 0x10-byte structures (3.51) | 3.51 only | ||
0xA4 (3.10); 0xC8 (3.51) |
INT cObjects; |
3.10 to 3.51 | ||
0xA8 (3.10) | unknown pointer | 3.10 only | ||
0xAC (3.10); 0xCC (3.51) |
<unknown-type> pOpenObjectTable; |
3.10 to 3.51 | ||
0xB0 (3.10); 0xD0 (3.51); 0xD4 (4.0); 0xDC (5.0 to 5.1); 0x0128 (5.2); 0x0130 (6.0); 0x0140 (6.1); 0x014C (6.2 to 1511); 0x0150 (1607 to 1703); 0x0158 (1709); 0x015C |
0x0228 (5.2); 0x0238 (6.0); 0x0258 (6.1); 0x0280 (6.2 to 1511); 0x0278 (1607 to 1703); 0x0280 |
WINDOWSTATION *spwinsta; |
3.10 to 3.51 | |
WINDOWSTATION *rpwinsta; |
4.0 and higher | |||
0xD4 (3.51); 0xD8 (4.0); 0xE0 (5.0 to 5.1); 0x012C (5.2); 0x0134 (6.0); 0x0144 (6.1); 0x0150 (6.2 to 1511); 0x0154 (1607 to 1703); 0x015C (1709); 0x0160 |
0x0230 (5.2); 0x0240 (6.0); 0x0260 (6.1); 0x0288 (6.2 to 1511); 0x0280 (1607 to 1703); 0x0288 |
HWINSTA hwinsta; |
3.51 and higher | |
0xDC (4.0); 0xE4 (5.0 to 5.1); 0x0130 (5.2); 0x0138 (6.0); 0x0148 (6.1); 0x0154 (6.2 to 1511); 0x0158 (1607 to 1703); 0x0160 (1709); 0x0164 |
0x0238 (5.2); 0x0248 (6.0); 0x0268 (6.1); 0x0290 (6.2 to 1511); 0x0288 (1607 to 1703); 0x0290 |
ACCESS_MASK amwinsta; |
4.0 and higher | |
0xB4 (3.10); 0xD8 (3.51); 0xE0 (4.0) |
USERSTARTUPINFO usi; |
3.10 to 4.0 | next at 0x011C | |
0xD0 (3.10); 0xF4 (3.51) |
DWORD PIF_flags; |
3.10 to 3.51 | next at 0x04 | |
0xD4 (3.10); 0xF8 (3.51); 0xFC (4.0) |
DWORD dwCompatFlags; |
3.10 to 4.0 | ||
0xD8 (3.10); 0xFC (3.51) |
ULONG timeStartCursorOverride; |
3.10 to 3.51 | next at 0x0C | |
0xDC (3.10); 0x0100 (3.51 to 4.0); 0xE8 (5.0 to 5.1); 0x0134 (5.2); 0x013C (6.0); 0x014C (6.1); 0x0158 (6.2 to 1511); 0x015C (1607 to 1703); 0x0164 (1709); 0x0168 |
0x023C (5.2); 0x024C (6.0); 0x026C (6.1); 0x0294 (6.2 to 1511); 0x028C (1607 to 1703); 0x0294 |
DWORD dwHotkey; |
all | |
0xE0 (3.10); 0x0104 (3.51) |
<unknown-type> pCsrProcess; |
3.10 to 3.51 | last PROCESSINFO member in 3.10 |
The name PIF_flags is hypothesised by analogy with TIF_flags in the THREADINFO. The USEREXTS debugger extension for Windows NT 3.51 has just “flags” but this seems more likely to be intended for easier presentation rather than for faithfully reproducing the member’s name. Note in particular that the names that this same debugger extension gives for the defined bits each begin with PIF.
The name dwCompatFlags is confirrmed by the USERKDX debugger extension for Windows NT 4.0. The dword is a copy of the dwCompatFlags that are also computed for the THREADINFO and CLIENTINFO. Keeping them in the PROCESSINFO too seems to have been dropped after version 4.0.
Offset (x86) | Definition | Versions | Remarks |
---|---|---|---|
0x0108 (3.51) |
W32PROCESS *ppiCalcNext; |
3.51 only | next at 0x10 as NextStart |
0x010C (3.51); 0x0104 (4.0) |
WOWPROCESSINFO *pwpi; |
3.51 to 4.0 | next at 0x40 |
0x0110 (3.51); 0x0108 (4.0) |
THREADINFO *ptiList; |
3.51 to 4.0 | next at 0x2C |
0x0114 (3.51); 0x010C (4.0) |
<unknown-type> pcurList; |
3.51 to 4.0 | |
0x0118 (3.51); 0x0110 (4.0) |
LUID luidSession; |
3.51 to 4.0 | last PROCESSINFO member in 3.51; next at 0x0114 |
Offset (x86) | Offset (x64) | Definition | Versions | Remarks |
---|---|---|---|---|
0xEC (5.0 to 5.1); 0x0138 (5.2); 0x0140 (6.0); 0x0150 (6.1); 0x015C (6.2 to 1511); 0x0160 (1607 to 1703); 0x0168 (1709); 0x016C |
0x0240 (5.2); 0x0250 (6.0); 0x0270 (6.1); 0x0298 (6.2 to 1511); 0x0290 (1607 to 1703); 0x0298 |
HMONITOR hMonitor; |
5.0 and higher | |
0x0118 (4.0); 0xF0 (5.0 to 5.1); 0x013C (5.2); 0x0144 (6.0); 0x0154 (6.1); 0x0160 (6.2 to 1511); 0x0164 (1607 to 1703); 0x016C (1709); 0x0170 |
0x0248 (5.2); 0x0258 (6.0); 0x0278 (6.1); 0x02A0 (6.2 to 1511); 0x0298 (1607 to 1703); 0x02A0 |
DESKTOPVIEW *pdvList; |
4.0 and higher | |
0x11C (4.0); 0xF4 (5.0 to 5.1); 0x0140 (5.2); 0x0148 (6.0); 0x0158 (6.1); 0x0164 (6.2 to 1511); 0x0168 (1607 to 1703); 0x0170 (1709); 0x0174 |
0x0250 (5.2); 0x0260 (6.0); 0x0280 (6.1); 0x02A8 (6.2 to 1511); 0x02A0 (1607 to 1703); 0x02A8 |
UINT iClipSerialNumber; |
4.0 and higher | |
0x0120 (4.0); 0xF8 (5.0 to 5.1); 0x0144 (5.2); 0x014C (6.0); 0x015C (6.1); 0x0168 (6.2 to 1511); 0x016C (1607 to 1703); 0x0174 (1709); 0x0178 |
0x0258 (5.2); 0x0268 (6.0); 0x0288 (6.1); 0x02B0 (6.2 to 1511); 0x02A8 (1607 to 1703); 0x02B0 |
RTL_BITMAP bmDesktopHookFlags; |
4.0 only | |
RTL_BITMAP bmHandleFlags; |
5.0 and higher | |||
0x0128 (4.0); 0x0100 (5.0 to 5.1); 0x014C (5.2); 0x0154 (6.0); 0x0164 (6.1); 0x0170 0x0174 0x017C 0x0180 |
0x0268 (5.2); 0x0278 (6.0); 0x0298 (6.1); 0x02C0 0x02B8 0x02C0 |
CURSOR *pCursorCache; |
4.0 and higher | last PROCESSINFO member in 4.0 |
That the PROCESSINFO as early as version 4.0 has an RTL_BITMAP where the Windows 7 symbol files locate bmHandleFlags is certain, but it is not clear that handle flags existed before version 5.0, at least not with the generality of later versions. The version 4.0 WIN32K operates on this bitmap not through such routines as SetHandleFlag but SetDesktopHookFlag. The USERKDX debugger extensions for WIndows NT 4.0 and Windows 2000 confirm that the difference also showed in the bitmap’s name.
Offset (x86) | Offset (x64) | Definition | Versions | Remarks |
---|---|---|---|---|
0x0104 (5.0 to 5.1); 0x0150 (5.2); 0x0158 (6.0); 0x0168 (6.1); 0x0174 (6.2 to 1511); 0x0178 (1607 to 1703); 0x0180 (1709); 0x0184 |
0x0270 (5.2); 0x0280 (6.0); 0x02A0 (6.1); 0x02C8 (6.2 to 1511); 0x02C0 (1607 to 1703); 0x02C8 |
PVOID pClientBase; |
5.0 and higher | |
0x0188 | 0x02D0 | unknown pointer | 1803 and higher | |
0x0108 (5.0 to 5.1); 0x0154 (5.2); 0x015C (6.0); 0x016C (6.1); 0x0178 (6.2 to 1511); 0x017C (1607 to 1703); 0x0184 (1709); 0x018C |
0x0278 (5.2); 0x0288 (6.0); 0x02A8 (6.1); 0x02D0 (6.2 to 1511); 0x02C8 (1607 to 1703); 0x02D0 (1709); 0x02D8 |
DWORD dwLpkEntryPoints; |
5.0 and higher | |
0x010C (5.0 to 5.1); 0x0158 (5.2); 0x0160 (6.0); 0x0170 (6.1); 0x017C (6.2 to 1511); 0x0180 (1607 to 1703); 0x0188 (1709); 0x0190 |
0x0280 (5.2); 0x0290 (6.0); 0x02B0 (6.1); 0x02D8 (6.2 to 1511); 0x02D0 (1607 to 1703); 0x02D8 (1709); 0x02E0 |
W32JOB *pW32Job; |
5.0 and higher | |
0x0110 (5.0 to 5.1); 0x015C (5.2); 0x0164 (6.0); 0x0174 (6.1); 0x0180 (6.2 to 1511); 0x0184 (1607 to 1703); 0x018C (1709); 0x0194 |
0x0288 (5.2); 0x0298 (6.0); 0x02B8 (6.1); 0x02E0 (6.2 to 1511); 0x02D8 (1607 to 1703); 0x02E0 (1709); 0x02E8 |
DWORD dwImeCompatFlags; |
5.0 and higher | |
0x0114 (5.0 to 5.1); 0x0160 (5.2); 0x0168 (6.0); 0x0178 (6.1); 0x0184 (6.2 to 1511); 0x0188 (1607 to 1703); 0x0190 (1709); 0x0198 |
0x028C (5.2); 0x029C (6.0); 0x02BC (6.1); 0x02E4 (6.2 to 1511); 0x02DC (1607 to 1703); 0x02E4 (1709); 0x02EC |
LUID luidSession; |
5.0 and higher | previously at 0x0110 |
0x011C (5.0 to 5.1); 0x0168 (5.2); 0x0170 (6.0); 0x0180 (6.1); 0x018C (6.2 to 1511); 0x0190 (1607 to 1703); 0x0198 (1709); 0x01A0 |
0x0294 (5.2); 0x02A4 (6.0); 0x02C4 (6.1); 0x02EC (6.2 to 1511); 0x02E4 (1607 to 1703); 0x02EC (1709); 0x02F4 |
USERSTARTUPINFO usi; |
5.0 and higher | previously at 0xE0 |
0x01BC | 0x0310 | unknown word | 1803 and higher | |
0x019C (6.1); 0x01A8 (6.2 to 1511); 0x01AC (1607 to 1703); 0x01B4 (1709); 0x01C0 |
0x02E0 (6.1); 0x0308 (6.2 to 1511); 0x0300 (1607 to 1703); 0x0308 (1709); 0x0314 |
union { ULONG Flags; struct { /* bit fields, follow link */ }; }; |
6.1 and higher | |
0x0138 (5.0 to 5.1); 0x0184 (5.2); 0x018C (6.0); 0x01A0 (6.1); 0x01AC (6.2 to 1511); 0x01B0 (1607 to 1703); 0x01B8 (1709); 0x01C4 |
0x02B0 (5.2); 0x02C0 (6.0); 0x02E4 (6.1); 0x030C (6.2 to 1511); 0x0304 (1607 to 1703); 0x030C (1709); 0x0318 |
ULONG dwLayout; |
5.0 and higher | last PROCESSINFO member in 5.0 |
The USERKDX debugger extension from the DDK for Windows 2000 does not list dwLayout among the PROCESSINFO members and would have it that the structure is 0x0138 bytes, not 0x013C. It is here thought that the DDK somehow retained a debugger extension for a pre-release build, but it may be that the inspected WIN32K executable is not truly from the original release.
Offset (x86) | Offset (x64) | Definition | Versions | Remarks |
---|---|---|---|---|
0x013C (5.1); 0x0188 (5.2); 0x0190 (6.0); 0x01A4 (6.1); 0x01B0 (6.2 to 1511); 0x01B4 (1607 to 1703); 0x01BC (1709); 0x01C8 |
0x02B8 (5.2); 0x02C8 (6.0); 0x02E8 (6.1); 0x0310 (6.2 to 1511); 0x0308 (1607 to 1703); 0x0310 (1709); 0x0320 |
PROCESS_HID_TABLE *pHidTable; |
5.1 and higher | last PROCESSINFO member in 5.2 |
0x0140 (5.1) | unknown dword of bit flags | 5.1 only | last PROCESSINFO member in 5.1 |
The four bytes at offset 0x0140 in version 5.1 are bit flags. The bit masked by 0x00000001 is set to disable ghosting. Version 5.2 moved it to the bit masked by 0x08000000 in the W32PF_Flags.
Offset (x86) | Offset (x64) | Definition | Versions | Remarks |
---|---|---|---|---|
0x0194 (6.0); 0x01A8 (6.1); 0x01B4 (6.2 to 1511); 0x01B8 (1607 to 1703); 0x01C0 (1709); 0x01CC |
0x02D0 (6.0); 0x02F0 (6.1); 0x0318 (6.2 to 1511); 0x0310 (1607 to 1703); 0x0318 (1709); 0x0328 |
DWORD dwRegisteredClasses; |
6.0 and higher | |
0x0198 (6.0); 0x01AC (6.1) |
0x02D4 (6.0); 0x02F4 (6.1) |
unknown dword | 6.0 to 6.1 | not present in 6.1 according to symbol files |
0x019C (6.0); 0x01B0 (6.1); 0x01B8 (6.2 to 1511); 0x01BC (1607 to 1703); 0x01C4 (1709); 0x01D0 |
0x02D8 (6.0); 0x02F8 (6.1); 0x0320 (6.2 to 1511); 0x0318 (1607 to 1703); 0x0320 (1709); 0x0330 |
unknown pointer | 6.0 and higher | not present in 6.1 according to symbol files |
0x01A0 (6.0) | 0x02E0 (6.0) | unaccounted | 6.0 only | last PROCESSINFO member in 6.0 |
Offset (x86) | Offset (x64) | Definition | Versions | Remarks |
---|---|---|---|---|
0x01B4 (6.1); 0x01BC (6.2 to 1511); 0x01C0 (1607 to 1703); 0x01C8 (1709); 0x01D4 |
0x0300 (6.1); 0x0328 (6.2 to 1511); 0x0320 (1607 to 1703); 0x0328 (1709); 0x0338 |
unknown VWPL pointer | 6.1 and higher | not present in 6.1 according to symbol files |
0x01B8 (6.1); 0x01C0 (6.2 to 1511); 0x01C4 (1607 to 1703); 0x01CC (1709); 0x01D8 |
0x0308 (6.1); 0x0330 (6.2 to 1511); 0x0328 (1607 to 1703); 0x0330 (1709); 0x0340 |
unaccounted | 6.1 and higher | not present in 6.1 according to symbol files |
0x01BC (6.1); 0x01C4 (6.2 to 1511); 0x01C8 (1607 to 1703); 0x01D0 (1709); 0x01DC |
0x0310 (6.1); 0x0338 (6.2 to 1511); 0x0330 (1607 to 1703); 0x0338 (1709); 0x0348 |
VWPL *pvwplWndGCList; |
6.1 and higher | 0x01AC and 0x02F8 in 6.1 according to symbol files |
0x01C0 (6.1) | 0x0318 (6.1) | unknown word | 6.1 only | not present in 6.1 according to symbol files |
0x01C4 (6.1) | 0x031C (6.1) | unknown dword | 6.1 only | not present in 6.1 according to symbol files; last PROCESSINFO member in 6.1 |
Type information in the WIN32K symbol files from version 6.1—which, remember, is all that Microsoft has disclosed in public—has the PROCESSINFO ending with pvwplWndGCList at offsets 0x01AC and 0x02F8. These offsets are simply not plausible for this member. For instance, where a routine that the symbol files name as GetWindowGCList calls another named VWPLGetData, it very plainly takes the pointer from offset 0x01BC. As if this were not trouble enough, there is evidently a second such pointer. For instance, a routine named GetWindowMessageFilter also calls VWPLGetData but taking the pointer from offset 0x01B4.
The unknown word is bit flags. The unknown dword that follows it is perhaps named ProcessCheckSum. It is set by an internal routine that the symbol files—yes, the ones that omit the member from the structure—name as WndLimit_GetProcessCheckSum.. It receives the checksum from the process’s Portable Executable (PE) header. Both seem to have existed only for Windows 7.
Microsoft’s names for members that have been added to the PROCESSINFO since Windows 7 may never be known.
Offset (x86) | Offset (x64) | Definition | Versions | Remarks |
---|---|---|---|---|
0x01C8 (6.2 to 1511); 0x01CC (1607 to 1703); 0x01D4 (1709); 0x01E0 |
0x0340 (6.2 to 1511); 0x0338 (1607 to 1703); 0x0340 (1709); 0x0350 |
unknown 8 bytes | 6.2 and higher | |
0x01D0 (6.3 to 1511); 0x01D4 (1607 to 1703); 0x01DC (1709); 0x01E8 |
0x0348 (6.3 to 1511); 0x0340 (1607 to 1703); 0x0348 (1709); 0x0358 |
unknown dword | 6.3 and higher | |
0x01D0 (6.2); 0x01D4 (6.3 to 1511); 0x01D8 (1607 to 1703); 0x01E0 (1709); 0x01EC |
0x0348 (6.2); 0x0350 (6.3 to 1511); 0x0348 (1607 to 1703); 0x0350 (1709); 0x0360 |
unknown pointer | 6.2 and higher | |
0x01D8 (10.0 to 1511); 0x01DC (1607 to 1703); 0x01E4 (1709); 0x01F0 |
0x0358 (10.0 to 1511); 0x0350 (1607 to 1703); 0x0358 (1709); 0x0368 |
unknown four pointers or handles | 10.0 only | |
unknown two pointers or handles | 1511 and higher | |||
0x01D4 (6.2); 0x01D8 (6.3); 0x01E8 (10.0); 0x01E0 (1511); 0x01E4 (1607 to 1703); 0x01EC (1709); 0x01F8 |
0x0350 (6.2); 0x0358 (6.3); 0x0378 (10.0); 0x0368 (1511); 0x0360 (1607 to 1703); 0x0368 (1709); 0x0378 |
unknown dword | 6.2 and higher | last PROCESSINFO member in 6.2; last PROCESSINFO member in 6.3 |
Offset (x86) | Offset (x64) | Definition | Versions | Remarks |
---|---|---|---|---|
0x01EC (10.0); 0x01E4 (1511); 0x01E8 (1607 to 1703); 0x01F0 (1709); 0x01FC |
0x0380 (10.0); 0x0370 (1511); 0x0368 (1607 to 1703); 0x0370 (1709); 0x0380 |
unknown pointer | 10.0 and higher | |
0x01F0 (10.0); 0x01E8 (1511); 0x01EC (1607 to 1703); 0x01F4 (1709); 0x0200 |
0x0388 (10.0); 0x0378 (1511); 0x0370 (1607 to 1703); 0x0378 (1709); 0x0388 |
unknown dword for NumberOfActivations | 10.0 and higher | |
0x01F4 (10.0); 0x01EC (1511); 0x01F0 (1607 to 1703); 0x01F8 (1709); 0x0204 |
0x038C (10.0); 0x037C (1511); 0x0374 (1607 to 1703); 0x037C (1709); 0x038C |
unknown CHAR [0x10] for ProcessImageName | 10.0 and higher | |
0x0204 (10.0); 0x01FC (1511); 0x0200 (1607 to 1703); 0x0208 (1709); 0x0214 |
0x039C (10.0); 0x038C (1511); 0x0384 (1607 to 1703); 0x038C (1709); 0x039C |
unknown dword for ProcessId | 10.0 and higher | |
0x0208 (10.0); 0x0200 (1511); 0x0204 (1607 to 1703); 0x020C (1709); 0x0218 |
0x03A0 (10.0); 0x0390 (1511); 0x0388 (1607 to 1703); 0x0390 (1709); 0x03A0 |
unknown RECT for Monitor.Left, etc | 10.0 and higher | |
0x0218 (10.0); 0x0210 (1511); 0x0214 (1607 to 1703); 0x021C (1709); 0x0228 |
0x03B0 (10.0); 0x03A0 (1511); 0x0398 (1607 to 1703); 0x03A0 (1709); 0x03B0 |
unknown dword for DisplayDPI | 10.0 and higher | |
0x021C (10.0); 0x0214 (1511); 0x0218 (1607 to 1703); 0x0220 (1709); 0x022C |
0x03B4 (10.0); 0x03A4 (1511); 0x039C (1607 to 1703); 0x03A4 (1709); 0x03B4 |
unknown dword for InitialDisplayDPI | 10.0 and higher | |
0x0220 (10.0); 0x0218 (1511); 0x021C (1607 to 1703); 0x0224 (1709); 0x0230 |
0x03B8 (10.0); 0x03A8 (1511); 0x03A0 (1607 to 1703); 0x03A8 (1709); 0x03B8 |
unknown dword for PrevDisplayDPI | 10.0 and higher | |
0x0224 (10.0); 0x021C (1511); 0x0220 (1607 to 1703); 0x0228 (1709); 0x0234 |
0x03BC (10.0); 0x03AC (1511); 0x03A4 (1607 to 1703); 0x03AC (1709); 0x03BC |
unknown dword of bit flags: 0x00000001 for MonitorHasChanged; 0x00000002 for DPIHasChangedWhenMonitorChanged; 0x00000004 for DPIHasChangedWhenMonitorNotChanged |
10.0 and higher | |
0x0228 (10.0); 0x0220 (1511); 0x0224 (1607 to 1703); 0x022C (1709); 0x0238 |
0x03C0 (10.0); 0x03B0 (1511); 0x03A8 (1607 to 1703); 0x03B0 (1709); 0x03C0 |
unknown WCHAR [0x10] | 10.0 and higher | |
0x0248 (10.0); 0x0240 (1511); 0x0244 (1607 to 1703); 0x024C (1709); 0x0258 |
0x03E0 (10.0); 0x03D0 (1511); 0x03C8 (1607 to 1703); 0x03D0 (1709); 0x03E0 |
UINT cVisWindows; |
10.0 and higher | |
0x024C (10.0); 0x0244 (1511); 0x0248 (1607 to 1703); 0x0250 (1709); 0x025C |
0x03E4 (10.0); 0x03D4 (1511); 0x03CC (1607 to 1703); 0x03D4 (1709); 0x03E4 |
unknown dword | 10.0 and higher | last PROCESSINFO member in 10.0; last PROCESSINFO member in 1511 |
0x024C (1607 to 1703); 0x0254 (1709); 0x0260 |
0x03D0 (1607 to 1703); 0x03D8 (1709); 0x03E8 |
unknown byte | 1607 and higher | |
0x024D (1607 to 1703); 0x0255 (1709); 0x0261 |
0x03D1 (1607 to 1703); 0x03D9 (1709); 0x03E9 |
unknown byte | 1607 and higher | |
0x024E (1607 to 1703); 0x0256 (1709); 0x0262 |
0x03D2 (1607 to 1703); 0x03DA (1709); 0x03EA |
unknown byte | 1607 and higher | last PROCESSINFO member in 1607 |
0x0250 (1703); 0x0258 (1709); 0x0264 |
0x03D4 (1703); 0x03DC (1709); 0x03EC |
unknown dword | 1703 and higher | |
0x0254 (1703); 0x025C (1709); 0x0268 |
0x03D8 (1703); 0x03E0 (1709); 0x03F0 |
unknown dword | 1703 and higher | |
0x0258 (1703); 0x0260 (1709); 0x026C |
0x03DC (1703); 0x03E4 (1709); 0x03F4 |
unknown dword | 1703 and higher | |
0x025C (1703); 0x0264 (1709); 0x0270 |
0x03E0 (1703); 0x03E8 (1709); 0x03F8 |
unknown dword | 1703 and higher | |
0x0260 (1703); 0x0268 (1709); 0x0274 |
0x03E8 (1703); 0x03F0 (1709); 0x0400 |
unknown LIST_ENTRY | 1703 and higher | last PROCESSINFO member in 1703 |
0x0270 (1709); 0x027C |
0x0400 (1709); 0x0410 |
unknown dword | 1709 and higher | |
0x0274 (1709); 0x0280 |
0x0404 (1709); 0x0414 |
unknown dword | 1709 and higher | |
0x0278 (1709); 0x0284 |
0x0408 (1709); 0x0418 |
unknown dword | 1709 and higher | |
0x027C (1709); 0x0288 |
0x040C (1709); 0x041C |
unknown dword | 1709 and higher | last PROCESSINFO member in 1709; last PROCESSINFO member in 1803 |
Many consecutive members that are new for Windows 10 support the trace logging event named AppUsageAndDisplayInfoOnExit. It is not known whether they are defined as a nested structure. Names given in italics are those of the parameters for the trace-logging event, except that in 1511 and higher what’s shown as the ProcessImageName is instead hard-coded as ATTRI_DEPRECATED.
The name cVisWindows is proposed with some confidence since it acts as a per-process counter in tandem with the very much older per-thread counter for which Microsoft’s name in version 6.1 is known with the certainty of type information from symbol files.