Geoff Chappell - Software Analyst
CURRENT WORK ITEM - PREVIEW ONLY
The RTL_USER_PROCESS_PARAMETERS structure (formally _RTL_USER_PROCESS_PARAMETERS) is the low-level packaging of the numerous arguments and parameters that can be specified to such Win32 API functions as CreateProcess.
By the phrase “low-level packaging” I mean very deliberately that the structure is not specifically a packaging for the transition to and from kernel mode. Ask almost anyone in the last decade or more for a potted description of the RTL_USER_PROCESS_PARAMETERS, and you can expect to hear that these are parameters that are passed from user mode to kernel mode for handling the NtCreateUserProcess and ZwCreateUserProcess functions, and that the kernel creates a copy in the created process’s address space where it is then available in user mode through the created process’s PEB. This, however, is not the history. Even now, it is not the full story. The clue is in the name, specifically in the RTL prefix.
For the first decade and more of Windows history, the RTL_USER_PROCESS_PARAMETERS structure does not cross between user and kernel modes as anything other than an uninterpreted blob that the creating process copies into the created process’s address space. The structure exists only as input to the RtlCreateUserProcess function. This Run Time Library (RTL) function is exported by name from NTDLL in all Windows versions, right from the beginning with version 3.10. It also exists in all versions of the kernel, but only as an internal routine which the kernel uses for starting the first user-mode process (and which is in a section that the kernel discards soon afterwards).
Presumably because of its role as input to an API function, albeit an undocumented one, the RTL_USER_PROCESS_PARAMETERS structure is strikingly stable. Indeed, while the RtlCreateUserProcess function was the only means of creating a user-mode process, its input structure did not change at all. Since then, the structure’s only variability is that new members are appended:
Version | Size (x86) | Size (x64) |
---|---|---|
3.10 to 5.2 | 0x0290 | 0x03F0 |
6.0 | 0x0294 | 0x03F8 |
6.1 | 0x0298 | 0x0400 |
6.2 to 6.3 | 0x02A0 | 0x0410 |
10.0 to 1803 | 0x02A4 | 0x0410 |
1809 | 0x02AC | 0x0420 |
1903 | 0x02BC | 0x0440 |
2004 | 0x02C0 | 0x0440 |
These sizes, and the offsets, names and types of members in the table below, are from Microsoft’s public symbol files for the kernel starting with Windows 2000 SP3.
For versions that predate the availability of type information in symbol files, continuity with the known definition for later versions is confirmed by inspection of the implementations and uses of RtlCreateUserProcess. For a handful of these early versions, the continuity can be established more readily. For instance, the import libraries GDISRVL.LIB and SHELL32.LIB that Microsoft supplied with the Device Driver Kit (DDK) for Windows NT 3.51 and 4.0, respectively, have an early form of type information, including for RTL_USER_PROCESS_PARAMETERS.
Offset (x86) | Offset (x64) | Definition | Versions |
---|---|---|---|
0x00 | 0x00 |
ULONG MaximumLength; |
all |
0x04 | 0x04 |
ULONG Length; |
all |
0x08 | 0x08 |
ULONG Flags; |
all |
0x0C | 0x0C |
ULONG DebugFlags; |
all |
0x10 | 0x10 |
HANDLE ConsoleHandle; |
all |
0x14 | 0x18 |
ULONG ConsoleFlags; |
all |
0x18 | 0x20 |
HANDLE StandardInput; |
all |
0x1C | 0x28 |
HANDLE StandardOutput; |
all |
0x20 | 0x30 |
HANDLE StandardError; |
all |
0x24 | 0x38 |
CURDIR CurrentDirectory; |
all |
0x30 | 0x50 |
UNICODE_STRING DllPath; |
all |
0x38 | 0x60 |
UNICODE_STRING ImagePathName; |
all |
0x40 | 0x70 |
UNICODE_STRING CommandLine; |
all |
0x48 | 0x80 |
PVOID Environment; |
all |
0x4C | 0x88 |
ULONG StartingX; |
all |
0x50 | 0x8C |
ULONG StartingY; |
all |
0x54 | 0x90 |
ULONG CountX; |
all |
0x58 | 0x94 |
ULONG CountY; |
all |
0x5C | 0x98 |
ULONG CountCharsX; |
all |
0x60 | 0x9C |
ULONG CountCharsY; |
all |
0x64 | 0xA0 |
ULONG FillAttribute; |
all |
0x68 | 0xA4 |
ULONG WindowFlags; |
all |
0x6C | 0xA8 |
ULONG ShowWindowFlags; |
all |
0x70 | 0xB0 |
UNICODE_STRING WindowTitle; |
all |
0x78 | 0xC0 |
UNICODE_STRING DesktopInfo; |
all |
0x80 | 0xD0 |
UNICODE_STRING ShellInfo; |
all |
0x88 | 0xE0 |
UNICODE_STRING RuntimeData; |
all |
0x90 | 0xF0 |
RTL_DRIVE_LETTER_CURDIR CurrentDirectores [0x20]; |
all |
0x0290 | 0x03F0 |
ULONG_PTR volatile EnvironmentSize; |
6.0 to 6.1 |
ULONG_PTR EnvironmentSize; |
6.2 and higher | ||
0x0294 | 0x03F8 |
ULONG_PTR volatile EnvironmentVersion; |
6.1 only |
ULONG_PTR EnvironmentVersion; |
6.2 and higher | ||
0x0298 | 0x0400 |
PVOID PackageDependencyData; |
6.2 and higher |
0x029C | 0x0408 |
ULONG ProcessGroupId; |
6.2 and highe |
0x02A0 | 0x040C |
ULONG LoaderThreads; |
10.0 and higher |
0x02A4 | 0x0410 |
UNICODE_STRING RedirectionDllName; |
1809 and higher |
0x02AC | 0x0420 |
UNICODE_STRING HeapPartitionName; |
1903 and higher |
0x02B4 | 0x0430 |
ULONGLONG *DefaultThreadpoolCpuSetMasks; |
1903 and higher |
0x02B8 | 0x0438 |
ULONG DefaultThreadpoolCpuSetMaskCount; |
1903 and higher |
0x02BC | 0x043C |
ULONG DefaultThreadpoolThreadMaximum; |
2004 and higher |
The spelling of CurrentDirectores is Microsoft’s.