diff options
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 | { |
