aboutsummaryrefslogtreecommitdiff
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.cpp123
1 files changed, 108 insertions, 15 deletions
diff --git a/src/burn/engine/dependency.cpp b/src/burn/engine/dependency.cpp
index 5d7e1a94..6ee95935 100644
--- a/src/burn/engine/dependency.cpp
+++ b/src/burn/engine/dependency.cpp
@@ -54,6 +54,10 @@ static HRESULT AddPackageDependencyActions(
54 __in const BURN_DEPENDENCY_ACTION dependencyRollbackAction 54 __in const BURN_DEPENDENCY_ACTION dependencyRollbackAction
55 ); 55 );
56 56
57static LPCWSTR GetPackageProviderId(
58 __in const BURN_PACKAGE* pPackage
59 );
60
57static HRESULT RegisterPackageProvider( 61static HRESULT RegisterPackageProvider(
58 __in const BURN_PACKAGE* pPackage 62 __in const BURN_PACKAGE* pPackage
59 ); 63 );
@@ -299,6 +303,9 @@ extern "C" HRESULT DependencyDetectChainPackage(
299 hr = DetectPackageDependents(pPackage, pRegistration); 303 hr = DetectPackageDependents(pPackage, pRegistration);
300 ExitOnFailure(hr, "Failed to detect dependents for package '%ls'", pPackage->sczId); 304 ExitOnFailure(hr, "Failed to detect dependents for package '%ls'", pPackage->sczId);
301 305
306 hr = DependencyDetectCompatibleEntry(pPackage, pRegistration);
307 ExitOnFailure(hr, "Failed to detect compatible package for package '%ls'", pPackage->sczId);
308
302LExit: 309LExit:
303 return hr; 310 return hr;
304} 311}
@@ -396,6 +403,8 @@ extern "C" HRESULT DependencyPlanPackageBegin(
396 STRINGDICT_HANDLE sdIgnoredDependents = NULL; 403 STRINGDICT_HANDLE sdIgnoredDependents = NULL;
397 BURN_DEPENDENCY_ACTION dependencyExecuteAction = BURN_DEPENDENCY_ACTION_NONE; 404 BURN_DEPENDENCY_ACTION dependencyExecuteAction = BURN_DEPENDENCY_ACTION_NONE;
398 BURN_DEPENDENCY_ACTION dependencyRollbackAction = BURN_DEPENDENCY_ACTION_NONE; 405 BURN_DEPENDENCY_ACTION dependencyRollbackAction = BURN_DEPENDENCY_ACTION_NONE;
406 BOOL fDependentBlocksUninstall = FALSE;
407 BOOL fAttemptingUninstall = BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pPackage->execute || pPackage->compatiblePackage.fRemove;
399 408
400 pPackage->dependencyExecute = BURN_DEPENDENCY_ACTION_NONE; 409 pPackage->dependencyExecute = BURN_DEPENDENCY_ACTION_NONE;
401 pPackage->dependencyRollback = BURN_DEPENDENCY_ACTION_NONE; 410 pPackage->dependencyRollback = BURN_DEPENDENCY_ACTION_NONE;
@@ -415,7 +424,7 @@ extern "C" HRESULT DependencyPlanPackageBegin(
415 } 424 }
416 425
417 // If we're uninstalling the package, check if any dependents are registered. 426 // If we're uninstalling the package, check if any dependents are registered.
418 if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pPackage->execute) 427 if (fAttemptingUninstall)
419 { 428 {
420 // Build up a list of dependents to ignore, including the current bundle. 429 // Build up a list of dependents to ignore, including the current bundle.
421 hr = GetIgnoredDependents(pPackage, pPlan, &sdIgnoredDependents); 430 hr = GetIgnoredDependents(pPackage, pPlan, &sdIgnoredDependents);
@@ -444,9 +453,9 @@ extern "C" HRESULT DependencyPlanPackageBegin(
444 { 453 {
445 hr = S_OK; 454 hr = S_OK;
446 455
447 if (!pPackage->fDependencyManagerWasHere) 456 if (!fDependentBlocksUninstall)
448 { 457 {
449 pPackage->fDependencyManagerWasHere = TRUE; 458 fDependentBlocksUninstall = TRUE;
450 459
451 LogId(REPORT_STANDARD, MSG_DEPENDENCY_PACKAGE_HASDEPENDENTS, pPackage->sczId); 460 LogId(REPORT_STANDARD, MSG_DEPENDENCY_PACKAGE_HASDEPENDENTS, pPackage->sczId);
452 } 461 }
@@ -459,14 +468,20 @@ extern "C" HRESULT DependencyPlanPackageBegin(
459 } 468 }
460 } 469 }
461 470
471 if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pPackage->execute)
472 {
473 pPackage->fDependencyManagerWasHere = fDependentBlocksUninstall;
474 }
475
462 // Calculate the dependency actions before the package itself is planned. 476 // Calculate the dependency actions before the package itself is planned.
463 CalculateDependencyActionStates(pPackage, pPlan->action, &dependencyExecuteAction, &dependencyRollbackAction); 477 CalculateDependencyActionStates(pPackage, pPlan->action, &dependencyExecuteAction, &dependencyRollbackAction);
464 478
465 // If dependents were found, change the action to not uninstall the package. 479 // If dependents were found, change the action to not uninstall the package.
466 if (pPackage->fDependencyManagerWasHere) 480 if (fDependentBlocksUninstall)
467 { 481 {
468 pPackage->execute = BOOTSTRAPPER_ACTION_STATE_NONE; 482 pPackage->execute = BOOTSTRAPPER_ACTION_STATE_NONE;
469 pPackage->rollback = BOOTSTRAPPER_ACTION_STATE_NONE; 483 pPackage->rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
484 pPackage->compatiblePackage.fRemove = FALSE;
470 } 485 }
471 else 486 else
472 { 487 {
@@ -494,7 +509,7 @@ extern "C" HRESULT DependencyPlanPackageBegin(
494 } 509 }
495 510
496 // If the package will be removed, add its providers to the growing list in the plan. 511 // If the package will be removed, add its providers to the growing list in the plan.
497 if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pPackage->execute) 512 if (fAttemptingUninstall)
498 { 513 {
499 for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i) 514 for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i)
500 { 515 {
@@ -739,6 +754,73 @@ extern "C" void DependencyUnregisterBundle(
739 } 754 }
740} 755}
741 756
757extern "C" HRESULT DependencyDetectCompatibleEntry(
758 __in BURN_PACKAGE* pPackage,
759 __in BURN_REGISTRATION* pRegistration
760 )
761{
762 HRESULT hr = S_OK;
763 LPWSTR sczId = NULL;
764 LPWSTR sczName = NULL;
765 LPWSTR sczVersion = NULL;
766 LPCWSTR wzPackageProviderId = GetPackageProviderId(pPackage);
767 HKEY hkHive = pRegistration->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
768
769 switch (pPackage->type)
770 {
771 case BURN_PACKAGE_TYPE_MSI:
772 // Only MSI packages can handle compatible entries.
773 break;
774 default:
775 ExitFunction();
776 }
777
778 for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i)
779 {
780 BURN_DEPENDENCY_PROVIDER* pProvider = &pPackage->rgDependencyProviders[i];
781
782 hr = DepGetProviderInformation(hkHive, pProvider->sczKey, &sczId, &sczName, &sczVersion);
783 if (E_NOTFOUND == hr)
784 {
785 hr = S_OK;
786 continue;
787 }
788 ExitOnFailure(hr, "Failed to get provider information for compatible package: %ls", pProvider->sczKey);
789
790 // Make sure the compatible package is not the package itself.
791 if (!wzPackageProviderId)
792 {
793 if (!sczId)
794 {
795 continue;
796 }
797 }
798 else if (sczId && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, wzPackageProviderId, -1, sczId, -1))
799 {
800 continue;
801 }
802
803 pPackage->compatiblePackage.fDetected = TRUE;
804
805 hr = StrAllocString(&pPackage->compatiblePackage.compatibleEntry.sczProviderKey, pProvider->sczKey, 0);
806 ExitOnFailure(hr, "Failed to copy provider key for compatible entry.");
807
808 pPackage->compatiblePackage.compatibleEntry.sczId = sczId;
809 sczId = NULL;
810
811 pPackage->compatiblePackage.compatibleEntry.sczName = sczName;
812 sczName = NULL;
813
814 pPackage->compatiblePackage.compatibleEntry.sczVersion = sczVersion;
815 sczVersion = NULL;
816
817 break;
818 }
819
820LExit:
821 return hr;
822}
823
742// internal functions 824// internal functions
743 825
744 826
@@ -1170,24 +1252,35 @@ LExit:
1170 return hr; 1252 return hr;
1171} 1253}
1172 1254
1255static LPCWSTR GetPackageProviderId(
1256 __in const BURN_PACKAGE* pPackage
1257 )
1258{
1259 LPCWSTR wzId = NULL;
1260
1261 switch (pPackage->type)
1262 {
1263 case BURN_PACKAGE_TYPE_MSI:
1264 wzId = pPackage->Msi.sczProductCode;
1265 break;
1266 case BURN_PACKAGE_TYPE_MSP:
1267 wzId = pPackage->Msp.sczPatchCode;
1268 break;
1269 }
1270
1271 return wzId;
1272}
1273
1173static HRESULT RegisterPackageProvider( 1274static HRESULT RegisterPackageProvider(
1174 __in const BURN_PACKAGE* pPackage 1275 __in const BURN_PACKAGE* pPackage
1175 ) 1276 )
1176{ 1277{
1177 HRESULT hr = S_OK; 1278 HRESULT hr = S_OK;
1178 LPWSTR wzId = NULL;
1179 HKEY hkRoot = pPackage->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
1180 1279
1181 if (pPackage->rgDependencyProviders) 1280 if (pPackage->rgDependencyProviders)
1182 { 1281 {
1183 if (BURN_PACKAGE_TYPE_MSI == pPackage->type) 1282 HKEY hkRoot = pPackage->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
1184 { 1283 LPCWSTR wzId = GetPackageProviderId(pPackage);
1185 wzId = pPackage->Msi.sczProductCode;
1186 }
1187 else if (BURN_PACKAGE_TYPE_MSP == pPackage->type)
1188 {
1189 wzId = pPackage->Msp.sczPatchCode;
1190 }
1191 1284
1192 for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i) 1285 for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i)
1193 { 1286 {