aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-01-31 16:43:44 -0600
committerSean Hall <r.sean.hall@gmail.com>2022-02-01 23:36:23 -0600
commita2b98c1abd6e6a1469936af5d93e4ace713b3fba (patch)
tree86f49a07f09f5052dd26c8310d8df7a0cd7c19cc
parentc95c41151d595f4630c4c2f4aeb4c7f9a97af5c7 (diff)
downloadwix-a2b98c1abd6e6a1469936af5d93e4ace713b3fba.tar.gz
wix-a2b98c1abd6e6a1469936af5d93e4ace713b3fba.tar.bz2
wix-a2b98c1abd6e6a1469936af5d93e4ace713b3fba.zip
Remove some assumptions in dependency planning.
* A package might be installed even if it was already present. * A package might be uninstalled even if it was already absent. * The bundle might not actually be uninstalled even if the planned action was uninstall. Fixes #6510
-rw-r--r--src/burn/engine/dependency.cpp257
-rw-r--r--src/burn/engine/detect.cpp4
-rw-r--r--src/burn/engine/package.h7
-rw-r--r--src/burn/engine/plan.cpp79
-rw-r--r--src/burn/engine/plan.h1
-rw-r--r--src/burn/test/BurnUnitTest/PlanTest.cpp18
-rw-r--r--src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs2
7 files changed, 158 insertions, 210 deletions
diff --git a/src/burn/engine/dependency.cpp b/src/burn/engine/dependency.cpp
index 01f27d72..b783d4c4 100644
--- a/src/burn/engine/dependency.cpp
+++ b/src/burn/engine/dependency.cpp
@@ -41,7 +41,6 @@ static BOOL GetProviderExists(
41 41
42static void CalculateDependencyActionStates( 42static void CalculateDependencyActionStates(
43 __in const BURN_PACKAGE* pPackage, 43 __in const BURN_PACKAGE* pPackage,
44 __in const BOOTSTRAPPER_ACTION action,
45 __out BURN_DEPENDENCY_ACTION* pDependencyExecuteAction, 44 __out BURN_DEPENDENCY_ACTION* pDependencyExecuteAction,
46 __out BURN_DEPENDENCY_ACTION* pDependencyRollbackAction 45 __out BURN_DEPENDENCY_ACTION* pDependencyRollbackAction
47 ); 46 );
@@ -497,7 +496,7 @@ extern "C" HRESULT DependencyPlanPackageBegin(
497 } 496 }
498 497
499 // Calculate the dependency actions before the package itself is planned. 498 // Calculate the dependency actions before the package itself is planned.
500 CalculateDependencyActionStates(pPackage, pPlan->action, &dependencyExecuteAction, &dependencyRollbackAction); 499 CalculateDependencyActionStates(pPackage, &dependencyExecuteAction, &dependencyRollbackAction);
501 500
502 // If dependents were found, change the action to not uninstall the package. 501 // If dependents were found, change the action to not uninstall the package.
503 if (fDependentBlocksUninstall) 502 if (fDependentBlocksUninstall)
@@ -510,37 +509,54 @@ extern "C" HRESULT DependencyPlanPackageBegin(
510 } 509 }
511 else 510 else
512 { 511 {
513 // Use the calculated dependency actions as the provider actions if there 512 // Only plan providers when the package is current (not obsolete).
514 // are any non-imported providers that need to be registered and the package
515 // is current (not obsolete).
516 if (BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE != pPackage->currentState) 513 if (BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE != pPackage->currentState)
517 { 514 {
518 BOOL fAllImportedProviders = TRUE; // assume all providers were imported.
519 for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i) 515 for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i)
520 { 516 {
521 const BURN_DEPENDENCY_PROVIDER* pProvider = &pPackage->rgDependencyProviders[i]; 517 BURN_DEPENDENCY_PROVIDER* pProvider = &pPackage->rgDependencyProviders[i];
522 if (!pProvider->fImported) 518
519 // Only need to handle providers that were authored directly in the bundle.
520 if (pProvider->fImported)
523 { 521 {
524 fAllImportedProviders = FALSE; 522 continue;
525 break;
526 } 523 }
527 }
528 524
529 if (!fAllImportedProviders) 525 pProvider->providerExecute = dependencyExecuteAction;
530 { 526 pProvider->providerRollback = dependencyRollbackAction;
531 for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i) 527
528 // Don't overwrite providers that we don't own.
529 if (pPackage->compatiblePackage.fDetected)
530 {
531 if (BURN_DEPENDENCY_ACTION_REGISTER == pProvider->providerExecute)
532 {
533 pProvider->providerExecute = BURN_DEPENDENCY_ACTION_NONE;
534 pProvider->providerRollback = BURN_DEPENDENCY_ACTION_NONE;
535 }
536
537 if (BURN_DEPENDENCY_ACTION_REGISTER == pProvider->providerRollback)
538 {
539 pProvider->providerRollback = BURN_DEPENDENCY_ACTION_NONE;
540 }
541 }
542
543 if (BURN_DEPENDENCY_ACTION_UNREGISTER == pProvider->providerExecute && !pProvider->fExists)
544 {
545 pProvider->providerExecute = BURN_DEPENDENCY_ACTION_NONE;
546 }
547
548 if (BURN_DEPENDENCY_ACTION_UNREGISTER == pProvider->providerRollback && pProvider->fExists ||
549 BURN_DEPENDENCY_ACTION_REGISTER == pProvider->providerRollback && !pProvider->fExists)
532 { 550 {
533 BURN_DEPENDENCY_PROVIDER* pProvider = &pPackage->rgDependencyProviders[i]; 551 pProvider->providerRollback = BURN_DEPENDENCY_ACTION_NONE;
534 pProvider->providerExecute = dependencyExecuteAction;
535 pProvider->providerRollback = dependencyRollbackAction;
536 } 552 }
537 553
538 if (BURN_DEPENDENCY_ACTION_NONE != dependencyExecuteAction) 554 if (BURN_DEPENDENCY_ACTION_NONE != pProvider->providerExecute)
539 { 555 {
540 pPackage->fProviderExecute = TRUE; 556 pPackage->fProviderExecute = TRUE;
541 } 557 }
542 558
543 if (BURN_DEPENDENCY_ACTION_NONE != dependencyRollbackAction) 559 if (BURN_DEPENDENCY_ACTION_NONE != pProvider->providerRollback)
544 { 560 {
545 pPackage->fProviderRollback = TRUE; 561 pPackage->fProviderRollback = TRUE;
546 } 562 }
@@ -567,6 +583,23 @@ extern "C" HRESULT DependencyPlanPackageBegin(
567 pProvider->dependentExecute = dependencyExecuteAction; 583 pProvider->dependentExecute = dependencyExecuteAction;
568 pProvider->dependentRollback = dependencyRollbackAction; 584 pProvider->dependentRollback = dependencyRollbackAction;
569 585
586 if (BURN_DEPENDENCY_ACTION_REGISTER == pProvider->dependentRollback &&
587 BURN_DEPENDENCY_ACTION_UNREGISTER == pProvider->providerExecute && BURN_DEPENDENCY_ACTION_REGISTER != pProvider->providerRollback)
588 {
589 pProvider->dependentRollback = BURN_DEPENDENCY_ACTION_NONE;
590 }
591
592 if (BURN_DEPENDENCY_ACTION_UNREGISTER == pProvider->dependentExecute && !pProvider->fBundleRegisteredAsDependent)
593 {
594 pProvider->dependentExecute = BURN_DEPENDENCY_ACTION_NONE;
595 }
596
597 if (BURN_DEPENDENCY_ACTION_UNREGISTER == pProvider->dependentRollback && pProvider->fBundleRegisteredAsDependent ||
598 BURN_DEPENDENCY_ACTION_REGISTER == pProvider->dependentRollback && !pProvider->fBundleRegisteredAsDependent)
599 {
600 pProvider->dependentRollback = BURN_DEPENDENCY_ACTION_NONE;
601 }
602
570 // The highest aggregate action state found will be returned. 603 // The highest aggregate action state found will be returned.
571 if (pPackage->dependencyExecute < pProvider->dependentExecute) 604 if (pPackage->dependencyExecute < pProvider->dependentExecute)
572 { 605 {
@@ -655,16 +688,8 @@ extern "C" HRESULT DependencyPlanPackageComplete(
655 // installed and all that good stuff. 688 // installed and all that good stuff.
656 if (BURN_DEPENDENCY_ACTION_REGISTER == pPackage->dependencyExecute) 689 if (BURN_DEPENDENCY_ACTION_REGISTER == pPackage->dependencyExecute)
657 { 690 {
658 // Recalculate the dependency actions in case other operations may have changed 691 hr = AddPackageDependencyActions(NULL, pPackage, pPlan, pPackage->dependencyExecute, pPackage->dependencyRollback);
659 // the package execution state. 692 ExitOnFailure(hr, "Failed to plan the dependency actions for package: %ls", pPackage->sczId);
660 CalculateDependencyActionStates(pPackage, pPlan->action, &pPackage->dependencyExecute, &pPackage->dependencyRollback);
661
662 // If the dependency execution action is *still* to register, add the dependency actions to the plan.
663 if (BURN_DEPENDENCY_ACTION_REGISTER == pPackage->dependencyExecute)
664 {
665 hr = AddPackageDependencyActions(NULL, pPackage, pPlan, pPackage->dependencyExecute, pPackage->dependencyRollback);
666 ExitOnFailure(hr, "Failed to plan the dependency actions for package: %ls", pPackage->sczId);
667 }
668 } 693 }
669 694
670LExit: 695LExit:
@@ -863,15 +888,6 @@ extern "C" HRESULT DependencyDetectCompatibleEntry(
863 LPCWSTR wzPackageProviderId = GetPackageProviderId(pPackage); 888 LPCWSTR wzPackageProviderId = GetPackageProviderId(pPackage);
864 HKEY hkHive = pRegistration->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 889 HKEY hkHive = pRegistration->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
865 890
866 switch (pPackage->type)
867 {
868 case BURN_PACKAGE_TYPE_MSI:
869 // Only MSI packages can handle compatible entries.
870 break;
871 default:
872 ExitFunction();
873 }
874
875 for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i) 891 for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i)
876 { 892 {
877 BURN_DEPENDENCY_PROVIDER* pProvider = &pPackage->rgDependencyProviders[i]; 893 BURN_DEPENDENCY_PROVIDER* pProvider = &pPackage->rgDependencyProviders[i];
@@ -944,46 +960,30 @@ static HRESULT DetectPackageDependents(
944 BURN_DEPENDENCY_PROVIDER* pProvider = &pPackage->rgDependencyProviders[i]; 960 BURN_DEPENDENCY_PROVIDER* pProvider = &pPackage->rgDependencyProviders[i];
945 961
946 hr = DepCheckDependents(hkHive, pProvider->sczKey, 0, NULL, &pProvider->rgDependents, &pProvider->cDependents); 962 hr = DepCheckDependents(hkHive, pProvider->sczKey, 0, NULL, &pProvider->rgDependents, &pProvider->cDependents);
947 if (E_FILENOTFOUND != hr) 963 if (E_FILENOTFOUND == hr)
948 { 964 {
949 ExitOnFailure(hr, "Failed dependents check on package provider: %ls", pProvider->sczKey); 965 hr = S_OK;
950 966 }
951 if (!pPackage->fPackageProviderExists && (0 < pProvider->cDependents || GetProviderExists(hkHive, pProvider->sczKey))) 967 ExitOnFailure(hr, "Failed dependents check on package provider: %ls", pProvider->sczKey);
952 {
953 pPackage->fPackageProviderExists = TRUE;
954 }
955
956 if (fCanIgnorePresence && !fBundleRegisteredAsDependent)
957 {
958 for (DWORD iDependent = 0; iDependent < pProvider->cDependents; ++iDependent)
959 {
960 DEPENDENCY* pDependent = pProvider->rgDependents + iDependent;
961 968
962 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->sczId, -1, pDependent->sczKey, -1)) 969 if (0 < pProvider->cDependents || GetProviderExists(hkHive, pProvider->sczKey))
963 { 970 {
964 fBundleRegisteredAsDependent = TRUE; 971 pProvider->fExists = TRUE;
965 break;
966 }
967 }
968 }
969 } 972 }
970 else 973
974 for (DWORD iDependent = 0; iDependent < pProvider->cDependents; ++iDependent)
971 { 975 {
972 hr = S_OK; 976 DEPENDENCY* pDependent = pProvider->rgDependents + iDependent;
973 977
974 if (!pPackage->fPackageProviderExists && GetProviderExists(hkHive, pProvider->sczKey)) 978 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->sczId, -1, pDependent->sczKey, -1))
975 { 979 {
976 pPackage->fPackageProviderExists = TRUE; 980 pProvider->fBundleRegisteredAsDependent = TRUE;
981 fBundleRegisteredAsDependent = TRUE;
982 break;
977 } 983 }
978 } 984 }
979 } 985 }
980 986
981 // Older bundles may not have written the id so try the default.
982 if (!pPackage->fPackageProviderExists && BURN_PACKAGE_TYPE_MSI == pPackage->type && pPackage->Msi.sczProductCode && GetProviderExists(hkHive, pPackage->Msi.sczProductCode))
983 {
984 pPackage->fPackageProviderExists = TRUE;
985 }
986
987 if (fCanIgnorePresence && !fBundleRegisteredAsDependent) 987 if (fCanIgnorePresence && !fBundleRegisteredAsDependent)
988 { 988 {
989 if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->cacheRegistrationState) 989 if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->cacheRegistrationState)
@@ -1190,95 +1190,54 @@ static BOOL GetProviderExists(
1190*********************************************************************/ 1190*********************************************************************/
1191static void CalculateDependencyActionStates( 1191static void CalculateDependencyActionStates(
1192 __in const BURN_PACKAGE* pPackage, 1192 __in const BURN_PACKAGE* pPackage,
1193 __in const BOOTSTRAPPER_ACTION action,
1194 __out BURN_DEPENDENCY_ACTION* pDependencyExecuteAction, 1193 __out BURN_DEPENDENCY_ACTION* pDependencyExecuteAction,
1195 __out BURN_DEPENDENCY_ACTION* pDependencyRollbackAction 1194 __out BURN_DEPENDENCY_ACTION* pDependencyRollbackAction
1196 ) 1195 )
1197{ 1196{
1198 switch (action) 1197 switch (pPackage->execute)
1199 { 1198 {
1200 case BOOTSTRAPPER_ACTION_UNINSTALL: 1199 case BOOTSTRAPPER_ACTION_STATE_NONE:
1201 // Always remove the dependency when uninstalling a bundle even if the package is absent. 1200 switch (pPackage->requested)
1202 *pDependencyExecuteAction = BURN_DEPENDENCY_ACTION_UNREGISTER;
1203 break;
1204 case BOOTSTRAPPER_ACTION_INSTALL: __fallthrough;
1205 case BOOTSTRAPPER_ACTION_CACHE:
1206 // Always remove the dependency during rollback when installing a bundle.
1207 *pDependencyRollbackAction = BURN_DEPENDENCY_ACTION_UNREGISTER;
1208 __fallthrough;
1209 case BOOTSTRAPPER_ACTION_MODIFY: __fallthrough;
1210 case BOOTSTRAPPER_ACTION_REPAIR:
1211 switch (pPackage->execute)
1212 { 1201 {
1213 case BOOTSTRAPPER_ACTION_STATE_NONE: 1202 case BOOTSTRAPPER_REQUEST_STATE_ABSENT:
1214 switch (pPackage->requested) 1203 // Unregister if the package is not requested but already not installed.
1204 *pDependencyExecuteAction = BURN_DEPENDENCY_ACTION_UNREGISTER;
1205 break;
1206 case BOOTSTRAPPER_REQUEST_STATE_NONE:
1207 // Register if a newer, compatible package is already installed.
1208 switch (pPackage->currentState)
1215 { 1209 {
1216 case BOOTSTRAPPER_REQUEST_STATE_NONE: 1210 case BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE: __fallthrough;
1217 // Register if a newer, compatible package is already installed. 1211 case BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED:
1218 switch (pPackage->currentState) 1212 *pDependencyExecuteAction = BURN_DEPENDENCY_ACTION_REGISTER;
1219 {
1220 case BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE:
1221 if (!pPackage->fPackageProviderExists)
1222 {
1223 break;
1224 }
1225 __fallthrough;
1226 case BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED:
1227 *pDependencyExecuteAction = BURN_DEPENDENCY_ACTION_REGISTER;
1228 break;
1229 }
1230 break;
1231 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
1232 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
1233 // Register if the package is requested but already installed.
1234 switch (pPackage->currentState)
1235 {
1236 case BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE:
1237 if (!pPackage->fPackageProviderExists)
1238 {
1239 break;
1240 }
1241 __fallthrough;
1242 case BOOTSTRAPPER_PACKAGE_STATE_PRESENT: __fallthrough;
1243 case BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED:
1244 *pDependencyExecuteAction = BURN_DEPENDENCY_ACTION_REGISTER;
1245 break;
1246 }
1247 break; 1213 break;
1248 } 1214 }
1249 break; 1215 break;
1250 case BOOTSTRAPPER_ACTION_STATE_UNINSTALL: 1216 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
1251 *pDependencyExecuteAction = BURN_DEPENDENCY_ACTION_UNREGISTER; 1217 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
1252 break; 1218 // Register if the package is requested but already installed.
1253 case BOOTSTRAPPER_ACTION_STATE_INSTALL: __fallthrough;
1254 case BOOTSTRAPPER_ACTION_STATE_MODIFY: __fallthrough;
1255 case BOOTSTRAPPER_ACTION_STATE_REPAIR: __fallthrough;
1256 case BOOTSTRAPPER_ACTION_STATE_MINOR_UPGRADE:
1257 *pDependencyExecuteAction = BURN_DEPENDENCY_ACTION_REGISTER; 1219 *pDependencyExecuteAction = BURN_DEPENDENCY_ACTION_REGISTER;
1258 break; 1220 break;
1259 } 1221 }
1260 break; 1222 break;
1223 case BOOTSTRAPPER_ACTION_STATE_UNINSTALL:
1224 *pDependencyExecuteAction = BURN_DEPENDENCY_ACTION_UNREGISTER;
1225 break;
1226 case BOOTSTRAPPER_ACTION_STATE_INSTALL: __fallthrough;
1227 case BOOTSTRAPPER_ACTION_STATE_MODIFY: __fallthrough;
1228 case BOOTSTRAPPER_ACTION_STATE_REPAIR: __fallthrough;
1229 case BOOTSTRAPPER_ACTION_STATE_MINOR_UPGRADE:
1230 *pDependencyExecuteAction = BURN_DEPENDENCY_ACTION_REGISTER;
1231 break;
1261 } 1232 }
1262 1233
1263 switch (*pDependencyExecuteAction) 1234 switch (*pDependencyExecuteAction)
1264 { 1235 {
1265 case BURN_DEPENDENCY_ACTION_REGISTER: 1236 case BURN_DEPENDENCY_ACTION_REGISTER:
1266 switch (pPackage->currentState) 1237 *pDependencyRollbackAction = BURN_DEPENDENCY_ACTION_UNREGISTER;
1267 {
1268 case BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE: __fallthrough;
1269 case BOOTSTRAPPER_PACKAGE_STATE_ABSENT:
1270 *pDependencyRollbackAction = BURN_DEPENDENCY_ACTION_UNREGISTER;
1271 break;
1272 }
1273 break; 1238 break;
1274 case BURN_DEPENDENCY_ACTION_UNREGISTER: 1239 case BURN_DEPENDENCY_ACTION_UNREGISTER:
1275 switch (pPackage->currentState) 1240 *pDependencyRollbackAction = BURN_DEPENDENCY_ACTION_REGISTER;
1276 {
1277 case BOOTSTRAPPER_PACKAGE_STATE_PRESENT: __fallthrough;
1278 case BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED:
1279 *pDependencyRollbackAction = BURN_DEPENDENCY_ACTION_REGISTER;
1280 break;
1281 }
1282 break; 1241 break;
1283 } 1242 }
1284} 1243}
@@ -1376,13 +1335,10 @@ static HRESULT RegisterPackageProvider(
1376{ 1335{
1377 HRESULT hr = S_OK; 1336 HRESULT hr = S_OK;
1378 1337
1379 if (!pProvider->fImported) 1338 LogId(REPORT_VERBOSE, MSG_DEPENDENCY_PACKAGE_REGISTER, pProvider->sczKey, pProvider->sczVersion, wzPackageId);
1380 {
1381 LogId(REPORT_VERBOSE, MSG_DEPENDENCY_PACKAGE_REGISTER, pProvider->sczKey, pProvider->sczVersion, wzPackageId);
1382 1339
1383 hr = DepRegisterDependency(hkRoot, pProvider->sczKey, pProvider->sczVersion, pProvider->sczDisplayName, wzPackageProviderId, 0); 1340 hr = DepRegisterDependency(hkRoot, pProvider->sczKey, pProvider->sczVersion, pProvider->sczDisplayName, wzPackageProviderId, 0);
1384 ExitOnFailure(hr, "Failed to register the package dependency provider: %ls", pProvider->sczKey); 1341 ExitOnFailure(hr, "Failed to register the package dependency provider: %ls", pProvider->sczKey);
1385 }
1386 1342
1387LExit: 1343LExit:
1388 if (!fVital) 1344 if (!fVital)
@@ -1406,17 +1362,14 @@ static void UnregisterPackageProvider(
1406{ 1362{
1407 HRESULT hr = S_OK; 1363 HRESULT hr = S_OK;
1408 1364
1409 if (!pProvider->fImported) 1365 hr = DepUnregisterDependency(hkRoot, pProvider->sczKey);
1366 if (SUCCEEDED(hr))
1410 { 1367 {
1411 hr = DepUnregisterDependency(hkRoot, pProvider->sczKey); 1368 LogId(REPORT_VERBOSE, MSG_DEPENDENCY_PACKAGE_UNREGISTERED, pProvider->sczKey, wzPackageId);
1412 if (SUCCEEDED(hr)) 1369 }
1413 { 1370 else if (FAILED(hr) && E_FILENOTFOUND != hr)
1414 LogId(REPORT_VERBOSE, MSG_DEPENDENCY_PACKAGE_UNREGISTERED, pProvider->sczKey, wzPackageId); 1371 {
1415 } 1372 LogId(REPORT_VERBOSE, MSG_DEPENDENCY_PACKAGE_UNREGISTERED_FAILED, pProvider->sczKey, wzPackageId, hr);
1416 else if (FAILED(hr) && E_FILENOTFOUND != hr)
1417 {
1418 LogId(REPORT_VERBOSE, MSG_DEPENDENCY_PACKAGE_UNREGISTERED_FAILED, pProvider->sczKey, wzPackageId, hr);
1419 }
1420 } 1373 }
1421} 1374}
1422 1375
diff --git a/src/burn/engine/detect.cpp b/src/burn/engine/detect.cpp
index 617b418b..e251871c 100644
--- a/src/burn/engine/detect.cpp
+++ b/src/burn/engine/detect.cpp
@@ -57,7 +57,6 @@ extern "C" void DetectReset(
57 BURN_PACKAGE* pPackage = pPackages->rgPackages + iPackage; 57 BURN_PACKAGE* pPackage = pPackages->rgPackages + iPackage;
58 58
59 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN; 59 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN;
60 pPackage->fPackageProviderExists = FALSE;
61 pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; 60 pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
62 pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; 61 pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
63 62
@@ -92,6 +91,9 @@ extern "C" void DetectReset(
92 { 91 {
93 BURN_DEPENDENCY_PROVIDER* pProvider = pPackage->rgDependencyProviders + iProvider; 92 BURN_DEPENDENCY_PROVIDER* pProvider = pPackage->rgDependencyProviders + iProvider;
94 93
94 pProvider->fExists = FALSE;
95 pProvider->fBundleRegisteredAsDependent = FALSE;
96
95 if (pProvider->rgDependents) 97 if (pProvider->rgDependents)
96 { 98 {
97 ReleaseDependencyArray(pProvider->rgDependents, pProvider->cDependents); 99 ReleaseDependencyArray(pProvider->rgDependents, pProvider->cDependents);
diff --git a/src/burn/engine/package.h b/src/burn/engine/package.h
index 38be2098..6d1b5dd9 100644
--- a/src/burn/engine/package.h
+++ b/src/burn/engine/package.h
@@ -193,8 +193,10 @@ typedef struct _BURN_DEPENDENCY_PROVIDER
193 LPWSTR sczDisplayName; 193 LPWSTR sczDisplayName;
194 BOOL fImported; 194 BOOL fImported;
195 195
196 DEPENDENCY* rgDependents; // only valid after Detect. 196 BOOL fExists; // only valid after Detect.
197 UINT cDependents; // only valid after Detect. 197 BOOL fBundleRegisteredAsDependent; // only valid after Detect.
198 DEPENDENCY* rgDependents; // only valid after Detect.
199 UINT cDependents; // only valid after Detect.
198 200
199 BURN_DEPENDENCY_ACTION dependentExecute; // only valid during Plan. 201 BURN_DEPENDENCY_ACTION dependentExecute; // only valid during Plan.
200 BURN_DEPENDENCY_ACTION dependentRollback; // only valid during Plan. 202 BURN_DEPENDENCY_ACTION dependentRollback; // only valid during Plan.
@@ -264,7 +266,6 @@ typedef struct _BURN_PACKAGE
264 266
265 BOOTSTRAPPER_PACKAGE_STATE currentState; // only valid after Detect. 267 BOOTSTRAPPER_PACKAGE_STATE currentState; // only valid after Detect.
266 BOOL fCached; // only valid after Detect. 268 BOOL fCached; // only valid after Detect.
267 BOOL fPackageProviderExists; // only valid after Detect.
268 BOOTSTRAPPER_CACHE_TYPE cacheType; // only valid during Plan. 269 BOOTSTRAPPER_CACHE_TYPE cacheType; // only valid during Plan.
269 BOOTSTRAPPER_REQUEST_STATE defaultRequested;// only valid during Plan. 270 BOOTSTRAPPER_REQUEST_STATE defaultRequested;// only valid during Plan.
270 BOOTSTRAPPER_REQUEST_STATE requested; // only valid during Plan. 271 BOOTSTRAPPER_REQUEST_STATE requested; // only valid during Plan.
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp
index 812dcd15..f850d49c 100644
--- a/src/burn/engine/plan.cpp
+++ b/src/burn/engine/plan.cpp
@@ -67,7 +67,6 @@ static HRESULT ProcessPackageRollbackBoundary(
67 ); 67 );
68static HRESULT GetActionDefaultRequestState( 68static HRESULT GetActionDefaultRequestState(
69 __in BOOTSTRAPPER_ACTION action, 69 __in BOOTSTRAPPER_ACTION action,
70 __in BOOL fPermanent,
71 __in BOOTSTRAPPER_PACKAGE_STATE currentState, 70 __in BOOTSTRAPPER_PACKAGE_STATE currentState,
72 __out BOOTSTRAPPER_REQUEST_STATE* pRequestState 71 __out BOOTSTRAPPER_REQUEST_STATE* pRequestState
73 ); 72 );
@@ -318,7 +317,6 @@ LExit:
318extern "C" HRESULT PlanDefaultPackageRequestState( 317extern "C" HRESULT PlanDefaultPackageRequestState(
319 __in BURN_PACKAGE_TYPE packageType, 318 __in BURN_PACKAGE_TYPE packageType,
320 __in BOOTSTRAPPER_PACKAGE_STATE currentState, 319 __in BOOTSTRAPPER_PACKAGE_STATE currentState,
321 __in BOOL fPermanent,
322 __in BOOTSTRAPPER_ACTION action, 320 __in BOOTSTRAPPER_ACTION action,
323 __in BOOTSTRAPPER_PACKAGE_CONDITION_RESULT installCondition, 321 __in BOOTSTRAPPER_PACKAGE_CONDITION_RESULT installCondition,
324 __in BOOTSTRAPPER_RELATION_TYPE relationType, 322 __in BOOTSTRAPPER_RELATION_TYPE relationType,
@@ -333,6 +331,20 @@ extern "C" HRESULT PlanDefaultPackageRequestState(
333 { 331 {
334 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_CACHE; 332 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_CACHE;
335 } 333 }
334 else if (BOOTSTRAPPER_ACTION_CACHE == action)
335 {
336 switch (currentState)
337 {
338 case BOOTSTRAPPER_PACKAGE_STATE_PRESENT: __fallthrough;
339 case BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED:
340 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT;
341 break;
342
343 default:
344 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_CACHE;
345 break;
346 }
347 }
336 else if (BOOTSTRAPPER_RELATION_PATCH == relationType && BURN_PACKAGE_TYPE_MSP == packageType) 348 else if (BOOTSTRAPPER_RELATION_PATCH == relationType && BURN_PACKAGE_TYPE_MSP == packageType)
337 { 349 {
338 // For patch related bundles, only install a patch if currently absent during install, modify, or repair. 350 // For patch related bundles, only install a patch if currently absent during install, modify, or repair.
@@ -345,33 +357,30 @@ extern "C" HRESULT PlanDefaultPackageRequestState(
345 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; 357 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE;
346 } 358 }
347 } 359 }
348 else if (BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED == currentState && BOOTSTRAPPER_ACTION_UNINSTALL != action)
349 {
350 // Superseded means the package is on the machine but not active, so only uninstall operations are allowed.
351 // All other operations do nothing.
352 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE;
353 }
354 else if (BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE == currentState && !(BOOTSTRAPPER_ACTION_UNINSTALL == action && BURN_PACKAGE_TYPE_MSP == packageType))
355 {
356 // Obsolete means the package is not on the machine and should not be installed, *except* patches can be obsolete
357 // and present so allow them to be removed during uninstall. Everyone else, gets nothing.
358 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE;
359 }
360 else // pick the best option for the action state and install condition. 360 else // pick the best option for the action state and install condition.
361 { 361 {
362 hr = GetActionDefaultRequestState(action, fPermanent, currentState, &defaultRequestState); 362 hr = GetActionDefaultRequestState(action, currentState, &defaultRequestState);
363 ExitOnFailure(hr, "Failed to get default request state for action."); 363 ExitOnFailure(hr, "Failed to get default request state for action.");
364 364
365 // If we're doing an install, use the install condition 365 if (BOOTSTRAPPER_ACTION_UNINSTALL != action)
366 // to determine whether to use the default request state or make the package absent.
367 if (BOOTSTRAPPER_ACTION_UNINSTALL != action && BOOTSTRAPPER_PACKAGE_CONDITION_FALSE == installCondition)
368 {
369 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_ABSENT;
370 }
371 else // just set the package to the default request state.
372 { 366 {
373 *pRequestState = defaultRequestState; 367 // If we're not doing an uninstall, use the install condition
368 // to determine whether to use the default request state or make the package absent.
369 if (BOOTSTRAPPER_PACKAGE_CONDITION_FALSE == installCondition)
370 {
371 defaultRequestState = BOOTSTRAPPER_REQUEST_STATE_ABSENT;
372 }
373 // Obsolete means the package is not on the machine and should not be installed,
374 // *except* patches can be obsolete and present.
375 // Superseded means the package is on the machine but not active, so only uninstall operations are allowed.
376 // All other operations do nothing.
377 else if (BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE == currentState || BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED == currentState)
378 {
379 defaultRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT <= defaultRequestState ? BOOTSTRAPPER_REQUEST_STATE_NONE : defaultRequestState;
380 }
374 } 381 }
382
383 *pRequestState = defaultRequestState;
375 } 384 }
376 385
377LExit: 386LExit:
@@ -873,7 +882,7 @@ static HRESULT InitializePackage(
873 } 882 }
874 883
875 // Remember the default requested state so the engine doesn't get blamed for planning the wrong thing if the BA changes it. 884 // Remember the default requested state so the engine doesn't get blamed for planning the wrong thing if the BA changes it.
876 hr = PlanDefaultPackageRequestState(pPackage->type, pPackage->currentState, pPackage->fPermanent, pPlan->action, installCondition, relationType, &pPackage->defaultRequested); 885 hr = PlanDefaultPackageRequestState(pPackage->type, pPackage->currentState, pPlan->action, installCondition, relationType, &pPackage->defaultRequested);
877 ExitOnFailure(hr, "Failed to set default package state."); 886 ExitOnFailure(hr, "Failed to set default package state.");
878 887
879 pPackage->requested = pPackage->defaultRequested; 888 pPackage->requested = pPackage->defaultRequested;
@@ -1993,7 +2002,6 @@ static void ResetPlannedRollbackBoundaryState(
1993 2002
1994static HRESULT GetActionDefaultRequestState( 2003static HRESULT GetActionDefaultRequestState(
1995 __in BOOTSTRAPPER_ACTION action, 2004 __in BOOTSTRAPPER_ACTION action,
1996 __in BOOL fPermanent,
1997 __in BOOTSTRAPPER_PACKAGE_STATE currentState, 2005 __in BOOTSTRAPPER_PACKAGE_STATE currentState,
1998 __out BOOTSTRAPPER_REQUEST_STATE* pRequestState 2006 __out BOOTSTRAPPER_REQUEST_STATE* pRequestState
1999 ) 2007 )
@@ -2002,22 +2010,7 @@ static HRESULT GetActionDefaultRequestState(
2002 2010
2003 switch (action) 2011 switch (action)
2004 { 2012 {
2005 case BOOTSTRAPPER_ACTION_CACHE: 2013 case BOOTSTRAPPER_ACTION_INSTALL:
2006 switch (currentState)
2007 {
2008 case BOOTSTRAPPER_PACKAGE_STATE_PRESENT:
2009 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT;
2010 break;
2011
2012 default:
2013 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_CACHE;
2014 break;
2015 }
2016 break;
2017
2018 case BOOTSTRAPPER_ACTION_INSTALL: __fallthrough;
2019 case BOOTSTRAPPER_ACTION_UPDATE_REPLACE: __fallthrough;
2020 case BOOTSTRAPPER_ACTION_UPDATE_REPLACE_EMBEDDED:
2021 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT; 2014 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT;
2022 break; 2015 break;
2023 2016
@@ -2026,7 +2019,7 @@ static HRESULT GetActionDefaultRequestState(
2026 break; 2019 break;
2027 2020
2028 case BOOTSTRAPPER_ACTION_UNINSTALL: 2021 case BOOTSTRAPPER_ACTION_UNINSTALL:
2029 *pRequestState = fPermanent ? BOOTSTRAPPER_REQUEST_STATE_NONE : BOOTSTRAPPER_REQUEST_STATE_ABSENT; 2022 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_ABSENT;
2030 break; 2023 break;
2031 2024
2032 case BOOTSTRAPPER_ACTION_MODIFY: 2025 case BOOTSTRAPPER_ACTION_MODIFY:
@@ -2052,7 +2045,7 @@ static HRESULT GetActionDefaultRequestState(
2052 } 2045 }
2053 2046
2054LExit: 2047LExit:
2055 return hr; 2048 return hr;
2056} 2049}
2057 2050
2058static HRESULT AddRegistrationAction( 2051static HRESULT AddRegistrationAction(
diff --git a/src/burn/engine/plan.h b/src/burn/engine/plan.h
index 3e5ab159..0734e39f 100644
--- a/src/burn/engine/plan.h
+++ b/src/burn/engine/plan.h
@@ -317,7 +317,6 @@ HRESULT PlanSetVariables(
317HRESULT PlanDefaultPackageRequestState( 317HRESULT PlanDefaultPackageRequestState(
318 __in BURN_PACKAGE_TYPE packageType, 318 __in BURN_PACKAGE_TYPE packageType,
319 __in BOOTSTRAPPER_PACKAGE_STATE currentState, 319 __in BOOTSTRAPPER_PACKAGE_STATE currentState,
320 __in BOOL fPermanent,
321 __in BOOTSTRAPPER_ACTION action, 320 __in BOOTSTRAPPER_ACTION action,
322 __in BOOTSTRAPPER_PACKAGE_CONDITION_RESULT installCondition, 321 __in BOOTSTRAPPER_PACKAGE_CONDITION_RESULT installCondition,
323 __in BOOTSTRAPPER_RELATION_TYPE relationType, 322 __in BOOTSTRAPPER_RELATION_TYPE relationType,
diff --git a/src/burn/test/BurnUnitTest/PlanTest.cpp b/src/burn/test/BurnUnitTest/PlanTest.cpp
index 1c390782..99644115 100644
--- a/src/burn/test/BurnUnitTest/PlanTest.cpp
+++ b/src/burn/test/BurnUnitTest/PlanTest.cpp
@@ -305,7 +305,7 @@ namespace Bootstrapper
305 305
306 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState); 306 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState);
307 DetectPackagesAsAbsent(pEngineState); 307 DetectPackagesAsAbsent(pEngineState);
308 DetectCompatibleMsiPackage(pEngineState->packages.rgPackages, L"{C24F3903-38E7-4D44-8037-D9856B3C5046}", L"2.0.0.0"); 308 DetectCompatibleMsiPackage(pEngineState, pEngineState->packages.rgPackages, L"{C24F3903-38E7-4D44-8037-D9856B3C5046}", L"2.0.0.0");
309 309
310 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_UNINSTALL); 310 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_UNINSTALL);
311 NativeAssert::Succeeded(hr, "CorePlan failed"); 311 NativeAssert::Succeeded(hr, "CorePlan failed");
@@ -491,7 +491,6 @@ namespace Bootstrapper
491 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 491 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
492 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageA"); 492 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
493 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 493 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
494 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
495 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++); 494 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
496 Assert::Equal(dwIndex, pPlan->cExecuteActions); 495 Assert::Equal(dwIndex, pPlan->cExecuteActions);
497 496
@@ -501,8 +500,6 @@ namespace Bootstrapper
501 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 500 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
502 ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PackageA"); 501 ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
503 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 502 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
504 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", unregisterActions1, 1);
505 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
506 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 503 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
507 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++); 504 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
508 Assert::Equal(dwIndex, pPlan->cRollbackActions); 505 Assert::Equal(dwIndex, pPlan->cRollbackActions);
@@ -561,8 +558,6 @@ namespace Bootstrapper
561 dwIndex = 0; 558 dwIndex = 0;
562 DWORD dwExecuteCheckpointId = 1; 559 DWORD dwExecuteCheckpointId = 1;
563 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 560 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
564 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", unregisterActions1, 1);
565 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", unregisterActions1, 1);
566 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, BOOTSTRAPPER_MSI_FILE_VERSIONING_MISSING_OR_OLDER, 0); 561 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, BOOTSTRAPPER_MSI_FILE_VERSIONING_MISSING_OR_OLDER, 0);
567 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 562 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
568 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 563 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -613,10 +608,10 @@ namespace Bootstrapper
613 vfUseRelatedBundleRequestState = TRUE; 608 vfUseRelatedBundleRequestState = TRUE;
614 vRelatedBundleRequestState = BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT; 609 vRelatedBundleRequestState = BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT;
615 610
616 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_MODIFY); 611 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_INSTALL);
617 NativeAssert::Succeeded(hr, "CorePlan failed"); 612 NativeAssert::Succeeded(hr, "CorePlan failed");
618 613
619 Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_MODIFY, pPlan->action); 614 Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_INSTALL, pPlan->action);
620 Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine); 615 Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine);
621 Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); 616 Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback);
622 617
@@ -1258,7 +1253,7 @@ namespace Bootstrapper
1258 } 1253 }
1259 } 1254 }
1260 1255
1261 void DetectCompatibleMsiPackage(BURN_PACKAGE* pPackage, LPCWSTR wzProductCode, LPCWSTR wzVersion) 1256 void DetectCompatibleMsiPackage(BURN_ENGINE_STATE* pEngineState, BURN_PACKAGE* pPackage, LPCWSTR wzProductCode, LPCWSTR wzVersion)
1262 { 1257 {
1263 HRESULT hr = S_OK; 1258 HRESULT hr = S_OK;
1264 Assert(BOOTSTRAPPER_PACKAGE_STATE_PRESENT > pPackage->currentState); 1259 Assert(BOOTSTRAPPER_PACKAGE_STATE_PRESENT > pPackage->currentState);
@@ -1286,6 +1281,8 @@ namespace Bootstrapper
1286 1281
1287 hr = StrAllocString(&pCompatiblePackage->compatibleEntry.sczProviderKey, pProvider->sczKey, 0); 1282 hr = StrAllocString(&pCompatiblePackage->compatibleEntry.sczProviderKey, pProvider->sczKey, 0);
1288 NativeAssert::Succeeded(hr, "Failed to copy provider key"); 1283 NativeAssert::Succeeded(hr, "Failed to copy provider key");
1284
1285 DetectPackageDependent(pPackage, pEngineState->registration.sczId);
1289 } 1286 }
1290 1287
1291 void DetectPackageAsAbsent(BURN_PACKAGE* pPackage) 1288 void DetectPackageAsAbsent(BURN_PACKAGE* pPackage)
@@ -1319,6 +1316,9 @@ namespace Bootstrapper
1319 1316
1320 hr = DepDependencyArrayAlloc(&pProvider->rgDependents, &pProvider->cDependents, wzId, NULL); 1317 hr = DepDependencyArrayAlloc(&pProvider->rgDependents, &pProvider->cDependents, wzId, NULL);
1321 NativeAssert::Succeeded(hr, "Failed to add package dependent"); 1318 NativeAssert::Succeeded(hr, "Failed to add package dependent");
1319
1320 pProvider->fExists = TRUE;
1321 pProvider->fBundleRegisteredAsDependent = TRUE;
1322 } 1322 }
1323 } 1323 }
1324 1324
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs
index ecd12fb3..7c74f348 100644
--- a/src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs
+++ b/src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs
@@ -611,7 +611,7 @@ namespace WixToolsetTest.BurnE2E
611 packageGv2.VerifyInstalled(false); 611 packageGv2.VerifyInstalled(false);
612 } 612 }
613 613
614 [Fact(Skip = "https://github.com/wixtoolset/issues/issues/6510")] 614 [Fact]
615 public void DoesntLoseDependenciesOnFailedMajorUpgradeBundleFromMinorUpdateMsi() 615 public void DoesntLoseDependenciesOnFailedMajorUpgradeBundleFromMinorUpdateMsi()
616 { 616 {
617 var packageAv1 = this.CreatePackageInstaller("PackageAv1"); 617 var packageAv1 = this.CreatePackageInstaller("PackageAv1");