aboutsummaryrefslogtreecommitdiff
path: root/src/burn/engine
diff options
context:
space:
mode:
Diffstat (limited to 'src/burn/engine')
-rw-r--r--src/burn/engine/msiengine.cpp65
1 files changed, 62 insertions, 3 deletions
diff --git a/src/burn/engine/msiengine.cpp b/src/burn/engine/msiengine.cpp
index 86fb0d9d..48ec0c81 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,22 @@ 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 if (BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED == pPackage->currentState)
910 {
911 // If the package is superseded, check to see if there's a patch installed.
912 // A minor upgrade patch could be (usually is) the cause of the
913 // supersedence. In that case, we should ignore the supersedence that would
914 // normally prevent the uninstall. There is a gap in this logic: If a minor
915 // upgrade package were installed without a bundle, then a small update patch
916 // (which by definition doesn't change the version number) were installed,
917 // this check would allow the uninstall. If the minor upgrade were installed
918 // by a bundle, dependencies would keep the package installed.
919 execute = PackageHasAppliedPatch(pPackage) ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
920 }
921 else
922 {
923 execute = BOOTSTRAPPER_ACTION_STATE_UNINSTALL;
924 }
908 } 925 }
909 else if (BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT == pPackage->requested) 926 else if (BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT == pPackage->requested)
910 { 927 {
@@ -2265,6 +2282,7 @@ LExit:
2265 ReleaseStr(sczMspPath); 2282 ReleaseStr(sczMspPath);
2266 ReleaseStr(sczCachedDirectory); 2283 ReleaseStr(sczCachedDirectory);
2267 ReleaseStr(sczPatches); 2284 ReleaseStr(sczPatches);
2285
2268 return hr; 2286 return hr;
2269} 2287}
2270 2288
@@ -2289,6 +2307,47 @@ static void RegisterSourceDirectory(
2289 2307
2290LExit: 2308LExit:
2291 ReleaseStr(sczMsiDirectory); 2309 ReleaseStr(sczMsiDirectory);
2310}
2311
2312static BOOL PackageHasAppliedPatch(
2313 __in BURN_PACKAGE* pPackage
2314)
2315{
2316 HRESULT hr = S_OK;
2317 BOOL fPatched = FALSE;
2318 UINT er = ERROR_SUCCESS;
2319 DWORD iPatch = 0;
2320 WCHAR wzPatchCode[MAX_GUID_CHARS + 1] = {};
2321 WCHAR wzTransforms[MAX_PATH] = {};
2322 DWORD cchTransforms = countof(wzTransforms);
2323 WCHAR wzPatchState[2] = {};
2324 DWORD cchPatchState = countof(wzPatchState);
2325
2326 for (;;)
2327 {
2328 er = ::MsiEnumPatchesW(pPackage->Msi.sczProductCode, iPatch, wzPatchCode, wzTransforms, &cchTransforms);
2329
2330 if (ERROR_NO_MORE_ITEMS == er)
2331 {
2332 ExitFunction();
2333 }
2334 ExitOnWin32Error(er, hr, "Failed to enumerate patches for package %ls, product code %ls.", pPackage->sczId, pPackage->Msi.sczProductCode);
2335
2336 er = ::MsiGetPatchInfoExW(wzPatchCode, pPackage->Msi.sczProductCode, NULL, pPackage->fPerMachine ? MSIINSTALLCONTEXT_MACHINE : MSIINSTALLCONTEXT_USERUNMANAGED
2337 , INSTALLPROPERTY_PATCHSTATE, wzPatchState, &cchPatchState);
2338 ExitOnWin32Error(er, hr, "Failed to get patch info for patch %ls.", wzPatchCode);
2339
2340 if ('1' == wzPatchState[0])
2341 {
2342 fPatched = TRUE;
2343
2344 ExitFunction();
2345 }
2346
2347 ++iPatch;
2348 }
2349
2350LExit:
2351 return fPatched;
2292 2352
2293 return;
2294} 2353}