VirtualBox

Changeset 69810 in vbox for trunk/src/VBox/Main/src-all


Ignore:
Timestamp:
Nov 22, 2017 5:53:44 PM (7 years ago)
Author:
vboxsync
Message:

VBoxProxyStub: Rewrote the VBoxSDS service updating code to do something useful should the service be misconfigured by the user or pointing to a different VirtualBox installation/build.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-all/win/VBoxProxyStub.c

    r69733 r69810  
    22982298
    22992299#ifdef VBOX_WITH_SDS
    2300 
    2301 static BOOL vbpsIsInstalledWindowsService(const WCHAR *pwszServiceName)
    2302 {
    2303     BOOL fRet = FALSE;
    2304     SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    2305     if (hSCM != NULL)
    2306     {
    2307         SC_HANDLE hService = OpenService(hSCM, pwszServiceName, SERVICE_QUERY_CONFIG);
    2308         if (hService != NULL)
    2309         {
    2310             CloseServiceHandle(hService);
    2311             fRet = TRUE;
    2312         }
    2313         CloseServiceHandle(hSCM);
    2314     }
    2315     return fRet;
    2316 }
    2317 
    2318 
    2319 /**
    2320  * Worker for installing a SCM service.
    2321  *
    2322  * @returns Success indicator.
     2300/**
     2301 * Update a SCM service.
     2302 *
     2303 * @param   pState              The state.
    23232304 * @param   pwszVBoxDir         The VirtualBox install directory (unicode),
    23242305 *                              trailing slash.
     
    23282309 * @param   pwszDescription     The service description.
    23292310 */
    2330 static BOOL vbpsInstallWindowsService(const WCHAR *pwszVBoxDir, const WCHAR *pwszModule, const WCHAR *pwszServiceName,
    2331                                       const WCHAR *pwszDisplayName, const WCHAR *pwszDescription)
    2332 {
    2333     BOOL fRet = vbpsIsInstalledWindowsService(pwszServiceName);
    2334     if (!fRet)
    2335     {
    2336         /* Make double quoted executable file path. ASSUMES pwszVBoxDir ends with a slash! */
    2337         WCHAR wszFilePath[MAX_PATH + 2];
    2338         int rc = RTUtf16CopyAscii(wszFilePath, RT_ELEMENTS(wszFilePath), "\"");
    2339         if (RT_SUCCESS(rc))
    2340             rc = RTUtf16Cat(wszFilePath, RT_ELEMENTS(wszFilePath), pwszVBoxDir);
    2341         if (RT_SUCCESS(rc))
    2342             rc = RTUtf16Cat(wszFilePath, RT_ELEMENTS(wszFilePath), pwszModule);
    2343         if (RT_SUCCESS(rc))
    2344             rc = RTUtf16CatAscii(wszFilePath, RT_ELEMENTS(wszFilePath), "\"");
    2345         if (RT_SUCCESS(rc))
     2311static void vbpsUpdateWindowsService(VBPSREGSTATE *pState, const WCHAR *pwszVBoxDir, const WCHAR *pwszModule,
     2312                                     const WCHAR *pwszServiceName, const WCHAR *pwszDisplayName, const WCHAR *pwszDescription)
     2313{
     2314    SC_HANDLE           hSCM;
     2315
     2316    /* Configuration options that are currently standard. */
     2317    uint32_t const      uServiceType         = SERVICE_WIN32_OWN_PROCESS;
     2318    uint32_t const      uStartType           = SERVICE_DEMAND_START;
     2319    uint32_t const      uErrorControl        = SERVICE_ERROR_NORMAL;
     2320    WCHAR const * const pwszServiceStartName = L"LocalSystem";
     2321    static WCHAR const  wszzDependencies[]   = L"RPCSS\0";
     2322
     2323    /*
     2324     * Make double quoted executable file path. ASSUMES pwszVBoxDir ends with a slash!
     2325     */
     2326    WCHAR wszFilePath[MAX_PATH + 2];
     2327    int rc = RTUtf16CopyAscii(wszFilePath, RT_ELEMENTS(wszFilePath), "\"");
     2328    if (RT_SUCCESS(rc))
     2329        rc = RTUtf16Cat(wszFilePath, RT_ELEMENTS(wszFilePath), pwszVBoxDir);
     2330    if (RT_SUCCESS(rc))
     2331        rc = RTUtf16Cat(wszFilePath, RT_ELEMENTS(wszFilePath), pwszModule);
     2332    if (RT_SUCCESS(rc))
     2333        rc = RTUtf16CatAscii(wszFilePath, RT_ELEMENTS(wszFilePath), "\"");
     2334    AssertLogRelRCReturnVoid(rc);
     2335
     2336    /*
     2337     * Open the service manager for the purpose of checking the configuration.
     2338     */
     2339    hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
     2340    if (hSCM != NULL)
     2341    {
     2342        union
    23462343        {
    2347             SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    2348             if (hSCM != NULL)
     2344            QUERY_SERVICE_CONFIGW   Config;
     2345            SERVICE_STATUS          Status;
     2346            SERVICE_DESCRIPTION     Desc;
     2347            uint8_t                 abPadding[sizeof(QUERY_SERVICE_CONFIGW) + 5 * _1K];
     2348        } uBuf;
     2349        SC_HANDLE   hService;
     2350        bool        fCreateIt = pState->fUpdate;
     2351        bool        fDeleteIt = true;
     2352
     2353        /*
     2354         * Step #1: Open the service and validate the configuration.
     2355         */
     2356        if (pState->fUpdate)
     2357        {
     2358            hService = OpenServiceW(hSCM, pwszServiceName, SERVICE_QUERY_CONFIG);
     2359            if (hService != NULL)
    23492360            {
    2350                 SC_HANDLE hService = CreateService(hSCM, pwszServiceName, pwszDisplayName,
    2351                                                    SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
    2352                                                    SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
    2353                                                    wszFilePath, NULL, NULL, L"RPCSS\0", NULL, NULL);
    2354                 if (hService != NULL)
     2361                DWORD cbNeeded = 0;
     2362                if (QueryServiceConfigW(hService, &uBuf.Config, sizeof(uBuf), &cbNeeded))
    23552363                {
    2356                     SERVICE_DESCRIPTION sd;
    2357                     sd.lpDescription = (WCHAR *)pwszDescription;
    2358                     if (ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &sd))
    2359                         fRet = TRUE;
    2360                     else
    2361                         AssertMsgFailed(("Could not set service description for %ls: %u\n", pwszServiceName, GetLastError()));
    2362                     CloseServiceHandle(hService);
     2364                    if (uBuf.Config.dwErrorControl)
     2365                    {
     2366                        uint32_t cErrors = 0;
     2367                        if (uBuf.Config.dwServiceType != uServiceType)
     2368                        {
     2369                            LogRel(("update service '%ls': dwServiceType %u, expected %u\n",
     2370                                    pwszServiceName, uBuf.Config.dwServiceType, uServiceType));
     2371                            cErrors++;
     2372                        }
     2373                        if (uBuf.Config.dwStartType != uStartType)
     2374                        {
     2375                            LogRel(("update service '%ls': dwStartType %u, expected %u\n",
     2376                                    pwszServiceName, uBuf.Config.dwStartType, uStartType));
     2377                            cErrors++;
     2378                        }
     2379                        if (uBuf.Config.dwErrorControl != uErrorControl)
     2380                        {
     2381                            LogRel(("update service '%ls': dwErrorControl %u, expected %u\n",
     2382                                    pwszServiceName, uBuf.Config.dwErrorControl, uErrorControl));
     2383                            cErrors++;
     2384                        }
     2385                        if (RTUtf16ICmp(uBuf.Config.lpBinaryPathName, wszFilePath) != 0)
     2386                        {
     2387                            LogRel(("update service '%ls': lpBinaryPathName '%ls', expected '%ls'\n",
     2388                                    pwszServiceName, uBuf.Config.lpBinaryPathName, wszFilePath));
     2389                            cErrors++;
     2390                        }
     2391                        if (   uBuf.Config.lpServiceStartName != NULL
     2392                            && *uBuf.Config.lpServiceStartName != L'\0'
     2393                            && RTUtf16ICmp(uBuf.Config.lpServiceStartName, pwszServiceStartName) != 0)
     2394                        {
     2395                            LogRel(("update service '%ls': lpServiceStartName '%ls', expected '%ls'\n",
     2396                                    pwszServiceName, uBuf.Config.lpBinaryPathName, pwszServiceStartName));
     2397                            cErrors++;
     2398                        }
     2399
     2400                        fDeleteIt = fCreateIt = cErrors > 0;
     2401                    }
    23632402                }
    23642403                else
    2365                     AssertMsgFailed(("Could not create service %ls: %u\n", pwszServiceName, GetLastError()));
    2366                 CloseServiceHandle(hSCM);
     2404                    AssertLogRelMsgFailed(("QueryServiceConfigW returned %u (cbNeeded=%u vs %zu)\n",
     2405                                           GetLastError(), cbNeeded, sizeof(uBuf)));
    23672406            }
    23682407            else
    2369                 AssertMsg(GetLastError() == ERROR_ACCESS_DENIED,
    2370                           ("Could not open service %ls: %u\n", pwszServiceName, GetLastError()));
     2408            {
     2409                DWORD dwErr = GetLastError();
     2410                fDeleteIt = dwErr != ERROR_SERVICE_DOES_NOT_EXIST;
     2411                AssertLogRelMsg(dwErr == ERROR_SERVICE_DOES_NOT_EXIST, ("OpenServiceW('%ls') -> %u\n", pwszServiceName, dwErr));
     2412            }
     2413            CloseServiceHandle(hService);
    23712414        }
    2372         else
    2373             AssertMsgFailed(("Could not open Service Manager: %u\n", GetLastError()));
    2374     }
    2375     return fRet;
    2376 }
    2377 
    2378 
    2379 /**
    2380  * Worker for uninstalling a SCM service.
    2381  *
    2382  * @returns Success indicator.
    2383  * @param   pwszServiceName The name of the SCM service.
    2384  */
    2385 static BOOL vbpsUninstallWindowsService(const WCHAR *pwszServiceName)
    2386 {
    2387     BOOL fRet = !vbpsIsInstalledWindowsService(pwszServiceName);
    2388     if (!fRet)
    2389     {
    2390         SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    2391         if (hSCM != NULL)
     2415
     2416        /*
     2417         * Step #2: Stop and delete the service if needed.
     2418         *          We can do this without reopening the service manager.
     2419         */
     2420        if (fDeleteIt)
    23922421        {
    2393             SC_HANDLE hService = OpenService(hSCM, pwszServiceName, SERVICE_STOP | DELETE);
     2422            hService = OpenServiceW(hSCM, pwszServiceName, SERVICE_STOP | DELETE);
    23942423            if (hService)
    23952424            {
    2396                 DWORD          dwErr;
    2397                 SERVICE_STATUS Status;
    2398                 RT_ZERO(Status);
    2399                 fRet = ControlService(hService, SERVICE_CONTROL_STOP, &Status);
     2425                BOOL            fRet;
     2426                DWORD           dwErr;
     2427                RT_ZERO(uBuf.Status);
     2428                SetLastError(ERROR_SERVICE_NOT_ACTIVE);
     2429                fRet = ControlService(hService, SERVICE_CONTROL_STOP, &uBuf.Status);
    24002430                dwErr = GetLastError();
    24012431                if (   fRet
    24022432                    || dwErr == ERROR_SERVICE_NOT_ACTIVE
    24032433                    || (   dwErr == ERROR_SERVICE_CANNOT_ACCEPT_CTRL
    2404                         && Status.dwCurrentState == SERVICE_STOP_PENDING) )
     2434                        && uBuf.Status.dwCurrentState == SERVICE_STOP_PENDING) )
    24052435                {
    2406                     fRet = DeleteService(hService);
    2407                     AssertMsg(fRet, ("Could not delete service %ls: %u\n", pwszServiceName, GetLastError()));
     2436                    if (DeleteService(hService))
     2437                        LogRel(("update service '%ls': deleted\n", pwszServiceName));
     2438                    else
     2439                        AssertLogRelMsgFailed(("Failed to not delete service %ls: %u\n", pwszServiceName, GetLastError()));
    24082440                }
    24092441                else
    24102442                    AssertMsg(dwErr == ERROR_ACCESS_DENIED,
    2411                               ("Could not stop service %ls: %u (state=%u)\n", pwszServiceName, dwErr, Status.dwCurrentState));
     2443                              ("Failed to stop service %ls: %u (state=%u)\n", pwszServiceName, dwErr, uBuf.Status.dwCurrentState));
    24122444                CloseServiceHandle(hService);
    24132445            }
    24142446            else
    2415                 AssertMsg(GetLastError() == ERROR_ACCESS_DENIED,
    2416                           ("Could not open service %ls: %u\n", pwszServiceName, GetLastError()));
    2417             CloseServiceHandle(hSCM);
     2447            {
     2448                pState->rc = GetLastError();
     2449                LogRel(("Failed to not open service %ls for stop+delete: %u\n", pwszServiceName, pState->rc));
     2450                hService = OpenServiceW(hSCM, pwszServiceName, SERVICE_CHANGE_CONFIG);
     2451            }
     2452            CloseServiceHandle(hService);
    24182453        }
    2419         else
    2420             AssertMsgFailed(("Could not open Service Manager: %u\n", GetLastError()));
    2421     }
    2422     return fRet;
    2423 }
    2424 
    2425 
    2426 /**
    2427  * Updates the VBoxSDS service with SCM.
    2428  *
    2429  * @param   pState              The registry modifier state.
    2430  * @param   pwszVBoxDir         The VirtualBox install directory (unicode),
    2431  *                              trailing slash.
    2432  */
    2433 static void vbpsUpdateVBoxSDSWindowsService(VBPSREGSTATE *pState, const WCHAR *pwszVBoxDir)
    2434 {
    2435     const WCHAR s_wszModuleName[]         = L"VBoxSDS.exe";
    2436     const WCHAR s_wszServiceName[]        = L"VBoxSDS";
    2437     const WCHAR s_wszServiceDisplayName[] = L"VirtualBox system service";
    2438     const WCHAR s_wszServiceDescription[] = L"Used as a COM server for VirtualBox API.";
    2439 
    2440     if (pState->fUpdate)
    2441     {
    2442         if (!vbpsInstallWindowsService(pwszVBoxDir, s_wszModuleName, s_wszServiceName,
    2443                                        s_wszServiceDisplayName, s_wszServiceDescription))
     2454
     2455        CloseServiceHandle(hSCM);
     2456
     2457        /*
     2458         * Step #3: Create the service (if requested).
     2459         *          Need to have the SC_MANAGER_CREATE_SERVICE access right for this.
     2460         */
     2461        if (fCreateIt)
    24442462        {
    2445             LogWarnFunc(("Error: Windows service '%ls' cannot be registered\n", s_wszServiceName));
    2446             pState->rc = E_FAIL;
     2463            Assert(pState->fUpdate);
     2464            hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_CREATE_SERVICE | SC_MANAGER_CONNECT);
     2465            if (hSCM)
     2466            {
     2467                hService = CreateServiceW(hSCM,
     2468                                          pwszServiceName,
     2469                                          pwszDisplayName,
     2470                                          SERVICE_ALL_ACCESS /* dwDesiredAccess */,
     2471                                          uServiceType,
     2472                                          uStartType,
     2473                                          uErrorControl,
     2474                                          wszFilePath,
     2475                                          NULL /* pwszLoadOrderGroup */,
     2476                                          NULL /* pdwTagId */,
     2477                                          wszzDependencies,
     2478                                          NULL /* pwszServiceStartName */,
     2479                                          NULL /* pwszPassword */);
     2480                if (hService != NULL)
     2481                {
     2482                    uBuf.Desc.lpDescription = (WCHAR *)pwszDescription;
     2483                    if (ChangeServiceConfig2W(hService, SERVICE_CONFIG_DESCRIPTION, &uBuf.Desc))
     2484                        LogRel(("update service '%ls': created\n", pwszServiceName));
     2485                    else
     2486                        AssertMsgFailed(("Failed to set service description for %ls: %u\n", pwszServiceName, GetLastError()));
     2487                    CloseServiceHandle(hService);
     2488                }
     2489                else
     2490                {
     2491                    pState->rc = GetLastError();
     2492                    AssertMsgFailed(("Failed to create service '%ls': %u\n", pwszServiceName, pState->rc));
     2493                }
     2494                CloseServiceHandle(hSCM);
     2495            }
     2496            else
     2497            {
     2498                pState->rc = GetLastError();
     2499                LogRel(("Failed to open service manager with create service access: %u\n", pState->rc));
     2500            }
    24472501        }
    24482502    }
    2449     else if (pState->fDelete)
    2450     {
    2451         if (!vbpsUninstallWindowsService(s_wszServiceName))
    2452         {
    2453             LogWarnFunc(("Error: Windows service '%ls' cannot be unregistered\n", s_wszServiceName));
    2454             pState->rc = E_FAIL;
    2455         }
    2456     }
    2457 }
    2458 
     2503    else
     2504        AssertLogRelMsgFailed(("OpenSCManagerW failed: %u\n", GetLastError()));
     2505}
    24592506#endif /* VBOX_WITH_SDS */
    24602507
     
    24982545
    24992546#ifdef VBOX_WITH_SDS
    2500         vbpsUpdateVBoxSDSWindowsService(&State, wszVBoxDir);
     2547        vbpsUpdateWindowsService(&State, wszVBoxDir, L"VBoxSDS.exe", L"VBoxSDS",
     2548                                 L"VirtualBox system service", L"Used as a COM server for VirtualBox API.");
    25012549#endif
    25022550        vbpsUpdateTypeLibRegistration(&State, wszVBoxDir, fIs32On64);
     
    25202568        if (rc == ERROR_SUCCESS && !vbpsIsUpToDate(&State))
    25212569        {
    2522 #ifdef VBOX_WITH_SDS
    2523             vbpsUpdateVBoxSDSWindowsService(&State, wszVBoxDir);
    2524 #endif
    25252570            vbpsUpdateTypeLibRegistration(&State, wszVBoxDir, !fIs32On64);
    25262571            vbpsUpdateProxyStubRegistration(&State, wszVBoxDir, !fIs32On64);
Note: See TracChangeset for help on using the changeset viewer.

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