Changeset 80569 in vbox for trunk/src/VBox/Frontends/VBoxAutostart
- Timestamp:
- Sep 3, 2019 2:34:21 PM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 133086
- Location:
- trunk/src/VBox/Frontends/VBoxAutostart
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxAutostart/Makefile.kmk
r76553 r80569 22 22 PROGRAMS += VBoxAutostartSvc 23 23 VBoxAutostartSvc_TEMPLATE = VBOXMAINCLIENTEXE 24 VBoxAutostartSvc_INCS = ../Common 24 25 VBoxAutostartSvc_SOURCES = \ 25 26 VBoxAutostartCfg.cpp \ … … 27 28 VBoxAutostartStop.cpp \ 28 29 VBoxAutostartUtils.cpp \ 29 VBoxAutostart-win.cpp 30 VBoxAutostart-win.cpp \ 31 ../Common/PasswordInput.cpp 32 VBoxAutostartSvc_LIBS.win += Secur32.lib 30 33 else 31 34 PROGRAMS += VBoxAutostart -
trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart-win.cpp
r76553 r80569 23 23 #include <tchar.h> 24 24 25 #define SECURITY_WIN32 26 #include <Security.h> 27 28 #include <VBox/com/array.h> 25 29 #include <VBox/com/com.h> 26 #include <VBox/com/string.h>27 #include <VBox/com/Guid.h>28 #include <VBox/com/array.h>29 30 #include <VBox/com/ErrorInfo.h> 30 31 #include <VBox/com/errorprint.h> 31 32 #include <VBox/com/Guid.h> 33 #include <VBox/com/listeners.h> 32 34 #include <VBox/com/NativeEventQueue.h> 33 #include <VBox/com/ listeners.h>35 #include <VBox/com/string.h> 34 36 #include <VBox/com/VirtualBox.h> 35 37 36 38 #include <VBox/log.h> 37 39 #include <VBox/version.h> 40 41 #include <iprt/env.h> 38 42 #include <iprt/errcore.h> 43 #include <iprt/getopt.h> 39 44 #include <iprt/initterm.h> 40 45 #include <iprt/mem.h> 41 #include <iprt/getopt.h> 46 #include <iprt/process.h> 47 #include <iprt/path.h> 42 48 #include <iprt/semaphore.h> 43 49 #include <iprt/stream.h> … … 46 52 47 53 #include "VBoxAutostart.h" 54 #include "PasswordInput.h" 48 55 49 56 … … 71 78 /** The semaphore the main service thread is waiting on in autostartSvcWinServiceMain. */ 72 79 static RTSEMEVENTMULTI g_hSupSvcWinEvent = NIL_RTSEMEVENTMULTI; 80 /** The service name is used for send to service main. */ 81 static com::Bstr g_bstrServiceName; 73 82 74 83 … … 77 86 *********************************************************************************************************************************/ 78 87 static SC_HANDLE autostartSvcWinOpenSCManager(const char *pszAction, DWORD dwAccess); 88 89 static int autostartGetProcessDomainUser(com::Utf8Str &aUser) 90 { 91 int rc = VERR_NOT_SUPPORTED; 92 93 RTUTF16 wszUsername[1024] = { 0 }; 94 ULONG cwcUsername = RT_ELEMENTS(wszUsername); 95 char *pszUser = NULL; 96 if (!GetUserNameExW(NameSamCompatible, &wszUsername[0], &cwcUsername)) 97 return RTErrConvertFromWin32(GetLastError()); 98 rc = RTUtf16ToUtf8(wszUsername, &pszUser); 99 aUser = pszUser; 100 RTStrFree(pszUser); 101 return rc; 102 } 103 104 static int autostartGetLocalDomain(com::Utf8Str &aDomain) 105 { 106 RTUTF16 pwszDomain[MAX_COMPUTERNAME_LENGTH + 1] = { 0 }; 107 uint32_t cwcDomainSize = MAX_COMPUTERNAME_LENGTH + 1; 108 if (!GetComputerNameW(pwszDomain, (LPDWORD)&cwcDomainSize)) 109 return RTErrConvertFromWin32(GetLastError()); 110 char *pszDomain = NULL; 111 int rc = RTUtf16ToUtf8(pwszDomain, &pszDomain); 112 aDomain = pszDomain; 113 RTStrFree(pszDomain); 114 return rc; 115 } 116 117 static int autostartGetDomainAndUser(const com::Utf8Str &aDomainAndUser, com::Utf8Str &aDomain, com::Utf8Str &aUser) 118 { 119 size_t offDelim = aDomainAndUser.find("\\"); 120 if (offDelim != aDomainAndUser.npos) 121 { 122 // if only domain is specified 123 if (aDomainAndUser.length() - offDelim == 1) 124 return VERR_INVALID_PARAMETER; 125 126 if (offDelim == 1 && aDomainAndUser[0] == '.') 127 { 128 int rc = autostartGetLocalDomain(aDomain); 129 aUser = aDomainAndUser.substr(offDelim + 1); 130 return rc; 131 } 132 aDomain = aDomainAndUser.substr(0, offDelim); 133 aUser = aDomainAndUser.substr(offDelim + 1); 134 return VINF_SUCCESS; 135 } 136 137 offDelim = aDomainAndUser.find("@"); 138 if (offDelim != aDomainAndUser.npos) 139 { 140 // if only domain is specified 141 if (offDelim == 0) 142 return VERR_INVALID_PARAMETER; 143 144 // with '@' but without domain 145 if (aDomainAndUser.length() - offDelim == 1) 146 { 147 int rc = autostartGetLocalDomain(aDomain); 148 aUser = aDomainAndUser.substr(0, offDelim); 149 return rc; 150 } 151 aDomain = aDomainAndUser.substr(offDelim + 1); 152 aUser = aDomainAndUser.substr(0, offDelim); 153 return VINF_SUCCESS; 154 } 155 156 // only user is specified 157 int rc = autostartGetLocalDomain(aDomain); 158 aUser = aDomainAndUser; 159 return rc; 160 } 161 162 /** Common helper for formatting the service name. */ 163 static void autostartFormatServiceName(const com::Utf8Str &aDomain, const com::Utf8Str &aUser, com::Utf8Str &aServiceName) 164 { 165 aServiceName.printf("%s%s%s", AUTOSTART_SERVICE_NAME, aDomain.c_str(), aUser.c_str()); 166 } 167 168 /** Used by the delete service operation. */ 169 static int autostartGetServiceName(const com::Utf8Str &aDomainAndUser, com::Utf8Str &aServiceName) 170 { 171 com::Utf8Str sDomain; 172 com::Utf8Str sUser; 173 int rc = autostartGetDomainAndUser(aDomainAndUser, sDomain, sUser); 174 if (RT_FAILURE(rc)) 175 return rc; 176 autostartFormatServiceName(sDomain, sUser, aServiceName); 177 return VINF_SUCCESS; 178 } 79 179 80 180 /** … … 228 328 * @param ... Errors codes that should not cause a message to be displayed. 229 329 */ 230 static SC_HANDLE autostartSvcWinOpenService(const char *pszAction, DWORD dwSCMAccess, DWORD dwSVCAccess,330 static SC_HANDLE autostartSvcWinOpenService(const PRTUTF16 pwszServiceName, const char *pszAction, DWORD dwSCMAccess, DWORD dwSVCAccess, 231 331 unsigned cIgnoredErrors, ...) 232 332 { … … 235 335 return NULL; 236 336 237 SC_HANDLE hSvc = OpenService A(hSCM, AUTOSTART_SERVICE_NAME, dwSVCAccess);337 SC_HANDLE hSvc = OpenServiceW(hSCM, pwszServiceName, dwSVCAccess); 238 338 if (hSvc) 239 339 { … … 258 358 break; 259 359 case ERROR_SERVICE_DOES_NOT_EXIST: 260 autostartSvcDisplayError("%s - OpenService failure: The service does not exist. Reinstall it.\n", pszAction); 360 autostartSvcDisplayError("%s - OpenService failure: The service %ls does not exist. Reinstall it.\n", 361 pszAction, pwszServiceName); 261 362 break; 262 363 default: … … 356 457 */ 357 458 bool fVerbose = false; 459 const char *pszUser = NULL; 358 460 static const RTGETOPTDEF s_aOptions[] = 359 461 { 360 { "--verbose", 'v', RTGETOPT_REQ_NOTHING } 462 { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, 463 { "--user", 'u', RTGETOPT_REQ_STRING }, 361 464 }; 362 465 int ch; 363 unsigned iArg = 0;364 466 RTGETOPTUNION Value; 365 467 RTGETOPTSTATE GetState; … … 372 474 fVerbose = true; 373 475 break; 374 case VINF_GETOPT_NOT_OPTION: 375 return autostartSvcDisplayTooManyArgsError("delete", argc, argv, iArg); 476 case 'u': 477 pszUser = Value.psz; 478 break; 376 479 default: 377 return autostartSvcDisplayGetOptError("delete", ch, argc, argv, iArg, &Value); 378 } 379 380 iArg++; 381 } 382 480 return autostartSvcDisplayGetOptError("delete", ch, &Value); 481 } 482 } 483 484 if (!pszUser) 485 return autostartSvcDisplayError("delete - DeleteService failed, user name required.\n"); 486 487 com::Utf8Str sServiceName; 488 int vrc = autostartGetServiceName(pszUser, sServiceName); 489 if (!RT_FAILURE(vrc)) 490 return autostartSvcDisplayError("delete - DeleteService failed, service name for user %s can not be constructed.\n", 491 pszUser); 383 492 /* 384 493 * Create the service. 385 494 */ 386 intrc = RTEXITCODE_FAILURE;387 SC_HANDLE hSvc = autostartSvcWinOpenService( "delete", SERVICE_CHANGE_CONFIG, DELETE,495 RTEXITCODE rc = RTEXITCODE_FAILURE; 496 SC_HANDLE hSvc = autostartSvcWinOpenService(com::Bstr(sServiceName).raw(), "delete", SERVICE_CHANGE_CONFIG, DELETE, 388 497 1, ERROR_SERVICE_DOES_NOT_EXIST); 389 498 if (hSvc) … … 391 500 if (DeleteService(hSvc)) 392 501 { 393 RTPrintf("Successfully deleted the %s service.\n", AUTOSTART_SERVICE_NAME);502 RTPrintf("Successfully deleted the %s service.\n", sServiceName.c_str()); 394 503 rc = RTEXITCODE_SUCCESS; 395 504 } … … 402 511 403 512 if (fVerbose) 404 RTPrintf("The service %s was not installed, nothing to be done.", AUTOSTART_SERVICE_NAME);513 RTPrintf("The service %s was not installed, nothing to be done.", sServiceName.c_str()); 405 514 else 406 RTPrintf("Successfully deleted the %s service.\n", AUTOSTART_SERVICE_NAME);515 RTPrintf("Successfully deleted the %s service.\n", sServiceName.c_str()); 407 516 rc = RTEXITCODE_SUCCESS; 408 517 } … … 425 534 bool fVerbose = false; 426 535 const char *pszUser = NULL; 427 const char *pszPwd = NULL; 536 com::Utf8Str strPwd; 537 const char *pszPwdFile = NULL; 428 538 static const RTGETOPTDEF s_aOptions[] = 429 539 { 430 { "--verbose", 'v', RTGETOPT_REQ_NOTHING },431 { "--user", 'u', RTGETOPT_REQ_STRING },432 { "--password ", 'p', RTGETOPT_REQ_STRING }540 { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, 541 { "--user", 'u', RTGETOPT_REQ_STRING }, 542 { "--password-file", 'p', RTGETOPT_REQ_STRING } 433 543 }; 434 int iArg = 0;435 544 int ch; 436 545 RTGETOPTUNION Value; … … 448 557 break; 449 558 case 'p': 450 pszPwd = Value.psz;559 pszPwdFile = Value.psz; 451 560 break; 452 561 default: 453 return autostartSvcDisplayGetOptError("create", ch, argc, argv, iArg, &Value); 454 } 455 iArg++; 456 } 457 if (iArg != argc) 458 return autostartSvcDisplayTooManyArgsError("create", argc, argv, iArg); 562 return autostartSvcDisplayGetOptError("create", ch, &Value); 563 } 564 } 565 566 if (!pszUser) 567 return autostartSvcDisplayError("Username is missing"); 568 569 if (pszPwdFile) 570 { 571 /* Get password from file. */ 572 RTEXITCODE rcExit = readPasswordFile(pszPwdFile, &strPwd); 573 if (rcExit == RTEXITCODE_FAILURE) 574 return rcExit; 575 } 576 else 577 { 578 /* Get password from console. */ 579 RTEXITCODE rcExit = readPasswordFromConsole(&strPwd, "Enter password:"); 580 if (rcExit == RTEXITCODE_FAILURE) 581 return rcExit; 582 } 583 584 if (strPwd.isEmpty()) 585 return autostartSvcDisplayError("Password is missing"); 586 587 com::Utf8Str sDomain; 588 com::Utf8Str sUserTmp; 589 int vrc = autostartGetDomainAndUser(pszUser, sDomain, sUserTmp); 590 if (RT_FAILURE(vrc)) 591 return autostartSvcDisplayError("create - CreateService failed, failed to get domain and user from string %s (%d).\n", 592 pszUser, vrc); 593 com::Utf8StrFmt sUserFullName("%s\\%s", sDomain.c_str(), sUserTmp.c_str()); 594 com::Utf8StrFmt sDisplayName("%s %s@%s", AUTOSTART_SERVICE_DISPLAY_NAME, sUserTmp.c_str(), sDomain.c_str()); 595 com::Utf8Str sServiceName; 596 autostartFormatServiceName(sDomain, sUserTmp, sServiceName); 459 597 460 598 /* … … 465 603 if (hSCM) 466 604 { 467 char szExecPath[ MAX_PATH];468 if ( GetModuleFileNameA(NULL /* the executable */,szExecPath, sizeof(szExecPath)))605 char szExecPath[RTPATH_MAX]; 606 if (RTProcGetExecutablePath(szExecPath, sizeof(szExecPath))) 469 607 { 470 608 if (fVerbose) 471 609 RTPrintf("Creating the %s service, binary \"%s\"...\n", 472 AUTOSTART_SERVICE_NAME, szExecPath); /* yea, the binary name isn't UTF-8, but wtf. */ 473 474 SC_HANDLE hSvc = CreateServiceA(hSCM, /* hSCManager */ 475 AUTOSTART_SERVICE_NAME, /* lpServiceName */ 476 AUTOSTART_SERVICE_DISPLAY_NAME, /* lpDisplayName */ 610 sServiceName.c_str(), szExecPath); /* yea, the binary name isn't UTF-8, but wtf. */ 611 612 /* 613 * Add service name as command line parameter for the service 614 */ 615 com::Utf8StrFmt sCmdLine("\"%s\" --service=%s", szExecPath, sServiceName.c_str()); 616 SC_HANDLE hSvc = CreateServiceW(hSCM, /* hSCManager */ 617 com::Bstr(sServiceName).raw(), /* lpServiceName */ 618 com::Bstr(sDisplayName).raw(), /* lpDisplayName */ 477 619 SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG, /* dwDesiredAccess */ 478 620 SERVICE_WIN32_OWN_PROCESS, /* dwServiceType ( | SERVICE_INTERACTIVE_PROCESS? ) */ 479 621 SERVICE_AUTO_START, /* dwStartType */ 480 622 SERVICE_ERROR_NORMAL, /* dwErrorControl */ 481 szExecPath,/* lpBinaryPathName */623 com::Bstr(sCmdLine).raw(), /* lpBinaryPathName */ 482 624 NULL, /* lpLoadOrderGroup */ 483 625 NULL, /* lpdwTagId */ 484 626 NULL, /* lpDependencies */ 485 pszUser,/* lpServiceStartName (NULL => LocalSystem) */486 pszPwd);/* lpPassword */627 com::Bstr(sUserFullName).raw(), /* lpServiceStartName (NULL => LocalSystem) */ 628 com::Bstr(strPwd).raw()); /* lpPassword */ 487 629 if (hSvc) 488 630 { 489 RTPrintf("Successfully created the %s service.\n", AUTOSTART_SERVICE_NAME);631 RTPrintf("Successfully created the %s service.\n", sServiceName.c_str()); 490 632 /** @todo Set the service description or it'll look weird in the vista service manager. 491 633 * Anything else that should be configured? Start access or something? */ … … 631 773 } 632 774 633 static DECLCALLBACK(int) autostartWorkerThread(RTTHREAD hThreadSelf, void *pvUser) 634 { 635 RT_NOREF(hThreadSelf, pvUser); 775 static int autostartStartVMs() 776 { 636 777 int rc = autostartSetup(); 637 778 638 /** @todo Implement config options. */ 639 rc = autostartStartMain(NULL); 779 const char *pszConfigFile = RTEnvGet("VBOXAUTOSTART_CONFIG"); 780 if (!pszConfigFile) 781 return autostartSvcLogError("Starting VMs failed. VBOXAUTOSTART_CONFIG environment variable is not defined.\n"); 782 bool fAllow = false; 783 784 PCFGAST pCfgAst = NULL; 785 rc = autostartParseConfig(pszConfigFile, &pCfgAst); 640 786 if (RT_FAILURE(rc)) 641 autostartSvcLogError("Starting VMs failed, rc=%Rrc", rc); 787 return autostartSvcLogError("Starting VMs failed. Failed to parse the config file. Check the access permissions and file structure.\n"); 788 789 PCFGAST pCfgAstPolicy = autostartConfigAstGetByName(pCfgAst, "default_policy"); 790 /* Check default policy. */ 791 if (pCfgAstPolicy) 792 { 793 if ( pCfgAstPolicy->enmType == CFGASTNODETYPE_KEYVALUE 794 && ( !RTStrCmp(pCfgAstPolicy->u.KeyValue.aszValue, "allow") 795 || !RTStrCmp(pCfgAstPolicy->u.KeyValue.aszValue, "deny"))) 796 { 797 if (!RTStrCmp(pCfgAstPolicy->u.KeyValue.aszValue, "allow")) 798 fAllow = true; 799 } 800 else 801 { 802 autostartConfigAstDestroy(pCfgAst); 803 return autostartSvcLogError("'default_policy' must be either 'allow' or 'deny'.\n"); 804 } 805 } 806 807 com::Utf8Str sUser; 808 rc = autostartGetProcessDomainUser(sUser); 809 if (RT_FAILURE(rc)) 810 { 811 autostartConfigAstDestroy(pCfgAst); 812 return autostartSvcLogError("Failed to query username of the process (%Rrc).\n", rc); 813 } 814 815 PCFGAST pCfgAstUser = NULL; 816 for (unsigned i = 0; i < pCfgAst->u.Compound.cAstNodes; i++) 817 { 818 PCFGAST pNode = pCfgAst->u.Compound.apAstNodes[i]; 819 com::Utf8Str sDomain; 820 com::Utf8Str sUserTmp; 821 int rc = autostartGetDomainAndUser(pNode->pszKey, sDomain, sUserTmp); 822 if (RT_FAILURE(rc)) 823 continue; 824 com::Utf8StrFmt sDomainUser("%s\\%s", sDomain.c_str(), sUserTmp.c_str()); 825 if (sDomainUser == sUser) 826 { 827 pCfgAstUser = pNode; 828 break; 829 } 830 } 831 832 if ( pCfgAstUser 833 && pCfgAstUser->enmType == CFGASTNODETYPE_COMPOUND) 834 { 835 pCfgAstPolicy = autostartConfigAstGetByName(pCfgAstUser, "allow"); 836 if (pCfgAstPolicy) 837 { 838 if ( pCfgAstPolicy->enmType == CFGASTNODETYPE_KEYVALUE 839 && ( !RTStrCmp(pCfgAstPolicy->u.KeyValue.aszValue, "true") 840 || !RTStrCmp(pCfgAstPolicy->u.KeyValue.aszValue, "false"))) 841 fAllow = RTStrCmp(pCfgAstPolicy->u.KeyValue.aszValue, "true") == 0; 842 else 843 { 844 autostartConfigAstDestroy(pCfgAst); 845 return autostartSvcLogError("'allow' must be either 'true' or 'false'.\n"); 846 } 847 } 848 } 849 else if (pCfgAstUser) 850 { 851 autostartConfigAstDestroy(pCfgAst); 852 return autostartSvcLogError("Invalid config, user is not a compound node.\n"); 853 } 854 855 if (!fAllow) 856 { 857 autostartConfigAstDestroy(pCfgAst); 858 return autostartSvcLogError("User is not allowed to autostart VMs.\n"); 859 } 860 861 rc = autostartStartMain(pCfgAstUser); 862 autostartConfigAstDestroy(pCfgAst); 863 if (RT_FAILURE(rc)) 864 autostartSvcLogError("Starting VMs failed, rc=%Rrc\n", rc); 642 865 643 866 return rc; … … 651 874 * 652 875 * @param cArgs Argument count. 653 * @param pap szArgsArgument vector.654 */ 655 static VOID WINAPI autostartSvcWinServiceMain(DWORD cArgs, LP TSTR *papszArgs)656 { 657 RT_NOREF(pap szArgs);876 * @param papwszArgs Argument vector. 877 */ 878 static VOID WINAPI autostartSvcWinServiceMain(DWORD cArgs, LPWSTR *papwszArgs) 879 { 880 RT_NOREF(papwszArgs); 658 881 LogFlowFuncEnter(); 659 882 … … 662 885 */ 663 886 Assert(g_u32SupSvcWinStatus == SERVICE_STOPPED); 664 g_hSupSvcWinCtrlHandler = RegisterServiceCtrlHandlerEx A(AUTOSTART_SERVICE_NAME, autostartSvcWinServiceCtrlHandlerEx, NULL);887 g_hSupSvcWinCtrlHandler = RegisterServiceCtrlHandlerExW(g_bstrServiceName.raw(), autostartSvcWinServiceCtrlHandlerEx, NULL); 665 888 if (g_hSupSvcWinCtrlHandler) 666 889 { … … 682 905 if (autostartSvcWinSetServiceStatus(SERVICE_RUNNING, 0, 0)) 683 906 { 684 LogFlow(("autostartSvcWinServiceMain: calling RTSemEventMultiWait\n")); 685 RTTHREAD hWorker; 686 RTThreadCreate(&hWorker, autostartWorkerThread, NULL, 0, RTTHREADTYPE_DEFAULT, 0, "WorkerThread"); 687 688 LogFlow(("autostartSvcWinServiceMain: woke up\n")); 689 err = NO_ERROR; 690 rc = RTSemEventMultiWait(g_hSupSvcWinEvent, RT_INDEFINITE_WAIT); 907 LogFlow(("autostartSvcWinServiceMain: calling autostartStartVMs\n")); 908 rc = autostartStartVMs(); 691 909 if (RT_SUCCESS(rc)) 692 910 { 693 LogFlow(("autostartSvcWinServiceMain: woke up\n")); 694 /** @todo Autostop part. */ 911 LogFlow(("autostartSvcWinServiceMain: done string VMs\n")); 695 912 err = NO_ERROR; 913 rc = RTSemEventMultiWait(g_hSupSvcWinEvent, RT_INDEFINITE_WAIT); 914 if (RT_SUCCESS(rc)) 915 { 916 LogFlow(("autostartSvcWinServiceMain: woke up\n")); 917 /** @todo Autostop part. */ 918 err = NO_ERROR; 919 } 920 else 921 autostartSvcLogError("RTSemEventWait failed, rc=%Rrc", rc); 696 922 } 697 else698 autostartSvcLogError("RTSemEventWait failed, rc=%Rrc", rc);699 923 700 924 autostartShutdown(); … … 703 927 { 704 928 err = GetLastError(); 705 autostartSvcLogError("SetServiceStatus failed, err=% d", err);929 autostartSvcLogError("SetServiceStatus failed, err=%u", err); 706 930 } 707 931 … … 718 942 { 719 943 err = GetLastError(); 720 autostartSvcLogError("SetServiceStatus failed, err=% d", err);944 autostartSvcLogError("SetServiceStatus failed, err=%u", err); 721 945 } 722 946 autostartSvcWinSetServiceStatus(SERVICE_STOPPED, 0, err); 723 947 } 724 948 else 725 autostartSvcLogError("RegisterServiceCtrlHandlerEx failed, err=% d", GetLastError());949 autostartSvcLogError("RegisterServiceCtrlHandlerEx failed, err=%u", GetLastError()); 726 950 727 951 LogFlowFuncLeave(); … … 750 974 static const RTGETOPTDEF s_aOptions[] = 751 975 { 752 { "-- dummy", 'd', RTGETOPT_REQ_NOTHING }976 { "--service", 's', RTGETOPT_REQ_STRING }, 753 977 }; 754 int iArg = 0; 978 979 const char *pszServiceName = NULL; 980 int ch; 981 RTGETOPTUNION Value; 982 RTGETOPTSTATE GetState; 983 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); 984 while ((ch = RTGetOpt(&GetState, &Value))) 985 { 986 switch (ch) 987 { 988 case 's': 989 pszServiceName = Value.psz; 990 try 991 { 992 g_bstrServiceName = com::Bstr(Value.psz); 993 } 994 catch (...) 995 { 996 autostartSvcLogError("runit failed, service name is not valid utf-8 string or out of memory"); 997 return RTEXITCODE_FAILURE; 998 } 999 break; 1000 default: 1001 return autostartSvcDisplayGetOptError("runit", ch, &Value); 1002 } 1003 } 1004 1005 if (!pszServiceName) 1006 { 1007 autostartSvcLogError("runit failed, service name is missing"); 1008 return RTEXITCODE_FAILURE; 1009 } 1010 1011 /* 1012 * Register the service with the service control manager 1013 * and start dispatching requests from it (all done by the API). 1014 */ 1015 SERVICE_TABLE_ENTRYW const s_aServiceStartTable[] = 1016 { 1017 { g_bstrServiceName.raw(), autostartSvcWinServiceMain }, 1018 { NULL, NULL} 1019 }; 1020 if (StartServiceCtrlDispatcherW(&s_aServiceStartTable[0])) 1021 { 1022 LogFlowFuncLeave(); 1023 return RTEXITCODE_SUCCESS; /* told to quit, so quit. */ 1024 } 1025 1026 DWORD err = GetLastError(); 1027 switch (err) 1028 { 1029 case ERROR_FAILED_SERVICE_CONTROLLER_CONNECT: 1030 autostartSvcWinServiceMain(0, NULL);//autostartSvcDisplayError("Cannot run a service from the command line. Use the 'start' action to start it the right way.\n"); 1031 break; 1032 default: 1033 autostartSvcLogError("StartServiceCtrlDispatcher failed, err=%u", err); 1034 break; 1035 } 1036 return RTEXITCODE_FAILURE; 1037 } 1038 1039 1040 /** 1041 * Show the version info. 1042 * 1043 * @returns RTEXITCODE_SUCCESS. 1044 */ 1045 static RTEXITCODE autostartSvcWinShowVersion(int argc, char **argv) 1046 { 1047 /* 1048 * Parse the arguments. 1049 */ 1050 bool fBrief = false; 1051 static const RTGETOPTDEF s_aOptions[] = 1052 { 1053 { "--brief", 'b', RTGETOPT_REQ_NOTHING } 1054 }; 755 1055 int ch; 756 1056 RTGETOPTUNION Value; … … 760 1060 switch (ch) 761 1061 { 762 default: return autostartSvcDisplayGetOptError("runit", ch, argc, argv, iArg, &Value);763 }764 if (iArg != argc)765 return autostartSvcDisplayTooManyArgsError("runit", argc, argv, iArg);766 767 /*768 * Register the service with the service control manager769 * and start dispatching requests from it (all done by the API).770 */771 static SERVICE_TABLE_ENTRY const s_aServiceStartTable[] =772 {773 { _T(AUTOSTART_SERVICE_NAME), autostartSvcWinServiceMain },774 { NULL, NULL}775 };776 if (StartServiceCtrlDispatcher(&s_aServiceStartTable[0]))777 {778 LogFlowFuncLeave();779 return RTEXITCODE_SUCCESS; /* told to quit, so quit. */780 }781 782 DWORD err = GetLastError();783 switch (err)784 {785 case ERROR_FAILED_SERVICE_CONTROLLER_CONNECT:786 autostartSvcWinServiceMain(0, NULL);//autostartSvcDisplayError("Cannot run a service from the command line. Use the 'start' action to start it the right way.\n");787 break;788 default:789 autostartSvcLogError("StartServiceCtrlDispatcher failed, err=%d", err);790 break;791 }792 return RTEXITCODE_FAILURE;793 }794 795 796 /**797 * Show the version info.798 *799 * @returns RTEXITCODE_SUCCESS.800 */801 static RTEXITCODE autostartSvcWinShowVersion(int argc, char **argv)802 {803 /*804 * Parse the arguments.805 */806 bool fBrief = false;807 static const RTGETOPTDEF s_aOptions[] =808 {809 { "--brief", 'b', RTGETOPT_REQ_NOTHING }810 };811 int iArg = 0;812 int ch;813 RTGETOPTUNION Value;814 RTGETOPTSTATE GetState;815 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);816 while ((ch = RTGetOpt(&GetState, &Value)))817 switch (ch)818 {819 1062 case 'b': fBrief = true; break; 820 default: return autostartSvcDisplayGetOptError("version", ch, argc, argv, iArg, &Value); 821 822 } 823 if (iArg != argc) 824 return autostartSvcDisplayTooManyArgsError("version", argc, argv, iArg); 1063 default: return autostartSvcDisplayGetOptError("version", ch, &Value); 1064 } 825 1065 826 1066 /* -
trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart.h
r76582 r80569 253 253 * @todo This should later be replaced by the release logger and callback destination(s). 254 254 */ 255 DECLHIDDEN( void) autostartSvcLogErrorV(const char *pszFormat, va_list va);255 DECLHIDDEN(RTEXITCODE) autostartSvcLogErrorV(const char *pszFormat, va_list va); 256 256 257 257 /** … … 265 265 * @todo This should later be replaced by the release logger and callback destination(s). 266 266 */ 267 DECLHIDDEN( void) autostartSvcLogError(const char *pszFormat, ...);267 DECLHIDDEN(RTEXITCODE) autostartSvcLogError(const char *pszFormat, ...); 268 268 269 269 /** … … 297 297 * @param va Format arguments. 298 298 */ 299 DECLHIDDEN( void) autostartSvcDisplayErrorV(const char *pszFormat, va_list va);299 DECLHIDDEN(RTEXITCODE) autostartSvcDisplayErrorV(const char *pszFormat, va_list va); 300 300 301 301 /** … … 305 305 * @param ... Format arguments. 306 306 */ 307 DECLHIDDEN( void) autostartSvcDisplayError(const char *pszFormat, ...);308 309 /** 310 * Deals with RTGetOpt failure .311 * 312 * @returns 1307 DECLHIDDEN(RTEXITCODE) autostartSvcDisplayError(const char *pszFormat, ...); 308 309 /** 310 * Deals with RTGetOpt failure, i.e. an syntax error. 311 * 312 * @returns RTEXITCODE_SYNTAX 313 313 * @param pszAction The action name. 314 314 * @param rc The RTGetOpt return value. 315 * @param argc The argument count.316 * @param argv The argument vector.317 * @param iArg The argument index.318 315 * @param pValue The value returned by RTGetOpt. 319 316 */ 320 DECLHIDDEN(RTEXITCODE) autostartSvcDisplayGetOptError(const char *pszAction, int rc, int argc, char **argv, int iArg, PCRTGETOPTUNION pValue); 321 322 /** 323 * Bitch about too many arguments (after RTGetOpt stops). 324 * 325 * @returns RTEXITCODE_FAILURE 326 * @param pszAction The action name. 327 * @param argc The argument count. 328 * @param argv The argument vector. 329 * @param iArg The argument index. 330 */ 331 DECLHIDDEN(RTEXITCODE) autostartSvcDisplayTooManyArgsError(const char *pszAction, int argc, char **argv, int iArg); 317 DECLHIDDEN(RTEXITCODE) autostartSvcDisplayGetOptError(const char *pszAction, int rc, PCRTGETOPTUNION pValue); 332 318 333 319 DECLHIDDEN(int) autostartSetup(); -
trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartUtils.cpp
r76553 r80569 94 94 } 95 95 96 DECLHIDDEN( void) autostartSvcLogErrorV(const char *pszFormat, va_list va)96 DECLHIDDEN(RTEXITCODE) autostartSvcLogErrorV(const char *pszFormat, va_list va) 97 97 { 98 98 if (*pszFormat) … … 107 107 autostartSvcOsLogStr(pszFormat, AUTOSTARTLOGTYPE_ERROR); 108 108 } 109 } 110 111 DECLHIDDEN(void) autostartSvcLogError(const char *pszFormat, ...) 109 return RTEXITCODE_FAILURE; 110 } 111 112 DECLHIDDEN(RTEXITCODE) autostartSvcLogError(const char *pszFormat, ...) 112 113 { 113 114 va_list va; … … 115 116 autostartSvcLogErrorV(pszFormat, va); 116 117 va_end(va); 118 return RTEXITCODE_FAILURE; 117 119 } 118 120 … … 203 205 } 204 206 205 DECLHIDDEN( void) autostartSvcDisplayErrorV(const char *pszFormat, va_list va)207 DECLHIDDEN(RTEXITCODE) autostartSvcDisplayErrorV(const char *pszFormat, va_list va) 206 208 { 207 209 RTStrmPrintf(g_pStdErr, "VBoxSupSvc error: "); 208 210 RTStrmPrintfV(g_pStdErr, pszFormat, va); 209 211 Log(("autostartSvcDisplayErrorV: %s", pszFormat)); /** @todo format it! */ 210 } 211 212 DECLHIDDEN(void) autostartSvcDisplayError(const char *pszFormat, ...) 212 return RTEXITCODE_FAILURE; 213 } 214 215 DECLHIDDEN(RTEXITCODE) autostartSvcDisplayError(const char *pszFormat, ...) 213 216 { 214 217 va_list va; … … 216 219 autostartSvcDisplayErrorV(pszFormat, va); 217 220 va_end(va); 218 } 219 220 DECLHIDDEN(RTEXITCODE) autostartSvcDisplayGetOptError(const char *pszAction, int rc, int argc, char **argv, int iArg, 221 PCRTGETOPTUNION pValue) 222 { 223 RT_NOREF(pValue); 224 autostartSvcDisplayError("%s - RTGetOpt failure, %Rrc (%d): %s\n", 225 pszAction, rc, rc, iArg < argc ? argv[iArg] : "<null>"); 226 return RTEXITCODE_FAILURE; 227 } 228 229 DECLHIDDEN(RTEXITCODE) autostartSvcDisplayTooManyArgsError(const char *pszAction, int argc, char **argv, int iArg) 230 { 231 RT_NOREF(argc); 232 Assert(iArg < argc); 233 autostartSvcDisplayError("%s - Too many arguments: %s\n", pszAction, argv[iArg]); 234 return RTEXITCODE_FAILURE; 221 return RTEXITCODE_FAILURE; 222 } 223 224 DECLHIDDEN(RTEXITCODE) autostartSvcDisplayGetOptError(const char *pszAction, int rc, PCRTGETOPTUNION pValue) 225 { 226 char szMsg[4096]; 227 RTGetOptFormatError(szMsg, sizeof(szMsg), rc, pValue); 228 autostartSvcDisplayError("%s - %s", pszAction, szMsg); 229 return RTEXITCODE_SYNTAX; 235 230 } 236 231
Note:
See TracChangeset
for help on using the changeset viewer.