Skip to content

Commit b435e1b

Browse files
committed
Lock upgrade bundles to original bundle's scope.
Fixes wixtoolset/issues#9236
1 parent de80ff1 commit b435e1b

19 files changed

Lines changed: 183 additions & 43 deletions

File tree

src/api/burn/WixToolset.BootstrapperApplicationApi/IBootstrapperEngine.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -345,23 +345,24 @@ public enum LaunchAction
345345
}
346346

347347
/// <summary>
348-
/// The scope of the bundle when the chain contains per-user-or-machine or per-machone-or-user packages.
348+
/// The scope of the bundle when the chain contains dual-purpose (per-user-or-machine or per-machone-or-user) packages.
349349
/// </summary>
350350
public enum BundleScope
351351
{
352352
/// <summary>
353353
/// Let Burn choose the scope. Per-user-or-machine packages will be
354+
/// planned as per-user packages. Per-user-or-machine packages will be
354355
/// planned as per-machine packages.
355356
/// </summary>
356357
Default,
357358

358359
/// <summary>
359-
/// Set per-machine scope for per-user-or-machine packages.
360+
/// Set per-machine scope for dual-purpose packages.
360361
/// </summary>
361362
PerMachine,
362363

363364
/// <summary>
364-
/// Set per-user scope for per-user-or-machine packages.
365+
/// Set per-user scope for dual-purpose packages.
365366
/// </summary>
366367
PerUser,
367368
}

