static HRESULT EnsureWUServiceEnabled( __in BOOL fStopWusaService, __out SC_HANDLE* pschWu, __out BOOL* pfPreviouslyDisabled ) { HRESULT hr = S_OK; SC_HANDLE schSCM = NULL; SC_HANDLE schWu = NULL; SERVICE_STATUS serviceStatus = { }; QUERY_SERVICE_CONFIGW* pConfig = NULL; schSCM = ::OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); ExitOnNullWithLastError(schSCM, hr, "Failed to open service control manager."); schWu = ::OpenServiceW(schSCM, L"wuauserv", SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS | SERVICE_STOP ); ExitOnNullWithLastError(schWu, hr, "Failed to open WU service."); if (!::QueryServiceStatus(schWu, &serviceStatus) ) { ExitWithLastError(hr, "Failed to query status of WU service."); } // Stop service if requested to. if (SERVICE_STOPPED != serviceStatus.dwCurrentState && fStopWusaService) { hr = StopWUService(schWu); } // If the service is not running then it might be disabled so let's check. if (SERVICE_RUNNING != serviceStatus.dwCurrentState) { hr = SvcQueryConfig(schWu, &pConfig); ExitOnFailure(hr, "Failed to read configuration for WU service."); // If WU is disabled, change it to a demand start service (but touch nothing else). if (SERVICE_DISABLED == pConfig->dwStartType) { hr = SetServiceStartType(schWu, SERVICE_DEMAND_START); ExitOnFailure(hr, "Failed to mark WU service to start on demand."); *pfPreviouslyDisabled = TRUE; } } *pschWu = schWu; schWu = NULL; LExit: ReleaseMem(pConfig); ReleaseServiceHandle(schWu); ReleaseServiceHandle(schSCM); return hr; }
extern "C" HRESULT MsuEngineExecutePackage( __in BURN_EXECUTE_ACTION* pExecuteAction, __in BOOL fRollback, __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler, __in LPVOID pvContext, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ) { HRESULT hr = S_OK; int nResult = IDNOACTION; LPWSTR sczCachedDirectory = NULL; LPWSTR sczMsuPath = NULL; LPWSTR sczSystemPath = NULL; LPWSTR sczWusaPath = NULL; LPWSTR sczCommand = NULL; SC_HANDLE schWu = NULL; BOOL fWuWasDisabled = FALSE; STARTUPINFOW si = { }; PROCESS_INFORMATION pi = { }; GENERIC_EXECUTE_MESSAGE message = { }; DWORD dwExitCode = 0; BOOL fDoDependency = FALSE; // get wusa.exe path hr = PathGetKnownFolder(CSIDL_SYSTEM, &sczSystemPath); ExitOnFailure(hr, "Failed to find System32 directory."); hr = PathConcat(sczSystemPath, L"wusa.exe", &sczWusaPath); ExitOnFailure(hr, "Failed to allocate WUSA.exe path."); // build command switch (pExecuteAction->msuPackage.action) { case BOOTSTRAPPER_ACTION_STATE_INSTALL: // get cached executable path hr = CacheGetCompletedPath(TRUE, pExecuteAction->msuPackage.pPackage->sczCacheId, &sczCachedDirectory); ExitOnFailure1(hr, "Failed to get cached path for package: %ls", pExecuteAction->msuPackage.pPackage->sczId); hr = PathConcat(sczCachedDirectory, pExecuteAction->msuPackage.pPackage->rgPayloads[0].pPayload->sczFilePath, &sczMsuPath); ExitOnFailure(hr, "Failed to build executable path."); // format command hr = StrAllocFormatted(&sczCommand, L"\"%ls\" \"%ls\" /quiet /norestart", sczWusaPath, sczMsuPath); ExitOnFailure(hr, "Failed to format MSU install command."); break; case BOOTSTRAPPER_ACTION_STATE_UNINSTALL: // format command hr = StrAllocFormatted(&sczCommand, L"\"%ls\" /uninstall /kb:%ls /quiet /norestart", sczWusaPath, pExecuteAction->msuPackage.pPackage->Msu.sczKB); ExitOnFailure(hr, "Failed to format MSU uninstall command."); break; default: hr = E_UNEXPECTED; ExitOnFailure(hr, "Failed to get action arguments for MSU package."); } if (pExecuteAction->msuPackage.sczLogPath && *pExecuteAction->msuPackage.sczLogPath) { hr = StrAllocConcat(&sczCommand, L" /log:", 0); ExitOnFailure(hr, "Failed to append log switch to MSU command-line."); hr = StrAllocConcat(&sczCommand, pExecuteAction->msuPackage.sczLogPath, 0); ExitOnFailure(hr, "Failed to append log path to MSU command-line."); } LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pExecuteAction->msuPackage.pPackage->sczId, LoggingActionStateToString(pExecuteAction->msuPackage.action), sczMsuPath ? sczMsuPath : pExecuteAction->msuPackage.pPackage->Msu.sczKB, sczCommand); hr = EnsureWUServiceEnabled(&schWu, &fWuWasDisabled); ExitOnFailure(hr, "Failed to ensure WU service was enabled to install MSU package."); // create process si.cb = sizeof(si); if (!::CreateProcessW(sczWusaPath, sczCommand, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { ExitWithLastError1(hr, "Failed to CreateProcess on path: %ls", sczWusaPath); } do { message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; message.dwAllowedResults = MB_OKCANCEL; message.progress.dwPercentage = 50; nResult = pfnGenericMessageHandler(&message, pvContext); hr = (IDOK == nResult || IDNOACTION == nResult) ? S_OK : IDCANCEL == nResult ? HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) : HRESULT_FROM_WIN32(ERROR_INSTALL_FAILURE); ExitOnRootFailure(hr, "Bootstrapper application aborted during MSU progress."); // wait for process to terminate hr = ProcWaitForCompletion(pi.hProcess, 500, &dwExitCode); if (HRESULT_FROM_WIN32(WAIT_TIMEOUT) != hr) { ExitOnFailure1(hr, "Failed to wait for executable to complete: %ls", sczWusaPath); } } while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr); // get process exit code if (!::GetExitCodeProcess(pi.hProcess, &dwExitCode)) { ExitWithLastError(hr, "Failed to get process exit code."); } // We'll normalize the restart required error code from wusa.exe just in case. Most likely // that on reboot we'll actually get WU_S_REBOOT_REQUIRED. if (HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED) == static_cast<HRESULT>(dwExitCode)) { dwExitCode = ERROR_SUCCESS_REBOOT_REQUIRED; } // handle exit code switch (dwExitCode) { case S_OK: __fallthrough; case WU_S_ALREADY_INSTALLED: fDoDependency = TRUE; __fallthrough; case S_FALSE: __fallthrough; case WU_E_NOT_APPLICABLE: *pRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; hr = S_OK; break; case ERROR_SUCCESS_REBOOT_REQUIRED: __fallthrough; case WU_S_REBOOT_REQUIRED: fDoDependency = TRUE; *pRestart = BOOTSTRAPPER_APPLY_RESTART_REQUIRED; hr = S_OK; break; default: hr = E_UNEXPECTED; break; } if (fDoDependency) { if (BOOTSTRAPPER_ACTION_STATE_INSTALL == pExecuteAction->msuPackage.action) { hr = DependencyRegisterPackage(pExecuteAction->msuPackage.pPackage); ExitOnFailure(hr, "Failed to register the package dependency providers."); } else if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pExecuteAction->msuPackage.action) { hr = DependencyUnregisterPackage(pExecuteAction->msuPackage.pPackage); ExitOnFailure(hr, "Failed to unregister the package dependency providers."); } } LExit: ReleaseStr(sczCachedDirectory); ReleaseStr(sczMsuPath); ReleaseStr(sczSystemPath); ReleaseStr(sczWusaPath); ReleaseStr(sczCommand); ReleaseHandle(pi.hProcess); ReleaseHandle(pi.hThread); if (fWuWasDisabled) { SetServiceStartType(schWu, SERVICE_DISABLED); } return hr; }