From 6f7bb97daa1ae6bf2486b1c566c29e1b524b7548 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Tue, 13 Apr 2021 00:09:00 -0700 Subject: Add MEND request state to repair any missing files in MSI packages --- .../inc/BootstrapperEngine.h | 2 ++ src/engine/dependency.cpp | 2 ++ src/engine/logging.cpp | 4 ++++ src/engine/msiengine.cpp | 21 +++++++++++++++------ 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperEngine.h b/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperEngine.h index c0e4ded1..99e9b9f0 100644 --- a/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperEngine.h +++ b/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperEngine.h @@ -37,6 +37,7 @@ enum BOOTSTRAPPER_ACTION_STATE BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BOOTSTRAPPER_ACTION_STATE_INSTALL, BOOTSTRAPPER_ACTION_STATE_MODIFY, + BOOTSTRAPPER_ACTION_STATE_MEND, BOOTSTRAPPER_ACTION_STATE_REPAIR, BOOTSTRAPPER_ACTION_STATE_MINOR_UPGRADE, }; @@ -58,6 +59,7 @@ enum BOOTSTRAPPER_REQUEST_STATE BOOTSTRAPPER_REQUEST_STATE_ABSENT, BOOTSTRAPPER_REQUEST_STATE_CACHE, BOOTSTRAPPER_REQUEST_STATE_PRESENT, + BOOTSTRAPPER_REQUEST_STATE_MEND, BOOTSTRAPPER_REQUEST_STATE_REPAIR, }; diff --git a/src/engine/dependency.cpp b/src/engine/dependency.cpp index 1bd0c7d4..c4af207a 100644 --- a/src/engine/dependency.cpp +++ b/src/engine/dependency.cpp @@ -1025,6 +1025,7 @@ static void CalculateDependencyActionStates( } break; case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; + case BOOTSTRAPPER_REQUEST_STATE_MEND: __fallthrough; case BOOTSTRAPPER_REQUEST_STATE_REPAIR: // Register if the package is requested but already installed. switch (pPackage->currentState) @@ -1048,6 +1049,7 @@ static void CalculateDependencyActionStates( break; case BOOTSTRAPPER_ACTION_STATE_INSTALL: __fallthrough; case BOOTSTRAPPER_ACTION_STATE_MODIFY: __fallthrough; + case BOOTSTRAPPER_ACTION_STATE_MEND: __fallthrough; case BOOTSTRAPPER_ACTION_STATE_REPAIR: __fallthrough; case BOOTSTRAPPER_ACTION_STATE_MINOR_UPGRADE: __fallthrough; *pDependencyExecuteAction = BURN_DEPENDENCY_ACTION_REGISTER; diff --git a/src/engine/logging.cpp b/src/engine/logging.cpp index d66f7cf5..67f39c85 100644 --- a/src/engine/logging.cpp +++ b/src/engine/logging.cpp @@ -326,6 +326,8 @@ extern "C" LPCSTR LoggingActionStateToString( return "Install"; case BOOTSTRAPPER_ACTION_STATE_MODIFY: return "Modify"; + case BOOTSTRAPPER_ACTION_STATE_MEND: + return "Mend"; case BOOTSTRAPPER_ACTION_STATE_REPAIR: return "Repair"; case BOOTSTRAPPER_ACTION_STATE_MINOR_UPGRADE: @@ -665,6 +667,8 @@ extern "C" LPCSTR LoggingRequestStateToString( return "Cache"; case BOOTSTRAPPER_REQUEST_STATE_PRESENT: return "Present"; + case BOOTSTRAPPER_REQUEST_STATE_MEND: + return "Mend"; case BOOTSTRAPPER_REQUEST_STATE_REPAIR: return "Repair"; default: diff --git a/src/engine/msiengine.cpp b/src/engine/msiengine.cpp index 4f6062ea..269fc831 100644 --- a/src/engine/msiengine.cpp +++ b/src/engine/msiengine.cpp @@ -789,7 +789,7 @@ extern "C" HRESULT MsiEnginePlanCalculatePackage( { case BOOTSTRAPPER_PACKAGE_STATE_PRESENT: __fallthrough; case BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED: - if (BOOTSTRAPPER_REQUEST_STATE_PRESENT == pPackage->requested || BOOTSTRAPPER_REQUEST_STATE_REPAIR == pPackage->requested) + if (BOOTSTRAPPER_REQUEST_STATE_PRESENT == pPackage->requested || BOOTSTRAPPER_REQUEST_STATE_MEND == pPackage->requested || BOOTSTRAPPER_REQUEST_STATE_REPAIR == pPackage->requested) { hr = VerCompareParsedVersions(pVersion, pInstalledVersion, &nCompareResult); ExitOnFailure(hr, "Failed to compare '%ls' to '%ls' for planning.", pVersion->sczVersion, pInstalledVersion->sczVersion); @@ -801,6 +801,10 @@ extern "C" HRESULT MsiEnginePlanCalculatePackage( { execute = BOOTSTRAPPER_ACTION_STATE_MINOR_UPGRADE; } + else if (BOOTSTRAPPER_REQUEST_STATE_MEND == pPackage->requested) + { + execute = BOOTSTRAPPER_ACTION_STATE_MEND; + } else if (BOOTSTRAPPER_REQUEST_STATE_REPAIR == pPackage->requested) { execute = BOOTSTRAPPER_ACTION_STATE_REPAIR; @@ -829,6 +833,7 @@ extern "C" HRESULT MsiEnginePlanCalculatePackage( switch (pPackage->requested) { case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; + case BOOTSTRAPPER_REQUEST_STATE_MEND: __fallthrough; case BOOTSTRAPPER_REQUEST_STATE_REPAIR: execute = BOOTSTRAPPER_ACTION_STATE_INSTALL; break; @@ -844,6 +849,7 @@ extern "C" HRESULT MsiEnginePlanCalculatePackage( switch (pPackage->requested) { case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; + case BOOTSTRAPPER_REQUEST_STATE_MEND: __fallthrough; case BOOTSTRAPPER_REQUEST_STATE_REPAIR: execute = BOOTSTRAPPER_ACTION_STATE_INSTALL; break; @@ -887,10 +893,12 @@ extern "C" HRESULT MsiEnginePlanCalculatePackage( case BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE: __fallthrough; case BOOTSTRAPPER_PACKAGE_STATE_ABSENT: __fallthrough; case BOOTSTRAPPER_PACKAGE_STATE_CACHED: - // If we requested to put the package on the machine then remove the package during rollback - // if the package is uninstallable. - if ((BOOTSTRAPPER_REQUEST_STATE_PRESENT == pPackage->requested || BOOTSTRAPPER_REQUEST_STATE_REPAIR == pPackage->requested) && - pPackage->fUninstallable) + // If the package is uninstallable and we requested to put the package on the machine then + // remove the package during rollback. + if (pPackage->fUninstallable && + (BOOTSTRAPPER_REQUEST_STATE_PRESENT == pPackage->requested || + BOOTSTRAPPER_REQUEST_STATE_MEND == pPackage->requested || + BOOTSTRAPPER_REQUEST_STATE_REPAIR == pPackage->requested)) { rollback = BOOTSTRAPPER_ACTION_STATE_UNINSTALL; } @@ -1228,11 +1236,12 @@ extern "C" HRESULT MsiEngineExecutePackage( break; case BOOTSTRAPPER_ACTION_STATE_MODIFY: __fallthrough; + case BOOTSTRAPPER_ACTION_STATE_MEND: __fallthrough; case BOOTSTRAPPER_ACTION_STATE_REPAIR: { LPCWSTR wzReinstallAll = (BOOTSTRAPPER_ACTION_STATE_MODIFY == pExecuteAction->msiPackage.action || pExecuteAction->msiPackage.pPackage->Msi.cFeatures) ? L"" : L" REINSTALL=ALL"; - LPCWSTR wzReinstallMode = (BOOTSTRAPPER_ACTION_STATE_MODIFY == pExecuteAction->msiPackage.action) ? L"o" : L"e"; + LPCWSTR wzReinstallMode = (BOOTSTRAPPER_ACTION_STATE_MODIFY == pExecuteAction->msiPackage.action || BOOTSTRAPPER_ACTION_STATE_MEND == pExecuteAction->msiPackage.action) ? L"o" : L"e"; hr = StrAllocFormattedSecure(&sczProperties, L"%ls%ls REINSTALLMODE=\"cmus%ls\" REBOOT=ReallySuppress", sczProperties ? sczProperties : L"", wzReinstallAll, wzReinstallMode); ExitOnFailure(hr, "Failed to add reinstall mode and reboot suppression properties on repair."); -- cgit v1.2.3-55-g6feb