From fd8c2b0899bfbce07386af245c04eb21dc01cbdf Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Tue, 2 Feb 2021 18:09:58 -0600 Subject: Update the logic for determining when the bundle should be registered. The basic rule is that if a non-permanent package is present at the end of the chain, then the bundle should be registered. If no non-permanent packages are present at the end of the chain, then the bundle should not be registered. This required tracking what actually happened with each package during Apply. Include cache status in registration calculation. Include dependency ref-counting when determining whether the bundle should be registered. --- src/engine/apply.cpp | 247 ++++++++++++++++++++++++------ src/engine/apply.h | 4 +- src/engine/core.cpp | 18 ++- src/engine/dependency.cpp | 29 ++++ src/engine/detect.cpp | 2 + src/engine/engine.mc | 19 ++- src/engine/exeengine.cpp | 30 ++++ src/engine/exeengine.h | 4 + src/engine/logging.cpp | 25 +++ src/engine/logging.h | 5 + src/engine/msiengine.cpp | 41 +++++ src/engine/msiengine.h | 5 + src/engine/mspengine.cpp | 109 ++++++++++++- src/engine/mspengine.h | 8 + src/engine/msuengine.cpp | 30 ++++ src/engine/msuengine.h | 4 + src/engine/package.cpp | 1 + src/engine/package.h | 18 +++ src/engine/plan.cpp | 192 ++++++++--------------- src/engine/plan.h | 18 +-- src/test/BurnUnitTest/BurnTestFixture.h | 2 + src/test/BurnUnitTest/PlanTest.cpp | 260 ++++++++++++++++++++++++-------- 22 files changed, 804 insertions(+), 267 deletions(-) (limited to 'src') diff --git a/src/engine/apply.cpp b/src/engine/apply.cpp index 76831461..8d2f5757 100644 --- a/src/engine/apply.cpp +++ b/src/engine/apply.cpp @@ -46,6 +46,10 @@ static HRESULT WINAPI AuthenticationRequired( __out BOOL* pfRetry ); +static void CalculateKeepRegistration( + __in BURN_ENGINE_STATE* pEngineState, + __inout BOOL* pfKeepRegistration + ); static HRESULT ExecuteDependentRegistrationActions( __in HANDLE hPipe, __in const BURN_REGISTRATION* pRegistration, @@ -141,7 +145,6 @@ static HRESULT DoExecuteAction( __in BURN_EXECUTE_CONTEXT* pContext, __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary, __inout BURN_EXECUTE_ACTION_CHECKPOINT** ppCheckpoint, - __out BOOL* pfKeepRegistration, __out BOOL* pfSuspend, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ); @@ -149,7 +152,6 @@ static HRESULT DoRollbackActions( __in BURN_ENGINE_STATE* pEngineState, __in BURN_EXECUTE_CONTEXT* pContext, __in DWORD dwCheckpoint, - __out BOOL* pfKeepRegistration, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ); static HRESULT ExecuteExePackage( @@ -165,6 +167,7 @@ static HRESULT ExecuteMsiPackage( __in BURN_ENGINE_STATE* pEngineState, __in BURN_EXECUTE_ACTION* pExecuteAction, __in BURN_EXECUTE_CONTEXT* pContext, + __in BOOL fInsideMsiTransaction, __in BOOL fRollback, __out BOOL* pfRetry, __out BOOL* pfSuspend, @@ -174,6 +177,7 @@ static HRESULT ExecuteMspPackage( __in BURN_ENGINE_STATE* pEngineState, __in BURN_EXECUTE_ACTION* pExecuteAction, __in BURN_EXECUTE_CONTEXT* pContext, + __in BOOL fInsideMsiTransaction, __in BOOL fRollback, __out BOOL* pfRetry, __out BOOL* pfSuspend, @@ -214,6 +218,10 @@ static HRESULT ExecuteMsiRollbackTransaction( __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary, __in BURN_EXECUTE_CONTEXT* pContext ); +static void ResetTransactionRegistrationState( + __in BURN_ENGINE_STATE* pEngineState, + __in BOOL fCommit + ); static HRESULT CleanPackage( __in HANDLE hElevatedPipe, __in BURN_PACKAGE* pPackage @@ -282,6 +290,7 @@ extern "C" void ApplyReset( { BURN_PACKAGE* pPackage = pPackages->rgPackages + i; pPackage->hrCacheResult = S_OK; + pPackage->transactionRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; } } @@ -380,13 +389,15 @@ LExit: extern "C" HRESULT ApplyUnregister( __in BURN_ENGINE_STATE* pEngineState, __in BOOL fFailedOrRollback, - __in BOOL fKeepRegistration, __in BOOL fSuspend, __in BOOTSTRAPPER_APPLY_RESTART restart ) { HRESULT hr = S_OK; BURN_RESUME_MODE resumeMode = BURN_RESUME_MODE_NONE; + BOOL fKeepRegistration = pEngineState->plan.fDisallowRemoval; + + CalculateKeepRegistration(pEngineState, &fKeepRegistration); hr = UserExperienceOnUnregisterBegin(&pEngineState->userExperience); ExitOnRootFailure(hr, "BA aborted unregister begin."); @@ -443,7 +454,7 @@ extern "C" HRESULT ApplyCache( __in BURN_PLAN* pPlan, __in HANDLE hPipe, __inout DWORD* pcOverallProgressTicks, - __out BOOL* pfRollback + __inout BOOL* pfRollback ) { HRESULT hr = S_OK; @@ -732,7 +743,6 @@ extern "C" HRESULT ApplyExecute( __in BURN_ENGINE_STATE* pEngineState, __in_opt HANDLE hCacheThread, __inout DWORD* pcOverallProgressTicks, - __inout BOOL* pfKeepRegistration, __out BOOL* pfRollback, __out BOOL* pfSuspend, __out BOOTSTRAPPER_APPLY_RESTART* pRestart @@ -779,7 +789,7 @@ extern "C" HRESULT ApplyExecute( } // Execute the action. - hr = DoExecuteAction(pEngineState, pExecuteAction, hCacheThread, &context, &pRollbackBoundary, &pCheckpoint, pfKeepRegistration, pfSuspend, pRestart); + hr = DoExecuteAction(pEngineState, pExecuteAction, hCacheThread, &context, &pRollbackBoundary, &pCheckpoint, pfSuspend, pRestart); if (*pfSuspend || BOOTSTRAPPER_APPLY_RESTART_INITIATED == *pRestart) { @@ -821,7 +831,7 @@ extern "C" HRESULT ApplyExecute( // The action failed, roll back to previous rollback boundary. if (pCheckpoint) { - hrRollback = DoRollbackActions(pEngineState, &context, pCheckpoint->dwId, pfKeepRegistration, pRestart); + hrRollback = DoRollbackActions(pEngineState, &context, pCheckpoint->dwId, pRestart); IgnoreRollbackError(hrRollback, "Failed rollback actions"); } @@ -855,14 +865,46 @@ extern "C" void ApplyClean( for (DWORD i = 0; i < pPlan->cCleanActions; ++i) { BURN_CLEAN_ACTION* pCleanAction = pPlan->rgCleanActions + i; + BURN_PACKAGE* pPackage = pCleanAction->pPackage; - hr = CleanPackage(hPipe, pCleanAction->pPackage); + hr = CleanPackage(hPipe, pPackage); } } // internal helper functions +static void CalculateKeepRegistration( + __in BURN_ENGINE_STATE* pEngineState, + __inout BOOL* pfKeepRegistration + ) +{ + LogId(REPORT_STANDARD, MSG_POST_APPLY_CALCULATE_REGISTRATION); + + for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i) + { + BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i; + + LogId(REPORT_STANDARD, MSG_POST_APPLY_PACKAGE, pPackage->sczId, LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->installRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->cacheRegistrationState)); + + if (!pPackage->fCanAffectRegistration) + { + continue; + } + + if (BURN_PACKAGE_TYPE_MSP == pPackage->type) + { + MspEngineFinalizeInstallRegistrationState(pPackage); + } + + if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->installRegistrationState || + BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->cacheRegistrationState) + { + *pfKeepRegistration = TRUE; + } + } +} + static HRESULT ExecuteDependentRegistrationActions( __in HANDLE hPipe, __in const BURN_REGISTRATION* pRegistration, @@ -1255,6 +1297,15 @@ static HRESULT LayoutOrCacheContainerOrPayload( LARGE_INTEGER liContainerOrPayloadSize = { }; LARGE_INTEGER liZero = { }; BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT progress = { }; + BOOL fCanAffectRegistration = FALSE; + + if (!wzLayoutDirectory) + { + Assert(!pContainer); + Assert(pPackage); + + fCanAffectRegistration = pPackage->fCanAffectRegistration; + } liContainerOrPayloadSize.QuadPart = pContainer ? pContainer->qwFileSize : pPayload->qwFileSize; @@ -1297,9 +1348,6 @@ static HRESULT LayoutOrCacheContainerOrPayload( } else // complete the payload. { - Assert(!pContainer); - Assert(pPackage); - hr = CacheCompletePayload(pPackage->fPerMachine, pPayload, pPackage->sczCacheId, wzUnverifiedPath, fMove); } @@ -1307,6 +1355,11 @@ static HRESULT LayoutOrCacheContainerOrPayload( // will get. if (SUCCEEDED(hr)) { + if (fCanAffectRegistration) + { + pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; + } + CacheProgressRoutine(liContainerOrPayloadSize, liContainerOrPayloadSize, liZero, liZero, 0, 0, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, &progress); if (progress.fCancel) { @@ -1639,7 +1692,6 @@ static HRESULT DoExecuteAction( __in BURN_EXECUTE_CONTEXT* pContext, __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary, __inout BURN_EXECUTE_ACTION_CHECKPOINT** ppCheckpoint, - __out BOOL* pfKeepRegistration, __out BOOL* pfSuspend, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ) @@ -1651,11 +1703,14 @@ static HRESULT DoExecuteAction( BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE; BOOL fRetry = FALSE; BOOL fStopWusaService = FALSE; + BOOL fInsideMsiTransaction = FALSE; pContext->fRollback = FALSE; do { + fInsideMsiTransaction = *ppRollbackBoundary && (*ppRollbackBoundary)->fActiveTransaction; + switch (pExecuteAction->type) { case BURN_EXECUTE_ACTION_TYPE_CHECKPOINT: @@ -1695,12 +1750,12 @@ static HRESULT DoExecuteAction( break; case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: - hr = ExecuteMsiPackage(pEngineState, pExecuteAction, pContext, FALSE, &fRetry, pfSuspend, &restart); + hr = ExecuteMsiPackage(pEngineState, pExecuteAction, pContext, fInsideMsiTransaction, FALSE, &fRetry, pfSuspend, &restart); ExitOnFailure(hr, "Failed to execute MSI package."); break; case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET: - hr = ExecuteMspPackage(pEngineState, pExecuteAction, pContext, FALSE, &fRetry, pfSuspend, &restart); + hr = ExecuteMspPackage(pEngineState, pExecuteAction, pContext, fInsideMsiTransaction, FALSE, &fRetry, pfSuspend, &restart); ExitOnFailure(hr, "Failed to execute MSP package."); break; @@ -1720,8 +1775,6 @@ static HRESULT DoExecuteAction( ExitOnFailure(hr, "Failed to execute dependency action."); break; - case BURN_EXECUTE_ACTION_TYPE_REGISTRATION: - *pfKeepRegistration = pExecuteAction->registration.fKeep; break; case BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY: @@ -1757,7 +1810,6 @@ static HRESULT DoRollbackActions( __in BURN_ENGINE_STATE* pEngineState, __in BURN_EXECUTE_CONTEXT* pContext, __in DWORD dwCheckpoint, - __out BOOL* pfKeepRegistration, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ) { @@ -1811,12 +1863,12 @@ static HRESULT DoRollbackActions( break; case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: - hr = ExecuteMsiPackage(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart); + hr = ExecuteMsiPackage(pEngineState, pRollbackAction, pContext, FALSE, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart); IgnoreRollbackError(hr, "Failed to rollback MSI package."); break; case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET: - hr = ExecuteMspPackage(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart); + hr = ExecuteMspPackage(pEngineState, pRollbackAction, pContext, FALSE, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart); IgnoreRollbackError(hr, "Failed to rollback MSP package."); break; @@ -1835,10 +1887,6 @@ static HRESULT DoRollbackActions( IgnoreRollbackError(hr, "Failed to rollback dependency action."); break; - case BURN_EXECUTE_ACTION_TYPE_REGISTRATION: - *pfKeepRegistration = pRollbackAction->registration.fKeep; - break; - case BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY: ExitFunction1(hr = S_OK); @@ -1878,19 +1926,21 @@ static HRESULT ExecuteExePackage( GENERIC_EXECUTE_MESSAGE message = { }; int nResult = 0; BOOL fBeginCalled = FALSE; + BOOL fExecuted = FALSE; + BURN_PACKAGE* pPackage = pExecuteAction->exePackage.pPackage; - if (FAILED(pExecuteAction->exePackage.pPackage->hrCacheResult)) + if (FAILED(pPackage->hrCacheResult)) { - LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pExecuteAction->exePackage.pPackage->sczId, pExecuteAction->exePackage.pPackage->hrCacheResult); + LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult); ExitFunction1(hr = S_OK); } Assert(pContext->fRollback == fRollback); - pContext->pExecutingPackage = pExecuteAction->exePackage.pPackage; + pContext->pExecutingPackage = pPackage; fBeginCalled = TRUE; // Send package execute begin to BA. - hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pExecuteAction->exePackage.pPackage->sczId, !fRollback, pExecuteAction->exePackage.action, INSTALLUILEVEL_NOCHANGE, FALSE); + hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pPackage->sczId, !fRollback, pExecuteAction->exePackage.action, INSTALLUILEVEL_NOCHANGE, FALSE); ExitOnRootFailure(hr, "BA aborted execute EXE package begin."); message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; @@ -1900,8 +1950,10 @@ static HRESULT ExecuteExePackage( hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwAllowedResults, nResult); ExitOnRootFailure(hr, "BA aborted EXE progress."); + fExecuted = TRUE; + // Execute package. - if (pExecuteAction->exePackage.pPackage->fPerMachine) + if (pPackage->fPerMachine) { hrExecute = ElevationExecuteExePackage(pEngineState->companionConnection.hPipe, pExecuteAction, &pEngineState->variables, fRollback, GenericExecuteMessageHandler, pContext, pRestart); ExitOnFailure(hrExecute, "Failed to configure per-machine EXE package."); @@ -1926,9 +1978,14 @@ static HRESULT ExecuteExePackage( ExitOnRootFailure(hr, "BA aborted EXE package execute progress."); LExit: + if (fExecuted) + { + ExeEngineUpdateInstallRegistrationState(pExecuteAction, hrExecute); + } + if (fBeginCalled) { - hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pExecuteAction->exePackage.pPackage, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend); + hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend); } return hr; @@ -1938,6 +1995,7 @@ static HRESULT ExecuteMsiPackage( __in BURN_ENGINE_STATE* pEngineState, __in BURN_EXECUTE_ACTION* pExecuteAction, __in BURN_EXECUTE_CONTEXT* pContext, + __in BOOL fInsideMsiTransaction, __in BOOL fRollback, __out BOOL* pfRetry, __out BOOL* pfSuspend, @@ -1947,23 +2005,27 @@ static HRESULT ExecuteMsiPackage( HRESULT hr = S_OK; HRESULT hrExecute = S_OK; BOOL fBeginCalled = FALSE; + BOOL fExecuted = FALSE; + BURN_PACKAGE* pPackage = pExecuteAction->msiPackage.pPackage; - if (FAILED(pExecuteAction->msiPackage.pPackage->hrCacheResult)) + if (FAILED(pPackage->hrCacheResult)) { - LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pExecuteAction->msiPackage.pPackage->sczId, pExecuteAction->msiPackage.pPackage->hrCacheResult); + LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult); ExitFunction1(hr = S_OK); } Assert(pContext->fRollback == fRollback); - pContext->pExecutingPackage = pExecuteAction->msiPackage.pPackage; + pContext->pExecutingPackage = pPackage; fBeginCalled = TRUE; // Send package execute begin to BA. - hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pExecuteAction->msiPackage.pPackage->sczId, !fRollback, pExecuteAction->msiPackage.action, pExecuteAction->msiPackage.uiLevel, pExecuteAction->msiPackage.fDisableExternalUiHandler); + hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pPackage->sczId, !fRollback, pExecuteAction->msiPackage.action, pExecuteAction->msiPackage.uiLevel, pExecuteAction->msiPackage.fDisableExternalUiHandler); ExitOnRootFailure(hr, "BA aborted execute MSI package begin."); + fExecuted = TRUE; + // execute package - if (pExecuteAction->msiPackage.pPackage->fPerMachine) + if (pPackage->fPerMachine) { hrExecute = ElevationExecuteMsiPackage(pEngineState->companionConnection.hPipe, pEngineState->userExperience.hwndApply, pExecuteAction, &pEngineState->variables, fRollback, MsiExecuteMessageHandler, pContext, pRestart); ExitOnFailure(hrExecute, "Failed to configure per-machine MSI package."); @@ -1981,9 +2043,14 @@ static HRESULT ExecuteMsiPackage( ExitOnRootFailure(hr, "BA aborted MSI package execute progress."); LExit: + if (fExecuted) + { + MsiEngineUpdateInstallRegistrationState(pExecuteAction, hrExecute, fInsideMsiTransaction); + } + if (fBeginCalled) { - hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pExecuteAction->msiPackage.pPackage, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend); + hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend); } return hr; @@ -1993,6 +2060,7 @@ static HRESULT ExecuteMspPackage( __in BURN_ENGINE_STATE* pEngineState, __in BURN_EXECUTE_ACTION* pExecuteAction, __in BURN_EXECUTE_CONTEXT* pContext, + __in BOOL fInsideMsiTransaction, __in BOOL fRollback, __out BOOL* pfRetry, __out BOOL* pfSuspend, @@ -2002,19 +2070,21 @@ static HRESULT ExecuteMspPackage( HRESULT hr = S_OK; HRESULT hrExecute = S_OK; BOOL fBeginCalled = FALSE; + BOOL fExecuted = FALSE; + BURN_PACKAGE* pPackage = pExecuteAction->mspTarget.pPackage; - if (FAILED(pExecuteAction->mspTarget.pPackage->hrCacheResult)) + if (FAILED(pPackage->hrCacheResult)) { - LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pExecuteAction->mspTarget.pPackage->sczId, pExecuteAction->mspTarget.pPackage->hrCacheResult); + LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult); ExitFunction1(hr = S_OK); } Assert(pContext->fRollback == fRollback); - pContext->pExecutingPackage = pExecuteAction->mspTarget.pPackage; + pContext->pExecutingPackage = pPackage; fBeginCalled = TRUE; // Send package execute begin to BA. - hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pExecuteAction->mspTarget.pPackage->sczId, !fRollback, pExecuteAction->mspTarget.action, pExecuteAction->mspTarget.uiLevel, pExecuteAction->mspTarget.fDisableExternalUiHandler); + hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pPackage->sczId, !fRollback, pExecuteAction->mspTarget.action, pExecuteAction->mspTarget.uiLevel, pExecuteAction->mspTarget.fDisableExternalUiHandler); ExitOnRootFailure(hr, "BA aborted execute MSP package begin."); // Now send all the patches that target this product code. @@ -2026,6 +2096,8 @@ static HRESULT ExecuteMspPackage( ExitOnRootFailure(hr, "BA aborted execute MSP target."); } + fExecuted = TRUE; + // execute package if (pExecuteAction->mspTarget.fPerMachineTarget) { @@ -2045,9 +2117,14 @@ static HRESULT ExecuteMspPackage( ExitOnRootFailure(hr, "BA aborted MSP package execute progress."); LExit: + if (fExecuted) + { + MspEngineUpdateInstallRegistrationState(pExecuteAction, hrExecute, fInsideMsiTransaction); + } + if (fBeginCalled) { - hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pExecuteAction->mspTarget.pPackage, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend); + hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend); } return hr; @@ -2069,19 +2146,21 @@ static HRESULT ExecuteMsuPackage( GENERIC_EXECUTE_MESSAGE message = { }; int nResult = 0; BOOL fBeginCalled = FALSE; + BOOL fExecuted = FALSE; + BURN_PACKAGE* pPackage = pExecuteAction->msuPackage.pPackage; - if (FAILED(pExecuteAction->msuPackage.pPackage->hrCacheResult)) + if (FAILED(pPackage->hrCacheResult)) { - LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pExecuteAction->msuPackage.pPackage->sczId, pExecuteAction->msuPackage.pPackage->hrCacheResult); + LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult); ExitFunction1(hr = S_OK); } Assert(pContext->fRollback == fRollback); - pContext->pExecutingPackage = pExecuteAction->msuPackage.pPackage; + pContext->pExecutingPackage = pPackage; fBeginCalled = TRUE; // Send package execute begin to BA. - hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pExecuteAction->msuPackage.pPackage->sczId, !fRollback, pExecuteAction->msuPackage.action, INSTALLUILEVEL_NOCHANGE, FALSE); + hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pPackage->sczId, !fRollback, pExecuteAction->msuPackage.action, INSTALLUILEVEL_NOCHANGE, FALSE); ExitOnRootFailure(hr, "BA aborted execute MSU package begin."); message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; @@ -2091,8 +2170,10 @@ static HRESULT ExecuteMsuPackage( hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwAllowedResults, nResult); ExitOnRootFailure(hr, "BA aborted MSU progress."); + fExecuted = TRUE; + // execute package - if (pExecuteAction->msuPackage.pPackage->fPerMachine) + if (pPackage->fPerMachine) { hrExecute = ElevationExecuteMsuPackage(pEngineState->companionConnection.hPipe, pExecuteAction, fRollback, fStopWusaService, GenericExecuteMessageHandler, pContext, pRestart); ExitOnFailure(hrExecute, "Failed to configure per-machine MSU package."); @@ -2117,9 +2198,14 @@ static HRESULT ExecuteMsuPackage( ExitOnRootFailure(hr, "BA aborted MSU package execute progress."); LExit: + if (fExecuted) + { + MsuEngineUpdateInstallRegistrationState(pExecuteAction, hrExecute); + } + if (fBeginCalled) { - hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pExecuteAction->msuPackage.pPackage, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend); + hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend); } return hr; @@ -2167,6 +2253,32 @@ static HRESULT ExecuteDependencyAction( ExitOnFailure(hr, "Failed to register the dependency on per-user package."); } + if (pAction->packageDependency.pPackage->fCanAffectRegistration) + { + if (BURN_DEPENDENCY_ACTION_REGISTER == pAction->packageDependency.action) + { + if (BURN_PACKAGE_REGISTRATION_STATE_IGNORED == pAction->packageDependency.pPackage->cacheRegistrationState) + { + pAction->packageDependency.pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; + } + if (BURN_PACKAGE_REGISTRATION_STATE_IGNORED == pAction->packageDependency.pPackage->installRegistrationState) + { + pAction->packageDependency.pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; + } + } + else if (BURN_DEPENDENCY_ACTION_UNREGISTER == pAction->packageDependency.action) + { + if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pAction->packageDependency.pPackage->cacheRegistrationState) + { + pAction->packageDependency.pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED; + } + if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pAction->packageDependency.pPackage->installRegistrationState) + { + pAction->packageDependency.pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED; + } + } + } + LExit: return hr; } @@ -2202,6 +2314,8 @@ static HRESULT ExecuteMsiBeginTransaction( if (SUCCEEDED(hr)) { pRollbackBoundary->fActiveTransaction = TRUE; + + ResetTransactionRegistrationState(pEngineState, FALSE); } LExit: @@ -2244,6 +2358,8 @@ static HRESULT ExecuteMsiCommitTransaction( if (SUCCEEDED(hr)) { pRollbackBoundary->fActiveTransaction = FALSE; + + ResetTransactionRegistrationState(pEngineState, TRUE); } LExit: @@ -2285,6 +2401,8 @@ static HRESULT ExecuteMsiRollbackTransaction( LExit: pRollbackBoundary->fActiveTransaction = FALSE; + ResetTransactionRegistrationState(pEngineState, FALSE); + if (fBeginCalled) { UserExperienceOnRollbackMsiTransactionComplete(&pEngineState->userExperience, pRollbackBoundary->sczId, hr); @@ -2293,6 +2411,38 @@ LExit: return hr; } +static void ResetTransactionRegistrationState( + __in BURN_ENGINE_STATE* pEngineState, + __in BOOL fCommit + ) +{ + for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i) + { + BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i; + + if (BURN_PACKAGE_TYPE_MSP == pPackage->type) + { + for (DWORD j = 0; j < pPackage->Msp.cTargetProductCodes; ++j) + { + BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + j; + + if (fCommit && BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN != pTargetProduct->transactionRegistrationState) + { + pTargetProduct->registrationState = pTargetProduct->transactionRegistrationState; + } + + pTargetProduct->transactionRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; + } + } + else if (fCommit && BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN != pPackage->transactionRegistrationState) + { + pPackage->installRegistrationState = pPackage->transactionRegistrationState; + } + + pPackage->transactionRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; + } +} + static HRESULT CleanPackage( __in HANDLE hElevatedPipe, __in BURN_PACKAGE* pPackage @@ -2309,6 +2459,11 @@ static HRESULT CleanPackage( hr = CacheRemovePackage(FALSE, pPackage->sczId, pPackage->sczCacheId); } + if (pPackage->fCanAffectRegistration) + { + pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT; + } + return hr; } diff --git a/src/engine/apply.h b/src/engine/apply.h index 00e1fceb..548e147d 100644 --- a/src/engine/apply.h +++ b/src/engine/apply.h @@ -72,7 +72,6 @@ HRESULT ApplyRegister( HRESULT ApplyUnregister( __in BURN_ENGINE_STATE* pEngineState, __in BOOL fFailedOrRollback, - __in BOOL fRollback, __in BOOL fSuspend, __in BOOTSTRAPPER_APPLY_RESTART restart ); @@ -83,13 +82,12 @@ HRESULT ApplyCache( __in BURN_PLAN* pPlan, __in HANDLE hPipe, __inout DWORD* pcOverallProgressTicks, - __out BOOL* pfRollback + __inout BOOL* pfRollback ); HRESULT ApplyExecute( __in BURN_ENGINE_STATE* pEngineState, __in_opt HANDLE hCacheThread, __inout DWORD* pcOverallProgressTicks, - __inout BOOL* pfKeepRegistration, __out BOOL* pfRollback, __out BOOL* pfSuspend, __out BOOTSTRAPPER_APPLY_RESTART* pRestart diff --git a/src/engine/core.cpp b/src/engine/core.cpp index a4c118a3..36471e93 100644 --- a/src/engine/core.cpp +++ b/src/engine/core.cpp @@ -331,6 +331,8 @@ extern "C" HRESULT CoreDetect( } pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN; + pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; } } @@ -342,7 +344,7 @@ extern "C" HRESULT CoreDetect( { pPackage = pEngineState->packages.rgPackages + iPackage; - LogId(REPORT_STANDARD, MSG_DETECTED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingCacheStateToString(pPackage->cache)); + LogId(REPORT_STANDARD, MSG_DETECTED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingCacheStateToString(pPackage->cache), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->installRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->cacheRegistrationState)); if (BURN_PACKAGE_TYPE_MSI == pPackage->type) { @@ -565,7 +567,6 @@ extern "C" HRESULT CoreApply( BOOL fApplyInitialize = FALSE; BOOL fElevated = FALSE; BOOL fRegistered = FALSE; - BOOL fKeepRegistration = pEngineState->plan.fKeepRegistrationDefault; BOOL fRollback = FALSE; BOOL fSuspend = FALSE; BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE; @@ -652,9 +653,9 @@ extern "C" HRESULT CoreApply( // Register. if (pEngineState->plan.fRegister) { + fRegistered = TRUE; hr = ApplyRegister(pEngineState); ExitOnFailure(hr, "Failed to register bundle."); - fRegistered = TRUE; } // Cache. @@ -681,7 +682,7 @@ extern "C" HRESULT CoreApply( // Execute. if (pEngineState->plan.cExecuteActions) { - hr = ApplyExecute(pEngineState, hCacheThread, &cOverallProgressTicks, &fKeepRegistration, &fRollback, &fSuspend, &restart); + hr = ApplyExecute(pEngineState, hCacheThread, &cOverallProgressTicks, &fRollback, &fSuspend, &restart); UserExperienceExecutePhaseComplete(&pEngineState->userExperience, hr); // signal that execute completed. } @@ -711,7 +712,7 @@ LExit: // Unregister. if (fRegistered) { - ApplyUnregister(pEngineState, FAILED(hr) || fRollback, fKeepRegistration || pEngineState->plan.fDisallowRemoval, fSuspend, restart); + ApplyUnregister(pEngineState, FAILED(hr) || fRollback, fSuspend, restart); } if (fElevated) @@ -1611,6 +1612,11 @@ static HRESULT DetectPackagePayloadsCached( pPackage->cache = cache; + if (pPackage->fCanAffectRegistration) + { + pPackage->cacheRegistrationState = BURN_CACHE_STATE_NONE < pPackage->cache ? BURN_PACKAGE_REGISTRATION_STATE_PRESENT : BURN_PACKAGE_REGISTRATION_STATE_ABSENT; + } + LExit: ReleaseStr(sczPayloadCachePath); ReleaseStr(sczCachePath); @@ -1703,7 +1709,7 @@ static void LogPackages( const DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == action) ? pPackages->cPackages - 1 - i : i; const BURN_PACKAGE* pPackage = &pPackages->rgPackages[iPackage]; - LogId(REPORT_STANDARD, MSG_PLANNED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingBoolToString(pPackage->fAcquire), LoggingBoolToString(pPackage->fUncache), LoggingDependencyActionToString(pPackage->dependencyExecute)); + LogId(REPORT_STANDARD, MSG_PLANNED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingBoolToString(pPackage->fAcquire), LoggingBoolToString(pPackage->fUncache), LoggingDependencyActionToString(pPackage->dependencyExecute), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedInstallRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedCacheRegistrationState)); } // Display related bundles last if caching, installing, modifying, or repairing. diff --git a/src/engine/dependency.cpp b/src/engine/dependency.cpp index 1c33aaf2..a6a8fe4d 100644 --- a/src/engine/dependency.cpp +++ b/src/engine/dependency.cpp @@ -708,6 +708,9 @@ static HRESULT DetectPackageDependents( { HRESULT hr = S_OK; HKEY hkHive = pPackage->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; + BOOL fCanIgnorePresence = pPackage->fCanAffectRegistration && 0 < pPackage->cDependencyProviders && + (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->cacheRegistrationState || BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->installRegistrationState); + BOOL fBundleRegisteredAsDependent = FALSE; // There's currently no point in getting the dependents if the scope doesn't match, // because they will just get ignored. @@ -729,6 +732,20 @@ static HRESULT DetectPackageDependents( { pPackage->fPackageProviderExists = TRUE; } + + if (fCanIgnorePresence && !fBundleRegisteredAsDependent) + { + for (DWORD iDependent = 0; iDependent < pProvider->cDependents; ++iDependent) + { + DEPENDENCY* pDependent = pProvider->rgDependents + iDependent; + + if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->sczId, -1, pDependent->sczKey, -1)) + { + fBundleRegisteredAsDependent = TRUE; + break; + } + } + } } else { @@ -747,6 +764,18 @@ static HRESULT DetectPackageDependents( pPackage->fPackageProviderExists = TRUE; } + if (fCanIgnorePresence && !fBundleRegisteredAsDependent) + { + if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->cacheRegistrationState) + { + pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED; + } + if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->installRegistrationState) + { + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED; + } + } + LExit: return hr; } diff --git a/src/engine/detect.cpp b/src/engine/detect.cpp index ff6ba4d7..159df3d0 100644 --- a/src/engine/detect.cpp +++ b/src/engine/detect.cpp @@ -63,6 +63,8 @@ extern "C" void DetectReset( pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN; pPackage->fPackageProviderExists = FALSE; + pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; pPackage->cache = BURN_CACHE_STATE_NONE; for (DWORD iPayload = 0; iPayload < pPackage->cPayloads; ++iPayload) diff --git a/src/engine/engine.mc b/src/engine/engine.mc index d2135839..59a05676 100644 --- a/src/engine/engine.mc +++ b/src/engine/engine.mc @@ -188,7 +188,7 @@ MessageId=101 Severity=Success SymbolicName=MSG_DETECTED_PACKAGE Language=English -Detected package: %1!ls!, state: %2!hs!, cached: %3!hs! +Detected package: %1!ls!, state: %2!hs!, cached: %3!hs!, install registration state: %4!hs!, cache registration state: %5!hs! . MessageId=102 @@ -300,7 +300,7 @@ MessageId=201 Severity=Success SymbolicName=MSG_PLANNED_PACKAGE Language=English -Planned package: %1!ls!, state: %2!hs!, default requested: %3!hs!, ba requested: %4!hs!, execute: %5!hs!, rollback: %6!hs!, cache: %7!hs!, uncache: %8!hs!, dependency: %9!hs! +Planned package: %1!ls!, state: %2!hs!, default requested: %3!hs!, ba requested: %4!hs!, execute: %5!hs!, rollback: %6!hs!, cache: %7!hs!, uncache: %8!hs!, dependency: %9!hs!, expected install registration state: %10!hs!, expected cache registration state: %11!hs! . MessageId=202 @@ -829,6 +829,21 @@ Language=English Session end, registration key: %1!ls!, resume: %2!hs!, restart: %3!hs!, disable resume: %4!hs! . +MessageId=373 +Severity=Success +SymbolicName=MSG_POST_APPLY_CALCULATE_REGISTRATION +Language=English +Calculating whether to keep registration +. + + +MessageId=374 +Severity=Success +SymbolicName=MSG_POST_APPLY_PACKAGE +Language=English + package: %1!ls!, install registration state: %2!hs!, cache registration state: %3!hs! +. + MessageId=380 Severity=Warning SymbolicName=MSG_APPLY_SKIPPED diff --git a/src/engine/exeengine.cpp b/src/engine/exeengine.cpp index fd33d926..1ca28473 100644 --- a/src/engine/exeengine.cpp +++ b/src/engine/exeengine.cpp @@ -145,6 +145,11 @@ extern "C" HRESULT ExeEngineDetectPackage( // update detect state pPackage->currentState = fDetected ? BOOTSTRAPPER_PACKAGE_STATE_PRESENT : BOOTSTRAPPER_PACKAGE_STATE_ABSENT; + if (pPackage->fCanAffectRegistration) + { + pPackage->installRegistrationState = BOOTSTRAPPER_PACKAGE_STATE_CACHED < pPackage->currentState ? BURN_PACKAGE_REGISTRATION_STATE_PRESENT : BURN_PACKAGE_REGISTRATION_STATE_ABSENT; + } + LExit: return hr; } @@ -585,6 +590,31 @@ LExit: return hr; } +extern "C" void ExeEngineUpdateInstallRegistrationState( + __in BURN_EXECUTE_ACTION* pAction, + __in HRESULT hrExecute + ) +{ + BURN_PACKAGE* pPackage = pAction->exePackage.pPackage; + + if (FAILED(hrExecute) || !pPackage->fCanAffectRegistration) + { + ExitFunction(); + } + + if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pAction->exePackage.action) + { + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT; + } + else + { + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; + } + +LExit: + return; +} + // internal helper functions diff --git a/src/engine/exeengine.h b/src/engine/exeengine.h index 402e51ed..1eac4232 100644 --- a/src/engine/exeengine.h +++ b/src/engine/exeengine.h @@ -41,6 +41,10 @@ HRESULT ExeEngineExecutePackage( __in LPVOID pvContext, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ); +void ExeEngineUpdateInstallRegistrationState( + __in BURN_EXECUTE_ACTION* pAction, + __in HRESULT hrExecute + ); #if defined(__cplusplus) diff --git a/src/engine/logging.cpp b/src/engine/logging.cpp index 9dca527a..a9646218 100644 --- a/src/engine/logging.cpp +++ b/src/engine/logging.cpp @@ -399,6 +399,31 @@ extern "C" LPCSTR LoggingPackageStateToString( } } +extern "C" LPCSTR LoggingPackageRegistrationStateToString( + __in BOOL fCanAffectRegistration, + __in BURN_PACKAGE_REGISTRATION_STATE registrationState + ) +{ + if (!fCanAffectRegistration) + { + return "(permanent)"; + } + + switch (registrationState) + { + case BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN: + return "Unknown"; + case BURN_PACKAGE_REGISTRATION_STATE_IGNORED: + return "Ignored"; + case BURN_PACKAGE_REGISTRATION_STATE_ABSENT: + return "Absent"; + case BURN_PACKAGE_REGISTRATION_STATE_PRESENT: + return "Present"; + default: + return "Invalid"; + } +} + extern "C" LPCSTR LoggingCacheStateToString( __in BURN_CACHE_STATE cacheState ) diff --git a/src/engine/logging.h b/src/engine/logging.h index b5c6c052..49a8ef5d 100644 --- a/src/engine/logging.h +++ b/src/engine/logging.h @@ -89,6 +89,11 @@ LPCSTR LoggingPackageStateToString( __in BOOTSTRAPPER_PACKAGE_STATE packageState ); +LPCSTR LoggingPackageRegistrationStateToString( + __in BOOL fCanAffectRegistration, + __in BURN_PACKAGE_REGISTRATION_STATE registrationState + ); + LPCSTR LoggingCacheStateToString( __in BURN_CACHE_STATE cacheState ); diff --git a/src/engine/msiengine.cpp b/src/engine/msiengine.cpp index 5bccb375..4fdf2b7a 100644 --- a/src/engine/msiengine.cpp +++ b/src/engine/msiengine.cpp @@ -661,6 +661,11 @@ extern "C" HRESULT MsiEngineDetectPackage( } } + if (pPackage->fCanAffectRegistration) + { + pPackage->installRegistrationState = BOOTSTRAPPER_PACKAGE_STATE_CACHED < pPackage->currentState ? BURN_PACKAGE_REGISTRATION_STATE_PRESENT : BURN_PACKAGE_REGISTRATION_STATE_ABSENT; + } + LExit: ReleaseStr(sczInstalledLanguage); ReleaseStr(sczInstalledVersion); @@ -1397,6 +1402,42 @@ extern "C" HRESULT MsiEngineCalculateInstallUiLevel( return UserExperienceOnPlanMsiPackage(pUserExperience, wzPackageId, fExecute, actionState, pActionMsiProperty, pUiLevel, pfDisableExternalUiHandler); } +extern "C" void MsiEngineUpdateInstallRegistrationState( + __in BURN_EXECUTE_ACTION* pAction, + __in HRESULT hrExecute, + __in BOOL fInsideMsiTransaction + ) +{ + BURN_PACKAGE_REGISTRATION_STATE newState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; + BURN_PACKAGE* pPackage = pAction->msiPackage.pPackage; + + if (FAILED(hrExecute) || !pPackage->fCanAffectRegistration) + { + ExitFunction(); + } + + if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pAction->msiPackage.action) + { + newState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT; + } + else + { + newState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; + } + + if (fInsideMsiTransaction) + { + pPackage->transactionRegistrationState = newState; + } + else + { + pPackage->installRegistrationState = newState; + } + +LExit: + return; +} + // internal helper functions diff --git a/src/engine/msiengine.h b/src/engine/msiengine.h index 1f450147..d1e46da8 100644 --- a/src/engine/msiengine.h +++ b/src/engine/msiengine.h @@ -88,6 +88,11 @@ HRESULT MsiEngineCalculateInstallUiLevel( __out INSTALLUILEVEL* pUiLevel, __out BOOL* pfDisableExternalUiHandler ); +void MsiEngineUpdateInstallRegistrationState( + __in BURN_EXECUTE_ACTION* pAction, + __in HRESULT hrExecute, + __in BOOL fInsideMsiTransaction + ); #if defined(__cplusplus) } diff --git a/src/engine/mspengine.cpp b/src/engine/mspengine.cpp index c432b78b..c0329d79 100644 --- a/src/engine/mspengine.cpp +++ b/src/engine/mspengine.cpp @@ -200,20 +200,26 @@ extern "C" HRESULT MspEngineDetectPackage( HRESULT hr = S_OK; LPWSTR sczState = NULL; + if (pPackage->fCanAffectRegistration) + { + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT; + } + if (0 == pPackage->Msp.cTargetProductCodes) { pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT; } else { - // Start the package state at the the highest state then loop through all the + // Start the package state at the highest state then loop through all the // target product codes and end up setting the current state to the lowest - // package state applied to the the target product codes. + // package state applied to the target product codes. pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED; for (DWORD i = 0; i < pPackage->Msp.cTargetProductCodes; ++i) { BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + i; + BOOL fInstalled = FALSE; hr = WiuGetPatchInfoEx(pPackage->Msp.sczPatchCode, pTargetProduct->wzTargetProductCode, NULL, pTargetProduct->context, INSTALLPROPERTY_PATCHSTATE, &sczState); if (SUCCEEDED(hr)) @@ -221,14 +227,17 @@ extern "C" HRESULT MspEngineDetectPackage( switch (*sczState) { case '1': + fInstalled = TRUE; pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT; break; case '2': + fInstalled = TRUE; pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED; break; case '4': + fInstalled = TRUE; pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE; break; @@ -249,6 +258,16 @@ extern "C" HRESULT MspEngineDetectPackage( pPackage->currentState = pTargetProduct->patchPackageState; } + if (pPackage->fCanAffectRegistration) + { + pTargetProduct->registrationState = fInstalled ? BURN_PACKAGE_REGISTRATION_STATE_PRESENT : BURN_PACKAGE_REGISTRATION_STATE_ABSENT; + + if (fInstalled) + { + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; + } + } + hr = UserExperienceOnDetectTargetMsiPackage(pUserExperience, pPackage->sczId, pTargetProduct->wzTargetProductCode, pTargetProduct->patchPackageState); ExitOnRootFailure(hr, "BA aborted detect target MSI package."); } @@ -642,6 +661,92 @@ extern "C" void MspEngineSlipstreamUpdateState( } } +extern "C" void MspEngineUpdateInstallRegistrationState( + __in BURN_EXECUTE_ACTION* pAction, + __in HRESULT hrExecute, + __in BOOL fInsideMsiTransaction + ) +{ + BURN_PACKAGE_REGISTRATION_STATE newState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; + + if (FAILED(hrExecute)) + { + ExitFunction(); + } + + if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pAction->mspTarget.action) + { + newState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT; + } + else + { + newState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; + } + + for (DWORD i = 0; i < pAction->mspTarget.cOrderedPatches; ++i) + { + BURN_ORDERED_PATCHES* pOrderedPatches = pAction->mspTarget.rgOrderedPatches + i; + BURN_PACKAGE* pPackage = pOrderedPatches->pPackage; + BURN_MSPTARGETPRODUCT* pTargetProduct = NULL; + + Assert(BURN_PACKAGE_TYPE_MSP == pPackage->type); + + if (!pPackage->fCanAffectRegistration) + { + continue; + } + + for (DWORD j = 0; j < pPackage->Msp.cTargetProductCodes; ++j) + { + pTargetProduct = pPackage->Msp.rgTargetProducts + j; + if (pAction->mspTarget.fPerMachineTarget == (MSIINSTALLCONTEXT_MACHINE == pTargetProduct->context) && + CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pAction->mspTarget.sczTargetProductCode, -1, pTargetProduct->wzTargetProductCode, -1)) + { + break; + } + + pTargetProduct = NULL; + } + + if (!pTargetProduct) + { + AssertSz(pTargetProduct, "Ordered patch didn't have corresponding target product"); + continue; + } + + if (fInsideMsiTransaction) + { + pTargetProduct->transactionRegistrationState = newState; + } + else + { + pTargetProduct->registrationState = newState; + } + } + +LExit: + return; +} + +extern "C" void MspEngineFinalizeInstallRegistrationState( + __in BURN_PACKAGE* pPackage + ) +{ + Assert(pPackage->fCanAffectRegistration); + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT; + + for (DWORD i = 0; i < pPackage->Msp.cTargetProductCodes; ++i) + { + BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + i; + + if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pTargetProduct->registrationState) + { + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; + break; + } + } +} + // internal helper functions diff --git a/src/engine/mspengine.h b/src/engine/mspengine.h index e08fe992..7cc9a119 100644 --- a/src/engine/mspengine.h +++ b/src/engine/mspengine.h @@ -62,6 +62,14 @@ void MspEngineSlipstreamUpdateState( __in BOOTSTRAPPER_ACTION_STATE execute, __in BOOTSTRAPPER_ACTION_STATE rollback ); +void MspEngineUpdateInstallRegistrationState( + __in BURN_EXECUTE_ACTION* pAction, + __in HRESULT hrExecute, + __in BOOL fInsideMsiTransaction + ); +void MspEngineFinalizeInstallRegistrationState( + __in BURN_PACKAGE* pPackage + ); #if defined(__cplusplus) diff --git a/src/engine/msuengine.cpp b/src/engine/msuengine.cpp index 641d55b1..b7a503ad 100644 --- a/src/engine/msuengine.cpp +++ b/src/engine/msuengine.cpp @@ -69,6 +69,11 @@ extern "C" HRESULT MsuEngineDetectPackage( // update detect state pPackage->currentState = fDetected ? BOOTSTRAPPER_PACKAGE_STATE_PRESENT : BOOTSTRAPPER_PACKAGE_STATE_ABSENT; + if (pPackage->fCanAffectRegistration) + { + pPackage->installRegistrationState = BOOTSTRAPPER_PACKAGE_STATE_CACHED < pPackage->currentState ? BURN_PACKAGE_REGISTRATION_STATE_PRESENT : BURN_PACKAGE_REGISTRATION_STATE_ABSENT; + } + LExit: return hr; } @@ -424,6 +429,31 @@ LExit: return hr; } +extern "C" void MsuEngineUpdateInstallRegistrationState( + __in BURN_EXECUTE_ACTION* pAction, + __in HRESULT hrExecute + ) +{ + BURN_PACKAGE* pPackage = pAction->msuPackage.pPackage; + + if (FAILED(hrExecute) || !pPackage->fCanAffectRegistration) + { + ExitFunction(); + } + + if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pAction->msuPackage.action) + { + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT; + } + else + { + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; + } + +LExit: + return; +} + static HRESULT EnsureWUServiceEnabled( __in BOOL fStopWusaService, __out SC_HANDLE* pschWu, diff --git a/src/engine/msuengine.h b/src/engine/msuengine.h index d0323b06..7f57a084 100644 --- a/src/engine/msuengine.h +++ b/src/engine/msuengine.h @@ -41,6 +41,10 @@ HRESULT MsuEngineExecutePackage( __in LPVOID pvContext, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ); +void MsuEngineUpdateInstallRegistrationState( + __in BURN_EXECUTE_ACTION* pAction, + __in HRESULT hrExecute + ); #if defined(__cplusplus) diff --git a/src/engine/package.cpp b/src/engine/package.cpp index 701dda08..b27b1e07 100644 --- a/src/engine/package.cpp +++ b/src/engine/package.cpp @@ -156,6 +156,7 @@ extern "C" HRESULT PackagesParseFromXml( hr = XmlGetYesNoAttribute(pixnNode, L"Permanent", &pPackage->fUninstallable); ExitOnFailure(hr, "Failed to get @Permanent."); pPackage->fUninstallable = !pPackage->fUninstallable; // TODO: change "Uninstallable" variable name to permanent, until then Uninstallable is the opposite of Permanent so fix the variable. + pPackage->fCanAffectRegistration = pPackage->fUninstallable; // @Vital hr = XmlGetYesNoAttribute(pixnNode, L"Vital", &pPackage->fVital); diff --git a/src/engine/package.h b/src/engine/package.h index 8f801e85..d3225fbc 100644 --- a/src/engine/package.h +++ b/src/engine/package.h @@ -78,6 +78,14 @@ enum BOOTSTRAPPER_FEATURE_ACTION BOOTSTRAPPER_FEATURE_ACTION_REMOVE, }; +enum BURN_PACKAGE_REGISTRATION_STATE +{ + BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN, + BURN_PACKAGE_REGISTRATION_STATE_IGNORED, + BURN_PACKAGE_REGISTRATION_STATE_ABSENT, + BURN_PACKAGE_REGISTRATION_STATE_PRESENT, +}; + // structs typedef struct _BURN_EXE_EXIT_CODE @@ -106,6 +114,9 @@ typedef struct _BURN_MSPTARGETPRODUCT BOOTSTRAPPER_PACKAGE_STATE patchPackageState; // only valid after Detect. BOOTSTRAPPER_ACTION_STATE execute; // only valid during Plan. BOOTSTRAPPER_ACTION_STATE rollback; // only valid during Plan. + + BURN_PACKAGE_REGISTRATION_STATE registrationState; // initialized during Detect, updated during Apply. + BURN_PACKAGE_REGISTRATION_STATE transactionRegistrationState;// only valid during Apply inside an MSI transaction. } BURN_MSPTARGETPRODUCT; typedef struct _BURN_MSIPROPERTY @@ -190,6 +201,7 @@ typedef struct _BURN_PACKAGE BOOL fPerMachine; BOOL fUninstallable; BOOL fVital; + BOOL fCanAffectRegistration; BURN_CACHE_TYPE cacheType; LPWSTR sczCacheId; @@ -216,6 +228,12 @@ typedef struct _BURN_PACKAGE BOOL fDependencyManagerWasHere; // only valid during Plan. HRESULT hrCacheResult; // only valid during Apply. + BURN_PACKAGE_REGISTRATION_STATE cacheRegistrationState; // initialized during Detect, updated during Apply. + BURN_PACKAGE_REGISTRATION_STATE installRegistrationState; // initialized during Detect, updated during Apply. + BURN_PACKAGE_REGISTRATION_STATE expectedCacheRegistrationState; // only valid after Plan. + BURN_PACKAGE_REGISTRATION_STATE expectedInstallRegistrationState;// only valid after Plan. + BURN_PACKAGE_REGISTRATION_STATE transactionRegistrationState; // only valid during Apply inside an MSI transaction. + BURN_PACKAGE_PAYLOAD* rgPayloads; DWORD cPayloads; diff --git a/src/engine/plan.cpp b/src/engine/plan.cpp index 6f5407b9..1aaec252 100644 --- a/src/engine/plan.cpp +++ b/src/engine/plan.cpp @@ -6,13 +6,6 @@ // internal struct definitions -struct PLAN_NONPERMANENT_PACKAGE_INDICES -{ - DWORD iAfterExecuteFirstNonPermanentPackage; - DWORD iBeforeRollbackFirstNonPermanentPackage; - DWORD iAfterExecuteLastNonPermanentPackage; - DWORD iAfterRollbackLastNonPermanentPackage; -}; // internal function definitions @@ -39,8 +32,7 @@ static HRESULT ProcessPackage( __in BOOTSTRAPPER_RELATION_TYPE relationType, __in_z_opt LPCWSTR wzLayoutDirectory, __inout HANDLE* phSyncpointEvent, - __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary, - __in_opt PLAN_NONPERMANENT_PACKAGE_INDICES* pNonpermanentPackageIndices + __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary ); static HRESULT ProcessPackageRollbackBoundary( __in BURN_PLAN* pPlan, @@ -479,7 +471,7 @@ extern "C" HRESULT PlanPackages( __in BURN_PLAN* pPlan, __in BURN_LOGGING* pLog, __in BURN_VARIABLES* pVariables, - __in BOOL fBundleInstalled, + __in BOOL /*fBundleInstalled*/, __in BOOTSTRAPPER_DISPLAY display, __in BOOTSTRAPPER_RELATION_TYPE relationType, __in_z_opt LPCWSTR wzLayoutDirectory, @@ -490,12 +482,6 @@ extern "C" HRESULT PlanPackages( BOOL fBundlePerMachine = pPlan->fPerMachine; // bundle is per-machine if plan starts per-machine. BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL; - PLAN_NONPERMANENT_PACKAGE_INDICES nonpermanentPackageIndices; - nonpermanentPackageIndices.iAfterExecuteFirstNonPermanentPackage = BURN_PLAN_INVALID_ACTION_INDEX; - nonpermanentPackageIndices.iBeforeRollbackFirstNonPermanentPackage = BURN_PLAN_INVALID_ACTION_INDEX; - nonpermanentPackageIndices.iAfterExecuteLastNonPermanentPackage = BURN_PLAN_INVALID_ACTION_INDEX; - nonpermanentPackageIndices.iAfterRollbackLastNonPermanentPackage = BURN_PLAN_INVALID_ACTION_INDEX; - // Plan the packages. for (DWORD i = 0; i < pPackages->cPackages; ++i) { @@ -518,34 +504,10 @@ extern "C" HRESULT PlanPackages( } } - hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, relationType, wzLayoutDirectory, phSyncpointEvent, &pRollbackBoundary, &nonpermanentPackageIndices); + hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, relationType, wzLayoutDirectory, phSyncpointEvent, &pRollbackBoundary); ExitOnFailure(hr, "Failed to process package."); } - // Insert the "keep registration" and "remove registration" actions in the plan when installing the first time and anytime we are uninstalling respectively. - if (!fBundleInstalled && (BOOTSTRAPPER_ACTION_INSTALL == pPlan->action || BOOTSTRAPPER_ACTION_MODIFY == pPlan->action || BOOTSTRAPPER_ACTION_REPAIR == pPlan->action)) - { - if (BURN_PLAN_INVALID_ACTION_INDEX == nonpermanentPackageIndices.iAfterExecuteFirstNonPermanentPackage) - { - nonpermanentPackageIndices.iAfterExecuteFirstNonPermanentPackage = pPlan->cExecuteActions; - nonpermanentPackageIndices.iBeforeRollbackFirstNonPermanentPackage = pPlan->cRollbackActions; - } - - hr = PlanKeepRegistration(pPlan, nonpermanentPackageIndices.iAfterExecuteFirstNonPermanentPackage, nonpermanentPackageIndices.iBeforeRollbackFirstNonPermanentPackage); - ExitOnFailure(hr, "Failed to plan install keep registration."); - } - else if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) - { - if (BURN_PLAN_INVALID_ACTION_INDEX == nonpermanentPackageIndices.iAfterExecuteLastNonPermanentPackage) - { - nonpermanentPackageIndices.iAfterExecuteLastNonPermanentPackage = pPlan->cExecuteActions; - nonpermanentPackageIndices.iAfterRollbackLastNonPermanentPackage = pPlan->cRollbackActions; - } - - hr = PlanRemoveRegistration(pPlan, nonpermanentPackageIndices.iAfterExecuteLastNonPermanentPackage, nonpermanentPackageIndices.iAfterRollbackLastNonPermanentPackage); - ExitOnFailure(hr, "Failed to plan uninstall remove registration."); - } - // If we still have an open rollback boundary, complete it. if (pRollbackBoundary) { @@ -572,9 +534,9 @@ LExit: extern "C" HRESULT PlanRegistration( __in BURN_PLAN* pPlan, __in BURN_REGISTRATION* pRegistration, - __in BOOTSTRAPPER_RESUME_TYPE resumeType, + __in BOOTSTRAPPER_RESUME_TYPE /*resumeType*/, __in BOOTSTRAPPER_RELATION_TYPE relationType, - __out BOOL* pfContinuePlanning + __inout BOOL* pfContinuePlanning ) { HRESULT hr = S_OK; @@ -583,9 +545,6 @@ extern "C" HRESULT PlanRegistration( pPlan->fRegister = TRUE; // register the bundle since we're modifying machine state. - // Keep the registration if the bundle was already installed or we are planning after a restart. - pPlan->fKeepRegistrationDefault = (pRegistration->fInstalled || BOOTSTRAPPER_RESUME_TYPE_REBOOT == resumeType); - pPlan->fDisallowRemoval = FALSE; // by default the bundle can be planned to be removed if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) @@ -692,7 +651,7 @@ extern "C" HRESULT PlanRegistration( pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE; pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION; } - else if (BOOTSTRAPPER_ACTION_REPAIR == pPlan->action && !CacheBundleRunningFromCache()) // repairing but not not running from the cache. + else if (BOOTSTRAPPER_ACTION_REPAIR == pPlan->action && !CacheBundleRunningFromCache()) // repairing but not running from the cache. { pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE; pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION; @@ -786,7 +745,7 @@ extern "C" HRESULT PlanPassThroughBundle( BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL; // Plan passthrough package. - hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, relationType, NULL, phSyncpointEvent, &pRollbackBoundary, NULL); + hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, relationType, NULL, phSyncpointEvent, &pRollbackBoundary); ExitOnFailure(hr, "Failed to process passthrough package."); // If we still have an open rollback boundary, complete it. @@ -820,7 +779,7 @@ extern "C" HRESULT PlanUpdateBundle( BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL; // Plan update package. - hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, relationType, NULL, phSyncpointEvent, &pRollbackBoundary, NULL); + hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, relationType, NULL, phSyncpointEvent, &pRollbackBoundary); ExitOnFailure(hr, "Failed to process update package."); // If we still have an open rollback boundary, complete it. @@ -849,8 +808,7 @@ static HRESULT ProcessPackage( __in BOOTSTRAPPER_RELATION_TYPE relationType, __in_z_opt LPCWSTR wzLayoutDirectory, __inout HANDLE* phSyncpointEvent, - __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary, - __in_opt PLAN_NONPERMANENT_PACKAGE_INDICES* pNonpermanentPackageIndices + __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary ) { HRESULT hr = S_OK; @@ -871,6 +829,12 @@ static HRESULT ProcessPackage( hr = ProcessPackageRollbackBoundary(pPlan, pEffectiveRollbackBoundary, ppRollbackBoundary); ExitOnFailure(hr, "Failed to process package rollback boundary."); + if (pPackage->fCanAffectRegistration) + { + pPackage->expectedCacheRegistrationState = pPackage->cacheRegistrationState; + pPackage->expectedInstallRegistrationState = pPackage->installRegistrationState; + } + // If the package is in a requested state, plan it. if (BOOTSTRAPPER_REQUEST_STATE_NONE != pPackage->requested) { @@ -881,26 +845,19 @@ static HRESULT ProcessPackage( } else { - if (pPackage->fUninstallable && pNonpermanentPackageIndices) - { - if (BURN_PLAN_INVALID_ACTION_INDEX == pNonpermanentPackageIndices->iBeforeRollbackFirstNonPermanentPackage) - { - pNonpermanentPackageIndices->iBeforeRollbackFirstNonPermanentPackage = pPlan->cRollbackActions; - } - } - hr = PlanExecutePackage(fBundlePerMachine, display, pUX, pPlan, pPackage, pLog, pVariables, phSyncpointEvent); ExitOnFailure(hr, "Failed to plan execute package."); - if (pPackage->fUninstallable && pNonpermanentPackageIndices) + if (pPackage->fCanAffectRegistration) { - if (BURN_PLAN_INVALID_ACTION_INDEX == pNonpermanentPackageIndices->iAfterExecuteFirstNonPermanentPackage) + if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL < pPackage->execute) { - pNonpermanentPackageIndices->iAfterExecuteFirstNonPermanentPackage = pPlan->cExecuteActions - 1; + pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; + } + else if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pPackage->execute) + { + pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT; } - - pNonpermanentPackageIndices->iAfterExecuteLastNonPermanentPackage = pPlan->cExecuteActions; - pNonpermanentPackageIndices->iAfterRollbackLastNonPermanentPackage = pPlan->cRollbackActions; } } } @@ -920,6 +877,32 @@ static HRESULT ProcessPackage( } } + if (pPackage->fCanAffectRegistration) + { + if (BURN_DEPENDENCY_ACTION_REGISTER == pPackage->dependencyExecute) + { + if (BURN_PACKAGE_REGISTRATION_STATE_IGNORED == pPackage->expectedCacheRegistrationState) + { + pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; + } + if (BURN_PACKAGE_REGISTRATION_STATE_IGNORED == pPackage->expectedInstallRegistrationState) + { + pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; + } + } + else if (BURN_DEPENDENCY_ACTION_UNREGISTER == pPackage->dependencyExecute) + { + if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->expectedCacheRegistrationState) + { + pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED; + } + if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->expectedInstallRegistrationState) + { + pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED; + } + } + } + // Add the checkpoint after each package and dependency registration action. if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute || BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->rollback || BURN_DEPENDENCY_ACTION_NONE != pPackage->dependencyExecute) { @@ -1572,6 +1555,11 @@ extern "C" HRESULT PlanCleanPackage( pCleanAction->pPackage = pPackage; pPackage->fUncache = TRUE; + + if (pPackage->fCanAffectRegistration) + { + pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT; + } } LExit: @@ -1708,68 +1696,6 @@ LExit: return hr; } -extern "C" HRESULT PlanKeepRegistration( - __in BURN_PLAN* pPlan, - __in DWORD iAfterExecutePackageAction, - __in DWORD iBeforeRollbackPackageAction - ) -{ - HRESULT hr = S_OK; - BURN_EXECUTE_ACTION* pAction = NULL; - - if (BURN_PLAN_INVALID_ACTION_INDEX != iAfterExecutePackageAction) - { - hr = PlanInsertExecuteAction(iAfterExecutePackageAction, pPlan, &pAction); - ExitOnFailure(hr, "Failed to insert keep registration execute action."); - - pAction->type = BURN_EXECUTE_ACTION_TYPE_REGISTRATION; - pAction->registration.fKeep = TRUE; - } - - if (BURN_PLAN_INVALID_ACTION_INDEX != iBeforeRollbackPackageAction) - { - hr = PlanInsertRollbackAction(iBeforeRollbackPackageAction, pPlan, &pAction); - ExitOnFailure(hr, "Failed to insert keep registration rollback action."); - - pAction->type = BURN_EXECUTE_ACTION_TYPE_REGISTRATION; - pAction->registration.fKeep = FALSE; - } - -LExit: - return hr; -} - -extern "C" HRESULT PlanRemoveRegistration( - __in BURN_PLAN* pPlan, - __in DWORD iAfterExecutePackageAction, - __in DWORD iAfterRollbackPackageAction - ) -{ - HRESULT hr = S_OK; - BURN_EXECUTE_ACTION* pAction = NULL; - - if (BURN_PLAN_INVALID_ACTION_INDEX != iAfterExecutePackageAction) - { - hr = PlanInsertExecuteAction(iAfterExecutePackageAction, pPlan, &pAction); - ExitOnFailure(hr, "Failed to insert remove registration execute action."); - - pAction->type = BURN_EXECUTE_ACTION_TYPE_REGISTRATION; - pAction->registration.fKeep = FALSE; - } - - if (BURN_PLAN_INVALID_ACTION_INDEX != iAfterRollbackPackageAction) - { - hr = PlanInsertRollbackAction(iAfterRollbackPackageAction, pPlan, &pAction); - ExitOnFailure(hr, "Failed to insert remove registration rollback action."); - - pAction->type = BURN_EXECUTE_ACTION_TYPE_REGISTRATION; - pAction->registration.fKeep = TRUE; - } - -LExit: - return hr; -} - extern "C" HRESULT PlanRollbackBoundaryBegin( __in BURN_PLAN* pPlan, __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary @@ -1925,6 +1851,8 @@ static void ResetPlannedPackageState( pPackage->dependencyExecute = BURN_DEPENDENCY_ACTION_NONE; pPackage->dependencyRollback = BURN_DEPENDENCY_ACTION_NONE; pPackage->fDependencyManagerWasHere = FALSE; + pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; + pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; if (BURN_PACKAGE_TYPE_MSI == pPackage->type && pPackage->Msi.rgFeatures) { @@ -2198,6 +2126,11 @@ static HRESULT AddCachePackageHelper( // did cache operations to verify the cache is valid so we did not plan the acquisition of the package. pPackage->fAcquire = (BURN_CACHE_STATE_COMPLETE != pPackage->cache); + if (pPackage->fCanAffectRegistration) + { + pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; + } + LExit: return hr; } @@ -3118,10 +3051,6 @@ static void ExecuteActionLog( LogStringLine(PlanDumpLevel, "%ls action[%u]: MSU_PACKAGE package id: %ls, action: %hs, log path: %ls", wzBase, iAction, pAction->msuPackage.pPackage->sczId, LoggingActionStateToString(pAction->msuPackage.action), pAction->msuPackage.sczLogPath); break; - case BURN_EXECUTE_ACTION_TYPE_REGISTRATION: - LogStringLine(PlanDumpLevel, "%ls action[%u]: REGISTRATION keep: %ls", wzBase, iAction, pAction->registration.fKeep ? L"yes" : L"no"); - break; - case BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY: LogStringLine(PlanDumpLevel, "%ls action[%u]: ROLLBACK_BOUNDARY id: %ls, vital: %ls", wzBase, iAction, pAction->rollbackBoundary.pRollbackBoundary->sczId, pAction->rollbackBoundary.pRollbackBoundary->fVital ? L"yes" : L"no"); break; @@ -3157,7 +3086,6 @@ extern "C" void PlanDump( LogStringLine(PlanDumpLevel, "Plan action: %hs", LoggingBurnActionToString(pPlan->action)); LogStringLine(PlanDumpLevel, " per-machine: %hs", LoggingTrueFalseToString(pPlan->fPerMachine)); LogStringLine(PlanDumpLevel, " disable-rollback: %hs", LoggingTrueFalseToString(pPlan->fDisableRollback)); - LogStringLine(PlanDumpLevel, " keep registration by default: %hs", LoggingTrueFalseToString(pPlan->fKeepRegistrationDefault)); LogStringLine(PlanDumpLevel, " estimated size: %llu", pPlan->qwEstimatedSize); LogStringLine(PlanDumpLevel, "Plan cache size: %llu", pPlan->qwCacheSizeTotal); diff --git a/src/engine/plan.h b/src/engine/plan.h index 54189973..6c12b5fa 100644 --- a/src/engine/plan.h +++ b/src/engine/plan.h @@ -64,7 +64,6 @@ enum BURN_EXECUTE_ACTION_TYPE BURN_EXECUTE_ACTION_TYPE_PACKAGE_PROVIDER, BURN_EXECUTE_ACTION_TYPE_PACKAGE_DEPENDENCY, BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY, - BURN_EXECUTE_ACTION_TYPE_REGISTRATION, BURN_EXECUTE_ACTION_TYPE_BEGIN_MSI_TRANSACTION, BURN_EXECUTE_ACTION_TYPE_COMMIT_MSI_TRANSACTION, }; @@ -281,10 +280,6 @@ typedef struct _BURN_EXECUTE_ACTION BOOTSTRAPPER_ACTION_STATE action; } msuPackage; struct - { - BOOL fKeep; - } registration; - struct { BURN_ROLLBACK_BOUNDARY* pRollbackBoundary; } rollbackBoundary; @@ -319,7 +314,6 @@ typedef struct _BURN_PLAN BOOL fPerMachine; BOOL fRegister; DWORD dwRegistrationOperations; - BOOL fKeepRegistrationDefault; BOOL fDisallowRemoval; BOOL fDisableRollback; @@ -418,7 +412,7 @@ HRESULT PlanRegistration( __in BURN_REGISTRATION* pRegistration, __in BOOTSTRAPPER_RESUME_TYPE resumeType, __in BOOTSTRAPPER_RELATION_TYPE relationType, - __out BOOL* pfContinuePlanning + __inout BOOL* pfContinuePlanning ); HRESULT PlanPassThroughBundle( __in BURN_USER_EXPERIENCE* pUX, @@ -519,16 +513,6 @@ HRESULT PlanAppendRollbackAction( __in BURN_PLAN* pPlan, __out BURN_EXECUTE_ACTION** ppExecuteAction ); -HRESULT PlanKeepRegistration( - __in BURN_PLAN* pPlan, - __in DWORD iAfterExecutePackageAction, - __in DWORD iBeforeRollbackPackageAction - ); -HRESULT PlanRemoveRegistration( - __in BURN_PLAN* pPlan, - __in DWORD iAfterExecutePackageAction, - __in DWORD iAfterRollbackPackageAction - ); HRESULT PlanRollbackBoundaryBegin( __in BURN_PLAN* pPlan, __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary diff --git a/src/test/BurnUnitTest/BurnTestFixture.h b/src/test/BurnUnitTest/BurnTestFixture.h index 6b041641..103972ef 100644 --- a/src/test/BurnUnitTest/BurnTestFixture.h +++ b/src/test/BurnUnitTest/BurnTestFixture.h @@ -35,6 +35,8 @@ namespace Bootstrapper LogInitialize(::GetModuleHandleW(NULL)); + LogSetLevel(REPORT_DEBUG, FALSE); + hr = LogOpen(NULL, L"BurnUnitTest", NULL, L"txt", FALSE, FALSE, NULL); TestThrowOnFailure(hr, L"Failed to open log."); } diff --git a/src/test/BurnUnitTest/PlanTest.cpp b/src/test/BurnUnitTest/PlanTest.cpp index a65bef4d..a50c64e1 100644 --- a/src/test/BurnUnitTest/PlanTest.cpp +++ b/src/test/BurnUnitTest/PlanTest.cpp @@ -50,13 +50,12 @@ namespace Bootstrapper Assert::Equal(BOOTSTRAPPER_ACTION_INSTALL, pPlan->action); Assert::Equal(TRUE, pPlan->fPerMachine); Assert::Equal(FALSE, pPlan->fDisableRollback); - Assert::Equal(FALSE, pPlan->fKeepRegistrationDefault); BOOL fRollback = FALSE; DWORD dwIndex = 0; DWORD dwPackageStart = 0; ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); - dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", 6, 2, 33743, FALSE); + dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, 6, 2, 33743, FALSE); ValidateCacheAcquireContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE); ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, dwPackageStart, 6); ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"PackageA", TRUE, FALSE, dwPackageStart); @@ -64,7 +63,7 @@ namespace Bootstrapper ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PackageA", FALSE); ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE); ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 9); - dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageB", 14, 2, 33743, FALSE); + dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageB", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, 14, 2, 33743, FALSE); ValidateCacheAcquireContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", TRUE); ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, dwPackageStart, 2); ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageB", L"PackageB", TRUE, FALSE, dwPackageStart); @@ -72,7 +71,7 @@ namespace Bootstrapper ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PackageB", FALSE); ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE); ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 14); - dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageC", 22, 2, 33743, FALSE); + dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageC", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, 22, 2, 33743, FALSE); ValidateCacheAcquireContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", TRUE); ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, dwPackageStart, 2); ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageC", L"PackageC", TRUE, FALSE, dwPackageStart); @@ -99,9 +98,8 @@ namespace Bootstrapper ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0); + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); - ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, TRUE); ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", BURN_DEPENDENCY_ACTION_REGISTER); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); @@ -113,7 +111,7 @@ namespace Bootstrapper ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageB", BURN_DEPENDENCY_ACTION_REGISTER); - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageB", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0); + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageB", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", BURN_DEPENDENCY_ACTION_REGISTER); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); @@ -122,26 +120,25 @@ namespace Bootstrapper ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageC", BURN_DEPENDENCY_ACTION_REGISTER); - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageC", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0); + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageC", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageC", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", BURN_DEPENDENCY_ACTION_REGISTER); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteCommitMsiTransaction(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ"); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[23].syncpoint.hEvent); - ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL); + ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN, BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL); Assert::Equal(dwIndex, pPlan->cExecuteActions); fRollback = TRUE; dwIndex = 0; dwExecuteCheckpointId = 2; ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); - ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, FALSE); ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PackageA"); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_UNREGISTER); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0); + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", BURN_DEPENDENCY_ACTION_UNREGISTER); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); @@ -166,7 +163,7 @@ namespace Bootstrapper ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); - ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL); + ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN, BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL); Assert::Equal(dwIndex, pPlan->cRollbackActions); Assert::Equal(4ul, pPlan->cExecutePackagesTotal); @@ -197,7 +194,6 @@ namespace Bootstrapper Assert::Equal(BOOTSTRAPPER_ACTION_UNINSTALL, pPlan->action); Assert::Equal(TRUE, pPlan->fPerMachine); Assert::Equal(FALSE, pPlan->fDisableRollback); - Assert::Equal(TRUE, pPlan->fKeepRegistrationDefault); BOOL fRollback = FALSE; DWORD dwIndex = 0; @@ -220,13 +216,13 @@ namespace Bootstrapper ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageC", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", BURN_DEPENDENCY_ACTION_UNREGISTER); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageC", BURN_DEPENDENCY_ACTION_UNREGISTER); - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageC", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0); + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageC", BURN_PACKAGE_REGISTRATION_STATE_ABSENT, BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", BURN_DEPENDENCY_ACTION_UNREGISTER); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageB", BURN_DEPENDENCY_ACTION_UNREGISTER); - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageB", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0); + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageB", BURN_PACKAGE_REGISTRATION_STATE_ABSENT, BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteCommitMsiTransaction(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ"); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); @@ -236,8 +232,7 @@ namespace Bootstrapper ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_UNREGISTER); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0); - ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, FALSE); + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_ABSENT, BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); Assert::Equal(dwIndex, pPlan->cExecuteActions); @@ -263,9 +258,8 @@ namespace Bootstrapper ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0); + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_ABSENT, BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); - ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, TRUE); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); Assert::Equal(dwIndex, pPlan->cRollbackActions); @@ -274,9 +268,9 @@ namespace Bootstrapper Assert::Equal(3ul, pPlan->cOverallProgressTicksTotal); dwIndex = 0; - ValidateCleanAction(pPlan, dwIndex++, L"PackageC"); - ValidateCleanAction(pPlan, dwIndex++, L"PackageB"); - ValidateCleanAction(pPlan, dwIndex++, L"PackageA"); + ValidateCleanAction(pPlan, dwIndex++, L"PackageC", BURN_PACKAGE_REGISTRATION_STATE_ABSENT); + ValidateCleanAction(pPlan, dwIndex++, L"PackageB", BURN_PACKAGE_REGISTRATION_STATE_ABSENT); + ValidateCleanAction(pPlan, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_ABSENT); Assert::Equal(dwIndex, pPlan->cCleanActions); UINT uIndex = 0; @@ -306,13 +300,12 @@ namespace Bootstrapper Assert::Equal(BOOTSTRAPPER_ACTION_CACHE, pPlan->action); Assert::Equal(TRUE, pPlan->fPerMachine); Assert::Equal(FALSE, pPlan->fDisableRollback); - Assert::Equal(FALSE, pPlan->fKeepRegistrationDefault); BOOL fRollback = FALSE; DWORD dwIndex = 0; DWORD dwPackageStart = 0; ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); - dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", 5, 2, 33743, FALSE); + dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, 5, 2, 33743, FALSE); ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, BURN_PLAN_INVALID_ACTION_INDEX, 2); ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"PackageA", TRUE, FALSE, dwPackageStart); ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"cab9Ins_fTP3wNwq5Gxo41ch5VUPaQ", TRUE, FALSE, dwPackageStart); @@ -378,13 +371,12 @@ namespace Bootstrapper Assert::Equal(BOOTSTRAPPER_ACTION_INSTALL, pPlan->action); Assert::Equal(TRUE, pPlan->fPerMachine); Assert::Equal(FALSE, pPlan->fDisableRollback); - Assert::Equal(FALSE, pPlan->fKeepRegistrationDefault); BOOL fRollback = FALSE; DWORD dwIndex = 0; DWORD dwPackageStart = 0; ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); - dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", 5, 2, 33743, FALSE); + dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, 5, 2, 33743, FALSE); ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, BURN_PLAN_INVALID_ACTION_INDEX, 2); ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"PackageA", TRUE, FALSE, dwPackageStart); ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"cab9Ins_fTP3wNwq5Gxo41ch5VUPaQ", TRUE, FALSE, dwPackageStart); @@ -410,32 +402,30 @@ namespace Bootstrapper ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0); + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); - ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, TRUE); ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", BURN_DEPENDENCY_ACTION_REGISTER); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[6].syncpoint.hEvent); - ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL); + ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN, BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL); Assert::Equal(dwIndex, pPlan->cExecuteActions); fRollback = TRUE; dwIndex = 0; dwExecuteCheckpointId = 2; ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); - ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, FALSE); ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PackageA"); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_UNREGISTER); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0); + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", BURN_DEPENDENCY_ACTION_UNREGISTER); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); - ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL); + ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN, BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL); Assert::Equal(dwIndex, pPlan->cRollbackActions); Assert::Equal(2ul, pPlan->cExecutePackagesTotal); @@ -449,6 +439,62 @@ namespace Bootstrapper Assert::Equal(uIndex, pPlan->cPlannedProviders); } + [Fact] + void SingleMsiInstalledWithNoInstalledPackagesModifyTest() + { + HRESULT hr = S_OK; + BURN_ENGINE_STATE engineState = { }; + BURN_ENGINE_STATE* pEngineState = &engineState; + BURN_PLAN* pPlan = &engineState.plan; + + InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState); + PlanTestDetect(pEngineState); + + pEngineState->registration.fInstalled = TRUE; + + hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_MODIFY); + NativeAssert::Succeeded(hr, "CorePlan failed"); + + Assert::Equal(BOOTSTRAPPER_ACTION_MODIFY, pPlan->action); + Assert::Equal(TRUE, pPlan->fPerMachine); + Assert::Equal(FALSE, pPlan->fDisableRollback); + + BOOL fRollback = FALSE; + DWORD dwIndex = 0; + Assert::Equal(dwIndex, pPlan->cCacheActions); + + fRollback = TRUE; + dwIndex = 0; + Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); + + Assert::Equal(0ull, pPlan->qwEstimatedSize); + Assert::Equal(0ull, pPlan->qwCacheSizeTotal); + + fRollback = FALSE; + dwIndex = 0; + DWORD dwExecuteCheckpointId = 1; + ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); + Assert::Equal(dwIndex, pPlan->cExecuteActions); + + fRollback = TRUE; + dwIndex = 0; + dwExecuteCheckpointId = 1; + ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); + Assert::Equal(dwIndex, pPlan->cRollbackActions); + + Assert::Equal(0ul, pPlan->cExecutePackagesTotal); + Assert::Equal(0ul, pPlan->cOverallProgressTicksTotal); + + dwIndex = 0; + Assert::Equal(dwIndex, pPlan->cCleanActions); + + UINT uIndex = 0; + ValidatePlannedProvider(pPlan, uIndex++, L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", NULL); + Assert::Equal(uIndex, pPlan->cPlannedProviders); + } + [Fact] void SingleMsiUninstallTest() { @@ -466,7 +512,6 @@ namespace Bootstrapper Assert::Equal(BOOTSTRAPPER_ACTION_UNINSTALL, pPlan->action); Assert::Equal(TRUE, pPlan->fPerMachine); Assert::Equal(FALSE, pPlan->fDisableRollback); - Assert::Equal(TRUE, pPlan->fKeepRegistrationDefault); BOOL fRollback = FALSE; DWORD dwIndex = 0; @@ -488,8 +533,7 @@ namespace Bootstrapper ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_UNREGISTER); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0); - ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, FALSE); + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_ABSENT, BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); Assert::Equal(dwIndex, pPlan->cExecuteActions); @@ -502,9 +546,8 @@ namespace Bootstrapper ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0); + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_ABSENT, BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); - ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, TRUE); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); Assert::Equal(dwIndex, pPlan->cRollbackActions); @@ -513,7 +556,7 @@ namespace Bootstrapper Assert::Equal(1ul, pPlan->cOverallProgressTicksTotal); dwIndex = 0; - ValidateCleanAction(pPlan, dwIndex++, L"PackageA"); + ValidateCleanAction(pPlan, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_ABSENT); Assert::Equal(dwIndex, pPlan->cCleanActions); UINT uIndex = 0; @@ -522,6 +565,66 @@ namespace Bootstrapper Assert::Equal(uIndex, pPlan->cPlannedProviders); } + [Fact] + void SingleMsiUninstallTestFromUpgradeBundleWithSameExactPackage() + { + HRESULT hr = S_OK; + BURN_ENGINE_STATE engineState = { }; + BURN_ENGINE_STATE* pEngineState = &engineState; + BURN_PLAN* pPlan = &engineState.plan; + + InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState); + DetectAsRelatedUpgradeBundle(&engineState, L"{02940F3E-C83E-452D-BFCF-C943777ACEAE}", L"2.0.0.0"); + + hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_UNINSTALL); + NativeAssert::Succeeded(hr, "CorePlan failed"); + + Assert::Equal(BOOTSTRAPPER_ACTION_UNINSTALL, pPlan->action); + Assert::Equal(TRUE, pPlan->fPerMachine); + Assert::Equal(FALSE, pPlan->fDisableRollback); + + BOOL fRollback = FALSE; + DWORD dwIndex = 0; + Assert::Equal(dwIndex, pPlan->cCacheActions); + + fRollback = TRUE; + dwIndex = 0; + Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); + + Assert::Equal(0ull, pPlan->qwEstimatedSize); + Assert::Equal(0ull, pPlan->qwCacheSizeTotal); + + fRollback = FALSE; + dwIndex = 0; + DWORD dwExecuteCheckpointId = 1; + ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); + ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", BURN_DEPENDENCY_ACTION_UNREGISTER); + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); + Assert::Equal(dwIndex, pPlan->cExecuteActions); + + fRollback = TRUE; + dwIndex = 0; + dwExecuteCheckpointId = 1; + ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); + ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", BURN_DEPENDENCY_ACTION_REGISTER); + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); + Assert::Equal(dwIndex, pPlan->cRollbackActions); + + Assert::Equal(0ul, pPlan->cExecutePackagesTotal); + Assert::Equal(0ul, pPlan->cOverallProgressTicksTotal); + + dwIndex = 0; + Assert::Equal(dwIndex, pPlan->cCleanActions); + + UINT uIndex = 0; + ValidatePlannedProvider(pPlan, uIndex++, L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", NULL); + Assert::Equal(uIndex, pPlan->cPlannedProviders); + } + private: // This doesn't initialize everything, just enough for CorePlan to work. void InitializeEngineStateForCorePlan(LPCWSTR wzManifestFileName, BURN_ENGINE_STATE* pEngineState) @@ -586,12 +689,22 @@ namespace Bootstrapper void DetectPackageAsAbsent(BURN_PACKAGE* pPackage) { pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT; + if (pPackage->fCanAffectRegistration) + { + pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT; + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT; + } } void DetectPackageAsPresentAndCached(BURN_PACKAGE* pPackage) { pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT; pPackage->cache = BURN_CACHE_STATE_COMPLETE; + if (pPackage->fCanAffectRegistration) + { + pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; + } for (DWORD i = 0; i < pPackage->cPayloads; ++i) { @@ -599,6 +712,19 @@ namespace Bootstrapper } } + void DetectPackageDependent(BURN_PACKAGE* pPackage, LPCWSTR wzId) + { + HRESULT hr = S_OK; + + for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i) + { + BURN_DEPENDENCY_PROVIDER* pProvider = pPackage->rgDependencyProviders + i; + + hr = DepDependencyArrayAlloc(&pProvider->rgDependents, &pProvider->cDependents, wzId, NULL); + NativeAssert::Succeeded(hr, "Failed to add package dependent"); + } + } + void DetectPackagesAsAbsent(BURN_ENGINE_STATE* pEngineState) { PlanTestDetect(pEngineState); @@ -620,6 +746,7 @@ namespace Bootstrapper { BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i; DetectPackageAsPresentAndCached(pPackage); + DetectPackageDependent(pPackage, pEngineState->registration.sczId); } } @@ -639,11 +766,12 @@ namespace Bootstrapper else { DetectPackageAsPresentAndCached(pPackage); + DetectPackageDependent(pPackage, pEngineState->registration.sczId); } } } - HRESULT DetectUpgradeBundle( + void DetectUpgradeBundle( __in BURN_ENGINE_STATE* pEngineState, __in LPCWSTR wzId, __in LPCWSTR wzVersion @@ -654,30 +782,48 @@ namespace Bootstrapper BURN_DEPENDENCY_PROVIDER dependencyProvider = { }; hr = StrAllocString(&dependencyProvider.sczKey, wzId, 0); - ExitOnFailure(hr, "Failed to copy provider key"); + NativeAssert::Succeeded(hr, "Failed to copy provider key"); dependencyProvider.fImported = TRUE; hr = StrAllocString(&dependencyProvider.sczVersion, wzVersion, 0); - ExitOnFailure(hr, "Failed to copy version"); + NativeAssert::Succeeded(hr, "Failed to copy version"); hr = MemEnsureArraySize(reinterpret_cast(&pRelatedBundles->rgRelatedBundles), pRelatedBundles->cRelatedBundles + 1, sizeof(BURN_RELATED_BUNDLE), 5); - ExitOnFailure(hr, "Failed to ensure there is space for related bundles."); + NativeAssert::Succeeded(hr, "Failed to ensure there is space for related bundles."); BURN_RELATED_BUNDLE* pRelatedBundle = pRelatedBundles->rgRelatedBundles + pRelatedBundles->cRelatedBundles; hr = VerParseVersion(wzVersion, 0, FALSE, &pRelatedBundle->pVersion); - ExitOnFailure(hr, "Failed to parse pseudo bundle version: %ls", wzVersion); + NativeAssert::Succeeded(hr, "Failed to parse pseudo bundle version: %ls", wzVersion); pRelatedBundle->relationType = BOOTSTRAPPER_RELATION_UPGRADE; hr = PseudoBundleInitialize(0, &pRelatedBundle->package, TRUE, wzId, pRelatedBundle->relationType, BOOTSTRAPPER_PACKAGE_STATE_PRESENT, NULL, NULL, NULL, 0, FALSE, L"-quiet", L"-repair -quiet", L"-uninstall -quiet", &dependencyProvider, NULL, 0); - ExitOnFailure(hr, "Failed to initialize related bundle to represent bundle: %ls", wzId); + NativeAssert::Succeeded(hr, "Failed to initialize related bundle to represent bundle: %ls", wzId); ++pRelatedBundles->cRelatedBundles; + } + + void DetectAsRelatedUpgradeBundle( + __in BURN_ENGINE_STATE* pEngineState, + __in LPCWSTR wzId, + __in LPCWSTR wzVersion + ) + { + HRESULT hr = StrAllocString(&pEngineState->registration.sczAncestors, wzId, 0); + NativeAssert::Succeeded(hr, "Failed to set registration's ancestors"); + + pEngineState->command.relationType = BOOTSTRAPPER_RELATION_UPGRADE; - LExit: - return hr; + DetectPackagesAsPresentAndCached(pEngineState); + DetectUpgradeBundle(pEngineState, wzId, wzVersion); + + for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i) + { + BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i; + DetectPackageDependent(pPackage, wzId); + } } void ValidateCacheAcquireContainer( @@ -755,6 +901,7 @@ namespace Bootstrapper __in BOOL fRollback, __in DWORD dwIndex, __in LPCWSTR wzPackageId, + __in BURN_PACKAGE_REGISTRATION_STATE expectedCacheRegistrationState, __in DWORD iPackageCompleteAction, __in DWORD cCachePayloads, __in DWORD64 qwCachePayloadSizeTotal, @@ -764,6 +911,7 @@ namespace Bootstrapper BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex); Assert::Equal(BURN_CACHE_ACTION_TYPE_PACKAGE_START, pAction->type); NativeAssert::StringEqual(wzPackageId, pAction->packageStart.pPackage->sczId); + Assert::Equal(expectedCacheRegistrationState, pAction->packageStart.pPackage->expectedCacheRegistrationState); Assert::Equal(iPackageCompleteAction, pAction->packageStart.iPackageCompleteAction); Assert::Equal(cCachePayloads, pAction->packageStart.cCachePayloads); Assert::Equal(qwCachePayloadSizeTotal, pAction->packageStart.qwCachePayloadSizeTotal); @@ -815,7 +963,8 @@ namespace Bootstrapper void ValidateCleanAction( __in BURN_PLAN* pPlan, __in DWORD dwIndex, - __in LPCWSTR wzPackageId + __in LPCWSTR wzPackageId, + __in BURN_PACKAGE_REGISTRATION_STATE expectedCacheRegistrationState ) { Assert::InRange(dwIndex + 1ul, 1ul, pPlan->cCleanActions); @@ -823,6 +972,7 @@ namespace Bootstrapper BURN_CLEAN_ACTION* pCleanAction = pPlan->rgCleanActions + dwIndex; Assert::NotEqual((DWORD_PTR)0, (DWORD_PTR)pCleanAction->pPackage); NativeAssert::StringEqual(wzPackageId, pCleanAction->pPackage->sczId); + Assert::Equal(expectedCacheRegistrationState, pCleanAction->pPackage->expectedCacheRegistrationState); } BURN_EXECUTE_ACTION* ValidateExecuteActionExists(BURN_PLAN* pPlan, BOOL fRollback, DWORD dwIndex) @@ -872,6 +1022,7 @@ namespace Bootstrapper __in BOOL fRollback, __in DWORD dwIndex, __in LPCWSTR wzPackageId, + __in BURN_PACKAGE_REGISTRATION_STATE expectedInstallRegistrationState, __in BOOTSTRAPPER_ACTION_STATE action, __in LPCWSTR wzIgnoreDependencies ) @@ -879,6 +1030,7 @@ namespace Bootstrapper BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex); Assert::Equal(BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE, pAction->type); NativeAssert::StringEqual(wzPackageId, pAction->exePackage.pPackage->sczId); + Assert::Equal(expectedInstallRegistrationState, pAction->exePackage.pPackage->expectedInstallRegistrationState); Assert::Equal(action, pAction->exePackage.action); NativeAssert::StringEqual(wzIgnoreDependencies, pAction->exePackage.sczIgnoreDependencies); } @@ -888,6 +1040,7 @@ namespace Bootstrapper __in BOOL fRollback, __in DWORD dwIndex, __in LPCWSTR wzPackageId, + __in BURN_PACKAGE_REGISTRATION_STATE expectedInstallRegistrationState, __in BOOTSTRAPPER_ACTION_STATE action, __in BURN_MSI_PROPERTY actionMsiProperty, __in DWORD uiLevel, @@ -898,6 +1051,7 @@ namespace Bootstrapper BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex); Assert::Equal(BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE, pAction->type); NativeAssert::StringEqual(wzPackageId, pAction->msiPackage.pPackage->sczId); + Assert::Equal(expectedInstallRegistrationState, pAction->msiPackage.pPackage->expectedInstallRegistrationState); Assert::Equal(action, pAction->msiPackage.action); Assert::Equal(actionMsiProperty, pAction->msiPackage.actionMsiProperty); Assert::Equal(uiLevel, pAction->msiPackage.uiLevel); @@ -936,18 +1090,6 @@ namespace Bootstrapper Assert::Equal(action, pAction->packageProvider.action); } - void ValidateExecuteRegistration( - __in BURN_PLAN* pPlan, - __in BOOL fRollback, - __in DWORD dwIndex, - __in BOOL fKeep - ) - { - BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex); - Assert::Equal(BURN_EXECUTE_ACTION_TYPE_REGISTRATION, pAction->type); - Assert::Equal(fKeep, pAction->registration.fKeep); - } - void ValidateExecuteRollbackBoundary( __in BURN_PLAN* pPlan, __in BOOL fRollback, -- cgit v1.2.3-55-g6feb