aboutsummaryrefslogtreecommitdiff
path: root/src/burn/engine/msiengine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/burn/engine/msiengine.cpp')
-rw-r--r--src/burn/engine/msiengine.cpp181
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
711LExit: 754LExit:
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
762extern "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
795LExit:
796 ReleaseStr(sczVersion);
797 ReleaseStr(sczCacheId);
798
799 return hr;
800}
801
719extern "C" HRESULT MsiEnginePlanInitializePackage( 802extern "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
750LExit: 846LExit:
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
993LExit: 1100LExit:
994 ReleaseMem(rgFeatureActions); 1101 ReleaseMem(rgFeatureActions);
@@ -1246,6 +1353,80 @@ LExit:
1246 return hr; 1353 return hr;
1247} 1354}
1248 1355
1356extern "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
1407LExit:
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
1249extern "C" HRESULT MsiEngineConcatBurnProperties( 1430extern "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,