PS_CREATE_INFO

The PS_CREATE_INFO structure is exchanged between user and kernel modes for the NtCreateUserProcess function, which was new for Windows Vista.

Documentation Status

The PS_CREATE_INFO structure is not documented. Microsoft is known to have disclosed its existence only in two ways: type information in public symbol files for Windows 8 and higher; an unreferenced type in a C-language header that appears to have been published by mistake in a Windows Driver Kit (WDK) for Windows 10.

Curiously, though the PS_CREATE_INFO is prepared by KERNEL32.DLL or KERNELBASE.DLL, depending on the Windows version, and is passed through NTDLL.DLL to kernel mode, and is then interpreted by the kernel, public symbol files for none of these modules have type information for the PS_CREATE_INFO in any known Windows version. Where this type information turns up instead is in public symbol files for a handful of higher-level user-mode modules that ought never to see the structure. Especially prominent as examples are OLE32.DLL and URLMON.DLL. The latter is conspicuous as a key component of Internet Explorer. Government-appointed reviewers of Microsoft’s settlement compliance apparently either did not notice or did not care that Internet Explorer is built with more detailed knowledge of Windows internals than Microsoft publishes even for kernel-mode programmers.

A pointer to a PS_CREATE_INFO is passed to the NtCreateUserProcess function as its second-last argument. Microsoft published a C-language prototype of this function, as its alias ZwCreateUserProcess, in a ZWAPI.H with the Enterprise edition of the Windows 10 WDK for the original and 1511 releases. No other header in the same WDK even declares the pointer’s type.

Layout

The PS_CREATE_INFO structure is 0x48 or 0x58 bytes in 32-bit and 64-bit Windows, respectively, in version 6.0 and higher.

Offset (x86) Offset (x64) Definition
0x00 0x00
ULONG_PTR Size;
0x04 0x08
PS_CREATE_STATE State;
0x08 0x10
union {
    struct {
        /* see below */
    } InitState;
    struct {
        HANDLE FileHandle;
    } FailSection;
    struct {
        USHORT DllCharacteristics;
    } ExeFormat;
    struct {
        HANDLE IFEOKey;
    } ExeName;
    struct {
        /* see below */
    } SuccessState;
};

The point to the State member is to indicate which branch to select from the unnamed union that follows. While the PS_CREATE_STATE enumeration is not known to be used elsewhere, it is as well given here. The defined values are:

Input

The PsCreateInitialState is required for input, i.e., when passing a PS_CREATE_INFO to NtCreateUserProcess. It selects the InitState branch.

Init State

Offset (x86) Offset (x64) Definition
0x08 0x10
union {
    ULONG InitFlags;
    struct {
        /* changing bit fields, follow link */
    };
};
0x0C 0x14
ACCESS_MASK AdditionalFileAccess;

Output

Five values of State in the PS_CREATE_INFO on output tell something of why NtCreateUserProcess failed. For three of these, the corresponding branch of the unnamed union has information that may help the user-mode caller to report the problem or even to recover from it.

Fail Section

Offset (x86) Offset (x64) Definition
0x08 0x10
HANDLE FileHandle;

Exe Format

Offset (x86) Offset (x64) Definition
0x08 0x10
USHORT DllCharacteristics;

Exe Name

Failure as PsCreateFailExeName indicates that however usable may be the executable as a file its execution is prevented by something about its name, specifically as its name appears as a subkey of Image File Execution Options. The caller is not explicitly told what prevents execution but is returned a handle to the subkey.

There may be multiple causes as a point of design but only one is implemented. The executable’s Image File Execution Options subkey has a Debugger value. The kernel in effect interprets this value’s presence as meaning that a process with this name cannot ordinarily be created. (The kernel’s error code is STATUS_OBJECT_PATH_INVALID.) The one exception to “ordinarily” is if the IFEOSkipDebugger bit is set on input.

Offset (x86) Offset (x64) Definition
0x08 0x10
HANDLE IFEOKey;

Success State

The greatest output in the unnamed union is produced when State is PsCreateSuccess:

Offset (x86) Offset (x64) Definition
0x08 0x10
union {
    ULONG OutputFlags;
    struct {
        /* changing bit fields, follow link */
    };
};
0x0C 0x18
HANDLE FileHandle;
0x10 0x20
HANDLE SectionHandle;
0x18 0x28
ULONGLONG UserProcessParametersNative;
0x20 0x30
ULONG UserProcessParametersWow64;
0x24 0x34
ULONG CurrentParameterFlags;
0x28 0x38
ULONGLONG PebAddressNative;
0x30 0x40
ULONG PebAddressWow64;
0x38 0x48
ULONGLONG ManifestAddress;
0x40 0x50
ULONG ManifestSize;