From a5fdd8816a937e890627f79377174cf81853d3a8 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Thu, 30 Dec 2021 15:11:35 -0600 Subject: [PATCH 1/3] Revert .wixburn version since the format didn't change. --- src/burn/engine/inc/engine.h | 8 ++++++++ src/burn/engine/precomp.h | 1 + src/burn/engine/section.cpp | 8 -------- src/burn/stub/StubSection.cpp | 9 ++++----- src/wix/WixToolset.Core.Burn/Bundles/BurnCommon.cs | 5 ++--- 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/burn/engine/inc/engine.h b/src/burn/engine/inc/engine.h index 808bb91ad..b80b42134 100644 --- a/src/burn/engine/inc/engine.h +++ b/src/burn/engine/inc/engine.h @@ -2,6 +2,14 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. +// constants + +// If these defaults ever change, be sure to update constants in wix\WixToolset.Core.Burn\Bundles\BurnCommon.cs as well. +#define BURN_SECTION_NAME ".wixburn" +#define BURN_SECTION_MAGIC 0x00f14300 +#define BURN_SECTION_VERSION 0x00000002 + + #if defined(__cplusplus) extern "C" { #endif diff --git a/src/burn/engine/precomp.h b/src/burn/engine/precomp.h index f76bb1984..3b4d989b6 100644 --- a/src/burn/engine/precomp.h +++ b/src/burn/engine/precomp.h @@ -101,3 +101,4 @@ #include "EngineForApplication.h" #include "EngineForExtension.h" #include "engine.messages.h" +#include "engine.h" diff --git a/src/burn/engine/section.cpp b/src/burn/engine/section.cpp index a9c7927e5..989bfb175 100644 --- a/src/burn/engine/section.cpp +++ b/src/burn/engine/section.cpp @@ -3,14 +3,6 @@ #include "precomp.h" -// constants - -// If these defaults ever change, be sure to update constants in burn\stub\StubSection.cpp as well. -#define BURN_SECTION_NAME ".wixburn" -#define BURN_SECTION_MAGIC 0x00f14300 -#define BURN_SECTION_VERSION 0x00000003 -#define MANIFEST_CABINET_TOKEN L"0" - // structs typedef struct _BURN_SECTION_HEADER { diff --git a/src/burn/stub/StubSection.cpp b/src/burn/stub/StubSection.cpp index 2191a1382..62d3e91ed 100644 --- a/src/burn/stub/StubSection.cpp +++ b/src/burn/stub/StubSection.cpp @@ -2,12 +2,11 @@ #include "precomp.h" -#pragma section(".wixburn",read) +#pragma section(BURN_SECTION_NAME,read) -// If these defaults ever change, be sure to update constants in burn\engine\section.cpp as well. -#pragma data_seg(push, ".wixburn") -static DWORD dwMagic = 0x00f14300; -static DWORD dwVersion = 0x00000003; +#pragma data_seg(push, BURN_SECTION_NAME) +static DWORD dwMagic = BURN_SECTION_MAGIC; +static DWORD dwVersion = BURN_SECTION_VERSION; static GUID guidBundleId = { }; diff --git a/src/wix/WixToolset.Core.Burn/Bundles/BurnCommon.cs b/src/wix/WixToolset.Core.Burn/Bundles/BurnCommon.cs index 27fad5b36..733f7c009 100644 --- a/src/wix/WixToolset.Core.Burn/Bundles/BurnCommon.cs +++ b/src/wix/WixToolset.Core.Burn/Bundles/BurnCommon.cs @@ -83,8 +83,7 @@ internal abstract class BurnCommon : IDisposable protected const UInt32 BURN_SECTION_MIN_SIZE = BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE0; protected const UInt32 BURN_SECTION_MAGIC = 0x00f14300; - protected const UInt32 BURN_SECTION_VERSION = 0x00000003; - protected const UInt32 BURN_SECTION_COMPATIBLE_VERSION = 0x00000002; + protected const UInt32 BURN_SECTION_VERSION = 0x00000002; protected string fileExe; protected UInt32 peOffset = UInt32.MaxValue; @@ -191,7 +190,7 @@ protected bool Initialize(BinaryReader reader) } this.Version = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_VERSION); - if ((BURN_SECTION_VERSION != this.Version) && (BURN_SECTION_COMPATIBLE_VERSION != this.Version)) + if (BURN_SECTION_VERSION != this.Version) { this.Messaging.Write(BurnBackendErrors.IncompatibleWixBurnSection(this.fileExe, this.Version)); return false; From e3f3a2d120af8036558a5db7f0dad6f0a9e74a60 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Thu, 30 Dec 2021 15:12:26 -0600 Subject: [PATCH 2/3] Add BURN_PROTOCOL_VERSION in registration to avoid version checks. Also, old versions of Burn should ignore ancestors if they doesn't support them. --- src/burn/engine/inc/engine.h | 2 ++ src/burn/engine/pipe.cpp | 1 + src/burn/engine/pseudobundle.cpp | 13 +++++-------- src/burn/engine/pseudobundle.h | 2 +- src/burn/engine/registration.cpp | 3 +++ src/burn/engine/registration.h | 1 + src/burn/engine/relatedbundle.cpp | 25 +++++++++++++++++++------ src/burn/test/BurnUnitTest/PlanTest.cpp | 2 +- 8 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/burn/engine/inc/engine.h b/src/burn/engine/inc/engine.h index b80b42134..9b29dd84d 100644 --- a/src/burn/engine/inc/engine.h +++ b/src/burn/engine/inc/engine.h @@ -9,6 +9,8 @@ #define BURN_SECTION_MAGIC 0x00f14300 #define BURN_SECTION_VERSION 0x00000002 +// This needs to be incremented whenever a breaking change is made to the Burn protocol. +#define BURN_PROTOCOL_VERSION 1 #if defined(__cplusplus) extern "C" { diff --git a/src/burn/engine/pipe.cpp b/src/burn/engine/pipe.cpp index 48be8785a..80275b521 100644 --- a/src/burn/engine/pipe.cpp +++ b/src/burn/engine/pipe.cpp @@ -710,6 +710,7 @@ static HRESULT ChildPipeConnected( } // All is well, tell the parent process. + // TODO: consider sending BURN_PROTOCOL_VERSION as a way to verify compatibility. hr = FileWriteHandle(hPipe, reinterpret_cast(&dwAck), sizeof(dwAck)); ExitOnFailure(hr, "Failed to inform parent process that child is running."); diff --git a/src/burn/engine/pseudobundle.cpp b/src/burn/engine/pseudobundle.cpp index 91c6c14ff..14dd2b77e 100644 --- a/src/burn/engine/pseudobundle.cpp +++ b/src/burn/engine/pseudobundle.cpp @@ -4,8 +4,8 @@ extern "C" HRESULT PseudoBundleInitialize( - __in DWORD64 qwEngineVersion, __in BURN_PACKAGE* pPackage, + __in BOOL fSupportsBurnProtocol, __in BOOL fPerMachine, __in_z LPCWSTR wzId, __in BOOTSTRAPPER_RELATION_TYPE relationType, @@ -84,6 +84,9 @@ extern "C" HRESULT PseudoBundleInitialize( pPackage->qwSize = qwSize; pPackage->fVital = fVital; + pPackage->Exe.protocol = fSupportsBurnProtocol ? BURN_EXE_PROTOCOL_TYPE_BURN : BURN_EXE_PROTOCOL_TYPE_NONE; + pPackage->Exe.fSupportsAncestors = TRUE; + hr = StrAllocString(&pPackage->sczId, wzId, 0); ExitOnFailure(hr, "Failed to copy key for pseudo bundle."); @@ -131,12 +134,6 @@ extern "C" HRESULT PseudoBundleInitialize( pPackage->fUninstallable = TRUE; } - // Only support progress from engines that are compatible (aka: version greater than or equal to last protocol breaking change *and* versions that are older or the same as this engine). - pPackage->Exe.protocol = (FILEMAKEVERSION(3, 6, 2221, 0) <= qwEngineVersion && qwEngineVersion <= FILEMAKEVERSION(rmj, rmm, rup, rpr)) ? BURN_EXE_PROTOCOL_TYPE_BURN : BURN_EXE_PROTOCOL_TYPE_NONE; - - // All versions of Burn past v3.9 RTM support suppressing ancestors. - pPackage->Exe.fSupportsAncestors = FILEMAKEVERSION(3, 9, 1006, 0) <= qwEngineVersion; - if (pDependencyProvider) { pPackage->rgDependencyProviders = (BURN_DEPENDENCY_PROVIDER*)MemAlloc(sizeof(BURN_DEPENDENCY_PROVIDER), TRUE); @@ -310,7 +307,7 @@ extern "C" HRESULT PseudoBundleInitializeUpdateBundle( hr = StrAllocString(&pPackage->Exe.sczInstallArguments, wzInstallArguments, 0); ExitOnFailure(hr, "Failed to copy install arguments for update bundle package"); - // Assume the update bundle has the same engine version as this one. + // Trust the BA to only use UPDATE_REPLACE_EMBEDDED when appropriate. pPackage->Exe.protocol = BURN_EXE_PROTOCOL_TYPE_BURN; pPackage->Exe.fSupportsAncestors = TRUE; diff --git a/src/burn/engine/pseudobundle.h b/src/burn/engine/pseudobundle.h index 0fd4cbdb9..22132c5ed 100644 --- a/src/burn/engine/pseudobundle.h +++ b/src/burn/engine/pseudobundle.h @@ -7,8 +7,8 @@ extern "C" { #endif HRESULT PseudoBundleInitialize( - __in DWORD64 qwEngineVersion, __in BURN_PACKAGE* pPackage, + __in BOOL fSupportsBurnProtocol, __in BOOL fPerMachine, __in_z LPCWSTR wzId, __in BOOTSTRAPPER_RELATION_TYPE relationType, diff --git a/src/burn/engine/registration.cpp b/src/burn/engine/registration.cpp index e06767e1b..9cc4b199c 100644 --- a/src/burn/engine/registration.cpp +++ b/src/burn/engine/registration.cpp @@ -671,6 +671,9 @@ extern "C" HRESULT RegistrationSessionBegin( hr = RegWriteStringFormatted(hkRegistration, BURN_REGISTRATION_REGISTRY_ENGINE_VERSION, L"%hs", szVerMajorMinorBuild); ExitOnFailure(hr, "Failed to write %ls value.", BURN_REGISTRATION_REGISTRY_ENGINE_VERSION); + hr = RegWriteNumber(hkRegistration, BURN_REGISTRATION_REGISTRY_ENGINE_PROTOCOL_VERSION, BURN_PROTOCOL_VERSION); + ExitOnFailure(hr, "Failed to write %ls value.", BURN_REGISTRATION_REGISTRY_ENGINE_PROTOCOL_VERSION); + // DisplayIcon: [path to exe] and ",0" to refer to the first icon in the executable. hr = RegWriteStringFormatted(hkRegistration, REGISTRY_BUNDLE_DISPLAY_ICON, L"%s,0", pRegistration->sczCacheExecutablePath); ExitOnFailure(hr, "Failed to write %ls value.", REGISTRY_BUNDLE_DISPLAY_ICON); diff --git a/src/burn/engine/registration.h b/src/burn/engine/registration.h index f94116369..e33d52708 100644 --- a/src/burn/engine/registration.h +++ b/src/burn/engine/registration.h @@ -23,6 +23,7 @@ const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE = L"BundleUpgradeCo const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_DISPLAY_NAME = L"DisplayName"; const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_VERSION = L"BundleVersion"; const LPCWSTR BURN_REGISTRATION_REGISTRY_ENGINE_VERSION = L"EngineVersion"; +const LPCWSTR BURN_REGISTRATION_REGISTRY_ENGINE_PROTOCOL_VERSION = L"EngineProtocolVersion"; const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY = L"BundleProviderKey"; const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_TAG = L"BundleTag"; diff --git a/src/burn/engine/relatedbundle.cpp b/src/burn/engine/relatedbundle.cpp index d3c856a64..4a694ef6f 100644 --- a/src/burn/engine/relatedbundle.cpp +++ b/src/burn/engine/relatedbundle.cpp @@ -21,7 +21,7 @@ static HRESULT LoadRelatedBundleFromKey( __in HKEY hkBundleId, __in BOOL fPerMachine, __in BOOTSTRAPPER_RELATION_TYPE relationType, - __inout BURN_RELATED_BUNDLE *pRelatedBundle + __in BURN_RELATED_BUNDLE *pRelatedBundle ); @@ -398,21 +398,34 @@ static HRESULT LoadRelatedBundleFromKey( __in HKEY hkBundleId, __in BOOL fPerMachine, __in BOOTSTRAPPER_RELATION_TYPE relationType, - __inout BURN_RELATED_BUNDLE* pRelatedBundle + __in BURN_RELATED_BUNDLE* pRelatedBundle ) { HRESULT hr = S_OK; DWORD64 qwEngineVersion = 0; + DWORD dwEngineProtocolVersion = 0; + BOOL fSupportsBurnProtocol = FALSE; LPWSTR sczBundleVersion = NULL; LPWSTR sczCachePath = NULL; BOOL fCached = FALSE; DWORD64 qwFileSize = 0; BURN_DEPENDENCY_PROVIDER dependencyProvider = { }; - hr = RegReadVersion(hkBundleId, BURN_REGISTRATION_REGISTRY_ENGINE_VERSION, &qwEngineVersion); - if (FAILED(hr)) + // Only support progress from engines that are compatible. + hr = RegReadNumber(hkBundleId, BURN_REGISTRATION_REGISTRY_ENGINE_PROTOCOL_VERSION, &dwEngineProtocolVersion); + if (SUCCEEDED(hr)) + { + fSupportsBurnProtocol = BURN_PROTOCOL_VERSION == dwEngineProtocolVersion; + } + else { - qwEngineVersion = 0; + // Rely on version checking (aka: version greater than or equal to last protocol breaking change *and* versions that are older or the same as this engine) + hr = RegReadVersion(hkBundleId, BURN_REGISTRATION_REGISTRY_ENGINE_VERSION, &qwEngineVersion); + if (SUCCEEDED(hr)) + { + fSupportsBurnProtocol = (FILEMAKEVERSION(3, 6, 2221, 0) <= qwEngineVersion && qwEngineVersion <= FILEMAKEVERSION(rmj, rmm, rup, rpr)); + } + hr = S_OK; } @@ -467,7 +480,7 @@ static HRESULT LoadRelatedBundleFromKey( pRelatedBundle->relationType = relationType; - hr = PseudoBundleInitialize(qwEngineVersion, &pRelatedBundle->package, fPerMachine, wzRelatedBundleId, pRelatedBundle->relationType, + hr = PseudoBundleInitialize(&pRelatedBundle->package, fSupportsBurnProtocol, fPerMachine, wzRelatedBundleId, pRelatedBundle->relationType, BOOTSTRAPPER_PACKAGE_STATE_PRESENT, fCached, sczCachePath, sczCachePath, NULL, qwFileSize, FALSE, L"-quiet", L"-repair -quiet", L"-uninstall -quiet", (dependencyProvider.sczKey && *dependencyProvider.sczKey) ? &dependencyProvider : NULL, diff --git a/src/burn/test/BurnUnitTest/PlanTest.cpp b/src/burn/test/BurnUnitTest/PlanTest.cpp index 627da49a3..35ddb22f3 100644 --- a/src/burn/test/BurnUnitTest/PlanTest.cpp +++ b/src/burn/test/BurnUnitTest/PlanTest.cpp @@ -1154,7 +1154,7 @@ namespace Bootstrapper pRelatedBundle->fPlannable = TRUE; pRelatedBundle->relationType = BOOTSTRAPPER_RELATION_UPGRADE; - hr = PseudoBundleInitialize(0, &pRelatedBundle->package, TRUE, wzId, pRelatedBundle->relationType, BOOTSTRAPPER_PACKAGE_STATE_PRESENT, TRUE, wzFilePath, wzFilePath, NULL, 0, FALSE, L"-quiet", L"-repair -quiet", L"-uninstall -quiet", &dependencyProvider, NULL, 0); + hr = PseudoBundleInitialize(&pRelatedBundle->package, TRUE, TRUE, wzId, pRelatedBundle->relationType, BOOTSTRAPPER_PACKAGE_STATE_PRESENT, TRUE, wzFilePath, wzFilePath, NULL, 0, FALSE, L"-quiet", L"-repair -quiet", L"-uninstall -quiet", &dependencyProvider, NULL, 0); NativeAssert::Succeeded(hr, "Failed to initialize related bundle to represent bundle: %ls", wzId); ++pRelatedBundles->cRelatedBundles; From 46d2492eda8712d076a460b1d2080074489691e5 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Thu, 30 Dec 2021 15:32:57 -0600 Subject: [PATCH 3/3] Don't report related operation in OnDetectRelatedBundle. #5796 --- .../inc/BootstrapperApplication.h | 1 - .../BootstrapperApplication.cs | 4 +- src/api/burn/WixToolset.Mba.Core/EventArgs.cs | 8 +-- .../IBootstrapperApplication.cs | 15 ------ src/api/burn/balutil/inc/BalBaseBAFunctions.h | 1 - .../inc/BalBaseBootstrapperApplication.h | 1 - .../inc/BalBaseBootstrapperApplicationProc.h | 2 +- .../balutil/inc/IBootstrapperApplication.h | 1 - src/burn/engine/core.cpp | 2 +- src/burn/engine/detect.cpp | 52 +------------------ src/burn/engine/detect.h | 1 - src/burn/engine/engine.mc | 2 +- src/burn/engine/userexperience.cpp | 4 +- src/burn/engine/userexperience.h | 1 - .../WixStandardBootstrapperApplication.cpp | 13 +++-- .../BundleA_v10/BundleA_v10.wixproj | 20 +++++++ .../WixToolset.WixBA/InstallationViewModel.cs | 47 +++++++++++------ .../burn/WixToolset.WixBA/RootViewModel.cs | 23 ++++++++ .../WixToolsetTest.BurnE2E/DependencyTests.cs | 2 +- .../UpgradeRelatedBundleTests.cs | 2 +- 20 files changed, 94 insertions(+), 108 deletions(-) create mode 100644 src/test/burn/TestData/WixStdBaTests/BundleA_v10/BundleA_v10.wixproj diff --git a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h index c2641b5f4..4fbfc8900 100644 --- a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h +++ b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h @@ -725,7 +725,6 @@ struct BA_ONDETECTRELATEDBUNDLE_ARGS LPCWSTR wzBundleTag; BOOL fPerMachine; LPCWSTR wzVersion; - BOOTSTRAPPER_RELATED_OPERATION operation; BOOL fMissingFromCache; }; diff --git a/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs b/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs index b1fcaea4d..34b63a508 100644 --- a/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs +++ b/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs @@ -1345,9 +1345,9 @@ int IBootstrapperApplication.OnDetectUpdateComplete(int hrStatus, ref bool fIgno return args.HResult; } - int IBootstrapperApplication.OnDetectRelatedBundle(string wzProductCode, RelationType relationType, string wzBundleTag, bool fPerMachine, string wzVersion, RelatedOperation operation, bool fMissingFromCache, ref bool fCancel) + int IBootstrapperApplication.OnDetectRelatedBundle(string wzProductCode, RelationType relationType, string wzBundleTag, bool fPerMachine, string wzVersion, bool fMissingFromCache, ref bool fCancel) { - DetectRelatedBundleEventArgs args = new DetectRelatedBundleEventArgs(wzProductCode, relationType, wzBundleTag, fPerMachine, wzVersion, operation, fMissingFromCache, fCancel); + DetectRelatedBundleEventArgs args = new DetectRelatedBundleEventArgs(wzProductCode, relationType, wzBundleTag, fPerMachine, wzVersion, fMissingFromCache, fCancel); this.OnDetectRelatedBundle(args); fCancel = args.Cancel; diff --git a/src/api/burn/WixToolset.Mba.Core/EventArgs.cs b/src/api/burn/WixToolset.Mba.Core/EventArgs.cs index 65169b255..93831be64 100644 --- a/src/api/burn/WixToolset.Mba.Core/EventArgs.cs +++ b/src/api/burn/WixToolset.Mba.Core/EventArgs.cs @@ -434,7 +434,7 @@ public DetectUpdateCompleteEventArgs(int hrStatus, bool ignoreRecommendation) public class DetectRelatedBundleEventArgs : CancellableHResultEventArgs { /// - public DetectRelatedBundleEventArgs(string productCode, RelationType relationType, string bundleTag, bool perMachine, string version, RelatedOperation operation, bool missingFromCache, bool cancelRecommendation) + public DetectRelatedBundleEventArgs(string productCode, RelationType relationType, string bundleTag, bool perMachine, string version, bool missingFromCache, bool cancelRecommendation) : base(cancelRecommendation) { this.ProductCode = productCode; @@ -442,7 +442,6 @@ public DetectRelatedBundleEventArgs(string productCode, RelationType relationTyp this.BundleTag = bundleTag; this.PerMachine = perMachine; this.Version = version; - this.Operation = operation; this.MissingFromCache = missingFromCache; } @@ -471,11 +470,6 @@ public DetectRelatedBundleEventArgs(string productCode, RelationType relationTyp /// public string Version { get; private set; } - /// - /// Gets the operation that will be taken on the detected bundle. - /// - public RelatedOperation Operation { get; private set; } - /// /// Whether the related bundle is missing from the package cache. /// diff --git a/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs b/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs index 3df54bde1..babd523a0 100644 --- a/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs +++ b/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs @@ -156,15 +156,6 @@ IntPtr pvContext /// /// See . /// - /// - /// - /// - /// - /// - /// - /// - /// - /// [PreserveSig] [return: MarshalAs(UnmanagedType.I4)] int OnDetectRelatedBundle( @@ -173,7 +164,6 @@ IntPtr pvContext [MarshalAs(UnmanagedType.LPWStr)] string wzBundleTag, [MarshalAs(UnmanagedType.Bool)] bool fPerMachine, [MarshalAs(UnmanagedType.LPWStr)] string wzVersion, - [MarshalAs(UnmanagedType.U4)] RelatedOperation operation, [MarshalAs(UnmanagedType.Bool)] bool fMissingFromCache, [MarshalAs(UnmanagedType.Bool)] ref bool fCancel ); @@ -289,11 +279,6 @@ IntPtr pvContext /// /// See . /// - /// - /// - /// - /// - /// [PreserveSig] [return: MarshalAs(UnmanagedType.I4)] int OnPlanRelatedBundle( diff --git a/src/api/burn/balutil/inc/BalBaseBAFunctions.h b/src/api/burn/balutil/inc/BalBaseBAFunctions.h index 7f52f76e9..22e16f1b9 100644 --- a/src/api/burn/balutil/inc/BalBaseBAFunctions.h +++ b/src/api/burn/balutil/inc/BalBaseBAFunctions.h @@ -167,7 +167,6 @@ class CBalBaseBAFunctions : public IBAFunctions __in_z LPCWSTR /*wzBundleTag*/, __in BOOL /*fPerMachine*/, __in LPCWSTR /*wzVersion*/, - __in BOOTSTRAPPER_RELATED_OPERATION /*operation*/, __in BOOL /*fMissingFromCache*/, __inout BOOL* /*pfCancel*/ ) diff --git a/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h b/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h index 5665fee30..631d3c621 100644 --- a/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h +++ b/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h @@ -172,7 +172,6 @@ class CBalBaseBootstrapperApplication : public IBootstrapperApplication __in_z LPCWSTR /*wzBundleTag*/, __in BOOL /*fPerMachine*/, __in LPCWSTR /*wzVersion*/, - __in BOOTSTRAPPER_RELATED_OPERATION /*operation*/, __in BOOL /*fMissingFromCache*/, __inout BOOL* pfCancel ) diff --git a/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h b/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h index 2292cd648..b9866e4b4 100644 --- a/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h +++ b/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h @@ -114,7 +114,7 @@ static HRESULT BalBaseBAProcOnDetectRelatedBundle( __inout BA_ONDETECTRELATEDBUNDLE_RESULTS* pResults ) { - return pBA->OnDetectRelatedBundle(pArgs->wzBundleId, pArgs->relationType, pArgs->wzBundleTag, pArgs->fPerMachine, pArgs->wzVersion, pArgs->operation, pArgs->fMissingFromCache, &pResults->fCancel); + return pBA->OnDetectRelatedBundle(pArgs->wzBundleId, pArgs->relationType, pArgs->wzBundleTag, pArgs->fPerMachine, pArgs->wzVersion, pArgs->fMissingFromCache, &pResults->fCancel); } static HRESULT BalBaseBAProcOnDetectPackageBegin( diff --git a/src/api/burn/balutil/inc/IBootstrapperApplication.h b/src/api/burn/balutil/inc/IBootstrapperApplication.h index 2ba1f5036..577a705bc 100644 --- a/src/api/burn/balutil/inc/IBootstrapperApplication.h +++ b/src/api/burn/balutil/inc/IBootstrapperApplication.h @@ -91,7 +91,6 @@ DECLARE_INTERFACE_IID_(IBootstrapperApplication, IUnknown, "53C31D56-49C0-426B-A __in_z LPCWSTR wzBundleTag, __in BOOL fPerMachine, __in_z LPCWSTR wzVersion, - __in BOOTSTRAPPER_RELATED_OPERATION operation, __in BOOL fMissingFromCache, __inout BOOL* pfCancel ) = 0; diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp index 96845655c..30c64b015 100644 --- a/src/burn/engine/core.cpp +++ b/src/burn/engine/core.cpp @@ -359,7 +359,7 @@ extern "C" HRESULT CoreDetect( ExitOnFailure(hr, "Failed to detect provider key bundle id."); // Report the related bundles. - hr = DetectReportRelatedBundles(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, pEngineState->command.action, &pEngineState->registration.fEligibleForCleanup); + hr = DetectReportRelatedBundles(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->registration.fEligibleForCleanup); ExitOnFailure(hr, "Failed to report detected related bundles."); // Do update detection. diff --git a/src/burn/engine/detect.cpp b/src/burn/engine/detect.cpp index 4eda240e9..be828366a 100644 --- a/src/burn/engine/detect.cpp +++ b/src/burn/engine/detect.cpp @@ -154,68 +154,20 @@ extern "C" HRESULT DetectReportRelatedBundles( __in BURN_USER_EXPERIENCE* pUX, __in BURN_REGISTRATION* pRegistration, __in BOOTSTRAPPER_RELATION_TYPE relationType, - __in BOOTSTRAPPER_ACTION action, __out BOOL* pfEligibleForCleanup ) { HRESULT hr = S_OK; - int nCompareResult = 0; BOOTSTRAPPER_REQUEST_STATE uninstallRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; *pfEligibleForCleanup = pRegistration->fInstalled || pRegistration->fCached; for (DWORD iRelatedBundle = 0; iRelatedBundle < pRegistration->relatedBundles.cRelatedBundles; ++iRelatedBundle) { const BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + iRelatedBundle; - BOOTSTRAPPER_RELATED_OPERATION operation = BOOTSTRAPPER_RELATED_OPERATION_NONE; - - switch (pRelatedBundle->relationType) - { - case BOOTSTRAPPER_RELATION_UPGRADE: - if (BOOTSTRAPPER_RELATION_UPGRADE != relationType && BOOTSTRAPPER_ACTION_UNINSTALL < action) - { - hr = VerCompareParsedVersions(pRegistration->pVersion, pRelatedBundle->pVersion, &nCompareResult); - ExitOnFailure(hr, "Failed to compare bundle version '%ls' to related bundle version '%ls'", pRegistration->pVersion->sczVersion, pRelatedBundle->pVersion->sczVersion); - - if (nCompareResult < 0) - { - operation = BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE; - } - else - { - operation = BOOTSTRAPPER_RELATED_OPERATION_MAJOR_UPGRADE; - } - } - break; - - case BOOTSTRAPPER_RELATION_PATCH: __fallthrough; - case BOOTSTRAPPER_RELATION_ADDON: - if (BOOTSTRAPPER_ACTION_UNINSTALL == action) - { - operation = BOOTSTRAPPER_RELATED_OPERATION_REMOVE; - } - else if (BOOTSTRAPPER_ACTION_INSTALL == action || BOOTSTRAPPER_ACTION_MODIFY == action) - { - operation = BOOTSTRAPPER_RELATED_OPERATION_INSTALL; - } - else if (BOOTSTRAPPER_ACTION_REPAIR == action) - { - operation = BOOTSTRAPPER_RELATED_OPERATION_REPAIR; - } - break; - - case BOOTSTRAPPER_RELATION_DETECT: __fallthrough; - case BOOTSTRAPPER_RELATION_DEPENDENT: - break; - - default: - hr = E_FAIL; - ExitOnRootFailure(hr, "Unexpected relation type encountered: %d", pRelatedBundle->relationType); - break; - } - LogId(REPORT_STANDARD, MSG_DETECTED_RELATED_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), pRelatedBundle->pVersion->sczVersion, LoggingRelatedOperationToString(operation), LoggingBoolToString(pRelatedBundle->package.fCached)); + LogId(REPORT_STANDARD, MSG_DETECTED_RELATED_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), pRelatedBundle->pVersion->sczVersion, LoggingBoolToString(pRelatedBundle->package.fCached)); - hr = UserExperienceOnDetectRelatedBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, operation, !pRelatedBundle->package.fCached); + hr = UserExperienceOnDetectRelatedBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, !pRelatedBundle->package.fCached); ExitOnRootFailure(hr, "BA aborted detect related bundle."); // For now, if any related bundles will be executed during uninstall by default then never automatically clean up the bundle. diff --git a/src/burn/engine/detect.h b/src/burn/engine/detect.h index 9bc34882b..cdca2777d 100644 --- a/src/burn/engine/detect.h +++ b/src/burn/engine/detect.h @@ -29,7 +29,6 @@ HRESULT DetectReportRelatedBundles( __in BURN_USER_EXPERIENCE* pUX, __in BURN_REGISTRATION* pRegistration, __in BOOTSTRAPPER_RELATION_TYPE relationType, - __in BOOTSTRAPPER_ACTION action, __out BOOL* pfEligibleForCleanup ); diff --git a/src/burn/engine/engine.mc b/src/burn/engine/engine.mc index dde4d40b7..5c1b0b696 100644 --- a/src/burn/engine/engine.mc +++ b/src/burn/engine/engine.mc @@ -223,7 +223,7 @@ MessageId=102 Severity=Success SymbolicName=MSG_DETECTED_RELATED_BUNDLE Language=English -Detected related bundle: %1!ls!, type: %2!hs!, scope: %3!hs!, version: %4!ls!, operation: %5!hs!, cached: %6!hs! +Detected related bundle: %1!ls!, type: %2!hs!, scope: %3!hs!, version: %4!ls!, cached: %5!hs! . MessageId=103 diff --git a/src/burn/engine/userexperience.cpp b/src/burn/engine/userexperience.cpp index ee22a3186..6ea169056 100644 --- a/src/burn/engine/userexperience.cpp +++ b/src/burn/engine/userexperience.cpp @@ -104,7 +104,7 @@ extern "C" HRESULT UserExperienceLoad( args.pCommand = pCommand; args.pfnBootstrapperEngineProc = EngineForApplicationProc; args.pvBootstrapperEngineProcContext = pEngineContext; - args.qwEngineAPIVersion = MAKEQWORDVERSION(2021, 12, 7, 0); + args.qwEngineAPIVersion = MAKEQWORDVERSION(2021, 12, 30, 0); results.cbSize = sizeof(BOOTSTRAPPER_CREATE_RESULTS); @@ -1164,7 +1164,6 @@ EXTERN_C BAAPI UserExperienceOnDetectRelatedBundle( __in_z LPCWSTR wzBundleTag, __in BOOL fPerMachine, __in VERUTIL_VERSION* pVersion, - __in BOOTSTRAPPER_RELATED_OPERATION operation, __in BOOL fMissingFromCache ) { @@ -1178,7 +1177,6 @@ EXTERN_C BAAPI UserExperienceOnDetectRelatedBundle( args.wzBundleTag = wzBundleTag; args.fPerMachine = fPerMachine; args.wzVersion = pVersion->sczVersion; - args.operation = operation; args.fMissingFromCache = fMissingFromCache; results.cbSize = sizeof(results); diff --git a/src/burn/engine/userexperience.h b/src/burn/engine/userexperience.h index 27d0a1e3a..e4c5d3ee2 100644 --- a/src/burn/engine/userexperience.h +++ b/src/burn/engine/userexperience.h @@ -286,7 +286,6 @@ BAAPI UserExperienceOnDetectRelatedBundle( __in_z LPCWSTR wzBundleTag, __in BOOL fPerMachine, __in VERUTIL_VERSION* pVersion, - __in BOOTSTRAPPER_RELATED_OPERATION operation, __in BOOL fMissingFromCache ); BAAPI UserExperienceOnDetectRelatedMsiPackage( diff --git a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp index ec3c268ac..7b70d7728 100644 --- a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp +++ b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp @@ -246,12 +246,12 @@ class CWixStandardBootstrapperApplication : public CBalBaseBootstrapperApplicati __in LPCWSTR wzBundleTag, __in BOOL fPerMachine, __in LPCWSTR wzVersion, - __in BOOTSTRAPPER_RELATED_OPERATION operation, __in BOOL fMissingFromCache, __inout BOOL* pfCancel ) { BAL_INFO_PACKAGE* pPackage = NULL; + int nCompare = 0; if (!fMissingFromCache) { @@ -261,14 +261,15 @@ class CWixStandardBootstrapperApplication : public CBalBaseBootstrapperApplicati } // If we're not doing a prerequisite install, remember when our bundle would cause a downgrade. - if (!m_fPrereq && BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE == operation) + if (!m_fPrereq && BOOTSTRAPPER_RELATION_UPGRADE == relationType && + SUCCEEDED(m_pEngine->CompareVersions(m_sczBundleVersion, wzVersion, &nCompare)) && 0 > nCompare) { BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "A newer version (v%ls) of this product is installed.", wzVersion); m_fDowngrading = TRUE; } } - return CBalBaseBootstrapperApplication::OnDetectRelatedBundle(wzBundleId, relationType, wzBundleTag, fPerMachine, wzVersion, operation, fMissingFromCache, pfCancel); + return CBalBaseBootstrapperApplication::OnDetectRelatedBundle(wzBundleId, relationType, wzBundleTag, fPerMachine, wzVersion, fMissingFromCache, pfCancel); } @@ -2091,7 +2092,8 @@ class CWixStandardBootstrapperApplication : public CBalBaseBootstrapperApplicati } } - hr = S_OK; + hr = BalGetStringVariable(L"WixBundleVersion", &m_sczBundleVersion); + BalExitOnFailure(hr, "CWixStandardBootstrapperApplication initialization failed."); LExit: return hr; @@ -4129,6 +4131,7 @@ class CWixStandardBootstrapperApplication : public CBalBaseBootstrapperApplicati m_plannedAction = BOOTSTRAPPER_ACTION_UNKNOWN; m_sczAfterForcedRestartPackage = NULL; + m_sczBundleVersion = NULL; m_pWixLoc = NULL; m_Bundle = { }; @@ -4367,6 +4370,7 @@ class CWixStandardBootstrapperApplication : public CBalBaseBootstrapperApplicati ReleaseStr(m_sczLanguage); ReleaseStr(m_sczLicenseFile); ReleaseStr(m_sczLicenseUrl); + ReleaseStr(m_sczBundleVersion); ReleaseStr(m_sczAfterForcedRestartPackage); ReleaseNullObject(m_pEngine); @@ -4391,6 +4395,7 @@ class CWixStandardBootstrapperApplication : public CBalBaseBootstrapperApplicati BOOTSTRAPPER_ACTION m_plannedAction; LPWSTR m_sczAfterForcedRestartPackage; + LPWSTR m_sczBundleVersion; WIX_LOCALIZATION* m_pWixLoc; BAL_INFO_BUNDLE m_Bundle; diff --git a/src/test/burn/TestData/WixStdBaTests/BundleA_v10/BundleA_v10.wixproj b/src/test/burn/TestData/WixStdBaTests/BundleA_v10/BundleA_v10.wixproj new file mode 100644 index 000000000..602dc4bc5 --- /dev/null +++ b/src/test/burn/TestData/WixStdBaTests/BundleA_v10/BundleA_v10.wixproj @@ -0,0 +1,20 @@ + + + + Bundle + hyperlinkLicense + {7D977157-06C9-4176-A931-AC16E18AAB51} + $(DefineConstants);Version=1.0 + WixStdBaTest1_v10 + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/burn/WixToolset.WixBA/InstallationViewModel.cs b/src/test/burn/WixToolset.WixBA/InstallationViewModel.cs index 1846d51b4..e056b943a 100644 --- a/src/test/burn/WixToolset.WixBA/InstallationViewModel.cs +++ b/src/test/burn/WixToolset.WixBA/InstallationViewModel.cs @@ -19,6 +19,18 @@ public enum DetectionState { Absent, Present, + } + + /// + /// The states of upgrade detection. + /// + public enum UpgradeDetectionState + { + // There are no Upgrade related bundles installed. + None, + // All Upgrade related bundles that are installed are older than or the same version as this bundle. + Older, + // At least one Upgrade related bundle is installed that is newer than this bundle. Newer, } @@ -90,7 +102,7 @@ public InstallationViewModel(RootViewModel root) void RootPropertyChanged(object sender, PropertyChangedEventArgs e) { - if (("DetectState" == e.PropertyName) || ("InstallState" == e.PropertyName)) + if (("DetectState" == e.PropertyName) || ("UpgradeDetectState" == e.PropertyName) || ("InstallState" == e.PropertyName)) { base.OnPropertyChanged("RepairEnabled"); base.OnPropertyChanged("InstallEnabled"); @@ -276,7 +288,9 @@ public ICommand InstallCommand { if (this.installCommand == null) { - this.installCommand = new RelayCommand(param => WixBA.Plan(LaunchAction.Install), param => this.root.DetectState == DetectionState.Absent && this.root.InstallState == InstallationState.Waiting); + this.installCommand = new RelayCommand( + param => WixBA.Plan(LaunchAction.Install), + param => this.root.DetectState == DetectionState.Absent && this.root.UpgradeDetectState != UpgradeDetectionState.Newer && this.root.InstallState == InstallationState.Waiting); } return this.installCommand; @@ -399,9 +413,19 @@ private void DetectBegin(object sender, DetectBeginEventArgs e) private void DetectedRelatedBundle(object sender, DetectRelatedBundleEventArgs e) { - if (e.Operation == RelatedOperation.Downgrade) + if (e.RelationType == RelationType.Upgrade) { - this.Downgrade = true; + if (WixBA.Model.Engine.CompareVersions(this.Version, e.Version) > 0) + { + if (this.root.UpgradeDetectState == UpgradeDetectionState.None) + { + this.root.UpgradeDetectState = UpgradeDetectionState.Older; + } + } + else + { + this.root.UpgradeDetectState = UpgradeDetectionState.Newer; + } } if (!WixBA.Model.BAManifest.Bundle.Packages.ContainsKey(e.ProductCode)) @@ -432,19 +456,10 @@ private void DetectComplete(object sender, DetectCompleteEventArgs e) } else if (Hresult.Succeeded(e.Status)) { - if (this.Downgrade) + if (this.root.UpgradeDetectState == UpgradeDetectionState.Newer) { - this.root.DetectState = DetectionState.Newer; - var relatedPackages = WixBA.Model.BAManifest.Bundle.Packages.Values.Where(p => p.Type == PackageType.UpgradeBundle); - var installedVersion = relatedPackages.Any() ? new Version(relatedPackages.Max(p => p.Version)) : null; - if (installedVersion != null && installedVersion < new Version(4, 1) && installedVersion.Build > 10) - { - this.DowngradeMessage = "You must uninstall WiX v" + installedVersion + " before you can install this."; - } - else - { - this.DowngradeMessage = "There is already a newer version of WiX installed on this machine."; - } + this.Downgrade = true; + this.DowngradeMessage = "There is already a newer version of WiX installed on this machine."; } if (LaunchAction.Layout == WixBA.Model.Command.Action) diff --git a/src/test/burn/WixToolset.WixBA/RootViewModel.cs b/src/test/burn/WixToolset.WixBA/RootViewModel.cs index 8cff72740..2dfd214e8 100644 --- a/src/test/burn/WixToolset.WixBA/RootViewModel.cs +++ b/src/test/burn/WixToolset.WixBA/RootViewModel.cs @@ -27,6 +27,7 @@ public class RootViewModel : PropertyNotifyBase private bool canceled; private InstallationState installState; private DetectionState detectState; + private UpgradeDetectionState upgradeDetectState; /// /// Creates a new model of the root view. @@ -119,6 +120,28 @@ public DetectionState DetectState } } + /// + /// Gets and sets the upgrade detect state of the view's model. + /// + public UpgradeDetectionState UpgradeDetectState + { + get + { + return this.upgradeDetectState; + } + + set + { + if (this.upgradeDetectState != value) + { + this.upgradeDetectState = value; + + // Notify all the properties derived from the state that the state changed. + base.OnPropertyChanged("UpgradeDetectState"); + } + } + } + /// /// Gets and sets the installation state of the view's model. /// diff --git a/src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs index e2975fc99..309241d98 100644 --- a/src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs +++ b/src/test/burn/WixToolsetTest.BurnE2E/DependencyTests.cs @@ -596,7 +596,7 @@ public void SkipsCrossScopeDependencyRegistration() packageDv2.VerifyInstalled(true); Assert.True(LogVerifier.MessageInLogFileRegex(bundleHv2InstallLogFilePath, @"Skipping cross-scope dependency registration on package: PackageA, bundle scope: PerUser, package scope: PerMachine")); - Assert.True(LogVerifier.MessageInLogFileRegex(bundleHv2InstallLogFilePath, @"Detected related bundle: \{[0-9A-Za-z\-]{36}\}, type: Upgrade, scope: PerUser, version: 1\.0\.0\.0, operation: MajorUpgrade, cached: Yes")); + Assert.True(LogVerifier.MessageInLogFileRegex(bundleHv2InstallLogFilePath, @"Detected related bundle: \{[0-9A-Za-z\-]{36}\}, type: Upgrade, scope: PerUser, version: 1\.0\.0\.0, cached: Yes")); bundleHv2.Uninstall(); bundleHv2.VerifyUnregisteredAndRemovedFromPackageCache(); diff --git a/src/test/burn/WixToolsetTest.BurnE2E/UpgradeRelatedBundleTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/UpgradeRelatedBundleTests.cs index 70c0c4749..35cc64f0c 100644 --- a/src/test/burn/WixToolsetTest.BurnE2E/UpgradeRelatedBundleTests.cs +++ b/src/test/burn/WixToolsetTest.BurnE2E/UpgradeRelatedBundleTests.cs @@ -30,7 +30,7 @@ public void ReportsRelatedBundleMissingFromCache() bundleAv2.VerifyRegisteredAndInPackageCache(); Assert.True(LogVerifier.MessageInLogFileRegex(bundleAv2InstallLogFilePath, @"OnDetectRelatedBundle\(\) - id: \{[0-9A-Za-z\-]{36}\}, missing from cache: True")); - Assert.True(LogVerifier.MessageInLogFileRegex(bundleAv2InstallLogFilePath, @"Detected related bundle: \{[0-9A-Za-z\-]{36}\}, type: Upgrade, scope: PerMachine, version: 1\.0\.0\.0, operation: MajorUpgrade, cached: No")); + Assert.True(LogVerifier.MessageInLogFileRegex(bundleAv2InstallLogFilePath, @"Detected related bundle: \{[0-9A-Za-z\-]{36}\}, type: Upgrade, scope: PerMachine, version: 1\.0\.0\.0, cached: No")); } } }