If you want to check if you are running on a Server Core edition of Windows you can use the GetProductInfo API.
GetProductInfo takes 4 input parameters that can be obtained using GetVersionEx and the OSVERSIONINFOEX structure:
var
osvi: OSVERSIONINFOEX;
begin
ZeroMemory(@osvi, SizeOf(osvi));
osvi.dwOSVersionInfoSize := SizeOf(osvi);
Win32Check(GetVersionEx(osvi));No we call GetProductInfo:
var
dwProdType: DWORD;
begin
Win32Check(GetProductInfo(osvi.dwMajorVersion, osvi.dwMinorVersion,
osvi.wServicePackMajor, osvi.wServicePackMinor, dwProdType));
The value returned in dwProdType can be checked against one of the constants for the Server Core editions:
PRODUCT_DATACENTER_SERVER_CORE,
PRODUCT_STANDARD_SERVER_CORE,
PRODUCT_ENTERPRISE_SERVER_CORE,
PRODUCT_WEB_SERVER_CORE,
PRODUCT_DATACENTER_SERVER_CORE_V,
PRODUCT_STANDARD_SERVER_CORE_V,
PRODUCT_ENTERPRISE_SERVER_CORE_V,
PRODUCT_STORAGE_EXPRESS_SERVER_CORE,
PRODUCT_STORAGE_STANDARD_SERVER_CORE,
PRODUCT_STORAGE_WORKGROUP_SERVER_CORE,
PRODUCT_STORAGE_ENTERPRISE_SERVER_CORE,
PRODUCT_STANDARD_SERVER_SOLUTIONS_CORE,
PRODUCT_SOLUTION_EMBEDDEDSERVER_CORE,
PRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORESo if put this all together we can write a function for it:
function IsServerCore: Boolean;
var
osvi: OSVERSIONINFOEX;
dwProdType: DWORD;
begin
ZeroMemory(@osvi, SizeOf(osvi));
osvi.dwOSVersionInfoSize := SizeOf(osvi);
Win32Check(GetVersionEx(osvi));
Win32Check(GetProductInfo(osvi.dwMajorVersion, osvi.dwMinorVersion,
osvi.wServicePackMajor, osvi.wServicePackMinor, dwProdType));
case dwProdType of
PRODUCT_DATACENTER_SERVER_CORE,
PRODUCT_STANDARD_SERVER_CORE,
PRODUCT_ENTERPRISE_SERVER_CORE,
PRODUCT_WEB_SERVER_CORE,
PRODUCT_DATACENTER_SERVER_CORE_V,
PRODUCT_STANDARD_SERVER_CORE_V,
PRODUCT_ENTERPRISE_SERVER_CORE_V,
PRODUCT_STORAGE_EXPRESS_SERVER_CORE,
PRODUCT_STORAGE_STANDARD_SERVER_CORE,
PRODUCT_STORAGE_WORKGROUP_SERVER_CORE,
PRODUCT_STORAGE_ENTERPRISE_SERVER_CORE,
PRODUCT_STANDARD_SERVER_SOLUTIONS_CORE,
PRODUCT_SOLUTION_EMBEDDEDSERVER_CORE,
PRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE: Result := True
else
Result := False;
end;
end;But where do these values come from?
GetProductInfo is exported by Kernel32.dll, this function is a stub to RtlGetProductInfo which is exported by ntdll.dll
RtlGetProductInfo performs a few checks on the input parameters and then calls the undocumented NtQueryLicenseValue API which has this signature:
function NtQueryLicenseValue(Name: PUNICODE_STRING; ulType: ULONG;
Buffer: Pointer; Length: ULONG; var DataLength: ULONG): NTSTATUS; stdcall;The value of the Name parameter on my Windows 7 machine is Kernel-ProductInfo, the ulType parameter is SL_DATA_DWORD (4), the buffer is a PDWORD with Length being SizeOf(DWORD).
If the call to NtQueryLicenseValue fails, a special value of 0xABCDABCDu is returned which equals PRODUCT_UNLICENSED.
You can directly check this value with the Licensing Demo from my Having fun with Windows Licensing article: