summaryrefslogtreecommitdiff
path: root/src/burn/engine/dependency.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/burn/engine/dependency.cpp')
-rw-r--r--src/burn/engine/dependency.cpp257
1 files changed, 105 insertions, 152 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