Geoff Chappell, Software Analyst
The SYSTEM_FLAGS_INFORMATION structure is produced as output or expected as input by the functions
respectively, when given the information class SystemFlagsInformation (0x09). This particular system information can be queried in all known Windows versions but cannot be set before version 3.51.
The SYSTEM_FLAGS_INFORMATION structure is not documented.
Microsoft does publish the practical equivalent of a C-language definition as type information in public symbol files, though not for the kernel, where the structure is prepared, nor even for low-level user-mode DLLs that interpret the structure, but for various higher-level user-mode DLLs such as URLMON.DLL and only then starting with version 6.2.
Two earlier disclosures of type information are known, though not in symbol files but in statically linked libraries: GDISRVL.LIB from the Device Driver Kit (DDK) for Windows NT 3.51; and SHELL32.LIB from the DDK for Windows NT 4.0.
The SYSTEM_FLAGS_INFORMATION is four bytes in both 32-bit and 64-bit Windows:
Offset | Definition |
---|---|
0x00 |
ULONG Flags; |
The one member receives a copy of the kernel’s NtGlobalFlag variable when querying for information. When setting, the member provides input for changing the variable and (in version 4.0 and higher) receives a copy of what the variable is changed to. Since all known versions of the kernel have NtGlobalFlag in read-write data and export its address, SystemFlagsInformation and SYSTEM_FLAGS_INFORMATION have little or no reason to exist except to help user-mode callers. Setting the kernel’s NtGlobalFlag from user mode requires SeDebugPrivilege. Even with privilege or even if calling from kernel mode, not all bits can be changed.
In the language of Microsoft’s GFLAGS tool for its /k switch, these bits that are queried and set as Flags through NtQuerySystemInformation and NtSetSystemInformation are the
Kernel flag settings. Displays or changes system-wide debugging flags for this session. These settings are effective immediately, but are lost when Windows shuts down. The settings affect processes started after this command completes.
Unfortunately for programmers who resort to these debugging flags, the selection of bits that Microsoft’s GFlags Flag Table presents with a K as a Destination or which the tool itself shows on its Kernel Flags tab bears little relationship to which flags the kernel actually does permit to change. Especially notable on this point is that Microsoft’s page Setting and Clearing Kernel Flags shows the GFLAGS dialog box as if ready to set “Show loader snaps” even though proceeding will just clear the checkbox silently unless you try it on version 5.1 or earlier.
Some sympathy is perhaps due to the GFLAGS programmers and technical writers since which bits can be changed varies widely between Windows versions. For each bit that has ever been defined, there is at least one Windows version that permits it to be changed and at least one that in some way or another does not. For only very few is the explanation plausibly that the bit was redefined. Instead, there seem to have been three distinct approaches to choosing which bits are subject to user-mode control:
Bits within the kernel’s NtGlobalFlags may affect kernel-mode execution or user-mode execution or both. User-mode execution is affected because whatever the kernel has for its NtGlobalFlags is the seed for the NtGlobalFlag member of every new user-mode process’s PEB.
The modern implementation for setting the Flags ignores roughly half the possible bits, i.e., preserves them as the kernel already had them. Though a full account is not yet known, two reasons seem plain. First, the kernel may be sensitive to the bit, such that whatever it configures of the kernel’s execution should not change until Windows is restarted. Second, the bit may have no kernel-mode effect at all, but its user-mode effects may be so wide-ranging that they would better not propagate to all new processes.
Mask | Name or Names | Action When Setting Information |
---|---|---|
0x00000001 | FLG_STOP_ON_EXCEPTION | accepted in 3.51 to 5.1; ignored in 5.2 and higher |
0x00000002 | FLG_SHOW_LDR_SNAPS | accepted in 3.51 to 5.1; ignored in 5.2 and higher |
0x00000004 | FLG_DEBUG_INITIAL_COMMAND | accepted in 3.51 to 4.0; cleared in 5.0 to 5.1; ignored in 5.2 and higher |
0x00000008 | FLG_STOP_ON_HUNG_GUI | accepted in 3.51 to 5.1; ignored in 5.2 and higher |
0x00000010 | FLG_HEAP_ENABLE_TAIL_CHECK | accepted in 3.51; cleared in 4.0 to 5.1; accepted in 5.2 and higher |
0x00000020 | FLG_HEAP_ENABLE_FREE_CHECK | accepted in 3.51; cleared in 4.0 to 5.1; accepted in 5.2 and higher |
0x00000040 | FLG_HEAP_VALIDATE_PARAMETERS | accepted in 3.51; cleared in 4.0 to 5.1; accepted in 5.2 and higher |
0x00000080 | FLG_HEAP_VALIDATE_ALL | accepted in 3.51; cleared in 4.0 to 5.1; accepted in 5.2 and higher |
0x00000100 | FLG_POOL_ENABLE_TAIL_CHECK FLG_APPLICATION_VERIFIER |
accepted in 3.51 to 4.0; cleared in 5.0 to 5.1; accepted in 5.2 and higher |
0x00000200 | FLG_POOL_ENABLE_FREE_CHECK FLG_MONITOR_SILENT_PROCESS_EXIT |
accepted in 3.51 to 4.0; cleared in 5.0 to 5.1; accepted in 5.2 and higher |
0x00000400 | FLG_POOL_ENABLE_TAGGING | accepted in 3.51 to 5.1; ignored in 5.2 and higher |
0x00000800 | FLG_HEAP_ENABLE_TAGGING | accepted in 3.51; cleared in 4.0 to 5.1; accepted in 5.2 and higher |
0x00001000 | FLG_USER_STACK_TRACE_DB | accepted in 3.51; cleared in 4.0 to 5.1; accepted in 5.2 and higher |
0x00002000 | FLG_KERNEL_STACK_TRACE_DB | accepted in 3.51; cleared in 4.0 to 5.1; ignored in 5.2 and higher |
0x00004000 | FLG_MAINTAIN_OBJECT_TYPELIST | accepted in 3.51; cleared in 4.0 to 5.1; ignored in 5.2 and higher |
0x00008000 | FLG_HEAP_ENABLE_TAG_BY_DLL | accepted in 3.51; cleared in 4.0 to 5.1; accepted in 5.2 and higher |
0x00010000 | FLG_IGNORE_DEBUG_PRIV FLG_DISABLE_STACK_EXTENSION |
accepted in 3.51 to 4.0; cleared in 5.0 to 5.1; accepted in 5.2 and higher |
0x00020000 | FLG_ENABLE_CSRDEBUG | accepted in 3.51; cleared in 4.0 to 5.1; ignored in 5.2 and higher |
0x00040000 | FLG_ENABLE_KDEBUG_SYMBOL_LOAD | accepted in 3.51 to 5.1; ignored in 5.2 and higher |
0x00080000 | FLG_DISABLE_PAGE_KERNEL_STACKS | accepted in 3.51; cleared in 4.0 to 5.1; ignored in 5.2 and higher |
0x00100000 | FLG_HEAP_ENABLE_CALL_TRACING FLG_ENABLE_SYSTEM_CRIT_BREAKS |
accepted in 3.51; cleared in 4.0 to 5.1; accepted in 5.2 and higher |
0x00200000 | FLG_HEAP_DISABLE_COALESCING | accepted in 3.51; cleared in 4.0 to 5.1; accepted in 5.2 and higher |
0x00400000 | FLG_ENABLE_CLOSE_EXCEPTIONS | cleared in 3.51; accepted in 4.0 to 5.1; ignored in 5.2 and higher |
0x00800000 | FLG_ENABLE_EXCEPTION_LOGGING | cleared in 3.51; accepted in 4.0 to 5.1; ignored in 5.2 and higher |
0x01000000 | FLG_ENABLE_HANDLE_TYPE_TAGGING | cleared in 3.51; accepted in 4.0 to 5.1; ignored in 5.2 and higher |
0x02000000 | FLG_HEAP_PAGE_ALLOCS | cleared in 3.51 to 5.1; accepted in 5.2 and higher |
0x04000000 | FLG_DEBUG_INITIAL_COMMAND_EX | cleared in 3.51; accepted in 4.0; cleared in 5.0 to 5.1; ignored in 5.2 and higher |
0x08000000 | FLG_DISABLE_DBGPRINT | cleared in 3.51 to 4.0; accepted in 5.0 to 5.1; ignored in 5.2 and higher |
0x10000000 | FLG_CRITSEC_EVENT_CREATION | cleared in 3.51 to 5.1; accepted in 5.2 and higher |
0x20000000 | FLG_LDR_TOP_DOWN FLG_STOP_ON_UNHANDLED_EXCEPTION |
cleared in 3.51 to 5.1; accepted in 5.2 to 6.2; ignored in 6.3 and higher |
0x40000000 | FLG_ENABLE_HANDLE_EXCEPTIONS | cleared in 3.51 to 5.0; accepted in 5.1; ignored in 5.2 and higher |
0x80000000 | FLG_DISABLE_PROTDLLS | cleared in 3.51 to 5.1; accepted in 5.2 and higher |