diff options
Diffstat (limited to 'src/burn/engine/msiengine.cpp')
-rw-r--r-- | src/burn/engine/msiengine.cpp | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/src/burn/engine/msiengine.cpp b/src/burn/engine/msiengine.cpp index 87ae77e9..68582d29 100644 --- a/src/burn/engine/msiengine.cpp +++ b/src/burn/engine/msiengine.cpp | |||
@@ -506,6 +506,9 @@ extern "C" HRESULT MsiEngineDetectPackage( | |||
506 | { | 506 | { |
507 | BURN_RELATED_MSI* pRelatedMsi = &pPackage->Msi.rgRelatedMsis[i]; | 507 | BURN_RELATED_MSI* pRelatedMsi = &pPackage->Msi.rgRelatedMsis[i]; |
508 | 508 | ||
509 | ReleaseVerutilVersion(pVersion); | ||
510 | pVersion = NULL; | ||
511 | |||
509 | for (DWORD iProduct = 0; ; ++iProduct) | 512 | for (DWORD iProduct = 0; ; ++iProduct) |
510 | { | 513 | { |
511 | // get product | 514 | // get product |
@@ -708,6 +711,46 @@ extern "C" HRESULT MsiEngineDetectPackage( | |||
708 | hr = DependencyDetectChainPackage(pPackage, pRegistration); | 711 | hr = DependencyDetectChainPackage(pPackage, pRegistration); |
709 | ExitOnFailure(hr, "Failed to detect dependencies for MSI package."); | 712 | ExitOnFailure(hr, "Failed to detect dependencies for MSI package."); |
710 | 713 | ||
714 | if (BOOTSTRAPPER_PACKAGE_STATE_PRESENT > pPackage->currentState) | ||
715 | { | ||
716 | hr = MsiEngineDetectCompatiblePackage(pPackage); | ||
717 | ExitOnFailure(hr, "Failed to detect compatible package for MSI package."); | ||
718 | |||
719 | if (BURN_PACKAGE_TYPE_MSI == pPackage->compatiblePackage.type) | ||
720 | { | ||
721 | LPCWSTR wzCompatibleProductCode = pPackage->compatiblePackage.compatibleEntry.sczId; | ||
722 | LPCWSTR wzCompatibleInstalledVersion = pPackage->compatiblePackage.Msi.sczVersion; | ||
723 | |||
724 | ReleaseVerutilVersion(pVersion); | ||
725 | pVersion = NULL; | ||
726 | |||
727 | hr = VerParseVersion(wzCompatibleInstalledVersion, 0, FALSE, &pVersion); | ||
728 | ExitOnFailure(hr, "Failed to parse dependency version: '%ls' for ProductCode: %ls", wzCompatibleInstalledVersion, wzCompatibleProductCode); | ||
729 | |||
730 | if (pVersion->fInvalid) | ||
731 | { | ||
732 | LogId(REPORT_WARNING, MSG_DETECTED_MSI_PACKAGE_INVALID_VERSION, wzCompatibleProductCode, wzCompatibleInstalledVersion); | ||
733 | } | ||
734 | |||
735 | pPackage->compatiblePackage.Msi.pVersion = pVersion; | ||
736 | pVersion = NULL; | ||
737 | |||
738 | // compare versions | ||
739 | hr = VerCompareParsedVersions(pPackage->Msi.pVersion, pPackage->compatiblePackage.Msi.pVersion, &nCompareResult); | ||
740 | ExitOnFailure(hr, "Failed to compare version '%ls' to dependency version: '%ls'", pPackage->Msi.pVersion->sczVersion, wzCompatibleInstalledVersion); | ||
741 | |||
742 | if (nCompareResult < 0) | ||
743 | { | ||
744 | pPackage->compatiblePackage.fPlannable = TRUE; | ||
745 | |||
746 | LogId(REPORT_STANDARD, MSG_DETECTED_COMPATIBLE_PACKAGE_FROM_PROVIDER, pPackage->sczId, pPackage->compatiblePackage.compatibleEntry.sczProviderKey, wzCompatibleProductCode, wzCompatibleInstalledVersion, pPackage->Msi.sczProductCode); | ||
747 | |||
748 | hr = UserExperienceOnDetectCompatibleMsiPackage(pUserExperience, pPackage->sczId, wzCompatibleProductCode, pPackage->compatiblePackage.Msi.pVersion); | ||
749 | ExitOnRootFailure(hr, "BA aborted detect compatible MSI package."); | ||
750 | } | ||
751 | } | ||
752 | } | ||
753 | |||
711 | LExit: | 754 | LExit: |
712 | ReleaseStr(sczInstalledLanguage); | 755 | ReleaseStr(sczInstalledLanguage); |
713 | ReleaseStr(sczInstalledVersion); | 756 | ReleaseStr(sczInstalledVersion); |
@@ -716,8 +759,49 @@ LExit: | |||
716 | return hr; | 759 | return hr; |
717 | } | 760 | } |
718 | 761 | ||
762 | extern "C" HRESULT MsiEngineDetectCompatiblePackage( | ||
763 | __in BURN_PACKAGE* pPackage | ||
764 | ) | ||
765 | { | ||
766 | HRESULT hr = S_OK; | ||
767 | LPWSTR sczVersion = NULL; | ||
768 | LPWSTR sczCacheId = NULL; | ||
769 | LPCWSTR wzCompatibleProductCode = pPackage->compatiblePackage.compatibleEntry.sczId; | ||
770 | |||
771 | if (!pPackage->compatiblePackage.fDetected) | ||
772 | { | ||
773 | ExitFunction(); | ||
774 | } | ||
775 | |||
776 | hr = WiuGetProductInfoEx(wzCompatibleProductCode, NULL, pPackage->fPerMachine ? MSIINSTALLCONTEXT_MACHINE : MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONSTRING, &sczVersion); | ||
777 | if (HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) == hr || HRESULT_FROM_WIN32(ERROR_UNKNOWN_PROPERTY) == hr) | ||
778 | { | ||
779 | ExitFunction1(hr = S_OK); | ||
780 | } | ||
781 | ExitOnFailure(hr, "Failed to get product information for compatible ProductCode: %ls", wzCompatibleProductCode); | ||
782 | |||
783 | // Assume the package used the default cache ID generation from the binder. | ||
784 | hr = StrAllocFormatted(&sczCacheId, L"%lsv%ls", wzCompatibleProductCode, sczVersion); | ||
785 | ExitOnFailure(hr, "Failed to format cache ID for compatible package."); | ||
786 | |||
787 | pPackage->compatiblePackage.sczCacheId = sczCacheId; | ||
788 | sczCacheId = NULL; | ||
789 | |||
790 | pPackage->compatiblePackage.Msi.sczVersion = sczVersion; | ||
791 | sczVersion = NULL; | ||
792 | |||
793 | pPackage->compatiblePackage.type = BURN_PACKAGE_TYPE_MSI; | ||
794 | |||
795 | LExit: | ||
796 | ReleaseStr(sczVersion); | ||
797 | ReleaseStr(sczCacheId); | ||
798 | |||
799 | return hr; | ||
800 | } | ||
801 | |||
719 | extern "C" HRESULT MsiEnginePlanInitializePackage( | 802 | extern "C" HRESULT MsiEnginePlanInitializePackage( |
720 | __in BURN_PACKAGE* pPackage, | 803 | __in BURN_PACKAGE* pPackage, |
804 | __in BOOTSTRAPPER_ACTION overallAction, | ||
721 | __in BURN_VARIABLES* pVariables, | 805 | __in BURN_VARIABLES* pVariables, |
722 | __in BURN_USER_EXPERIENCE* pUserExperience | 806 | __in BURN_USER_EXPERIENCE* pUserExperience |
723 | ) | 807 | ) |
@@ -747,6 +831,18 @@ extern "C" HRESULT MsiEnginePlanInitializePackage( | |||
747 | } | 831 | } |
748 | } | 832 | } |
749 | 833 | ||
834 | if (pPackage->compatiblePackage.fPlannable) | ||
835 | { | ||
836 | Assert(BURN_PACKAGE_TYPE_MSI == pPackage->compatiblePackage.type); | ||
837 | |||
838 | pPackage->compatiblePackage.fDefaultRequested = BOOTSTRAPPER_ACTION_UNINSTALL == overallAction; | ||
839 | pPackage->compatiblePackage.fRequested = pPackage->compatiblePackage.fDefaultRequested; | ||
840 | |||
841 | hr = UserExperienceOnPlanCompatibleMsiPackageBegin(pUserExperience, pPackage->sczId, pPackage->compatiblePackage.compatibleEntry.sczId, pPackage->compatiblePackage.Msi.pVersion, &pPackage->compatiblePackage.fRequested); | ||
842 | UserExperienceOnPlanCompatibleMsiPackageComplete(pUserExperience, pPackage->sczId, pPackage->compatiblePackage.compatibleEntry.sczId, hr, pPackage->compatiblePackage.fRequested); | ||
843 | ExitOnRootFailure(hr, "BA aborted plan compatible MSI package begin."); | ||
844 | } | ||
845 | |||
750 | LExit: | 846 | LExit: |
751 | return hr; | 847 | return hr; |
752 | } | 848 | } |
@@ -989,6 +1085,17 @@ extern "C" HRESULT MsiEnginePlanAddPackage( | |||
989 | LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, &pAction->msiPackage.sczLogPath); // ignore errors. | 1085 | LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, &pAction->msiPackage.sczLogPath); // ignore errors. |
990 | pAction->msiPackage.dwLoggingAttributes = pLog->dwAttributes; | 1086 | pAction->msiPackage.dwLoggingAttributes = pLog->dwAttributes; |
991 | } | 1087 | } |
1088 | else if (pPackage->compatiblePackage.fRemove) | ||
1089 | { | ||
1090 | hr = PlanAppendExecuteAction(pPlan, &pAction); | ||
1091 | ExitOnFailure(hr, "Failed to append execute action."); | ||
1092 | |||
1093 | pAction->type = BURN_EXECUTE_ACTION_TYPE_UNINSTALL_MSI_COMPATIBLE_PACKAGE; | ||
1094 | pAction->uninstallMsiCompatiblePackage.pParentPackage = pPackage; | ||
1095 | pAction->uninstallMsiCompatiblePackage.dwLoggingAttributes = pLog->dwAttributes; | ||
1096 | |||
1097 | LoggingSetCompatiblePackageVariable(pPackage, pLog, pVariables, &pAction->uninstallMsiCompatiblePackage.sczLogPath); // ignore errors. | ||
1098 | } | ||
992 | 1099 | ||
993 | LExit: | 1100 | LExit: |
994 | ReleaseMem(rgFeatureActions); | 1101 | ReleaseMem(rgFeatureActions); |
@@ -1246,6 +1353,80 @@ LExit: | |||
1246 | return hr; | 1353 | return hr; |
1247 | } | 1354 | } |
1248 | 1355 | ||
1356 | extern "C" HRESULT MsiEngineUninstallCompatiblePackage( | ||
1357 | __in_opt HWND hwndParent, | ||
1358 | __in BURN_EXECUTE_ACTION* pExecuteAction, | ||
1359 | __in BURN_CACHE* /*pCache*/, | ||
1360 | __in BURN_VARIABLES* /*pVariables*/, | ||
1361 | __in BOOL fRollback, | ||
1362 | __in PFN_MSIEXECUTEMESSAGEHANDLER pfnMessageHandler, | ||
1363 | __in LPVOID pvContext, | ||
1364 | __out BOOTSTRAPPER_APPLY_RESTART* pRestart | ||
1365 | ) | ||
1366 | { | ||
1367 | HRESULT hr = S_OK; | ||
1368 | WIU_MSI_EXECUTE_CONTEXT context = { }; | ||
1369 | WIU_RESTART restart = WIU_RESTART_NONE; | ||
1370 | LPWSTR sczProperties = NULL; | ||
1371 | BOOTSTRAPPER_ACTION_STATE action = BOOTSTRAPPER_ACTION_STATE_UNINSTALL; | ||
1372 | BURN_MSI_PROPERTY burnMsiProperty = BURN_MSI_PROPERTY_NONE; | ||
1373 | BOOTSTRAPPER_MSI_FILE_VERSIONING fileVersioning = BOOTSTRAPPER_MSI_FILE_VERSIONING_MISSING_OR_OLDER; | ||
1374 | BURN_PACKAGE* pParentPackage = pExecuteAction->uninstallMsiCompatiblePackage.pParentPackage; | ||
1375 | BURN_COMPATIBLE_PROVIDER_ENTRY* pCompatibleEntry = &pExecuteAction->uninstallMsiCompatiblePackage.pParentPackage->compatiblePackage.compatibleEntry; | ||
1376 | |||
1377 | // Default to "verbose" logging and set extra debug mode only if explicitly required. | ||
1378 | DWORD dwLogMode = WIU_LOG_DEFAULT | INSTALLLOGMODE_VERBOSE; | ||
1379 | |||
1380 | if (pExecuteAction->uninstallMsiCompatiblePackage.dwLoggingAttributes & BURN_LOGGING_ATTRIBUTE_EXTRADEBUG) | ||
1381 | { | ||
1382 | dwLogMode |= INSTALLLOGMODE_EXTRADEBUG; | ||
1383 | } | ||
1384 | |||
1385 | hr = WiuInitializeExternalUI(pfnMessageHandler, INSTALLUILEVEL_NONE, hwndParent, pvContext, fRollback, &context); | ||
1386 | ExitOnFailure(hr, "Failed to initialize external UI handler."); | ||
1387 | |||
1388 | if (pExecuteAction->uninstallMsiCompatiblePackage.sczLogPath && *pExecuteAction->uninstallMsiCompatiblePackage.sczLogPath) | ||
1389 | { | ||
1390 | hr = WiuEnableLog(dwLogMode, pExecuteAction->uninstallMsiCompatiblePackage.sczLogPath, INSTALLLOGATTRIBUTES_APPEND); | ||
1391 | ExitOnFailure(hr, "Failed to enable logging for compatible package: %ls to: %ls", pCompatibleEntry->sczId, pExecuteAction->uninstallMsiCompatiblePackage.sczLogPath); | ||
1392 | } | ||
1393 | |||
1394 | hr = MsiEngineConcatBurnProperties(action, burnMsiProperty, fileVersioning, TRUE, FALSE, &sczProperties); | ||
1395 | ExitOnFailure(hr, "Failed to add action property to argument string."); | ||
1396 | |||
1397 | LogId(REPORT_STANDARD, MSG_APPLYING_ORPHAN_COMPATIBLE_PACKAGE, LoggingRollbackOrExecute(fRollback), pCompatibleEntry->sczId, pParentPackage->sczId, LoggingActionStateToString(action), sczProperties ? sczProperties : L""); | ||
1398 | |||
1399 | hr = WiuConfigureProductEx(pCompatibleEntry->sczId, INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, sczProperties, &restart); | ||
1400 | if (HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) == hr) | ||
1401 | { | ||
1402 | LogId(REPORT_STANDARD, MSG_ATTEMPTED_UNINSTALL_ABSENT_PACKAGE, pCompatibleEntry->sczId); | ||
1403 | hr = S_OK; | ||
1404 | } | ||
1405 | ExitOnFailure(hr, "Failed to uninstall compatible MSI package."); | ||
1406 | |||
1407 | LExit: | ||
1408 | WiuUninitializeExternalUI(&context); | ||
1409 | |||
1410 | StrSecureZeroFreeString(sczProperties); | ||
1411 | |||
1412 | switch (restart) | ||
1413 | { | ||
1414 | case WIU_RESTART_NONE: | ||
1415 | *pRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; | ||
1416 | break; | ||
1417 | |||
1418 | case WIU_RESTART_REQUIRED: | ||
1419 | *pRestart = BOOTSTRAPPER_APPLY_RESTART_REQUIRED; | ||
1420 | break; | ||
1421 | |||
1422 | case WIU_RESTART_INITIATED: | ||
1423 | *pRestart = BOOTSTRAPPER_APPLY_RESTART_INITIATED; | ||
1424 | break; | ||
1425 | } | ||
1426 | |||
1427 | return hr; | ||
1428 | } | ||
1429 | |||
1249 | extern "C" HRESULT MsiEngineConcatBurnProperties( | 1430 | extern "C" HRESULT MsiEngineConcatBurnProperties( |
1250 | __in BOOTSTRAPPER_ACTION_STATE action, | 1431 | __in BOOTSTRAPPER_ACTION_STATE action, |
1251 | __in BURN_MSI_PROPERTY actionMsiProperty, | 1432 | __in BURN_MSI_PROPERTY actionMsiProperty, |