CSR_PROCESS

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.

Documentation Status

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.

Variability

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

Layout

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).