diff options
| author | Bob Arnson <bob@firegiant.com> | 2026-02-17 19:41:03 -0500 |
|---|---|---|
| committer | Bob Arnson <bob@firegiant.com> | 2026-02-17 19:48:12 -0500 |
| commit | 5658492062bf28ffb670ede15cbd1413bf1182d8 (patch) | |
| tree | 7e959881fdabed13359ff8cb78e68d9c74b81931 /src | |
| parent | de80ff1102a1b34e430bbc718fe65a42bab196cf (diff) | |
| download | wix-bob/BundleLockUpgradeScope.tar.gz wix-bob/BundleLockUpgradeScope.tar.bz2 wix-bob/BundleLockUpgradeScope.zip | |
Lock upgrade bundles to original bundle's scope.bob/BundleLockUpgradeScope
Fixes https://github.com/wixtoolset/issues/issues/9236
Diffstat (limited to 'src')
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( | |||
| 235 | HRESULT CoreQueryRegistration( | 235 | HRESULT 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 | // ); | ||
| 243 | HRESULT CoreDetect( | 238 | HRESULT 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 | |||
| 418 | Severity=Success | 418 | Severity=Success |
| 419 | SymbolicName=MSG_PLAN_INSTALLED_SCOPE | 419 | SymbolicName=MSG_PLAN_INSTALLED_SCOPE |
| 420 | Language=English | 420 | 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. | ||
| 422 | . | 429 | . |
| 423 | 430 | ||
| 424 | MessageId=201 | 431 | MessageId=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 | ); |
| 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 | ); | ||
| 147 | 153 | ||
| 148 | // function definitions | 154 | // function definitions |
| 149 | 155 | ||
| @@ -823,6 +829,9 @@ LExit: | |||
| 823 | extern "C" HRESULT PlanPackagesAndBundleScope( | 829 | extern "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 | ||
| 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 | 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 | |||
| 942 | LExit: | ||
| 943 | return hr; | ||
| 944 | } | ||
| 945 | |||
| 891 | static HRESULT PlanPackagesHelper( | 946 | static 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( | |||
| 485 | HRESULT PlanPackagesAndBundleScope( | 485 | HRESULT 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"; | |||
| 29 | const LPCWSTR REGISTRY_BUNDLE_RESUME_COMMAND_LINE = L"BundleResumeCommandLine"; | 29 | const LPCWSTR REGISTRY_BUNDLE_RESUME_COMMAND_LINE = L"BundleResumeCommandLine"; |
| 30 | const LPCWSTR REGISTRY_BUNDLE_VERSION_MAJOR = L"VersionMajor"; | 30 | const LPCWSTR REGISTRY_BUNDLE_VERSION_MAJOR = L"VersionMajor"; |
| 31 | const LPCWSTR REGISTRY_BUNDLE_VERSION_MINOR = L"VersionMinor"; | 31 | const LPCWSTR REGISTRY_BUNDLE_VERSION_MINOR = L"VersionMinor"; |
| 32 | const LPCWSTR REGISTRY_BUNDLE_SCOPE = L"BundleScope"; | ||
| 33 | const LPCWSTR SWIDTAG_FOLDER = L"swidtag"; | 32 | const LPCWSTR SWIDTAG_FOLDER = L"swidtag"; |
| 34 | const LPCWSTR REGISTRY_BUNDLE_VARIABLE_KEY = L"variables"; | 33 | const LPCWSTR REGISTRY_BUNDLE_VARIABLE_KEY = L"variables"; |
| 34 | const 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"; | |||
| 21 | const LPCWSTR BURN_REGISTRATION_REGISTRY_ENGINE_PROTOCOL_VERSION = L"EngineProtocolVersion"; | 21 | const LPCWSTR BURN_REGISTRATION_REGISTRY_ENGINE_PROTOCOL_VERSION = L"EngineProtocolVersion"; |
| 22 | const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY = L"BundleProviderKey"; | 22 | const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY = L"BundleProviderKey"; |
| 23 | const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_TAG = L"BundleTag"; | 23 | const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_TAG = L"BundleTag"; |
| 24 | 24 | const LPCWSTR BURN_REGISTRATION_REGISTRY_BUNDLE_SCOPE = L"BundleScope"; | |
| 25 | const LPCWSTR REGISTRY_BUNDLE_INSTALLED = L"Installed"; | ||
| 26 | 25 | ||
| 27 | enum BURN_RESUME_MODE | 26 | enum 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 | ||
| 74 | typedef struct _BURN_RELATED_BUNDLES | 74 | typedef 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 | } |
