Browse Source

[sys/info] Initial version.

Jeroen van Rijn 3 years ago
parent
commit
d5f94d73ad

+ 26 - 0
core/sys/info/cpu_arm.odin

@@ -0,0 +1,26 @@
+//+build arm32, arm64
+package sysinfo
+
+// TODO: Set up an enum with the ARM equivalent of the above.
+CPU_Feature :: enum u64 {}
+
+cpu_features: Maybe(CPU_Feature)
+cpu_name:     Maybe(string)
+
+@(init, private)
+init_cpu_features :: proc "c" () {
+}
+
+@(private)
+_cpu_name_buf: [72]u8
+
+@(init, private)
+init_cpu_name :: proc "c" () {
+	when ODIN_ARCH == .arm32 {
+		copy(_cpu_name_buf, "ARM")
+		cpu_name = string(_cpu_name_buf[:3])
+	} else {
+		copy(_cpu_name_buf, "ARM64")
+		cpu_name = string(_cpu_name_buf[:5])
+	}
+}

+ 30 - 2
core/simd/x86/cpu.odin → core/sys/info/cpu_intel.odin

@@ -1,5 +1,5 @@
 //+build i386, amd64
-package simd_x86
+package sysinfo
 
 import "core:intrinsics"
 
@@ -9,7 +9,6 @@ cpuid :: intrinsics.x86_cpuid
 // xgetbv :: proc(cx: u32) -> (eax, edx: u32) ---
 xgetbv :: intrinsics.x86_xgetbv
 
