Geoff Chappell, Software Analyst
The CSR_PROCESS structure is what CSRSRV.DLL and the various server DLLs in the CSRSS.EXE server process use for representing a client process.
The CSR_PROCESS structure is not documented. Neither is Microsoft known to have published a C-language definition in any header from any software development kit.
Type information for the CSR_PROCESS is in public symbol files for CSRSS.EXE starting with Windows Vista. Earlier type information is known in a statically linked library, named GDISRVL.LIB, which Microsoft published with the Device Driver Kit (DDK) for Windows NT 3.51.
Members, but not types, are also listed by the !dso command as implemented in the USEREXTS and USERKDX debugger extensions from the DDK for Windows 2000.
Considering how little of anything to do with CSRSS is documented, the CSR_PROCESS is surprisingly stable. Tidying in the early versions and then the gradual withdrawal of functionality from CSRSS has seen the CSR_PROCESS shrink but it is very well settled since Windows 7. The following changes of size are known:
Version | Size (x86) | Size (x64) |
---|---|---|
3.10 | 0xC8 | |
3.51 to 5.1 | 0x70 | |
5.2 | 0x6C | 0xB0 |
6.0 | 0x6C | 0xA0 |
6.1 to 10.0 | 0x60 | 0x90 |
These sizes and the names and types in the table that follows are from type information in public symbol files (or such as would ordinarily be in public symbol files) for version 3.51 as an isolated case and for version 6.0 and higher. What’s known of Microsoft’s names and types for other versions is something of a guess, being inferred from what use CSRSRV is seen to make of the structure. Where use of a member corresponds closely with that of a version for which Microsoft’s symbols are available, it seems reasonable to suppose continuity. Some use, however, has no correspondence, the code having changed too much. Even where the use hasn’t changed, tracking it down exhaustively would be difficult, if not impossible, even with source code.
Offset (x86) | Offset (x64) | Definition | Versions | Remarks |
---|---|---|---|---|
0x00 | 0x00 |
CLIENT_ID ClientId; |
3.51 and higher | previously at 0x2C |
0x00 (3.10) | unaccounted four bytes | 3.10 only | ||
0x04 (3.10); 0x08 |
0x10 |
LIST_ENTRY ListLink; |
all | |
0x0C (3.10) |
CSR_PROCESS *Parent; |
3.10 only | next at 0x18 | |
0x10 | 0x20 |
LIST_ENTRY ThreadList; |
all | |
0x18 (3.51 to 5.1) |
CSR_PROCESS *Parent; |
3.51 to 5.1 | previously at 0x0C | |
0x18 (3.10); 0x1C (3.51 to 5.1); 0x18 |
0x30 |
CSR_NT_SESSION *NtSession; |
all | |
0x1C (3.10); 0x20 (3.51 to 5.1); 0x1C (5.2 to 6.0) |
0x38 (before 6.1) |
ULONG ExpectedVersion; |
3.10 to 6.0 | |
0x20 (3.10); 0x24 (3.51 to 5.1); 0x20 (5.2 to 6.0); 0x1C |
0x40 (before 6.1); 0x38 |
HANDLE ClientPort; |
all | |
0x24 (3.10); 0x28 (3.51 to 5.1); 0x24 (5.2 to 6.0); 0x20 |
0x48 (before 6.1); 0x40 |
CHAR *ClientViewBase; |
all | |
0x28 (3.10); 0x2C (3.51 to 5.1); 0x28 (5.2 to 6.0); 0x24 |
0x50 (before 6.1); 0x48 |
CHAR *ClientViewBounds; |
all | |
0x2C (3.10) |
CLIENT_ID ClientId; |
3.10 only | next at 0x00 | |
0x34 (3.10); 0x30 (3.51 to 5.1); 0x2C (5.2 to 6.0); 0x28 |
0x58 (before 6.1); 0x50 |
HANDLE ProcessHandle; |
all | |
0x38 (3.10); 0x34 (3.51 to 5.1); 0x30 (5.2 to 6.0); 0x2C |
0x60 (before 6.1); 0x58 |
ULONG SequenceNumber; |
all | |
0x3C (3.10); 0x38 (3.51 to 5.1); 0x34 (5.2 to 6.0); 0x30 |
0x64 (before 6.1); 0x5C |
ULONG Flags; |
all | |
0x40 (3.10); 0x3C (3.51 to 5.1); 0x38 (5.2 to 6.0); 0x34 |
0x68 (before 6.1); 0x60 |
ULONG DebugFlags; |
all | |
0x44 (3.10); 0x40 (3.51 to 5.1); 0x3C (5.2) |
0x70 (late 5.2) |
CLIENT_ID DebugUserInterface; |
3.10 to 5.2 | |
0x4C (3.10); 0x48 (3.51 to 5.1); 0x44 (5.2); 0x3C (6.0); 0x38 |
0x80 (late 5.2); 0x6C (6.0); 0x64 |
ULONG ReferenceCount; |
all | |
0x50 (3.10); 0x4C (3.51 to 5.1); 0x48 (5.2); 0x40 (6.0); 0x3C |
0x84 (late 5.2); 0x70 (6.0); 0x68 |
ULONG ProcessGroupId; |
all | |
0x54 (3.10); 0x50 (3.51 to 5.1); 0x4C (5.2); 0x44 (6.0); 0x40 |
0x88 (late 5.2); 0x74 (6.0); 0x6C |
ULONG ProcessGroupSequence; |
all | |
0x58 (3.10); 0x54 (3.51 to 5.1); 0x50 (5.2); 0x48 (6.0) |
0x8C (late 5.2); 0x78 (6.0) |
ULONG fVDM; |
3.10 to 6.0 | |
0x5C (3.10); 0x58 (3.51 to 5.1); 0x54 (5.2); 0x4C (6.0) |
0x90 (late 5.2); 0x7C (6.0) |
ULONG ThreadCount; |
3.10 to 6.0 | |
0x60 (3.10) | unaccounted 0x54 bytes | 3.10 only | ||
0xB4 (3.10); 0x5C (3.51 to 5.1); 0x58 (5.2); 0x50 (6.0); 0x44 |
0x94 (late 5.2); 0x80 (6.0); 0x70 |
unknown dword: foreground priority | 3.10 only | |
UCHAR PriorityClass; |
3.51 | |||
ULONG LastMessageSequence; |
6.0 and higher | |||
0x5D (3.51) |
UCHAR Spare0; |
3.51 | ||
0x5E (3.51) |
UCHAR Spare1; |
3.51 | ||
0x5F (3.51) |
UCHAR Spare2; |
3.51 | ||
0xB8 (3.10); 0x60 (3.51 to 5.1); 0x5C (5.2); 0x54 (6.0); 0x48 |
0x98 (late 5.2); 0x84 (6.0); 0x74 |
unknown dword: background priority | 3.10 only | |
ULONG Spare3; |
3.51 | |||
ULONG NumOutstandingMessages; |
6.0 and higher | |||
0xBC (3.10); 0x64 (3.51 to 5.1); 0x60 (5.2); 0x58 (6.0); 0x4C |
0x9C (late 5.2); 0x88 (6.0); 0x78 |
ULONG ShutdownLevel; |
all | |
0xC0 (3.10); 0x68 (3.51 to 5.1); 0x64 (5.2); 0x5C (6.0); 0x50 |
0xA0 (late 5.2); 0x8C (6.0); 0x7C |
ULONG ShutdownFlags; |
all | |
0x60 (6.0); 0x54 |
0x90 (6.0); 0x80 |
LUID Luid; |
6.0 and higher | |
0xC4 (3.10); 0x6C (3.51 to 5.1); 0x68 (5.2 to 6.0); 0x5C |
0xA8 (late 5.2); 0x98 (6.0); 0x88 |
PVOID ServerDllPerProcessData [ANYSIZE_ARRAY]; |
all |
The CSR_PROCESS is built in a memory block that continues with:
A server DLL requests per-process space for all future processes by setting the wanted amount into the PerProcessDataLength member of the CSR_SERVER_DLL during initialisation. Each server DLL’s allowance is aligned up to 4 bytes in version 3.10 but 8 bytes in all later versions. Each ServerDllPerProcessData element points to the allowance for the corresponding server DLL (or is NULL if the server DLL has no per-process space).