Geoff Chappell, Software Analyst
The LdrQueryImageFileExecutionOptionsEx function queries one value in the Image File Execution Options key for a named image file.
NTSTATUS LdrQueryImageFileExecutionOptionsEx ( PUNICODE_STRING lpImageFile, PCWSTR lpszOption, ULONG dwType, PVOID lpData, ULONG cbData, ULONG *lpcbData, BOOLEAN bWow64);
The lpImageFile argument names the executable image for which the option is sought. This can be NULL in version 6.0 and higher to query for global options.
The lpszOption argument names the one option whose value is sought.
The dwType argument specifies the type for the value as produced in the output buffer. This is typically also, but need not be, the required type for the value as stored in the registry.
The optional lpData and cbData arguments are respectively the address and size of the output buffer that is to receive the value. These arguments can be NULL and zero to query for the option’s existence or size.
The optional lpcbData argument provides the address of a variable that is to receive the size, in bytes, of the value that the successful function has put into the buffer and which may receive the size that the failed function might have put into the buffer (had the buffer been large enough). This argument can be NULL if the caller does not want to know how much data is produced or is available.
The bWow64 argument is non-zero to query the Wow6432Node branch. This argument is ignored in version 6.1 and higher.
The function returns STATUS_SUCCESS if successful, else a negative error code.
Of particular importance is STATUS_BUFFER_OVERFLOW, which is the function’s indication that the buffer, if any, is too small for the whole value and that a size that would have sufficed has been set into the variable, if any, that was specified through the lpcbData argument.
The LdrQueryImageFileExecutionOptionsEx function is exported by name from NTDLL.DLL in version 5.2 and higher.
In version 6.0 and higher, the name LdrQueryImageFileExecutionOptionsEx exists just for export. Were the function not exported, it would be an internal routine whose only name is RtlQueryImageFileExecutionOptions. As usual for Run Time Library (RTL) routines, the code is written for both kernel and user modes. The relatively little use that the kernel makes of this routine in version 6.0 and higher is mostly inline but the routine is explicit in versions 6.2 and 10.0. No version of the kernel exports it.
The LdrQueryImageFileExecutionOptionsEx function is not documented. Neither is it declared in any C-language header that Microsoft is known to have published in any development kit for either user-mode or kernel-mode software. While Microsoft’s names and types for the function’s arguments are not known, this article uses inventions.
The general business of the LdrQueryImageFileExecutionOptionsEx function is to open the registry key for the given executable, query the given option as a registry value, and close the key. In all versions that export the function, except on one point (taken up in the next paragraph), the open and the query are done by subroutines. Starting with the version 5.2 from Windows Server 2003 SP1, these subroutines are exported as LdrOpenImageFileOptionsKey and LdrQueryImageFileKeyOption. This allows for efficiency when querying multiple options for one executable. The LdrQueryImageFileExecutionOptionsEx function is then a convenient compound when querying just one option. For the behaviour of each part, follow the links.
The one point of exception to this function’s being a compound of LdrOpenImageFileOptionsKey and LdrQueryImageFileKeyOption concerns access in version 6.0 and higher to what the notes on LdrOpenImageFileOptionsKey refer to as the base key:
Options for different executables are in different subkeys of this base key, or even deeper, but version 6.0 and higher also allow for global options in the base key itself. These are queried by giving NULL for the lpImageFile argument. This is not suitable input for LdrOpenImageFileOptionsKey, which knows of the base key only as a root to keep open for more efficient access to the subkeys, not for exposing to its callers. Though the LdrQueryImageFileExecutionOptionsEx function therefore does not use LdrOpenImageFileOptionsKey in this case, the base key is handled in common. If the base key is not already open, then failure to open it becomes failure for the function. The required access is KEY_QUERY_VALUE and KEY_ENUMERATE_SUB_KEYS.
It seems likely that NULL for lpImageFile never was intended for this function as an NTDLL export. Microsoft’s only known use is by the kernel. Though LdrQueryImageFileExecutionOptionsEx is not a kernel-mode export, the kernel does have the same code internally in a reduction that assumes NULL for lpImageFile and has other arguments specialised to query only for a REG_DWORD value. The known global options are:
|DevOverrideEnable||6.0 and higher|
|MaxLoaderThreads||10.0 and higher|
|NoRemoteThreadBeforeProcessInit||1709 and higher|
The DevOverrideEnable value, if not more generally that Image File Execution Options can be global, was disclosed from the start as semi-official folklore by making it the subject of a Microsoft blog: DotLocal (.local) Dll Redirection.
In version 5.2 before Windows Server 2003 SP1, the function is a compound as in later versions but the components that separately open the key and query the value are not yet exported and are slightly less developed. Notably, the routine that opens the key does not cache handles to the base keys. If the path to the key for the named image exceeds 710 bytes, the function fails, returning STATUS_BUFFER_TOO_SMALL. That 710 bytes, specifically, is allowed on the stack may be a programmer’s rough allowance of a round-number 500 bytes for appending the filename to the longer of the base-key paths. Failure to open the key (from this full path) is failure for the function.