-
 CPU_Feature :: enum u64 {
 	aes,       // AES hardware implementation (AES NI)
 	adx,       // Multi-precision add-carry instruction extensions
@@ -34,6 +33,7 @@ CPU_Feature :: enum u64 {
 CPU_Features :: distinct bit_set[CPU_Feature; u64]
 
 cpu_features: Maybe(CPU_Features)
+cpu_name:     Maybe(string)
 
 @(init, private)
 init_cpu_features :: proc "c" () {
@@ -92,3 +92,31 @@ init_cpu_features :: proc "c" () {
 
 	cpu_features = set
 }
+
+@(private)
+_cpu_name_buf: [72]u8
+
+@(init, private)
+init_cpu_name :: proc "c" () {
+	number_of_extended_ids, _, _, _ := cpuid(0x8000_0000, 0)
+	if number_of_extended_ids < 0x8000_0004 {
+		return
+	}
+
+	_buf := transmute(^[0x12]u32)&_cpu_name_buf
+	_buf[ 0], _buf[ 1], _buf[ 2], _buf[ 3] = cpuid(0x8000_0002, 0)
+	_buf[ 4], _buf[ 5], _buf[ 6], _buf[ 7] = cpuid(0x8000_0003, 0)
+	_buf[ 8], _buf[ 9], _buf[10], _buf[11] = cpuid(0x8000_0004, 0)
+
+	// Some CPUs like may include leading or trailing spaces. Trim them.
+	// e.g. `      Intel(R) Xeon(R) CPU E5-1650 v2 @ 3.50GHz`
+
+	brand := string(_cpu_name_buf[:])
+	for len(brand) > 0 && brand[0] == 0 || brand[0] == ' ' {
+		brand = brand[1:]
+	}
+	for len(brand) > 0 && brand[len(brand) - 1] == 0 || brand[len(brand) - 1] == ' ' {
+		brand = brand[:len(brand) - 1]
+	}
+	cpu_name = brand
+}

+ 33 - 0
core/sys/info/platform_darwin.odin

@@ -0,0 +1,33 @@
+// +build darwin
+package sysinfo
+
+import sys "core:sys/darwin"
+import "core:intrinsics"
+
+@(init, private)
+init_os_version :: proc "c" () {
+	os_version = {}
+}
+
+@(init)
+init_ram :: proc() {
+	// Retrieve RAM info using `sysinfo`
+
+	CTL_HW     :: 6
+	HW_MEMSIZE :: 24
+
+	sysctls := []int{CTL_HW, HW_MEMSIZE}
+
+	mem_size: i64
+
+	if intrinsics.syscall(
+		uintptr(sys.System_Call_Number.sysctl),
+		uintptr(raw_data(sysctls)), uintptr(len(sysctls)),
+		uintptr(&mem_size), uintptr(size_of(mem_size))) == 0 {
+		return
+	}
+	ram.total_ram = int(mem_size)
+}
+
+@(private)
+sysctl :: proc(leaf: int)

+ 54 - 0
core/sys/info/platform_linux.odin

@@ -0,0 +1,54 @@
+// +build linux
+package sysinfo
+
+import "core:c"
+import sys "core:sys/unix"
+import "core:intrinsics"
+// import "core:fmt"
+
+@(init, private)
+init_os_version :: proc "c" () {
+	os_version = {}
+}
+
+Sys_Info :: struct {
+	uptime:    c.long,     // Seconds since boot
+	loads:     [3]c.long,  // 1, 5, 15 minute load averages
+	totalram:  c.ulong,    // Total usable main memory size
+	freeram:   c.ulong,    // Available memory size
+	sharedram: c.ulong,    // Amount of shared memory
+	bufferram: c.ulong,    // Memory used by buffers
+	totalswap: c.ulong,    // Total swap space size
+	freeswap:  c.ulong,    // Swap space still available
+	procs:     c.ushort,   // Number of current processes
+	totalhigh: c.ulong,    // Total high memory size
+	freehigh:  c.ulong,    // Available high memory size
+	mem_unit:  c.int,      // Memory unit size in bytes
+	_padding:  [20 - (2 * size_of(c.long)) - size_of(c.int)]u8,
+}
+
+get_sysinfo :: proc "c" () -> (res: Sys_Info, ok: bool) {
+	si: Sys_Info
+	err := intrinsics.syscall(sys.SYS_sysinfo, uintptr(rawptr(&si)))
+	if err != 0 {
+		// Unable to retrieve sysinfo
+		return {}, false
+	}
+	return si, true
+}
+
+@(init)
+init_ram :: proc() {
+	// Retrieve RAM info using `sysinfo`
+	si, ok := get_sysinfo()
+	if !ok {
+		return
+	}
+
+	ram = RAM{
+		total_ram  = int(si.totalram)  * int(si.mem_unit),
+		free_ram   = int(si.freeram)   * int(si.mem_unit),
+		total_swap = int(si.totalswap) * int(si.mem_unit),
+		free_swap  = int(si.freeswap)  * int(si.mem_unit),
+	}
+}

+ 305 - 0
core/sys/info/platform_windows.odin

@@ -0,0 +1,305 @@
+// +build windows
+package sysinfo
+
+import sys "core:sys/windows"
+import "core:intrinsics"
+import "core:strings"
+
+
+@(private)
+version_string_buf: [1024]u8
+
+@(init, private)
+init_os_version :: proc () {
+	/*
+		NOTE(Jeroen):
+			`GetVersionEx`  will return 6.2 for Windows 10 unless the program is manifested for Windows 10.
+			`RtlGetVersion` will return the true version.
+
+			Rather than include the WinDDK, we ask the kernel directly.
+			`HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion` is for the minor build version (Update Build Release)
+
+	*/
+	osvi: sys.OSVERSIONINFOEXW
+	osvi.dwOSVersionInfoSize = size_of(osvi)
+	status := sys.RtlGetVersion(&osvi)
+
+	if status != 0 {
+		return
+	}
+
+	product_type: sys.Windows_Product_Type
+	sys.GetProductInfo(
+		osvi.dwMajorVersion,         osvi.dwMinorVersion,
+		u32(osvi.wServicePackMajor), u32(osvi.wServicePackMinor),
+		&product_type,
+	)
+
+	os_version = {
+		platform = .Windows,
+		major    = int(osvi.dwMajorVersion),
+		minor    = int(osvi.dwMinorVersion),
+	}
+	os_version.build[0] = int(osvi.dwBuildNumber)
+
+	b := strings.builder_from_bytes(version_string_buf[:])
+
+	strings.write_string(&b, "Windows ")
+
+	switch osvi.dwMajorVersion {
+	case 10:
+		switch osvi.wProductType {
+		case 1: // VER_NT_WORKSTATION:
+			if osvi.dwBuildNumber < 22000 {
+				strings.write_string(&b, "10 ")
+			} else {
+				strings.write_string(&b, "11 ")
+			}
+			format_windows_product_type(&b, product_type)
+
+		case: // Server or Domain Controller
+			switch osvi.dwBuildNumber {
+			case 14393:
+				strings.write_string(&b, "2016 Server")
+			case 17763:
+				strings.write_string(&b, "2019 Server")
+			case 20348:
+				strings.write_string(&b, "2022 Server")
+			case:
+				strings.write_string(&b, "Unknown Server")
+			}
+		}
+
+	case 6:
+		switch osvi.dwMinorVersion {
+		case 0:
+			switch osvi.wProductType {
+			case 1: // VER_NT_WORKSTATION
+				strings.write_string(&b, "Windows Vista ")
+				format_windows_product_type(&b, product_type)
+			case 3:
+				strings.write_string(&b, "Windows Server 2008")
+			}
+
+		case 1:
+			switch osvi.wProductType {
+			case 1: // VER_NT_WORKSTATION:
+				strings.write_string(&b, "Windows 7 ")
+				format_windows_product_type(&b, product_type)
+			case 3:
+				strings.write_string(&b, "Windows Server 2008 R2")
+			}
+
+		case 2:
+			switch osvi.wProductType {
+			case 1: // VER_NT_WORKSTATION:
+				strings.write_string(&b, "Windows 8 ")
+				format_windows_product_type(&b, product_type)
+			case 3:
+				strings.write_string(&b, "Windows Server 2012")
+			}
+
+		case 3:
+			switch osvi.wProductType {
+			case 1: // VER_NT_WORKSTATION:
+				strings.write_string(&b, "Windows 8.1 ")
+				format_windows_product_type(&b, product_type)
+			case 3:
+				strings.write_string(&b, "Windows Server 2012 R2")
+			}
+		}
+
+	case 5:
+		switch osvi.dwMinorVersion {
+		case 0:
+			strings.write_string(&b, "Windows 2000")
+		case 1:
+			strings.write_string(&b, "Windows XP")
+		case 2:
+			strings.write_string(&b, "Windows Server 2003")
+		}
+	}
+
+	// Grab DisplayVersion
+	os_version.version = format_display_version(&b)
+
+	// Grab build number and UBR
+	os_version.build[1]  = format_build_number(&b, int(osvi.dwBuildNumber))
+
+	// Finish the string
+	os_version.as_string = strings.to_string(b)
+
+	format_windows_product_type :: proc (b: ^strings.Builder, prod_type: sys.Windows_Product_Type) {
+		#partial switch prod_type {
+		case .ULTIMATE:
+			strings.write_string(b, "Ultimate")
+
+		case .HOME_BASIC:
+			strings.write_string(b, "Home Basic")
+
+		case .HOME_PREMIUM:
+			strings.write_string(b, "Home Premium")
+
+		case .ENTERPRISE:
+			strings.write_string(b, "Enterprise")
+
+		case .CORE:
+			strings.write_string(b, "Home Basic")
+
+		case .HOME_BASIC_N:
+			strings.write_string(b, "Home Basic N")
+
+		case .EDUCATION:
+			strings.write_string(b, "Education")
+
+		case .EDUCATION_N:
+			strings.write_string(b, "Education N")
+
+		case .BUSINESS:
+			strings.write_string(b, "Business")
+
+		case .STANDARD_SERVER:
+			strings.write_string(b, "Standard Server")
+
+		case .DATACENTER_SERVER:
+			strings.write_string(b, "Datacenter")
+
+		case .SMALLBUSINESS_SERVER:
+			strings.write_string(b, "Windows Small Business Server")
+
+		case .ENTERPRISE_SERVER:
+			strings.write_string(b, "Enterprise Server")
+
+		case .STARTER:
+			strings.write_string(b, "Starter")
+
+		case .DATACENTER_SERVER_CORE:
+			strings.write_string(b, "Datacenter Server Core")
+
+		case .STANDARD_SERVER_CORE:
+			strings.write_string(b, "Server Standard Core")
+
+		case .ENTERPRISE_SERVER_CORE:
+			strings.write_string(b, "Enterprise Server Core")
+
+		case .BUSINESS_N:
+			strings.write_string(b, "Business N")
+
+		case .HOME_SERVER:
+			strings.write_string(b, "Home Server")
+
+		case .SERVER_FOR_SMALLBUSINESS:
+			strings.write_string(b, "Windows Server 2008 for Windows Essential Server Solutions")
+
+		case .SMALLBUSINESS_SERVER_PREMIUM:
+			strings.write_string(b, "Small Business Server Premium")
+
+		case .HOME_PREMIUM_N:
+			strings.write_string(b, "Home Premium N")
+
+		case .ENTERPRISE_N:
+			strings.write_string(b, "Enterprise N")
+
+		case .ULTIMATE_N:
+			strings.write_string(b, "Ultimate N")
+
+		case .HYPERV:
+			strings.write_string(b, "HyperV")
+
+		case .STARTER_N:
+			strings.write_string(b, "Starter N")
+
+		case .PROFESSIONAL:
+			strings.write_string(b, "Professional")
+
+		case .PROFESSIONAL_N:
+			strings.write_string(b, "Professional N")
+
+		case:
+			strings.write_string(b, "Unknown Edition")
+		}
+	}
+
+	// Grab Windows DisplayVersion (like 20H02)
+	format_display_version :: proc (b: ^strings.Builder) -> (version: string) {
+		value_type: ^sys.DWORD
+		display_version: [256]u16le
+		value_size := sys.DWORD(size_of(display_version))
+
+		status := sys.RegGetValueW(
+			sys.HKEY_LOCAL_MACHINE,
+			sys.L("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"),
+			sys.L("DisplayVersion"),
+			sys.RRF_RT_REG_SZ,
+			value_type,
+			raw_data(display_version[:]),
+			&value_size,
+		)
+		if status != 0 {
+			// Couldn't retrieve DisplayVersion
+			return
+		}
+
+		strings.write_string(b, " (version: ")
+		l := strings.builder_len(b^)
+
+		for r, i in display_version {
+			if r == 0 {
+				s := strings.to_string(b^)
+				version = string(s[l:][:i])
+				break
+			}
+			if r < 256 {
+				strings.write_rune(b, rune(r))
+			}
+		}
+		strings.write_rune(b, ')')
+		return
+	}
+
+	// Grab build number and UBR
+	format_build_number :: proc (b: ^strings.Builder, major_build: int) -> (ubr: int) {
+		value_type: ^sys.DWORD
+		_ubr: sys.DWORD
+		value_size := sys.DWORD(size_of(ubr))
+
+		status := sys.RegGetValueW(
+			sys.HKEY_LOCAL_MACHINE,
+			sys.L("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"),
+			sys.L("UBR"),
+			sys.RRF_RT_REG_DWORD,
+			value_type,
+			&_ubr,
+			&value_size,
+		)
+
+		if status != 0 {
+			// Couldn't retrieve DisplayVersion
+			return
+		}
+
+		ubr  = int(_ubr)
+		strings.write_string(b, ", build: ")
+		strings.write_int(b, major_build)
+		strings.write_rune(b, '.')
+		strings.write_int(b, ubr)
+		return
+	}
+}
+
+@(init)
+init_ram :: proc() {
+	state: sys.MEMORYSTATUSEX
+
+	state.dwLength = size_of(state)
+	ok := sys.GlobalMemoryStatusEx(&state)
+	if !ok {
+		return
+	}
+	ram = RAM{
+		total_ram  = int(state.ullTotalPhys),
+		free_ram   = int(state.ullAvailPhys),
+		total_swap = int(state.ullTotalPageFil),
+		free_swap  = int(state.ullAvailPageFil),
+	}
+}

+ 38 - 0
core/sys/info/sysinfo.odin

@@ -0,0 +1,38 @@
+package sysinfo
+
+when !(ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 || ODIN_ARCH == .arm32 || ODIN_ARCH == .arm64) {
+	#assert(false, "This package is unsupported on this architecture.")
+}
+
+os_version: OS_Version
+ram:        RAM
+
+OS_Version_Platform :: enum {
+	Unknown,
+	Windows,
+	Linux,
+	MacOS,
+	iOS,
+	FreeBSD,
+	OpenBSD,
+	NetBSD,
+}
+
+OS_Version :: struct {
+	platform: OS_Version_Platform,
+
+	major:     int,
+	minor:     int,
+	patch:     int,
+	build:     [2]int,
+	version:   string,
+
+	as_string: string,
+}
+
+RAM :: struct {
+	total_ram:  int,
+	free_ram:   int,
+	total_swap: int,
+	free_swap:  int,
+}

+ 18 - 0
core/sys/windows/kernel32.odin

@@ -637,6 +637,13 @@ foreign kernel32 {
 	) -> BOOL ---
 }
 
+@(default_calling_convention="stdcall")
+foreign kernel32 {
+	GlobalMemoryStatusEx :: proc(
+		lpBuffer: ^MEMORYSTATUSEX,
+	) -> BOOL ---
+}
+
 PBAD_MEMORY_CALLBACK_ROUTINE :: #type proc "stdcall" ()
 
 @(default_calling_convention="stdcall")
@@ -794,3 +801,14 @@ Control_Event :: enum DWORD {
 	logoff    = 5,
 	shutdown  = 6,
 }
+
+@(default_calling_convention="stdcall")
+foreign kernel32 {
+	GetProductInfo :: proc(
+		OSMajorVersion: DWORD,
+		OSMinorVersion: DWORD,
+		SpMajorVersion: DWORD,
+		SpMinorVersion: DWORD,
+		product_type: ^Windows_Product_Type,
+	) -> BOOL ---
+}

+ 114 - 0
core/sys/windows/types.odin

@@ -17,6 +17,7 @@ size_t      :: c.size_t
 wchar_t     :: c.wchar_t
 
 DWORD :: c_ulong
+DWORDLONG :: c.ulonglong
 QWORD :: c.ulonglong
 HANDLE :: distinct LPVOID
 HINSTANCE :: HANDLE
@@ -3265,3 +3266,116 @@ IFileSaveDialogVtbl :: struct {
 	GetProperties:          proc "stdcall" (this: ^IFileSaveDialog, ppStore: ^^IPropertyStore) -> HRESULT,
 	ApplyProperties:        proc "stdcall" (this: ^IFileSaveDialog, psi: ^IShellItem, pStore: ^IPropertyStore, hwnd: HWND, pSink: ^IFileOperationProgressSink) -> HRESULT,
 }
+
+MEMORYSTATUSEX :: struct {
+	dwLength:                DWORD,
+	dwMemoryLoad:            DWORD,
+	ullTotalPhys:            DWORDLONG,
+	ullAvailPhys:            DWORDLONG,
+	ullTotalPageFil:         DWORDLONG,
+	ullAvailPageFil:         DWORDLONG,
+	ullTotalVirtual:         DWORDLONG,
+	ullAvailVirtual:         DWORDLONG,
+	ullAvailExtendedVirtual: DWORDLONG,
+}
+
+Windows_Product_Type :: enum DWORD {
+	BUSINESS                            = 0x00000006, // Business
+	BUSINESS_N                          = 0x00000010, // Business N
+	CLUSTER_SERVER                      = 0x00000012, // HPC Edition
+	CLUSTER_SERVER_V                    = 0x00000040, // Server Hyper Core V
+	CORE                                = 0x00000065, // Windows 10 Home
+	CORE_COUNTRYSPECIFIC                = 0x00000063, // Windows 10 Home China
+	CORE_N                              = 0x00000062, // Windows 10 Home N
+	CORE_SINGLELANGUAGE                 = 0x00000064, // Windows 10 Home Single Language
+	DATACENTER_EVALUATION_SERVER        = 0x00000050, // Server Datacenter (evaluation installation)
+	DATACENTER_A_SERVER_CORE            = 0x00000091, // Server Datacenter, Semi-Annual Channel (core installation)
+	STANDARD_A_SERVER_CORE              = 0x00000092, // Server Standard, Semi-Annual Channel (core installation)
+	DATACENTER_SERVER                   = 0x00000008, // Server Datacenter (full installation. For Server Core installations of Windows Server 2012 and later, use the method, Determining whether Server Core is running.)
+	DATACENTER_SERVER_CORE              = 0x0000000C, // Server Datacenter (core installation, Windows Server 2008 R2 and earlier)
+	DATACENTER_SERVER_CORE_V            = 0x00000027, // Server Datacenter without Hyper-V (core installation)
+	DATACENTER_SERVER_V                 = 0x00000025, // Server Datacenter without Hyper-V (full installation)
+	EDUCATION                           = 0x00000079, // Windows 10 Education
+	EDUCATION_N                         = 0x0000007A, // Windows 10 Education N
+	ENTERPRISE                          = 0x00000004, // Windows 10 Enterprise
+	ENTERPRISE_E                        = 0x00000046, // Windows 10 Enterprise E
+	ENTERPRISE_EVALUATION               = 0x00000048, // Windows 10 Enterprise Evaluation
+	ENTERPRISE_N                        = 0x0000001B, // Windows 10 Enterprise N
+	ENTERPRISE_N_EVALUATION             = 0x00000054, // Windows 10 Enterprise N Evaluation
+	ENTERPRISE_S                        = 0x0000007D, // Windows 10 Enterprise 2015 LTSB
+	ENTERPRISE_S_EVALUATION             = 0x00000081, // Windows 10 Enterprise 2015 LTSB Evaluation
+	ENTERPRISE_S_N                      = 0x0000007E, // Windows 10 Enterprise 2015 LTSB N
+	ENTERPRISE_S_N_EVALUATION           = 0x00000082, // Windows 10 Enterprise 2015 LTSB N Evaluation
+	ENTERPRISE_SERVER                   = 0x0000000A, // Server Enterprise (full installation)
+	ENTERPRISE_SERVER_CORE              = 0x0000000E, // Server Enterprise (core installation)
+	ENTERPRISE_SERVER_CORE_V            = 0x00000029, // Server Enterprise without Hyper-V (core installation)
+	ENTERPRISE_SERVER_IA64              = 0x0000000F, // Server Enterprise for Itanium-based Systems
+	ENTERPRISE_SERVER_V                 = 0x00000026, // Server Enterprise without Hyper-V (full installation)
+	ESSENTIALBUSINESS_SERVER_ADDL       = 0x0000003C, // Windows Essential Server Solution Additional
+	ESSENTIALBUSINESS_SERVER_ADDLSVC    = 0x0000003E, // Windows Essential Server Solution Additional SVC
+	ESSENTIALBUSINESS_SERVER_MGMT       = 0x0000003B, // Windows Essential Server Solution Management
+	ESSENTIALBUSINESS_SERVER_MGMTSVC    = 0x0000003D, // Windows Essential Server Solution Management SVC
+	HOME_BASIC                          = 0x00000002, // Home Basic
+	HOME_BASIC_E                        = 0x00000043, // Not supported
+	HOME_BASIC_N                        = 0x00000005, // Home Basic N
+	HOME_PREMIUM                        = 0x00000003, // Home Premium
+	HOME_PREMIUM_E                      = 0x00000044, // Not supported
+	HOME_PREMIUM_N                      = 0x0000001A, // Home Premium N
+	HOME_PREMIUM_SERVER                 = 0x00000022, // Windows Home Server 2011
+	HOME_SERVER                         = 0x00000013, // Windows Storage Server 2008 R2 Essentials
+	HYPERV                              = 0x0000002A, // Microsoft Hyper-V Server
+	IOTENTERPRISE                       = 0x000000BC, // Windows IoT Enterprise
+	IOTENTERPRISE_S                     = 0x000000BF, // Windows IoT Enterprise LTSC
+	IOTUAP                              = 0x0000007B, // Windows 10 IoT Core
+	IOTUAPCOMMERCIAL                    = 0x00000083, // Windows 10 IoT Core Commercial
+	MEDIUMBUSINESS_SERVER_MANAGEMENT    = 0x0000001E, // Windows Essential Business Server Management Server
+	MEDIUMBUSINESS_SERVER_MESSAGING     = 0x00000020, // Windows Essential Business Server Messaging Server
+	MEDIUMBUSINESS_SERVER_SECURITY      = 0x0000001F, // Windows Essential Business Server Security Server
+	MOBILE_CORE                         = 0x00000068, // Windows 10 Mobile
+	MOBILE_ENTERPRISE                   = 0x00000085, // Windows 10 Mobile Enterprise
+	MULTIPOINT_PREMIUM_SERVER           = 0x0000004D, // Windows MultiPoint Server Premium (full installation)
+	MULTIPOINT_STANDARD_SERVER          = 0x0000004C, // Windows MultiPoint Server Standard (full installation)
+	PRO_WORKSTATION                     = 0x000000A1, // Windows 10 Pro for Workstations
+	PRO_WORKSTATION_N                   = 0x000000A2, // Windows 10 Pro for Workstations N
+	PROFESSIONAL                        = 0x00000030, // Windows 10 Pro
+	PROFESSIONAL_E                      = 0x00000045, // Not supported
+	PROFESSIONAL_N                      = 0x00000031, // Windows 10 Pro N
+	PROFESSIONAL_WMC                    = 0x00000067, // Professional with Media Center
+	SB_SOLUTION_SERVER                  = 0x00000032, // Windows Small Business Server 2011 Essentials
+	SB_SOLUTION_SERVER_EM               = 0x00000036, // Server For SB Solutions EM
+	SERVER_FOR_SB_SOLUTIONS             = 0x00000033, // Server For SB Solutions
+	SERVER_FOR_SB_SOLUTIONS_EM          = 0x00000037, // Server For SB Solutions EM
+	SERVER_FOR_SMALLBUSINESS            = 0x00000018, // Windows Server 2008 for Windows Essential Server Solutions
+	SERVER_FOR_SMALLBUSINESS_V          = 0x00000023, // Windows Server 2008 without Hyper-V for Windows Essential Server Solutions
+	SERVER_FOUNDATION                   = 0x00000021, // Server Foundation
+	SMALLBUSINESS_SERVER                = 0x00000009, // Windows Small Business Server
+	SMALLBUSINESS_SERVER_PREMIUM        = 0x00000019, // Small Business Server Premium
+	SMALLBUSINESS_SERVER_PREMIUM_CORE   = 0x0000003F, // Small Business Server Premium (core installation)
+	SOLUTION_EMBEDDEDSERVER             = 0x00000038, // Windows MultiPoint Server
+	STANDARD_EVALUATION_SERVER          = 0x0000004F, // Server Standard (evaluation installation)
+	STANDARD_SERVER                     = 0x00000007, // Server Standard (full installation. For Server Core installations of Windows Server 2012 and later, use the method, Determining whether Server Core is running.)
+	STANDARD_SERVER_CORE                = 0x0000000D, // Server Standard (core installation, Windows Server 2008 R2 and earlier)
+	STANDARD_SERVER_CORE_V              = 0x00000028, // Server Standard without Hyper-V (core installation)
+	STANDARD_SERVER_V                   = 0x00000024, // Server Standard without Hyper-V
+	STANDARD_SERVER_SOLUTIONS           = 0x00000034, // Server Solutions Premium
+	STANDARD_SERVER_SOLUTIONS_CORE      = 0x00000035, // Server Solutions Premium (core installation)
+	STARTER                             = 0x0000000B, // Starter
+	STARTER_E                           = 0x00000042, // Not supported
+	STARTER_N                           = 0x0000002F, // Starter N
+	STORAGE_ENTERPRISE_SERVER           = 0x00000017, // Storage Server Enterprise
+	STORAGE_ENTERPRISE_SERVER_CORE      = 0x0000002E, // Storage Server Enterprise (core installation)
+	STORAGE_EXPRESS_SERVER              = 0x00000014, // Storage Server Express
+	STORAGE_EXPRESS_SERVER_CORE         = 0x0000002B, // Storage Server Express (core installation)
+	STORAGE_STANDARD_EVALUATION_SERVER  = 0x00000060, // Storage Server Standard (evaluation installation)
+	STORAGE_STANDARD_SERVER             = 0x00000015, // Storage Server Standard
+	STORAGE_STANDARD_SERVER_CORE        = 0x0000002C, // Storage Server Standard (core installation)
+	STORAGE_WORKGROUP_EVALUATION_SERVER = 0x0000005F, // Storage Server Workgroup (evaluation installation)
+	STORAGE_WORKGROUP_SERVER            = 0x00000016, // Storage Server Workgroup
+	STORAGE_WORKGROUP_SERVER_CORE       = 0x0000002D, // Storage Server Workgroup (core installation)
+	ULTIMATE                            = 0x00000001, // Ultimate
+	ULTIMATE_E                          = 0x00000047, // Not supported
+	ULTIMATE_N                          = 0x0000001C, // Ultimate N
+	UNDEFINED                           = 0x00000000, // An unknown product
+	WEB_SERVER                          = 0x00000011, // Web Server (full installation)
+	WEB_SERVER_CORE                     = 0x0000001D, // Web Server (core installation)
+}