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' />" +