Changeset 69810 in vbox for trunk/src/VBox/Main/src-all
- Timestamp:
- Nov 22, 2017 5:53:44 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-all/win/VBoxProxyStub.c
r69733 r69810 2298 2298 2299 2299 #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. 2323 2304 * @param pwszVBoxDir The VirtualBox install directory (unicode), 2324 2305 * trailing slash. … … 2328 2309 * @param pwszDescription The service description. 2329 2310 */ 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)) 2311 static 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 2346 2343 { 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) 2349 2360 { 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)) 2355 2363 { 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 } 2363 2402 } 2364 2403 else 2365 Assert MsgFailed(("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))); 2367 2406 } 2368 2407 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); 2371 2414 } 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) 2392 2421 { 2393 SC_HANDLE hService = OpenService(hSCM, pwszServiceName, SERVICE_STOP | DELETE);2422 hService = OpenServiceW(hSCM, pwszServiceName, SERVICE_STOP | DELETE); 2394 2423 if (hService) 2395 2424 { 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); 2400 2430 dwErr = GetLastError(); 2401 2431 if ( fRet 2402 2432 || dwErr == ERROR_SERVICE_NOT_ACTIVE 2403 2433 || ( dwErr == ERROR_SERVICE_CANNOT_ACCEPT_CTRL 2404 && Status.dwCurrentState == SERVICE_STOP_PENDING) )2434 && uBuf.Status.dwCurrentState == SERVICE_STOP_PENDING) ) 2405 2435 { 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())); 2408 2440 } 2409 2441 else 2410 2442 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)); 2412 2444 CloseServiceHandle(hService); 2413 2445 } 2414 2446 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); 2418 2453 } 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) 2444 2462 { 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 } 2447 2501 } 2448 2502 } 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 } 2459 2506 #endif /* VBOX_WITH_SDS */ 2460 2507 … … 2498 2545 2499 2546 #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."); 2501 2549 #endif 2502 2550 vbpsUpdateTypeLibRegistration(&State, wszVBoxDir, fIs32On64); … … 2520 2568 if (rc == ERROR_SUCCESS && !vbpsIsUpToDate(&State)) 2521 2569 { 2522 #ifdef VBOX_WITH_SDS2523 vbpsUpdateVBoxSDSWindowsService(&State, wszVBoxDir);2524 #endif2525 2570 vbpsUpdateTypeLibRegistration(&State, wszVBoxDir, !fIs32On64); 2526 2571 vbpsUpdateProxyStubRegistration(&State, wszVBoxDir, !fIs32On64);
Note:
See TracChangeset
for help on using the changeset viewer.