1 /*
2 Bacula(R) - The Network Backup Solution
3
4 Copyright (C) 2000-2020 Kern Sibbald
5
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
8
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
13
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
16
17 Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19
20 /*
21 *
22 * Kern Sibbald, August 2007
23 *
24 * Note, some of the original Bacula Windows startup and service handling code
25 * was derived from VNC code that was used in apcupsd then ported to
26 * Bacula. However, since then the code has been significantly enhanced
27 * and largely rewritten.
28 *
29 * Evidently due to the nature of Windows startup code and service
30 * handling code, certain similarities remain. Thanks to the original
31 * VNC authors.
32 *
33 * This is a generic main routine, which is used by all three
34 * of the daemons. Each one compiles it with slightly different
35 * #defines.
36 *
37 */
38
39 #define LOCKMGR_COMPLIANT
40 #include "bacula.h"
41 #include "win32.h"
42 #include <signal.h>
43 #include <pthread.h>
44
45 #include <commctrl.h>
46
47
48 /* Globals */
49 HINSTANCE appInstance;
50 DWORD mainthreadId;
51 bool opt_debug = false;
52 bool have_service_api;
53 DWORD service_thread_id = 0;
54 char win_os[300];
55
56 bool GetWindowsVersionString(LPTSTR osbuf, int maxsiz);
57
58
59 #define MAX_COMMAND_ARGS 100
60 static char *command_args[MAX_COMMAND_ARGS] = {(char *)LC_APP_NAME, NULL};
61 static int num_command_args = 1;
62 static pid_t main_pid;
63 static pthread_t main_tid;
64
65 const char usage[] = APP_NAME "[/debug] [/service] [/run] [/kill] [/install] [/remove] [/help]\n";
66
67 /*
68 *
69 * Main Windows entry point.
70 *
71 * We parse the command line and either calls the main App
72 * or starts up the service.
73 */
WinMain(HINSTANCE Instance,HINSTANCE,PSTR CmdLine,int)74 int WINAPI WinMain(HINSTANCE Instance, HINSTANCE /*PrevInstance*/, PSTR CmdLine,
75 int /*show*/)
76 {
77 char *cmdLine = CmdLine;
78 char *wordPtr, *tempPtr;
79 int i, quote;
80 OSVERSIONINFO osversioninfo;
81 osversioninfo.dwOSVersionInfoSize = sizeof(osversioninfo);
82
83 /* Save the application instance and main thread id */
84 appInstance = Instance;
85 mainthreadId = GetCurrentThreadId();
86
87 if (GetVersionEx(&osversioninfo) &&
88 osversioninfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
89 have_service_api = true;
90 }
91
92 GetWindowsVersionString(win_os, sizeof(win_os));
93
94 main_pid = getpid();
95 main_tid = pthread_self();
96
97 INITCOMMONCONTROLSEX initCC = {
98 sizeof(INITCOMMONCONTROLSEX),
99 ICC_STANDARD_CLASSES
100 };
101
102 InitCommonControlsEx(&initCC);
103
104 /*
105 * Funny things happen with the command line if the
106 * execution comes from c:/Program Files/bacula/bacula.exe
107 * We get a command line like: Files/bacula/bacula.exe" options
108 * I.e. someone stops scanning command line on a space, not
109 * realizing that the filename is quoted!!!!!!!!!!
110 * So if first character is not a double quote and
111 * the last character before first space is a double
112 * quote, we throw away the junk.
113 */
114
115 wordPtr = cmdLine;
116 while (*wordPtr && *wordPtr != ' ')
117 wordPtr++;
118 if (wordPtr > cmdLine) /* backup to char before space */
119 wordPtr--;
120 /* if first character is not a quote and last is, junk it */
121 if (*cmdLine != '"' && *wordPtr == '"') {
122 cmdLine = wordPtr + 1;
123 }
124
125 /*
126 * Build Unix style argc *argv[] for the main "Unix" code
127 * stripping out any Windows options
128 */
129
130 /* Don't NULL command_args[0] !!! */
131 for (i=1;i<MAX_COMMAND_ARGS;i++) {
132 command_args[i] = NULL;
133 }
134
135 char *pszArgs = bstrdup(cmdLine);
136 wordPtr = pszArgs;
137 quote = 0;
138 while (*wordPtr && (*wordPtr == ' ' || *wordPtr == '\t'))
139 wordPtr++;
140 if (*wordPtr == '\"') {
141 quote = 1;
142 wordPtr++;
143 } else if (*wordPtr == '/') {
144 /* Skip Windows options */
145 while (*wordPtr && (*wordPtr != ' ' && *wordPtr != '\t'))
146 wordPtr++;
147 while (*wordPtr && (*wordPtr == ' ' || *wordPtr == '\t'))
148 wordPtr++;
149 }
150 if (*wordPtr) {
151 while (*wordPtr && num_command_args < MAX_COMMAND_ARGS) {
152 tempPtr = wordPtr;
153 if (quote) {
154 while (*tempPtr && *tempPtr != '\"')
155 tempPtr++;
156 quote = 0;
157 } else {
158 while (*tempPtr && *tempPtr != ' ')
159 tempPtr++;
160 }
161 if (*tempPtr)
162 *(tempPtr++) = '\0';
163 command_args[num_command_args++] = wordPtr;
164 wordPtr = tempPtr;
165 while (*wordPtr && (*wordPtr == ' ' || *wordPtr == '\t'))
166 wordPtr++;
167 if (*wordPtr == '\"') {
168 quote = 1;
169 wordPtr++;
170 }
171 }
172 }
173
174 /*
175 * Now process Windows command line options. Most of these options
176 * are single shot -- i.e. we accept one option, do something and
177 * terminate.
178 */
179 for (i = 0; i < (int)strlen(cmdLine); i++) {
180 char *p = &cmdLine[i];
181
182 if (*p <= ' ') {
183 continue; /* toss junk */
184 }
185
186 if (*p != '/') {
187 break; /* syntax error */
188 }
189
190 /* Start as a service? */
191 if (strncasecmp(p, "/service", 8) == 0) {
192 return baculaServiceMain(); /* yes, run as a service */
193 }
194
195 /* Stop any running copy? */
196 if (strncasecmp(p, "/kill", 5) == 0) {
197 return stopRunningBacula();
198 }
199
200 /* Run app as user program? */
201 if (strncasecmp(p, "/run", 4) == 0) {
202 return BaculaAppMain(); /* yes, run as a user program */
203 }
204
205 /* Install Bacula in registry? */
206 if (strncasecmp(p, "/install", 8) == 0) {
207 return installService(p+8); /* Pass command options */
208 }
209
210 /* Remove Bacula registry entry? */
211 if (strncasecmp(p, "/remove", 7) == 0) {
212 return removeService();
213 }
214
215 /* Set debug mode? -- causes more dialogs to be displayed */
216 if (strncasecmp(p, "/debug", 6) == 0) {
217 opt_debug = true;
218 i += 6; /* skip /debug */
219 continue;
220 }
221
222 /* Display help? -- displays usage */
223 if (strncasecmp(p, "/help", 5) == 0) {
224 MessageBox(NULL, usage, APP_DESC, MB_OK|MB_ICONINFORMATION);
225 return 0;
226 }
227
228 MessageBox(NULL, cmdLine, _("Bad Command Line Option"), MB_OK);
229
230 /* Show the usage dialog */
231 MessageBox(NULL, usage, APP_DESC, MB_OK | MB_ICONINFORMATION);
232
233 return 1;
234 }
235 return BaculaAppMain();
236 }
237
238 #ifndef HAVE_TRAY_MONITOR
239 /* Minimalist winproc when don't have tray monitor */
bacWinProc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam)240 LRESULT CALLBACK bacWinProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
241 {
242 switch (iMsg) {
243 case WM_DESTROY:
244 PostQuitMessage(0);
245 return 0;
246 }
247 return DefWindowProc(hwnd, iMsg, wParam, lParam);
248 }
249 #endif
250
251
252 /*
253 * Called as a thread from BaculaAppMain()
254 * Here we handle the Windows messages
255 */
Main_Msg_Loop(LPVOID lpwThreadParam)256 void *Main_Msg_Loop(LPVOID lpwThreadParam)
257 {
258 MSG msg;
259
260 pthread_detach(pthread_self());
261
262 /*
263 * Since we are the only thread with a message loop
264 * mark ourselves as the service thread so that
265 * we can receive all the window events.
266 */
267 service_thread_id = GetCurrentThreadId();
268
269 #ifdef HAVE_TRAY_MONITOR
270 /* Create tray icon & menu if we're running as an app */
271 trayMonitor *monitor = new trayMonitor();
272 if (monitor == NULL) {
273 PostQuitMessage(0);
274 }
275
276 #else
277 /* Create a window to handle Windows messages */
278 WNDCLASSEX baclass;
279
280 baclass.cbSize = sizeof(baclass);
281 baclass.style = 0;
282 baclass.lpfnWndProc = bacWinProc;
283 baclass.cbClsExtra = 0;
284 baclass.cbWndExtra = 0;
285 baclass.hInstance = appInstance;
286 baclass.hIcon = NULL;
287 baclass.hCursor = NULL;
288 baclass.hbrBackground = NULL;
289 baclass.lpszMenuName = NULL;
290 baclass.lpszClassName = APP_NAME;
291 baclass.hIconSm = NULL;
292
293 RegisterClassEx(&baclass);
294
295 if (CreateWindow(APP_NAME, APP_NAME, WS_OVERLAPPEDWINDOW,
296 CW_USEDEFAULT, CW_USEDEFAULT, 0, 0,
297 NULL, NULL, appInstance, NULL) == NULL) {
298 PostQuitMessage(0);
299 }
300 #endif
301
302 /* Now enter the Windows message handling loop until told to quit! */
303 while (GetMessage(&msg, NULL, 0,0) ) {
304 TranslateMessage(&msg);
305 DispatchMessage(&msg);
306 }
307
308 /* If we get here, we are shutting down */
309
310 #ifdef HAVE_TRAY_MONITOR
311 if (monitor != NULL) {
312 delete monitor;
313 }
314 #endif
315
316 if (have_service_api) {
317 /* Mark that we're no longer running */
318 service_thread_id = 0;
319 /* Tell the service manager that we've stopped. */
320 ReportStatus(SERVICE_STOPPED, service_error, 0);
321 }
322 /* Tell main "Unix" program to go away */
323 terminate_app(0);
324
325 /* Should not get here */
326 pthread_kill(main_tid, SIGTERM); /* ask main thread to terminate */
327 sleep(1);
328 kill(main_pid, SIGTERM); /* kill main thread */
329 _exit(0);
330 }
331
332 /*
333 * This is the main routine for Bacula when running as an application,
334 * or after the service has started up.
335 */
BaculaAppMain()336 int BaculaAppMain()
337 {
338 pthread_t tid;
339 DWORD dwCharsWritten;
340
341 OSDependentInit();
342 /* If no arguments were given then just run */
343 if (p_AttachConsole == NULL || !p_AttachConsole(ATTACH_PARENT_PROCESS)) {
344 if (opt_debug) {
345 AllocConsole();
346 }
347 }
348
349 WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), "\r\n", 2, &dwCharsWritten, NULL);
350
351 /* Startup networking */
352 WSA_Init();
353
354 /* Set this process to be the last application to be shut down. */
355 if (p_SetProcessShutdownParameters) {
356 p_SetProcessShutdownParameters(0x100, 0);
357 }
358
359 /* Create a thread to handle the Windows messages */
360 pthread_create(&tid, NULL, Main_Msg_Loop, (void *)0);
361
362 /* Call the Unix Bacula daemon */
363 BaculaMain(num_command_args, command_args);
364 PostQuitMessage(0); /* terminate our main message loop */
365
366 WSACleanup();
367 _exit(0);
368 }
369
370
pause_msg(const char * file,const char * func,int line,const char * msg)371 void pause_msg(const char *file, const char *func, int line, const char *msg)
372 {
373 char buf[1000];
374 if (msg) {
375 bsnprintf(buf, sizeof(buf), "%s:%s:%d %s", file, func, line, msg);
376 } else {
377 bsnprintf(buf, sizeof(buf), "%s:%s:%d", file, func, line);
378 }
379 MessageBox(NULL, buf, "Pause", MB_OK);
380 }
381
382 #include <tchar.h>
383 #include <stdio.h>
384
385 #ifndef PRODUCT_UNLICENSED
386 #define PRODUCT_UNLICENSED 0xABCDABCD
387 #define PRODUCT_BUSINESS 0x00000006
388 #define PRODUCT_BUSINESS_N 0x00000010
389 #define PRODUCT_CLUSTER_SERVER 0x00000012
390 #define PRODUCT_DATACENTER_SERVER 0x00000008
391 #define PRODUCT_DATACENTER_SERVER_CORE 0x0000000C
392 #define PRODUCT_DATACENTER_SERVER_CORE_V 0x00000027
393 #define PRODUCT_DATACENTER_SERVER_V 0x00000025
394 #define PRODUCT_ENTERPRISE 0x00000004
395 #define PRODUCT_ENTERPRISE_E 0x00000046
396 #define PRODUCT_ENTERPRISE_N 0x0000001B
397 #define PRODUCT_ENTERPRISE_SERVER 0x0000000A
398 #define PRODUCT_ENTERPRISE_SERVER_CORE 0x0000000E
399 #define PRODUCT_ENTERPRISE_SERVER_CORE_V 0x00000029
400 #define PRODUCT_ENTERPRISE_SERVER_IA64 0x0000000F
401 #define PRODUCT_ENTERPRISE_SERVER_V 0x00000026
402 #define PRODUCT_HOME_BASIC 0x00000002
403 #define PRODUCT_HOME_BASIC_E 0x00000043
404 #define PRODUCT_HOME_BASIC_N 0x00000005
405 #define PRODUCT_HOME_PREMIUM 0x00000003
406 #define PRODUCT_HOME_PREMIUM_E 0x00000044
407 #define PRODUCT_HOME_PREMIUM_N 0x0000001A
408 #define PRODUCT_HYPERV 0x0000002A
409 #define PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT 0x0000001E
410 #define PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING 0x00000020
411 #define PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY 0x0000001F
412 #define PRODUCT_PROFESSIONAL 0x00000030
413 #define PRODUCT_PROFESSIONAL_E 0x00000045
414 #define PRODUCT_PROFESSIONAL_N 0x00000031
415 #define PRODUCT_SERVER_FOR_SMALLBUSINESS 0x00000018
416 #define PRODUCT_SERVER_FOR_SMALLBUSINESS_V 0x00000023
417 #define PRODUCT_SERVER_FOUNDATION 0x00000021
418 #define PRODUCT_SMALLBUSINESS_SERVER 0x00000009
419 #define PRODUCT_SOLUTION_EMBEDDEDSERVER 0x00000038
420 #define PRODUCT_STANDARD_SERVER 0x00000007
421 #define PRODUCT_STANDARD_SERVER_CORE 0x0000000D
422 #define PRODUCT_STANDARD_SERVER_CORE_V 0x00000028
423 #define PRODUCT_STANDARD_SERVER_V 0x00000024
424 #define PRODUCT_STARTER 0x0000000B
425 #define PRODUCT_STARTER_E 0x00000042
426 #define PRODUCT_STARTER_N 0x0000002F
427 #define PRODUCT_STORAGE_ENTERPRISE_SERVER 0x00000017
428 #define PRODUCT_STORAGE_EXPRESS_SERVER 0x00000014
429 #define PRODUCT_STORAGE_STANDARD_SERVER 0x00000015
430 #define PRODUCT_STORAGE_WORKGROUP_SERVER 0x00000016
431 #define PRODUCT_UNDEFINED 0x00000000
432 #define PRODUCT_ULTIMATE 0x00000001
433 #define PRODUCT_ULTIMATE_E 0x00000047
434 #define PRODUCT_ULTIMATE_N 0x0000001C
435 #define PRODUCT_WEB_SERVER 0x00000011
436 #define PRODUCT_WEB_SERVER_CORE 0x0000001D
437
438 #define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM 0x19
439 #define SM_SERVERR2 89
440 #define VER_SERVER_NT 0x80000000
441
442 #define PRODUCT_CLUSTER_SERVER_V 0x00000040
443 #define PRODUCT_ENTERPRISE_EVALUATION 0x00000048
444 #define PRODUCT_ENTERPRISE_N_EVALUATION 0x00000054
445 #define PRODUCT_HOME_PREMIUM_SERVER 0x00000022
446 #define PRODUCT_HOME_SERVER 0x00000013
447 #define PRODUCT_STORAGE_ENTERPRISE_SERVER_CORE 0x0000002E
448 #define PRODUCT_STORAGE_EXPRESS_SERVER_CORE 0x0000002B
449 #define PRODUCT_STORAGE_STANDARD_SERVER_CORE 0x0000002C
450 #define PRODUCT_STORAGE_STANDARD_EVALUATION_SERVER 0x00000060
451 #define PRODUCT_STORAGE_WORKGROUP_SERVER_CORE 0x0000002D
452 #define PRODUCT_STORAGE_WORKGROUP_EVALUATION_SERVER 0x0000005F
453 #define PRODUCT_CORE 0x00000065
454 #define PRODUCT_CORE_COUNTRYSPECIFIC 0x00000063
455 #define PRODUCT_CORE_N 0x00000062
456 #define PRODUCT_CORE_SINGLELANGUAGE 0x00000064
457 #define PRODUCT_DATACENTER_EVALUATION_SERVER 0x00000050
458 #define PRODUCT_DATACENTER_A_SERVER_CORE 0x00000091
459 #define PRODUCT_STANDARD_A_SERVER_CORE 0x00000092
460 #define PRODUCT_EDUCATION 0x00000079
461 #define PRODUCT_EDUCATION_N 0x0000007A
462 #define PRODUCT_ESSENTIALBUSINESS_SERVER_ADDL 0x0000003C
463 #define PRODUCT_ESSENTIALBUSINESS_SERVER_ADDLSVC 0x0000003E
464 #define PRODUCT_ESSENTIALBUSINESS_SERVER_MGMT 0x0000003B
465 #define PRODUCT_ESSENTIALBUSINESS_SERVER_MGMTSVC 0x0000003D
466 #define PRODUCT_MOBILE_CORE 0x00000068
467 #define PRODUCT_MOBILE_ENTERPRISE 0x00000085
468 #define PRODUCT_MULTIPOINT_PREMIUM_SERVER 0x0000004D
469 #define PRODUCT_MULTIPOINT_STANDARD_SERVER 0x0000004C
470 #define PRODUCT_PRO_WORKSTATION 0x000000A1
471 #define PRODUCT_PRO_WORKSTATION_N 0x000000A2
472 #define PRODUCT_PROFESSIONAL_WMC 0x00000067
473 #define PRODUCT_SB_SOLUTION_SERVER 0x00000032
474 #define PRODUCT_SB_SOLUTION_SERVER_EM 0x00000036
475 #define PRODUCT_SERVER_FOR_SB_SOLUTIONS 0x00000033
476 #define PRODUCT_SERVER_FOR_SB_SOLUTIONS_EM 0x00000037
477 #define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE 0x0000003F
478 #define PRODUCT_STANDARD_EVALUATION_SERVER 0x0000004F
479 #define PRODUCT_STANDARD_SERVER_SOLUTIONS 0x00000034
480 #define PRODUCT_STANDARD_SERVER_SOLUTIONS_CORE 0x00000035
481 #endif
482
483 /* Windows 10 */
484 #ifndef PRODUCT_ENTERPRISE_S
485 #define PRODUCT_ENTERPRISE_S 0x0000007D
486 #define PRODUCT_ENTERPRISE_S_EVALUATION 0x00000081
487 #define PRODUCT_ENTERPRISE_S_N 0x0000007E
488 #define PRODUCT_ENTERPRISE_S_N_EVALUATION 0x00000082
489 #endif
490 #define PRODUCT_IOTUAP 0x0000007B
491 #define PRODUCT_IOTUAPCOMMERCIAL 0x00000083
492
493 #define PRODUCT_DATACENTER_A_SERVER_CORE 0x00000091
494 #define PRODUCT_PRO_WORKSTATION 0x000000A1
495 #define PRODUCT_PRO_WORKSTATION_N 0x000000A2
496 #define PRODUCT_STANDARD_A_SERVER_CORE 0x00000092
497
498
499
500
501 #ifndef PRODUCT_PROFESSIONAL
502 #define PRODUCT_PROFESSIONAL 0x00000030
503 #endif
504 #ifndef VER_SUITE_STORAGE_SERVER
505 #define VER_SUITE_STORAGE_SERVER 0x00002000
506 #endif
507 #ifndef VER_SUITE_COMPUTE_SERVER
508 #define VER_SUITE_COMPUTE_SERVER 0x00004000
509 #endif
510
511 /* Unknown value */
512 #ifndef VER_SUITE_WH_SERVER
513 #define VER_SUITE_WH_SERVER -1
514 #endif
515
516 typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
517 typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);
518
519 /*
520 * Get Windows version display string
521 */
GetWindowsVersionString(LPTSTR osbuf,int maxsiz)522 bool GetWindowsVersionString(LPTSTR osbuf, int maxsiz)
523 {
524 OSVERSIONINFOEX osvi;
525 SYSTEM_INFO si;
526 PGNSI pGNSI;
527 PGPI pGPI;
528 BOOL bOsVersionInfoEx;
529 DWORD dwType;
530
531 memset(&si, 0, sizeof(SYSTEM_INFO));
532 memset(&osvi, 0, sizeof(OSVERSIONINFOEX));
533
534 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
535
536 if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
537 return 1;
538
539 // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.
540
541 pGNSI = (PGNSI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
542 "GetNativeSystemInfo");
543 if (pGNSI) {
544 pGNSI(&si);
545 } else {
546 GetSystemInfo(&si);
547 }
548
549 if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion > 4) {
550 bstrncpy(osbuf, TEXT("Microsoft "), maxsiz);
551
552 // Test for the specific product.
553
554 if (osvi.dwMajorVersion == 10) {
555 if (osvi.dwMinorVersion == 0) {
556 if (osvi.wProductType == VER_NT_WORKSTATION)
557 bstrncat(osbuf, TEXT("Windows 10 "), maxsiz);
558 else
559 bstrncat(osbuf, TEXT("Windows Server 2016 " ), maxsiz);
560 }
561
562 pGPI = (PGPI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
563 "GetProductInfo");
564
565 if (pGPI) {
566 pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);
567 } else {
568 dwType = PRODUCT_HOME_BASIC;
569 }
570
571 switch (dwType) {
572 case PRODUCT_ULTIMATE:
573 bstrncat(osbuf, TEXT("Ultimate Edition" ), maxsiz);
574 break;
575 case PRODUCT_PROFESSIONAL:
576 bstrncat(osbuf, TEXT("Professional" ), maxsiz);
577 break;
578 case PRODUCT_HOME_PREMIUM:
579 bstrncat(osbuf, TEXT("Home Premium Edition" ), maxsiz);
580 break;
581 case PRODUCT_HOME_BASIC:
582 bstrncat(osbuf, TEXT("Home Basic Edition" ), maxsiz);
583 break;
584 case PRODUCT_ENTERPRISE:
585 bstrncat(osbuf, TEXT("Enterprise Edition" ), maxsiz);
586 break;
587 case PRODUCT_BUSINESS:
588 bstrncat(osbuf, TEXT("Business Edition" ), maxsiz);
589 break;
590 case PRODUCT_BUSINESS_N:
591 bstrncat(osbuf, TEXT("Business Edition N" ), maxsiz);
592 break;
593 case PRODUCT_CORE:
594 bstrncat(osbuf, TEXT("Home Edition" ), maxsiz);
595 break;
596 case PRODUCT_CORE_COUNTRYSPECIFIC:
597 bstrncat(osbuf, TEXT("Home China Edition" ), maxsiz);
598 break;
599 case PRODUCT_CORE_N:
600 bstrncat(osbuf, TEXT("Home N Edition" ), maxsiz);
601 break;
602 case PRODUCT_CORE_SINGLELANGUAGE:
603 bstrncat(osbuf, TEXT("Home Single Language Edition" ), maxsiz);
604 break;
605 case PRODUCT_DATACENTER_EVALUATION_SERVER:
606 bstrncat(osbuf, TEXT("Server Datacenter (evaluation installation)" ), maxsiz);
607 break;
608 case PRODUCT_DATACENTER_A_SERVER_CORE:
609 bstrncat(osbuf, TEXT("Server Datacenter, Semi-Annual Channel (core installation)" ), maxsiz);
610 break;
611 case PRODUCT_STANDARD_A_SERVER_CORE:
612 bstrncat(osbuf, TEXT("Server Standard, Semi-Annual Channel (core installation)" ), maxsiz);
613 break;
614 case PRODUCT_DATACENTER_SERVER_CORE_V:
615 bstrncat(osbuf, TEXT("Server Datacenter without Hyper-V (core installation)" ), maxsiz);
616 break;
617 case PRODUCT_DATACENTER_SERVER_V:
618 bstrncat(osbuf, TEXT("Server Datacenter without Hyper-V (full installation)" ), maxsiz);
619 break;
620 case PRODUCT_EDUCATION:
621 bstrncat(osbuf, TEXT("Education" ), maxsiz);
622 break;
623 case PRODUCT_EDUCATION_N:
624 bstrncat(osbuf, TEXT("Education N" ), maxsiz);
625 break;
626 case PRODUCT_ENTERPRISE_E:
627 bstrncat(osbuf, TEXT("Enterprise E" ), maxsiz);
628 break;
629 case PRODUCT_ENTERPRISE_EVALUATION:
630 bstrncat(osbuf, TEXT("Enterprise Evaluation" ), maxsiz);
631 break;
632 case PRODUCT_ENTERPRISE_N:
633 bstrncat(osbuf, TEXT("Enterprise N" ), maxsiz);
634 break;
635 case PRODUCT_ENTERPRISE_N_EVALUATION:
636 bstrncat(osbuf, TEXT("Enterprise N Evaluation" ), maxsiz);
637 break;
638 case PRODUCT_ENTERPRISE_S:
639 bstrncat(osbuf, TEXT("Enterprise 2015 LTSB" ), maxsiz);
640 break;
641 case PRODUCT_ENTERPRISE_S_EVALUATION:
642 bstrncat(osbuf, TEXT("Enterprise 2015 LTSB Evaluation" ), maxsiz);
643 break;
644 case PRODUCT_ENTERPRISE_S_N:
645 bstrncat(osbuf, TEXT("Enterprise 2015 LTSB N" ), maxsiz);
646 break;
647 case PRODUCT_ENTERPRISE_S_N_EVALUATION:
648 bstrncat(osbuf, TEXT("Enterprise 2015 LTSB N Evaluation" ), maxsiz);
649 break;
650 case PRODUCT_ENTERPRISE_SERVER:
651 bstrncat(osbuf, TEXT("Enterprise (full installation)" ), maxsiz);
652 break;
653 case PRODUCT_ENTERPRISE_SERVER_CORE_V:
654 bstrncat(osbuf, TEXT("Server Enterprise without Hyper-V (core installation)" ), maxsiz);
655 break;
656 case PRODUCT_ENTERPRISE_SERVER_IA64:
657 bstrncat(osbuf, TEXT("Server Enterprise for Itanium-based Systems" ), maxsiz);
658 break;
659 case PRODUCT_ENTERPRISE_SERVER_V:
660 bstrncat(osbuf, TEXT("Server Enterprise without Hyper-V (full installation)" ), maxsiz);
661 break;
662 case PRODUCT_ESSENTIALBUSINESS_SERVER_ADDL:
663 bstrncat(osbuf, TEXT("Essential Server Solution Additional" ), maxsiz);
664 break;
665 case PRODUCT_ESSENTIALBUSINESS_SERVER_ADDLSVC:
666 bstrncat(osbuf, TEXT("Essential Server Solution Additional SVC" ), maxsiz);
667 break;
668 case PRODUCT_ESSENTIALBUSINESS_SERVER_MGMT:
669 bstrncat(osbuf, TEXT("Essential Server Solution Management" ), maxsiz);
670 break;
671 case PRODUCT_ESSENTIALBUSINESS_SERVER_MGMTSVC:
672 bstrncat(osbuf, TEXT("Essential Server Solution Management SVC" ), maxsiz);
673 break;
674 case PRODUCT_HOME_BASIC_E:
675 bstrncat(osbuf, TEXT("Not supported" ), maxsiz);
676 break;
677 case PRODUCT_HOME_BASIC_N:
678 bstrncat(osbuf, TEXT("Home Basic N" ), maxsiz);
679 break;
680 case PRODUCT_HOME_PREMIUM_E:
681 bstrncat(osbuf, TEXT("Not supported" ), maxsiz);
682 break;
683 case PRODUCT_HOME_PREMIUM_N:
684 bstrncat(osbuf, TEXT("Home Premium N" ), maxsiz);
685 break;
686 case PRODUCT_HOME_PREMIUM_SERVER:
687 bstrncat(osbuf, TEXT("Home Server 2011" ), maxsiz);
688 break;
689 case PRODUCT_HOME_SERVER:
690 bstrncat(osbuf, TEXT("Storage Server 2008 R2 Essentials" ), maxsiz);
691 break;
692 case PRODUCT_HYPERV:
693 bstrncat(osbuf, TEXT("Hyper-V Server" ), maxsiz);
694 break;
695 case PRODUCT_IOTUAP:
696 bstrncat(osbuf, TEXT("IoT Core" ), maxsiz);
697 break;
698 case PRODUCT_IOTUAPCOMMERCIAL:
699 bstrncat(osbuf, TEXT("IoT Core Commercial" ), maxsiz);
700 break;
701 case PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT:
702 bstrncat(osbuf, TEXT("Essential Business Server Management Server" ), maxsiz);
703 break;
704 case PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING:
705 bstrncat(osbuf, TEXT("Essential Business Server Messaging Server" ), maxsiz);
706 break;
707 case PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY:
708 bstrncat(osbuf, TEXT("Essential Business Server Security Server" ), maxsiz);
709 break;
710 case PRODUCT_MOBILE_CORE:
711 bstrncat(osbuf, TEXT("Mobile" ), maxsiz);
712 break;
713 case PRODUCT_MOBILE_ENTERPRISE:
714 bstrncat(osbuf, TEXT("Mobile Enterprise" ), maxsiz);
715 break;
716 case PRODUCT_MULTIPOINT_PREMIUM_SERVER:
717 bstrncat(osbuf, TEXT("MultiPoint Server Premium (full installation)" ), maxsiz);
718 break;
719 case PRODUCT_MULTIPOINT_STANDARD_SERVER:
720 bstrncat(osbuf, TEXT("MultiPoint Server Standard (full installation)" ), maxsiz);
721 break;
722 case PRODUCT_PRO_WORKSTATION:
723 bstrncat(osbuf, TEXT("Pro for Workstations" ), maxsiz);
724 break;
725 case PRODUCT_PRO_WORKSTATION_N:
726 bstrncat(osbuf, TEXT("Pro for Workstations N" ), maxsiz);
727 break;
728 case PRODUCT_PROFESSIONAL_E:
729 bstrncat(osbuf, TEXT("Not supported" ), maxsiz);
730 break;
731 case PRODUCT_PROFESSIONAL_N:
732 bstrncat(osbuf, TEXT("Pro N" ), maxsiz);
733 break;
734 case PRODUCT_PROFESSIONAL_WMC:
735 bstrncat(osbuf, TEXT("Professional with Media Center" ), maxsiz);
736 break;
737 case PRODUCT_SB_SOLUTION_SERVER:
738 bstrncat(osbuf, TEXT("Small Business Server 2011 Essentials" ), maxsiz);
739 break;
740 case PRODUCT_SB_SOLUTION_SERVER_EM:
741 bstrncat(osbuf, TEXT("Server For SB Solutions EM" ), maxsiz);
742 break;
743 case PRODUCT_SERVER_FOR_SB_SOLUTIONS:
744 bstrncat(osbuf, TEXT("Server For SB Solutions" ), maxsiz);
745 break;
746 case PRODUCT_SERVER_FOR_SB_SOLUTIONS_EM:
747 bstrncat(osbuf, TEXT("Server For SB Solutions EM" ), maxsiz);
748 break;
749 case PRODUCT_SERVER_FOR_SMALLBUSINESS:
750 bstrncat(osbuf, TEXT("for Windows Essential Server Solutions" ), maxsiz);
751 break;
752 case PRODUCT_SERVER_FOR_SMALLBUSINESS_V:
753 bstrncat(osbuf, TEXT("without Hyper-V for Windows Essential Server Solutions" ), maxsiz);
754 break;
755 case PRODUCT_SERVER_FOUNDATION:
756 bstrncat(osbuf, TEXT("Server Foundation" ), maxsiz);
757 break;
758 case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE:
759 bstrncat(osbuf, TEXT("Small Business Server Premium (core installation)" ), maxsiz);
760 break;
761 case PRODUCT_SOLUTION_EMBEDDEDSERVER:
762 bstrncat(osbuf, TEXT("Windows MultiPoint Server" ), maxsiz);
763 break;
764 case PRODUCT_STANDARD_EVALUATION_SERVER:
765 bstrncat(osbuf, TEXT("Server Standard (evaluation installation)" ), maxsiz);
766 break;
767 case PRODUCT_STANDARD_SERVER_CORE_V:
768 bstrncat(osbuf, TEXT("Server Standard without Hyper-V" ), maxsiz);
769 break;
770 case PRODUCT_STANDARD_SERVER_SOLUTIONS:
771 bstrncat(osbuf, TEXT("Server Solutions Premium" ), maxsiz);
772 break;
773 case PRODUCT_STANDARD_SERVER_SOLUTIONS_CORE:
774 bstrncat(osbuf, TEXT("Server Solutions Premium (core installation)" ), maxsiz);
775 break;
776 case PRODUCT_STARTER_E:
777 bstrncat(osbuf, TEXT("Not supported" ), maxsiz);
778 break;
779 case PRODUCT_STARTER_N:
780 bstrncat(osbuf, TEXT("Starter N" ), maxsiz);
781 break;
782 case PRODUCT_STORAGE_ENTERPRISE_SERVER:
783 bstrncat(osbuf, TEXT("Storage Server Enterprise" ), maxsiz);
784 break;
785 case PRODUCT_STORAGE_ENTERPRISE_SERVER_CORE:
786 bstrncat(osbuf, TEXT("Storage Server Enterprise (core installation)" ), maxsiz);
787 break;
788 case PRODUCT_STORAGE_EXPRESS_SERVER:
789 bstrncat(osbuf, TEXT("Storage Server Express" ), maxsiz);
790 break;
791 case PRODUCT_STORAGE_EXPRESS_SERVER_CORE:
792 bstrncat(osbuf, TEXT("Storage Server Express (core installation)" ), maxsiz);
793 break;
794 case PRODUCT_STORAGE_STANDARD_EVALUATION_SERVER:
795 bstrncat(osbuf, TEXT("Storage Server Standard (evaluation installation)" ), maxsiz);
796 break;
797 case PRODUCT_STORAGE_STANDARD_SERVER:
798 bstrncat(osbuf, TEXT("Storage Server Standard" ), maxsiz);
799 break;
800 case PRODUCT_STORAGE_STANDARD_SERVER_CORE:
801 bstrncat(osbuf, TEXT("Storage Server Standard (core installation)" ), maxsiz);
802 break;
803 case PRODUCT_STORAGE_WORKGROUP_EVALUATION_SERVER:
804 bstrncat(osbuf, TEXT("Storage Server Workgroup (evaluation installation)" ), maxsiz);
805 break;
806 case PRODUCT_STORAGE_WORKGROUP_SERVER:
807 bstrncat(osbuf, TEXT("Storage Server Workgroup" ), maxsiz);
808 break;
809 case PRODUCT_STORAGE_WORKGROUP_SERVER_CORE:
810 bstrncat(osbuf, TEXT("Storage Server Workgroup (core installation)" ), maxsiz);
811 break;
812 case PRODUCT_ULTIMATE_E:
813 bstrncat(osbuf, TEXT("Not supported" ), maxsiz);
814 break;
815 case PRODUCT_ULTIMATE_N:
816 bstrncat(osbuf, TEXT("Ultimate N" ), maxsiz);
817 break;
818 case PRODUCT_UNDEFINED:
819 bstrncat(osbuf, TEXT("Unknown product" ), maxsiz);
820 break;
821 case PRODUCT_WEB_SERVER_CORE:
822 bstrncat(osbuf, TEXT("Web Server (core installation)" ), maxsiz);
823 break;
824 case PRODUCT_STARTER:
825 bstrncat(osbuf, TEXT("Starter Edition" ), maxsiz);
826 break;
827 case PRODUCT_CLUSTER_SERVER_V:
828 bstrncat(osbuf, TEXT("Server Hyper Core V" ), maxsiz);
829 break;
830 case PRODUCT_CLUSTER_SERVER:
831 bstrncat(osbuf, TEXT("Cluster Server Edition" ), maxsiz);
832 break;
833 case PRODUCT_DATACENTER_SERVER:
834 bstrncat(osbuf, TEXT("Datacenter Edition" ), maxsiz);
835 break;
836 case PRODUCT_DATACENTER_SERVER_CORE:
837 bstrncat(osbuf, TEXT("Datacenter Edition (core installation)" ), maxsiz);
838 break;
839 case PRODUCT_ENTERPRISE_SERVER_CORE:
840 bstrncat(osbuf, TEXT("Enterprise Edition (core installation)" ), maxsiz);
841 break;
842 case PRODUCT_SMALLBUSINESS_SERVER:
843 bstrncat(osbuf, TEXT("Small Business Server" ), maxsiz);
844 break;
845 case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
846 bstrncat(osbuf, TEXT("Small Business Server Premium Edition" ), maxsiz);
847 break;
848 case PRODUCT_STANDARD_SERVER:
849 bstrncat(osbuf, TEXT("Standard Edition" ), maxsiz);
850 break;
851 case PRODUCT_STANDARD_SERVER_CORE:
852 bstrncat(osbuf, TEXT("Standard Edition (core installation)" ), maxsiz);
853 break;
854 case PRODUCT_WEB_SERVER:
855 bstrncat(osbuf, TEXT("Web Server Edition" ), maxsiz);
856 break;
857 }
858 }
859 if (osvi.dwMajorVersion == 6) {
860 if (osvi.dwMinorVersion == 0) {
861 if (osvi.wProductType == VER_NT_WORKSTATION)
862 bstrncat(osbuf, TEXT("Windows Vista "), maxsiz);
863 else
864 bstrncat(osbuf, TEXT("Windows Server 2008 " ), maxsiz);
865 }
866
867 if (osvi.dwMinorVersion == 1) {
868 if (osvi.wProductType == VER_NT_WORKSTATION )
869 bstrncat(osbuf, TEXT("Windows 7 "), maxsiz);
870 else
871 bstrncat(osbuf, TEXT("Windows Server 2008 R2 " ), maxsiz);
872 }
873 if (osvi.dwMinorVersion == 2) {
874 if (osvi.wProductType == VER_NT_WORKSTATION )
875 bstrncat(osbuf, TEXT("Windows 8 "), maxsiz);
876 else
877 bstrncat(osbuf, TEXT("Windows Server 2012 " ), maxsiz);
878 }
879 if (osvi.dwMinorVersion == 3) {
880 if (osvi.wProductType == VER_NT_WORKSTATION )
881 bstrncat(osbuf, TEXT("Windows 8.1 "), maxsiz);
882 else
883 bstrncat(osbuf, TEXT("Windows Server 2012 RC2 " ), maxsiz);
884 }
885
886 pGPI = (PGPI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
887 "GetProductInfo");
888
889 if (pGPI) {
890 pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);
891 } else {
892 dwType = PRODUCT_HOME_BASIC;
893 }
894
895 switch (dwType) {
896 case PRODUCT_ULTIMATE:
897 bstrncat(osbuf, TEXT("Ultimate Edition" ), maxsiz);
898 break;
899 case PRODUCT_PROFESSIONAL:
900 bstrncat(osbuf, TEXT("Professional" ), maxsiz);
901 break;
902 case PRODUCT_HOME_PREMIUM:
903 bstrncat(osbuf, TEXT("Home Premium Edition" ), maxsiz);
904 break;
905 case PRODUCT_HOME_BASIC:
906 bstrncat(osbuf, TEXT("Home Basic Edition" ), maxsiz);
907 break;
908 case PRODUCT_ENTERPRISE:
909 bstrncat(osbuf, TEXT("Enterprise Edition" ), maxsiz);
910 break;
911 case PRODUCT_BUSINESS:
912 bstrncat(osbuf, TEXT("Business Edition" ), maxsiz);
913 break;
914 case PRODUCT_STARTER:
915 bstrncat(osbuf, TEXT("Starter Edition" ), maxsiz);
916 break;
917 case PRODUCT_CLUSTER_SERVER:
918 bstrncat(osbuf, TEXT("Cluster Server Edition" ), maxsiz);
919 break;
920 case PRODUCT_DATACENTER_SERVER:
921 bstrncat(osbuf, TEXT("Datacenter Edition" ), maxsiz);
922 break;
923 case PRODUCT_DATACENTER_SERVER_CORE:
924 bstrncat(osbuf, TEXT("Datacenter Edition (core installation)" ), maxsiz);
925 break;
926 case PRODUCT_ENTERPRISE_SERVER:
927 bstrncat(osbuf, TEXT("Enterprise Edition" ), maxsiz);
928 break;
929 case PRODUCT_ENTERPRISE_SERVER_CORE:
930 bstrncat(osbuf, TEXT("Enterprise Edition (core installation)" ), maxsiz);
931 break;
932 case PRODUCT_ENTERPRISE_SERVER_IA64:
933 bstrncat(osbuf, TEXT("Enterprise Edition for Itanium-based Systems" ), maxsiz);
934 break;
935 case PRODUCT_SMALLBUSINESS_SERVER:
936 bstrncat(osbuf, TEXT("Small Business Server" ), maxsiz);
937 break;
938 case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
939 bstrncat(osbuf, TEXT("Small Business Server Premium Edition" ), maxsiz);
940 break;
941 case PRODUCT_STANDARD_SERVER:
942 bstrncat(osbuf, TEXT("Standard Edition" ), maxsiz);
943 break;
944 case PRODUCT_STANDARD_SERVER_CORE:
945 bstrncat(osbuf, TEXT("Standard Edition (core installation)" ), maxsiz);
946 break;
947 case PRODUCT_WEB_SERVER:
948 bstrncat(osbuf, TEXT("Web Server Edition" ), maxsiz);
949 break;
950 }
951 }
952
953 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) {
954 if( GetSystemMetrics(SM_SERVERR2) )
955 bstrncat(osbuf, TEXT( "Windows Server 2003 R2 "), maxsiz);
956 else if (osvi.wSuiteMask & VER_SUITE_STORAGE_SERVER)
957 bstrncat(osbuf, TEXT( "Windows Storage Server 2003"), maxsiz);
958 else if (osvi.wSuiteMask & VER_SUITE_WH_SERVER )
959 bstrncat(osbuf, TEXT( "Windows Home Server"), maxsiz);
960 else if (osvi.wProductType == VER_NT_WORKSTATION &&
961 si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
962 bstrncat(osbuf, TEXT( "Windows XP Professional x64 Edition"), maxsiz);
963 else
964 bstrncat(osbuf, TEXT("Windows Server 2003 "), maxsiz);
965
966 // Test for the server type.
967 if (osvi.wProductType != VER_NT_WORKSTATION) {
968 if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64) {
969 if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
970 bstrncat(osbuf, TEXT( "Datacenter Edition for Itanium-based Systems" ), maxsiz);
971 else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
972 bstrncat(osbuf, TEXT( "Enterprise Edition for Itanium-based Systems" ), maxsiz);
973 }
974
975 else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) {
976 if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
977 bstrncat(osbuf, TEXT( "Datacenter x64 Edition" ), maxsiz);
978 else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
979 bstrncat(osbuf, TEXT( "Enterprise x64 Edition" ), maxsiz);
980 else bstrncat(osbuf, TEXT( "Standard x64 Edition" ), maxsiz);
981 } else {
982 if ( osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER )
983 bstrncat(osbuf, TEXT( "Compute Cluster Edition" ), maxsiz);
984 else if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
985 bstrncat(osbuf, TEXT( "Datacenter Edition" ), maxsiz);
986 else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
987 bstrncat(osbuf, TEXT( "Enterprise Edition" ), maxsiz);
988 else if ( osvi.wSuiteMask & VER_SUITE_BLADE )
989 bstrncat(osbuf, TEXT( "Web Edition" ), maxsiz);
990 else bstrncat(osbuf, TEXT( "Standard Edition" ), maxsiz);
991 }
992 }
993 }
994
995 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
996 bstrncat(osbuf, TEXT("Windows XP "), maxsiz);
997 if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
998 bstrncat(osbuf, TEXT( "Home Edition" ), maxsiz);
999 else
1000 bstrncat(osbuf, TEXT( "Professional" ), maxsiz);
1001 }
1002
1003 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) {
1004 bstrncat(osbuf, TEXT("Windows 2000 "), maxsiz);
1005 if ( osvi.wProductType == VER_NT_WORKSTATION ) {
1006 bstrncat(osbuf, TEXT( "Professional" ), maxsiz);
1007 } else {
1008 if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
1009 bstrncat(osbuf, TEXT( "Datacenter Server" ), maxsiz);
1010 else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
1011 bstrncat(osbuf, TEXT( "Advanced Server" ), maxsiz);
1012 else bstrncat(osbuf, TEXT( "Server" ), maxsiz);
1013 }
1014 }
1015
1016 // Include service pack (if any) and build number.
1017
1018 if (_tcslen(osvi.szCSDVersion) > 0) {
1019 bstrncat(osbuf, TEXT(" ") , maxsiz);
1020 bstrncat(osbuf, osvi.szCSDVersion, maxsiz);
1021 }
1022
1023 char buf[80];
1024
1025 snprintf(buf, 80, " (build %d)", (int)osvi.dwBuildNumber);
1026 bstrncat(osbuf, buf, maxsiz);
1027
1028 if (osvi.dwMajorVersion >= 6) {
1029 if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
1030 bstrncat(osbuf, TEXT( ", 64-bit" ), maxsiz);
1031 else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL )
1032 bstrncat(osbuf, TEXT(", 32-bit"), maxsiz);
1033 }
1034
1035 return true;
1036 } else {
1037 bstrncpy(osbuf, "Unknown Windows version.", maxsiz);
1038 return true;
1039 }
1040 }
1041