aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/api/burn/WixToolset.BootstrapperApplicationApi/IBootstrapperEngine.cs7
-rw-r--r--src/burn/engine/core.cpp2
-rw-r--r--src/burn/engine/core.h5
-rw-r--r--src/burn/engine/engine.mc9
-rw-r--r--src/burn/engine/plan.cpp57
-rw-r--r--src/burn/engine/plan.h3
-rw-r--r--src/burn/engine/registration.cpp18
-rw-r--r--src/burn/engine/registration.h5
-rw-r--r--src/burn/engine/relatedbundle.cpp12
-rw-r--r--src/burn/test/BurnUnitTest/RelatedBundleTest.cpp3
-rw-r--r--src/test/burn/TestData/ConfigurableScopeTests/AllPuomBundle/AllPuomBundleTestBA.wixproj1
-rw-r--r--src/test/burn/TestData/ConfigurableScopeTests/AllPuomBundle/AllPuomBundleTestBAv2.wixproj8
-rw-r--r--src/test/burn/TestData/ConfigurableScopeTests/AllPuomBundle/AllPuomBundleWixStdBA.wixproj1
-rw-r--r--src/test/burn/TestData/ConfigurableScopeTests/AllPuomBundle/Bundle.wxs2
-rw-r--r--src/test/burn/WixToolsetTest.BurnE2E/ConfigurableScopeTests.cs48
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs1
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/BundleFixture.cs2
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs41
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/DependencyExtensionFixture.cs2
19 files changed, 184 insertions, 43 deletions
diff --git a/src/api/burn/WixToolset.BootstrapperApplicationApi/IBootstrapperEngine.cs b/src/api/burn/WixToolset.BootstrapperApplicationApi/IBootstrapperEngine.cs
index 9df57cd3..4b1c4b52 100644
--- a/src/api/burn/WixToolset.BootstrapperApplicationApi/IBootstrapperEngine.cs
+++ b/src/api/burn/WixToolset.BootstrapperApplicationApi/IBootstrapperEngine.cs
@@ -345,23 +345,24 @@ namespace WixToolset.BootstrapperApplicationApi
345 } 345 }
346 346
347 /// <summary> 347 /// <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.
349 /// </summary> 349 /// </summary>
350 public enum BundleScope 350 public enum BundleScope
351 { 351 {
352 /// <summary> 352 /// <summary>
353 /// Let Burn choose the scope. Per-user-or-machine packages will be 353 /// Let Burn choose the scope. Per-user-or-machine packages will be
354 /// planned as per-user packages. Per-machine-or-user packages will be
354 /// planned as per-machine packages. 355 /// planned as per-machine packages.
355 /// </summary> 356 /// </summary>
356 Default, 357 Default,
357 358
358 /// <summary> 359 /// <summary>
359 /// Set per-machine scope for per-user-or-machine packages. 360 /// Set per-machine scope for dual-purpose packages.
360 /// </summary> 361 /// </summary>
361 PerMachine, 362 PerMachine,
362 363
363 /// <summary> 364 /// <summary>
364 /// Set per-user scope for per-user-or-machine packages. 365 /// Set per-user scope for dual-purpose packages.
365 /// </summary> 366 /// </summary>
366 PerUser, 367 PerUser,
367 } 368 }
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index dc0af8ce..5483e46f 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -469,7 +469,7 @@ extern "C" HRESULT CorePlan(
469 pEngineState->plan.fDisableRollback = pEngineState->fDisableRollback || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pEngineState->plan.action; 469 pEngineState->plan.fDisableRollback = pEngineState->fDisableRollback || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pEngineState->plan.action;
470 pEngineState->plan.fPlanPackageCacheRollback = BOOTSTRAPPER_REGISTRATION_TYPE_NONE == pEngineState->registration.detectedRegistrationType; 470 pEngineState->plan.fPlanPackageCacheRollback = BOOTSTRAPPER_REGISTRATION_TYPE_NONE == pEngineState->registration.detectedRegistrationType;
471 471
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);
473 ExitOnFailure(hr, "Failed to determine packages and bundle scope."); 473 ExitOnFailure(hr, "Failed to determine packages and bundle scope.");
474 474
475 if (BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE_OR_PER_USER == pEngineState->registration.scope || BOOTSTRAPPER_PACKAGE_SCOPE_PER_USER_OR_PER_MACHINE == pEngineState->registration.scope) 475 if (BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE_OR_PER_USER == pEngineState->registration.scope || BOOTSTRAPPER_PACKAGE_SCOPE_PER_USER_OR_PER_MACHINE == pEngineState->registration.scope)
diff --git a/src/burn/engine/core.h b/src/burn/engine/core.h
index 520fdcd5..2ad9111f 100644
--- a/src/burn/engine/core.h
+++ b/src/burn/engine/core.h
@@ -235,11 +235,6 @@ HRESULT CoreSerializeEngineState(
235HRESULT CoreQueryRegistration( 235HRESULT CoreQueryRegistration(
236 __in BURN_ENGINE_STATE* pEngineState 236 __in BURN_ENGINE_STATE* pEngineState
237 ); 237 );
238//HRESULT CoreDeserializeEngineState(
239// __in BURN_ENGINE_STATE* pEngineState,
240// __in_bcount(cbBuffer) BYTE* pbBuffer,
241// __in SIZE_T cbBuffer
242// );
243HRESULT CoreDetect( 238HRESULT CoreDetect(
244 __in BURN_ENGINE_STATE* pEngineState, 239 __in BURN_ENGINE_STATE* pEngineState,
245 __in_opt HWND hwndParent 240 __in_opt HWND hwndParent
diff --git a/src/burn/engine/engine.mc b/src/burn/engine/engine.mc
index f7ec0359..edafef97 100644
--- a/src/burn/engine/engine.mc
+++ b/src/burn/engine/engine.mc
@@ -418,7 +418,14 @@ MessageId=227
418Severity=Success 418Severity=Success
419SymbolicName=MSG_PLAN_INSTALLED_SCOPE 419SymbolicName=MSG_PLAN_INSTALLED_SCOPE
420Language=English 420Language=English
421Bundle was already installed with scope: %1!hs! 421Bundle was already installed with scope: %1!hs!. Scope cannot change during maintenance.
422.
423
424MessageId=228
425Severity=Success
426SymbolicName=MSG_PLAN_UPGRADE_SCOPE
427Language=English
428Upgraded bundle %1!ls! was already installed with scope: %2!hs!. Scope cannot change during upgrade.
422. 429.
423 430
424MessageId=201 431MessageId=201
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp
index 889ad68c..2257b28c 100644
--- a/src/burn/engine/plan.cpp
+++ b/src/burn/engine/plan.cpp
@@ -144,6 +144,12 @@ static BOOL ForceCache(
144 __in BURN_PLAN* pPlan, 144 __in BURN_PLAN* pPlan,
145 __in BURN_PACKAGE* pPackage 145 __in BURN_PACKAGE* pPackage
146 ); 146 );
147static HRESULT GetUpgradedBundleScope(
148 __in DWORD cRelatedBundles,
149 __in BURN_RELATED_BUNDLE* rgRelatedBundles,
150 __in_z LPCWSTR wzUpgradeCode,
151 __inout BOOTSTRAPPER_SCOPE* pScope
152);
147 153
148// function definitions 154// function definitions
149 155
@@ -823,6 +829,9 @@ LExit:
823extern "C" HRESULT PlanPackagesAndBundleScope( 829extern "C" HRESULT PlanPackagesAndBundleScope(
824 __in BURN_PACKAGE* rgPackages, 830 __in BURN_PACKAGE* rgPackages,
825 __in DWORD cPackages, 831 __in DWORD cPackages,
832 __in_z LPCWSTR wzUpgradeCode,
833 __in BURN_RELATED_BUNDLE* rgRelatedBundles,
834 __in DWORD cRelatedBundles,
826 __in BOOTSTRAPPER_SCOPE scope, 835 __in BOOTSTRAPPER_SCOPE scope,
827 __in BOOTSTRAPPER_PACKAGE_SCOPE authoredScope, 836 __in BOOTSTRAPPER_PACKAGE_SCOPE authoredScope,
828 __in BOOTSTRAPPER_SCOPE commandLineScope, 837 __in BOOTSTRAPPER_SCOPE commandLineScope,
@@ -855,7 +864,11 @@ extern "C" HRESULT PlanPackagesAndBundleScope(
855 } 864 }
856 } 865 }
857 866
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)
859 { 872 {
860 scope = detectedScope; 873 scope = detectedScope;
861 874
@@ -888,6 +901,48 @@ extern "C" HRESULT PlanPackagesAndBundleScope(
888} 901}
889 902
890 903
904static 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 if (CSTR_EQUAL == ::CompareStringOrdinal(wzRelatedUpgradeCode, -1, wzUpgradeCode, -1, TRUE))
927 {
928 *pScope = pRelatedBundle->detectedScope;
929
930 LogId(REPORT_STANDARD, MSG_PLAN_UPGRADE_SCOPE, pRelatedBundle->package.Bundle.sczBundleCode, LoggingBundleScopeToString(*pScope));
931
932 ExitFunction();
933 }
934 }
935 }
936 }
937
938 // No upgrade codes or none match, which is fine. But note it via S_FALSE
939 // so we can distinguish the upgrade case from the maintenance case.
940 hr = S_FALSE;
941
942LExit:
943 return hr;
944}
945
891static HRESULT PlanPackagesHelper( 946static HRESULT PlanPackagesHelper(
892 __in BURN_PACKAGE* rgPackages, 947 __in BURN_PACKAGE* rgPackages,
893 __in DWORD cPackages, 948 __in DWORD cPackages,
diff --git a/src/burn/engine/plan.h b/src/burn/engine/plan.h
index f9996ac0..09918440 100644
--- a/src/burn/engine/plan.h
+++ b/src/burn/engine/plan.h
@@ -485,6 +485,9 @@ void PlanDump(
485HRESULT PlanPackagesAndBundleScope( 485HRESULT PlanPackagesAndBundleScope(
486 __in BURN_PACKAGE* rgPackages, 486 __in BURN_PACKAGE* rgPackages,
487 __in DWORD cPackages, 487 __in DWORD cPackages,
488 __in_z LPCWSTR wzUpgradeCode,
489 __in BURN_RELATED_BUNDLE* rgRelatedBundles,
490 __in DWORD cRelatedBundles,
488 __in BOOTSTRAPPER_SCOPE scope, 491 __in BOOTSTRAPPER_SCOPE scope,
489 __in BOOTSTRAPPER_PACKAGE_SCOPE authoredScope, 492 __in BOOTSTRAPPER_PACKAGE_SCOPE authoredScope,
490 __in BOOTSTRAPPER_SCOPE commandLineScope, 493 __in BOOTSTRAPPER_SCOPE commandLineScope,
diff --git a/src/burn/engine/registration.cpp b/src/burn/engine/registration.cpp
index e588bef0..7c9ca182 100644
--- a/src/burn/engine/registration.cpp
+++ b/src/burn/engine/registration.cpp
@@ -29,9 +29,10 @@ const LPCWSTR REGISTRY_BUNDLE_UNINSTALL_STRING = L"UninstallString";
29const LPCWSTR REGISTRY_BUNDLE_RESUME_COMMAND_LINE = L"BundleResumeCommandLine"; 29const LPCWSTR REGISTRY_BUNDLE_RESUME_COMMAND_LINE = L"BundleResumeCommandLine";
30const LPCWSTR REGISTRY_BUNDLE_VERSION_MAJOR = L"VersionMajor"; 30const LPCWSTR REGISTRY_BUNDLE_VERSION_MAJOR = L"VersionMajor";
31const LPCWSTR REGISTRY_BUNDLE_VERSION_MINOR = L"VersionMinor"; 31const LPCWSTR REGISTRY_BUNDLE_VERSION_MINOR = L"VersionMinor";
32const LPCWSTR REGISTRY_BUNDLE_SCOPE = L"BundleScope";
33const LPCWSTR SWIDTAG_FOLDER = L"swidtag"; 32const LPCWSTR SWIDTAG_FOLDER = L"swidtag";
34const LPCWSTR REGISTRY_BUNDLE_VARIABLE_KEY = L"variables"; 33const LPCWSTR REGISTRY_BUNDLE_VARIABLE_KEY = L"variables";
34const LPCWSTR REGISTRY_BUNDLE_INSTALLED = L"Installed";
35
35 36
36// internal function declarations 37// internal function declarations
37 38
@@ -146,6 +147,10 @@ extern "C" HRESULT RegistrationParseFromXml(
146 hr = XmlGetAttributeEx(pixnRegistrationNode, L"Tag", &pRegistration->sczTag); 147 hr = XmlGetAttributeEx(pixnRegistrationNode, L"Tag", &pRegistration->sczTag);
147 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Tag."); 148 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Tag.");
148 149
150 // @PrimaryUpgradeCode
151 hr = XmlGetAttributeEx(pixnRegistrationNode, L"PrimaryUpgradeCode", &pRegistration->sczPrimaryUpgradeCode);
152 ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @PrimaryUpgradeCode.");
153
149 hr = BundlePackageEngineParseRelatedCodes(pixnBundle, &pRegistration->rgsczDetectCodes, &pRegistration->cDetectCodes, &pRegistration->rgsczUpgradeCodes, &pRegistration->cUpgradeCodes, &pRegistration->rgsczAddonCodes, &pRegistration->cAddonCodes, &pRegistration->rgsczPatchCodes, &pRegistration->cPatchCodes); 154 hr = BundlePackageEngineParseRelatedCodes(pixnBundle, &pRegistration->rgsczDetectCodes, &pRegistration->cDetectCodes, &pRegistration->rgsczUpgradeCodes, &pRegistration->cUpgradeCodes, &pRegistration->rgsczAddonCodes, &pRegistration->cAddonCodes, &pRegistration->rgsczPatchCodes, &pRegistration->cPatchCodes);
150 ExitOnFailure(hr, "Failed to parse related bundles"); 155 ExitOnFailure(hr, "Failed to parse related bundles");
151 156
@@ -327,7 +332,8 @@ extern "C" void RegistrationUninitialize(
327{ 332{
328 ReleaseStr(pRegistration->sczCode); 333 ReleaseStr(pRegistration->sczCode);
329 ReleaseStr(pRegistration->sczTag); 334 ReleaseStr(pRegistration->sczTag);
330 335 ReleaseStr(pRegistration->sczPrimaryUpgradeCode);
336
331 for (DWORD i = 0; i < pRegistration->cDetectCodes; ++i) 337 for (DWORD i = 0; i < pRegistration->cDetectCodes; ++i)
332 { 338 {
333 ReleaseStr(pRegistration->rgsczDetectCodes[i]); 339 ReleaseStr(pRegistration->rgsczDetectCodes[i]);
@@ -666,8 +672,8 @@ extern "C" HRESULT RegistrationSessionBegin(
666 hr = RegWriteStringFormatted(hkRegistration, REGISTRY_BUNDLE_DISPLAY_ICON, L"%s,0", pRegistration->sczCacheExecutablePath); 672 hr = RegWriteStringFormatted(hkRegistration, REGISTRY_BUNDLE_DISPLAY_ICON, L"%s,0", pRegistration->sczCacheExecutablePath);
667 ExitOnFailure(hr, "Failed to write %ls value.", REGISTRY_BUNDLE_DISPLAY_ICON); 673 ExitOnFailure(hr, "Failed to write %ls value.", REGISTRY_BUNDLE_DISPLAY_ICON);
668 674
669 hr = RegWriteNumber(hkRegistration, REGISTRY_BUNDLE_SCOPE, pRegistration->fPerMachine ? BOOTSTRAPPER_SCOPE_PER_MACHINE : BOOTSTRAPPER_SCOPE_PER_USER); 675 hr = RegWriteNumber(hkRegistration, BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE, pRegistration->fPerMachine ? BOOTSTRAPPER_SCOPE_PER_MACHINE : BOOTSTRAPPER_SCOPE_PER_USER);
670 ExitOnFailure(hr, "Failed to write %ls value.", REGISTRY_BUNDLE_SCOPE); 676 ExitOnFailure(hr, "Failed to write %ls value.", BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE);
671 677
672 // update display name 678 // update display name
673 hr = UpdateBundleNameRegistration(pRegistration, pVariables, hkRegistration, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS == registrationType); 679 hr = UpdateBundleNameRegistration(pRegistration, pVariables, hkRegistration, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS == registrationType);
@@ -1780,8 +1786,8 @@ static HRESULT DetectInstalled(
1780 1786
1781 pRegistration->detectedRegistrationType = (1 == dwInstalled) ? BOOTSTRAPPER_REGISTRATION_TYPE_FULL : BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS; 1787 pRegistration->detectedRegistrationType = (1 == dwInstalled) ? BOOTSTRAPPER_REGISTRATION_TYPE_FULL : BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS;
1782 1788
1783 hr = RegReadNumber(hkRegistration, REGISTRY_BUNDLE_SCOPE, &dwScope); 1789 hr = RegReadNumber(hkRegistration, BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE, &dwScope);
1784 ExitOnFailure(hr, "Failed to read registration %ls@%ls.", pRegistration->sczRegistrationKey, REGISTRY_BUNDLE_SCOPE); 1790 ExitOnFailure(hr, "Failed to read registration %ls@%ls.", pRegistration->sczRegistrationKey, BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE);
1785 1791
1786 pRegistration->detectedScope = static_cast<BOOTSTRAPPER_SCOPE>(dwScope); 1792 pRegistration->detectedScope = static_cast<BOOTSTRAPPER_SCOPE>(dwScope);
1787 } 1793 }
diff --git a/src/burn/engine/registration.h b/src/burn/engine/registration.h
index f340999a..97c6951b 100644
--- a/src/burn/engine/registration.h
+++ b/src/burn/engine/registration.h
@@ -21,8 +21,7 @@ const LPCWSTR BURN_REGISTRATION_REGISTRY_ENGINE_VERSION = L"EngineVersion";
21const LPCWSTR BURN_REGISTRATION_REGISTRY_ENGINE_PROTOCOL_VERSION = L"EngineProtocolVersion"; 21const LPCWSTR BURN_REGISTRATION_REGISTRY_ENGINE_PROTOCOL_VERSION = L"EngineProtocolVersion";
22const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY = L"BundleProviderKey"; 22const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY = L"BundleProviderKey";
23const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_TAG = L"BundleTag"; 23const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_TAG = L"BundleTag";
24 24const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE = L"BundleScope";
25const LPCWSTR REGISTRY_BUNDLE_INSTALLED = L"Installed";
26 25
27enum BURN_RESUME_MODE 26enum BURN_RESUME_MODE
28{ 27{
@@ -69,6 +68,7 @@ typedef struct _BURN_RELATED_BUNDLE
69 BOOTSTRAPPER_REQUEST_STATE defaultRequestedRestore; 68 BOOTSTRAPPER_REQUEST_STATE defaultRequestedRestore;
70 BOOTSTRAPPER_REQUEST_STATE requestedRestore; 69 BOOTSTRAPPER_REQUEST_STATE requestedRestore;
71 BOOTSTRAPPER_ACTION_STATE restore; 70 BOOTSTRAPPER_ACTION_STATE restore;
71 BOOTSTRAPPER_SCOPE detectedScope;
72} BURN_RELATED_BUNDLE; 72} BURN_RELATED_BUNDLE;
73 73
74typedef struct _BURN_RELATED_BUNDLES 74typedef struct _BURN_RELATED_BUNDLES
@@ -106,6 +106,7 @@ typedef struct _BURN_REGISTRATION
106 BOOTSTRAPPER_PACKAGE_SCOPE scope; 106 BOOTSTRAPPER_PACKAGE_SCOPE scope;
107 LPWSTR sczCode; 107 LPWSTR sczCode;
108 LPWSTR sczTag; 108 LPWSTR sczTag;
109 LPWSTR sczPrimaryUpgradeCode;
109 110
110 LPWSTR *rgsczDetectCodes; 111 LPWSTR *rgsczDetectCodes;
111 DWORD cDetectCodes; 112 DWORD cDetectCodes;
diff --git a/src/burn/engine/relatedbundle.cpp b/src/burn/engine/relatedbundle.cpp
index d0b97af0..166c4ae8 100644
--- a/src/burn/engine/relatedbundle.cpp
+++ b/src/burn/engine/relatedbundle.cpp
@@ -325,6 +325,7 @@ static HRESULT LoadRelatedBundleFromKey(
325 BOOL fExists = FALSE; 325 BOOL fExists = FALSE;
326 BURN_DEPENDENCY_PROVIDER dependencyProvider = { }; 326 BURN_DEPENDENCY_PROVIDER dependencyProvider = { };
327 BURN_DEPENDENCY_PROVIDER* pBundleDependencyProvider = NULL; 327 BURN_DEPENDENCY_PROVIDER* pBundleDependencyProvider = NULL;
328 DWORD dwScope = 0;
328 329
329 // Only support progress from engines that are compatible. 330 // Only support progress from engines that are compatible.
330 hr = RegReadNumber(hkBundleCode, BURN_REGISTRATION_REGISTRY_ENGINE_PROTOCOL_VERSION, &dwEngineProtocolVersion); 331 hr = RegReadNumber(hkBundleCode, BURN_REGISTRATION_REGISTRY_ENGINE_PROTOCOL_VERSION, &dwEngineProtocolVersion);
@@ -355,6 +356,11 @@ static HRESULT LoadRelatedBundleFromKey(
355 LogId(REPORT_WARNING, MSG_RELATED_PACKAGE_INVALID_VERSION, wzRelatedBundleCode, sczBundleVersion); 356 LogId(REPORT_WARNING, MSG_RELATED_PACKAGE_INVALID_VERSION, wzRelatedBundleCode, sczBundleVersion);
356 } 357 }
357 358
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
358 hr = RegReadString(hkBundleCode, BURN_REGISTRATION_REGISTRY_BUNDLE_CACHE_PATH, &sczCachePath); 364 hr = RegReadString(hkBundleCode, BURN_REGISTRATION_REGISTRY_BUNDLE_CACHE_PATH, &sczCachePath);
359 ExitOnFailure(hr, "Failed to read cache path from registry for bundle: %ls", wzRelatedBundleCode); 365 ExitOnFailure(hr, "Failed to read cache path from registry for bundle: %ls", wzRelatedBundleCode);
360 366
@@ -390,6 +396,12 @@ static HRESULT LoadRelatedBundleFromKey(
390 396
391 pRelatedBundle->detectRelationType = relationType; 397 pRelatedBundle->detectRelationType = relationType;
392 398
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
393 hr = PseudoBundleInitializeRelated(&pRelatedBundle->package, fSupportsBurnProtocol, fPerMachine, wzRelatedBundleCode, 405 hr = PseudoBundleInitializeRelated(&pRelatedBundle->package, fSupportsBurnProtocol, fPerMachine, wzRelatedBundleCode,
394#ifdef DEBUG 406#ifdef DEBUG
395 pRelatedBundle->detectRelationType, 407 pRelatedBundle->detectRelationType,
diff --git a/src/burn/test/BurnUnitTest/RelatedBundleTest.cpp b/src/burn/test/BurnUnitTest/RelatedBundleTest.cpp
index dcccc589..38c99121 100644
--- a/src/burn/test/BurnUnitTest/RelatedBundleTest.cpp
+++ b/src/burn/test/BurnUnitTest/RelatedBundleTest.cpp
@@ -178,6 +178,9 @@ namespace Bootstrapper
178 178
179 hr = RegWriteString(hkRegistration, BURN_REGISTRATION_REGISTRY_BUNDLE_VERSION, wzVersion); 179 hr = RegWriteString(hkRegistration, BURN_REGISTRATION_REGISTRY_BUNDLE_VERSION, wzVersion);
180 NativeAssert::Succeeded(hr, "Failed to write %ls value.", BURN_REGISTRATION_REGISTRY_BUNDLE_VERSION); 180 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);
181 } 184 }
182 finally 185 finally
183 { 186 {
diff --git a/src/test/burn/TestData/ConfigurableScopeTests/AllPuomBundle/AllPuomBundleTestBA.wixproj b/src/test/burn/TestData/ConfigurableScopeTests/AllPuomBundle/AllPuomBundleTestBA.wixproj
index 30d850d4..258d7b42 100644
--- a/src/test/burn/TestData/ConfigurableScopeTests/AllPuomBundle/AllPuomBundleTestBA.wixproj
+++ b/src/test/burn/TestData/ConfigurableScopeTests/AllPuomBundle/AllPuomBundleTestBA.wixproj
@@ -1,6 +1,7 @@
1<Project Sdk="WixToolset.Sdk"> 1<Project Sdk="WixToolset.Sdk">
2 <PropertyGroup> 2 <PropertyGroup>
3 <BA>TestBA</BA> 3 <BA>TestBA</BA>
4 <DefineConstants>$(DefineConstants);Version=1.0.0.0</DefineConstants>
4 </PropertyGroup> 5 </PropertyGroup>
5 6
6 <Import Project="Bundle.props" /> 7 <Import Project="Bundle.props" />
diff --git a/src/test/burn/TestData/ConfigurableScopeTests/AllPuomBundle/AllPuomBundleTestBAv2.wixproj b/src/test/burn/TestData/ConfigurableScopeTests/AllPuomBundle/AllPuomBundleTestBAv2.wixproj
new file mode 100644
index 00000000..0daacca8
--- /dev/null
+++ b/src/test/burn/TestData/ConfigurableScopeTests/AllPuomBundle/AllPuomBundleTestBAv2.wixproj
@@ -0,0 +1,8 @@
1<Project Sdk="WixToolset.Sdk">
2 <PropertyGroup>
3 <BA>TestBA</BA>
4 <DefineConstants>$(DefineConstants);Version=2.0.0.0</DefineConstants>
5 </PropertyGroup>
6
7 <Import Project="Bundle.props" />
8</Project> \ No newline at end of file
diff --git a/src/test/burn/TestData/ConfigurableScopeTests/AllPuomBundle/AllPuomBundleWixStdBA.wixproj b/src/test/burn/TestData/ConfigurableScopeTests/AllPuomBundle/AllPuomBundleWixStdBA.wixproj
index 56db1fdc..9ca5f8a3 100644
--- a/src/test/burn/TestData/ConfigurableScopeTests/AllPuomBundle/AllPuomBundleWixStdBA.wixproj
+++ b/src/test/burn/TestData/ConfigurableScopeTests/AllPuomBundle/AllPuomBundleWixStdBA.wixproj
@@ -1,6 +1,7 @@
1<Project Sdk="WixToolset.Sdk"> 1<Project Sdk="WixToolset.Sdk">
2 <PropertyGroup> 2 <PropertyGroup>
3 <BA>WixStdBA</BA> 3 <BA>WixStdBA</BA>
4 <DefineConstants>$(DefineConstants);Version=1.0.0.0</DefineConstants>
4 </PropertyGroup> 5 </PropertyGroup>
5 6
6 <Import Project="Bundle.props" /> 7 <Import Project="Bundle.props" />
diff --git a/src/test/burn/TestData/ConfigurableScopeTests/AllPuomBundle/Bundle.wxs b/src/test/burn/TestData/ConfigurableScopeTests/AllPuomBundle/Bundle.wxs
index 4cb11a98..8e1a881a 100644
--- a/src/test/burn/TestData/ConfigurableScopeTests/AllPuomBundle/Bundle.wxs
+++ b/src/test/burn/TestData/ConfigurableScopeTests/AllPuomBundle/Bundle.wxs
@@ -1,5 +1,5 @@
1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal"> 1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
2 <Bundle Id="AllPuomBundle$(BA)" Name="AllPuomBundle$(BA)" Manufacturer="Acme" Version="1.0.0.0"> 2 <Bundle Id="AllPuomBundle$(BA)" Name="AllPuomBundle$(BA)" Manufacturer="Acme" Version="$(Version)">
3 <?if $(BA) = "WixStdBA"?> 3 <?if $(BA) = "WixStdBA"?>
4 <BootstrapperApplication> 4 <BootstrapperApplication>
5 <bal:WixStandardBootstrapperApplication LicenseUrl="https://www.example.com/license" Theme="hyperlinkLicense" /> 5 <bal:WixStandardBootstrapperApplication LicenseUrl="https://www.example.com/license" Theme="hyperlinkLicense" />
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/ConfigurableScopeTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/ConfigurableScopeTests.cs
index 8b31ac00..bb1381b3 100644
--- a/src/test/burn/WixToolsetTest.BurnE2E/ConfigurableScopeTests.cs
+++ b/src/test/burn/WixToolsetTest.BurnE2E/ConfigurableScopeTests.cs
@@ -96,6 +96,54 @@ namespace WixToolsetTest.BurnE2E
96 } 96 }
97 97
98 [RuntimeFact] 98 [RuntimeFact]
99 public void BundleUpgradeIsLockedToFirstBundlesScope()
100 {
101 var testBAController = this.CreateTestBAController();
102 testBAController.SetBundleScope(BundleScope.Default);
103
104 var bundle = this.CreateBundleInstaller("AllPuomBundleTestBA");
105 var log = bundle.Install();
106
107 bundle.VerifyRegisteredAndInPackageCache(plannedPerMachine: false);
108
109 Assert.True(LogVerifier.MessageInLogFile(log, "Plan begin, 3 packages, action: Install, planned scope: Default"));
110
111 log = bundle.Repair();
112 Assert.True(LogVerifier.MessageInLogFile(log, "Bundle was already installed with scope: PerUser. Scope cannot change during maintenance."));
113
114 var bundleV2 = this.CreateBundleInstaller("AllPuomBundleTestBAv2");
115 testBAController.SetBundleScope(BundleScope.PerMachine);
116 log = bundleV2.Install();
117 Assert.True(LogVerifier.MessageInLogFileRegex(log, @"Upgraded bundle [{][0-9A-Fa-f\-]{36}[}] was already installed with scope: PerUser\. Scope cannot change during upgrade\."));
118
119 bundleV2.Uninstall();
120 bundleV2.VerifyUnregisteredAndRemovedFromPackageCache(plannedPerMachine: false);
121 bundle.VerifyUnregisteredAndRemovedFromPackageCache(plannedPerMachine: false);
122 }
123
124 [RuntimeFact]
125 public void BundleUpgradeWithSameScopeSucceeds()
126 {
127 var bundle = this.CreateBundleInstaller("AllPuomBundleTestBA");
128 var log = bundle.Install();
129
130 bundle.VerifyRegisteredAndInPackageCache(plannedPerMachine: false);
131
132 Assert.True(LogVerifier.MessageInLogFile(log, "Plan begin, 3 packages, action: Install, planned scope: Default"));
133
134 log = bundle.Repair();
135 Assert.True(LogVerifier.MessageInLogFile(log, "Bundle was already installed with scope: PerUser. Scope cannot change during maintenance."));
136
137 var bundleV2 = this.CreateBundleInstaller("AllPuomBundleTestBAv2");
138 log = bundleV2.Install();
139 Assert.True(LogVerifier.MessageInLogFileRegex(log, @"Upgraded bundle [{][0-9A-Fa-f\-]{36}[}] was already installed with scope: PerUser\. Scope cannot change during upgrade\."));
140
141 bundleV2.Uninstall();
142 bundleV2.VerifyUnregisteredAndRemovedFromPackageCache(plannedPerMachine: false);
143 bundle.VerifyUnregisteredAndRemovedFromPackageCache(plannedPerMachine: false);
144 }
145
146 [RuntimeFact]
99 public void PMOU_Bundle_Default_Plan_Installs_PerMachine() 147 public void PMOU_Bundle_Default_Plan_Installs_PerMachine()
100 { 148 {
101 var testBAController = this.CreateTestBAController(); 149 var testBAController = this.CreateTestBAController();
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs
index a1ca32ac..d7f90f1e 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs
@@ -227,6 +227,7 @@ namespace WixToolset.Core.Burn.Bundles
227 writer.WriteAttributeString("Tag", this.BundleSymbol.Tag); 227 writer.WriteAttributeString("Tag", this.BundleSymbol.Tag);
228 writer.WriteAttributeString("Version", this.BundleSymbol.Version); 228 writer.WriteAttributeString("Version", this.BundleSymbol.Version);
229 writer.WriteAttributeString("ProviderKey", this.BundleSymbol.ProviderKey); 229 writer.WriteAttributeString("ProviderKey", this.BundleSymbol.ProviderKey);
230 writer.WriteAttributeString("PrimaryUpgradeCode", this.BundleSymbol.UpgradeCode);
230 231
231 writer.WriteStartElement("Arp"); 232 writer.WriteStartElement("Arp");
232 writer.WriteAttributeString("DisplayName", this.BundleSymbol.Name); 233 writer.WriteAttributeString("DisplayName", this.BundleSymbol.Name);
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/BundleFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/BundleFixture.cs
index 93aae7be..ef168f88 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/BundleFixture.cs
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/BundleFixture.cs
@@ -170,7 +170,7 @@ namespace WixToolsetTest.CoreIntegration
170 var registrationElements = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration"); 170 var registrationElements = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration");
171 WixAssert.CompareLineByLine(new[] 171 WixAssert.CompareLineByLine(new[]
172 { 172 {
173 $"<Registration Code='{bundleSymbol.BundleCode}' ExecutableName='test.exe' Scope='perMachine' Tag='' Version='1.0.0.0' ProviderKey='{bundleSymbol.BundleCode}'>" + 173 $"<Registration Code='{bundleSymbol.BundleCode}' ExecutableName='test.exe' Scope='perMachine' Tag='' Version='1.0.0.0' ProviderKey='{bundleSymbol.BundleCode}' PrimaryUpgradeCode='{bundleSymbol.UpgradeCode}'>" +
174 "<Arp DisplayName='~TestBundle' DisplayVersion='1.0.0.0' InProgressDisplayName='~InProgressTestBundle' Publisher='Example Corporation' />" + 174 "<Arp DisplayName='~TestBundle' DisplayVersion='1.0.0.0' InProgressDisplayName='~InProgressTestBundle' Publisher='Example Corporation' />" +
175 "</Registration>", 175 "</Registration>",
176 }, registrationElements); 176 }, registrationElements);
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs
index 51fdac6f..fa787977 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs
@@ -50,7 +50,7 @@ namespace WixToolsetTest.CoreIntegration
50 50
51 Assert.True(File.Exists(chainBundlePath)); 51 Assert.True(File.Exists(chainBundlePath));
52 52
53 var chainBundleId = GetBundleCodeFromWixpdb(chainPdbPath); 53 var (chainBundleId, _) = GetBundleCodesFromWixpdb(chainPdbPath);
54 54
55 // parent.exe 55 // parent.exe
56 result = WixRunner.Execute(new[] 56 result = WixRunner.Execute(new[]
@@ -68,7 +68,7 @@ namespace WixToolsetTest.CoreIntegration
68 68
69 Assert.True(File.Exists(parentBundlePath)); 69 Assert.True(File.Exists(parentBundlePath));
70 70
71 var parentBundleId = GetBundleCodeFromWixpdb(parentPdbPath); 71 var (parentBundleId, parentUpgradeCode) = GetBundleCodesFromWixpdb(parentPdbPath);
72 72
73 var extractResult = BundleExtractor.ExtractBAContainer(null, parentBundlePath, parentBaFolderPath, extractFolderPath); 73 var extractResult = BundleExtractor.ExtractBAContainer(null, parentBundlePath, parentBaFolderPath, extractFolderPath);
74 extractResult.AssertSuccess(); 74 extractResult.AssertSuccess();
@@ -91,7 +91,7 @@ namespace WixToolsetTest.CoreIntegration
91 var registrations = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration"); 91 var registrations = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration");
92 WixAssert.CompareLineByLine(new[] 92 WixAssert.CompareLineByLine(new[]
93 { 93 {
94 $"<Registration BundleId='WixToolsetTest.TestBundle' Code='{parentBundleId}' ExecutableName='parent.exe' Scope='perMachine' Tag='' Version='1.0.1.0' ProviderKey='{parentBundleId}'>" + 94 $"<Registration BundleId='WixToolsetTest.TestBundle' Code='{parentBundleId}' ExecutableName='parent.exe' Scope='perMachine' Tag='' Version='1.0.1.0' ProviderKey='{parentBundleId}' PrimaryUpgradeCode='{parentUpgradeCode}'>" +
95 "<Arp DisplayName='BundlePackageBundle' DisplayVersion='1.0.1.0' Publisher='Example Corporation' />" + 95 "<Arp DisplayName='BundlePackageBundle' DisplayVersion='1.0.1.0' Publisher='Example Corporation' />" +
96 "</Registration>" 96 "</Registration>"
97 }, registrations); 97 }, registrations);
@@ -121,7 +121,7 @@ namespace WixToolsetTest.CoreIntegration
121 121
122 Assert.True(File.Exists(grandparentBundlePath)); 122 Assert.True(File.Exists(grandparentBundlePath));
123 123
124 var grandparentBundleId = GetBundleCodeFromWixpdb(grandparentPdbPath); 124 var (grandparentBundleId, grandparentUpgradeCode) = GetBundleCodesFromWixpdb(grandparentPdbPath);
125 125
126 var grandparentExtractResult = BundleExtractor.ExtractBAContainer(null, grandparentBundlePath, grandparentBaFolderPath, extractFolderPath); 126 var grandparentExtractResult = BundleExtractor.ExtractBAContainer(null, grandparentBundlePath, grandparentBaFolderPath, extractFolderPath);
127 grandparentExtractResult.AssertSuccess(); 127 grandparentExtractResult.AssertSuccess();
@@ -154,7 +154,7 @@ namespace WixToolsetTest.CoreIntegration
154 registrations = grandparentExtractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration"); 154 registrations = grandparentExtractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration");
155 WixAssert.CompareLineByLine(new[] 155 WixAssert.CompareLineByLine(new[]
156 { 156 {
157 $"<Registration BundleId='WixToolsetTest.TestBundle' Code='{grandparentBundleId}' ExecutableName='grandparent.exe' Scope='perMachine' Tag='' Version='1.0.2.0' ProviderKey='{grandparentBundleId}'>" + 157 $"<Registration BundleId='WixToolsetTest.TestBundle' Code='{grandparentBundleId}' ExecutableName='grandparent.exe' Scope='perMachine' Tag='' Version='1.0.2.0' ProviderKey='{grandparentBundleId}' PrimaryUpgradeCode='{grandparentUpgradeCode}'>" +
158 "<Arp DisplayName='PermanentBundlePackageBundle' DisplayVersion='1.0.2.0' Publisher='Example Corporation' />" + 158 "<Arp DisplayName='PermanentBundlePackageBundle' DisplayVersion='1.0.2.0' Publisher='Example Corporation' />" +
159 "</Registration>" 159 "</Registration>"
160 }, registrations); 160 }, registrations);
@@ -202,7 +202,7 @@ namespace WixToolsetTest.CoreIntegration
202 202
203 var chainBundleId = "{216BDA7F-74BD-45E8-957B-500552F05629}"; 203 var chainBundleId = "{216BDA7F-74BD-45E8-957B-500552F05629}";
204 204
205 var parentBundleId = GetBundleCodeFromWixpdb(parentPdbPath); 205 var (parentBundleId, parentUpgradeCode) = GetBundleCodesFromWixpdb(parentPdbPath);
206 206
207 var extractResult = BundleExtractor.ExtractBAContainer(null, parentBundlePath, parentBaFolderPath, extractFolderPath); 207 var extractResult = BundleExtractor.ExtractBAContainer(null, parentBundlePath, parentBaFolderPath, extractFolderPath);
208 extractResult.AssertSuccess(); 208 extractResult.AssertSuccess();
@@ -224,7 +224,7 @@ namespace WixToolsetTest.CoreIntegration
224 var registrations = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration"); 224 var registrations = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration");
225 WixAssert.CompareLineByLine(new[] 225 WixAssert.CompareLineByLine(new[]
226 { 226 {
227 $"<Registration BundleId='WixToolsetTest.TestBundle' Code='{parentBundleId}' ExecutableName='parent.exe' Scope='perMachine' Tag='' Version='1.0.1.0' ProviderKey='{parentBundleId}'>" + 227 $"<Registration BundleId='WixToolsetTest.TestBundle' Code='{parentBundleId}' ExecutableName='parent.exe' Scope='perMachine' Tag='' Version='1.0.1.0' ProviderKey='{parentBundleId}' PrimaryUpgradeCode='{parentUpgradeCode}'>" +
228 "<Arp DisplayName='RemoteBundlePackageBundle' DisplayVersion='1.0.1.0' Publisher='Example Corporation' />" + 228 "<Arp DisplayName='RemoteBundlePackageBundle' DisplayVersion='1.0.1.0' Publisher='Example Corporation' />" +
229 "</Registration>" 229 "</Registration>"
230 }, registrations); 230 }, registrations);
@@ -280,7 +280,7 @@ namespace WixToolsetTest.CoreIntegration
280 280
281 Assert.True(File.Exists(parentBundlePath)); 281 Assert.True(File.Exists(parentBundlePath));
282 282
283 var parentBundleId = GetBundleCodeFromWixpdb(parentPdbPath); 283 var (parentBundleId, parentUpgradeCode) = GetBundleCodesFromWixpdb(parentPdbPath);
284 284
285 var extractResult = BundleExtractor.ExtractBAContainer(null, parentBundlePath, baFolderPath, extractFolderPath); 285 var extractResult = BundleExtractor.ExtractBAContainer(null, parentBundlePath, baFolderPath, extractFolderPath);
286 extractResult.AssertSuccess(); 286 extractResult.AssertSuccess();
@@ -302,7 +302,7 @@ namespace WixToolsetTest.CoreIntegration
302 var registrations = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration"); 302 var registrations = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration");
303 WixAssert.CompareLineByLine(new[] 303 WixAssert.CompareLineByLine(new[]
304 { 304 {
305 $"<Registration Code='{parentBundleId}' ExecutableName='parent.exe' Scope='perMachine' Tag='' Version='1.1.1.1' ProviderKey='{parentBundleId}'>" + 305 $"<Registration Code='{parentBundleId}' ExecutableName='parent.exe' Scope='perMachine' Tag='' Version='1.1.1.1' ProviderKey='{parentBundleId}' PrimaryUpgradeCode='{parentUpgradeCode}'>" +
306 "<Arp DisplayName='V3BundlePackageBundle' DisplayVersion='1.1.1.1' Publisher='Example Corporation' />" + 306 "<Arp DisplayName='V3BundlePackageBundle' DisplayVersion='1.1.1.1' Publisher='Example Corporation' />" +
307 "</Registration>" 307 "</Registration>"
308 }, registrations); 308 }, registrations);
@@ -364,7 +364,7 @@ namespace WixToolsetTest.CoreIntegration
364 364
365 result.AssertSuccess(); 365 result.AssertSuccess();
366 366
367 var bundleId = GetBundleCodeFromWixpdb(bundlePdbPath); 367 var (bundleId, _) = GetBundleCodesFromWixpdb(bundlePdbPath);
368 368
369 var consumingBundleIntermediateFolder = Path.Combine(baseFolder, "obj", "bundle2"); 369 var consumingBundleIntermediateFolder = Path.Combine(baseFolder, "obj", "bundle2");
370 var consumingBundleBinFolder = Path.Combine(baseFolder, "bin", "bundle2"); 370 var consumingBundleBinFolder = Path.Combine(baseFolder, "bin", "bundle2");
@@ -383,7 +383,7 @@ namespace WixToolsetTest.CoreIntegration
383 383
384 result.AssertSuccess(); 384 result.AssertSuccess();
385 385
386 var bundle2Id = GetBundleCodeFromWixpdb(consumingBundlePdbPath); 386 var (bundle2Id, bundle2UpgradeCode) = GetBundleCodesFromWixpdb(consumingBundlePdbPath);
387 387
388 var parentBaFolderPath = Path.Combine(baseFolder, "parentba"); 388 var parentBaFolderPath = Path.Combine(baseFolder, "parentba");
389 var grandparentBaFolderPath = Path.Combine(baseFolder, "grandparentba"); 389 var grandparentBaFolderPath = Path.Combine(baseFolder, "grandparentba");
@@ -409,7 +409,7 @@ namespace WixToolsetTest.CoreIntegration
409 var registrations = bundle2ExtractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration"); 409 var registrations = bundle2ExtractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration");
410 WixAssert.CompareLineByLine(new[] 410 WixAssert.CompareLineByLine(new[]
411 { 411 {
412 $"<Registration BundleId='WixToolsetTest.PerUserOrMachineBundlePackage' Code='{bundle2Id}' ExecutableName='PerUserOrMachineBundlePackage.exe' Scope='perUserOrMachine' Tag='' Version='1.0.2.0' ProviderKey='{bundle2Id}'>" + 412 $"<Registration BundleId='WixToolsetTest.PerUserOrMachineBundlePackage' Code='{bundle2Id}' ExecutableName='PerUserOrMachineBundlePackage.exe' Scope='perUserOrMachine' Tag='' Version='1.0.2.0' ProviderKey='{bundle2Id}' PrimaryUpgradeCode='{bundle2UpgradeCode}'>" +
413 "<Arp DisplayName='PerUserOrMachineBundlePackage' DisplayVersion='1.0.2.0' Publisher='Example Corporation' />" + 413 "<Arp DisplayName='PerUserOrMachineBundlePackage' DisplayVersion='1.0.2.0' Publisher='Example Corporation' />" +
414 "</Registration>" 414 "</Registration>"
415 }, registrations); 415 }, registrations);
@@ -461,7 +461,7 @@ namespace WixToolsetTest.CoreIntegration
461 461
462 result.AssertSuccess(); 462 result.AssertSuccess();
463 463
464 var parentBundleId = GetBundleCodeFromWixpdb(bundlePdbPath); 464 var (parentBundleId, parentUpgradeCode) = GetBundleCodesFromWixpdb(bundlePdbPath);
465 465
466 var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath); 466 var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath);
467 extractResult.AssertSuccess(); 467 extractResult.AssertSuccess();
@@ -469,7 +469,7 @@ namespace WixToolsetTest.CoreIntegration
469 var registrations = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration"); 469 var registrations = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration");
470 WixAssert.CompareLineByLine(new[] 470 WixAssert.CompareLineByLine(new[]
471 { 471 {
472 $"<Registration BundleId='WixToolsetTest.TestBundle' Code='{parentBundleId}' ExecutableName='bundle.exe' Scope='perMachine' Tag='' Version='9.9' ProviderKey='{parentBundleId}'>" + 472 $"<Registration BundleId='WixToolsetTest.TestBundle' Code='{parentBundleId}' ExecutableName='bundle.exe' Scope='perMachine' Tag='' Version='9.9' ProviderKey='{parentBundleId}' PrimaryUpgradeCode='{parentUpgradeCode}'>" +
473 "<Arp DisplayName='All Users Bundle' DisplayVersion='9.9' Publisher='Example Corporation' />" + 473 "<Arp DisplayName='All Users Bundle' DisplayVersion='9.9' Publisher='Example Corporation' />" +
474 "</Registration>" 474 "</Registration>"
475 }, registrations); 475 }, registrations);
@@ -532,7 +532,7 @@ namespace WixToolsetTest.CoreIntegration
532 532
533 result.AssertSuccess(); 533 result.AssertSuccess();
534 534
535 var parentBundleId = GetBundleCodeFromWixpdb(bundlePdbPath); 535 var (parentBundleId, parentUpgradeCode) = GetBundleCodesFromWixpdb(bundlePdbPath);
536 536
537 var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath); 537 var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath);
538 extractResult.AssertSuccess(); 538 extractResult.AssertSuccess();
@@ -540,7 +540,7 @@ namespace WixToolsetTest.CoreIntegration
540 var registrations = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration"); 540 var registrations = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration");
541 WixAssert.CompareLineByLine(new[] 541 WixAssert.CompareLineByLine(new[]
542 { 542 {
543 $"<Registration BundleId='WixToolsetTest.PerUserBundle' Code='{parentBundleId}' ExecutableName='bundle.exe' Scope='perUser' Tag='' Version='9.9' ProviderKey='{parentBundleId}'>" + 543 $"<Registration BundleId='WixToolsetTest.PerUserBundle' Code='{parentBundleId}' ExecutableName='bundle.exe' Scope='perUser' Tag='' Version='9.9' ProviderKey='{parentBundleId}' PrimaryUpgradeCode='{parentUpgradeCode}'>" +
544 "<Arp DisplayName='Per-User Bundle' DisplayVersion='9.9' Publisher='Example Corporation' />" + 544 "<Arp DisplayName='Per-User Bundle' DisplayVersion='9.9' Publisher='Example Corporation' />" +
545 "</Registration>" 545 "</Registration>"
546 }, registrations); 546 }, registrations);
@@ -603,7 +603,7 @@ namespace WixToolsetTest.CoreIntegration
603 603
604 result.AssertSuccess(); 604 result.AssertSuccess();
605 605
606 var parentBundleId = GetBundleCodeFromWixpdb(bundlePdbPath); 606 var (parentBundleId, parentUpgradeCode) = GetBundleCodesFromWixpdb(bundlePdbPath);
607 607
608 var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath); 608 var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath);
609 extractResult.AssertSuccess(); 609 extractResult.AssertSuccess();
@@ -611,7 +611,7 @@ namespace WixToolsetTest.CoreIntegration
611 var registrations = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration"); 611 var registrations = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration");
612 WixAssert.CompareLineByLine(new[] 612 WixAssert.CompareLineByLine(new[]
613 { 613 {
614 $"<Registration BundleId='WixToolsetTest.PerUserOrMachineBundle' Code='{parentBundleId}' ExecutableName='bundle.exe' Scope='perUserOrMachine' Tag='' Version='9.9' ProviderKey='{parentBundleId}'>" + 614 $"<Registration BundleId='WixToolsetTest.PerUserOrMachineBundle' Code='{parentBundleId}' ExecutableName='bundle.exe' Scope='perUserOrMachine' Tag='' Version='9.9' ProviderKey='{parentBundleId}' PrimaryUpgradeCode='{parentUpgradeCode}'>" +
615 "<Arp DisplayName='Per-user-or-machine Bundle' DisplayVersion='9.9' Publisher='Example Corporation' />" + 615 "<Arp DisplayName='Per-user-or-machine Bundle' DisplayVersion='9.9' Publisher='Example Corporation' />" +
616 "</Registration>" 616 "</Registration>"
617 }, registrations); 617 }, registrations);
@@ -629,16 +629,15 @@ namespace WixToolsetTest.CoreIntegration
629 } 629 }
630 } 630 }
631 631
632 private static string GetBundleCodeFromWixpdb(string bundlePdbPath) 632 private static (string, string) GetBundleCodesFromWixpdb(string bundlePdbPath)
633 { 633 {
634 using (var wixOutput = WixOutput.Read(bundlePdbPath)) 634 using (var wixOutput = WixOutput.Read(bundlePdbPath))
635 { 635 {
636
637 var intermediate = Intermediate.Load(wixOutput); 636 var intermediate = Intermediate.Load(wixOutput);
638 var section = intermediate.Sections.Single(); 637 var section = intermediate.Sections.Single();
639 638
640 var bundleSymbol = section.Symbols.OfType<WixBundleSymbol>().Single(); 639 var bundleSymbol = section.Symbols.OfType<WixBundleSymbol>().Single();
641 return bundleSymbol.BundleCode; 640 return (bundleSymbol.BundleCode, bundleSymbol.UpgradeCode);
642 } 641 }
643 } 642 }
644 } 643 }
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/DependencyExtensionFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/DependencyExtensionFixture.cs
index e26fda71..e684b7d9 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/DependencyExtensionFixture.cs
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/DependencyExtensionFixture.cs
@@ -144,7 +144,7 @@ namespace WixToolsetTest.CoreIntegration
144 var registration = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration", ignoreAttributesByElementName); 144 var registration = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Registration", ignoreAttributesByElementName);
145 WixAssert.CompareLineByLine(new string[] 145 WixAssert.CompareLineByLine(new string[]
146 { 146 {
147 "<Registration BundleId='WixToolsetTest.TestBundle' Code='*' ExecutableName='test.exe' Scope='perMachine' Tag='' Version='1.0.0.0' ProviderKey='MyProviderKey,v1.0'><Arp DisplayName='BurnBundle' DisplayVersion='1.0.0.0' Publisher='Example Corporation' /></Registration>", 147 "<Registration BundleId='WixToolsetTest.TestBundle' Code='*' ExecutableName='test.exe' Scope='perMachine' Tag='' Version='1.0.0.0' ProviderKey='MyProviderKey,v1.0' PrimaryUpgradeCode='{DFEA7F84-8F9D-5330-AAAE-7D849E650215}'><Arp DisplayName='BurnBundle' DisplayVersion='1.0.0.0' Publisher='Example Corporation' /></Registration>",
148 }, registration); 148 }, registration);
149 } 149 }
150 } 150 }