src/burn/engine/core.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ extern "C" HRESULT CorePlan(
469469
pEngineState->plan.fDisableRollback = pEngineState->fDisableRollback || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pEngineState->plan.action;
470470
pEngineState->plan.fPlanPackageCacheRollback = BOOTSTRAPPER_REGISTRATION_TYPE_NONE == pEngineState->registration.detectedRegistrationType;
471471

472-
hr = PlanPackagesAndBundleScope(pEngineState->packages.rgPackages, pEngineState->packages.cPackages, pEngineState->plan.plannedScope, pEngineState->registration.scope, pEngineState->command.commandLineScope, pEngineState->registration.detectedScope, &pEngineState->plan.plannedScope, &pEngineState->registration.fPerMachine);
472+
hr = PlanPackagesAndBundleScope(pEngineState->packages.rgPackages, pEngineState->packages.cPackages, pEngineState->registration.sczPrimaryUpgradeCode, pEngineState->registration.relatedBundles.rgRelatedBundles, pEngineState->registration.relatedBundles.cRelatedBundles, pEngineState->plan.plannedScope, pEngineState->registration.scope, pEngineState->command.commandLineScope, pEngineState->registration.detectedScope, &pEngineState->plan.plannedScope, &pEngineState->registration.fPerMachine);
473473
ExitOnFailure(hr, "Failed to determine packages and bundle scope.");
474474

475475
if (BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE_OR_PER_USER == pEngineState->registration.scope || BOOTSTRAPPER_PACKAGE_SCOPE_PER_USER_OR_PER_MACHINE == pEngineState->registration.scope)

src/burn/engine/core.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,6 @@ HRESULT CoreSerializeEngineState(
235235
HRESULT CoreQueryRegistration(
236236
__in BURN_ENGINE_STATE* pEngineState
237237
);
238-
//HRESULT CoreDeserializeEngineState(
239-
// __in BURN_ENGINE_STATE* pEngineState,
240-
// __in_bcount(cbBuffer) BYTE* pbBuffer,
241-
// __in SIZE_T cbBuffer
242-
// );
243238
HRESULT CoreDetect(
244239
__in BURN_ENGINE_STATE* pEngineState,
245240
__in_opt HWND hwndParent

src/burn/engine/engine.mc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,14 @@ MessageId=227
418418
Severity=Success
419419
SymbolicName=MSG_PLAN_INSTALLED_SCOPE
420420
Language=English
421-
Bundle was already installed with scope: %1!hs!
421+
Bundle was already installed with scope: %1!hs!. Scope cannot change during maintenance.
422+
.
423+
424+
MessageId=228
425+
Severity=Success
426+
SymbolicName=MSG_PLAN_UPGRADE_SCOPE
427+
Language=English
428+
Upgraded bundle %1!ls! was already installed with scope: %2!hs!. Scope cannot change during upgrade.
422429
.
423430
424431
MessageId=201

src/burn/engine/plan.cpp

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,12 @@ static BOOL ForceCache(
144144
__in BURN_PLAN* pPlan,
145145
__in BURN_PACKAGE* pPackage
146146
);
147+
static HRESULT GetUpgradedBundleScope(
148+
__in DWORD cRelatedBundles,
149+
__in BURN_RELATED_BUNDLE* rgRelatedBundles,
150+
__in_z LPCWSTR wzUpgradeCode,
151+
__inout BOOTSTRAPPER_SCOPE* pScope
152+
);
147153

148154
// function definitions
149155

@@ -823,6 +829,9 @@ extern "C" HRESULT PlanUpdateBundle(
823829
extern "C" HRESULT PlanPackagesAndBundleScope(
824830
__in BURN_PACKAGE* rgPackages,
825831
__in DWORD cPackages,
832+
__in_z LPCWSTR wzUpgradeCode,
833+
__in BURN_RELATED_BUNDLE* rgRelatedBundles,
834+
__in DWORD cRelatedBundles,
826835
__in BOOTSTRAPPER_SCOPE scope,
827836
__in BOOTSTRAPPER_PACKAGE_SCOPE authoredScope,
828837
__in BOOTSTRAPPER_SCOPE commandLineScope,
@@ -855,7 +864,11 @@ extern "C" HRESULT PlanPackagesAndBundleScope(
855864
}
856865
}
857866

858-
if (BOOTSTRAPPER_SCOPE_DEFAULT != detectedScope)
867+
// If we're upgrading, lock the scope to that of the upgraded bundle.
868+
hr = GetUpgradedBundleScope(cRelatedBundles, rgRelatedBundles, wzUpgradeCode, &scope);
869+
870+
// If we're in maintenance mode instead, lock the scope to the original scope.
871+
if (S_FALSE == hr && BOOTSTRAPPER_SCOPE_DEFAULT != detectedScope)
859872
{
860873
scope = detectedScope;
861874

@@ -888,6 +901,47 @@ extern "C" HRESULT PlanPackagesAndBundleScope(
888901
}
889902

890903

904+
static HRESULT GetUpgradedBundleScope(
905+
__in DWORD cRelatedBundles,
906+
__in BURN_RELATED_BUNDLE* rgRelatedBundles,
907+
__in_z LPCWSTR wzUpgradeCode,
908+
__inout BOOTSTRAPPER_SCOPE* pScope
909+
)
910+
{
911+
HRESULT hr = S_OK;
912+
913+
for (DWORD i = 0; i < cRelatedBundles; ++i)
914+
{
915+
BURN_RELATED_BUNDLE* pRelatedBundle = rgRelatedBundles + i;
916+
917+
if (BOOTSTRAPPER_RELATION_UPGRADE == pRelatedBundle->detectRelationType)
918+
{
919+
for (DWORD j = 0; j < pRelatedBundle->package.Bundle.cUpgradeCodes; ++j)
920+
{
921+
LPCWSTR wzRelatedUpgradeCode = *(pRelatedBundle->package.Bundle.rgsczUpgradeCodes + j);
922+
923+
// Is the related bundle's upgrade code the same as ours?
924+
// If so, lock our scope to the "original" bundle's scope.
925+
if (CSTR_EQUAL == ::CompareStringOrdinal(wzRelatedUpgradeCode, -1, wzUpgradeCode, -1, FALSE))
926+
{
927+
*pScope = pRelatedBundle->detectedScope;
928+
929+
LogId(REPORT_STANDARD, MSG_PLAN_UPGRADE_SCOPE, pRelatedBundle->package.Bundle.sczBundleCode, LoggingBundleScopeToString(*pScope));
930+
931+
ExitFunction();
932+
}
933+
}
934+
}
935+
}
936+
937+
// No upgrade codes or none match, which is fine. But note it via S_FALSE
938+
// so we can distinguish the upgrade case from the maintenance case.
939+
hr = S_FALSE;
940+
941+
LExit:
942+
return hr;
943+
}
944+
891945
static HRESULT PlanPackagesHelper(
892946
__in BURN_PACKAGE* rgPackages,
893947
__in DWORD cPackages,

src/burn/engine/plan.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,9 @@ void PlanDump(
485485
HRESULT PlanPackagesAndBundleScope(
486486
__in BURN_PACKAGE* rgPackages,
487487
__in DWORD cPackages,
488+
__in_z LPCWSTR wzUpgradeCode,
489+
__in BURN_RELATED_BUNDLE* rgRelatedBundles,
490+
__in DWORD cRelatedBundles,
488491
__in BOOTSTRAPPER_SCOPE scope,
489492
__in BOOTSTRAPPER_PACKAGE_SCOPE authoredScope,
490493
__in BOOTSTRAPPER_SCOPE commandLineScope,

src/burn/engine/registration.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@ const LPCWSTR REGISTRY_BUNDLE_UNINSTALL_STRING = L"UninstallString";
2929
const LPCWSTR REGISTRY_BUNDLE_RESUME_COMMAND_LINE = L"BundleResumeCommandLine";
3030
const LPCWSTR REGISTRY_BUNDLE_VERSION_MAJOR = L"VersionMajor";
3131
const LPCWSTR REGISTRY_BUNDLE_VERSION_MINOR = L"VersionMinor";
32-
const LPCWSTR REGISTRY_BUNDLE_SCOPE = L"BundleScope";
3332
const LPCWSTR SWIDTAG_FOLDER = L"swidtag";
3433
const LPCWSTR REGISTRY_BUNDLE_VARIABLE_KEY = L"variables";
34+
const LPCWSTR REGISTRY_BUNDLE_INSTALLED = L"Installed";
35+
3536

3637
// internal function declarations
3738

@@ -146,6 +147,10 @@ extern "C" HRESULT RegistrationParseFromXml(
146147
hr = XmlGetAttributeEx(pixnRegistrationNode, L"Tag", &pRegistration->sczTag);
147148
ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Tag.");
148149

150+
// @PrimaryUpgradeCode
151+
hr = XmlGetAttributeEx(pixnRegistrationNode, L"PrimaryUpgradeCode", &pRegistration->sczPrimaryUpgradeCode);
152+
ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @PrimaryUpgradeCode.");
153+
149154
hr = BundlePackageEngineParseRelatedCodes(pixnBundle, &pRegistration->rgsczDetectCodes, &pRegistration->cDetectCodes, &pRegistration->rgsczUpgradeCodes, &pRegistration->cUpgradeCodes, &pRegistration->rgsczAddonCodes, &pRegistration->cAddonCodes, &pRegistration->rgsczPatchCodes, &pRegistration->cPatchCodes);
150155
ExitOnFailure(hr, "Failed to parse related bundles");
151156

@@ -327,7 +332,8 @@ extern "C" void RegistrationUninitialize(
327332
{
328333
ReleaseStr(pRegistration->sczCode);
329334
ReleaseStr(pRegistration->sczTag);
330-
335+
ReleaseStr(pRegistration->sczPrimaryUpgradeCode);
336+
331337
for (DWORD i = 0; i < pRegistration->cDetectCodes; ++i)
332338
{
333339
ReleaseStr(pRegistration->rgsczDetectCodes[i]);
@@ -666,8 +672,8 @@ extern "C" HRESULT RegistrationSessionBegin(
666672
hr = RegWriteStringFormatted(hkRegistration, REGISTRY_BUNDLE_DISPLAY_ICON, L"%s,0", pRegistration->sczCacheExecutablePath);
667673
ExitOnFailure(hr, "Failed to write %ls value.", REGISTRY_BUNDLE_DISPLAY_ICON);
668674

669-
hr = RegWriteNumber(hkRegistration, REGISTRY_BUNDLE_SCOPE, pRegistration->fPerMachine ? BOOTSTRAPPER_SCOPE_PER_MACHINE : BOOTSTRAPPER_SCOPE_PER_USER);
670-
ExitOnFailure(hr, "Failed to write %ls value.", REGISTRY_BUNDLE_SCOPE);
675+
hr = RegWriteNumber(hkRegistration, BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE, pRegistration->fPerMachine ? BOOTSTRAPPER_SCOPE_PER_MACHINE : BOOTSTRAPPER_SCOPE_PER_USER);
676+
ExitOnFailure(hr, "Failed to write %ls value.", BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE);
671677

672678
// update display name
673679
hr = UpdateBundleNameRegistration(pRegistration, pVariables, hkRegistration, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS == registrationType);
@@ -1780,8 +1786,8 @@ static HRESULT DetectInstalled(
17801786

17811787
pRegistration->detectedRegistrationType = (1 == dwInstalled) ? BOOTSTRAPPER_REGISTRATION_TYPE_FULL : BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS;
17821788

1783-
hr = RegReadNumber(hkRegistration, REGISTRY_BUNDLE_SCOPE, &dwScope);
1784-
ExitOnFailure(hr, "Failed to read registration %ls@%ls.", pRegistration->sczRegistrationKey, REGISTRY_BUNDLE_SCOPE);
1789+
hr = RegReadNumber(hkRegistration, BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE, &dwScope);
1790+
ExitOnFailure(hr, "Failed to read registration %ls@%ls.", pRegistration->sczRegistrationKey, BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE);
17851791

17861792
pRegistration->detectedScope = static_cast<BOOTSTRAPPER_SCOPE>(dwScope);
17871793
}

src/burn/engine/registration.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ const LPCWSTR BURN_REGISTRATION_REGISTRY_ENGINE_VERSION = L"EngineVersion";
2121
const LPCWSTR BURN_REGISTRATION_REGISTRY_ENGINE_PROTOCOL_VERSION = L"EngineProtocolVersion";
2222
const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY = L"BundleProviderKey";
2323
const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_TAG = L"BundleTag";
24-
25-
const LPCWSTR REGISTRY_BUNDLE_INSTALLED = L"Installed";
24+
const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE = L"BundleScope";
2625

2726
enum BURN_RESUME_MODE
2827
{
@@ -69,6 +68,7 @@ typedef struct _BURN_RELATED_BUNDLE
6968
BOOTSTRAPPER_REQUEST_STATE defaultRequestedRestore;
7069
BOOTSTRAPPER_REQUEST_STATE requestedRestore;
7170
BOOTSTRAPPER_ACTION_STATE restore;
71+
BOOTSTRAPPER_SCOPE detectedScope;
7272
} BURN_RELATED_BUNDLE;
7373

7474
typedef struct _BURN_RELATED_BUNDLES
@@ -106,6 +106,7 @@ typedef struct _BURN_REGISTRATION
106106
BOOTSTRAPPER_PACKAGE_SCOPE scope;
107107
LPWSTR sczCode;
108108
LPWSTR sczTag;
109+
LPWSTR sczPrimaryUpgradeCode;
109110

110111
LPWSTR *rgsczDetectCodes;
111112
DWORD cDetectCodes;

src/burn/engine/relatedbundle.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ static HRESULT LoadRelatedBundleFromKey(
325325
BOOL fExists = FALSE;
326326
BURN_DEPENDENCY_PROVIDER dependencyProvider = { };
327327
BURN_DEPENDENCY_PROVIDER* pBundleDependencyProvider = NULL;
328+
DWORD dwScope = 0;
328329

329330
// Only support progress from engines that are compatible.
330331
hr = RegReadNumber(hkBundleCode, BURN_REGISTRATION_REGISTRY_ENGINE_PROTOCOL_VERSION, &dwEngineProtocolVersion);
@@ -355,6 +356,11 @@ static HRESULT LoadRelatedBundleFromKey(
355356
LogId(REPORT_WARNING, MSG_RELATED_PACKAGE_INVALID_VERSION, wzRelatedBundleCode, sczBundleVersion);
356357
}
357358

359+
hr = RegReadNumber(hkBundleCode, BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE, &dwScope);
360+
ExitOnFailure(hr, "Failed to read registration %ls for bundle %ls.", wzRelatedBundleCode, BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE);
361+
362+
pRelatedBundle->detectedScope = static_cast<BOOTSTRAPPER_SCOPE>(dwScope);
363+
358364
hr = RegReadString(hkBundleCode, BURN_REGISTRATION_REGISTRY_BUNDLE_CACHE_PATH, &sczCachePath);
359365
ExitOnFailure(hr, "Failed to read cache path from registry for bundle: %ls", wzRelatedBundleCode);
360366

@@ -390,6 +396,12 @@ static HRESULT LoadRelatedBundleFromKey(
390396

391397
pRelatedBundle->detectRelationType = relationType;
392398

399+
hr = StrAllocString(&pRelatedBundle->package.Bundle.sczBundleCode, wzRelatedBundleCode, 0);
400+
ExitOnFailure(hr, "Failed to bundle code to related bundle.");
401+
402+
hr = RegReadStringArray(hkBundleCode, BURN_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &pRelatedBundle->package.Bundle.rgsczUpgradeCodes, &pRelatedBundle->package.Bundle.cUpgradeCodes);
403+
ExitOnFailure(hr, "Failed to read upgrade codes.");
404+
393405
hr = PseudoBundleInitializeRelated(&pRelatedBundle->package, fSupportsBurnProtocol, fPerMachine, wzRelatedBundleCode,
394406
#ifdef DEBUG
395407
pRelatedBundle->detectRelationType,

src/burn/test/BurnUnitTest/RelatedBundleTest.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,9 @@ namespace Bootstrapper
178178

179179
hr = RegWriteString(hkRegistration, BURN_REGISTRATION_REGISTRY_BUNDLE_VERSION, wzVersion);
180180
NativeAssert::Succeeded(hr, "Failed to write %ls value.", BURN_REGISTRATION_REGISTRY_BUNDLE_VERSION);
181+
182+
hr = RegWriteNumber(hkRegistration, BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE, fPerMachine ? BOOTSTRAPPER_SCOPE_PER_MACHINE : BOOTSTRAPPER_SCOPE_PER_USER);
183+
NativeAssert::Succeeded(hr, "Failed to write %ls value.", BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE);
181184
}
182185
finally
183186
{

0 commit comments

Comments
 (0)