@joebigelow / wix / commits / 1f422997

Detect MinorUpgrade MsiPackages independently of the base product.

Fixes #6535

Sean Hall committed Feb 11, 2022 at 13:05 UTC 1f422997c701625a53d08648521de709e280f4af
6 files changed +46 -52
src/burn/engine/detect.cpp
+2
@@ -64,6 +64,8 @@ extern "C" void DetectReset(
64
65 if (BURN_PACKAGE_TYPE_MSI == pPackage->type)
66 {
67 + pPackage->Msi.operation = BOOTSTRAPPER_RELATED_OPERATION_NONE;
68 +
69 for (DWORD iFeature = 0; iFeature < pPackage->Msi.cFeatures; ++iFeature)
70 {
71 BURN_MSIFEATURE* pFeature = pPackage->Msi.rgFeatures + iFeature;
src/burn/engine/msiengine.cpp
+25 -32
@@ -443,7 +443,6 @@ extern "C" HRESULT MsiEngineDetectPackage(
443 LPWSTR sczInstalledVersion = NULL;
444 LPWSTR sczInstalledLanguage = NULL;
445 INSTALLSTATE installState = INSTALLSTATE_UNKNOWN;
446 - BOOTSTRAPPER_RELATED_OPERATION operation = BOOTSTRAPPER_RELATED_OPERATION_NONE;
446 BOOTSTRAPPER_RELATED_OPERATION relatedMsiOperation = BOOTSTRAPPER_RELATED_OPERATION_NONE;
447 WCHAR wzProductCode[MAX_GUID_CHARS + 1] = { };
448 VERUTIL_VERSION* pVersion = NULL;
@@ -455,39 +454,39 @@ extern "C" HRESULT MsiEngineDetectPackage(
454 hr = WiuGetProductInfoEx(pPackage->Msi.sczProductCode, NULL, pPackage->fPerMachine ? MSIINSTALLCONTEXT_MACHINE : MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONSTRING, &sczInstalledVersion);
455 if (SUCCEEDED(hr))
456 {
458 - hr = VerParseVersion(sczInstalledVersion, 0, FALSE, &pPackage->Msi.pInstalledVersion);
457 + hr = VerParseVersion(sczInstalledVersion, 0, FALSE, &pVersion);
458 ExitOnFailure(hr, "Failed to parse installed version: '%ls' for ProductCode: %ls", sczInstalledVersion, pPackage->Msi.sczProductCode);
459
461 - if (pPackage->Msi.pInstalledVersion->fInvalid)
460 + if (pVersion->fInvalid)
461 {
462 LogId(REPORT_WARNING, MSG_DETECTED_MSI_PACKAGE_INVALID_VERSION, pPackage->Msi.sczProductCode, sczInstalledVersion);
463 }
464
465 // compare versions
467 - hr = VerCompareParsedVersions(pPackage->Msi.pVersion, pPackage->Msi.pInstalledVersion, &nCompareResult);
468 - ExitOnFailure(hr, "Failed to compare version '%ls' to installed version: '%ls'", pPackage->Msi.pVersion->sczVersion, pPackage->Msi.pInstalledVersion->sczVersion);
466 + hr = VerCompareParsedVersions(pPackage->Msi.pVersion, pVersion, &nCompareResult);
467 + ExitOnFailure(hr, "Failed to compare version '%ls' to installed version: '%ls'", pPackage->Msi.pVersion->sczVersion, pVersion->sczVersion);
468
469 if (nCompareResult < 0)
470 {
472 - operation = BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE;
471 + pPackage->Msi.operation = BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE;
472 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED;
473 }
474 + else if (nCompareResult > 0)
475 + {
476 + pPackage->Msi.operation = BOOTSTRAPPER_RELATED_OPERATION_MINOR_UPDATE;
477 + pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT;
478 + }
479 else
480 {
477 - if (nCompareResult > 0)
478 - {
479 - operation = BOOTSTRAPPER_RELATED_OPERATION_MINOR_UPDATE;
480 - }
481 -
481 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT;
482 }
483
484 // Report related MSI package to BA.
486 - if (BOOTSTRAPPER_RELATED_OPERATION_NONE != operation)
485 + if (BOOTSTRAPPER_RELATED_OPERATION_NONE != pPackage->Msi.operation)
486 {
488 - LogId(REPORT_STANDARD, MSG_DETECTED_RELATED_PACKAGE, pPackage->Msi.sczProductCode, LoggingPerMachineToString(pPackage->fPerMachine), pPackage->Msi.pInstalledVersion->sczVersion, pPackage->Msi.dwLanguage, LoggingRelatedOperationToString(operation));
487 + LogId(REPORT_STANDARD, MSG_DETECTED_RELATED_PACKAGE, pPackage->Msi.sczProductCode, LoggingPerMachineToString(pPackage->fPerMachine), pVersion->sczVersion, pPackage->Msi.dwLanguage, LoggingRelatedOperationToString(pPackage->Msi.operation));
488
490 - hr = UserExperienceOnDetectRelatedMsiPackage(pUserExperience, pPackage->sczId, pPackage->Msi.sczUpgradeCode, pPackage->Msi.sczProductCode, pPackage->fPerMachine, pPackage->Msi.pInstalledVersion, operation);
489 + hr = UserExperienceOnDetectRelatedMsiPackage(pUserExperience, pPackage->sczId, pPackage->Msi.sczUpgradeCode, pPackage->Msi.sczProductCode, pPackage->fPerMachine, pVersion, pPackage->Msi.operation);
490 ExitOnRootFailure(hr, "BA aborted detect related MSI package.");
491 }
492 }
@@ -623,7 +622,7 @@ extern "C" HRESULT MsiEngineDetectPackage(
622 {
623 // If we've already detected a major upgrade that trumps any guesses that the detect is a downgrade
624 // or even something else.
626 - if (BOOTSTRAPPER_RELATED_OPERATION_MAJOR_UPGRADE == operation)
625 + if (BOOTSTRAPPER_RELATED_OPERATION_MAJOR_UPGRADE == pPackage->Msi.operation)
626 {
627 relatedMsiOperation = BOOTSTRAPPER_RELATED_OPERATION_NONE;
628 }
@@ -632,7 +631,7 @@ extern "C" HRESULT MsiEngineDetectPackage(
631 pPackage->Msi.sczUpgradeCode && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pPackage->Msi.sczUpgradeCode, -1, pRelatedMsi->sczUpgradeCode, -1))
632 {
633 relatedMsiOperation = BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE;
635 - operation = BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE;
634 + pPackage->Msi.operation = BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE;
635 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE;
636 }
637 else // we're already on the machine so the detect-only *must* be for detection purposes only.
@@ -643,7 +642,7 @@ extern "C" HRESULT MsiEngineDetectPackage(
642 else
643 {
644 relatedMsiOperation = BOOTSTRAPPER_RELATED_OPERATION_MAJOR_UPGRADE;
646 - operation = BOOTSTRAPPER_RELATED_OPERATION_MAJOR_UPGRADE;
645 + pPackage->Msi.operation = BOOTSTRAPPER_RELATED_OPERATION_MAJOR_UPGRADE;
646 }
647
648 LogId(REPORT_STANDARD, MSG_DETECTED_RELATED_PACKAGE, wzProductCode, LoggingPerMachineToString(fPerMachine), pVersion->sczVersion, uLcid, LoggingRelatedOperationToString(relatedMsiOperation));
@@ -858,9 +857,6 @@ extern "C" HRESULT MsiEnginePlanCalculatePackage(
857 Trace(REPORT_STANDARD, "Planning MSI package 0x%p", pPackage);
858
859 HRESULT hr = S_OK;
861 - VERUTIL_VERSION* pVersion = pPackage->Msi.pVersion;
862 - VERUTIL_VERSION* pInstalledVersion = pPackage->Msi.pInstalledVersion;
863 - int nCompareResult = 0;
860 BOOTSTRAPPER_ACTION_STATE execute = BOOTSTRAPPER_ACTION_STATE_NONE;
861 BOOTSTRAPPER_ACTION_STATE rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
862 BOOL fFeatureActionDelta = FALSE;
@@ -892,17 +888,7 @@ extern "C" HRESULT MsiEnginePlanCalculatePackage(
888 case BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED:
889 if (BOOTSTRAPPER_REQUEST_STATE_PRESENT == pPackage->requested || BOOTSTRAPPER_REQUEST_STATE_REPAIR == pPackage->requested)
890 {
895 - hr = VerCompareParsedVersions(pVersion, pInstalledVersion, &nCompareResult);
896 - ExitOnFailure(hr, "Failed to compare '%ls' to '%ls' for planning.", pVersion->sczVersion, pInstalledVersion->sczVersion);
897 -
898 - // Take a look at the version and determine if this is a potential
899 - // minor upgrade (same ProductCode newer ProductVersion), otherwise,
900 - // there is a newer version so no work necessary.
901 - if (nCompareResult > 0)
902 - {
903 - execute = BOOTSTRAPPER_ACTION_STATE_MINOR_UPGRADE;
904 - }
905 - else if (BOOTSTRAPPER_REQUEST_STATE_REPAIR == pPackage->requested)
891 + if (BOOTSTRAPPER_REQUEST_STATE_REPAIR == pPackage->requested)
892 {
893 execute = BOOTSTRAPPER_ACTION_STATE_REPAIR;
894 }
@@ -937,7 +923,14 @@ extern "C" HRESULT MsiEnginePlanCalculatePackage(
923 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
924 case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT: __fallthrough;
925 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
940 - execute = BOOTSTRAPPER_ACTION_STATE_INSTALL;
926 + if (BOOTSTRAPPER_RELATED_OPERATION_MINOR_UPDATE == pPackage->Msi.operation)
927 + {
928 + execute = BOOTSTRAPPER_ACTION_STATE_MINOR_UPGRADE;
929 + }
930 + else
931 + {
932 + execute = BOOTSTRAPPER_ACTION_STATE_INSTALL;
933 + }
934 break;
935
936 case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT:
src/burn/engine/package.h
+2 -1
@@ -341,9 +341,10 @@ typedef struct _BURN_PACKAGE
341 LPWSTR sczProductCode;
342 DWORD dwLanguage;
343 VERUTIL_VERSION* pVersion;
344 - VERUTIL_VERSION* pInstalledVersion;
344 LPWSTR sczUpgradeCode;
345
346 + BOOTSTRAPPER_RELATED_OPERATION operation;
347 +
348 BURN_MSIPROPERTY* rgProperties;
349 DWORD cProperties;
350
src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs
+14 -16
@@ -730,22 +730,21 @@ namespace WixToolsetTest.BurnE2E
730 bundleNv101.VerifyUnregisteredAndRemovedFromPackageCache();
731 bundleNv1.VerifyRegisteredAndInPackageCache();
732
733 - // The expected values will change after implementing https://github.com/wixtoolset/issues/issues/6535 and https://github.com/wixtoolset/issues/issues/3421
733 packageAv1.VerifyInstalled(true);
734 packageC.VerifyInstalled(false);
736 - packageFv1.VerifyInstalledWithVersion(false);
737 - packageFv101.VerifyInstalledWithVersion(true);
738 - packageGv1.VerifyInstalledWithVersion(false);
739 - packageGv101.VerifyInstalledWithVersion(true);
735 + packageFv1.VerifyInstalledWithVersion(true);
736 + packageFv101.VerifyInstalledWithVersion(false);
737 + packageGv1.VerifyInstalledWithVersion(true);
738 + packageGv101.VerifyInstalledWithVersion(false);
739
740 bundleM.Uninstall();
741 bundleM.VerifyUnregisteredAndRemovedFromPackageCache();
742
743 packageAv1.VerifyInstalled(false);
745 - packageFv1.VerifyInstalledWithVersion(false);
746 - packageFv101.VerifyInstalledWithVersion(true);
747 - packageGv1.VerifyInstalledWithVersion(false);
748 - packageGv101.VerifyInstalledWithVersion(true);
744 + packageFv1.VerifyInstalledWithVersion(true);
745 + packageFv101.VerifyInstalledWithVersion(false);
746 + packageGv1.VerifyInstalledWithVersion(true);
747 + packageGv101.VerifyInstalledWithVersion(false);
748
749 bundleNv1.Uninstall();
750 bundleNv1.VerifyUnregisteredAndRemovedFromPackageCache();
@@ -804,20 +803,19 @@ namespace WixToolsetTest.BurnE2E
803 bundleNv101.VerifyUnregisteredAndRemovedFromPackageCache();
804 bundleNv1.VerifyRegisteredAndInPackageCache();
805
807 - // The expected values will change after implementing https://github.com/wixtoolset/issues/issues/6535 and https://github.com/wixtoolset/issues/issues/3421
806 packageAv1.VerifyInstalled(true);
807 packageC.VerifyInstalled(false);
810 - packageFv1.VerifyInstalledWithVersion(false);
811 - packageFv101.VerifyInstalledWithVersion(true);
812 - packageGv1.VerifyInstalledWithVersion(false);
813 - packageGv101.VerifyInstalledWithVersion(true);
808 + packageFv1.VerifyInstalledWithVersion(true);
809 + packageFv101.VerifyInstalledWithVersion(false);
810 + packageGv1.VerifyInstalledWithVersion(true);
811 + packageGv101.VerifyInstalledWithVersion(false);
812
813 bundleNv1.Uninstall();
814 bundleNv1.VerifyUnregisteredAndRemovedFromPackageCache();
815
816 packageAv1.VerifyInstalled(true);
819 - packageFv1.VerifyInstalledWithVersion(false);
820 - packageFv101.VerifyInstalledWithVersion(true);
817 + packageFv1.VerifyInstalledWithVersion(true);
818 + packageFv101.VerifyInstalledWithVersion(false);
819 packageGv1.VerifyInstalledWithVersion(false);
820 packageGv101.VerifyInstalledWithVersion(false);
821
src/wix/WixToolset.Core.Burn/Bind/ProcessDependencyProvidersCommand.cs
+1 -1
@@ -107,7 +107,7 @@ namespace WixToolset.Core.Burn.Bind
107 this.Section.AddSymbol(new WixDependencyProviderSymbol(facade.PackageSymbol.SourceLineNumbers, facade.PackageSymbol.Id)
108 {
109 ParentRef = facade.PackageId,
110 - ProviderKey = key,
110 + ProviderKey = $"{key}_v{facade.PackageSymbol.Version}",
111 Version = facade.PackageSymbol.Version,
112 DisplayName = facade.PackageSymbol.DisplayName
113 });
src/wix/test/WixToolsetTest.CoreIntegration/ContainerFixture.cs
+2 -2
@@ -150,7 +150,7 @@ namespace WixToolsetTest.CoreIntegration
150 {
151 "<MsiPackage Id='FirstX86.msi' Cache='keep' CacheId='*' InstallSize='*' Size='*' PerMachine='yes' Permanent='no' Vital='yes' RollbackBoundaryForward='WixDefaultBoundary' LogPathVariable='WixBundleLog_FirstX86.msi' RollbackLogPathVariable='WixBundleRollbackLog_FirstX86.msi' ProductCode='*' Language='1033' Version='1.0.0.0' UpgradeCode='{12E4699F-E774-4D05-8A01-5BDD41BBA127}'>" +
152 "<MsiProperty Id='ARPSYSTEMCOMPONENT' Value='1' />" +
153 - $"<Provides Key='{GetProductCodeFromMsiPdb(pdbPaths[0])}' Version='1.0.0.0' DisplayName='MsiPackage' />" +
153 + $"<Provides Key='{GetProductCodeFromMsiPdb(pdbPaths[0])}_v1.0.0.0' Version='1.0.0.0' DisplayName='MsiPackage' />" +
154 "<RelatedPackage Id='{12E4699F-E774-4D05-8A01-5BDD41BBA127}' MaxVersion='1.0.0.0' MaxInclusive='no' OnlyDetect='no' LangInclusive='yes'><Language Id='1033' /></RelatedPackage>" +
155 "<RelatedPackage Id='{12E4699F-E774-4D05-8A01-5BDD41BBA127}' MinVersion='1.0.0.0' MinInclusive='no' OnlyDetect='yes' LangInclusive='yes'><Language Id='1033' /></RelatedPackage>" +
156 "<PayloadRef Id='FirstX86.msi' />" +
@@ -158,7 +158,7 @@ namespace WixToolsetTest.CoreIntegration
158 "</MsiPackage>",
159 "<MsiPackage Id='FirstX64.msi' Cache='keep' CacheId='*' InstallSize='*' Size='*' PerMachine='yes' Permanent='no' Vital='yes' RollbackBoundaryBackward='WixDefaultBoundary' LogPathVariable='WixBundleLog_FirstX64.msi' RollbackLogPathVariable='WixBundleRollbackLog_FirstX64.msi' ProductCode='*' Language='1033' Version='1.0.0.0' UpgradeCode='{12E4699F-E774-4D05-8A01-5BDD41BBA127}'>" +
160 "<MsiProperty Id='ARPSYSTEMCOMPONENT' Value='1' />" +
161 - $"<Provides Key='{GetProductCodeFromMsiPdb(pdbPaths[1])}' Version='1.0.0.0' DisplayName='MsiPackage' />" +
161 + $"<Provides Key='{GetProductCodeFromMsiPdb(pdbPaths[1])}_v1.0.0.0' Version='1.0.0.0' DisplayName='MsiPackage' />" +
162 "<RelatedPackage Id='{12E4699F-E774-4D05-8A01-5BDD41BBA127}' MaxVersion='1.0.0.0' MaxInclusive='no' OnlyDetect='no' LangInclusive='yes'><Language Id='1033' /></RelatedPackage>" +
163 "<RelatedPackage Id='{12E4699F-E774-4D05-8A01-5BDD41BBA127}' MinVersion='1.0.0.0' MinInclusive='no' OnlyDetect='yes' LangInclusive='yes'><Language Id='1033' /></RelatedPackage>" +
164 "<PayloadRef Id='FirstX64.msi' />" +