Geoff Chappell, Software Analyst
This function gets the data for a named license value.
NTSTATUS ZwQueryLicenseValue ( PUNICODE_STRING ValueName, ULONG *Type, PVOID Data, ULONG DataSize, ULONG *ResultDataSize);
The ValueName argument provides the address of a UNICODE_STRING structure for the name of the value for which data is wanted.
The optional Type argument provides the address of a variable that is to receive the type of data: REG_SZ (0x01) for a string; REG_BINARY (0x03) for binary data; REG_DWORD (0x04) for a dword.
The optional Data and DataSize arguments provide the address and size (in bytes) of a buffer that is to receive the data for the named value.
The ResultDataSize argument provides the address of a variable that is to receive the size (in bytes) of whatever data the function produces in the buffer.
The function returns STATUS_SUCCESS if successful, else a negative error code.
Of particular importance is STATUS_BUFFER_TOO_SMALL, which is the function’s indication that the license value exists but the buffer is too small to receive the data. A size that would have sufficed for a full return of the data will have been set into the variable that was specified through the ReturnDataSize argument.
The ZwQueryLicenseValue function is exported by name from the kernel in version 6.0 and higher. It is also available in user mode, being exported by name both as NtQueryLicenseValue and ZwQueryLicenseValue from NTDLL.DLL in version 6.0 and higher.
Neither ZwQueryLicenseValue nor its alias is documented. As ZwQueryLicenseValue, it is declared in the ZWAPI.H file in the Windows Driver Kit (WDK) for Windows 10. This article has been adapted to use Microsoft’s names for the function’s arguments, as disclosed by that declaration.
Unusually for native API functions, no repackaging of NtQueryLicenseValue, documented or not, is known in any higher-level user-mode module that is distributed as standard with Windows.
The function has no purpose except to produce data for a named value or at least to report how much data might be produced. The ValueName is therefore required and since the amount of data cannot be known to the caller in advance with certainty, the ResultDataSize argument is required too. If either is NULL, the function returns STATUS_INVALID_PARAMETER.
To ease the calling of the function just to discover how big a buffer to provide for the data, it is allowed that Data may be NULL. Starting with the 1607 release of Windows 10, if Data is NULL, then DataSize must be zero, else again the function returns STATUS_INVALID_PARAMETER. Also starting with that release, if a buffer is provided, then the DataSize cannot exceed 0x00800000, i.e., 8MB, else the function returns STATUS_NO_MEMORY.
If the license has been tampered with, the function fails (returning STATUS_INTERNAL_ERROR). If the licensing cache is corrupt, the function fails (returning STATUS_DATA_ERROR). If there are no licensing descriptors but the kernel thinks it has the licensing descriptors sorted, the function fails (returning STATUS_OJBECT_NAME_NOT_FOUND). If the licensing descriptors are not sorted, they have to be.