diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2022-01-14 21:37:24 -0600 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2022-01-16 10:30:28 -0600 |
commit | da1d1376953ef1c9afb32d5eee02b785e52e372e (patch) | |
tree | 0df8550960259d7b13f5cd90f04d21b5576f16b7 /src/burn/engine/dependency.cpp | |
parent | abe316b80fae80eba54b0b79e76b6362105fa098 (diff) | |
download | wix-da1d1376953ef1c9afb32d5eee02b785e52e372e.tar.gz wix-da1d1376953ef1c9afb32d5eee02b785e52e372e.tar.bz2 wix-da1d1376953ef1c9afb32d5eee02b785e52e372e.zip |
Remove orphan compatible MSI packages.
Reimplements #3190
Diffstat (limited to 'src/burn/engine/dependency.cpp')
-rw-r--r-- | src/burn/engine/dependency.cpp | 123 |
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 | ||
57 | static LPCWSTR GetPackageProviderId( | ||
58 | __in const BURN_PACKAGE* pPackage | ||
59 | ); | ||
60 | |||
57 | static HRESULT RegisterPackageProvider( | 61 | static 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 | |||
302 | LExit: | 309 | LExit: |
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 | ||
757 | extern "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 | |||
820 | LExit: | ||
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 | ||
1255 | static 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 | |||
1173 | static HRESULT RegisterPackageProvider( | 1274 | static 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 | { |