VirtualBox

Ignore:
Timestamp:
Sep 3, 2019 2:34:21 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
133086
Message:

Main: bugref:9341: Added VM autostart during boot support for windows host

Location:
trunk/src/VBox/Frontends/VBoxAutostart
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxAutostart/Makefile.kmk

    r76553 r80569  
    2222 PROGRAMS += VBoxAutostartSvc
    2323 VBoxAutostartSvc_TEMPLATE   = VBOXMAINCLIENTEXE
     24 VBoxAutostartSvc_INCS       = ../Common
    2425 VBoxAutostartSvc_SOURCES    = \
    2526        VBoxAutostartCfg.cpp \
     
    2728        VBoxAutostartStop.cpp \
    2829        VBoxAutostartUtils.cpp \
    29         VBoxAutostart-win.cpp
     30        VBoxAutostart-win.cpp \
     31        ../Common/PasswordInput.cpp
     32 VBoxAutostartSvc_LIBS.win += Secur32.lib       
    3033else
    3134 PROGRAMS += VBoxAutostart
  • trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart-win.cpp

    r76553 r80569  
    2323#include <tchar.h>
    2424
     25#define SECURITY_WIN32
     26#include <Security.h>
     27
     28#include <VBox/com/array.h>
    2529#include <VBox/com/com.h>
    26 #include <VBox/com/string.h>
    27 #include <VBox/com/Guid.h>
    28 #include <VBox/com/array.h>
    2930#include <VBox/com/ErrorInfo.h>
    3031#include <VBox/com/errorprint.h>
    31 
     32#include <VBox/com/Guid.h>
     33#include <VBox/com/listeners.h>
    3234#include <VBox/com/NativeEventQueue.h>
    33 #include <VBox/com/listeners.h>
     35#include <VBox/com/string.h>
    3436#include <VBox/com/VirtualBox.h>
    3537
    3638#include <VBox/log.h>
    3739#include <VBox/version.h>
     40
     41#include <iprt/env.h>
    3842#include <iprt/errcore.h>
     43#include <iprt/getopt.h>
    3944#include <iprt/initterm.h>
    4045#include <iprt/mem.h>
    41 #include <iprt/getopt.h>
     46#include <iprt/process.h>
     47#include <iprt/path.h>
    4248#include <iprt/semaphore.h>
    4349#include <iprt/stream.h>
     
    4652
    4753#include "VBoxAutostart.h"
     54#include "PasswordInput.h"
    4855
    4956
     
    7178/** The semaphore the main service thread is waiting on in autostartSvcWinServiceMain. */
    7279static RTSEMEVENTMULTI g_hSupSvcWinEvent = NIL_RTSEMEVENTMULTI;
     80/** The service name is used for send to service main. */
     81static com::Bstr g_bstrServiceName;
    7382
    7483
     
    7786*********************************************************************************************************************************/
    7887static SC_HANDLE autostartSvcWinOpenSCManager(const char *pszAction, DWORD dwAccess);
     88
     89static 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
     104static 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
     117static 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. */
     163static 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. */
     169static 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}
    79179
    80180/**
     
    228328 * @param   ...                 Errors codes that should not cause a message to be displayed.
    229329 */
    230 static SC_HANDLE autostartSvcWinOpenService(const char *pszAction, DWORD dwSCMAccess, DWORD dwSVCAccess,
     330static SC_HANDLE autostartSvcWinOpenService(const PRTUTF16 pwszServiceName, const char *pszAction, DWORD dwSCMAccess, DWORD dwSVCAccess,
    231331                                            unsigned cIgnoredErrors, ...)
    232332{
     
    235335        return NULL;
    236336
    237     SC_HANDLE hSvc = OpenServiceA(hSCM, AUTOSTART_SERVICE_NAME, dwSVCAccess);
     337    SC_HANDLE hSvc = OpenServiceW(hSCM, pwszServiceName, dwSVCAccess);
    238338    if (hSvc)
    239339    {
     
    258358                    break;
    259359                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);
    261362                    break;
    262363                default:
     
    356457     */
    357458    bool fVerbose = false;
     459    const char *pszUser = NULL;
    358460    static const RTGETOPTDEF s_aOptions[] =
    359461    {
    360         { "--verbose", 'v', RTGETOPT_REQ_NOTHING }
     462        { "--verbose", 'v', RTGETOPT_REQ_NOTHING },
     463        { "--user",    'u', RTGETOPT_REQ_STRING  },
    361464    };
    362465    int ch;
    363     unsigned iArg = 0;
    364466    RTGETOPTUNION Value;
    365467    RTGETOPTSTATE GetState;
     
    372474                fVerbose = true;
    373475                break;
    374             case VINF_GETOPT_NOT_OPTION:
    375                 return autostartSvcDisplayTooManyArgsError("delete", argc, argv, iArg);
     476            case 'u':
     477                pszUser = Value.psz;
     478                break;
    376479            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);
    383492    /*
    384493     * Create the service.
    385494     */
    386     int rc = 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,
    388497                                                1, ERROR_SERVICE_DOES_NOT_EXIST);
    389498    if (hSvc)
     
    391500        if (DeleteService(hSvc))
    392501        {
    393             RTPrintf("Successfully deleted the %s service.\n", AUTOSTART_SERVICE_NAME);
     502            RTPrintf("Successfully deleted the %s service.\n", sServiceName.c_str());
    394503            rc = RTEXITCODE_SUCCESS;
    395504        }
     
    402511
    403512        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());
    405514        else
    406             RTPrintf("Successfully deleted the %s service.\n", AUTOSTART_SERVICE_NAME);
     515            RTPrintf("Successfully deleted the %s service.\n", sServiceName.c_str());
    407516        rc = RTEXITCODE_SUCCESS;
    408517    }
     
    425534    bool fVerbose = false;
    426535    const char *pszUser = NULL;
    427     const char *pszPwd = NULL;
     536    com::Utf8Str strPwd;
     537    const char *pszPwdFile = NULL;
    428538    static const RTGETOPTDEF s_aOptions[] =
    429539    {
    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  }
    433543    };
    434     int iArg = 0;
    435544    int ch;
    436545    RTGETOPTUNION Value;
     
    448557                break;
    449558            case 'p':
    450                 pszPwd = Value.psz;
     559                pszPwdFile = Value.psz;
    451560                break;
    452561            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);
    459597
    460598    /*
     
    465603    if (hSCM)
    466604    {
    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)))
    469607        {
    470608            if (fVerbose)
    471609                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 */
    477619                                            SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG, /* dwDesiredAccess */
    478620                                            SERVICE_WIN32_OWN_PROCESS,       /* dwServiceType ( | SERVICE_INTERACTIVE_PROCESS? ) */
    479621                                            SERVICE_AUTO_START,              /* dwStartType */
    480622                                            SERVICE_ERROR_NORMAL,            /* dwErrorControl */
    481                                             szExecPath,                      /* lpBinaryPathName */
     623                                            com::Bstr(sCmdLine).raw(),       /* lpBinaryPathName */
    482624                                            NULL,                            /* lpLoadOrderGroup */
    483625                                            NULL,                            /* lpdwTagId */
    484626                                            NULL,                            /* lpDependencies */
    485                                             pszUser,                         /* lpServiceStartName (NULL => LocalSystem) */
    486                                             pszPwd);                         /* lpPassword */
     627                                            com::Bstr(sUserFullName).raw(),  /* lpServiceStartName (NULL => LocalSystem) */
     628                                            com::Bstr(strPwd).raw());        /* lpPassword */
    487629            if (hSvc)
    488630            {
    489                 RTPrintf("Successfully created the %s service.\n", AUTOSTART_SERVICE_NAME);
     631                RTPrintf("Successfully created the %s service.\n", sServiceName.c_str());
    490632                /** @todo Set the service description or it'll look weird in the vista service manager.
    491633                 *  Anything else that should be configured? Start access or something? */
     
    631773}
    632774
    633 static DECLCALLBACK(int) autostartWorkerThread(RTTHREAD hThreadSelf, void *pvUser)
    634 {
    635     RT_NOREF(hThreadSelf, pvUser);
     775static int autostartStartVMs()
     776{
    636777    int rc = autostartSetup();
    637778
    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);
    640786    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);
    642865
    643866    return rc;
     
    651874 *
    652875 * @param   cArgs           Argument count.
    653  * @param   papszArgs       Argument vector.
    654  */
    655 static VOID WINAPI autostartSvcWinServiceMain(DWORD cArgs, LPTSTR *papszArgs)
    656 {
    657     RT_NOREF(papszArgs);
     876 * @param   papwszArgs      Argument vector.
     877 */
     878static VOID WINAPI autostartSvcWinServiceMain(DWORD cArgs, LPWSTR *papwszArgs)
     879{
     880    RT_NOREF(papwszArgs);
    658881    LogFlowFuncEnter();
    659882
     
    662885     */
    663886    Assert(g_u32SupSvcWinStatus == SERVICE_STOPPED);
    664     g_hSupSvcWinCtrlHandler = RegisterServiceCtrlHandlerExA(AUTOSTART_SERVICE_NAME, autostartSvcWinServiceCtrlHandlerEx, NULL);
     887    g_hSupSvcWinCtrlHandler = RegisterServiceCtrlHandlerExW(g_bstrServiceName.raw(), autostartSvcWinServiceCtrlHandlerEx, NULL);
    665888    if (g_hSupSvcWinCtrlHandler)
    666889    {
     
    682905                    if (autostartSvcWinSetServiceStatus(SERVICE_RUNNING, 0, 0))
    683906                    {
    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();
    691909                        if (RT_SUCCESS(rc))
    692910                        {
    693                             LogFlow(("autostartSvcWinServiceMain: woke up\n"));
    694                             /** @todo Autostop part. */
     911                            LogFlow(("autostartSvcWinServiceMain: done string VMs\n"));
    695912                            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);
    696922                        }
    697                         else
    698                             autostartSvcLogError("RTSemEventWait failed, rc=%Rrc", rc);
    699923
    700924                        autostartShutdown();
     
    703927                    {
    704928                        err = GetLastError();
    705                         autostartSvcLogError("SetServiceStatus failed, err=%d", err);
     929                        autostartSvcLogError("SetServiceStatus failed, err=%u", err);
    706930                    }
    707931
     
    718942        {
    719943            err = GetLastError();
    720             autostartSvcLogError("SetServiceStatus failed, err=%d", err);
     944            autostartSvcLogError("SetServiceStatus failed, err=%u", err);
    721945        }
    722946        autostartSvcWinSetServiceStatus(SERVICE_STOPPED, 0, err);
    723947    }
    724948    else
    725         autostartSvcLogError("RegisterServiceCtrlHandlerEx failed, err=%d", GetLastError());
     949        autostartSvcLogError("RegisterServiceCtrlHandlerEx failed, err=%u", GetLastError());
    726950
    727951    LogFlowFuncLeave();
     
    750974    static const RTGETOPTDEF s_aOptions[] =
    751975    {
    752         { "--dummy", 'd', RTGETOPT_REQ_NOTHING }
     976        { "--service", 's', RTGETOPT_REQ_STRING },
    753977    };
    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 */
     1045static 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    };
    7551055    int ch;
    7561056    RTGETOPTUNION Value;
     
    7601060        switch (ch)
    7611061        {
    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 manager
    769      * 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         {
    8191062            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        }
    8251065
    8261066    /*
  • trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart.h

    r76582 r80569  
    253253 * @todo    This should later be replaced by the release logger and callback destination(s).
    254254 */
    255 DECLHIDDEN(void) autostartSvcLogErrorV(const char *pszFormat, va_list va);
     255DECLHIDDEN(RTEXITCODE) autostartSvcLogErrorV(const char *pszFormat, va_list va);
    256256
    257257/**
     
    265265 * @todo    This should later be replaced by the release logger and callback destination(s).
    266266 */
    267 DECLHIDDEN(void) autostartSvcLogError(const char *pszFormat, ...);
     267DECLHIDDEN(RTEXITCODE) autostartSvcLogError(const char *pszFormat, ...);
    268268
    269269/**
     
    297297 * @param   va          Format arguments.
    298298 */
    299 DECLHIDDEN(void) autostartSvcDisplayErrorV(const char *pszFormat, va_list va);
     299DECLHIDDEN(RTEXITCODE) autostartSvcDisplayErrorV(const char *pszFormat, va_list va);
    300300
    301301/**
     
    305305 * @param   ...         Format arguments.
    306306 */
    307 DECLHIDDEN(void) autostartSvcDisplayError(const char *pszFormat, ...);
    308 
    309 /**
    310  * Deals with RTGetOpt failure.
    311  *
    312  * @returns 1
     307DECLHIDDEN(RTEXITCODE) autostartSvcDisplayError(const char *pszFormat, ...);
     308
     309/**
     310 * Deals with RTGetOpt failure, i.e. an syntax error.
     311 *
     312 * @returns RTEXITCODE_SYNTAX
    313313 * @param   pszAction       The action name.
    314314 * @param   rc              The RTGetOpt return value.
    315  * @param   argc            The argument count.
    316  * @param   argv            The argument vector.
    317  * @param   iArg            The argument index.
    318315 * @param   pValue          The value returned by RTGetOpt.
    319316 */
    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);
     317DECLHIDDEN(RTEXITCODE) autostartSvcDisplayGetOptError(const char *pszAction, int rc, PCRTGETOPTUNION pValue);
    332318
    333319DECLHIDDEN(int) autostartSetup();
  • trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartUtils.cpp

    r76553 r80569  
    9494}
    9595
    96 DECLHIDDEN(void) autostartSvcLogErrorV(const char *pszFormat, va_list va)
     96DECLHIDDEN(RTEXITCODE) autostartSvcLogErrorV(const char *pszFormat, va_list va)
    9797{
    9898    if (*pszFormat)
     
    107107            autostartSvcOsLogStr(pszFormat, AUTOSTARTLOGTYPE_ERROR);
    108108    }
    109 }
    110 
    111 DECLHIDDEN(void) autostartSvcLogError(const char *pszFormat, ...)
     109    return RTEXITCODE_FAILURE;
     110}
     111
     112DECLHIDDEN(RTEXITCODE) autostartSvcLogError(const char *pszFormat, ...)
    112113{
    113114    va_list va;
     
    115116    autostartSvcLogErrorV(pszFormat, va);
    116117    va_end(va);
     118    return RTEXITCODE_FAILURE;
    117119}
    118120
     
    203205}
    204206
    205 DECLHIDDEN(void) autostartSvcDisplayErrorV(const char *pszFormat, va_list va)
     207DECLHIDDEN(RTEXITCODE) autostartSvcDisplayErrorV(const char *pszFormat, va_list va)
    206208{
    207209    RTStrmPrintf(g_pStdErr, "VBoxSupSvc error: ");
    208210    RTStrmPrintfV(g_pStdErr, pszFormat, va);
    209211    Log(("autostartSvcDisplayErrorV: %s", pszFormat)); /** @todo format it! */
    210 }
    211 
    212 DECLHIDDEN(void) autostartSvcDisplayError(const char *pszFormat, ...)
     212    return RTEXITCODE_FAILURE;
     213}
     214
     215DECLHIDDEN(RTEXITCODE) autostartSvcDisplayError(const char *pszFormat, ...)
    213216{
    214217    va_list va;
     
    216219    autostartSvcDisplayErrorV(pszFormat, va);
    217220    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
     224DECLHIDDEN(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;
    235230}
    236231
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette