extern "C" HRESULT DetectForwardCompatibleBundle( __in BURN_USER_EXPERIENCE* pUX, __in BOOTSTRAPPER_COMMAND* pCommand, __in BURN_REGISTRATION* pRegistration ) { HRESULT hr = S_OK; int nRecommendation = IDNOACTION; if (pRegistration->sczDetectedProviderKeyBundleId && CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->sczDetectedProviderKeyBundleId, -1, pRegistration->sczId, -1)) { // Only change the recommendation if an parent was provided. if (pRegistration->sczActiveParent && *pRegistration->sczActiveParent) { // On install, recommend running the forward compatible bundle because there is an active parent. This // will essentially register the parent with the forward compatible bundle. if (BOOTSTRAPPER_ACTION_INSTALL == pCommand->action) { nRecommendation = IDOK; } else if (BOOTSTRAPPER_ACTION_UNINSTALL == pCommand->action || BOOTSTRAPPER_ACTION_MODIFY == pCommand->action || BOOTSTRAPPER_ACTION_REPAIR == pCommand->action) { // When modifying the bundle, only recommend running the forward compatible bundle if the parent // is already registered as a dependent of the provider key. if (DependencyDependentExists(pRegistration, pRegistration->sczActiveParent)) { nRecommendation = IDOK; } } } for (DWORD iRelatedBundle = 0; iRelatedBundle < pRegistration->relatedBundles.cRelatedBundles; ++iRelatedBundle) { BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + iRelatedBundle; if (BOOTSTRAPPER_RELATION_UPGRADE == pRelatedBundle->relationType && pRegistration->qwVersion <= pRelatedBundle->qwVersion && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->sczDetectedProviderKeyBundleId, -1, pRelatedBundle->package.sczId, -1)) { int nResult = pUX->pUserExperience->OnDetectForwardCompatibleBundle(pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->qwVersion, nRecommendation); hr = UserExperienceInterpretResult(pUX, MB_OKCANCEL, nResult); ExitOnRootFailure(hr, "BA aborted detect forward compatible bundle."); if (IDOK == nResult) { hr = PseudoBundleInitializePassthrough(&pRegistration->forwardCompatibleBundle, pCommand, NULL, pRegistration->sczActiveParent, pRegistration->sczAncestors, &pRelatedBundle->package); ExitOnFailure(hr, "Failed to initialize update bundle."); pRegistration->fEnabledForwardCompatibleBundle = TRUE; } LogId(REPORT_STANDARD, MSG_DETECTED_FORWARD_COMPATIBLE_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), LoggingVersionToString(pRelatedBundle->qwVersion), LoggingBoolToString(pRegistration->fEnabledForwardCompatibleBundle)); break; } } } LExit: return hr; }
extern "C" HRESULT EngineRun( __in HINSTANCE hInstance, __in_z_opt LPCWSTR wzCommandLine, __in int nCmdShow, __out DWORD* pdwExitCode ) { HRESULT hr = S_OK; BOOL fComInitialized = FALSE; BOOL fLogInitialized = FALSE; BOOL fRegInitialized = FALSE; BOOL fWiuInitialized = FALSE; BOOL fXmlInitialized = FALSE; OSVERSIONINFOEXW ovix = { }; LPWSTR sczExePath = NULL; BOOL fRunNormal = FALSE; BOOL fRestart = FALSE; BURN_ENGINE_STATE engineState = { }; hr = InitializeEngineState(&engineState); ExitOnFailure(hr, "Failed to initialize engine state."); engineState.command.nCmdShow = nCmdShow; // Ensure that log contains approriate level of information #ifdef _DEBUG LogSetLevel(REPORT_DEBUG, FALSE); #else LogSetLevel(REPORT_VERBOSE, FALSE); // FALSE means don't write an additional text line to the log saying the level changed #endif // initialize platform layer PlatformInitialize(); // initialize COM hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); ExitOnFailure(hr, "Failed to initialize COM."); fComInitialized = TRUE; // Initialize dutil. LogInitialize(::GetModuleHandleW(NULL)); fLogInitialized = TRUE; hr = RegInitialize(); ExitOnFailure(hr, "Failed to initialize Regutil."); fRegInitialized = TRUE; hr = WiuInitialize(); ExitOnFailure(hr, "Failed to initialize Wiutil."); fWiuInitialized = TRUE; hr = XmlInitialize(); ExitOnFailure(hr, "Failed to initialize XML util."); fXmlInitialized = TRUE; ovix.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); if (!::GetVersionExW((LPOSVERSIONINFOW)&ovix)) { ExitWithLastError(hr, "Failed to get OS info."); } PathForCurrentProcess(&sczExePath, NULL); // Ignore failure. LogId(REPORT_STANDARD, MSG_BURN_INFO, szVerMajorMinorBuild, ovix.dwMajorVersion, ovix.dwMinorVersion, ovix.dwBuildNumber, ovix.wServicePackMajor, sczExePath, wzCommandLine ? wzCommandLine : L""); ReleaseNullStr(sczExePath); // initialize core hr = CoreInitialize(wzCommandLine, &engineState); ExitOnFailure(hr, "Failed to initialize core."); // select run mode switch (engineState.mode) { case BURN_MODE_NORMAL: fRunNormal = TRUE; hr = RunNormal(hInstance, &engineState); ExitOnFailure(hr, "Failed to run per-user mode."); break; case BURN_MODE_ELEVATED: hr = RunElevated(hInstance, wzCommandLine, &engineState); ExitOnFailure(hr, "Failed to run per-machine mode."); break; case BURN_MODE_EMBEDDED: fRunNormal = TRUE; hr = RunEmbedded(hInstance, &engineState); ExitOnFailure(hr, "Failed to run embedded mode."); break; case BURN_MODE_RUNONCE: hr = RunRunOnce(wzCommandLine, nCmdShow); ExitOnFailure(hr, "Failed to run RunOnce mode."); break; default: hr = E_UNEXPECTED; ExitOnFailure(hr, "Invalid run mode."); } // set exit code and remember if we are supposed to restart. *pdwExitCode = engineState.userExperience.dwExitCode; fRestart = engineState.fRestart; LExit: ReleaseStr(sczExePath); // If anything went wrong but the log was never open, try to open a "failure" log // and that will dump anything captured in the log memory buffer to the log. if (FAILED(hr) && BURN_LOGGING_STATE_CLOSED == engineState.log.state) { LogOpen(NULL, L"Setup", L"_Failed", L"txt", FALSE, FALSE, NULL); } UserExperienceRemove(&engineState.userExperience); CacheRemoveWorkingFolder(engineState.registration.sczId); // If this is a related bundle (but not an update) suppress restart and return the standard restart error code. if (fRestart && BOOTSTRAPPER_RELATION_NONE != engineState.command.relationType && BOOTSTRAPPER_RELATION_UPDATE != engineState.command.relationType) { LogId(REPORT_STANDARD, MSG_RESTART_ABORTED, LoggingRelationTypeToString(engineState.command.relationType)); fRestart = FALSE; hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED); } UninitializeEngineState(&engineState); if (fXmlInitialized) { XmlUninitialize(); } if (fWiuInitialized) { WiuUninitialize(); } if (fRegInitialized) { RegUninitialize(); } if (fComInitialized) { ::CoUninitialize(); } if (fRunNormal) { LogId(REPORT_STANDARD, MSG_EXITING, FAILED(hr) ? (int)hr : *pdwExitCode, LoggingBoolToString(fRestart)); if (fRestart) { LogId(REPORT_STANDARD, MSG_RESTARTING); } } if (fLogInitialized) { LogClose(FALSE); } if (fRestart) { Restart(); } if (fLogInitialized) { LogUninitialize(FALSE); } return hr; }
extern "C" HRESULT DetectReportRelatedBundles( __in BURN_USER_EXPERIENCE* pUX, __in BURN_REGISTRATION* pRegistration, __in BOOTSTRAPPER_RELATION_TYPE relationType, __in BOOTSTRAPPER_ACTION action ) { HRESULT hr = S_OK; for (DWORD iRelatedBundle = 0; iRelatedBundle < pRegistration->relatedBundles.cRelatedBundles; ++iRelatedBundle) { const BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + iRelatedBundle; BOOTSTRAPPER_RELATED_OPERATION operation = BOOTSTRAPPER_RELATED_OPERATION_NONE; switch (pRelatedBundle->relationType) { case BOOTSTRAPPER_RELATION_UPGRADE: if (BOOTSTRAPPER_RELATION_UPGRADE != relationType && BOOTSTRAPPER_ACTION_UNINSTALL < action) { if (pRegistration->qwVersion > pRelatedBundle->qwVersion) { operation = BOOTSTRAPPER_RELATED_OPERATION_MAJOR_UPGRADE; } else if (pRegistration->qwVersion < pRelatedBundle->qwVersion) { operation = BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE; } } break; case BOOTSTRAPPER_RELATION_PATCH: __fallthrough; case BOOTSTRAPPER_RELATION_ADDON: if (BOOTSTRAPPER_ACTION_UNINSTALL == action) { operation = BOOTSTRAPPER_RELATED_OPERATION_REMOVE; } else if (BOOTSTRAPPER_ACTION_INSTALL == action || BOOTSTRAPPER_ACTION_MODIFY == action) { operation = BOOTSTRAPPER_RELATED_OPERATION_INSTALL; } else if (BOOTSTRAPPER_ACTION_REPAIR == action) { operation = BOOTSTRAPPER_RELATED_OPERATION_REPAIR; } break; case BOOTSTRAPPER_RELATION_DETECT: __fallthrough; case BOOTSTRAPPER_RELATION_DEPENDENT: break; default: hr = E_FAIL; ExitOnRootFailure1(hr, "Unexpected relation type encountered: %d", pRelatedBundle->relationType); break; } LogId(REPORT_STANDARD, MSG_DETECTED_RELATED_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), LoggingVersionToString(pRelatedBundle->qwVersion), LoggingRelatedOperationToString(operation)); int nResult = pUX->pUserExperience->OnDetectRelatedBundle(pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->qwVersion, operation); hr = UserExperienceInterpretResult(pUX, MB_OKCANCEL, nResult); ExitOnRootFailure(hr, "BA aborted detect related bundle."); } LExit: return hr; }