diff options
Diffstat (limited to 'src')
8 files changed, 151 insertions, 4 deletions
diff --git a/src/burn/engine/msiengine.cpp b/src/burn/engine/msiengine.cpp index 86fb0d9d..a2a29bda 100644 --- a/src/burn/engine/msiengine.cpp +++ b/src/burn/engine/msiengine.cpp | |||
| @@ -50,7 +50,9 @@ static void RegisterSourceDirectory( | |||
| 50 | __in BURN_PACKAGE* pPackage, | 50 | __in BURN_PACKAGE* pPackage, |
| 51 | __in_z LPCWSTR wzCacheDirectory | 51 | __in_z LPCWSTR wzCacheDirectory |
| 52 | ); | 52 | ); |
| 53 | 53 | static BOOL PackageHasAppliedPatch( | |
| 54 | __in BURN_PACKAGE* pPackage | ||
| 55 | ); | ||
| 54 | 56 | ||
| 55 | // function definitions | 57 | // function definitions |
| 56 | 58 | ||
| @@ -904,7 +906,9 @@ extern "C" HRESULT MsiEnginePlanCalculatePackage( | |||
| 904 | else if ((BOOTSTRAPPER_REQUEST_STATE_ABSENT == pPackage->requested || BOOTSTRAPPER_REQUEST_STATE_CACHE == pPackage->requested) && | 906 | else if ((BOOTSTRAPPER_REQUEST_STATE_ABSENT == pPackage->requested || BOOTSTRAPPER_REQUEST_STATE_CACHE == pPackage->requested) && |
| 905 | !pPackage->fPermanent) // removing a package that should be removed. | 907 | !pPackage->fPermanent) // removing a package that should be removed. |
| 906 | { | 908 | { |
| 907 | execute = BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED == pPackage->currentState ? BOOTSTRAPPER_ACTION_STATE_NONE : BOOTSTRAPPER_ACTION_STATE_UNINSTALL; | 909 | BOOL fPackageHasAppliedPatch = PackageHasAppliedPatch(pPackage); |
| 910 | |||
| 911 | execute = BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED == pPackage->currentState && !fPackageHasAppliedPatch ? BOOTSTRAPPER_ACTION_STATE_NONE : BOOTSTRAPPER_ACTION_STATE_UNINSTALL; | ||
| 908 | } | 912 | } |
| 909 | else if (BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT == pPackage->requested) | 913 | else if (BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT == pPackage->requested) |
| 910 | { | 914 | { |
| @@ -2265,6 +2269,7 @@ LExit: | |||
| 2265 | ReleaseStr(sczMspPath); | 2269 | ReleaseStr(sczMspPath); |
| 2266 | ReleaseStr(sczCachedDirectory); | 2270 | ReleaseStr(sczCachedDirectory); |
| 2267 | ReleaseStr(sczPatches); | 2271 | ReleaseStr(sczPatches); |
| 2272 | |||
| 2268 | return hr; | 2273 | return hr; |
| 2269 | } | 2274 | } |
| 2270 | 2275 | ||
| @@ -2289,6 +2294,47 @@ static void RegisterSourceDirectory( | |||
| 2289 | 2294 | ||
| 2290 | LExit: | 2295 | LExit: |
| 2291 | ReleaseStr(sczMsiDirectory); | 2296 | ReleaseStr(sczMsiDirectory); |
| 2297 | } | ||
| 2298 | |||
| 2299 | static BOOL PackageHasAppliedPatch( | ||
| 2300 | __in BURN_PACKAGE* pPackage | ||
| 2301 | ) | ||
| 2302 | { | ||
| 2303 | HRESULT hr = S_OK; | ||
| 2304 | BOOL fPatched = FALSE; | ||
| 2305 | UINT er = ERROR_SUCCESS; | ||
| 2306 | DWORD iPatch = 0; | ||
| 2307 | WCHAR wzPatchCode[MAX_GUID_CHARS + 1] = {}; | ||
| 2308 | WCHAR wzTransforms[MAX_PATH] = {}; | ||
| 2309 | DWORD cchTransforms = countof(wzTransforms); | ||
| 2310 | WCHAR wzPatchState[2] = {}; | ||
| 2311 | DWORD cchPatchState = countof(wzPatchState); | ||
| 2312 | |||
| 2313 | for (;;) | ||
| 2314 | { | ||
| 2315 | er = ::MsiEnumPatchesW(pPackage->Msi.sczProductCode, iPatch, wzPatchCode, wzTransforms, &cchTransforms); | ||
| 2316 | |||
| 2317 | if (ERROR_NO_MORE_ITEMS == er) | ||
| 2318 | { | ||
| 2319 | ExitFunction(); | ||
| 2320 | } | ||
| 2321 | ExitOnWin32Error(er, hr, "Failed to enumerate patches for package %ls, product code %ls.", pPackage->sczId, pPackage->Msi.sczProductCode); | ||
| 2322 | |||
| 2323 | er = ::MsiGetPatchInfoExW(wzPatchCode, pPackage->Msi.sczProductCode, NULL, pPackage->fPerMachine ? MSIINSTALLCONTEXT_MACHINE : MSIINSTALLCONTEXT_USERUNMANAGED | ||
| 2324 | , INSTALLPROPERTY_PATCHSTATE, wzPatchState, &cchPatchState); | ||
| 2325 | ExitOnWin32Error(er, hr, "Failed to get patch info for patch %ls.", wzPatchCode); | ||
| 2326 | |||
| 2327 | if ('1' == wzPatchState[0]) | ||
| 2328 | { | ||
| 2329 | fPatched = TRUE; | ||
| 2330 | |||
| 2331 | ExitFunction(); | ||
| 2332 | } | ||
| 2333 | |||
| 2334 | ++iPatch; | ||
| 2335 | } | ||
| 2336 | |||
| 2337 | LExit: | ||
| 2338 | return fPatched; | ||
| 2292 | 2339 | ||
| 2293 | return; | ||
| 2294 | } | 2340 | } |
diff --git a/src/test/burn/TestData/SlipstreamTests/BundleAv1_0_1/BundleAv1_0_1.wixproj b/src/test/burn/TestData/SlipstreamTests/BundleAv1_0_1/BundleAv1_0_1.wixproj new file mode 100644 index 00000000..ac9cf71e --- /dev/null +++ b/src/test/burn/TestData/SlipstreamTests/BundleAv1_0_1/BundleAv1_0_1.wixproj | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | <Project Sdk="WixToolset.Sdk"> | ||
| 3 | <PropertyGroup> | ||
| 4 | <OutputType>Bundle</OutputType> | ||
| 5 | <UpgradeCode>{62C28DAF-A13E-4F55-ACA1-FB843630789C}</UpgradeCode> | ||
| 6 | </PropertyGroup> | ||
| 7 | <ItemGroup> | ||
| 8 | <Compile Include="..\..\Templates\Bundle.wxs" Link="Bundle.wxs" /> | ||
| 9 | </ItemGroup> | ||
| 10 | <ItemGroup> | ||
| 11 | <ProjectReference Include="..\PackageAv1\PackageAv1.wixproj" /> | ||
| 12 | <ProjectReference Include="..\PatchAMinor\PatchAMinor.wixproj" /> | ||
| 13 | <ProjectReference Include="..\..\TestBA\TestBAWixlib\testbawixlib.wixproj" /> | ||
| 14 | </ItemGroup> | ||
| 15 | <ItemGroup> | ||
| 16 | <PackageReference Include="WixToolset.BootstrapperApplications.wixext" /> | ||
| 17 | <PackageReference Include="WixToolset.NetFx.wixext" /> | ||
| 18 | </ItemGroup> | ||
| 19 | </Project> | ||
diff --git a/src/test/burn/TestData/SlipstreamTests/BundleAv1_0_1/BundleAv1_0_1.wxs b/src/test/burn/TestData/SlipstreamTests/BundleAv1_0_1/BundleAv1_0_1.wxs new file mode 100644 index 00000000..a14383d3 --- /dev/null +++ b/src/test/burn/TestData/SlipstreamTests/BundleAv1_0_1/BundleAv1_0_1.wxs | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
| 4 | <Fragment> | ||
| 5 | <PackageGroup Id="BundlePackages"> | ||
| 6 | <MsiPackage Id="PackageA" SourceFile="$(var.PackageAv1.TargetPath)" Compressed="no"> | ||
| 7 | <SlipstreamMsp Id="PatchAMinor" /> | ||
| 8 | </MsiPackage> | ||
| 9 | <MspPackage Id="PatchAMinor" SourceFile="$(var.PatchAMinor.TargetPath)" Compressed="no" /> | ||
| 10 | </PackageGroup> | ||
| 11 | </Fragment> | ||
| 12 | </Wix> | ||
diff --git a/src/test/burn/TestData/SlipstreamTests/PatchAMinor/PatchAMinor.wixproj b/src/test/burn/TestData/SlipstreamTests/PatchAMinor/PatchAMinor.wixproj new file mode 100644 index 00000000..3deb2263 --- /dev/null +++ b/src/test/burn/TestData/SlipstreamTests/PatchAMinor/PatchAMinor.wixproj | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | <Project Sdk="WixToolset.Sdk"> | ||
| 3 | <PropertyGroup> | ||
| 4 | <OutputType>Patch</OutputType> | ||
| 5 | <TargetExt>.msp</TargetExt> | ||
| 6 | <SuppressSpecificWarnings>1079</SuppressSpecificWarnings> | ||
| 7 | </PropertyGroup> | ||
| 8 | <ItemGroup> | ||
| 9 | <ProjectReference Include="..\PackageAv1\PackageAv1.wixproj" /> | ||
| 10 | <ProjectReference Include="..\PackageAv1_0_1\PackageAv1_0_1.wixproj" /> | ||
| 11 | </ItemGroup> | ||
| 12 | </Project> | ||
diff --git a/src/test/burn/TestData/SlipstreamTests/PatchAMinor/PatchAMinor.wxs b/src/test/burn/TestData/SlipstreamTests/PatchAMinor/PatchAMinor.wxs new file mode 100644 index 00000000..0f4abd2b --- /dev/null +++ b/src/test/burn/TestData/SlipstreamTests/PatchAMinor/PatchAMinor.wxs | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 2 | |||
| 3 | <?ifndef TestVersion?> | ||
| 4 | <?define TestVersion = 1.0.0.0?> | ||
| 5 | <?endif?> | ||
| 6 | |||
| 7 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
| 8 | <Patch AllowRemoval="yes" Classification="Update" Description="Patch A minor upgrade in test $(var.TestGroupName)" DisplayName="$(var.TestGroupName) - Patch A minor upgrade" Manufacturer="Example Corporation" MinorUpdateTargetRTM="yes"> | ||
| 9 | <Media Id="100" Cabinet="PatchA" EmbedCab="yes"> | ||
| 10 | <PatchBaseline | ||
| 11 | Id="PatchA" | ||
| 12 | BaselineFile="$(var.PackageAv1.TargetDir)$(var.PackageAv1.TargetName).wixpdb" | ||
| 13 | UpdateFile="$(var.PackageAv1_0_1.TargetDir)$(var.PackageAv1_0_1.TargetName).wixpdb" | ||
| 14 | /> | ||
| 15 | </Media> | ||
| 16 | |||
| 17 | <PatchFamily Id="A" Version="$(var.TestVersion)" Supersede="yes"> | ||
| 18 | <ComponentRef Id="RegistryComponent" /> | ||
| 19 | <PropertyRef Id="TestVersion" /> | ||
| 20 | <PropertyRef Id="ProductVersion" /> | ||
| 21 | </PatchFamily> | ||
| 22 | </Patch> | ||
| 23 | </Wix> | ||
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/SlipstreamTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/SlipstreamTests.cs index d07e80f1..d4cf447d 100644 --- a/src/test/burn/WixToolsetTest.BurnE2E/SlipstreamTests.cs +++ b/src/test/burn/WixToolsetTest.BurnE2E/SlipstreamTests.cs | |||
| @@ -18,7 +18,7 @@ namespace WixToolsetTest.BurnE2E | |||
| 18 | private const string V101 = "1.0.1.0"; | 18 | private const string V101 = "1.0.1.0"; |
| 19 | 19 | ||
| 20 | [RuntimeFact] | 20 | [RuntimeFact] |
| 21 | public void CanInstallBundleWithSlipstreamedPatchThenRemoveIt() | 21 | public void CanInstallBundleWithSlipstreamedSmallUpdatePatchThenRemoveIt() |
| 22 | { | 22 | { |
| 23 | var testRegistryValue = "PackageA"; | 23 | var testRegistryValue = "PackageA"; |
| 24 | 24 | ||
| @@ -39,6 +39,28 @@ namespace WixToolsetTest.BurnE2E | |||
| 39 | packageAv1.VerifyTestRegistryRootDeleted(); | 39 | packageAv1.VerifyTestRegistryRootDeleted(); |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | [RuntimeFact] | ||
| 43 | public void CanInstallBundleWithSlipstreamedMinorUpgradePatchThenRemoveIt() | ||
| 44 | { | ||
| 45 | var testRegistryValue = "PackageA"; | ||
| 46 | |||
| 47 | var packageAv1 = this.CreatePackageInstaller("PackageAv1"); | ||
| 48 | var bundleA = this.CreateBundleInstaller("BundleAv1_0_1"); | ||
| 49 | |||
| 50 | var packageAv1SourceCodeInstalled = packageAv1.GetInstalledFilePath("Package.wxs"); | ||
| 51 | Assert.False(File.Exists(packageAv1SourceCodeInstalled), $"PackageAv1 payload should not be there on test start: {packageAv1SourceCodeInstalled}"); | ||
| 52 | |||
| 53 | bundleA.Install(); | ||
| 54 | bundleA.VerifyRegisteredAndInPackageCache(); | ||
| 55 | Assert.True(File.Exists(packageAv1SourceCodeInstalled), String.Concat("Should have found PackageAv1 payload installed at: ", packageAv1SourceCodeInstalled)); | ||
| 56 | packageAv1.VerifyTestRegistryValue(testRegistryValue, V101); | ||
| 57 | |||
| 58 | bundleA.Uninstall(); | ||
| 59 | bundleA.VerifyUnregisteredAndRemovedFromPackageCache(); | ||
| 60 | Assert.False(File.Exists(packageAv1SourceCodeInstalled), String.Concat("PackageAv1 payload should have been removed by uninstall from: ", packageAv1SourceCodeInstalled)); | ||
| 61 | packageAv1.VerifyTestRegistryRootDeleted(); | ||
| 62 | } | ||
| 63 | |||
| 42 | /// <summary> | 64 | /// <summary> |
| 43 | /// BundleA installs PackageA with slipstreamed PatchA. | 65 | /// BundleA installs PackageA with slipstreamed PatchA. |
| 44 | /// BundleOnlyPatchA is installed which contains PatchA (which should be a no-op). | 66 | /// BundleOnlyPatchA is installed which contains PatchA (which should be a no-op). |
diff --git a/src/test/sandbox/TestSandbox.wsb b/src/test/sandbox/TestSandbox.wsb index 01e11e6b..97c3c759 100644 --- a/src/test/sandbox/TestSandbox.wsb +++ b/src/test/sandbox/TestSandbox.wsb | |||
| @@ -5,6 +5,11 @@ | |||
| 5 | <SandboxFolder>C:\build</SandboxFolder> | 5 | <SandboxFolder>C:\build</SandboxFolder> |
| 6 | <ReadOnly>true</ReadOnly> | 6 | <ReadOnly>true</ReadOnly> |
| 7 | </MappedFolder> | 7 | </MappedFolder> |
| 8 | <MappedFolder> | ||
| 9 | <HostFolder>..\..\..\build\logs</HostFolder> | ||
| 10 | <SandboxFolder>C:\logs</SandboxFolder> | ||
| 11 | <ReadOnly>false</ReadOnly> | ||
| 12 | </MappedFolder> | ||
| 8 | <MappedFolder> | 13 | <MappedFolder> |
| 9 | <HostFolder>.\</HostFolder> | 14 | <HostFolder>.\</HostFolder> |
| 10 | <SandboxFolder>C:\sandbox</SandboxFolder> | 15 | <SandboxFolder>C:\sandbox</SandboxFolder> |
diff --git a/src/test/sandbox/startup.bat b/src/test/sandbox/startup.bat index 52f550ee..90f04f5f 100644 --- a/src/test/sandbox/startup.bat +++ b/src/test/sandbox/startup.bat | |||
| @@ -1,5 +1,13 @@ | |||
| 1 | @setlocal | 1 | @setlocal |
| 2 | @echo off | 2 | @echo off |
| 3 | |||
| 4 | |||
| 5 | ::// Fix Sandbox glacial perf (24H2-???) | ||
| 6 | ::// | ||
| 7 | REG ADD HKLM\SYSTEM\CurrentControlSet\Control\CI\Policy /v VerifiedAndReputablePolicyState /t REG_DWORD /d 0 /f | ||
| 8 | CITOOL -r -j | ||
| 9 | |||
| 10 | |||
| 3 | SET DOTNET_VERSION=8.0 | 11 | SET DOTNET_VERSION=8.0 |
| 4 | SET SANDBOX_FILES=C:\sandbox | 12 | SET SANDBOX_FILES=C:\sandbox |
| 5 | 13 | ||
