Show bonus/malus timer text if available
[ryzomcore.git] / nel / src / misc / system_info.cpp
blobd8a79ca7712d1a9d9f2b18111c43d079ca34f11d
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 # else
192 # include <sys/vfs.h>
193 # endif
194 #endif // NL_OS_WINDOWS
196 #include "nel/misc/system_info.h"
197 #include "nel/misc/command.h"
198 #include "nel/misc/variable.h"
200 using namespace std;
202 #ifdef DEBUG_NEW
203 #define new DEBUG_NEW
204 #endif
206 namespace NLMISC {
208 #ifdef NL_OS_UNIX
209 static string getCpuInfo(const string &colname)
211 if (colname.empty())
212 return "";
214 int fd = open("/proc/cpuinfo", O_RDONLY);
215 if (fd == -1)
217 nlwarning ("SI: Can't open /proc/cpuinfo: %s", strerror (errno));
218 return "";
220 else
222 char buffer[4096+1];
223 uint32 len = read(fd, buffer, sizeof(buffer)-1);
224 close(fd);
225 buffer[len] = '\0';
227 vector<string> splitted;
228 explode(string(buffer), string("\n"), splitted, true);
230 std::string value;
232 for(uint32 i = 0; i < splitted.size(); i++)
234 vector<string> sline;
235 explode(splitted[i], string(":"), sline, true);
236 if(sline.size() == 2 && trim(sline[0]) == colname)
238 value = sline[1];
242 if (!value.empty())
243 return trim(value);
245 nlwarning ("SI: Can't find the colname '%s' in /proc/cpuinfo", colname.c_str());
246 return "";
249 // return the value of the colname in bytes from /proc/meminfo
250 static uint64 getSystemMemory (const string &colname)
252 if (colname.empty())
253 return 0;
255 int fd = open("/proc/meminfo", O_RDONLY);
256 if (fd == -1)
258 nlwarning ("SI: Can't open /proc/meminfo: %s", strerror (errno));
259 return 0;
261 else
263 char buffer[4096+1];
264 uint32 len = read(fd, buffer, sizeof(buffer)-1);
265 close(fd);
266 buffer[len] = '\0';
268 vector<string> splitted;
269 explode(string(buffer), string("\n"), splitted, true);
271 for(uint32 i = 0; i < splitted.size(); i++)
273 vector<string> sline;
274 explode(splitted[i], string(" "), sline, true);
275 if(sline.size() == 3 && sline[0] == colname)
277 uint64 val = atoiInt64(sline[1].c_str());
278 if(sline[2] == "kB") val *= 1024;
279 return val;
283 nlwarning ("SI: Can't find the colname '%s' in /proc/meminfo", colname.c_str());
284 return 0;
286 #endif // NL_OS_UNIX
288 #ifdef NL_OS_MAC
289 static sint32 getsysctlnum(const string &name)
291 sint32 value = 0;
292 size_t len = sizeof(value);
293 if(sysctlbyname(name.c_str(), &value, &len, NULL, 0) != 0)
295 nlwarning("SI: Can't get '%s' from sysctl: %s", name.c_str(), strerror (errno));
297 return value;
300 static sint64 getsysctlnum64(const string &name)
302 sint64 value = 0;
303 size_t len = sizeof(value);
304 if(sysctlbyname(name.c_str(), &value, &len, NULL, 0) != 0)
306 nlwarning("SI: Can't get '%s' from sysctl: %s", name.c_str(), strerror (errno));
308 return value;
311 static string getsysctlstr(const string &name)
313 string value("Unknown");
314 size_t len;
315 char *p;
316 if(sysctlbyname(name.c_str(), NULL, &len, NULL, 0) == 0)
318 p = (char*)malloc(len);
319 if(sysctlbyname(name.c_str(), p, &len, NULL, 0) == 0)
321 value = p;
323 else
325 nlwarning("SI: Can't get '%s' from sysctl: %s", name.c_str(), strerror (errno));
327 free(p);
329 else
331 nlwarning("SI: Can't get '%s' from sysctl: %s", name.c_str(), strerror (errno));
333 return value;
335 #endif // NL_OS_MAC
337 string CSystemInfo::getOS()
339 string OSString = "Unknown";
341 #ifdef NL_OS_WINDOWS
343 typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
344 typedef BOOL (WINAPI *PGetProductInfo)(DWORD, DWORD, DWORD, DWORD, PDWORD);
345 typedef LONG (WINAPI* PRtlGetVersion)(OSVERSIONINFOEXA*);
347 const int BUFSIZE = 80;
349 // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
350 // If that fails, try using the OSVERSIONINFO structure.
352 SYSTEM_INFO si;
353 ZeroMemory(&si, sizeof(SYSTEM_INFO));
355 // RtlGetVersion always returns the right version
356 HMODULE hNtDll = GetModuleHandleA("ntdll.dll");
357 PRtlGetVersion pRtlGetVersion = (PRtlGetVersion)GetProcAddress(hNtDll, "RtlGetVersion");
359 BOOL bOsVersionInfoEx = 0;
361 // init OSVERSIONINFOEXA
362 OSVERSIONINFOEXA osvi;
363 ZeroMemory(&osvi, sizeof(osvi));
364 osvi.dwOSVersionInfoSize = sizeof(osvi);
366 if (pRtlGetVersion)
368 // try RtlGetVersion
369 bOsVersionInfoEx = pRtlGetVersion(&osvi) == 0;
372 if (!bOsVersionInfoEx)
374 // fall back to GetVersionExA
375 bOsVersionInfoEx = GetVersionExA ((OSVERSIONINFOA *) &osvi);
378 if (!bOsVersionInfoEx)
380 // fall back to GetVersionA struct
381 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
382 if (! GetVersionExA ( (OSVERSIONINFOA *) &osvi) )
383 return OSString+" Can't GetVersionEx()";
386 // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.
388 PGNSI pGNSI = (PGNSI) GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetNativeSystemInfo");
390 if (pGNSI)
391 pGNSI(&si);
392 else
393 GetSystemInfo(&si);
395 // Test for the Windows NT product family
396 if (VER_PLATFORM_WIN32_NT == osvi.dwPlatformId && osvi.dwMajorVersion > 4)
398 OSString = "Microsoft";
400 if (osvi.dwMajorVersion > 10)
402 OSString += " Windows (not released)";
404 else if (osvi.dwMajorVersion == 10)
406 OSString += " Windows 10";
408 else if (osvi.dwMajorVersion == 6)
410 if (osvi.dwMinorVersion == 3)
412 if (osvi.wProductType == VER_NT_WORKSTATION)
413 OSString += " Windows 8.1";
414 else
415 OSString += " Windows Server 2012 R2";
417 else if (osvi.dwMinorVersion == 2)
419 if (osvi.wProductType == VER_NT_WORKSTATION)
420 OSString += " Windows 8";
421 else
422 OSString += " Windows Server 2012";
424 else if (osvi.dwMinorVersion == 1)
426 if (osvi.wProductType == VER_NT_WORKSTATION)
427 OSString += " Windows 7";
428 else
429 OSString += " Windows Server 2008 R2";
431 else if (osvi.dwMinorVersion == 0)
433 if (osvi.wProductType == VER_NT_WORKSTATION)
434 OSString += " Windows Vista";
435 else
436 OSString += " Windows Server 2008";
438 else
440 OSString += " Windows (unknown)";
443 else if (osvi.dwMajorVersion == 5)
445 if (osvi.dwMinorVersion == 2)
447 if (GetSystemMetrics(89 /* SM_SERVERR2 */))
448 OSString += " Windows Server 2003 R2";
449 #ifdef VER_SUITE_STORAGE_SERVER
450 else if (osvi.wSuiteMask == VER_SUITE_STORAGE_SERVER)
451 OSString += " Windows Storage Server 2003";
452 #endif
453 #ifdef VER_SUITE_WH_SERVER
454 else if (osvi.wSuiteMask == VER_SUITE_WH_SERVER)
455 OSString += " Windows Home Server";
456 #endif
457 else if (osvi.wProductType == VER_NT_WORKSTATION &&
458 si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
459 OSString += " Windows XP Professional x64 Edition";
460 else
461 OSString += " Windows Server 2003";
463 // Test for the server type.
464 if (osvi.wProductType != VER_NT_WORKSTATION)
466 if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
468 if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
469 OSString += " Datacenter Edition for Itanium-based Systems";
470 else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
471 OSString += " Enterprise Edition for Itanium-based Systems";
474 else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
476 if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
477 OSString += " Datacenter x64 Edition";
478 else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
479 OSString += " Enterprise x64 Edition";
480 else
481 OSString += " Standard x64 Edition";
484 else
486 if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
487 OSString += " Enterprise Edition";
488 #ifdef VER_SUITE_DATACENTER
489 else if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
490 OSString += " Datacenter Edition";
491 #endif
492 #ifdef VER_SUITE_BLADE
493 else if (osvi.wSuiteMask & VER_SUITE_BLADE)
494 OSString += " Web Edition";
495 #endif
496 #ifdef VER_SUITE_COMPUTE_SERVER
497 else if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER)
498 OSString += " Compute Cluster Edition";
499 #endif
500 else
501 OSString += " Standard Edition";
505 else if (osvi.dwMinorVersion == 1)
507 OSString += " Windows XP";
508 if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
509 OSString += " Home Edition";
510 else
511 OSString += " Professional";
513 else if (osvi.dwMinorVersion == 0)
515 OSString += " Windows 2000";
517 if (osvi.wProductType == VER_NT_WORKSTATION)
519 OSString += " Professional";
521 else
523 if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
524 OSString += " Datacenter Server";
525 else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
526 OSString += " Advanced Server";
527 else
528 OSString += " Server";
531 else
533 OSString += " Unknown Windows";
536 else if (osvi.dwMajorVersion <= 4)
538 OSString += " Windows NT";
540 // Test for specific product on Windows NT 4.0 SP6 and later.
541 if (bOsVersionInfoEx)
543 // Test for the workstation type.
544 if (osvi.wProductType == VER_NT_WORKSTATION)
546 if (osvi.dwMajorVersion == 4 )
547 OSString += " Workstation 4.0";
548 else if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
549 OSString += " Home Edition";
550 else
551 OSString += " Professional";
554 // Test for the server type.
555 else if (osvi.wProductType == VER_NT_SERVER)
557 if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
558 OSString += " Server 4.0 Enterprise Edition";
559 else
560 OSString += " Server 4.0";
563 else // Test for specific product on Windows NT 4.0 SP5 and earlier
565 HKEY hKey;
566 char szProductType[BUFSIZE];
567 DWORD dwBufLen=BUFSIZE;
568 LONG lRet;
570 lRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 0, KEY_QUERY_VALUE, &hKey );
571 if (lRet != ERROR_SUCCESS)
572 return OSString + " Can't RegOpenKeyEx";
574 lRet = RegQueryValueExA(hKey, "ProductType", NULL, NULL, (LPBYTE) szProductType, &dwBufLen);
575 if ((lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE))
576 return OSString + " Can't ReQueryValueEx";
578 RegCloseKey(hKey);
580 if (lstrcmpiA("WINNT", szProductType) == 0)
581 OSString += " Workstation";
583 if (lstrcmpiA("LANMANNT", szProductType) == 0)
584 OSString += " Server";
586 if (lstrcmpiA("SERVERNT", szProductType) == 0)
587 OSString += " Advanced Server";
591 PGetProductInfo pGetProductInfo = (PGetProductInfo)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetProductInfo");
593 DWORD dwType;
595 if (pGetProductInfo && pGetProductInfo(osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.wServicePackMajor, osvi.wServicePackMinor, &dwType))
597 // Test for the specific product family.
598 // see https://msdn.microsoft.com/fr-fr/library/windows/desktop/ms724358(v=vs.85).aspx
599 switch (dwType)
601 case NL_PRODUCT_UNLICENSED:
602 OSString += " Unlicensed";
603 break;
604 case NL_PRODUCT_ULTIMATE:
605 OSString += " Ultimate";
606 break;
607 case NL_PRODUCT_HOME_BASIC:
608 OSString += " Home Basic";
609 break;
610 case NL_PRODUCT_HOME_PREMIUM:
611 OSString += " Home Premium";
612 break;
613 case NL_PRODUCT_ENTERPRISE:
614 OSString += " Enterprise";
615 break;
616 case NL_PRODUCT_HOME_BASIC_N:
617 OSString += " Home Basic N";
618 break;
619 case NL_PRODUCT_BUSINESS:
620 OSString += " Business";
621 break;
622 case NL_PRODUCT_STANDARD_SERVER:
623 OSString += " Server Standard";
624 break;
625 case NL_PRODUCT_DATACENTER_SERVER:
626 OSString += " Server Datacenter (full installation)";
627 break;
628 case NL_PRODUCT_SMALLBUSINESS_SERVER:
629 OSString += " Small Business Server";
630 break;
631 case NL_PRODUCT_ENTERPRISE_SERVER:
632 OSString += " Server Enterprise (full installation)";
633 break;
634 case NL_PRODUCT_STARTER:
635 OSString += " Starter";
636 break;
637 case NL_PRODUCT_DATACENTER_SERVER_CORE:
638 OSString += " Server Datacenter (core installation)";
639 break;
640 case NL_PRODUCT_STANDARD_SERVER_CORE:
641 OSString += " Server Standard (core installation)";
642 break;
643 case NL_PRODUCT_ENTERPRISE_SERVER_CORE:
644 OSString += " Server Enterprise (core installation)";
645 break;
646 case NL_PRODUCT_ENTERPRISE_SERVER_IA64:
647 OSString += " Server Enterprise for Itanium-based Systems";
648 break;
649 case NL_PRODUCT_BUSINESS_N:
650 OSString += " Business N";
651 break;
652 case NL_PRODUCT_WEB_SERVER:
653 OSString += " Web Server (full installation)";
654 break;
655 case NL_PRODUCT_CLUSTER_SERVER:
656 OSString += " Server Hyper Core";
657 break;
658 case NL_PRODUCT_HOME_SERVER:
659 OSString += " Home Server";
660 break;
661 case NL_PRODUCT_STORAGE_EXPRESS_SERVER:
662 OSString += " Storage Server Express";
663 break;
664 case NL_PRODUCT_STORAGE_STANDARD_SERVER:
665 OSString += " Storage Server Standard";
666 break;
667 case NL_PRODUCT_STORAGE_WORKGROUP_SERVER:
668 OSString += " Storage Server Workgroup";
669 break;
670 case NL_PRODUCT_STORAGE_ENTERPRISE_SERVER:
671 OSString += " Storage Server Enterprise";
672 break;
673 case NL_PRODUCT_SERVER_FOR_SMALLBUSINESS:
674 OSString += " Essential Server Solutions";
675 break;
676 case NL_PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
677 OSString += " Small Business Server Premium";
678 break;
679 case NL_PRODUCT_HOME_PREMIUM_N:
680 OSString += " Home Premium N";
681 break;
682 case NL_PRODUCT_ENTERPRISE_N:
683 OSString += " Enterprise N";
684 break;
685 case NL_PRODUCT_ULTIMATE_N:
686 OSString += " Ultimate N";
687 break;
688 case NL_PRODUCT_WEB_SERVER_CORE:
689 OSString += " Web Server (core installation)";
690 break;
691 case NL_PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT:
692 OSString += " Essential Business Server Management Server";
693 break;
694 case NL_PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY:
695 OSString += " Essential Business Server Security Server";
696 break;
697 case NL_PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING:
698 OSString += " Essential Business Server Messaging Server";
699 break;
700 case NL_PRODUCT_SERVER_FOUNDATION:
701 OSString += " Server Foundation";
702 break;
703 case NL_PRODUCT_HOME_PREMIUM_SERVER:
704 OSString += " Home Server";
705 break;
706 case NL_PRODUCT_SERVER_FOR_SMALLBUSINESS_V:
707 OSString += " Server without Hyper-V for Windows Essential Server Solutions";
708 break;
709 case NL_PRODUCT_STANDARD_SERVER_V:
710 OSString += " Server Standard without Hyper-V";
711 break;
712 case NL_PRODUCT_DATACENTER_SERVER_V:
713 OSString += " Server Datacenter without Hyper-V (full installation)";
714 break;
715 case NL_PRODUCT_ENTERPRISE_SERVER_V:
716 OSString += " Enterprise without Hyper-V (full installation)";
717 break;
718 case NL_PRODUCT_DATACENTER_SERVER_CORE_V:
719 OSString += " Datacenter without Hyper-V (core installation)";
720 break;
721 case NL_PRODUCT_STANDARD_SERVER_CORE_V:
722 OSString += " Standard without Hyper-V (core installation)";
723 break;
724 case NL_PRODUCT_ENTERPRISE_SERVER_CORE_V:
725 OSString += " Enterprise without Hyper-V (core installation)";
726 break;
727 case NL_PRODUCT_HYPERV:
728 OSString += " Hyper-V Server";
729 break;
730 case NL_PRODUCT_STORAGE_EXPRESS_SERVER_CORE:
731 OSString += " Storage Server Express (core installation)";
732 break;
733 case NL_PRODUCT_STORAGE_STANDARD_SERVER_CORE:
734 OSString += " Storage Server Standard (core installation)";
735 break;
736 case NL_PRODUCT_STORAGE_WORKGROUP_SERVER_CORE:
737 OSString += " Storage Server Workgroup (core installation)";
738 break;
739 case NL_PRODUCT_STORAGE_ENTERPRISE_SERVER_CORE:
740 OSString += " Storage Server Enterprise (core installation)";
741 break;
742 case NL_PRODUCT_STARTER_N:
743 OSString += " Starter N Edition";
744 break;
745 case NL_PRODUCT_PROFESSIONAL:
746 OSString += " Professional";
747 break;
748 case NL_PRODUCT_PROFESSIONAL_N:
749 OSString += " Professional N";
750 break;
751 case NL_PRODUCT_SB_SOLUTION_SERVER:
752 OSString += " Small Business Server";
753 break;
754 case NL_PRODUCT_SERVER_FOR_SB_SOLUTIONS:
755 OSString += " Server For Small Business Solutions";
756 break;
757 case NL_PRODUCT_STANDARD_SERVER_SOLUTIONS:
758 OSString += " Server Solutions Premium";
759 break;
760 case NL_PRODUCT_STANDARD_SERVER_SOLUTIONS_CORE:
761 OSString += " Server Solutions Premium (core installation)";
762 break;
763 case NL_PRODUCT_SB_SOLUTION_SERVER_EM:
764 OSString += " Server For Small Business Solutions EM";
765 break;
766 case NL_PRODUCT_SERVER_FOR_SB_SOLUTIONS_EM:
767 OSString += " Server For Small Business Solutions EM";
768 break;
769 case NL_PRODUCT_SOLUTION_EMBEDDEDSERVER:
770 OSString += " Solution Embedded Server (full installation)";
771 break;
772 case NL_PRODUCT_SOLUTION_EMBEDDEDSERVER_CORE:
773 OSString += " Solution Embedded Server (core installation)";
774 break;
775 case NL_PRODUCT_PROFESSIONAL_EMBEDDED:
776 OSString += " Professional Embedded";
777 break;
778 case NL_PRODUCT_ESSENTIALBUSINESS_SERVER_MGMT:
779 OSString += " Essential Server Solution Management";
780 break;
781 case NL_PRODUCT_ESSENTIALBUSINESS_SERVER_ADDL:
782 OSString += " Essential Server Solution Additional";
783 break;
784 case NL_PRODUCT_ESSENTIALBUSINESS_SERVER_MGMTSVC:
785 OSString += " Essential Server Solution Management SVC";
786 break;
787 case NL_PRODUCT_ESSENTIALBUSINESS_SERVER_ADDLSVC:
788 OSString += " Essential Server Solution Additional SVC";
789 break;
790 case NL_PRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE:
791 OSString += " Small Business Server Premium (core installation)";
792 break;
793 case NL_PRODUCT_CLUSTER_SERVER_V:
794 OSString += " Server Hyper Core V";
795 break;
796 case NL_PRODUCT_EMBEDDED:
797 OSString += " Embedded";
798 break;
799 case NL_PRODUCT_STARTER_E:
800 OSString += " Starter E";
801 break;
802 case NL_PRODUCT_HOME_BASIC_E:
803 OSString += " Home Basic E";
804 break;
805 case NL_PRODUCT_HOME_PREMIUM_E:
806 OSString += " Home Premium E";
807 break;
808 case NL_PRODUCT_PROFESSIONAL_E:
809 OSString += " Professional E";
810 break;
811 case NL_PRODUCT_ENTERPRISE_E:
812 OSString += " Enterprise E";
813 break;
814 case NL_PRODUCT_ULTIMATE_E:
815 OSString += " Ultimate E";
816 break;
817 case NL_PRODUCT_ENTERPRISE_EVALUATION:
818 OSString += " Enterprise Evaluation";
819 break;
820 // nothing from 0x49 to 0x4b
821 case NL_PRODUCT_MULTIPOINT_STANDARD_SERVER:
822 OSString += " MultiPoint Server Standard (full installation)";
823 break;
824 case NL_PRODUCT_MULTIPOINT_PREMIUM_SERVER:
825 OSString += " MultiPoint Server Premium (full installation)";
826 break;
827 case NL_PRODUCT_STANDARD_EVALUATION_SERVER:
828 OSString += " Server Standard (evaluation installation)";
829 break;
830 case NL_PRODUCT_DATACENTER_EVALUATION_SERVER:
831 OSString += " Server Datacenter (evaluation installation)";
832 break;
833 // nothing from 0x51 to 0x53
834 case NL_PRODUCT_ENTERPRISE_N_EVALUATION:
835 OSString += " Enterprise N (evaluation installation)";
836 break;
837 case NL_PRODUCT_EMBEDDED_AUTOMOTIVE:
838 OSString += " Embedded Automotive";
839 break;
840 case NL_PRODUCT_EMBEDDED_INDUSTRY_A:
841 OSString += " Embedded Industry A";
842 break;
843 case NL_PRODUCT_THINPC:
844 OSString += " Thin PC";
845 break;
846 case NL_PRODUCT_EMBEDDED_A:
847 OSString += " Embedded A";
848 break;
849 case NL_PRODUCT_EMBEDDED_INDUSTRY:
850 OSString += " Embedded Industry";
851 break;
852 case NL_PRODUCT_EMBEDDED_E:
853 OSString += " Embedded E";
854 break;
855 case NL_PRODUCT_EMBEDDED_INDUSTRY_E:
856 OSString += " Embedded Industry E";
857 break;
858 case NL_PRODUCT_EMBEDDED_INDUSTRY_A_E:
859 OSString += " Embedded Industry A E";
860 break;
861 // nothing from 0x5d to 0x5e
862 case NL_PRODUCT_STORAGE_WORKGROUP_EVALUATION_SERVER:
863 OSString += " Storage Server Workgroup (evaluation installation)";
864 break;
865 case NL_PRODUCT_STORAGE_STANDARD_EVALUATION_SERVER:
866 OSString += " Storage Server Standard (evaluation installation)";
867 break;
868 case NL_PRODUCT_CORE_ARM:
869 OSString += " RT";
870 break;
871 case NL_PRODUCT_CORE_N:
872 OSString += " Home N";
873 break;
874 case NL_PRODUCT_CORE_COUNTRYSPECIFIC:
875 OSString += " Home China";
876 break;
877 case NL_PRODUCT_CORE_SINGLELANGUAGE:
878 OSString += " Home Single Language";
879 break;
880 case NL_PRODUCT_CORE:
881 OSString += " Home";
882 break;
883 // nothing at 0x66
884 case NL_PRODUCT_PROFESSIONAL_WMC:
885 OSString += " Professional with Media Center";
886 break;
887 case NL_PRODUCT_MOBILE_CORE:
888 OSString += " Mobile";
889 break;
890 case NL_PRODUCT_EMBEDDED_INDUSTRY_EVAL:
891 OSString += " Embedded Industry (evaluation installation)";
892 break;
893 case NL_PRODUCT_EMBEDDED_INDUSTRY_E_EVAL:
894 OSString += " Embedded Industry E (evaluation installation)";
895 break;
896 case NL_PRODUCT_EMBEDDED_EVAL:
897 OSString += " Embedded (evaluation installation)";
898 break;
899 case NL_PRODUCT_EMBEDDED_E_EVAL:
900 OSString += " Embedded E (evaluation installation)";
901 break;
902 case NL_PRODUCT_CORE_SERVER:
903 OSString += " Server";
904 break;
905 case NL_PRODUCT_CLOUD_STORAGE_SERVER:
906 OSString += " Server Could Storage";
907 break;
908 case NL_PRODUCT_CORE_CONNECTED:
909 OSString += " Home Connected";
910 break;
911 case NL_PRODUCT_PROFESSIONAL_STUDENT:
912 OSString += " Professional Student";
913 break;
914 case NL_PRODUCT_CORE_CONNECTED_N:
915 OSString += " Home N Connected";
916 break;
917 case NL_PRODUCT_PROFESSIONAL_STUDENT_N:
918 OSString += " Professional Student N";
919 break;
920 case NL_PRODUCT_CORE_CONNECTED_SINGLELANGUAGE:
921 OSString += " Home Single Language Connected";
922 break;
923 case NL_PRODUCT_CORE_CONNECTED_COUNTRYSPECIFIC:
924 OSString += " Home China Connected";
925 break;
926 case NL_PRODUCT_CONNECTED_CAR:
927 OSString += " Connected Car";
928 break;
929 case NL_PRODUCT_INDUSTRY_HANDHELD:
930 OSString += " Industry Handheld";
931 break;
932 case NL_PRODUCT_PPI_PRO:
933 OSString += " PPI Pro";
934 break;
935 case NL_PRODUCT_ARM64_SERVER:
936 OSString += " ARM64 Server";
937 break;
938 case NL_PRODUCT_EDUCATION:
939 OSString += " Education";
940 break;
941 case NL_PRODUCT_EDUCATION_N:
942 OSString += " Education N";
943 break;
944 case NL_PRODUCT_IOTUAP:
945 OSString += " IoT Core";
946 break;
947 case NL_PRODUCT_CLOUD_HOST_INFRASTRUCTURE_SERVER:
948 OSString += " Cloud Host Infrastructure Server";
949 break;
950 case NL_PRODUCT_ENTERPRISE_S:
951 OSString += " Product Enterprise S";
952 break;
953 case NL_PRODUCT_ENTERPRISE_S_N:
954 OSString += " Enterprise S N";
955 break;
956 case NL_PRODUCT_PROFESSIONAL_S:
957 OSString += " Professional S";
958 break;
959 case NL_PRODUCT_PROFESSIONAL_S_N:
960 OSString += " Professional S N";
961 break;
962 case NL_PRODUCT_ENTERPRISE_S_EVALUATION:
963 OSString += " Enterprise S Evaluation";
964 break;
965 case NL_PRODUCT_ENTERPRISE_S_N_EVALUATION:
966 OSString += " Enterprise S N Evaluation";
967 break;
968 // nothing from x83 to 0x86
969 case NL_PRODUCT_HOLOGRAPHIC:
970 OSString += " Holographic";
971 break;
972 // nothing from x88 to 0x89
973 case NL_PRODUCT_PRO_SINGLE_LANGUAGE:
974 OSString += " Pro Single Language";
975 break;
976 case NL_PRODUCT_PRO_CHINA:
977 OSString += " Pro China";
978 break;
979 case NL_PRODUCT_ENTERPRISE_SUBSCRIPTION:
980 OSString += " Enterprise Subscription";
981 break;
982 case NL_PRODUCT_ENTERPRISE_SUBSCRIPTION_N:
983 OSString += " Enterprise Subscription N";
984 break;
985 // nothing at 0x8e
986 case NL_PRODUCT_DATACENTER_NANO_SERVER:
987 OSString += " Datacenter Nano Server";
988 break;
989 case NL_PRODUCT_STANDARD_NANO_SERVER:
990 OSString += " Standard Nano Server";
991 break;
992 case NL_PRODUCT_DATACENTER_A_SERVER_CORE:
993 OSString += " Datacenter A Server Core";
994 break;
995 case NL_PRODUCT_STANDARD_A_SERVER_CORE:
996 OSString += " Standard A Server Core";
997 break;
998 case NL_PRODUCT_DATACENTER_WS_SERVER_CORE:
999 OSString += " Datacenter WS Server Core";
1000 break;
1001 case NL_PRODUCT_STANDARD_WS_SERVER_CORE:
1002 OSString += " Standard WS Server Core";
1003 break;
1004 case NL_PRODUCT_UTILITY_VM:
1005 OSString += " Utility VM";
1006 break;
1007 // nothing from 0x96 to 0x9e
1008 case NL_PRODUCT_DATACENTER_EVALUATION_SERVER_CORE:
1009 OSString += " Datacenter_evaluation_server_core";
1010 break;
1011 case NL_PRODUCT_STANDARD_EVALUATION_SERVER_CORE:
1012 OSString += " Standard Evaluation Server Core";
1013 break;
1014 case NL_PRODUCT_PRO_WORKSTATION:
1015 OSString += " Pro Workstation";
1016 break;
1017 case NL_PRODUCT_PRO_WORKSTATION_N:
1018 OSString += " Pro Workstation N";
1019 break;
1020 // nothing at 0xa3
1021 case NL_PRODUCT_PRO_FOR_EDUCATION:
1022 OSString += " Pro for Education";
1023 break;
1024 case NL_PRODUCT_PRO_FOR_EDUCATION_N:
1025 OSString += " Pro for Education N";
1026 break;
1027 // nothing from 0xa6 to 0xa7
1028 case NL_PRODUCT_AZURE_SERVER_CORE:
1029 OSString += " Azure Server Core";
1030 break;
1031 case NL_PRODUCT_AZURE_NANO_SERVER:
1032 OSString += " Azure Nano Server";
1033 break;
1034 // nothing at 0xaa
1035 case NL_PRODUCT_ENTERPRISEG:
1036 OSString += " Enterprise G";
1037 break;
1038 case NL_PRODUCT_ENTERPRISEGN:
1039 OSString += " Enterprise GN";
1040 break;
1041 // nothing from 0xad to 0xae
1042 case NL_PRODUCT_SERVERRDSH:
1043 OSString += " Server RDSH";
1044 break;
1045 // nothing from 0xb0 to 0xb1
1046 case NL_PRODUCT_CLOUD:
1047 OSString += " Cloud";
1048 break;
1049 case NL_PRODUCT_CLOUDN:
1050 OSString += " Cloud N";
1051 break;
1053 default:
1054 OSString += toString(" Unknown Edition (0x%04x)", dwType);
1058 if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
1059 OSString += " 64-bit";
1060 else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
1061 OSString += " 32-bit";
1063 std::string servicePack;
1065 // special case for Windows NT 4.0
1066 if (osvi.dwMajorVersion == 4 && lstrcmpiA(osvi.szCSDVersion, "Service Pack 6") == 0 )
1068 HKEY hKey;
1069 LONG lRet;
1071 // Test for SP6 versus SP6a.
1072 lRet = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009", 0, KEY_QUERY_VALUE, &hKey );
1073 if( lRet == ERROR_SUCCESS )
1074 servicePack = "Service Pack 6a";
1075 else // Windows NT 4.0 prior to SP6a
1077 servicePack = osvi.szCSDVersion;
1080 RegCloseKey( hKey );
1082 else // Windows NT 3.51 and earlier or Windows 2000 and later
1084 servicePack = osvi.szCSDVersion;
1087 // Include service pack (if any)
1088 if (!servicePack.empty()) OSString += " " + servicePack;
1090 // Include build number
1091 OSString += toString(" (Build %d)", osvi.dwBuildNumber & 0xFFFF);
1093 // Windows 9x
1094 else if ( VER_PLATFORM_WIN32_WINDOWS == osvi.dwPlatformId )
1096 OSString = "Microsoft";
1098 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
1100 OSString += " Windows 95";
1101 if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' )
1102 OSString += " OSR2";
1104 else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
1106 OSString += " Windows 98";
1107 if ( osvi.szCSDVersion[1] == 'A' )
1108 OSString += " SE";
1110 else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
1112 OSString += " Windows Millennium Edition";
1114 else
1115 OSString += " Windows 9x";
1117 // Windows 3.1 with Win32s
1118 else if ( VER_PLATFORM_WIN32s == osvi.dwPlatformId )
1120 OSString = toString("Microsoft Windows %d.%d + Win32s", osvi.dwMajorVersion, osvi.dwMinorVersion);
1122 // Unknown Windows version
1123 else
1125 OSString = toString("Microsoft Windows %d.%d", osvi.dwMajorVersion, osvi.dwMinorVersion);
1128 OSString += toString( " (%d.%d %d)", osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
1130 #elif defined NL_OS_MAC
1132 OSString = getsysctlstr("kern.version");
1134 #elif defined NL_OS_UNIX
1136 int fd = open("/proc/version", O_RDONLY);
1137 if (fd == -1)
1139 nlwarning ("SI: Can't get OS from /proc/version: %s", strerror (errno));
1141 else
1143 char buffer[4096+1];
1144 int len = read(fd, buffer, sizeof(buffer)-1);
1145 close(fd);
1147 // remove the \n and set \0
1148 buffer[len-1] = '\0';
1150 OSString = buffer;
1153 #endif // NL_OS_UNIX
1155 return OSString;
1158 string CSystemInfo::getProc ()
1160 string ProcString = "Unknown";
1162 #ifdef NL_OS_WINDOWS
1164 LONG result;
1165 char value[1024];
1166 DWORD valueSize;
1167 HKEY hKey;
1169 result = ::RegOpenKeyExA (HKEY_LOCAL_MACHINE, "Hardware\\Description\\System\\CentralProcessor\\0", 0, KEY_QUERY_VALUE, &hKey);
1170 if (result == ERROR_SUCCESS)
1172 // get processor name
1173 valueSize = 1024;
1174 result = ::RegQueryValueExA (hKey, "ProcessorNameString", NULL, NULL, (LPBYTE)value, &valueSize);
1175 if (result == ERROR_SUCCESS)
1176 ProcString = value;
1177 else
1178 ProcString = "UnknownProc";
1180 ProcString += " / ";
1182 // get processor identifier
1183 valueSize = 1024;
1184 result = ::RegQueryValueExA (hKey, "Identifier", NULL, NULL, (LPBYTE)value, &valueSize);
1185 if (result == ERROR_SUCCESS)
1186 ProcString += value;
1187 else
1188 ProcString += "UnknownIdentifier";
1190 ProcString += " / ";
1192 // get processor vendor
1193 valueSize = 1024;
1194 result = ::RegQueryValueExA (hKey, "VendorIdentifier", NULL, NULL, (LPBYTE)value, &valueSize);
1195 if (result == ERROR_SUCCESS)
1196 ProcString += value;
1197 else
1198 ProcString += "UnknownVendor";
1200 ProcString += " / ";
1202 // get processor frequency
1203 result = ::RegQueryValueExA (hKey, "~MHz", NULL, NULL, (LPBYTE)value, &valueSize);
1204 if (result == ERROR_SUCCESS)
1206 uint32 freq = *(int *)value;
1207 // discard the low value (not enough significant)
1208 freq /= 10;
1209 freq *= 10;
1210 ProcString += toString("%uMHz", freq);
1212 else
1213 ProcString += "UnknownFreq";
1216 // Make sure to close the reg key
1217 RegCloseKey (hKey);
1219 // count the number of processor (max 8, in case this code don't work well)
1220 uint numProc= 1;
1221 for(uint i=1;i<8;i++)
1223 string tmp= string("Hardware\\Description\\System\\CentralProcessor\\") + toString(i);
1225 // try to open the key
1226 result = ::RegOpenKeyExA (HKEY_LOCAL_MACHINE, tmp.c_str(), 0, KEY_QUERY_VALUE, &hKey);
1227 // Make sure to close the reg key
1228 RegCloseKey (hKey);
1230 if(result == ERROR_SUCCESS)
1231 numProc++;
1232 else
1233 break;
1235 ProcString += " / ";
1236 ProcString += toString(numProc) + " Processors found";
1238 #elif defined NL_OS_MAC
1240 ProcString = getsysctlstr("machdep.cpu.brand_string");
1241 ProcString += " / ";
1242 ProcString += getsysctlstr("hw.machine");
1243 ProcString += " Family " + toString(getsysctlnum("machdep.cpu.family"));
1244 ProcString += " Model " + toString(getsysctlnum("machdep.cpu.model"));
1245 ProcString += " Stepping " + toString(getsysctlnum("machdep.cpu.stepping"));
1246 ProcString += " / ";
1247 ProcString += getsysctlstr("machdep.cpu.vendor");
1248 ProcString += " / ";
1249 ProcString += toString(getsysctlnum64("hw.cpufrequency")/1000000)+"MHz";
1250 ProcString += " / ";
1251 ProcString += toString(getsysctlnum("hw.ncpu")) + " Processors found";
1253 #elif defined NL_OS_UNIX
1255 uint processors = 0;
1256 if (fromString(getCpuInfo("processor"), processors)) ++processors;
1258 ProcString = getCpuInfo("model name");
1259 ProcString += " / ?";
1260 ProcString += " Family " + getCpuInfo("cpu family");
1261 ProcString += " Model " + getCpuInfo("model");
1262 ProcString += " Stepping " + getCpuInfo("stepping");
1263 ProcString += " / ";
1264 ProcString += getCpuInfo("vendor_id");
1265 ProcString += " / ";
1266 ProcString += getCpuInfo("cpu MHz")+"MHz";
1267 ProcString += " / ";
1268 ProcString += toString("%u Processors found", processors);
1270 #endif
1272 // Remove beginning spaces
1273 ProcString = ProcString.substr (ProcString.find_first_not_of (" "));
1275 return ProcString;
1278 uint64 CSystemInfo::getProcessorFrequency(bool quick)
1280 static uint64 freq = 0;
1281 #ifdef NL_CPU_INTEL
1282 static bool freqComputed = false;
1283 if (freqComputed) return freq;
1285 if (!quick)
1287 TTicks bestNumTicks = 0;
1288 uint64 bestNumCycles = 0;
1289 uint64 numCycles;
1290 const uint numSamples = 5;
1291 const uint numLoops = 50000000;
1293 volatile uint k; // prevent optimization for the loop
1294 for(uint l = 0; l < numSamples; ++l)
1296 TTicks startTick = NLMISC::CTime::getPerformanceTime();
1297 uint64 startCycle = rdtsc();
1298 volatile uint dummy = 0;
1299 for(k = 0; k < numLoops; ++k)
1301 ++ dummy;
1303 numCycles = rdtsc() - startCycle;
1304 TTicks numTicks = NLMISC::CTime::getPerformanceTime() - startTick;
1305 if (numTicks > bestNumTicks)
1307 bestNumTicks = numTicks;
1308 bestNumCycles = numCycles;
1311 freq = (uint64) ((double) bestNumCycles * 1 / CTime::ticksToSecond(bestNumTicks));
1313 else
1315 TTicks timeBefore = NLMISC::CTime::getPerformanceTime();
1316 uint64 tickBefore = rdtsc();
1317 nlSleep (100);
1318 TTicks timeAfter = NLMISC::CTime::getPerformanceTime();
1319 TTicks tickAfter = rdtsc();
1321 double timeDelta = CTime::ticksToSecond(timeAfter - timeBefore);
1322 TTicks tickDelta = tickAfter - tickBefore;
1324 freq = (uint64) ((double)tickDelta / timeDelta);
1327 nlinfo ("SI: CSystemInfo: Processor frequency is %.0f MHz", (float)freq/1000000.0);
1328 freqComputed = true;
1329 #endif // NL_CPU_INTEL
1330 return freq;
1333 static bool DetectMMX()
1335 #ifdef NL_CPU_INTEL
1336 if (!CSystemInfo::hasCPUID()) return false; // cpuid not supported ...
1338 sint32 CPUInfo[4];
1339 nlcpuid(CPUInfo, 1);
1340 // check for bit 23 = MMX instruction set
1341 if (CPUInfo[3] & 0x800000) return true;
1342 #endif // NL_CPU_INTEL
1344 return false;
1348 static bool DetectSSE()
1350 #ifdef NL_CPU_INTEL
1351 if (!CSystemInfo::hasCPUID()) return false; // cpuid not supported ...
1353 sint32 CPUInfo[4];
1354 nlcpuid(CPUInfo, 1);
1356 if (CPUInfo[3] & 0x2000000)
1358 // check OS support for SSE
1361 unsigned int tmp = _mm_getcsr();
1362 nlunreferenced(tmp);
1364 catch(...)
1366 return false;
1369 // printf("sse detected\n");
1371 return true;
1373 #endif // NL_CPU_INTEL
1375 return false;
1378 bool CSystemInfo::_HaveMMX = DetectMMX ();
1379 bool CSystemInfo::_HaveSSE = DetectSSE ();
1381 bool CSystemInfo::hasCPUID ()
1383 #ifdef NL_CPU_INTEL
1384 uint32 result = 0;
1385 sint32 CPUInfo[4] = {-1};
1386 nlcpuid(CPUInfo, 0);
1387 if (CPUInfo[3] != -1) result = 1;
1388 return result == 1;
1389 #else
1390 return false;
1391 #endif
1395 uint32 CSystemInfo::getCPUID()
1397 #ifdef NL_CPU_INTEL
1398 if (hasCPUID())
1400 uint32 result = 0;
1401 sint32 CPUInfo[4];
1402 nlcpuid(CPUInfo, 1);
1403 return CPUInfo[3];
1405 #endif // NL_CPU_INTEL
1407 return 0;
1411 * 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
1412 * Returns true if the CPU has HT, even if it is disabled. Maybe shoud count how many (virtual) core there is.
1414 bool CSystemInfo::hasHyperThreading()
1416 #ifdef NL_OS_WINDOWS
1417 if(hasCPUID())
1419 sint32 CPUInfo[4];
1421 // get vendor string from cpuid
1422 char vendor_id[32];
1423 vendor_id[31] = '\0';
1424 memset(vendor_id, 0, sizeof(vendor_id));
1425 nlcpuid(CPUInfo, 0);
1426 memcpy(vendor_id, &CPUInfo[1], sizeof(sint32));
1427 memcpy(vendor_id+4, &CPUInfo[3], sizeof(sint32));
1428 memcpy(vendor_id+8, &CPUInfo[2], sizeof(sint32));
1430 // get cpuid flags
1431 nlcpuid(CPUInfo, 1);
1433 // pentium 4 or later processor?
1434 if ((((CPUInfo[0] & 0xf00) == 0xf00) || (CPUInfo[0] & 0xf00000)) &&
1435 strcmp(vendor_id, "GenuineIntel") == 0)
1436 return (CPUInfo[3] & 0x10000000)!=0; // Intel Processor Hyper-Threading
1438 #endif
1440 return false;
1443 bool CSystemInfo::isNT()
1445 #ifdef NL_OS_WINDOWS
1446 OSVERSIONINFO ver;
1447 ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1448 GetVersionEx(&ver);
1449 return ver.dwPlatformId == VER_PLATFORM_WIN32_NT;
1450 #else
1451 return false;
1452 #endif
1455 uint64 CSystemInfo::availableHDSpace (const string &filename)
1457 std::string path = CFile::getPath(filename);
1459 #ifdef NL_OS_UNIX
1460 struct statfs stfs;
1461 if (::statfs(path.c_str(), &stfs) != 0) return 0;
1463 return (uint64)stfs.f_bavail * (uint64)stfs.f_bsize;
1464 #else
1465 ULARGE_INTEGER freeSpace = {0};
1466 BOOL bRes = ::GetDiskFreeSpaceExW(nlUtf8ToWide(path), &freeSpace, NULL, NULL);
1467 if (!bRes) return 0;
1469 return (uint64)freeSpace.QuadPart;
1470 #endif
1473 uint64 CSystemInfo::availablePhysicalMemory ()
1475 #ifdef NL_OS_WINDOWS
1476 MEMORYSTATUSEX ms;
1477 GlobalMemoryStatusEx(&ms);
1478 return ms.ullAvailPhys;
1479 #elif defined NL_OS_MAC
1480 return uint64(getsysctlnum64("hw.usermem"));
1481 #elif defined NL_OS_UNIX
1482 return getSystemMemory("MemFree:")+getSystemMemory("Buffers:")+getSystemMemory("Cached:");
1483 #else
1484 return 0;
1485 #endif
1488 uint64 CSystemInfo::totalPhysicalMemory ()
1490 #ifdef NL_OS_WINDOWS
1491 MEMORYSTATUSEX ms;
1492 GlobalMemoryStatusEx(&ms);
1493 return ms.ullTotalPhys;
1494 #elif defined NL_OS_MAC
1495 return uint64(getsysctlnum64("hw.physmem"));
1496 #elif defined NL_OS_UNIX
1497 return getSystemMemory("MemTotal:");
1498 #else
1499 return 0;
1500 #endif
1503 #ifndef NL_OS_WINDOWS
1504 static inline char *skipWS(const char *p)
1506 while (isspace(*p)) p++;
1507 return (char *)p;
1510 static inline char *skipToken(const char *p)
1512 while (isspace(*p)) p++;
1513 while (*p && !isspace(*p)) p++;
1514 return (char *)p;
1516 #endif
1518 uint64 CSystemInfo::getAllocatedSystemMemory ()
1520 uint64 systemMemory = 0;
1521 #ifdef NL_OS_WINDOWS
1522 // Get system memory information
1523 HANDLE hHeap[100];
1524 DWORD heapCount = GetProcessHeaps (100, hHeap);
1526 uint heap;
1527 for (heap = 0; heap < heapCount; heap++)
1529 PROCESS_HEAP_ENTRY entry;
1530 entry.lpData = NULL;
1531 while (HeapWalk (hHeap[heap], &entry))
1533 if (entry.wFlags & PROCESS_HEAP_ENTRY_BUSY)
1535 systemMemory += entry.cbData + entry.cbOverhead;
1540 #elif defined NL_OS_UNIX
1542 int fd = open("/proc/self/stat", O_RDONLY);
1543 if (fd == -1)
1545 nlwarning ("HA: Can't get OS from /proc/self/stat: %s", strerror (errno));
1547 else
1549 char buffer[4096], *p;
1550 int len = read(fd, buffer, sizeof(buffer)-1);
1551 close(fd);
1553 buffer[len] = '\0';
1555 p = buffer;
1556 p = strchr(p, ')')+1; /* skip pid */
1557 p = skipWS(p);
1558 p++;
1560 p = skipToken(p); /* skip ppid */
1561 p = skipToken(p); /* skip pgrp */
1562 p = skipToken(p); /* skip session */
1563 p = skipToken(p); /* skip tty */
1564 p = skipToken(p); /* skip tty pgrp */
1565 p = skipToken(p); /* skip flags */
1566 p = skipToken(p); /* skip min flt */
1567 p = skipToken(p); /* skip cmin flt */
1568 p = skipToken(p); /* skip maj flt */
1569 p = skipToken(p); /* skip cmaj flt */
1570 p = skipToken(p); /* utime */
1571 p = skipToken(p); /* stime */
1572 p = skipToken(p); /* skip cutime */
1573 p = skipToken(p); /* skip cstime */
1574 p = skipToken(p); /* priority */
1575 p = skipToken(p); /* nice */
1576 p = skipToken(p); /* skip timeout */
1577 p = skipToken(p); /* skip it_real_val */
1578 p = skipToken(p); /* skip start_time */
1580 systemMemory = strtoul(p, &p, 10); /* vsize in bytes */
1583 #endif // NL_OS_WINDOWS
1584 return systemMemory;
1588 NLMISC_CATEGORISED_DYNVARIABLE(nel, string, AvailableHDSpace, "Hard drive space left in bytes")
1590 // ace: it's a little bit tricky, if you don't understand how it works, don't touch!
1591 static string location;
1592 if (get)
1594 *pointer = (CSystemInfo::availableHDSpace(location));
1595 location.clear();
1597 else
1599 location = *pointer;
1603 NLMISC_CATEGORISED_DYNVARIABLE(nel, string, AvailablePhysicalMemory, "Physical memory available on this computer in bytes")
1605 if (get) *pointer = bytesToHumanReadable(CSystemInfo::availablePhysicalMemory ());
1608 NLMISC_CATEGORISED_DYNVARIABLE(nel, string, TotalPhysicalMemory, "Total physical memory on this computer in bytes")
1610 if (get) *pointer = bytesToHumanReadable(CSystemInfo::totalPhysicalMemory ());
1613 NLMISC_CATEGORISED_DYNVARIABLE(nel, string, ProcessUsedMemory, "Memory used by this process in bytes")
1615 if (get) *pointer = bytesToHumanReadable(CSystemInfo::getAllocatedSystemMemory ());
1618 NLMISC_CATEGORISED_DYNVARIABLE(nel, string, OS, "OS used")
1620 if (get) *pointer = CSystemInfo::getOS();
1623 #ifdef NL_OS_WINDOWS
1624 struct DISPLAY_DEVICE_EX
1626 DWORD cb;
1627 CHAR DeviceName[32];
1628 CHAR DeviceString[128];
1629 DWORD StateFlags;
1630 CHAR DeviceID[128];
1631 CHAR DeviceKey[128];
1633 #endif // NL_OS_WINDOWS
1635 bool CSystemInfo::getVideoInfo (std::string &deviceName, uint64 &driverVersion)
1637 #ifdef NL_OS_WINDOWS
1638 /* Get the device name with EnumDisplayDevices (doesn't work under win95).
1639 * Look for driver information for this device in the registry
1641 * Follow the recommendations in the news group comp.os.ms-windows.programmer.nt.kernel-mode : "Get Video Driver ... Need Version"
1644 HMODULE hm = GetModuleHandle(TEXT("USER32"));
1645 if (hm)
1647 BOOL (WINAPI* EnumDisplayDevices)(LPCTSTR lpDevice, DWORD iDevNum, PDISPLAY_DEVICE lpDisplayDevice, DWORD dwFlags) = NULL;
1648 *(FARPROC*)&EnumDisplayDevices = GetProcAddress(hm, "EnumDisplayDevicesA");
1649 if (EnumDisplayDevices)
1651 DISPLAY_DEVICE_EX DisplayDevice;
1652 uint device = 0;
1653 DisplayDevice.cb = sizeof (DISPLAY_DEVICE_EX);
1654 bool found = false;
1655 while (EnumDisplayDevices(NULL, device, (DISPLAY_DEVICE*)&DisplayDevice, 0))
1657 // Main board ?
1658 if ((DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) &&
1659 (DisplayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) &&
1660 ((DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) == 0) &&
1661 (DisplayDevice.DeviceKey[0] != 0))
1663 found = true;
1665 // The device name
1666 deviceName = DisplayDevice.DeviceString;
1668 string keyPath = DisplayDevice.DeviceKey;
1669 string keyName;
1671 // Get the window version
1672 OSVERSIONINFO ver;
1673 ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1674 GetVersionEx(&ver);
1675 bool atleastNT4 = (ver.dwMajorVersion > 3) && (ver.dwPlatformId == VER_PLATFORM_WIN32_NT);
1676 bool winXP = ((ver.dwMajorVersion == 5) && (ver.dwMinorVersion == 1)) || (ver.dwMajorVersion > 5);
1678 // * Get the registry entry for driver
1680 // OSversion >= osWin2k
1681 if (atleastNT4)
1683 if (winXP)
1685 string::size_type pos = keyPath.rfind ('\\');
1686 if (pos != string::npos)
1687 keyPath = keyPath.substr (0, pos+1);
1688 keyPath += "Video";
1689 keyName = "Service";
1691 else
1693 string::size_type pos = toLowerAscii(keyPath).find ("\\device");
1694 if (pos != string::npos)
1695 keyPath = keyPath.substr (0, pos+1);
1696 keyName = "ImagePath";
1699 else // Win 9x
1701 keyPath += "\\default";
1702 keyName = "drv";
1705 // Format the key path
1706 if (toLowerAscii(keyPath).find ("\\registry\\machine") == 0)
1708 keyPath = "HKEY_LOCAL_MACHINE" + keyPath.substr (strlen ("\\registry\\machine"));
1711 // Get the root key
1712 static const char *rootKeys[]=
1714 "HKEY_CLASSES_ROOT\\",
1715 "HKEY_CURRENT_CONFIG\\",
1716 "HKEY_CURRENT_USER\\",
1717 "HKEY_LOCAL_MACHINE\\",
1718 "HKEY_USERS\\",
1719 "HKEY_PERFORMANCE_DATA\\",
1720 "HKEY_DYN_DATA\\"
1722 static const HKEY rootKeysH[]=
1724 HKEY_CLASSES_ROOT,
1725 HKEY_CURRENT_CONFIG,
1726 HKEY_CURRENT_USER,
1727 HKEY_LOCAL_MACHINE,
1728 HKEY_USERS,
1729 HKEY_PERFORMANCE_DATA,
1730 HKEY_DYN_DATA,
1732 uint i;
1733 HKEY keyRoot = HKEY_LOCAL_MACHINE;
1734 for (i=0; i<sizeof(rootKeysH)/sizeof(HKEY); i++)
1736 if (toUpperAscii(keyPath).find (rootKeys[i]) == 0)
1738 keyPath = keyPath.substr (strlen (rootKeys[i]));
1739 keyRoot = rootKeysH[i];
1740 break;
1744 // * Read the registry
1745 HKEY baseKey;
1746 if (RegOpenKeyExA(keyRoot, keyPath.c_str(), 0, KEY_READ, &baseKey) == ERROR_SUCCESS)
1748 DWORD valueType;
1749 char value[512];
1750 DWORD size = 512;
1751 string driverName;
1752 if (RegQueryValueExA(baseKey, keyName.c_str(), NULL, &valueType, (unsigned char *)value, &size) == ERROR_SUCCESS)
1754 // Null ?
1755 if (value[0] != 0)
1757 bool ok = !winXP;
1758 if (winXP)
1760 // In Windows'XP we got service name -> not real driver name, so
1761 string xpKey = string ("System\\CurrentControlSet\\Services\\")+value;
1762 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, xpKey.c_str(), 0, KEY_READ, &baseKey) == ERROR_SUCCESS)
1764 size = 512;
1765 if (RegQueryValueExA(baseKey, "ImagePath", NULL, &valueType, (unsigned char *)value, &size) == ERROR_SUCCESS)
1767 if (value[0] != 0)
1769 static const std::string s_systemRoot = "\\SystemRoot\\";
1771 driverName = value;
1773 if (driverName.substr(0, s_systemRoot.length()) == s_systemRoot)
1775 driverName = driverName.substr(s_systemRoot.length());
1778 ok = true;
1780 else
1781 nlwarning ("CSystemInfo::getVideoInfo : empty value ImagePath in key %s", xpKey.c_str());
1783 else
1784 nlwarning ("CSystemInfo::getVideoInfo : can't query ImagePath in key %s", xpKey.c_str());
1786 else
1787 nlwarning ("CSystemInfo::getVideoInfo : can't open key %s", xpKey.c_str());
1790 // Version dll link
1791 HMODULE hmVersion = LoadLibraryA ("version.dll");
1792 if (hmVersion)
1794 BOOL (WINAPI* _GetFileVersionInfo)(LPSTR, DWORD, DWORD, LPVOID) = NULL;
1795 DWORD (WINAPI* _GetFileVersionInfoSize)(LPSTR, LPDWORD) = NULL;
1796 BOOL (WINAPI* _VerQueryValue)(const LPVOID, LPSTR, LPVOID*, PUINT) = NULL;
1797 *(FARPROC*)&_GetFileVersionInfo = GetProcAddress(hmVersion, "GetFileVersionInfoA");
1798 *(FARPROC*)&_GetFileVersionInfoSize = GetProcAddress(hmVersion, "GetFileVersionInfoSizeA");
1799 *(FARPROC*)&_VerQueryValue = GetProcAddress(hmVersion, "VerQueryValueA");
1800 if (_VerQueryValue && _GetFileVersionInfoSize && _GetFileVersionInfo)
1802 // value got the path to the driver
1803 if (atleastNT4)
1805 nlverify (GetWindowsDirectoryA(value, 512) != 0);
1807 else
1809 nlverify (GetSystemDirectoryA(value, 512) != 0);
1811 driverName = string (value) + "\\" + driverName;
1813 DWORD dwHandle;
1814 DWORD size = _GetFileVersionInfoSize ((char*)driverName.c_str(), &dwHandle);
1815 if (size)
1817 vector<uint8> buffer;
1818 buffer.resize (size);
1819 if (_GetFileVersionInfo((char*)driverName.c_str(), dwHandle, size, &buffer[0]))
1821 VS_FIXEDFILEINFO *info;
1822 UINT len;
1823 char bslash[] = { '\\', 0x00 };
1824 if (_VerQueryValue(&buffer[0], bslash, (VOID**)&info, &len))
1826 driverVersion = (((uint64)info->dwFileVersionMS)<<32)|info->dwFileVersionLS;
1827 return true;
1829 else
1830 nlwarning ("CSystemInfo::getVideoInfo : VerQueryValue fails (%s)", driverName.c_str());
1832 else
1833 nlwarning ("CSystemInfo::getVideoInfo : GetFileVersionInfo fails (%s)", driverName.c_str());
1835 else
1836 nlwarning ("CSystemInfo::getVideoInfo : GetFileVersionInfoSize == 0 (%s)", driverName.c_str());
1838 else
1839 nlwarning ("CSystemInfo::getVideoInfo : No VerQuery, GetFileVersionInfoSize, GetFileVersionInfo functions");
1841 else
1842 nlwarning ("CSystemInfo::getVideoInfo : No version dll");
1844 else
1845 nlwarning ("CSystemInfo::getVideoInfo : empty value %s in key %s", keyName.c_str(), keyPath.c_str());
1847 else
1848 nlwarning ("CSystemInfo::getVideoInfo : can't query value %s in key %s", keyName.c_str(), keyPath.c_str());
1850 else
1851 nlwarning ("CSystemInfo::getVideoInfo : can't open key %s", keyPath.c_str());
1853 device++;
1855 if (!found)
1856 nlwarning ("CSystemInfo::getVideoInfo : No primary display device found");
1858 else
1859 nlwarning ("CSystemInfo::getVideoInfo : No EnumDisplayDevices function");
1861 else
1862 nlwarning ("CSystemInfo::getVideoInfo : No user32 dll");
1864 #endif // NL_OS_WINDOWS
1866 // Fails
1867 return false;
1870 uint64 CSystemInfo::virtualMemory ()
1872 #ifdef NL_OS_WINDOWS
1873 MEMORYSTATUSEX ms;
1874 GlobalMemoryStatusEx(&ms);
1875 return ms.ullTotalVirtual - ms.ullAvailVirtual;
1876 #else
1877 return 0;
1878 #endif
1881 } // NLMISC