Cogs.Core
OsNameLogger.cpp
1#include "OSNameLogger.h"
2
3#ifdef _WIN32
4#include "Unicode.h"
5
6#include <Windows.h>
7#include <tchar.h>
8#include <strsafe.h>
9
10#define STATUS_SUCCESS (0x00000000)
11#define BUFSIZE 256
12
13#pragma comment(lib, "User32.lib")
14
15typedef LONG(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
16typedef void (WINAPI* PGNSI)(LPSYSTEM_INFO);
17typedef BOOL(WINAPI* PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);
18#endif
19
20#if defined(__APPLE__) || defined(__MACH__)
21#include "TargetConditionals.h"
22#endif
23
24#if defined(__linux__) || defined(__unix) || defined(__unix__)
25#include <sys/utsname.h>
26#endif
27
28#if defined(__ANDROID__)
29// Untested
30// #include <sys/system_properties.h>
31#endif
32
33#ifdef _WIN32
34// Can report versions up to 10, opposed to other deprecated system calls reporting only until dwMajorVersion 6 (windows 8)
35//https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_osversioninfow
36RTL_OSVERSIONINFOW getRealOSVersion()
37{
38 HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
39 if (hMod)
40 {
41 RtlGetVersionPtr fxPtr = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
42 if (fxPtr != nullptr)
43 {
44 RTL_OSVERSIONINFOW rovi = { 0 };
45 rovi.dwOSVersionInfoSize = sizeof(rovi);
46 if (STATUS_SUCCESS == fxPtr(&rovi))
47 {
48 return rovi;
49 }
50 }
51 }
52 RTL_OSVERSIONINFOW rovi = { 0 };
53 return rovi;
54}
55
56BOOL GetOSDisplayString(LPTSTR pszOS)
57{
58 OSVERSIONINFOEX osvi;
59 SYSTEM_INFO si;
60 PGNSI pGNSI;
61 PGPI pGPI;
62 DWORD dwType;
63
64 RTL_OSVERSIONINFOW version = getRealOSVersion();
65
66 ZeroMemory(&si, sizeof(SYSTEM_INFO));
67 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
68
69 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
70
71 // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.
72
73 pGNSI = (PGNSI)GetProcAddress(
74 GetModuleHandle(TEXT("kernel32.dll")),
75 "GetNativeSystemInfo");
76 if (NULL != pGNSI)
77 pGNSI(&si);
78 else GetSystemInfo(&si);
79
80 // WARNING function is deprecated
81 // For this use case we only care about the wProductType, which is not otherwise reported on the system calls supporting up to Win10
82#pragma warning(push)
83#pragma warning(disable : 4996) // 'GetVersionExA': was declared deprecated
84 GetVersionEx((OSVERSIONINFO*)&osvi);
85#pragma warning(pop)
86
87 if (VER_PLATFORM_WIN32_NT == version.dwPlatformId && version.dwMajorVersion > 4)
88 {
89 StringCchCopy(pszOS, BUFSIZE, TEXT("Microsoft "));
90
91 // Test for the specific product.
92
93 if (version.dwMajorVersion == 10)
94 {
95 if (osvi.wProductType == VER_NT_WORKSTATION)
96 {
97 if (version.dwMinorVersion == 0)
98 {
99 StringCchCat(pszOS, BUFSIZE, TEXT("Windows 10 "));
100 }
101 }
102 else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2016"));
103
104 //TODO: To be expanded with subsequent versions of Windows.
105
106 }
107
108 if (version.dwMajorVersion == 6)
109 {
110 if (version.dwMinorVersion == 0)
111 {
112 if (osvi.wProductType == VER_NT_WORKSTATION)
113 StringCchCat(pszOS, BUFSIZE, TEXT("Windows Vista "));
114 else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 "));
115 }
116
117 if (version.dwMinorVersion == 1 || version.dwMinorVersion == 2)
118 {
119 if (osvi.wProductType == VER_NT_WORKSTATION && version.dwMinorVersion == 1)
120 StringCchCat(pszOS, BUFSIZE, TEXT("Windows 7 "));
121 else
122 if (osvi.wProductType == VER_NT_WORKSTATION && version.dwMinorVersion == 2)
123 StringCchCat(pszOS, BUFSIZE, TEXT("Windows 8 "));
124 else
125 StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 R2 "));
126 }
127
128 if (version.dwMinorVersion == 3)
129 {
130 if (osvi.wProductType == VER_NT_WORKSTATION)
131 StringCchCat(pszOS, BUFSIZE, TEXT("Windows 8.1 "));
132 else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2012 R2"));
133 }
134
135 pGPI = (PGPI)GetProcAddress(
136 GetModuleHandle(TEXT("kernel32.dll")),
137 "GetProductInfo");
138
139 pGPI(version.dwMajorVersion, version.dwMinorVersion, 0, 0, &dwType);
140
141 switch (dwType)
142 {
143 case PRODUCT_ULTIMATE:
144 StringCchCat(pszOS, BUFSIZE, TEXT("Ultimate Edition"));
145 break;
146 case PRODUCT_PROFESSIONAL:
147 StringCchCat(pszOS, BUFSIZE, TEXT("Professional"));
148 break;
149 case PRODUCT_HOME_PREMIUM:
150 StringCchCat(pszOS, BUFSIZE, TEXT("Home Premium Edition"));
151 break;
152 case PRODUCT_HOME_BASIC:
153 StringCchCat(pszOS, BUFSIZE, TEXT("Home Basic Edition"));
154 break;
155 case PRODUCT_ENTERPRISE:
156 StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition"));
157 break;
158 case PRODUCT_BUSINESS:
159 StringCchCat(pszOS, BUFSIZE, TEXT("Business Edition"));
160 break;
161 case PRODUCT_STARTER:
162 StringCchCat(pszOS, BUFSIZE, TEXT("Starter Edition"));
163 break;
164 case PRODUCT_CLUSTER_SERVER:
165 StringCchCat(pszOS, BUFSIZE, TEXT("Cluster Server Edition"));
166 break;
167 case PRODUCT_DATACENTER_SERVER:
168 StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition"));
169 break;
170 case PRODUCT_DATACENTER_SERVER_CORE:
171 StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition (core installation)"));
172 break;
173 case PRODUCT_ENTERPRISE_SERVER:
174 StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition"));
175 break;
176 case PRODUCT_ENTERPRISE_SERVER_CORE:
177 StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition (core installation)"));
178 break;
179 case PRODUCT_ENTERPRISE_SERVER_IA64:
180 StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition for Itanium-based Systems"));
181 break;
182 case PRODUCT_SMALLBUSINESS_SERVER:
183 StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server"));
184 break;
185 case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
186 StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server Premium Edition"));
187 break;
188 case PRODUCT_STANDARD_SERVER:
189 StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition"));
190 break;
191 case PRODUCT_STANDARD_SERVER_CORE:
192 StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition (core installation)"));
193 break;
194 case PRODUCT_WEB_SERVER:
195 StringCchCat(pszOS, BUFSIZE, TEXT("Web Server Edition"));
196 break;
197 }
198 }
199
200 if (version.dwMajorVersion == 5 && version.dwMinorVersion == 2)
201 {
202 if (GetSystemMetrics(SM_SERVERR2))
203 StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2003 R2, "));
204 else if (osvi.wSuiteMask & VER_SUITE_STORAGE_SERVER)
205 StringCchCat(pszOS, BUFSIZE, TEXT("Windows Storage Server 2003"));
206 else if (osvi.wSuiteMask & VER_SUITE_WH_SERVER)
207 StringCchCat(pszOS, BUFSIZE, TEXT("Windows Home Server"));
208 else if (osvi.wProductType == VER_NT_WORKSTATION &&
209 si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
210 {
211 StringCchCat(pszOS, BUFSIZE, TEXT("Windows XP Professional x64 Edition"));
212 }
213 else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2003, "));
214
215 // Test for the server type.
216 if (osvi.wProductType != VER_NT_WORKSTATION)
217 {
218 if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
219 {
220 if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
221 StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition for Itanium-based Systems"));
222 else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
223 StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition for Itanium-based Systems"));
224 }
225
226 else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
227 {
228 if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
229 StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter x64 Edition"));
230 else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
231 StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise x64 Edition"));
232 else StringCchCat(pszOS, BUFSIZE, TEXT("Standard x64 Edition"));
233 }
234
235 else
236 {
237 if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER)
238 StringCchCat(pszOS, BUFSIZE, TEXT("Compute Cluster Edition"));
239 else if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
240 StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition"));
241 else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
242 StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition"));
243 else if (osvi.wSuiteMask & VER_SUITE_BLADE)
244 StringCchCat(pszOS, BUFSIZE, TEXT("Web Edition"));
245 else StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition"));
246 }
247 }
248 }
249
250 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
251 {
252 StringCchCat(pszOS, BUFSIZE, TEXT("Windows XP "));
253 if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
254 StringCchCat(pszOS, BUFSIZE, TEXT("Home Edition"));
255 else StringCchCat(pszOS, BUFSIZE, TEXT("Professional"));
256 }
257
258 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
259 {
260 StringCchCat(pszOS, BUFSIZE, TEXT("Windows 2000 "));
261
262 if (osvi.wProductType == VER_NT_WORKSTATION)
263 {
264 StringCchCat(pszOS, BUFSIZE, TEXT("Professional"));
265 }
266 else
267 {
268 if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
269 StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Server"));
270 else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
271 StringCchCat(pszOS, BUFSIZE, TEXT("Advanced Server"));
272 else StringCchCat(pszOS, BUFSIZE, TEXT("Server"));
273 }
274 }
275
276 // Include service pack (if any) and build number.
277
278 if (_tcslen(osvi.szCSDVersion) > 0)
279 {
280 StringCchCat(pszOS, BUFSIZE, TEXT(" "));
281 StringCchCat(pszOS, BUFSIZE, osvi.szCSDVersion);
282 }
283
284 TCHAR buf[80];
285
286 StringCchPrintf(buf, 80, TEXT(" (build %d)"), osvi.dwBuildNumber);
287 StringCchCat(pszOS, BUFSIZE, buf);
288
289 if (osvi.dwMajorVersion >= 6)
290 {
291 if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
292 StringCchCat(pszOS, BUFSIZE, TEXT(", 64-bit"));
293 else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
294 StringCchCat(pszOS, BUFSIZE, TEXT(", 32-bit"));
295 }
296
297 return TRUE;
298 }
299
300 else
301 {
302 printf("This sample does not support this version of Windows.\n");
303 return FALSE;
304 }
305}
306#endif
307
308std::string Cogs::Logging::getOsNameAndVersion()
309{
310 std::string header{ "Logging OS Version: " };
311
312#ifdef _WIN32 // Includes both 32 bit and 64 bit application type.
313
314 TCHAR szOS[BUFSIZE];
315 BOOL displaystring = GetOSDisplayString(szOS);
316 if (displaystring)
317 {
318#ifdef UNICODE
319 std::string windowsVersion(narrow(szOS));
320#else
321 std::string windowsVersion(szOS);
322#endif
323 return header + "[OS Name]: Windows [OS Version]: " + windowsVersion;
324 }
325 else
326 return header + "[OS Name]: Windows [OS Version]: -";
327
328#elif defined(__CYGWIN__) && !defined(_WIN32)
329 return header + "[OS Name]: Windows (Cygwin POSIX under Microsoft Window) [OS Version]: -"
330
331#elif __ANDROID__
332
333 //TODO: Get Proper Version and Test
334 int getAndroidVersion()
335 {
336 /*char sdk_ver_str[1024];
337 if (__system_property_get("ro.build.version.sdk", sdk_ver_str)) {
338 sdk_ver = atoi(sdk_ver_str);
339 }
340 else {
341 // Not running on Android or SDK version is not available
342 // ...
343 }
344 // ... */
345 return 0;
346 }
347 return header + "[OS Name]: Android [OS Version]: " + (getAndridVersion() == 0) ? "-" : getAndroidVersion();
348
349#elif defined(__APPLE__) || defined(__MACH__)
350#if TARGET_OS_IPHONE && TARGET_IPHONE_SIMULATOR
351 //Getting Version info requires of Objective C code and partial port of the code to compile under MacOs
352 //TODO: Get version info
353 return header + "[OS Name]: iPhone Simulator [OS Version]: - ";
354#elif TARGET_OS_IPHONE
355 return header + "[OS Name]: iPhone [OS Version]: - ";
356#elif TARGET_OS_MAC
357 return header + "[OS Name]: Mac OS X [OS Version]: - ";
358#else
359 return header + "[OS Name]: Unknown Apple OS [OS Version]: -";
360#endif
361
362#elif __FreeBSD__
363
364 return header + "[OS Name]: FreeBSD [OS Version]: - ";
365
366#elif __linux__ || __unix || __unix__
367
368 struct utsname name;
369 // TODO: There might be a more readable string mapping from name.release / name.version (a la windows helper function)
370 // but I cannot find info about the human readable system names
371 if (uname(&name)) return header + "[OS Name]: Unknown Linux/Unix based platform [OS Version]: -";
372 return header + "[OS Name]: " + name.sysname + " [OS Version]: " + name.release + " " + name.version;
373
374#else
375 return header + "[OS Name]: Other/Non standard OS [OS Version]: -";
376#endif
377}