aboutsummaryrefslogtreecommitdiff
path: root/src/burn/engine/plan.cpp
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-02-22 20:23:43 -0600
committerSean Hall <r.sean.hall@gmail.com>2022-02-22 23:37:57 -0600
commit8e8f724d90c6835febb8b5865009746aea73a334 (patch)
treeb255c0a7232af8d24bcf44fd476b95bdfdcfe777 /src/burn/engine/plan.cpp
parent0740d93ca8be06ec0e5da5b51ceff52f67ab5bf5 (diff)
downloadwix-8e8f724d90c6835febb8b5865009746aea73a334.tar.gz
wix-8e8f724d90c6835febb8b5865009746aea73a334.tar.bz2
wix-8e8f724d90c6835febb8b5865009746aea73a334.zip
Add UnsafeUninstall action.
Fixes #6721
Diffstat (limited to 'src/burn/engine/plan.cpp')
-rw-r--r--src/burn/engine/plan.cpp84
1 files changed, 53 insertions, 31 deletions
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp
index f1fb87b8..49dd83f4 100644
--- a/src/burn/engine/plan.cpp
+++ b/src/burn/engine/plan.cpp
@@ -361,13 +361,15 @@ extern "C" HRESULT PlanDefaultPackageRequestState(
361 else if (BOOTSTRAPPER_RELATION_PATCH == relationType && BURN_PACKAGE_TYPE_MSP == packageType) 361 else if (BOOTSTRAPPER_RELATION_PATCH == relationType && BURN_PACKAGE_TYPE_MSP == packageType)
362 { 362 {
363 // For patch related bundles, only install a patch if currently absent during install, modify, or repair. 363 // For patch related bundles, only install a patch if currently absent during install, modify, or repair.
364 if (BOOTSTRAPPER_PACKAGE_STATE_ABSENT == currentState && BOOTSTRAPPER_ACTION_INSTALL <= action) 364 if (BOOTSTRAPPER_PACKAGE_STATE_ABSENT != currentState)
365 { 365 {
366 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT; 366 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE;
367 } 367 }
368 else 368 else if (BOOTSTRAPPER_ACTION_INSTALL == action ||
369 BOOTSTRAPPER_ACTION_MODIFY == action ||
370 BOOTSTRAPPER_ACTION_REPAIR == action)
369 { 371 {
370 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; 372 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT;
371 } 373 }
372 } 374 }
373 else // pick the best option for the action state and install condition. 375 else // pick the best option for the action state and install condition.
@@ -375,7 +377,7 @@ extern "C" HRESULT PlanDefaultPackageRequestState(
375 hr = GetActionDefaultRequestState(action, currentState, &defaultRequestState); 377 hr = GetActionDefaultRequestState(action, currentState, &defaultRequestState);
376 ExitOnFailure(hr, "Failed to get default request state for action."); 378 ExitOnFailure(hr, "Failed to get default request state for action.");
377 379
378 if (BOOTSTRAPPER_ACTION_UNINSTALL != action) 380 if (BOOTSTRAPPER_ACTION_UNINSTALL != action && BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL != action)
379 { 381 {
380 // If we're not doing an uninstall, use the install condition 382 // If we're not doing an uninstall, use the install condition
381 // to determine whether to use the default request state or make the package absent. 383 // to determine whether to use the default request state or make the package absent.
@@ -485,7 +487,8 @@ extern "C" HRESULT PlanForwardCompatibleBundles(
485 { 487 {
486 fRecommendIgnore = FALSE; 488 fRecommendIgnore = FALSE;
487 } 489 }
488 else if (BOOTSTRAPPER_ACTION_UNINSTALL == action || 490 else if (BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == action ||
491 BOOTSTRAPPER_ACTION_UNINSTALL == action ||
489 BOOTSTRAPPER_ACTION_MODIFY == action || 492 BOOTSTRAPPER_ACTION_MODIFY == action ||
490 BOOTSTRAPPER_ACTION_REPAIR == action) 493 BOOTSTRAPPER_ACTION_REPAIR == action)
491 { 494 {
@@ -552,10 +555,10 @@ extern "C" HRESULT PlanRegistration(
552 HRESULT hr = S_OK; 555 HRESULT hr = S_OK;
553 STRINGDICT_HANDLE sdBundleDependents = NULL; 556 STRINGDICT_HANDLE sdBundleDependents = NULL;
554 STRINGDICT_HANDLE sdIgnoreDependents = NULL; 557 STRINGDICT_HANDLE sdIgnoreDependents = NULL;
558 BOOL fDependentBlocksUninstall = FALSE;
555 559
556 pPlan->fCanAffectMachineState = TRUE; // register the bundle since we're modifying machine state. 560 pPlan->fCanAffectMachineState = TRUE; // register the bundle since we're modifying machine state.
557 pPlan->fDisallowRemoval = FALSE; // by default the bundle can be planned to be removed 561 pPlan->fDisallowRemoval = FALSE; // by default the bundle can be planned to be removed
558 pPlan->fIgnoreAllDependents = pDependencies->fIgnoreAllDependents;
559 562
560 // Ensure the bundle is cached if not running from the cache. 563 // Ensure the bundle is cached if not running from the cache.
561 if (!CacheBundleRunningFromCache(pPlan->pCache)) 564 if (!CacheBundleRunningFromCache(pPlan->pCache))
@@ -563,7 +566,7 @@ extern "C" HRESULT PlanRegistration(
563 pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE; 566 pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE;
564 } 567 }
565 568
566 if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) 569 if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pPlan->action)
567 { 570 {
568 // If our provider key was not owned by a different bundle, 571 // If our provider key was not owned by a different bundle,
569 // then plan to write our provider key registration to "fix it" if broken 572 // then plan to write our provider key registration to "fix it" if broken
@@ -588,7 +591,7 @@ extern "C" HRESULT PlanRegistration(
588 ExitOnFailure(hr, "Failed to add self-dependent to ignore dependents."); 591 ExitOnFailure(hr, "Failed to add self-dependent to ignore dependents.");
589 } 592 }
590 593
591 if (!pPlan->fIgnoreAllDependents) 594 if (!pDependencies->fIgnoreAllDependents)
592 { 595 {
593 // If we are not doing an upgrade, we check to see if there are still dependents on us and if so we skip planning. 596 // If we are not doing an upgrade, we check to see if there are still dependents on us and if so we skip planning.
594 // However, when being upgraded, we always execute our uninstall because a newer version of us is probably 597 // However, when being upgraded, we always execute our uninstall because a newer version of us is probably
@@ -641,10 +644,9 @@ extern "C" HRESULT PlanRegistration(
641 hr = S_OK; 644 hr = S_OK;
642 645
643 // TODO: callback to the BA and let it have the option to ignore this dependent? 646 // TODO: callback to the BA and let it have the option to ignore this dependent?
644 if (!pPlan->fDisallowRemoval) 647 if (!fDependentBlocksUninstall)
645 { 648 {
646 pPlan->fDisallowRemoval = TRUE; // ensure the registration stays 649 fDependentBlocksUninstall = TRUE;
647 *pfContinuePlanning = FALSE; // skip the rest of planning.
648 650
649 LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_DUE_TO_DEPENDENTS); 651 LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_DUE_TO_DEPENDENTS);
650 } 652 }
@@ -653,6 +655,20 @@ extern "C" HRESULT PlanRegistration(
653 } 655 }
654 ExitOnFailure(hr, "Failed to check for remaining dependents during planning."); 656 ExitOnFailure(hr, "Failed to check for remaining dependents during planning.");
655 } 657 }
658
659 if (fDependentBlocksUninstall)
660 {
661 if (BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pPlan->action)
662 {
663 fDependentBlocksUninstall = FALSE;
664 LogId(REPORT_STANDARD, MSG_PLAN_NOT_SKIPPED_DUE_TO_DEPENDENTS);
665 }
666 else
667 {
668 pPlan->fDisallowRemoval = TRUE; // ensure the registration stays
669 *pfContinuePlanning = FALSE; // skip the rest of planning.
670 }
671 }
656 } 672 }
657 } 673 }
658 } 674 }
@@ -776,11 +792,12 @@ static HRESULT PlanPackagesHelper(
776 HRESULT hr = S_OK; 792 HRESULT hr = S_OK;
777 BOOL fBundlePerMachine = pPlan->fPerMachine; // bundle is per-machine if plan starts per-machine. 793 BOOL fBundlePerMachine = pPlan->fPerMachine; // bundle is per-machine if plan starts per-machine.
778 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL; 794 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL;
795 BOOL fReverseOrder = BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pPlan->action;
779 796
780 // Initialize the packages. 797 // Initialize the packages.
781 for (DWORD i = 0; i < cPackages; ++i) 798 for (DWORD i = 0; i < cPackages; ++i)
782 { 799 {
783 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; 800 DWORD iPackage = fReverseOrder ? cPackages - 1 - i : i;
784 BURN_PACKAGE* pPackage = rgPackages + iPackage; 801 BURN_PACKAGE* pPackage = rgPackages + iPackage;
785 802
786 hr = InitializePackage(pPlan, pUX, pVariables, pPackage); 803 hr = InitializePackage(pPlan, pUX, pVariables, pPackage);
@@ -790,7 +807,7 @@ static HRESULT PlanPackagesHelper(
790 // Initialize the patch targets after all packages, since they could rely on the requested state of packages that are after the patch's package in the chain. 807 // Initialize the patch targets after all packages, since they could rely on the requested state of packages that are after the patch's package in the chain.
791 for (DWORD i = 0; i < cPackages; ++i) 808 for (DWORD i = 0; i < cPackages; ++i)
792 { 809 {
793 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; 810 DWORD iPackage = fReverseOrder ? cPackages - 1 - i : i;
794 BURN_PACKAGE* pPackage = rgPackages + iPackage; 811 BURN_PACKAGE* pPackage = rgPackages + iPackage;
795 812
796 if (BURN_PACKAGE_TYPE_MSP == pPackage->type) 813 if (BURN_PACKAGE_TYPE_MSP == pPackage->type)
@@ -803,7 +820,7 @@ static HRESULT PlanPackagesHelper(
803 // Plan the packages. 820 // Plan the packages.
804 for (DWORD i = 0; i < cPackages; ++i) 821 for (DWORD i = 0; i < cPackages; ++i)
805 { 822 {
806 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; 823 DWORD iPackage = fReverseOrder ? cPackages - 1 - i : i;
807 BURN_PACKAGE* pPackage = rgPackages + iPackage; 824 BURN_PACKAGE* pPackage = rgPackages + iPackage;
808 825
809 hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, &pRollbackBoundary); 826 hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, &pRollbackBoundary);
@@ -825,7 +842,7 @@ static HRESULT PlanPackagesHelper(
825 // Plan clean up of packages. 842 // Plan clean up of packages.
826 for (DWORD i = 0; i < cPackages; ++i) 843 for (DWORD i = 0; i < cPackages; ++i)
827 { 844 {
828 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; 845 DWORD iPackage = fReverseOrder ? cPackages - 1 - i : i;
829 BURN_PACKAGE* pPackage = rgPackages + iPackage; 846 BURN_PACKAGE* pPackage = rgPackages + iPackage;
830 847
831 hr = PlanCleanPackage(pPlan, pPackage); 848 hr = PlanCleanPackage(pPlan, pPackage);
@@ -842,7 +859,7 @@ static HRESULT PlanPackagesHelper(
842 // Let the BA know the actions that were planned. 859 // Let the BA know the actions that were planned.
843 for (DWORD i = 0; i < cPackages; ++i) 860 for (DWORD i = 0; i < cPackages; ++i)
844 { 861 {
845 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; 862 DWORD iPackage = fReverseOrder ? cPackages - 1 - i : i;
846 BURN_PACKAGE* pPackage = rgPackages + iPackage; 863 BURN_PACKAGE* pPackage = rgPackages + iPackage;
847 864
848 UserExperienceOnPlannedPackage(pUX, pPackage->sczId, pPackage->execute, pPackage->rollback, pPackage->fPlannedCache, pPackage->fPlannedUncache); 865 UserExperienceOnPlannedPackage(pUX, pPackage->sczId, pPackage->execute, pPackage->rollback, pPackage->fPlannedCache, pPackage->fPlannedUncache);
@@ -931,8 +948,9 @@ static HRESULT ProcessPackage(
931{ 948{
932 HRESULT hr = S_OK; 949 HRESULT hr = S_OK;
933 BURN_ROLLBACK_BOUNDARY* pEffectiveRollbackBoundary = NULL; 950 BURN_ROLLBACK_BOUNDARY* pEffectiveRollbackBoundary = NULL;
951 BOOL fBackward = BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pPlan->action;
934 952
935 pEffectiveRollbackBoundary = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? pPackage->pRollbackBoundaryBackward : pPackage->pRollbackBoundaryForward; 953 pEffectiveRollbackBoundary = fBackward ? pPackage->pRollbackBoundaryBackward : pPackage->pRollbackBoundaryForward;
936 hr = ProcessPackageRollbackBoundary(pPlan, pUX, pLog, pVariables, pEffectiveRollbackBoundary, ppRollbackBoundary); 954 hr = ProcessPackageRollbackBoundary(pPlan, pUX, pLog, pVariables, pEffectiveRollbackBoundary, ppRollbackBoundary);
937 ExitOnFailure(hr, "Failed to process package rollback boundary."); 955 ExitOnFailure(hr, "Failed to process package rollback boundary.");
938 956
@@ -1205,6 +1223,7 @@ extern "C" HRESULT PlanDefaultRelatedBundleRequestState(
1205{ 1223{
1206 HRESULT hr = S_OK; 1224 HRESULT hr = S_OK;
1207 int nCompareResult = 0; 1225 int nCompareResult = 0;
1226 BOOL fUninstalling = BOOTSTRAPPER_ACTION_UNINSTALL == action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == action;
1208 1227
1209 // Never touch related bundles during Cache. 1228 // Never touch related bundles during Cache.
1210 if (BOOTSTRAPPER_ACTION_CACHE == action) 1229 if (BOOTSTRAPPER_ACTION_CACHE == action)
@@ -1215,7 +1234,7 @@ extern "C" HRESULT PlanDefaultRelatedBundleRequestState(
1215 switch (relatedBundleRelationType) 1234 switch (relatedBundleRelationType)
1216 { 1235 {
1217 case BOOTSTRAPPER_RELATION_UPGRADE: 1236 case BOOTSTRAPPER_RELATION_UPGRADE:
1218 if (BOOTSTRAPPER_RELATION_UPGRADE != commandRelationType && BOOTSTRAPPER_ACTION_UNINSTALL < action) 1237 if (BOOTSTRAPPER_RELATION_UPGRADE != commandRelationType && !fUninstalling)
1219 { 1238 {
1220 hr = VerCompareParsedVersions(pRegistrationVersion, pRelatedBundleVersion, &nCompareResult); 1239 hr = VerCompareParsedVersions(pRegistrationVersion, pRelatedBundleVersion, &nCompareResult);
1221 ExitOnFailure(hr, "Failed to compare bundle version '%ls' to related bundle version '%ls'", pRegistrationVersion ? pRegistrationVersion->sczVersion : NULL, pRelatedBundleVersion ? pRelatedBundleVersion->sczVersion : NULL); 1240 ExitOnFailure(hr, "Failed to compare bundle version '%ls' to related bundle version '%ls'", pRegistrationVersion ? pRegistrationVersion->sczVersion : NULL, pRelatedBundleVersion ? pRelatedBundleVersion->sczVersion : NULL);
@@ -1225,7 +1244,7 @@ extern "C" HRESULT PlanDefaultRelatedBundleRequestState(
1225 break; 1244 break;
1226 case BOOTSTRAPPER_RELATION_PATCH: __fallthrough; 1245 case BOOTSTRAPPER_RELATION_PATCH: __fallthrough;
1227 case BOOTSTRAPPER_RELATION_ADDON: 1246 case BOOTSTRAPPER_RELATION_ADDON:
1228 if (BOOTSTRAPPER_ACTION_UNINSTALL == action) 1247 if (fUninstalling)
1229 { 1248 {
1230 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_ABSENT; 1249 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_ABSENT;
1231 } 1250 }
@@ -1242,7 +1261,7 @@ extern "C" HRESULT PlanDefaultRelatedBundleRequestState(
1242 // Automatically repair dependent bundles to restore missing 1261 // Automatically repair dependent bundles to restore missing
1243 // packages after uninstall unless we're being upgraded with the 1262 // packages after uninstall unless we're being upgraded with the
1244 // assumption that upgrades are cumulative (as intended). 1263 // assumption that upgrades are cumulative (as intended).
1245 if (BOOTSTRAPPER_RELATION_UPGRADE != commandRelationType && BOOTSTRAPPER_ACTION_UNINSTALL == action) 1264 if (BOOTSTRAPPER_RELATION_UPGRADE != commandRelationType && fUninstalling)
1246 { 1265 {
1247 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_REPAIR; 1266 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_REPAIR;
1248 } 1267 }
@@ -1270,6 +1289,7 @@ extern "C" HRESULT PlanRelatedBundlesBegin(
1270 LPWSTR* rgsczAncestors = NULL; 1289 LPWSTR* rgsczAncestors = NULL;
1271 UINT cAncestors = 0; 1290 UINT cAncestors = 0;
1272 STRINGDICT_HANDLE sdAncestors = NULL; 1291 STRINGDICT_HANDLE sdAncestors = NULL;
1292 BOOL fUninstalling = BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pPlan->action;
1273 1293
1274 if (pPlan->pInternalCommand->sczAncestors) 1294 if (pPlan->pInternalCommand->sczAncestors)
1275 { 1295 {
@@ -1329,7 +1349,7 @@ extern "C" HRESULT PlanRelatedBundlesBegin(
1329 ExitOnRootFailure(hr, "BA aborted plan related bundle."); 1349 ExitOnRootFailure(hr, "BA aborted plan related bundle.");
1330 1350
1331 // If uninstalling and the dependent related bundle may be executed, ignore its provider key to allow for downgrades with ref-counting. 1351 // If uninstalling and the dependent related bundle may be executed, ignore its provider key to allow for downgrades with ref-counting.
1332 if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action && BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType && BOOTSTRAPPER_REQUEST_STATE_NONE != pRelatedBundle->package.requested) 1352 if (fUninstalling && BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType && BOOTSTRAPPER_REQUEST_STATE_NONE != pRelatedBundle->package.requested)
1333 { 1353 {
1334 if (0 < pRelatedBundle->package.cDependencyProviders) 1354 if (0 < pRelatedBundle->package.cDependencyProviders)
1335 { 1355 {
@@ -1361,6 +1381,9 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1361 HRESULT hr = S_OK; 1381 HRESULT hr = S_OK;
1362 LPWSTR sczIgnoreDependencies = NULL; 1382 LPWSTR sczIgnoreDependencies = NULL;
1363 STRINGDICT_HANDLE sdProviderKeys = NULL; 1383 STRINGDICT_HANDLE sdProviderKeys = NULL;
1384 BOOL fExecutingAnyPackage = FALSE;
1385 BOOL fInstallingAnyPackage = FALSE;
1386 BOOL fUninstalling = BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pPlan->action;
1364 1387
1365 // Get the list of dependencies to ignore to pass to related bundles. 1388 // Get the list of dependencies to ignore to pass to related bundles.
1366 hr = DependencyAllocIgnoreDependencies(pPlan, &sczIgnoreDependencies); 1389 hr = DependencyAllocIgnoreDependencies(pPlan, &sczIgnoreDependencies);
@@ -1369,9 +1392,6 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1369 hr = DictCreateStringList(&sdProviderKeys, pPlan->cExecuteActions, DICT_FLAG_CASEINSENSITIVE); 1392 hr = DictCreateStringList(&sdProviderKeys, pPlan->cExecuteActions, DICT_FLAG_CASEINSENSITIVE);
1370 ExitOnFailure(hr, "Failed to create dictionary for planned packages."); 1393 ExitOnFailure(hr, "Failed to create dictionary for planned packages.");
1371 1394
1372 BOOL fExecutingAnyPackage = FALSE;
1373 BOOL fInstallingAnyPackage = FALSE;
1374
1375 for (DWORD i = 0; i < pPlan->cExecuteActions; ++i) 1395 for (DWORD i = 0; i < pPlan->cExecuteActions; ++i)
1376 { 1396 {
1377 BOOTSTRAPPER_ACTION_STATE packageAction = BOOTSTRAPPER_ACTION_STATE_NONE; 1397 BOOTSTRAPPER_ACTION_STATE packageAction = BOOTSTRAPPER_ACTION_STATE_NONE;
@@ -1444,7 +1464,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1444 } 1464 }
1445 1465
1446 // For an uninstall, there is no need to repair dependent bundles if no packages are executing. 1466 // For an uninstall, there is no need to repair dependent bundles if no packages are executing.
1447 if (!fExecutingAnyPackage && BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType && BOOTSTRAPPER_REQUEST_STATE_REPAIR == pRelatedBundle->package.requested && BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) 1467 if (!fExecutingAnyPackage && BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType && BOOTSTRAPPER_REQUEST_STATE_REPAIR == pRelatedBundle->package.requested && fUninstalling)
1448 { 1468 {
1449 pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE; 1469 pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE;
1450 LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_DEPENDENT_BUNDLE_REPAIR, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType)); 1470 LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_DEPENDENT_BUNDLE_REPAIR, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType));
@@ -1457,7 +1477,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1457 ExitOnFailure(hr, "Failed to copy the list of dependencies to ignore."); 1477 ExitOnFailure(hr, "Failed to copy the list of dependencies to ignore.");
1458 1478
1459 // Uninstall addons and patches early in the chain, before other packages are uninstalled. 1479 // Uninstall addons and patches early in the chain, before other packages are uninstalled.
1460 if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) 1480 if (fUninstalling)
1461 { 1481 {
1462 pdwInsertIndex = &dwExecuteActionEarlyIndex; 1482 pdwInsertIndex = &dwExecuteActionEarlyIndex;
1463 } 1483 }
@@ -1475,7 +1495,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1475 ExitOnFailure(hr, "Failed to begin plan dependency actions to package: %ls", pRelatedBundle->package.sczId); 1495 ExitOnFailure(hr, "Failed to begin plan dependency actions to package: %ls", pRelatedBundle->package.sczId);
1476 1496
1477 // If uninstalling a related bundle, make sure the bundle is uninstalled after removing registration. 1497 // If uninstalling a related bundle, make sure the bundle is uninstalled after removing registration.
1478 if (pdwInsertIndex && BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) 1498 if (pdwInsertIndex && fUninstalling)
1479 { 1499 {
1480 ++(*pdwInsertIndex); 1500 ++(*pdwInsertIndex);
1481 } 1501 }
@@ -1599,9 +1619,10 @@ extern "C" HRESULT PlanCleanPackage(
1599 HRESULT hr = S_OK; 1619 HRESULT hr = S_OK;
1600 BOOL fPlanCleanPackage = FALSE; 1620 BOOL fPlanCleanPackage = FALSE;
1601 BURN_CLEAN_ACTION* pCleanAction = NULL; 1621 BURN_CLEAN_ACTION* pCleanAction = NULL;
1622 BOOL fUninstalling = BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pPlan->action;
1602 1623
1603 // The following is a complex set of logic that determines when a package should be cleaned from the cache. 1624 // The following is a complex set of logic that determines when a package should be cleaned from the cache.
1604 if (BOOTSTRAPPER_CACHE_TYPE_FORCE > pPackage->cacheType || BOOTSTRAPPER_ACTION_CACHE > pPlan->action) 1625 if (BOOTSTRAPPER_CACHE_TYPE_FORCE > pPackage->cacheType || fUninstalling)
1605 { 1626 {
1606 // The following are all different reasons why the package should be cleaned from the cache. 1627 // The following are all different reasons why the package should be cleaned from the cache.
1607 // The else-ifs are used to make the conditions easier to see (rather than have them combined 1628 // The else-ifs are used to make the conditions easier to see (rather than have them combined
@@ -1624,7 +1645,7 @@ extern "C" HRESULT PlanCleanPackage(
1624 { 1645 {
1625 fPlanCleanPackage = TRUE; 1646 fPlanCleanPackage = TRUE;
1626 } 1647 }
1627 else if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action && // uninstalling and 1648 else if (fUninstalling && // uninstalling and
1628 BOOTSTRAPPER_REQUEST_STATE_NONE == pPackage->requested && // requested do nothing (aka: default) and 1649 BOOTSTRAPPER_REQUEST_STATE_NONE == pPackage->requested && // requested do nothing (aka: default) and
1629 BOOTSTRAPPER_ACTION_STATE_NONE == pPackage->execute && // execute is still do nothing and 1650 BOOTSTRAPPER_ACTION_STATE_NONE == pPackage->execute && // execute is still do nothing and
1630 !pPackage->fDependencyManagerWasHere && // dependency manager didn't change execute and 1651 !pPackage->fDependencyManagerWasHere && // dependency manager didn't change execute and
@@ -2091,6 +2112,7 @@ static HRESULT GetActionDefaultRequestState(
2091 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_REPAIR; 2112 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_REPAIR;
2092 break; 2113 break;
2093 2114
2115 case BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL: __fallthrough;
2094 case BOOTSTRAPPER_ACTION_UNINSTALL: 2116 case BOOTSTRAPPER_ACTION_UNINSTALL:
2095 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_ABSENT; 2117 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_ABSENT;
2096 break; 2118 break;
@@ -2671,7 +2693,7 @@ static BOOL ForceCache(
2671 BOOTSTRAPPER_REQUEST_STATE_CACHE < pPackage->requested; 2693 BOOTSTRAPPER_REQUEST_STATE_CACHE < pPackage->requested;
2672 case BOOTSTRAPPER_CACHE_TYPE_FORCE: 2694 case BOOTSTRAPPER_CACHE_TYPE_FORCE:
2673 // All packages that have cacheType set to force should be cached if the bundle is going to be present. 2695 // All packages that have cacheType set to force should be cached if the bundle is going to be present.
2674 return BOOTSTRAPPER_ACTION_UNINSTALL < pPlan->action; 2696 return BOOTSTRAPPER_ACTION_UNINSTALL != pPlan->action && BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL != pPlan->action;
2675 default: 2697 default:
2676 return FALSE; 2698 return FALSE;
2677 } 2699 }