Geoff Chappell - Software Analyst
The SYSTEM_ROOT_SILO_INFORMATION structure is what a successful call to ZwQuerySystemInformation or NtQuerySystemInformation produces in its output buffer when given the information class SystemRootSiloInformation (0xAE).
The SYSTEM_ROOT_SILO_INFORMATION structure is not documented. Neither is Microsoft known to have published any C-language declaration in any header from any development kit for either kernel-mode or user-mode programming.
Microsoft does publish the practical equivalent of a C-language definition as type information in a handful of private symbol files that Microsoft has included in packages of public symbol files and continues to make available through Microsoft’s public symbol server. These private symbol files are not for the kernel, where the structures is prepared, nor even for low-level user-mode DLLs that interpret the structure. They are instead for various higher-level user-mode DLLs such as URLMON.DLL. The latter is here singled out because of its origins in Internet Explorer and thence for the strong suggestion that even a decade after Microsoft’s anti-trust settlement Microsoft’s programmers of Internet Explorer had access to more details of low-level Windows programming than Microsoft publishes for wider use.
Though the SYSTEM_ROOT_SILO_INFORMATION is used for output through an API to both kernel-mode and user-mode callers, it varied while Microsoft’s implementation of silos was yet to settle:
Version | Size (x86) | Size (x64) |
---|---|---|
10.0 | 0x08 | 0x10 |
1511 | 0x14 | 0x14 |
1607 to 2004 | 0x08 | 0x08 |
Except for the original Windows 10, the structure is not just the same size in 32-bit and 64-bit Windows but is identical internally.
The sizes in the preceding table and the offsets, names and types in the next are from type information in symbol files.
Offset (x86) | Offset (x64) | Definition | Versions |
---|---|---|---|
0x00 | 0x00 |
ULONG NumberOfSilos; |
10.0 and higher |
0x04 | 0x08 (10.0); 0x04 |
ULONG_PTR SiloIdList [ANYSIZE_ARRAY]; |
10.0 only |
GUID SiloIdList [ANYSIZE_ARRAY]; |
1511 only | ||
ULONG SiloIdList [ANYSIZE_ARRAY]; |
1607 and higher |
Provided the function is given a large enough output buffer, it aims to enter into the SiloIdList one silo identifier for each silo that is in the caller’s silo. Put another way, the caller’s silo is taken as the root silo. The caller is to be told of this silo and any within, but of none without.
The nature of the identifier changed through the early versions while the silo implementation was still in flux. Originally, the identifier is allocated from a handle table (and is kept in the ESILO) and is thus produced as a pointer-sized integer. Version 1511 instead produces the ContainerId from the EJOB. What Microsoft settled on for Version 1607 is the 32-bit JobId.