aboutsummaryrefslogtreecommitdiff
path: root/src/burn/engine
diff options
context:
space:
mode:
authorBob Arnson <bob@firegiant.com>2026-01-21 21:20:40 -0500
committerBob Arnson <bob@firegiant.com>2026-01-21 21:20:40 -0500
commitfafdaa522ff2a3888dfceb0ab56911c4f8cdf48d (patch)
tree02e91784289063f01ee71c2b72ec04b890802cee /src/burn/engine
parent9a26c32398337aff57da6e92088b90314b81cf03 (diff)
downloadwix-bob/SupersededPackageUninstall.tar.gz
wix-bob/SupersededPackageUninstall.tar.bz2
wix-bob/SupersededPackageUninstall.zip
Allow patched package to be uninstalled.bob/SupersededPackageUninstall
Normally, a patched package is detected as superseded and therefore a normal uninstall takes no action. This change looks for applied patches and allows a normal uninstall to remove the package. Fixes https://github.com/wixtoolset/issues/issues/6350
Diffstat (limited to 'src/burn/engine')
-rw-r--r--src/burn/engine/msiengine.cpp52
1 files changed, 49 insertions, 3 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 53static 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
2290LExit: 2295LExit:
2291 ReleaseStr(sczMsiDirectory); 2296 ReleaseStr(sczMsiDirectory);
2297}
2298
2299static 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
2337LExit:
2338 return fPatched;
2292 2339
2293 return;
2294} 2340}