1 /*
2    BAREOS® - Backup Archiving REcovery Open Sourced
3 
4    Copyright (C) 2007-2011 Free Software Foundation Europe e.V.
5    Copyright (C) 2016-2020 Bareos GmbH & Co. KG
6 
7    This program is Free Software; you can redistribute it and/or
8    modify it under the terms of version three of the GNU Affero General Public
9    License as published by the Free Software Foundation and included
10    in the file LICENSE.
11 
12    This program is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15    Affero General Public License for more details.
16 
17    You should have received a copy of the GNU Affero General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20    02110-1301, USA.
21 */
22 /*
23  * Kern Sibbald, August 2007
24  *
25  * Note, some of the original Bareos Windows startup and service handling code
26  * was derived from VNC code that was used in apcupsd then ported to
27  * Bareos.  However, since then the code has been significantly enhanced
28  * and largely rewritten.
29  *
30  * Evidently due to the nature of Windows startup code and service
31  * handling code, certain similarities remain. Thanks to the original
32  * VNC authors.
33  *
34  * This is a generic main routine, which is used by all three
35  * of the daemons. Each one compiles it with slightly different
36  * #defines.
37  */
38 
39 #include <mutex>
40 #include <windows.h>
41 #include <tchar.h>
42 #include <stdio.h>
43 
44 #include "osinfo.h"
45 
46 static char win_os[300];
47 static bool win_os_initialized = false;
48 static std::mutex init_mutex;
49 
50 static bool GetWindowsVersionString(LPTSTR osbuf, int maxsiz);
51 
GetOsInfoString()52 const char* GetOsInfoString()
53 {
54   if (!win_os_initialized) {
55     const std::lock_guard<std::mutex> lock(init_mutex);
56     if (!win_os_initialized) {
57       GetWindowsVersionString(win_os, sizeof(win_os) - 1);
58       win_os_initialized = true;
59     }
60   }
61   return win_os;
62 }
63 
64 
65 #ifndef PRODUCT_UNLICENSED
66 #  define PRODUCT_UNLICENSED 0xABCDABCD
67 #  define PRODUCT_BUSINESS 0x00000006
68 #  define PRODUCT_BUSINESS_N 0x00000010
69 #  define PRODUCT_CLUSTER_SERVER 0x00000012
70 #  define PRODUCT_DATACENTER_SERVER 0x00000008
71 #  define PRODUCT_DATACENTER_SERVER_CORE 0x0000000C
72 #  define PRODUCT_DATACENTER_SERVER_CORE_V 0x00000027
73 #  define PRODUCT_DATACENTER_SERVER_V 0x00000025
74 #  define PRODUCT_ENTERPRISE 0x00000004
75 #  define PRODUCT_ENTERPRISE_E 0x00000046
76 #  define PRODUCT_ENTERPRISE_N 0x0000001B
77 #  define PRODUCT_ENTERPRISE_SERVER 0x0000000A
78 #  define PRODUCT_ENTERPRISE_SERVER_CORE 0x0000000E
79 #  define PRODUCT_ENTERPRISE_SERVER_CORE_V 0x00000029
80 #  define PRODUCT_ENTERPRISE_SERVER_IA64 0x0000000F
81 #  define PRODUCT_ENTERPRISE_SERVER_V 0x00000026
82 #  define PRODUCT_HOME_BASIC 0x00000002
83 #  define PRODUCT_HOME_BASIC_E 0x00000043
84 #  define PRODUCT_HOME_BASIC_N 0x00000005
85 #  define PRODUCT_HOME_PREMIUM 0x00000003
86 #  define PRODUCT_HOME_PREMIUM_E 0x00000044
87 #  define PRODUCT_HOME_PREMIUM_N 0x0000001A
88 #  define PRODUCT_HYPERV 0x0000002A
89 #  define PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT 0x0000001E
90 #  define PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING 0x00000020
91 #  define PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY 0x0000001F
92 #  define PRODUCT_PROFESSIONAL 0x00000030
93 #  define PRODUCT_PROFESSIONAL_E 0x00000045
94 #  define PRODUCT_PROFESSIONAL_N 0x00000031
95 #  define PRODUCT_SERVER_FOR_SMALLBUSINESS 0x00000018
96 #  define PRODUCT_SERVER_FOR_SMALLBUSINESS_V 0x00000023
97 #  define PRODUCT_SERVER_FOUNDATION 0x00000021
98 #  define PRODUCT_SMALLBUSINESS_SERVER 0x00000009
99 #  define PRODUCT_SOLUTION_EMBEDDEDSERVER 0x00000038
100 #  define PRODUCT_STANDARD_SERVER 0x00000007
101 #  define PRODUCT_STANDARD_SERVER_CORE 0x0000000D
102 #  define PRODUCT_STANDARD_SERVER_CORE_V 0x00000028
103 #  define PRODUCT_STANDARD_SERVER_V 0x00000024
104 #  define PRODUCT_STARTER 0x0000000B
105 #  define PRODUCT_STARTER_E 0x00000042
106 #  define PRODUCT_STARTER_N 0x0000002F
107 #  define PRODUCT_STORAGE_ENTERPRISE_SERVER 0x00000017
108 #  define PRODUCT_STORAGE_EXPRESS_SERVER 0x00000014
109 #  define PRODUCT_STORAGE_STANDARD_SERVER 0x00000015
110 #  define PRODUCT_STORAGE_WORKGROUP_SERVER 0x00000016
111 #  define PRODUCT_UNDEFINED 0x00000000
112 #  define PRODUCT_ULTIMATE 0x00000001
113 #  define PRODUCT_ULTIMATE_E 0x00000047
114 #  define PRODUCT_ULTIMATE_N 0x0000001C
115 #  define PRODUCT_WEB_SERVER 0x00000011
116 #  define PRODUCT_WEB_SERVER_CORE 0x0000001D
117 
118 #  define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM 0x19
119 #  define SM_SERVERR2 89
120 #  define VER_SERVER_NT 0x80000000
121 
122 #endif
123 
124 #ifndef PRODUCT_PROFESSIONAL
125 #  define PRODUCT_PROFESSIONAL 0x00000030
126 #endif
127 #ifndef VER_SUITE_STORAGE_SERVER
128 #  define VER_SUITE_STORAGE_SERVER 0x00002000
129 #endif
130 #ifndef VER_SUITE_COMPUTE_SERVER
131 #  define VER_SUITE_COMPUTE_SERVER 0x00004000
132 #endif
133 
134 /* Unknown value */
135 #undef VER_SUITE_WH_SERVER
136 #define VER_SUITE_WH_SERVER -1
137 
138 
139 typedef void(WINAPI* PGNSI)(LPSYSTEM_INFO);
140 typedef BOOL(WINAPI* PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);
141 
142 /*
143  * Get Windows version display string
144  */
GetWindowsVersionString(LPTSTR osbuf,int maxsiz)145 static bool GetWindowsVersionString(LPTSTR osbuf, int maxsiz)
146 {
147   OSVERSIONINFOEX osvi;
148   SYSTEM_INFO si;
149   PGNSI pGNSI;
150   PGPI pGPI;
151   BOOL bOsVersionInfoEx;
152   DWORD dwType;
153 
154   memset(&si, 0, sizeof(SYSTEM_INFO));
155   memset(&osvi, 0, sizeof(OSVERSIONINFOEX));
156 
157   osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
158 
159   if (!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*)&osvi))) return 1;
160 
161   // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.
162 
163   pGNSI = (PGNSI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
164                                 "GetNativeSystemInfo");
165   if (pGNSI) {
166     pGNSI(&si);
167   } else {
168     GetSystemInfo(&si);
169   }
170 
171   if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion > 4) {
172     strncpy(osbuf, TEXT("Microsoft "), maxsiz);
173 
174     /*
175      * Test for the specific product.
176      */
177     switch (osvi.dwMajorVersion) {
178       case 6:
179         switch (osvi.dwMinorVersion) {
180           case 0:
181             if (osvi.wProductType == VER_NT_WORKSTATION) {
182               strncat(osbuf, TEXT("Windows Vista "), maxsiz);
183             } else {
184               strncat(osbuf, TEXT("Windows Server 2008 "), maxsiz);
185             }
186             break;
187           case 1:
188             if (osvi.wProductType == VER_NT_WORKSTATION) {
189               strncat(osbuf, TEXT("Windows 7 "), maxsiz);
190             } else {
191               strncat(osbuf, TEXT("Windows Server 2008 R2 "), maxsiz);
192             }
193             break;
194           case 2:
195             if (osvi.wProductType == VER_NT_WORKSTATION) {
196               strncat(osbuf, TEXT("Windows 8 "), maxsiz);
197             } else {
198               strncat(osbuf, TEXT("Windows Server 2012 "), maxsiz);
199             }
200             break;
201           default:
202             strncat(osbuf, TEXT("Windows Unknown Release "), maxsiz);
203             break;
204         }
205 
206         pGPI = (PGPI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
207                                     "GetProductInfo");
208         if (pGPI) {
209           pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);
210         } else {
211           dwType = PRODUCT_HOME_BASIC;
212         }
213 
214         switch (dwType) {
215           case PRODUCT_ULTIMATE:
216             strncat(osbuf, TEXT("Ultimate Edition"), maxsiz);
217             break;
218           case PRODUCT_PROFESSIONAL:
219             strncat(osbuf, TEXT("Professional"), maxsiz);
220             break;
221           case PRODUCT_HOME_PREMIUM:
222             strncat(osbuf, TEXT("Home Premium Edition"), maxsiz);
223             break;
224           case PRODUCT_HOME_BASIC:
225             strncat(osbuf, TEXT("Home Basic Edition"), maxsiz);
226             break;
227           case PRODUCT_ENTERPRISE:
228             strncat(osbuf, TEXT("Enterprise Edition"), maxsiz);
229             break;
230           case PRODUCT_BUSINESS:
231             strncat(osbuf, TEXT("Business Edition"), maxsiz);
232             break;
233           case PRODUCT_STARTER:
234             strncat(osbuf, TEXT("Starter Edition"), maxsiz);
235             break;
236           case PRODUCT_CLUSTER_SERVER:
237             strncat(osbuf, TEXT("Cluster Server Edition"), maxsiz);
238             break;
239           case PRODUCT_DATACENTER_SERVER:
240             strncat(osbuf, TEXT("Datacenter Edition"), maxsiz);
241             break;
242           case PRODUCT_DATACENTER_SERVER_CORE:
243             strncat(osbuf, TEXT("Datacenter Edition (core installation)"),
244                     maxsiz);
245             break;
246           case PRODUCT_ENTERPRISE_SERVER:
247             strncat(osbuf, TEXT("Enterprise Edition"), maxsiz);
248             break;
249           case PRODUCT_ENTERPRISE_SERVER_CORE:
250             strncat(osbuf, TEXT("Enterprise Edition (core installation)"),
251                     maxsiz);
252             break;
253           case PRODUCT_ENTERPRISE_SERVER_IA64:
254             strncat(osbuf, TEXT("Enterprise Edition for Itanium-based Systems"),
255                     maxsiz);
256             break;
257           case PRODUCT_SMALLBUSINESS_SERVER:
258             strncat(osbuf, TEXT("Small Business Server"), maxsiz);
259             break;
260           case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
261             strncat(osbuf, TEXT("Small Business Server Premium Edition"),
262                     maxsiz);
263             break;
264           case PRODUCT_STANDARD_SERVER:
265             strncat(osbuf, TEXT("Standard Edition"), maxsiz);
266             break;
267           case PRODUCT_STANDARD_SERVER_CORE:
268             strncat(osbuf, TEXT("Standard Edition (core installation)"),
269                     maxsiz);
270             break;
271           case PRODUCT_WEB_SERVER:
272             strncat(osbuf, TEXT("Web Server Edition"), maxsiz);
273             break;
274         }
275         break;
276       case 5:
277         switch (osvi.dwMinorVersion) {
278           case 2:
279             if (GetSystemMetrics(SM_SERVERR2)) {
280               strncat(osbuf, TEXT("Windows Server 2003 R2 "), maxsiz);
281             } else if (osvi.wSuiteMask & VER_SUITE_STORAGE_SERVER) {
282               strncat(osbuf, TEXT("Windows Storage Server 2003"), maxsiz);
283             } else if (osvi.wSuiteMask & VER_SUITE_WH_SERVER) {
284               strncat(osbuf, TEXT("Windows Home Server"), maxsiz);
285             } else if (osvi.wProductType == VER_NT_WORKSTATION
286                        && si.wProcessorArchitecture
287                               == PROCESSOR_ARCHITECTURE_AMD64) {
288               strncat(osbuf, TEXT("Windows XP Professional x64 Edition"),
289                       maxsiz);
290             } else {
291               strncat(osbuf, TEXT("Windows Server 2003 "), maxsiz);
292             }
293 
294             /*
295              * Test for the server type.
296              */
297             if (osvi.wProductType != VER_NT_WORKSTATION) {
298               if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) {
299                 if (osvi.wSuiteMask & VER_SUITE_DATACENTER) {
300                   strncat(osbuf,
301                           TEXT("Datacenter Edition for Itanium-based Systems"),
302                           maxsiz);
303                 } else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) {
304                   strncat(osbuf,
305                           TEXT("Enterprise Edition for Itanium-based Systems"),
306                           maxsiz);
307                 }
308               } else if (si.wProcessorArchitecture
309                          == PROCESSOR_ARCHITECTURE_AMD64) {
310                 if (osvi.wSuiteMask & VER_SUITE_DATACENTER) {
311                   strncat(osbuf, TEXT("Datacenter x64 Edition"), maxsiz);
312                 } else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) {
313                   strncat(osbuf, TEXT("Enterprise x64 Edition"), maxsiz);
314                 } else {
315                   strncat(osbuf, TEXT("Standard x64 Edition"), maxsiz);
316                 }
317               } else {
318                 if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER) {
319                   strncat(osbuf, TEXT("Compute Cluster Edition"), maxsiz);
320                 } else if (osvi.wSuiteMask & VER_SUITE_DATACENTER) {
321                   strncat(osbuf, TEXT("Datacenter Edition"), maxsiz);
322                 } else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) {
323                   strncat(osbuf, TEXT("Enterprise Edition"), maxsiz);
324                 } else if (osvi.wSuiteMask & VER_SUITE_BLADE) {
325                   strncat(osbuf, TEXT("Web Edition"), maxsiz);
326                 } else {
327                   strncat(osbuf, TEXT("Standard Edition"), maxsiz);
328                 }
329               }
330             }
331             break;
332           case 1:
333             strncat(osbuf, TEXT("Windows XP "), maxsiz);
334             if (osvi.wSuiteMask & VER_SUITE_PERSONAL) {
335               strncat(osbuf, TEXT("Home Edition"), maxsiz);
336             } else {
337               strncat(osbuf, TEXT("Professional"), maxsiz);
338             }
339             break;
340           case 0:
341             strncat(osbuf, TEXT("Windows 2000 "), maxsiz);
342             if (osvi.wProductType == VER_NT_WORKSTATION) {
343               strncat(osbuf, TEXT("Professional"), maxsiz);
344             } else {
345               if (osvi.wSuiteMask & VER_SUITE_DATACENTER) {
346                 strncat(osbuf, TEXT("Datacenter Server"), maxsiz);
347               } else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) {
348                 strncat(osbuf, TEXT("Advanced Server"), maxsiz);
349               } else {
350                 strncat(osbuf, TEXT("Server"), maxsiz);
351               }
352             }
353             break;
354         }
355         break;
356       default:
357         break;
358     }
359 
360     /*
361      * Include service pack (if any) and build number.
362      */
363     if (_tcslen(osvi.szCSDVersion) > 0) {
364       strncat(osbuf, TEXT(" "), maxsiz);
365       strncat(osbuf, osvi.szCSDVersion, maxsiz);
366     }
367 
368     char buf[80];
369 
370     snprintf(buf, 80, " (build %d)", (int)osvi.dwBuildNumber);
371     strncat(osbuf, buf, maxsiz);
372 
373     if (osvi.dwMajorVersion >= 6) {
374       if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
375         strncat(osbuf, TEXT(", 64-bit"), maxsiz);
376       else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
377         strncat(osbuf, TEXT(", 32-bit"), maxsiz);
378     }
379 
380     return true;
381   } else {
382     strncpy(osbuf, "Unknown Windows version.", maxsiz);
383     return true;
384   }
385 }
386