Merge branch '138-toggle-free-look-with-hotkey' into 'main/atys-live'
[ryzomcore.git] / nel / src / misc / system_info.cpp
blobddf66d56b89d6a2d02016d760f70ce6b524199cf
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2014-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "stdmisc.h"
22 #include "nel/misc/system_info.h"
24 #ifdef NL_OS_WINDOWS
25 # include <WinNT.h>
26 # include <tchar.h>
27 # include <intrin.h>
28 # define nlcpuid(regs, idx) __cpuid(regs, idx)
30 // define them here to not rely on Windows 10 SDKs
31 # define NL_PRODUCT_UNDEFINED 0x00000000
32 # define NL_PRODUCT_ULTIMATE 0x00000001
33 # define NL_PRODUCT_HOME_BASIC 0x00000002
34 # define NL_PRODUCT_HOME_PREMIUM 0x00000003
35 # define NL_PRODUCT_ENTERPRISE 0x00000004
36 # define NL_PRODUCT_HOME_BASIC_N 0x00000005
37 # define NL_PRODUCT_BUSINESS 0x00000006
38 # define NL_PRODUCT_STANDARD_SERVER 0x00000007
39 # define NL_PRODUCT_DATACENTER_SERVER 0x00000008
40 # define NL_PRODUCT_SMALLBUSINESS_SERVER 0x00000009
41 # define NL_PRODUCT_ENTERPRISE_SERVER 0x0000000A
42 # define NL_PRODUCT_STARTER 0x0000000B
43 # define NL_PRODUCT_DATACENTER_SERVER_CORE 0x0000000C
44 # define NL_PRODUCT_STANDARD_SERVER_CORE 0x0000000D
45 # define NL_PRODUCT_ENTERPRISE_SERVER_CORE 0x0000000E
46 # define NL_PRODUCT_ENTERPRISE_SERVER_IA64 0x0000000F
47 # define NL_PRODUCT_BUSINESS_N 0x00000010
48 # define NL_PRODUCT_WEB_SERVER 0x00000011
49 # define NL_PRODUCT_CLUSTER_SERVER 0x00000012
50 # define NL_PRODUCT_HOME_SERVER 0x00000013
51 # define NL_PRODUCT_STORAGE_EXPRESS_SERVER 0x00000014
52 # define NL_PRODUCT_STORAGE_STANDARD_SERVER 0x00000015
53 # define NL_PRODUCT_STORAGE_WORKGROUP_SERVER 0x00000016
54 # define NL_PRODUCT_STORAGE_ENTERPRISE_SERVER 0x00000017
55 # define NL_PRODUCT_SERVER_FOR_SMALLBUSINESS 0x00000018
56 # define NL_PRODUCT_SMALLBUSINESS_SERVER_PREMIUM 0x00000019
57 # define NL_PRODUCT_HOME_PREMIUM_N 0x0000001A
58 # define NL_PRODUCT_ENTERPRISE_N 0x0000001B
59 # define NL_PRODUCT_ULTIMATE_N 0x0000001C
60 # define NL_PRODUCT_WEB_SERVER_CORE 0x0000001D
61 # define NL_PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT 0x0000001E
62 # define NL_PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY 0x0000001F
63 # define NL_PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING 0x00000020
64 # define NL_PRODUCT_SERVER_FOUNDATION 0x00000021
65 # define NL_PRODUCT_HOME_PREMIUM_SERVER 0x00000022
66 # define NL_PRODUCT_SERVER_FOR_SMALLBUSINESS_V 0x00000023
67 # define NL_PRODUCT_STANDARD_SERVER_V 0x00000024
68 # define NL_PRODUCT_DATACENTER_SERVER_V 0x00000025
69 # define NL_PRODUCT_ENTERPRISE_SERVER_V 0x00000026
70 # define NL_PRODUCT_DATACENTER_SERVER_CORE_V 0x00000027
71 # define NL_PRODUCT_STANDARD_SERVER_CORE_V 0x00000028
72 # define NL_PRODUCT_ENTERPRISE_SERVER_CORE_V 0x00000029
73 # define NL_PRODUCT_HYPERV 0x0000002A
74 # define NL_PRODUCT_STORAGE_EXPRESS_SERVER_CORE 0x0000002B
75 # define NL_PRODUCT_STORAGE_STANDARD_SERVER_CORE 0x0000002C
76 # define NL_PRODUCT_STORAGE_WORKGROUP_SERVER_CORE 0x0000002D
77 # define NL_PRODUCT_STORAGE_ENTERPRISE_SERVER_CORE 0x0000002E
78 # define NL_PRODUCT_STARTER_N 0x0000002F
79 # define NL_PRODUCT_PROFESSIONAL 0x00000030
80 # define NL_PRODUCT_PROFESSIONAL_N 0x00000031
81 # define NL_PRODUCT_SB_SOLUTION_SERVER 0x00000032
82 # define NL_PRODUCT_SERVER_FOR_SB_SOLUTIONS 0x00000033
83 # define NL_PRODUCT_STANDARD_SERVER_SOLUTIONS 0x00000034
84 # define NL_PRODUCT_STANDARD_SERVER_SOLUTIONS_CORE 0x00000035
85 # define NL_PRODUCT_SB_SOLUTION_SERVER_EM 0x00000036
86 # define NL_PRODUCT_SERVER_FOR_SB_SOLUTIONS_EM 0x00000037
87 # define NL_PRODUCT_SOLUTION_EMBEDDEDSERVER 0x00000038
88 # define NL_PRODUCT_SOLUTION_EMBEDDEDSERVER_CORE 0x00000039
89 # define NL_PRODUCT_PROFESSIONAL_EMBEDDED 0x0000003A
90 # define NL_PRODUCT_ESSENTIALBUSINESS_SERVER_MGMT 0x0000003B
91 # define NL_PRODUCT_ESSENTIALBUSINESS_SERVER_ADDL 0x0000003C
92 # define NL_PRODUCT_ESSENTIALBUSINESS_SERVER_MGMTSVC 0x0000003D
93 # define NL_PRODUCT_ESSENTIALBUSINESS_SERVER_ADDLSVC 0x0000003E
94 # define NL_PRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE 0x0000003F
95 # define NL_PRODUCT_CLUSTER_SERVER_V 0x00000040
96 # define NL_PRODUCT_EMBEDDED 0x00000041
97 # define NL_PRODUCT_STARTER_E 0x00000042
98 # define NL_PRODUCT_HOME_BASIC_E 0x00000043
99 # define NL_PRODUCT_HOME_PREMIUM_E 0x00000044
100 # define NL_PRODUCT_PROFESSIONAL_E 0x00000045
101 # define NL_PRODUCT_ENTERPRISE_E 0x00000046
102 # define NL_PRODUCT_ULTIMATE_E 0x00000047
103 # define NL_PRODUCT_ENTERPRISE_EVALUATION 0x00000048
104 # define NL_PRODUCT_MULTIPOINT_STANDARD_SERVER 0x0000004C
105 # define NL_PRODUCT_MULTIPOINT_PREMIUM_SERVER 0x0000004D
106 # define NL_PRODUCT_STANDARD_EVALUATION_SERVER 0x0000004F
107 # define NL_PRODUCT_DATACENTER_EVALUATION_SERVER 0x00000050
108 # define NL_PRODUCT_ENTERPRISE_N_EVALUATION 0x00000054
109 # define NL_PRODUCT_EMBEDDED_AUTOMOTIVE 0x00000055
110 # define NL_PRODUCT_EMBEDDED_INDUSTRY_A 0x00000056
111 # define NL_PRODUCT_THINPC 0x00000057
112 # define NL_PRODUCT_EMBEDDED_A 0x00000058
113 # define NL_PRODUCT_EMBEDDED_INDUSTRY 0x00000059
114 # define NL_PRODUCT_EMBEDDED_E 0x0000005A
115 # define NL_PRODUCT_EMBEDDED_INDUSTRY_E 0x0000005B
116 # define NL_PRODUCT_EMBEDDED_INDUSTRY_A_E 0x0000005C
117 # define NL_PRODUCT_STORAGE_WORKGROUP_EVALUATION_SERVER 0x0000005F
118 # define NL_PRODUCT_STORAGE_STANDARD_EVALUATION_SERVER 0x00000060
119 # define NL_PRODUCT_CORE_ARM 0x00000061
120 # define NL_PRODUCT_CORE_N 0x00000062
121 # define NL_PRODUCT_CORE_COUNTRYSPECIFIC 0x00000063
122 # define NL_PRODUCT_CORE_SINGLELANGUAGE 0x00000064
123 # define NL_PRODUCT_CORE 0x00000065
124 # define NL_PRODUCT_PROFESSIONAL_WMC 0x00000067
125 # define NL_PRODUCT_MOBILE_CORE 0x00000068
126 # define NL_PRODUCT_EMBEDDED_INDUSTRY_EVAL 0x00000069
127 # define NL_PRODUCT_EMBEDDED_INDUSTRY_E_EVAL 0x0000006A
128 # define NL_PRODUCT_EMBEDDED_EVAL 0x0000006B
129 # define NL_PRODUCT_EMBEDDED_E_EVAL 0x0000006C
130 # define NL_PRODUCT_CORE_SERVER 0x0000006D
131 # define NL_PRODUCT_CLOUD_STORAGE_SERVER 0x0000006E
132 # define NL_PRODUCT_CORE_CONNECTED 0x0000006F
133 # define NL_PRODUCT_PROFESSIONAL_STUDENT 0x00000070
134 # define NL_PRODUCT_CORE_CONNECTED_N 0x00000071
135 # define NL_PRODUCT_PROFESSIONAL_STUDENT_N 0x00000072
136 # define NL_PRODUCT_CORE_CONNECTED_SINGLELANGUAGE 0x00000073
137 # define NL_PRODUCT_CORE_CONNECTED_COUNTRYSPECIFIC 0x00000074
138 # define NL_PRODUCT_CONNECTED_CAR 0x00000075
139 # define NL_PRODUCT_INDUSTRY_HANDHELD 0x00000076
140 # define NL_PRODUCT_PPI_PRO 0x00000077
141 # define NL_PRODUCT_ARM64_SERVER 0x00000078
142 # define NL_PRODUCT_EDUCATION 0x00000079
143 # define NL_PRODUCT_EDUCATION_N 0x0000007A
144 # define NL_PRODUCT_IOTUAP 0x0000007B
145 # define NL_PRODUCT_CLOUD_HOST_INFRASTRUCTURE_SERVER 0x0000007C
146 # define NL_PRODUCT_ENTERPRISE_S 0x0000007D
147 # define NL_PRODUCT_ENTERPRISE_S_N 0x0000007E
148 # define NL_PRODUCT_PROFESSIONAL_S 0x0000007F
149 # define NL_PRODUCT_PROFESSIONAL_S_N 0x00000080
150 # define NL_PRODUCT_ENTERPRISE_S_EVALUATION 0x00000081
151 # define NL_PRODUCT_ENTERPRISE_S_N_EVALUATION 0x00000082
152 # define NL_PRODUCT_HOLOGRAPHIC 0x00000087
153 # define NL_PRODUCT_PRO_SINGLE_LANGUAGE 0x0000008A
154 # define NL_PRODUCT_PRO_CHINA 0x0000008B
155 # define NL_PRODUCT_ENTERPRISE_SUBSCRIPTION 0x0000008C
156 # define NL_PRODUCT_ENTERPRISE_SUBSCRIPTION_N 0x0000008D
157 # define NL_PRODUCT_DATACENTER_NANO_SERVER 0x0000008F
158 # define NL_PRODUCT_STANDARD_NANO_SERVER 0x00000090
159 # define NL_PRODUCT_DATACENTER_A_SERVER_CORE 0x00000091
160 # define NL_PRODUCT_STANDARD_A_SERVER_CORE 0x00000092
161 # define NL_PRODUCT_DATACENTER_WS_SERVER_CORE 0x00000093
162 # define NL_PRODUCT_STANDARD_WS_SERVER_CORE 0x00000094
163 # define NL_PRODUCT_UTILITY_VM 0x00000095
164 # define NL_PRODUCT_DATACENTER_EVALUATION_SERVER_CORE 0x0000009F
165 # define NL_PRODUCT_STANDARD_EVALUATION_SERVER_CORE 0x000000A0
166 # define NL_PRODUCT_PRO_WORKSTATION 0x000000A1
167 # define NL_PRODUCT_PRO_WORKSTATION_N 0x000000A2
168 # define NL_PRODUCT_PRO_FOR_EDUCATION 0x000000A4
169 # define NL_PRODUCT_PRO_FOR_EDUCATION_N 0x000000A5
170 # define NL_PRODUCT_AZURE_SERVER_CORE 0x000000A8
171 # define NL_PRODUCT_AZURE_NANO_SERVER 0x000000A9
172 # define NL_PRODUCT_ENTERPRISEG 0x000000AB
173 # define NL_PRODUCT_ENTERPRISEGN 0x000000AC
174 # define NL_PRODUCT_SERVERRDSH 0x000000AF
175 # define NL_PRODUCT_CLOUD 0x000000B2
176 # define NL_PRODUCT_CLOUDN 0x000000B3
177 # define NL_PRODUCT_UNLICENSED 0xABCDABCD
179 #else
180 # include <sys/types.h>
181 # include <sys/stat.h>
182 # include <fcntl.h>
183 # include <unistd.h>
184 # include <cerrno>
185 # ifdef NL_CPU_INTEL
186 # include <cpuid.h>
187 # define nlcpuid(regs, idx) __cpuid(idx, regs[0], regs[1], regs[2], regs[3])
188 # endif // NL_CPU_INTEL
189 # ifdef NL_OS_MAC
190 # include <sys/mount.h>
191 # include <sys/sysctl.h>
192 # else
193 # include <sys/vfs.h>
194 # endif
195 #endif // NL_OS_WINDOWS
197 #include "nel/misc/system_info.h"
198 #include "nel/misc/command.h"
199 #include "nel/misc/variable.h"
201 using namespace std;
203 #ifdef DEBUG_NEW
204 #define new DEBUG_NEW
205 #endif
207 namespace NLMISC {
209 #ifdef NL_OS_UNIX
210 static string getCpuInfo(const string &colname)
212 if (colname.empty())
213 return "";
215 int fd = open("/proc/cpuinfo", O_RDONLY);
216 if (fd == -1)
218 nlwarning ("SI: Can't open /proc/cpuinfo: %s", strerror (errno));
219 return "";
221 else
223 char buffer[4096+1];
224 uint32 len = read(fd, buffer, sizeof(buffer)-1);
225 close(fd);
226 buffer[len] = '\0';
228 vector<string> splitted;
229 explode(string(buffer), string("\n"), splitted, true);
231 std::string value;
233 for(uint32 i = 0; i < splitted.size(); i++)
235 vector<string> sline;
236 explode(splitted[i], string(":"), sline, true);
237 if(sline.size() == 2 && trim(sline[0]) == colname)
239 value = sline[1];
243 if (!value.empty())
244 return trim(value);
246 nlwarning ("SI: Can't find the colname '%s' in /proc/cpuinfo", colname.c_str());
247 return "";
250 // return the value of the colname in bytes from /proc/meminfo
251 static uint64 getSystemMemory (const string &colname)
253 if (colname.empty())
254 return 0;
256 int fd = open("/proc/meminfo", O_RDONLY);
257 if (fd == -1)
259 nlwarning ("SI: Can't open /proc/meminfo: %s", strerror (errno));
260 return 0;
262 else
264 char buffer[4096+1];
265 uint32 len = read(fd, buffer, sizeof(buffer)-1);
266 close(fd);
267 buffer[len] = '\0';
269 vector<string> splitted;
270 explode(string(buffer), string("\n"), splitted, true);
272 for(uint32 i = 0; i < splitted.size(); i++)
274 vector<string> sline;
275 explode(splitted[i], string(" "), sline, true);
276 if(sline.size() == 3 && sline[0] == colname)
278 uint64 val = atoiInt64(sline[1].c_str());
279 if(sline[2] == "kB") val *= 1024;
280 return val;
284 nlwarning ("SI: Can't find the colname '%s' in /proc/meminfo", colname.c_str());
285 return 0;
287 #endif // NL_OS_UNIX
289 #ifdef NL_OS_MAC
290 static sint32 getsysctlnum(const string &name)
292 sint32 value = 0;
293 size_t len = sizeof(value);
294 if(sysctlbyname(name.c_str(), &value, &len, NULL, 0) != 0)
296 nlwarning("SI: Can't get '%s' from sysctl: %s", name.c_str(), strerror (errno));
298 return value;
301 static sint64 getsysctlnum64(const string &name)
303 sint64 value = 0;
304 size_t len = sizeof(value);
305 if(sysctlbyname(name.c_str(), &value, &len, NULL, 0) != 0)
307 nlwarning("SI: Can't get '%s' from sysctl: %s", name.c_str(), strerror (errno));
309 return value;
312 static string getsysctlstr(const string &name)
314 string value("Unknown");
315 size_t len;
316 char *p;
317 if(sysctlbyname(name.c_str(), NULL, &len, NULL, 0) == 0)
319 p = (char*)malloc(len);
320 if(sysctlbyname(name.c_str(), p, &len, NULL, 0) == 0)
322 value = p;
324 else
326 nlwarning("SI: Can't get '%s' from sysctl: %s", name.c_str(), strerror (errno));
328 free(p);
330 else
332 nlwarning("SI: Can't get '%s' from sysctl: %s", name.c_str(), strerror (errno));
334 return value;
336 #endif // NL_OS_MAC
338 string CSystemInfo::getOS()
340 string OSString = "Unknown";
342 #ifdef NL_OS_WINDOWS
344 typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
345 typedef BOOL (WINAPI *PGetProductInfo)(DWORD, DWORD, DWORD, DWORD, PDWORD);
346 typedef LONG (WINAPI* PRtlGetVersion)(OSVERSIONINFOEXA*);
348 const int BUFSIZE = 80;
350 // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
351 // If that fails, try using the OSVERSIONINFO structure.
353 SYSTEM_INFO si;
354 ZeroMemory(&si, sizeof(SYSTEM_INFO));
356 // RtlGetVersion always returns the right version
357 HMODULE hNtDll = GetModuleHandleA("ntdll.dll");
358 PRtlGetVersion pRtlGetVersion = (PRtlGetVersion)GetProcAddress(hNtDll, "RtlGetVersion");
360 BOOL bOsVersionInfoEx = 0;
362 // init OSVERSIONINFOEXA
363 OSVERSIONINFOEXA osvi;
364 ZeroMemory(&osvi, sizeof(osvi));
365 osvi.dwOSVersionInfoSize = sizeof(osvi);
367 if (pRtlGetVersion)
369 // try RtlGetVersion
370 bOsVersionInfoEx = pRtlGetVersion(&osvi) == 0;
373 if (!bOsVersionInfoEx)
375 // fall back to GetVersionExA
376 bOsVersionInfoEx = GetVersionExA ((OSVERSIONINFOA *) &osvi);
379 if (!bOsVersionInfoEx)
381 // fall back to GetVersionA struct
382 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
383 if (! GetVersionExA ( (OSVERSIONINFOA *) &osvi) )
384 return OSString+" Can't GetVersionEx()";
387 // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.
389 PGNSI pGNSI = (PGNSI) GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetNativeSystemInfo");
391 if (pGNSI)
392 pGNSI(&si);
393 else
394 GetSystemInfo(&si);
396 // Test for the Windows NT product family
397 if (VER_PLATFORM_WIN32_NT == osvi.dwPlatformId && osvi.dwMajorVersion > 4)
399 OSString = "Microsoft";
401 if (osvi.dwMajorVersion > 10)
403 OSString += " Windows (not released)";
405 else if (osvi.dwMajorVersion == 10)
407 OSString += " Windows 10";
409 else if (osvi.dwMajorVersion == 6)
411 if (osvi.dwMinorVersion == 3)
413 if (osvi.wProductType == VER_NT_WORKSTATION)
414 OSString += " Windows 8.1";
415 else
416 OSString += " Windows Server 2012 R2";
418 else if (osvi.dwMinorVersion == 2)
420 if (osvi.wProductType == VER_NT_WORKSTATION)
421 OSString += " Windows 8";
422 else
423 OSString += " Windows Server 2012";
425 else if (osvi.dwMinorVersion == 1)
427 if (osvi.wProductType == VER_NT_WORKSTATION)
428 OSString += " Windows 7";
429 else
430 OSString += " Windows Server 2008 R2";
432 else if (osvi.dwMinorVersion == 0)
434 if (osvi.wProductType == VER_NT_WORKSTATION)
435 OSString += " Windows Vista";
436 else
437 OSString += " Windows Server 2008";
439 else
441 OSString += " Windows (unknown)";
444 else if (osvi.dwMajorVersion == 5)
446 if (osvi.dwMinorVersion == 2)
448 if (GetSystemMetrics(89 /* SM_SERVERR2 */))
449 OSString += " Windows Server 2003 R2";
450 #ifdef VER_SUITE_STORAGE_SERVER
451 else if (osvi.wSuiteMask == VER_SUITE_STORAGE_SERVER)
452 OSString += " Windows Storage Server 2003";
453 #endif
454 #ifdef VER_SUITE_WH_SERVER
455 else if (osvi.wSuiteMask == VER_SUITE_WH_SERVER)
456 OSString += " Windows Home Server";
457 #endif
458 else if (osvi.wProductType == VER_NT_WORKSTATION &&
459 si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
460 OSString += " Windows XP Professional x64 Edition";
461 else
462 OSString += " Windows Server 2003";
464 // Test for the server type.
465 if (osvi.wProductType != VER_NT_WORKSTATION)
467 if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
469 if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
470 OSString += " Datacenter Edition for Itanium-based Systems";
471 else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
472 OSString += " Enterprise Edition for Itanium-based Systems";
475 else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
477 if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
478 OSString += " Datacenter x64 Edition";
479 else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
480 OSString += " Enterprise x64 Edition";
481 else
482 OSString += " Standard x64 Edition";
485 else
487 if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
488 OSString += " Enterprise Edition";
489 #ifdef VER_SUITE_DATACENTER
490 else if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
491 OSString += " Datacenter Edition";
492 #endif
493 #ifdef VER_SUITE_BLADE
494 else if (osvi.wSuiteMask & VER_SUITE_BLADE)
495 OSString += " Web Edition";
496 #endif
497 #ifdef VER_SUITE_COMPUTE_SERVER
498 else if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER)
499 OSString += " Compute Cluster Edition";
500 #endif
501 else
502 OSString += " Standard Edition";
506 else if (osvi.dwMinorVersion == 1)
508 OSString += " Windows XP";
509 if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
510 OSString += " Home Edition";
511 else
512 OSString += " Professional";
514 else if (osvi.dwMinorVersion == 0)
516 OSString += " Windows 2000";
518 if (osvi.wProductType == VER_NT_WORKSTATION)
520 OSString += " Professional";
522 else
524 if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
525 OSString += " Datacenter Server";
526 else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
527 OSString += " Advanced Server";
528 else
529 OSString += " Server";
532 else
534 OSString += " Unknown Windows";
537 else if (osvi.dwMajorVersion <= 4)
539 OSString += " Windows NT";
541 // Test for specific product on Windows NT 4.0 SP6 and later.
542 if (bOsVersionInfoEx)
544 // Test for the workstation type.
545 if (osvi.wProductType == VER_NT_WORKSTATION)
547 if (osvi.dwMajorVersion == 4 )
548 OSString += " Workstation 4.0";
549 else if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
550 OSString += " Home Edition";
551 else
552 OSString += " Professional";
555 // Test for the server type.
556 else if (osvi.wProductType == VER_NT_SERVER)
558 if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
559 OSString += " Server 4.0 Enterprise Edition";
560 else
561 OSString += " Server 4.0";
564 else // Test for specific product on Windows NT 4.0 SP5 and earlier
566 HKEY hKey;
567 char szProductType[BUFSIZE];
568 DWORD dwBufLen=BUFSIZE;
569 LONG lRet;
571 lRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 0, KEY_QUERY_VALUE, &hKey );
572 if (lRet != ERROR_SUCCESS)
573 return OSString + " Can't RegOpenKeyEx";
575 lRet = RegQueryValueExA(hKey, "ProductType", NULL, NULL, (LPBYTE) szProductType, &dwBufLen);
576 if ((lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE))
577 return OSString + " Can't ReQueryValueEx";
579 RegCloseKey(hKey);
581 if (lstrcmpiA("WINNT", szProductType) == 0)
582 OSString += " Workstation";
584 if (lstrcmpiA("LANMANNT", szProductType) == 0)
585 OSString += " Server";
587 if (lstrcmpiA("SERVERNT", szProductType) == 0)
588 OSString += " Advanced Server";
592 PGetProductInfo pGetProductInfo = (PGetProductInfo)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetProductInfo");
594 DWORD dwType;
596 if (pGetProductInfo && pGetProductInfo(osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.wServicePackMajor, osvi.wServicePackMinor, &dwType))
598 // Test for the specific product family.
599 // see https://msdn.microsoft.com/fr-fr/library/windows/desktop/ms724358(v=vs.85).aspx
600 switch (dwType)
602 case NL_PRODUCT_UNLICENSED:
603 OSString += " Unlicensed";
604 break;
605 case NL_PRODUCT_ULTIMATE:
606 OSString += " Ultimate";
607 break;
608 case NL_PRODUCT_HOME_BASIC:
609 OSString += " Home Basic";
610 break;
611 case NL_PRODUCT_HOME_PREMIUM:
612 OSString += " Home Premium";
613 break;
614 case NL_PRODUCT_ENTERPRISE:
615 OSString += " Enterprise";
616 break;
617 case NL_PRODUCT_HOME_BASIC_N:
618 OSString += " Home Basic N";
619 break;
620 case NL_PRODUCT_BUSINESS:
621 OSString += " Business";
622 break;
623 case NL_PRODUCT_STANDARD_SERVER:
624 OSString += " Server Standard";
625 break;
626 case NL_PRODUCT_DATACENTER_SERVER:
627 OSString += " Server Datacenter (full installation)";
628 break;
629 case NL_PRODUCT_SMALLBUSINESS_SERVER:
630 OSString += " Small Business Server";
631 break;
632 case NL_PRODUCT_ENTERPRISE_SERVER:
633 OSString += " Server Enterprise (full installation)";
634 break;
635 case NL_PRODUCT_STARTER:
636 OSString += " Starter";
637 break;
638 case NL_PRODUCT_DATACENTER_SERVER_CORE:
639 OSString += " Server Datacenter (core installation)";
640 break;
641 case NL_PRODUCT_STANDARD_SERVER_CORE:
642 OSString += " Server Standard (core installation)";
643 break;
644 case NL_PRODUCT_ENTERPRISE_SERVER_CORE:
645 OSString += " Server Enterprise (core installation)";
646 break;
647 case NL_PRODUCT_ENTERPRISE_SERVER_IA64:
648 OSString += " Server Enterprise for Itanium-based Systems";
649 break;
650 case NL_PRODUCT_BUSINESS_N:
651 OSString += " Business N";
652 break;
653 case NL_PRODUCT_WEB_SERVER:
654 OSString += " Web Server (full installation)";
655 break;
656 case NL_PRODUCT_CLUSTER_SERVER:
657 OSString += " Server Hyper Core";
658 break;
659 case NL_PRODUCT_HOME_SERVER:
660 OSString += " Home Server";
661 break;
662 case NL_PRODUCT_STORAGE_EXPRESS_SERVER:
663 OSString += " Storage Server Express";
664 break;
665 case NL_PRODUCT_STORAGE_STANDARD_SERVER:
666 OSString += " Storage Server Standard";
667 break;
668 case NL_PRODUCT_STORAGE_WORKGROUP_SERVER:
669 OSString += " Storage Server Workgroup";
670 break;
671 case NL_PRODUCT_STORAGE_ENTERPRISE_SERVER:
672 OSString += " Storage Server Enterprise";
673 break;
674 case NL_PRODUCT_SERVER_FOR_SMALLBUSINESS:
675 OSString += " Essential Server Solutions";
676 break;
677 case NL_PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
678 OSString += " Small Business Server Premium";
679 break;
680 case NL_PRODUCT_HOME_PREMIUM_N:
681 OSString += " Home Premium N";
682 break;
683 case NL_PRODUCT_ENTERPRISE_N:
684 OSString += " Enterprise N";
685 break;
686 case NL_PRODUCT_ULTIMATE_N:
687 OSString += " Ultimate N";
688 break;
689 case NL_PRODUCT_WEB_SERVER_CORE:
690 OSString += " Web Server (core installation)";
691 break;
692 case NL_PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT:
693 OSString += " Essential Business Server Management Server";
694 break;
695 case NL_PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY:
696 OSString += " Essential Business Server Security Server";
697 break;
698 case NL_PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING:
699 OSString += " Essential Business Server Messaging Server";
700 break;
701 case NL_PRODUCT_SERVER_FOUNDATION:
702 OSString += " Server Foundation";
703 break;
704 case NL_PRODUCT_HOME_PREMIUM_SERVER:
705 OSString += " Home Server";
706 break;
707 case NL_PRODUCT_SERVER_FOR_SMALLBUSINESS_V:
708 OSString += " Server without Hyper-V for Windows Essential Server Solutions";
709 break;
710 case NL_PRODUCT_STANDARD_SERVER_V:
711 OSString += " Server Standard without Hyper-V";
712 break;
713 case NL_PRODUCT_DATACENTER_SERVER_V:
714 OSString += " Server Datacenter without Hyper-V (full installation)";
715 break;
716 case NL_PRODUCT_ENTERPRISE_SERVER_V:
717 OSString += " Enterprise without Hyper-V (full installation)";
718 break;
719 case NL_PRODUCT_DATACENTER_SERVER_CORE_V:
720 OSString += " Datacenter without Hyper-V (core installation)";
721 break;
722 case NL_PRODUCT_STANDARD_SERVER_CORE_V:
723 OSString += " Standard without Hyper-V (core installation)";
724 break;
725 case NL_PRODUCT_ENTERPRISE_SERVER_CORE_V:
726 OSString += " Enterprise without Hyper-V (core installation)";
727 break;
728 case NL_PRODUCT_HYPERV:
729 OSString += " Hyper-V Server";
730 break;
731 case NL_PRODUCT_STORAGE_EXPRESS_SERVER_CORE:
732 OSString += " Storage Server Express (core installation)";
733 break;
734 case NL_PRODUCT_STORAGE_STANDARD_SERVER_CORE:
735 OSString += " Storage Server Standard (core installation)";
736 break;
737 case NL_PRODUCT_STORAGE_WORKGROUP_SERVER_CORE:
738 OSString += " Storage Server Workgroup (core installation)";
739 break;
740 case NL_PRODUCT_STORAGE_ENTERPRISE_SERVER_CORE:
741 OSString += " Storage Server Enterprise (core installation)";
742 break;
743 case NL_PRODUCT_STARTER_N:
744 OSString += " Starter N Edition";
745 break;
746 case NL_PRODUCT_PROFESSIONAL:
747 OSString += " Professional";
748 break;
749 case NL_PRODUCT_PROFESSIONAL_N:
750 OSString += " Professional N";
751 break;
752 case NL_PRODUCT_SB_SOLUTION_SERVER:
753 OSString += " Small Business Server";
754 break;
755 case NL_PRODUCT_SERVER_FOR_SB_SOLUTIONS:
756 OSString += " Server For Small Business Solutions";
757 break;
758 case NL_PRODUCT_STANDARD_SERVER_SOLUTIONS:
759 OSString += " Server Solutions Premium";
760 break;
761 case NL_PRODUCT_STANDARD_SERVER_SOLUTIONS_CORE:
762 OSString += " Server Solutions Premium (core installation)";
763 break;
764 case NL_PRODUCT_SB_SOLUTION_SERVER_EM:
765 OSString += " Server For Small Business Solutions EM";
766 break;
767 case NL_PRODUCT_SERVER_FOR_SB_SOLUTIONS_EM:
768 OSString += " Server For Small Business Solutions EM";
769 break;
770 case NL_PRODUCT_SOLUTION_EMBEDDEDSERVER:
771 OSString += " Solution Embedded Server (full installation)";
772 break;
773 case NL_PRODUCT_SOLUTION_EMBEDDEDSERVER_CORE:
774 OSString += " Solution Embedded Server (core installation)";
775 break;
776 case NL_PRODUCT_PROFESSIONAL_EMBEDDED:
777 OSString += " Professional Embedded";
778 break;
779 case NL_PRODUCT_ESSENTIALBUSINESS_SERVER_MGMT:
780 OSString += " Essential Server Solution Management";
781 break;
782 case NL_PRODUCT_ESSENTIALBUSINESS_SERVER_ADDL:
783 OSString += " Essential Server Solution Additional";
784 break;
785 case NL_PRODUCT_ESSENTIALBUSINESS_SERVER_MGMTSVC:
786 OSString += " Essential Server Solution Management SVC";
787 break;
788 case NL_PRODUCT_ESSENTIALBUSINESS_SERVER_ADDLSVC:
789 OSString += " Essential Server Solution Additional SVC";
790 break;
791 case NL_PRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE:
792 OSString += " Small Business Server Premium (core installation)";
793 break;
794 case NL_PRODUCT_CLUSTER_SERVER_V:
795 OSString += " Server Hyper Core V";
796 break;
797 case NL_PRODUCT_EMBEDDED:
798 OSString += " Embedded";
799 break;
800 case NL_PRODUCT_STARTER_E:
801 OSString += " Starter E";
802 break;
803 case NL_PRODUCT_HOME_BASIC_E:
804 OSString += " Home Basic E";
805 break;
806 case NL_PRODUCT_HOME_PREMIUM_E:
807 OSString += " Home Premium E";
808 break;
809 case NL_PRODUCT_PROFESSIONAL_E:
810 OSString += " Professional E";
811 break;
812 case NL_PRODUCT_ENTERPRISE_E:
813 OSString += " Enterprise E";
814 break;
815 case NL_PRODUCT_ULTIMATE_E:
816 OSString += " Ultimate E";
817 break;
818 case NL_PRODUCT_ENTERPRISE_EVALUATION:
819 OSString += " Enterprise Evaluation";
820 break;
821 // nothing from 0x49 to 0x4b
822 case NL_PRODUCT_MULTIPOINT_STANDARD_SERVER:
823 OSString += " MultiPoint Server Standard (full installation)";
824 break;
825 case NL_PRODUCT_MULTIPOINT_PREMIUM_SERVER:
826 OSString += " MultiPoint Server Premium (full installation)";
827 break;
828 case NL_PRODUCT_STANDARD_EVALUATION_SERVER:
829 OSString += " Server Standard (evaluation installation)";
830 break;
831 case NL_PRODUCT_DATACENTER_EVALUATION_SERVER:
832 OSString += " Server Datacenter (evaluation installation)";
833 break;
834 // nothing from 0x51 to 0x53
835 case NL_PRODUCT_ENTERPRISE_N_EVALUATION:
836 OSString += " Enterprise N (evaluation installation)";
837 break;
838 case NL_PRODUCT_EMBEDDED_AUTOMOTIVE:
839 OSString += " Embedded Automotive";
840 break;
841 case NL_PRODUCT_EMBEDDED_INDUSTRY_A:
842 OSString += " Embedded Industry A";
843 break;
844 case NL_PRODUCT_THINPC:
845 OSString += " Thin PC";
846 break;
847 case NL_PRODUCT_EMBEDDED_A:
848 OSString += " Embedded A";
849 break;
850 case NL_PRODUCT_EMBEDDED_INDUSTRY:
851 OSString += " Embedded Industry";
852 break;
853 case NL_PRODUCT_EMBEDDED_E:
854 OSString += " Embedded E";
855 break;
856 case NL_PRODUCT_EMBEDDED_INDUSTRY_E:
857 OSString += " Embedded Industry E";
858 break;
859 case NL_PRODUCT_EMBEDDED_INDUSTRY_A_E:
860 OSString += " Embedded Industry A E";
861 break;
862 // nothing from 0x5d to 0x5e
863 case NL_PRODUCT_STORAGE_WORKGROUP_EVALUATION_SERVER:
864 OSString += " Storage Server Workgroup (evaluation installation)";
865 break;
866 case NL_PRODUCT_STORAGE_STANDARD_EVALUATION_SERVER:
867 OSString += " Storage Server Standard (evaluation installation)";
868 break;
869 case NL_PRODUCT_CORE_ARM:
870 OSString += " RT";
871 break;
872 case NL_PRODUCT_CORE_N:
873 OSString += " Home N";
874 break;
875 case NL_PRODUCT_CORE_COUNTRYSPECIFIC:
876 OSString += " Home China";
877 break;
878 case NL_PRODUCT_CORE_SINGLELANGUAGE:
879 OSString += " Home Single Language";
880 break;
881 case NL_PRODUCT_CORE:
882 OSString += " Home";
883 break;
884 // nothing at 0x66
885 case NL_PRODUCT_PROFESSIONAL_WMC:
886 OSString += " Professional with Media Center";
887 break;
888 case NL_PRODUCT_MOBILE_CORE:
889 OSString += " Mobile";
890 break;
891 case NL_PRODUCT_EMBEDDED_INDUSTRY_EVAL:
892 OSString += " Embedded Industry (evaluation installation)";
893 break;
894 case NL_PRODUCT_EMBEDDED_INDUSTRY_E_EVAL:
895 OSString += " Embedded Industry E (evaluation installation)";
896 break;
897 case NL_PRODUCT_EMBEDDED_EVAL:
898 OSString += " Embedded (evaluation installation)";
899 break;
900 case NL_PRODUCT_EMBEDDED_E_EVAL:
901 OSString += " Embedded E (evaluation installation)";
902 break;
903 case NL_PRODUCT_CORE_SERVER:
904 OSString += " Server";
905 break;
906 case NL_PRODUCT_CLOUD_STORAGE_SERVER:
907 OSString += " Server Could Storage";
908 break;
909 case NL_PRODUCT_CORE_CONNECTED:
910 OSString += " Home Connected";
911 break;
912 case NL_PRODUCT_PROFESSIONAL_STUDENT:
913 OSString += " Professional Student";
914 break;
915 case NL_PRODUCT_CORE_CONNECTED_N:
916 OSString += " Home N Connected";
917 break;
918 case NL_PRODUCT_PROFESSIONAL_STUDENT_N:
919 OSString += " Professional Student N";
920 break;
921 case NL_PRODUCT_CORE_CONNECTED_SINGLELANGUAGE:
922 OSString += " Home Single Language Connected";
923 break;
924 case NL_PRODUCT_CORE_CONNECTED_COUNTRYSPECIFIC:
925 OSString += " Home China Connected";
926 break;
927 case NL_PRODUCT_CONNECTED_CAR:
928 OSString += " Connected Car";
929 break;
930 case NL_PRODUCT_INDUSTRY_HANDHELD:
931 OSString += " Industry Handheld";
932 break;
933 case NL_PRODUCT_PPI_PRO:
934 OSString += " PPI Pro";
935 break;
936 case NL_PRODUCT_ARM64_SERVER:
937 OSString += " ARM64 Server";
938 break;
939 case NL_PRODUCT_EDUCATION:
940 OSString += " Education";
941 break;
942 case NL_PRODUCT_EDUCATION_N:
943 OSString += " Education N";
944 break;
945 case NL_PRODUCT_IOTUAP:
946 OSString += " IoT Core";
947 break;
948 case NL_PRODUCT_CLOUD_HOST_INFRASTRUCTURE_SERVER:
949 OSString += " Cloud Host Infrastructure Server";
950 break;
951 case NL_PRODUCT_ENTERPRISE_S:
952 OSString += " Product Enterprise S";
953 break;
954 case NL_PRODUCT_ENTERPRISE_S_N:
955 OSString += " Enterprise S N";
956 break;
957 case NL_PRODUCT_PROFESSIONAL_S:
958 OSString += " Professional S";
959 break;
960 case NL_PRODUCT_PROFESSIONAL_S_N:
961 OSString += " Professional S N";
962 break;
963 case NL_PRODUCT_ENTERPRISE_S_EVALUATION:
964 OSString += " Enterprise S Evaluation";
965 break;
966 case NL_PRODUCT_ENTERPRISE_S_N_EVALUATION:
967 OSString += " Enterprise S N Evaluation";
968 break;
969 // nothing from x83 to 0x86
970 case NL_PRODUCT_HOLOGRAPHIC:
971 OSString += " Holographic";
972 break;
973 // nothing from x88 to 0x89
974 case NL_PRODUCT_PRO_SINGLE_LANGUAGE:
975 OSString += " Pro Single Language";
976 break;
977 case NL_PRODUCT_PRO_CHINA:
978 OSString += " Pro China";
979 break;
980 case NL_PRODUCT_ENTERPRISE_SUBSCRIPTION:
981 OSString += " Enterprise Subscription";
982 break;
983 case NL_PRODUCT_ENTERPRISE_SUBSCRIPTION_N:
984 OSString += " Enterprise Subscription N";
985 break;
986 // nothing at 0x8e
987 case NL_PRODUCT_DATACENTER_NANO_SERVER:
988 OSString += " Datacenter Nano Server";
989 break;
990 case NL_PRODUCT_STANDARD_NANO_SERVER:
991 OSString += " Standard Nano Server";
992 break;
993 case NL_PRODUCT_DATACENTER_A_SERVER_CORE:
994 OSString += " Datacenter A Server Core";
995 break;
996 case NL_PRODUCT_STANDARD_A_SERVER_CORE:
997 OSString += " Standard A Server Core";
998 break;
999 case NL_PRODUCT_DATACENTER_WS_SERVER_CORE:
1000 OSString += " Datacenter WS Server Core";
1001 break;
1002 case NL_PRODUCT_STANDARD_WS_SERVER_CORE:
1003 OSString += " Standard WS Server Core";
1004 break;
1005 case NL_PRODUCT_UTILITY_VM:
1006 OSString += " Utility VM";
1007 break;
1008 // nothing from 0x96 to 0x9e
1009 case NL_PRODUCT_DATACENTER_EVALUATION_SERVER_CORE:
1010 OSString += " Datacenter_evaluation_server_core";
1011 break;
1012 case NL_PRODUCT_STANDARD_EVALUATION_SERVER_CORE:
1013 OSString += " Standard Evaluation Server Core";
1014 break;
1015 case NL_PRODUCT_PRO_WORKSTATION:
1016 OSString += " Pro Workstation";
1017 break;
1018 case NL_PRODUCT_PRO_WORKSTATION_N:
1019 OSString += " Pro Workstation N";
1020 break;
1021 // nothing at 0xa3
1022 case NL_PRODUCT_PRO_FOR_EDUCATION:
1023 OSString += " Pro for Education";
1024 break;
1025 case NL_PRODUCT_PRO_FOR_EDUCATION_N:
1026 OSString += " Pro for Education N";
1027 break;
1028 // nothing from 0xa6 to 0xa7
1029 case NL_PRODUCT_AZURE_SERVER_CORE:
1030 OSString += " Azure Server Core";
1031 break;
1032 case NL_PRODUCT_AZURE_NANO_SERVER:
1033 OSString += " Azure Nano Server";
1034 break;
1035 // nothing at 0xaa
1036 case NL_PRODUCT_ENTERPRISEG:
1037 OSString += " Enterprise G";
1038 break;
1039 case NL_PRODUCT_ENTERPRISEGN:
1040 OSString += " Enterprise GN";
1041 break;
1042 // nothing from 0xad to 0xae
1043 case NL_PRODUCT_SERVERRDSH:
1044 OSString += " Server RDSH";
1045 break;
1046 // nothing from 0xb0 to 0xb1
1047 case NL_PRODUCT_CLOUD:
1048 OSString += " Cloud";
1049 break;
1050 case NL_PRODUCT_CLOUDN:
1051 OSString += " Cloud N";
1052 break;
1054 default:
1055 OSString += toString(" Unknown Edition (0x%04x)", dwType);
1059 if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
1060 OSString += " 64-bit";
1061 else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
1062 OSString += " 32-bit";
1064 std::string servicePack;
1066 // special case for Windows NT 4.0
1067 if (osvi.dwMajorVersion == 4 && lstrcmpiA(osvi.szCSDVersion, "Service Pack 6") == 0 )
1069 HKEY hKey;
1070 LONG lRet;
1072 // Test for SP6 versus SP6a.
1073 lRet = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009", 0, KEY_QUERY_VALUE, &hKey );
1074 if( lRet == ERROR_SUCCESS )
1075 servicePack = "Service Pack 6a";
1076 else // Windows NT 4.0 prior to SP6a
1078 servicePack = osvi.szCSDVersion;
1081 RegCloseKey( hKey );
1083 else // Windows NT 3.51 and earlier or Windows 2000 and later
1085 servicePack = osvi.szCSDVersion;
1088 // Include service pack (if any)
1089 if (!servicePack.empty()) OSString += " " + servicePack;
1091 // Include build number
1092 OSString += toString(" (Build %d)", osvi.dwBuildNumber & 0xFFFF);
1094 // Windows 9x
1095 else if ( VER_PLATFORM_WIN32_WINDOWS == osvi.dwPlatformId )
1097 OSString = "Microsoft";
1099 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
1101 OSString += " Windows 95";
1102 if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' )
1103 OSString += " OSR2";
1105 else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
1107 OSString += " Windows 98";
1108 if ( osvi.szCSDVersion[1] == 'A' )
1109 OSString += " SE";
1111 else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
1113 OSString += " Windows Millennium Edition";
1115 else
1116 OSString += " Windows 9x";
1118 // Windows 3.1 with Win32s
1119 else if ( VER_PLATFORM_WIN32s == osvi.dwPlatformId )
1121 OSString = toString("Microsoft Windows %d.%d + Win32s", osvi.dwMajorVersion, osvi.dwMinorVersion);
1123 // Unknown Windows version
1124 else
1126 OSString = toString("Microsoft Windows %d.%d", osvi.dwMajorVersion, osvi.dwMinorVersion);
1129 OSString += toString( " (%d.%d %d)", osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
1131 #elif defined NL_OS_MAC
1133 OSString = getsysctlstr("kern.version");
1135 #elif defined NL_OS_UNIX
1137 int fd = open("/proc/version", O_RDONLY);
1138 if (fd == -1)
1140 nlwarning ("SI: Can't get OS from /proc/version: %s", strerror (errno));
1142 else
1144 char buffer[4096+1];
1145 int len = read(fd, buffer, sizeof(buffer)-1);
1146 close(fd);
1148 // remove the \n and set \0
1149 buffer[len-1] = '\0';
1151 OSString = buffer;
1154 #endif // NL_OS_UNIX
1156 return OSString;
1159 string CSystemInfo::getProc ()
1161 string ProcString = "Unknown";
1163 #ifdef NL_OS_WINDOWS
1165 LONG result;
1166 char value[1024];
1167 DWORD valueSize;
1168 HKEY hKey;
1170 result = ::RegOpenKeyExA (HKEY_LOCAL_MACHINE, "Hardware\\Description\\System\\CentralProcessor\\0", 0, KEY_QUERY_VALUE, &hKey);
1171 if (result == ERROR_SUCCESS)
1173 // get processor name
1174 valueSize = 1024;
1175 result = ::RegQueryValueExA (hKey, "ProcessorNameString", NULL, NULL, (LPBYTE)value, &valueSize);
1176 if (result == ERROR_SUCCESS)
1177 ProcString = value;
1178 else
1179 ProcString = "UnknownProc";
1181 ProcString += " / ";
1183 // get processor identifier
1184 valueSize = 1024;
1185 result = ::RegQueryValueExA (hKey, "Identifier", NULL, NULL, (LPBYTE)value, &valueSize);
1186 if (result == ERROR_SUCCESS)
1187 ProcString += value;
1188 else
1189 ProcString += "UnknownIdentifier";
1191 ProcString += " / ";
1193 // get processor vendor
1194 valueSize = 1024;
1195 result = ::RegQueryValueExA (hKey, "VendorIdentifier", NULL, NULL, (LPBYTE)value, &valueSize);
1196 if (result == ERROR_SUCCESS)
1197 ProcString += value;
1198 else
1199 ProcString += "UnknownVendor";
1201 ProcString += " / ";
1203 // get processor frequency
1204 result = ::RegQueryValueExA (hKey, "~MHz", NULL, NULL, (LPBYTE)value, &valueSize);
1205 if (result == ERROR_SUCCESS)
1207 uint32 freq = *(int *)value;
1208 // discard the low value (not enough significant)
1209 freq /= 10;
1210 freq *= 10;
1211 ProcString += toString("%uMHz", freq);
1213 else
1214 ProcString += "UnknownFreq";
1217 // Make sure to close the reg key
1218 RegCloseKey (hKey);
1220 // count the number of processor (max 8, in case this code don't work well)
1221 uint numProc= 1;
1222 for(uint i=1;i<8;i++)
1224 string tmp= string("Hardware\\Description\\System\\CentralProcessor\\") + toString(i);
1226 // try to open the key
1227 result = ::RegOpenKeyExA (HKEY_LOCAL_MACHINE, tmp.c_str(), 0, KEY_QUERY_VALUE, &hKey);
1228 // Make sure to close the reg key
1229 RegCloseKey (hKey);
1231 if(result == ERROR_SUCCESS)
1232 numProc++;
1233 else
1234 break;
1236 ProcString += " / ";
1237 ProcString += toString(numProc) + " Processors found";
1239 #elif defined NL_OS_MAC
1241 ProcString = getsysctlstr("machdep.cpu.brand_string");
1242 ProcString += " / ";
1243 ProcString += getsysctlstr("hw.machine");
1244 ProcString += " Family " + toString(getsysctlnum("machdep.cpu.family"));
1245 ProcString += " Model " + toString(getsysctlnum("machdep.cpu.model"));
1246 ProcString += " Stepping " + toString(getsysctlnum("machdep.cpu.stepping"));
1247 ProcString += " / ";
1248 ProcString += getsysctlstr("machdep.cpu.vendor");
1249 ProcString += " / ";
1250 ProcString += toString(getsysctlnum64("hw.cpufrequency")/1000000)+"MHz";
1251 ProcString += " / ";
1252 ProcString += toString(getsysctlnum("hw.ncpu")) + " Processors found";
1254 #elif defined NL_OS_UNIX
1256 uint processors = 0;
1257 if (fromString(getCpuInfo("processor"), processors)) ++processors;
1259 ProcString = getCpuInfo("model name");
1260 ProcString += " / ?";
1261 ProcString += " Family " + getCpuInfo("cpu family");
1262 ProcString += " Model " + getCpuInfo("model");
1263 ProcString += " Stepping " + getCpuInfo("stepping");
1264 ProcString += " / ";
1265 ProcString += getCpuInfo("vendor_id");
1266 ProcString += " / ";
1267 ProcString += getCpuInfo("cpu MHz")+"MHz";
1268 ProcString += " / ";
1269 ProcString += toString("%u Processors found", processors);
1271 #endif
1273 // Remove beginning spaces
1274 ProcString = ProcString.substr (ProcString.find_first_not_of (" "));
1276 return ProcString;
1279 uint64 CSystemInfo::getProcessorFrequency(bool quick)
1281 static uint64 freq = 0;
1282 #ifdef NL_CPU_INTEL
1283 static bool freqComputed = false;
1284 if (freqComputed) return freq;
1286 if (!quick)
1288 TTicks bestNumTicks = 0;
1289 uint64 bestNumCycles = 0;
1290 uint64 numCycles;
1291 const uint numSamples = 5;
1292 const uint numLoops = 50000000;
1294 volatile uint k; // prevent optimization for the loop
1295 for(uint l = 0; l < numSamples; ++l)
1297 TTicks startTick = NLMISC::CTime::getPerformanceTime();
1298 uint64 startCycle = rdtsc();
1299 volatile uint dummy = 0;
1300 for(k = 0; k < numLoops; ++k)
1302 ++ dummy;
1304 numCycles = rdtsc() - startCycle;
1305 TTicks numTicks = NLMISC::CTime::getPerformanceTime() - startTick;
1306 if (numTicks > bestNumTicks)
1308 bestNumTicks = numTicks;
1309 bestNumCycles = numCycles;
1312 freq = (uint64) ((double) bestNumCycles * 1 / CTime::ticksToSecond(bestNumTicks));
1314 else
1316 TTicks timeBefore = NLMISC::CTime::getPerformanceTime();
1317 uint64 tickBefore = rdtsc();
1318 nlSleep (100);
1319 TTicks timeAfter = NLMISC::CTime::getPerformanceTime();
1320 TTicks tickAfter = rdtsc();
1322 double timeDelta = CTime::ticksToSecond(timeAfter - timeBefore);
1323 TTicks tickDelta = tickAfter - tickBefore;
1325 freq = (uint64) ((double)tickDelta / timeDelta);
1328 nlinfo ("SI: CSystemInfo: Processor frequency is %.0f MHz", (float)freq/1000000.0);
1329 freqComputed = true;
1330 #endif // NL_CPU_INTEL
1331 return freq;
1334 static bool DetectMMX()
1336 #ifdef NL_CPU_INTEL
1337 if (!CSystemInfo::hasCPUID()) return false; // cpuid not supported ...
1339 sint32 CPUInfo[4];
1340 nlcpuid(CPUInfo, 1);
1341 // check for bit 23 = MMX instruction set
1342 if (CPUInfo[3] & 0x800000) return true;
1343 #endif // NL_CPU_INTEL
1345 return false;
1349 static bool DetectSSE()
1351 #ifdef NL_CPU_INTEL
1352 if (!CSystemInfo::hasCPUID()) return false; // cpuid not supported ...
1354 sint32 CPUInfo[4];
1355 nlcpuid(CPUInfo, 1);
1357 if (CPUInfo[3] & 0x2000000)
1359 // check OS support for SSE
1362 unsigned int tmp = _mm_getcsr();
1363 nlunreferenced(tmp);
1365 catch(...)
1367 return false;
1370 // printf("sse detected\n");
1372 return true;
1374 #endif // NL_CPU_INTEL
1376 return false;
1379 bool CSystemInfo::_HaveMMX = DetectMMX ();
1380 bool CSystemInfo::_HaveSSE = DetectSSE ();
1382 bool CSystemInfo::hasCPUID ()
1384 #ifdef NL_CPU_INTEL
1385 uint32 result = 0;
1386 sint32 CPUInfo[4] = {-1};
1387 nlcpuid(CPUInfo, 0);
1388 if (CPUInfo[3] != -1) result = 1;
1389 return result == 1;
1390 #else
1391 return false;
1392 #endif
1396 uint32 CSystemInfo::getCPUID()
1398 #ifdef NL_CPU_INTEL
1399 if (hasCPUID())
1401 uint32 result = 0;
1402 sint32 CPUInfo[4];
1403 nlcpuid(CPUInfo, 1);
1404 return CPUInfo[3];
1406 #endif // NL_CPU_INTEL
1408 return 0;
1412 * Note: Not used in NeL probably in Ryzom closed source. Not translated in AT&T asm, I don't understand the aim of this method
1413 * Returns true if the CPU has HT, even if it is disabled. Maybe shoud count how many (virtual) core there is.
1415 bool CSystemInfo::hasHyperThreading()
1417 #ifdef NL_OS_WINDOWS
1418 if(hasCPUID())
1420 sint32 CPUInfo[4];
1422 // get vendor string from cpuid
1423 char vendor_id[32];
1424 vendor_id[31] = '\0';
1425 memset(vendor_id, 0, sizeof(vendor_id));
1426 nlcpuid(CPUInfo, 0);
1427 memcpy(vendor_id, &CPUInfo[1], sizeof(sint32));
1428 memcpy(vendor_id+4, &CPUInfo[3], sizeof(sint32));
1429 memcpy(vendor_id+8, &CPUInfo[2], sizeof(sint32));
1431 // get cpuid flags
1432 nlcpuid(CPUInfo, 1);
1434 // pentium 4 or later processor?
1435 if ((((CPUInfo[0] & 0xf00) == 0xf00) || (CPUInfo[0] & 0xf00000)) &&
1436 strcmp(vendor_id, "GenuineIntel") == 0)
1437 return (CPUInfo[3] & 0x10000000)!=0; // Intel Processor Hyper-Threading
1439 #endif
1441 return false;
1444 bool CSystemInfo::isNT()
1446 #ifdef NL_OS_WINDOWS
1447 OSVERSIONINFO ver;
1448 ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1449 GetVersionEx(&ver);
1450 return ver.dwPlatformId == VER_PLATFORM_WIN32_NT;
1451 #else
1452 return false;
1453 #endif
1456 uint64 CSystemInfo::availableHDSpace (const string &filename)
1458 std::string path = CFile::getPath(filename);
1460 #ifdef NL_OS_UNIX
1461 struct statfs stfs;
1462 if (::statfs(path.c_str(), &stfs) != 0) return 0;
1464 return (uint64)stfs.f_bavail * (uint64)stfs.f_bsize;
1465 #else
1466 ULARGE_INTEGER freeSpace = {0};
1467 BOOL bRes = ::GetDiskFreeSpaceExW(nlUtf8ToWide(path), &freeSpace, NULL, NULL);
1468 if (!bRes) return 0;
1470 return (uint64)freeSpace.QuadPart;
1471 #endif
1474 uint64 CSystemInfo::availablePhysicalMemory ()
1476 #ifdef NL_OS_WINDOWS
1477 MEMORYSTATUSEX ms;
1478 GlobalMemoryStatusEx(&ms);
1479 return ms.ullAvailPhys;
1480 #elif defined NL_OS_MAC
1481 return uint64(getsysctlnum64("hw.usermem"));
1482 #elif defined NL_OS_UNIX
1483 return getSystemMemory("MemFree:")+getSystemMemory("Buffers:")+getSystemMemory("Cached:");
1484 #else
1485 return 0;
1486 #endif
1489 uint64 CSystemInfo::totalPhysicalMemory ()
1491 #ifdef NL_OS_WINDOWS
1492 MEMORYSTATUSEX ms;
1493 GlobalMemoryStatusEx(&ms);
1494 return ms.ullTotalPhys;
1495 #elif defined NL_OS_MAC
1496 return uint64(getsysctlnum64("hw.physmem"));
1497 #elif defined NL_OS_UNIX
1498 return getSystemMemory("MemTotal:");
1499 #else
1500 return 0;
1501 #endif
1504 #ifndef NL_OS_WINDOWS
1505 static inline char *skipWS(const char *p)
1507 while (isspace(*p)) p++;
1508 return (char *)p;
1511 static inline char *skipToken(const char *p)
1513 while (isspace(*p)) p++;
1514 while (*p && !isspace(*p)) p++;
1515 return (char *)p;
1517 #endif
1519 uint64 CSystemInfo::getAllocatedSystemMemory ()
1521 uint64 systemMemory = 0;
1522 #ifdef NL_OS_WINDOWS
1523 // Get system memory information
1524 HANDLE hHeap[100];
1525 DWORD heapCount = GetProcessHeaps (100, hHeap);
1527 uint heap;
1528 for (heap = 0; heap < heapCount; heap++)
1530 PROCESS_HEAP_ENTRY entry;
1531 entry.lpData = NULL;
1532 while (HeapWalk (hHeap[heap], &entry))
1534 if (entry.wFlags & PROCESS_HEAP_ENTRY_BUSY)
1536 systemMemory += entry.cbData + entry.cbOverhead;
1541 #elif defined NL_OS_UNIX
1543 int fd = open("/proc/self/stat", O_RDONLY);
1544 if (fd == -1)
1546 nlwarning ("HA: Can't get OS from /proc/self/stat: %s", strerror (errno));
1548 else
1550 char buffer[4096], *p;
1551 int len = read(fd, buffer, sizeof(buffer)-1);
1552 close(fd);
1554 buffer[len] = '\0';
1556 p = buffer;
1557 p = strchr(p, ')')+1; /* skip pid */
1558 p = skipWS(p);
1559 p++;
1561 p = skipToken(p); /* skip ppid */
1562 p = skipToken(p); /* skip pgrp */
1563 p = skipToken(p); /* skip session */
1564 p = skipToken(p); /* skip tty */
1565 p = skipToken(p); /* skip tty pgrp */
1566 p = skipToken(p); /* skip flags */
1567 p = skipToken(p); /* skip min flt */
1568 p = skipToken(p); /* skip cmin flt */
1569 p = skipToken(p); /* skip maj flt */
1570 p = skipToken(p); /* skip cmaj flt */
1571 p = skipToken(p); /* utime */
1572 p = skipToken(p); /* stime */
1573 p = skipToken(p); /* skip cutime */
1574 p = skipToken(p); /* skip cstime */
1575 p = skipToken(p); /* priority */
1576 p = skipToken(p); /* nice */
1577 p = skipToken(p); /* skip timeout */
1578 p = skipToken(p); /* skip it_real_val */
1579 p = skipToken(p); /* skip start_time */
1581 systemMemory = strtoul(p, &p, 10); /* vsize in bytes */
1584 #endif // NL_OS_WINDOWS
1585 return systemMemory;
1589 NLMISC_CATEGORISED_DYNVARIABLE(nel, string, AvailableHDSpace, "Hard drive space left in bytes")
1591 // ace: it's a little bit tricky, if you don't understand how it works, don't touch!
1592 static string location;
1593 if (get)
1595 *pointer = (CSystemInfo::availableHDSpace(location));
1596 location.clear();
1598 else
1600 location = *pointer;
1604 NLMISC_CATEGORISED_DYNVARIABLE(nel, string, AvailablePhysicalMemory, "Physical memory available on this computer in bytes")
1606 if (get) *pointer = bytesToHumanReadable(CSystemInfo::availablePhysicalMemory ());
1609 NLMISC_CATEGORISED_DYNVARIABLE(nel, string, TotalPhysicalMemory, "Total physical memory on this computer in bytes")
1611 if (get) *pointer = bytesToHumanReadable(CSystemInfo::totalPhysicalMemory ());
1614 NLMISC_CATEGORISED_DYNVARIABLE(nel, string, ProcessUsedMemory, "Memory used by this process in bytes")
1616 if (get) *pointer = bytesToHumanReadable(CSystemInfo::getAllocatedSystemMemory ());
1619 NLMISC_CATEGORISED_DYNVARIABLE(nel, string, OS, "OS used")
1621 if (get) *pointer = CSystemInfo::getOS();
1624 #ifdef NL_OS_WINDOWS
1625 struct DISPLAY_DEVICE_EX
1627 DWORD cb;
1628 CHAR DeviceName[32];
1629 CHAR DeviceString[128];
1630 DWORD StateFlags;
1631 CHAR DeviceID[128];
1632 CHAR DeviceKey[128];
1634 #endif // NL_OS_WINDOWS
1636 bool CSystemInfo::getVideoInfo (std::string &deviceName, uint64 &driverVersion)
1638 #ifdef NL_OS_WINDOWS
1639 /* Get the device name with EnumDisplayDevices (doesn't work under win95).
1640 * Look for driver information for this device in the registry
1642 * Follow the recommendations in the news group comp.os.ms-windows.programmer.nt.kernel-mode : "Get Video Driver ... Need Version"
1645 HMODULE hm = GetModuleHandle(TEXT("USER32"));
1646 if (hm)
1648 BOOL (WINAPI* EnumDisplayDevices)(LPCTSTR lpDevice, DWORD iDevNum, PDISPLAY_DEVICE lpDisplayDevice, DWORD dwFlags) = NULL;
1649 *(FARPROC*)&EnumDisplayDevices = GetProcAddress(hm, "EnumDisplayDevicesA");
1650 if (EnumDisplayDevices)
1652 DISPLAY_DEVICE_EX DisplayDevice;
1653 uint device = 0;
1654 DisplayDevice.cb = sizeof (DISPLAY_DEVICE_EX);
1655 bool found = false;
1656 while (EnumDisplayDevices(NULL, device, (DISPLAY_DEVICE*)&DisplayDevice, 0))
1658 // Main board ?
1659 if ((DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) &&
1660 (DisplayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) &&
1661 ((DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) == 0) &&
1662 (DisplayDevice.DeviceKey[0] != 0))
1664 found = true;
1666 // The device name
1667 deviceName = DisplayDevice.DeviceString;
1669 string keyPath = DisplayDevice.DeviceKey;
1670 string keyName;
1672 // Get the window version
1673 OSVERSIONINFO ver;
1674 ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1675 GetVersionEx(&ver);
1676 bool atleastNT4 = (ver.dwMajorVersion > 3) && (ver.dwPlatformId == VER_PLATFORM_WIN32_NT);
1677 bool winXP = ((ver.dwMajorVersion == 5) && (ver.dwMinorVersion == 1)) || (ver.dwMajorVersion > 5);
1679 // * Get the registry entry for driver
1681 // OSversion >= osWin2k
1682 if (atleastNT4)
1684 if (winXP)
1686 string::size_type pos = keyPath.rfind ('\\');
1687 if (pos != string::npos)
1688 keyPath = keyPath.substr (0, pos+1);
1689 keyPath += "Video";
1690 keyName = "Service";
1692 else
1694 string::size_type pos = toLowerAscii(keyPath).find ("\\device");
1695 if (pos != string::npos)
1696 keyPath = keyPath.substr (0, pos+1);
1697 keyName = "ImagePath";
1700 else // Win 9x
1702 keyPath += "\\default";
1703 keyName = "drv";
1706 // Format the key path
1707 if (toLowerAscii(keyPath).find ("\\registry\\machine") == 0)
1709 keyPath = "HKEY_LOCAL_MACHINE" + keyPath.substr (strlen ("\\registry\\machine"));
1712 // Get the root key
1713 static const char *rootKeys[]=
1715 "HKEY_CLASSES_ROOT\\",
1716 "HKEY_CURRENT_CONFIG\\",
1717 "HKEY_CURRENT_USER\\",
1718 "HKEY_LOCAL_MACHINE\\",
1719 "HKEY_USERS\\",
1720 "HKEY_PERFORMANCE_DATA\\",
1721 "HKEY_DYN_DATA\\"
1723 static const HKEY rootKeysH[]=
1725 HKEY_CLASSES_ROOT,
1726 HKEY_CURRENT_CONFIG,
1727 HKEY_CURRENT_USER,
1728 HKEY_LOCAL_MACHINE,
1729 HKEY_USERS,
1730 HKEY_PERFORMANCE_DATA,
1731 HKEY_DYN_DATA,
1733 uint i;
1734 HKEY keyRoot = HKEY_LOCAL_MACHINE;
1735 for (i=0; i<sizeof(rootKeysH)/sizeof(HKEY); i++)
1737 if (toUpperAscii(keyPath).find (rootKeys[i]) == 0)
1739 keyPath = keyPath.substr (strlen (rootKeys[i]));
1740 keyRoot = rootKeysH[i];
1741 break;
1745 // * Read the registry
1746 HKEY baseKey;
1747 if (RegOpenKeyExA(keyRoot, keyPath.c_str(), 0, KEY_READ, &baseKey) == ERROR_SUCCESS)
1749 DWORD valueType;
1750 char value[512];
1751 DWORD size = 512;
1752 string driverName;
1753 if (RegQueryValueExA(baseKey, keyName.c_str(), NULL, &valueType, (unsigned char *)value, &size) == ERROR_SUCCESS)
1755 // Null ?
1756 if (value[0] != 0)
1758 bool ok = !winXP;
1759 if (winXP)
1761 // In Windows'XP we got service name -> not real driver name, so
1762 string xpKey = string ("System\\CurrentControlSet\\Services\\")+value;
1763 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, xpKey.c_str(), 0, KEY_READ, &baseKey) == ERROR_SUCCESS)
1765 size = 512;
1766 if (RegQueryValueExA(baseKey, "ImagePath", NULL, &valueType, (unsigned char *)value, &size) == ERROR_SUCCESS)
1768 if (value[0] != 0)
1770 static const std::string s_systemRoot = "\\SystemRoot\\";
1772 driverName = value;
1774 if (driverName.substr(0, s_systemRoot.length()) == s_systemRoot)
1776 driverName = driverName.substr(s_systemRoot.length());
1779 ok = true;
1781 else
1782 nlwarning ("CSystemInfo::getVideoInfo : empty value ImagePath in key %s", xpKey.c_str());
1784 else
1785 nlwarning ("CSystemInfo::getVideoInfo : can't query ImagePath in key %s", xpKey.c_str());
1787 else
1788 nlwarning ("CSystemInfo::getVideoInfo : can't open key %s", xpKey.c_str());
1791 // Version dll link
1792 HMODULE hmVersion = LoadLibraryA ("version.dll");
1793 if (hmVersion)
1795 BOOL (WINAPI* _GetFileVersionInfo)(LPSTR, DWORD, DWORD, LPVOID) = NULL;
1796 DWORD (WINAPI* _GetFileVersionInfoSize)(LPSTR, LPDWORD) = NULL;
1797 BOOL (WINAPI* _VerQueryValue)(const LPVOID, LPSTR, LPVOID*, PUINT) = NULL;
1798 *(FARPROC*)&_GetFileVersionInfo = GetProcAddress(hmVersion, "GetFileVersionInfoA");
1799 *(FARPROC*)&_GetFileVersionInfoSize = GetProcAddress(hmVersion, "GetFileVersionInfoSizeA");
1800 *(FARPROC*)&_VerQueryValue = GetProcAddress(hmVersion, "VerQueryValueA");
1801 if (_VerQueryValue && _GetFileVersionInfoSize && _GetFileVersionInfo)
1803 // value got the path to the driver
1804 if (atleastNT4)
1806 nlverify (GetWindowsDirectoryA(value, 512) != 0);
1808 else
1810 nlverify (GetSystemDirectoryA(value, 512) != 0);
1812 driverName = string (value) + "\\" + driverName;
1814 DWORD dwHandle;
1815 DWORD size = _GetFileVersionInfoSize ((char*)driverName.c_str(), &dwHandle);
1816 if (size)
1818 vector<uint8> buffer;
1819 buffer.resize (size);
1820 if (_GetFileVersionInfo((char*)driverName.c_str(), dwHandle, size, &buffer[0]))
1822 VS_FIXEDFILEINFO *info;
1823 UINT len;
1824 char bslash[] = { '\\', 0x00 };
1825 if (_VerQueryValue(&buffer[0], bslash, (VOID**)&info, &len))
1827 driverVersion = (((uint64)info->dwFileVersionMS)<<32)|info->dwFileVersionLS;
1828 return true;
1830 else
1831 nlwarning ("CSystemInfo::getVideoInfo : VerQueryValue fails (%s)", driverName.c_str());
1833 else
1834 nlwarning ("CSystemInfo::getVideoInfo : GetFileVersionInfo fails (%s)", driverName.c_str());
1836 else
1837 nlwarning ("CSystemInfo::getVideoInfo : GetFileVersionInfoSize == 0 (%s)", driverName.c_str());
1839 else
1840 nlwarning ("CSystemInfo::getVideoInfo : No VerQuery, GetFileVersionInfoSize, GetFileVersionInfo functions");
1842 else
1843 nlwarning ("CSystemInfo::getVideoInfo : No version dll");
1845 else
1846 nlwarning ("CSystemInfo::getVideoInfo : empty value %s in key %s", keyName.c_str(), keyPath.c_str());
1848 else
1849 nlwarning ("CSystemInfo::getVideoInfo : can't query value %s in key %s", keyName.c_str(), keyPath.c_str());
1851 else
1852 nlwarning ("CSystemInfo::getVideoInfo : can't open key %s", keyPath.c_str());
1854 device++;
1856 if (!found)
1857 nlwarning ("CSystemInfo::getVideoInfo : No primary display device found");
1859 else
1860 nlwarning ("CSystemInfo::getVideoInfo : No EnumDisplayDevices function");
1862 else
1863 nlwarning ("CSystemInfo::getVideoInfo : No user32 dll");
1865 #endif // NL_OS_WINDOWS
1867 // Fails
1868 return false;
1871 uint64 CSystemInfo::virtualMemory ()
1873 #ifdef NL_OS_WINDOWS
1874 MEMORYSTATUSEX ms;
1875 GlobalMemoryStatusEx(&ms);
1876 return ms.ullTotalVirtual - ms.ullAvailVirtual;
1877 #else
1878 return 0;
1879 #endif
1882 } // NLMISC