Changeset 43850 in vbox
- Timestamp:
- Nov 9, 2012 1:28:58 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Installer/win/Stub/VBoxStub.cpp
r39613 r43850 36 36 #include <iprt/file.h> 37 37 #include <iprt/initterm.h> 38 #include <iprt/getopt.h> 38 39 #include <iprt/mem.h> 40 #include <iprt/message.h> 39 41 #include <iprt/path.h> 40 42 #include <iprt/param.h> 43 #include <iprt/stream.h> 41 44 #include <iprt/string.h> 42 45 #include <iprt/thread.h> … … 51 54 52 55 53 /** 54 * Shows a message box with a printf() style formatted string. 55 * 56 * @returns Message box result (IDOK, IDCANCEL, ...). 57 * 58 * @param uType Type of the message box (see MSDN). 56 /******************************************************************************* 57 * Global Variables * 58 *******************************************************************************/ 59 static bool g_fSilent = false; 60 61 62 /** 63 * Shows an error message box with a printf() style formatted string. 64 * 59 65 * @param pszFmt Printf-style format string to show in the message box body. 60 66 * 61 67 */ 62 static int ShowInfo(const char *pszFmt, ...)68 static void ShowError(const char *pszFmt, ...) 63 69 { 64 70 char *pszMsg; … … 66 72 67 73 va_start(va, pszFmt); 68 RTStrAPrintfV(&pszMsg, pszFmt, va);69 va_end(va);70 71 int rc;72 if (pszMsg)73 rc = MessageBox(GetDesktopWindow(), pszMsg, VBOX_STUB_TITLE, MB_ICONINFORMATION);74 else75 rc = MessageBox(GetDesktopWindow(), pszFmt, VBOX_STUB_TITLE, MB_ICONINFORMATION);76 RTStrFree(pszMsg);77 return rc;78 }79 80 81 /**82 * Shows an error message box with a printf() style formatted string.83 *84 * @returns Message box result (IDOK, IDCANCEL, ...).85 *86 * @param pszFmt Printf-style format string to show in the message box body.87 *88 */89 static int ShowError(const char *pszFmt, ...)90 {91 char *pszMsg;92 va_list va;93 int rc;94 95 va_start(va, pszFmt);96 74 if (RTStrAPrintfV(&pszMsg, pszFmt, va)) 97 75 { 98 rc = MessageBox(GetDesktopWindow(), pszMsg, VBOX_STUB_TITLE, MB_ICONERROR); 76 if (g_fSilent) 77 RTMsgError("%s", pszMsg); 78 else 79 MessageBox(GetDesktopWindow(), pszMsg, VBOX_STUB_TITLE, MB_ICONERROR); 99 80 RTStrFree(pszMsg); 100 81 } … … 102 83 AssertMsgFailed(("Failed to format error text of format string: %s!\n", pszFmt)); 103 84 va_end(va); 104 return rc; 85 } 86 87 88 /** 89 * Shows a message box with a printf() style formatted string. 90 * 91 * @param uType Type of the message box (see MSDN). 92 * @param pszFmt Printf-style format string to show in the message box body. 93 * 94 */ 95 static void ShowInfo(const char *pszFmt, ...) 96 { 97 char *pszMsg; 98 va_list va; 99 va_start(va, pszFmt); 100 int rc = RTStrAPrintfV(&pszMsg, pszFmt, va); 101 va_end(va); 102 if (rc >= 0) 103 { 104 if (g_fSilent) 105 RTPrintf("%s\n", pszMsg); 106 else 107 MessageBox(GetDesktopWindow(), pszMsg, VBOX_STUB_TITLE, MB_ICONINFORMATION); 108 } 109 else /* Should never happen! */ 110 AssertMsgFailed(("Failed to format error text of format string: %s!\n", pszFmt)); 111 RTStrFree(pszMsg); 105 112 } 106 113 … … 316 323 s.pTo = szDest; 317 324 s.pFrom = szSource; 318 s.fFlags = FOF_SILENT |319 FOF_NOCONFIRMATION |320 FOF_NOCONFIRMMKDIR |321 325 s.fFlags = FOF_SILENT 326 | FOF_NOCONFIRMATION 327 | FOF_NOCONFIRMMKDIR 328 | FOF_NOERRORUI; 322 329 } 323 330 return RTErrConvertFromWin32(SHFileOperation(&s)); … … 335 342 /* Check if we're already running and jump out if so. */ 336 343 /* Do not use a global namespace ("Global\\") for mutex name here, will blow up NT4 compatibility! */ 337 HANDLE hMutexAppRunning = CreateMutex 344 HANDLE hMutexAppRunning = CreateMutex(NULL, FALSE, "VBoxStubInstaller"); 338 345 if ( (hMutexAppRunning != NULL) 339 346 && (GetLastError() == ERROR_ALREADY_EXISTS)) … … 350 357 return vrc; 351 358 352 BOOL fExtractOnly = FALSE; 353 BOOL fSilent = FALSE; 354 BOOL fEnableLogging = FALSE; 355 BOOL fExit = FALSE; 356 357 /* Temp variables for arguments. */ 359 /* 360 * Parse arguments. 361 */ 362 363 /* Parameter variables. */ 364 bool fExtractOnly = false; 365 bool fEnableLogging = false; 358 366 char szExtractPath[RTPATH_MAX] = {0}; 359 char szMSIArgs[RTPATH_MAX] = {0}; 360 361 /* Process arguments. */ 362 for (int i = 0; i < argc; i++) 363 { 364 if ( (0 == RTStrICmp(argv[i], "-x")) 365 || (0 == RTStrICmp(argv[i], "-extract")) 366 || (0 == RTStrICmp(argv[i], "/extract"))) 367 { 368 fExtractOnly = TRUE; 369 } 370 371 else if ( (0 == RTStrICmp(argv[i], "-s")) 372 || (0 == RTStrICmp(argv[i], "-silent")) 373 || (0 == RTStrICmp(argv[i], "/silent"))) 374 { 375 fSilent = TRUE; 376 } 377 378 else if ( (0 == RTStrICmp(argv[i], "-l")) 379 || (0 == RTStrICmp(argv[i], "-logging")) 380 || (0 == RTStrICmp(argv[i], "/logging"))) 381 { 382 fEnableLogging = TRUE; 383 } 384 385 else if (( (0 == RTStrICmp(argv[i], "-p")) 386 || (0 == RTStrICmp(argv[i], "-path")) 387 || (0 == RTStrICmp(argv[i], "/path"))) 388 ) 389 { 390 if (argc > i) 391 { 392 vrc = ::StringCbCat(szExtractPath, sizeof(szExtractPath), argv[i+1]); 393 i++; /* Avoid the specified path from being parsed. */ 394 } 395 else 396 { 397 ShowError("No path for extraction specified!"); 398 fExit = TRUE; 399 } 400 } 401 402 else if (( (0 == RTStrICmp(argv[i], "-msiparams")) 403 || (0 == RTStrICmp(argv[i], "/msiparams"))) 404 && (argc > i)) 405 { 406 for (int a = i + 1; a < argc; a++) 407 { 408 if (a > i+1) /* Insert a space. */ 409 vrc = ::StringCbCat(szMSIArgs, sizeof(szMSIArgs), " "); 410 411 vrc = ::StringCbCat(szMSIArgs, sizeof(szMSIArgs), argv[a]); 412 } 413 } 414 415 else if ( (0 == RTStrICmp(argv[i], "-v")) 416 || (0 == RTStrICmp(argv[i], "-version")) 417 || (0 == RTStrICmp(argv[i], "/version"))) 418 { 419 ShowInfo("Version: %d.%d.%d.%d", 420 VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV); 421 fExit = TRUE; 422 } 423 424 else if ( (0 == RTStrICmp(argv[i], "-help")) 425 || (0 == RTStrICmp(argv[i], "/help")) 426 || (0 == RTStrICmp(argv[i], "/?"))) 427 { 428 ShowInfo("-- %s v%d.%d.%d.%d --\n" 367 char szMSIArgs[4096] = {0}; 368 369 /* Parameter definitions. */ 370 static const RTGETOPTDEF s_aOptions[] = 371 { 372 { "--extract", 'x', RTGETOPT_REQ_NOTHING }, 373 { "-extract", 'x', RTGETOPT_REQ_NOTHING }, 374 { "/extract", 'x', RTGETOPT_REQ_NOTHING }, 375 { "--silent", 's', RTGETOPT_REQ_NOTHING }, 376 { "-silent", 's', RTGETOPT_REQ_NOTHING }, 377 { "/silent", 's', RTGETOPT_REQ_NOTHING }, 378 { "--logging", 'l', RTGETOPT_REQ_NOTHING }, 379 { "-logging", 'l', RTGETOPT_REQ_NOTHING }, 380 { "/logging", 'l', RTGETOPT_REQ_NOTHING }, 381 { "--path", 'p', RTGETOPT_REQ_STRING }, 382 { "-path", 'p', RTGETOPT_REQ_STRING }, 383 { "/path", 'p', RTGETOPT_REQ_STRING }, 384 { "--msiparams", 'm', RTGETOPT_REQ_STRING }, 385 { "-msiparams", 'm', RTGETOPT_REQ_STRING }, 386 { "--version", 'V', RTGETOPT_REQ_NOTHING }, 387 { "-version", 'V', RTGETOPT_REQ_NOTHING }, 388 { "/version", 'V', RTGETOPT_REQ_NOTHING }, 389 { "-v", 'V', RTGETOPT_REQ_NOTHING }, 390 { "--help", 'h', RTGETOPT_REQ_NOTHING }, 391 { "-help", 'h', RTGETOPT_REQ_NOTHING }, 392 { "/help", 'h', RTGETOPT_REQ_NOTHING }, 393 { "/?", 'h', RTGETOPT_REQ_NOTHING }, 394 }; 395 396 /* Parse the parameters. */ 397 int ch; 398 RTGETOPTUNION ValueUnion; 399 RTGETOPTSTATE GetState; 400 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); 401 while ((ch = RTGetOpt(&GetState, &ValueUnion))) 402 { 403 switch (ch) 404 { 405 case 'x': 406 fExtractOnly = true; 407 break; 408 409 case 's': 410 g_fSilent = true; 411 break; 412 413 case 'l': 414 fEnableLogging = true; 415 break; 416 417 case 'p': 418 vrc = RTStrCopy(szExtractPath, sizeof(szExtractPath), ValueUnion.psz); 419 if (RT_FAILURE(vrc)) 420 { 421 ShowError("Extraction path is too long."); 422 return RTEXITCODE_FAILURE; 423 } 424 break; 425 426 case 'm': 427 if (szMSIArgs[0]) 428 vrc = RTStrCat(szMSIArgs, sizeof(szMSIArgs), " "); 429 if (RT_SUCCESS(vrc)) 430 vrc = RTStrCat(szMSIArgs, sizeof(szMSIArgs), ValueUnion.psz); 431 if (RT_FAILURE(vrc)) 432 { 433 ShowError("MSI parameters are too long."); 434 return RTEXITCODE_FAILURE; 435 } 436 break; 437 438 case 'V': 439 ShowInfo("Version: %d.%d.%d.%d", 440 VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV); 441 return VINF_SUCCESS; 442 443 case 'h': 444 ShowInfo("-- %s v%d.%d.%d.%d --\n" 429 445 "Command Line Parameters:\n\n" 430 "- extract | -x- Extract file contents to temporary directory\n"431 "- silent | -s- Enables silent mode installation\n"432 "- path | -p- Sets the path of the extraction directory\n"433 "- help | /? - Print this help and exit\n"434 "- msiparams <parameters> - Specifies extra parameters for the MSI installers\n"435 "- logging | -l - Enables installer logging\n"436 "- version | -v- Print version number and exit\n\n"446 "--extract - Extract file contents to temporary directory\n" 447 "--silent - Enables silent mode installation\n" 448 "--path - Sets the path of the extraction directory\n" 449 "--msiparams <parameters> - Specifies extra parameters for the MSI installers\n" 450 "--logging - Enables installer logging\n" 451 "--help - Print this help and exit\n" 452 "--version - Print version number and exit\n\n" 437 453 "Examples:\n" 438 "%s - msiparams INSTALLDIR=C:\\VBox\n"439 "%s - extract -path C:\\VBox\n",454 "%s --msiparams INSTALLDIR=C:\\VBox\n" 455 "%s --extract -path C:\\VBox", 440 456 VBOX_STUB_TITLE, VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV, 441 457 argv[0], argv[0]); 442 fExit = TRUE; 443 } 444 else 445 { 446 if (i > 0) 447 { 448 ShowError("Unknown option \"%s\"!\n" 449 "Please refer to the command line help by specifying \"/?\"\n" 450 "to get more information.", argv[i]); 451 fExit = TRUE; 452 } 453 } 454 } 455 456 if (fExit) 457 return 0; 458 return VINF_SUCCESS; 459 460 default: 461 if (g_fSilent) 462 return RTGetOptPrintError(ch, &ValueUnion); 463 if (ch == VINF_GETOPT_NOT_OPTION || ch == VERR_GETOPT_UNKNOWN_OPTION) 464 ShowError("Unknown option \"%s\"!\n" 465 "Please refer to the command line help by specifying \"/?\"\n" 466 "to get more information.", ValueUnion.psz); 467 else 468 ShowError("Parameter parsing error: %Rrc\n" 469 "Please refer to the command line help by specifying \"/?\"\n" 470 "to get more information.", ch); 471 return RTEXITCODE_SYNTAX; 472 473 } 474 } 458 475 459 476 HRESULT hr = S_OK; … … 551 568 { 552 569 /* Set UI level. */ 553 INSTALLUILEVEL UILevel = MsiSetInternalUI( fSilent570 INSTALLUILEVEL UILevel = MsiSetInternalUI( g_fSilent 554 571 ? INSTALLUILEVEL_NONE 555 572 : INSTALLUILEVEL_FULL, … … 585 602 && (uStatus != ERROR_INSTALL_USEREXIT)) 586 603 { 587 if (!fSilent)604 switch (uStatus) 588 605 { 589 switch (uStatus) 606 case ERROR_INSTALL_PACKAGE_VERSION: 607 ShowError("This installation package cannot be installed by the Windows Installer service.\n" 608 "You must install a Windows service pack that contains a newer version of the Windows Installer service."); 609 break; 610 611 case ERROR_INSTALL_PLATFORM_UNSUPPORTED: 612 ShowError("This installation package is not supported on this platform."); 613 break; 614 615 default: 590 616 { 591 case ERROR_INSTALL_PACKAGE_VERSION: 592 593 ShowError("This installation package cannot be installed by the Windows Installer service.\n" 594 "You must install a Windows service pack that contains a newer version of the Windows Installer service."); 595 break; 596 597 case ERROR_INSTALL_PLATFORM_UNSUPPORTED: 598 599 ShowError("This installation package is not supported on this platform."); 600 break; 601 602 default: 617 DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER 618 | FORMAT_MESSAGE_IGNORE_INSERTS 619 | FORMAT_MESSAGE_FROM_SYSTEM; 620 HMODULE hModule = NULL; 621 if (uStatus >= NERR_BASE && uStatus <= MAX_NERR) 603 622 { 604 DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER 605 | FORMAT_MESSAGE_IGNORE_INSERTS 606 | FORMAT_MESSAGE_FROM_SYSTEM; 607 HMODULE hModule = NULL; 608 if (uStatus >= NERR_BASE && uStatus <= MAX_NERR) 609 { 610 hModule = LoadLibraryEx(TEXT("netmsg.dll"), 611 NULL, 612 LOAD_LIBRARY_AS_DATAFILE); 613 if (hModule != NULL) 614 dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE; 615 } 616 617 DWORD dwBufferLength; 618 LPSTR szMessageBuffer; 619 if (dwBufferLength = FormatMessageA(dwFormatFlags, 620 hModule, /* If NULL, load system stuff. */ 621 uStatus, 622 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 623 (LPSTR)&szMessageBuffer, 624 0, 625 NULL)) 626 { 627 ShowError("Installation failed! Error: %s", szMessageBuffer); 628 LocalFree(szMessageBuffer); 629 } 630 else /* If text lookup failed, show at least the error number. */ 631 ShowError("Installation failed! Error: %u", uStatus); 632 if (hModule) 633 FreeLibrary(hModule); 634 break; 623 hModule = LoadLibraryEx(TEXT("netmsg.dll"), 624 NULL, 625 LOAD_LIBRARY_AS_DATAFILE); 626 if (hModule != NULL) 627 dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE; 635 628 } 629 630 DWORD dwBufferLength; 631 LPSTR szMessageBuffer; 632 if (dwBufferLength = FormatMessageA(dwFormatFlags, 633 hModule, /* If NULL, load system stuff. */ 634 uStatus, 635 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 636 (LPSTR)&szMessageBuffer, 637 0, 638 NULL)) 639 { 640 ShowError("Installation failed! Error: %s", szMessageBuffer); 641 LocalFree(szMessageBuffer); 642 } 643 else /* If text lookup failed, show at least the error number. */ 644 ShowError("Installation failed! Error: %u", uStatus); 645 if (hModule) 646 FreeLibrary(hModule); 647 break; 636 648 } 637 649 } … … 663 675 { 664 676 if ( fExtractOnly 665 && ! fSilent)677 && !g_fSilent) 666 678 { 667 679 ShowInfo("Files were extracted to: %s", szExtractPath);
Note:
See TracChangeset
for help on using the changeset viewer.