@joebigelow / wix / commits / fd8c2b08

Update the logic for determining when the bundle should be registered.

The basic rule is that if a non-permanent package is present at the end of the chain, then the bundle should be registered. If no non-permanent packages are present at the end of the chain, then the bundle should not be registered. This required tracking what actually happened with each package during Apply. Include cache status in registration calculation. Include dependency ref-counting when determining whether the bundle should be registered.

Sean Hall committed Feb 2, 2021 at 18:09 UTC fd8c2b0899bfbce07386af245c04eb21dc01cbdf
22 files changed +804 -267
src/engine/apply.cpp
+201 -46
@@ -46,6 +46,10 @@ static HRESULT WINAPI AuthenticationRequired(
46 __out BOOL* pfRetry
47 );
48
49 +static void CalculateKeepRegistration(
50 + __in BURN_ENGINE_STATE* pEngineState,
51 + __inout BOOL* pfKeepRegistration
52 + );
53 static HRESULT ExecuteDependentRegistrationActions(
54 __in HANDLE hPipe,
55 __in const BURN_REGISTRATION* pRegistration,
@@ -141,7 +145,6 @@ static HRESULT DoExecuteAction(
145 __in BURN_EXECUTE_CONTEXT* pContext,
146 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary,
147 __inout BURN_EXECUTE_ACTION_CHECKPOINT** ppCheckpoint,
144 - __out BOOL* pfKeepRegistration,
148 __out BOOL* pfSuspend,
149 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
150 );
@@ -149,7 +152,6 @@ static HRESULT DoRollbackActions(
152 __in BURN_ENGINE_STATE* pEngineState,
153 __in BURN_EXECUTE_CONTEXT* pContext,
154 __in DWORD dwCheckpoint,
152 - __out BOOL* pfKeepRegistration,
155 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
156 );
157 static HRESULT ExecuteExePackage(
@@ -165,6 +167,7 @@ static HRESULT ExecuteMsiPackage(
167 __in BURN_ENGINE_STATE* pEngineState,
168 __in BURN_EXECUTE_ACTION* pExecuteAction,
169 __in BURN_EXECUTE_CONTEXT* pContext,
170 + __in BOOL fInsideMsiTransaction,
171 __in BOOL fRollback,
172 __out BOOL* pfRetry,
173 __out BOOL* pfSuspend,
@@ -174,6 +177,7 @@ static HRESULT ExecuteMspPackage(
177 __in BURN_ENGINE_STATE* pEngineState,
178 __in BURN_EXECUTE_ACTION* pExecuteAction,
179 __in BURN_EXECUTE_CONTEXT* pContext,
180 + __in BOOL fInsideMsiTransaction,
181 __in BOOL fRollback,
182 __out BOOL* pfRetry,
183 __out BOOL* pfSuspend,
@@ -214,6 +218,10 @@ static HRESULT ExecuteMsiRollbackTransaction(
218 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary,
219 __in BURN_EXECUTE_CONTEXT* pContext
220 );
221 +static void ResetTransactionRegistrationState(
222 + __in BURN_ENGINE_STATE* pEngineState,
223 + __in BOOL fCommit
224 + );
225 static HRESULT CleanPackage(
226 __in HANDLE hElevatedPipe,
227 __in BURN_PACKAGE* pPackage
@@ -282,6 +290,7 @@ extern "C" void ApplyReset(
290 {
291 BURN_PACKAGE* pPackage = pPackages->rgPackages + i;
292 pPackage->hrCacheResult = S_OK;
293 + pPackage->transactionRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
294 }
295 }
296
@@ -380,13 +389,15 @@ LExit:
389 extern "C" HRESULT ApplyUnregister(
390 __in BURN_ENGINE_STATE* pEngineState,
391 __in BOOL fFailedOrRollback,
383 - __in BOOL fKeepRegistration,
392 __in BOOL fSuspend,
393 __in BOOTSTRAPPER_APPLY_RESTART restart
394 )
395 {
396 HRESULT hr = S_OK;
397 BURN_RESUME_MODE resumeMode = BURN_RESUME_MODE_NONE;
398 + BOOL fKeepRegistration = pEngineState->plan.fDisallowRemoval;
399 +
400 + CalculateKeepRegistration(pEngineState, &fKeepRegistration);
401
402 hr = UserExperienceOnUnregisterBegin(&pEngineState->userExperience);
403 ExitOnRootFailure(hr, "BA aborted unregister begin.");
@@ -443,7 +454,7 @@ extern "C" HRESULT ApplyCache(
454 __in BURN_PLAN* pPlan,
455 __in HANDLE hPipe,
456 __inout DWORD* pcOverallProgressTicks,
446 - __out BOOL* pfRollback
457 + __inout BOOL* pfRollback
458 )
459 {
460 HRESULT hr = S_OK;
@@ -732,7 +743,6 @@ extern "C" HRESULT ApplyExecute(
743 __in BURN_ENGINE_STATE* pEngineState,
744 __in_opt HANDLE hCacheThread,
745 __inout DWORD* pcOverallProgressTicks,
735 - __inout BOOL* pfKeepRegistration,
746 __out BOOL* pfRollback,
747 __out BOOL* pfSuspend,
748 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
@@ -779,7 +789,7 @@ extern "C" HRESULT ApplyExecute(
789 }
790
791 // Execute the action.
782 - hr = DoExecuteAction(pEngineState, pExecuteAction, hCacheThread, &context, &pRollbackBoundary, &pCheckpoint, pfKeepRegistration, pfSuspend, pRestart);
792 + hr = DoExecuteAction(pEngineState, pExecuteAction, hCacheThread, &context, &pRollbackBoundary, &pCheckpoint, pfSuspend, pRestart);
793
794 if (*pfSuspend || BOOTSTRAPPER_APPLY_RESTART_INITIATED == *pRestart)
795 {
@@ -821,7 +831,7 @@ extern "C" HRESULT ApplyExecute(
831 // The action failed, roll back to previous rollback boundary.
832 if (pCheckpoint)
833 {
824 - hrRollback = DoRollbackActions(pEngineState, &context, pCheckpoint->dwId, pfKeepRegistration, pRestart);
834 + hrRollback = DoRollbackActions(pEngineState, &context, pCheckpoint->dwId, pRestart);
835 IgnoreRollbackError(hrRollback, "Failed rollback actions");
836 }
837
@@ -855,14 +865,46 @@ extern "C" void ApplyClean(
865 for (DWORD i = 0; i < pPlan->cCleanActions; ++i)
866 {
867 BURN_CLEAN_ACTION* pCleanAction = pPlan->rgCleanActions + i;
868 + BURN_PACKAGE* pPackage = pCleanAction->pPackage;
869
859 - hr = CleanPackage(hPipe, pCleanAction->pPackage);
870 + hr = CleanPackage(hPipe, pPackage);
871 }
872 }
873
874
875 // internal helper functions
876
877 +static void CalculateKeepRegistration(
878 + __in BURN_ENGINE_STATE* pEngineState,
879 + __inout BOOL* pfKeepRegistration
880 + )
881 +{
882 + LogId(REPORT_STANDARD, MSG_POST_APPLY_CALCULATE_REGISTRATION);
883 +
884 + for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i)
885 + {
886 + BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i;
887 +
888 + LogId(REPORT_STANDARD, MSG_POST_APPLY_PACKAGE, pPackage->sczId, LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->installRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->cacheRegistrationState));
889 +
890 + if (!pPackage->fCanAffectRegistration)
891 + {
892 + continue;
893 + }
894 +
895 + if (BURN_PACKAGE_TYPE_MSP == pPackage->type)
896 + {
897 + MspEngineFinalizeInstallRegistrationState(pPackage);
898 + }
899 +
900 + if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->installRegistrationState ||
901 + BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->cacheRegistrationState)
902 + {
903 + *pfKeepRegistration = TRUE;
904 + }
905 + }
906 +}
907 +
908 static HRESULT ExecuteDependentRegistrationActions(
909 __in HANDLE hPipe,
910 __in const BURN_REGISTRATION* pRegistration,
@@ -1255,6 +1297,15 @@ static HRESULT LayoutOrCacheContainerOrPayload(
1297 LARGE_INTEGER liContainerOrPayloadSize = { };
1298 LARGE_INTEGER liZero = { };
1299 BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT progress = { };
1300 + BOOL fCanAffectRegistration = FALSE;
1301 +
1302 + if (!wzLayoutDirectory)
1303 + {
1304 + Assert(!pContainer);
1305 + Assert(pPackage);
1306 +
1307 + fCanAffectRegistration = pPackage->fCanAffectRegistration;
1308 + }
1309
1310 liContainerOrPayloadSize.QuadPart = pContainer ? pContainer->qwFileSize : pPayload->qwFileSize;
1311
@@ -1297,9 +1348,6 @@ static HRESULT LayoutOrCacheContainerOrPayload(
1348 }
1349 else // complete the payload.
1350 {
1300 - Assert(!pContainer);
1301 - Assert(pPackage);
1302 -
1351 hr = CacheCompletePayload(pPackage->fPerMachine, pPayload, pPackage->sczCacheId, wzUnverifiedPath, fMove);
1352 }
1353
@@ -1307,6 +1355,11 @@ static HRESULT LayoutOrCacheContainerOrPayload(
1355 // will get.
1356 if (SUCCEEDED(hr))
1357 {
1358 + if (fCanAffectRegistration)
1359 + {
1360 + pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
1361 + }
1362 +
1363 CacheProgressRoutine(liContainerOrPayloadSize, liContainerOrPayloadSize, liZero, liZero, 0, 0, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, &progress);
1364 if (progress.fCancel)
1365 {
@@ -1639,7 +1692,6 @@ static HRESULT DoExecuteAction(
1692 __in BURN_EXECUTE_CONTEXT* pContext,
1693 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary,
1694 __inout BURN_EXECUTE_ACTION_CHECKPOINT** ppCheckpoint,
1642 - __out BOOL* pfKeepRegistration,
1695 __out BOOL* pfSuspend,
1696 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
1697 )
@@ -1651,11 +1703,14 @@ static HRESULT DoExecuteAction(
1703 BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE;
1704 BOOL fRetry = FALSE;
1705 BOOL fStopWusaService = FALSE;
1706 + BOOL fInsideMsiTransaction = FALSE;
1707
1708 pContext->fRollback = FALSE;
1709
1710 do
1711 {
1712 + fInsideMsiTransaction = *ppRollbackBoundary && (*ppRollbackBoundary)->fActiveTransaction;
1713 +
1714 switch (pExecuteAction->type)
1715 {
1716 case BURN_EXECUTE_ACTION_TYPE_CHECKPOINT:
@@ -1695,12 +1750,12 @@ static HRESULT DoExecuteAction(
1750 break;
1751
1752 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
1698 - hr = ExecuteMsiPackage(pEngineState, pExecuteAction, pContext, FALSE, &fRetry, pfSuspend, &restart);
1753 + hr = ExecuteMsiPackage(pEngineState, pExecuteAction, pContext, fInsideMsiTransaction, FALSE, &fRetry, pfSuspend, &restart);
1754 ExitOnFailure(hr, "Failed to execute MSI package.");
1755 break;
1756
1757 case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET:
1703 - hr = ExecuteMspPackage(pEngineState, pExecuteAction, pContext, FALSE, &fRetry, pfSuspend, &restart);
1758 + hr = ExecuteMspPackage(pEngineState, pExecuteAction, pContext, fInsideMsiTransaction, FALSE, &fRetry, pfSuspend, &restart);
1759 ExitOnFailure(hr, "Failed to execute MSP package.");
1760 break;
1761
@@ -1720,8 +1775,6 @@ static HRESULT DoExecuteAction(
1775 ExitOnFailure(hr, "Failed to execute dependency action.");
1776 break;
1777
1723 - case BURN_EXECUTE_ACTION_TYPE_REGISTRATION:
1724 - *pfKeepRegistration = pExecuteAction->registration.fKeep;
1778 break;
1779
1780 case BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY:
@@ -1757,7 +1810,6 @@ static HRESULT DoRollbackActions(
1810 __in BURN_ENGINE_STATE* pEngineState,
1811 __in BURN_EXECUTE_CONTEXT* pContext,
1812 __in DWORD dwCheckpoint,
1760 - __out BOOL* pfKeepRegistration,
1813 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
1814 )
1815 {
@@ -1811,12 +1863,12 @@ static HRESULT DoRollbackActions(
1863 break;
1864
1865 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
1814 - hr = ExecuteMsiPackage(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart);
1866 + hr = ExecuteMsiPackage(pEngineState, pRollbackAction, pContext, FALSE, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart);
1867 IgnoreRollbackError(hr, "Failed to rollback MSI package.");
1868 break;
1869
1870 case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET:
1819 - hr = ExecuteMspPackage(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart);
1871 + hr = ExecuteMspPackage(pEngineState, pRollbackAction, pContext, FALSE, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart);
1872 IgnoreRollbackError(hr, "Failed to rollback MSP package.");
1873 break;
1874
@@ -1835,10 +1887,6 @@ static HRESULT DoRollbackActions(
1887 IgnoreRollbackError(hr, "Failed to rollback dependency action.");
1888 break;
1889
1838 - case BURN_EXECUTE_ACTION_TYPE_REGISTRATION:
1839 - *pfKeepRegistration = pRollbackAction->registration.fKeep;
1840 - break;
1841 -
1890 case BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY:
1891 ExitFunction1(hr = S_OK);
1892
@@ -1878,19 +1926,21 @@ static HRESULT ExecuteExePackage(
1926 GENERIC_EXECUTE_MESSAGE message = { };
1927 int nResult = 0;
1928 BOOL fBeginCalled = FALSE;
1929 + BOOL fExecuted = FALSE;
1930 + BURN_PACKAGE* pPackage = pExecuteAction->exePackage.pPackage;
1931
1882 - if (FAILED(pExecuteAction->exePackage.pPackage->hrCacheResult))
1932 + if (FAILED(pPackage->hrCacheResult))
1933 {
1884 - LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pExecuteAction->exePackage.pPackage->sczId, pExecuteAction->exePackage.pPackage->hrCacheResult);
1934 + LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult);
1935 ExitFunction1(hr = S_OK);
1936 }
1937
1938 Assert(pContext->fRollback == fRollback);
1889 - pContext->pExecutingPackage = pExecuteAction->exePackage.pPackage;
1939 + pContext->pExecutingPackage = pPackage;
1940 fBeginCalled = TRUE;
1941
1942 // Send package execute begin to BA.
1893 - hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pExecuteAction->exePackage.pPackage->sczId, !fRollback, pExecuteAction->exePackage.action, INSTALLUILEVEL_NOCHANGE, FALSE);
1943 + hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pPackage->sczId, !fRollback, pExecuteAction->exePackage.action, INSTALLUILEVEL_NOCHANGE, FALSE);
1944 ExitOnRootFailure(hr, "BA aborted execute EXE package begin.");
1945
1946 message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS;
@@ -1900,8 +1950,10 @@ static HRESULT ExecuteExePackage(
1950 hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwAllowedResults, nResult);
1951 ExitOnRootFailure(hr, "BA aborted EXE progress.");
1952
1953 + fExecuted = TRUE;
1954 +
1955 // Execute package.
1904 - if (pExecuteAction->exePackage.pPackage->fPerMachine)
1956 + if (pPackage->fPerMachine)
1957 {
1958 hrExecute = ElevationExecuteExePackage(pEngineState->companionConnection.hPipe, pExecuteAction, &pEngineState->variables, fRollback, GenericExecuteMessageHandler, pContext, pRestart);
1959 ExitOnFailure(hrExecute, "Failed to configure per-machine EXE package.");
@@ -1926,9 +1978,14 @@ static HRESULT ExecuteExePackage(
1978 ExitOnRootFailure(hr, "BA aborted EXE package execute progress.");
1979
1980 LExit:
1981 + if (fExecuted)
1982 + {
1983 + ExeEngineUpdateInstallRegistrationState(pExecuteAction, hrExecute);
1984 + }
1985 +
1986 if (fBeginCalled)
1987 {
1931 - hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pExecuteAction->exePackage.pPackage, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend);
1988 + hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend);
1989 }
1990
1991 return hr;
@@ -1938,6 +1995,7 @@ static HRESULT ExecuteMsiPackage(
1995 __in BURN_ENGINE_STATE* pEngineState,
1996 __in BURN_EXECUTE_ACTION* pExecuteAction,
1997 __in BURN_EXECUTE_CONTEXT* pContext,
1998 + __in BOOL fInsideMsiTransaction,
1999 __in BOOL fRollback,
2000 __out BOOL* pfRetry,
2001 __out BOOL* pfSuspend,
@@ -1947,23 +2005,27 @@ static HRESULT ExecuteMsiPackage(
2005 HRESULT hr = S_OK;
2006 HRESULT hrExecute = S_OK;
2007 BOOL fBeginCalled = FALSE;
2008 + BOOL fExecuted = FALSE;
2009 + BURN_PACKAGE* pPackage = pExecuteAction->msiPackage.pPackage;
2010
1951 - if (FAILED(pExecuteAction->msiPackage.pPackage->hrCacheResult))
2011 + if (FAILED(pPackage->hrCacheResult))
2012 {
1953 - LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pExecuteAction->msiPackage.pPackage->sczId, pExecuteAction->msiPackage.pPackage->hrCacheResult);
2013 + LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult);
2014 ExitFunction1(hr = S_OK);
2015 }
2016
2017 Assert(pContext->fRollback == fRollback);
1958 - pContext->pExecutingPackage = pExecuteAction->msiPackage.pPackage;
2018 + pContext->pExecutingPackage = pPackage;
2019 fBeginCalled = TRUE;
2020
2021 // Send package execute begin to BA.
1962 - hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pExecuteAction->msiPackage.pPackage->sczId, !fRollback, pExecuteAction->msiPackage.action, pExecuteAction->msiPackage.uiLevel, pExecuteAction->msiPackage.fDisableExternalUiHandler);
2022 + hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pPackage->sczId, !fRollback, pExecuteAction->msiPackage.action, pExecuteAction->msiPackage.uiLevel, pExecuteAction->msiPackage.fDisableExternalUiHandler);
2023 ExitOnRootFailure(hr, "BA aborted execute MSI package begin.");
2024
2025 + fExecuted = TRUE;
2026 +
2027 // execute package
1966 - if (pExecuteAction->msiPackage.pPackage->fPerMachine)
2028 + if (pPackage->fPerMachine)
2029 {
2030 hrExecute = ElevationExecuteMsiPackage(pEngineState->companionConnection.hPipe, pEngineState->userExperience.hwndApply, pExecuteAction, &pEngineState->variables, fRollback, MsiExecuteMessageHandler, pContext, pRestart);
2031 ExitOnFailure(hrExecute, "Failed to configure per-machine MSI package.");
@@ -1981,9 +2043,14 @@ static HRESULT ExecuteMsiPackage(
2043 ExitOnRootFailure(hr, "BA aborted MSI package execute progress.");
2044
2045 LExit:
2046 + if (fExecuted)
2047 + {
2048 + MsiEngineUpdateInstallRegistrationState(pExecuteAction, hrExecute, fInsideMsiTransaction);
2049 + }
2050 +
2051 if (fBeginCalled)
2052 {
1986 - hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pExecuteAction->msiPackage.pPackage, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend);
2053 + hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend);
2054 }
2055
2056 return hr;
@@ -1993,6 +2060,7 @@ static HRESULT ExecuteMspPackage(
2060 __in BURN_ENGINE_STATE* pEngineState,
2061 __in BURN_EXECUTE_ACTION* pExecuteAction,
2062 __in BURN_EXECUTE_CONTEXT* pContext,
2063 + __in BOOL fInsideMsiTransaction,
2064 __in BOOL fRollback,
2065 __out BOOL* pfRetry,
2066 __out BOOL* pfSuspend,
@@ -2002,19 +2070,21 @@ static HRESULT ExecuteMspPackage(
2070 HRESULT hr = S_OK;
2071 HRESULT hrExecute = S_OK;
2072 BOOL fBeginCalled = FALSE;
2073 + BOOL fExecuted = FALSE;
2074 + BURN_PACKAGE* pPackage = pExecuteAction->mspTarget.pPackage;
2075
2006 - if (FAILED(pExecuteAction->mspTarget.pPackage->hrCacheResult))
2076 + if (FAILED(pPackage->hrCacheResult))
2077 {
2008 - LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pExecuteAction->mspTarget.pPackage->sczId, pExecuteAction->mspTarget.pPackage->hrCacheResult);
2078 + LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult);
2079 ExitFunction1(hr = S_OK);
2080 }
2081
2082 Assert(pContext->fRollback == fRollback);
2013 - pContext->pExecutingPackage = pExecuteAction->mspTarget.pPackage;
2083 + pContext->pExecutingPackage = pPackage;
2084 fBeginCalled = TRUE;
2085
2086 // Send package execute begin to BA.
2017 - hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pExecuteAction->mspTarget.pPackage->sczId, !fRollback, pExecuteAction->mspTarget.action, pExecuteAction->mspTarget.uiLevel, pExecuteAction->mspTarget.fDisableExternalUiHandler);
2087 + hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pPackage->sczId, !fRollback, pExecuteAction->mspTarget.action, pExecuteAction->mspTarget.uiLevel, pExecuteAction->mspTarget.fDisableExternalUiHandler);
2088 ExitOnRootFailure(hr, "BA aborted execute MSP package begin.");
2089
2090 // Now send all the patches that target this product code.
@@ -2026,6 +2096,8 @@ static HRESULT ExecuteMspPackage(
2096 ExitOnRootFailure(hr, "BA aborted execute MSP target.");
2097 }
2098
2099 + fExecuted = TRUE;
2100 +
2101 // execute package
2102 if (pExecuteAction->mspTarget.fPerMachineTarget)
2103 {
@@ -2045,9 +2117,14 @@ static HRESULT ExecuteMspPackage(
2117 ExitOnRootFailure(hr, "BA aborted MSP package execute progress.");
2118
2119 LExit:
2120 + if (fExecuted)
2121 + {
2122 + MspEngineUpdateInstallRegistrationState(pExecuteAction, hrExecute, fInsideMsiTransaction);
2123 + }
2124 +
2125 if (fBeginCalled)
2126 {
2050 - hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pExecuteAction->mspTarget.pPackage, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend);
2127 + hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend);
2128 }
2129
2130 return hr;
@@ -2069,19 +2146,21 @@ static HRESULT ExecuteMsuPackage(
2146 GENERIC_EXECUTE_MESSAGE message = { };
2147 int nResult = 0;
2148 BOOL fBeginCalled = FALSE;
2149 + BOOL fExecuted = FALSE;
2150 + BURN_PACKAGE* pPackage = pExecuteAction->msuPackage.pPackage;
2151
2073 - if (FAILED(pExecuteAction->msuPackage.pPackage->hrCacheResult))
2152 + if (FAILED(pPackage->hrCacheResult))
2153 {
2075 - LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pExecuteAction->msuPackage.pPackage->sczId, pExecuteAction->msuPackage.pPackage->hrCacheResult);
2154 + LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult);
2155 ExitFunction1(hr = S_OK);
2156 }
2157
2158 Assert(pContext->fRollback == fRollback);
2080 - pContext->pExecutingPackage = pExecuteAction->msuPackage.pPackage;
2159 + pContext->pExecutingPackage = pPackage;
2160 fBeginCalled = TRUE;
2161
2162 // Send package execute begin to BA.
2084 - hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pExecuteAction->msuPackage.pPackage->sczId, !fRollback, pExecuteAction->msuPackage.action, INSTALLUILEVEL_NOCHANGE, FALSE);
2163 + hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pPackage->sczId, !fRollback, pExecuteAction->msuPackage.action, INSTALLUILEVEL_NOCHANGE, FALSE);
2164 ExitOnRootFailure(hr, "BA aborted execute MSU package begin.");
2165
2166 message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS;
@@ -2091,8 +2170,10 @@ static HRESULT ExecuteMsuPackage(
2170 hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwAllowedResults, nResult);
2171 ExitOnRootFailure(hr, "BA aborted MSU progress.");
2172
2173 + fExecuted = TRUE;
2174 +
2175 // execute package
2095 - if (pExecuteAction->msuPackage.pPackage->fPerMachine)
2176 + if (pPackage->fPerMachine)
2177 {
2178 hrExecute = ElevationExecuteMsuPackage(pEngineState->companionConnection.hPipe, pExecuteAction, fRollback, fStopWusaService, GenericExecuteMessageHandler, pContext, pRestart);
2179 ExitOnFailure(hrExecute, "Failed to configure per-machine MSU package.");
@@ -2117,9 +2198,14 @@ static HRESULT ExecuteMsuPackage(
2198 ExitOnRootFailure(hr, "BA aborted MSU package execute progress.");
2199
2200 LExit:
2201 + if (fExecuted)
2202 + {
2203 + MsuEngineUpdateInstallRegistrationState(pExecuteAction, hrExecute);
2204 + }
2205 +
2206 if (fBeginCalled)
2207 {
2122 - hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pExecuteAction->msuPackage.pPackage, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend);
2208 + hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend);
2209 }
2210
2211 return hr;
@@ -2167,6 +2253,32 @@ static HRESULT ExecuteDependencyAction(
2253 ExitOnFailure(hr, "Failed to register the dependency on per-user package.");
2254 }
2255
2256 + if (pAction->packageDependency.pPackage->fCanAffectRegistration)
2257 + {
2258 + if (BURN_DEPENDENCY_ACTION_REGISTER == pAction->packageDependency.action)
2259 + {
2260 + if (BURN_PACKAGE_REGISTRATION_STATE_IGNORED == pAction->packageDependency.pPackage->cacheRegistrationState)
2261 + {
2262 + pAction->packageDependency.pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
2263 + }
2264 + if (BURN_PACKAGE_REGISTRATION_STATE_IGNORED == pAction->packageDependency.pPackage->installRegistrationState)
2265 + {
2266 + pAction->packageDependency.pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
2267 + }
2268 + }
2269 + else if (BURN_DEPENDENCY_ACTION_UNREGISTER == pAction->packageDependency.action)
2270 + {
2271 + if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pAction->packageDependency.pPackage->cacheRegistrationState)
2272 + {
2273 + pAction->packageDependency.pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED;
2274 + }
2275 + if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pAction->packageDependency.pPackage->installRegistrationState)
2276 + {
2277 + pAction->packageDependency.pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED;
2278 + }
2279 + }
2280 + }
2281 +
2282 LExit:
2283 return hr;
2284 }
@@ -2202,6 +2314,8 @@ static HRESULT ExecuteMsiBeginTransaction(
2314 if (SUCCEEDED(hr))
2315 {
2316 pRollbackBoundary->fActiveTransaction = TRUE;
2317 +
2318 + ResetTransactionRegistrationState(pEngineState, FALSE);
2319 }
2320
2321 LExit:
@@ -2244,6 +2358,8 @@ static HRESULT ExecuteMsiCommitTransaction(
2358 if (SUCCEEDED(hr))
2359 {
2360 pRollbackBoundary->fActiveTransaction = FALSE;
2361 +
2362 + ResetTransactionRegistrationState(pEngineState, TRUE);
2363 }
2364
2365 LExit:
@@ -2285,6 +2401,8 @@ static HRESULT ExecuteMsiRollbackTransaction(
2401 LExit:
2402 pRollbackBoundary->fActiveTransaction = FALSE;
2403
2404 + ResetTransactionRegistrationState(pEngineState, FALSE);
2405 +
2406 if (fBeginCalled)
2407 {
2408 UserExperienceOnRollbackMsiTransactionComplete(&pEngineState->userExperience, pRollbackBoundary->sczId, hr);
@@ -2293,6 +2411,38 @@ LExit:
2411 return hr;
2412 }
2413
2414 +static void ResetTransactionRegistrationState(
2415 + __in BURN_ENGINE_STATE* pEngineState,
2416 + __in BOOL fCommit
2417 + )
2418 +{
2419 + for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i)
2420 + {
2421 + BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i;
2422 +
2423 + if (BURN_PACKAGE_TYPE_MSP == pPackage->type)
2424 + {
2425 + for (DWORD j = 0; j < pPackage->Msp.cTargetProductCodes; ++j)
2426 + {
2427 + BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + j;
2428 +
2429 + if (fCommit && BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN != pTargetProduct->transactionRegistrationState)
2430 + {
2431 + pTargetProduct->registrationState = pTargetProduct->transactionRegistrationState;
2432 + }
2433 +
2434 + pTargetProduct->transactionRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
2435 + }
2436 + }
2437 + else if (fCommit && BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN != pPackage->transactionRegistrationState)
2438 + {
2439 + pPackage->installRegistrationState = pPackage->transactionRegistrationState;
2440 + }
2441 +
2442 + pPackage->transactionRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
2443 + }
2444 +}
2445 +
2446 static HRESULT CleanPackage(
2447 __in HANDLE hElevatedPipe,
2448 __in BURN_PACKAGE* pPackage
@@ -2309,6 +2459,11 @@ static HRESULT CleanPackage(
2459 hr = CacheRemovePackage(FALSE, pPackage->sczId, pPackage->sczCacheId);
2460 }
2461
2462 + if (pPackage->fCanAffectRegistration)
2463 + {
2464 + pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
2465 + }
2466 +
2467 return hr;
2468 }
2469
src/engine/apply.h
+1 -3
@@ -72,7 +72,6 @@ HRESULT ApplyRegister(
72 HRESULT ApplyUnregister(
73 __in BURN_ENGINE_STATE* pEngineState,
74 __in BOOL fFailedOrRollback,
75 - __in BOOL fRollback,
75 __in BOOL fSuspend,
76 __in BOOTSTRAPPER_APPLY_RESTART restart
77 );
@@ -83,13 +82,12 @@ HRESULT ApplyCache(
82 __in BURN_PLAN* pPlan,
83 __in HANDLE hPipe,
84 __inout DWORD* pcOverallProgressTicks,
86 - __out BOOL* pfRollback
85 + __inout BOOL* pfRollback
86 );
87 HRESULT ApplyExecute(
88 __in BURN_ENGINE_STATE* pEngineState,
89 __in_opt HANDLE hCacheThread,
90 __inout DWORD* pcOverallProgressTicks,
92 - __inout BOOL* pfKeepRegistration,
91 __out BOOL* pfRollback,
92 __out BOOL* pfSuspend,
93 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
src/engine/core.cpp
+12 -6
@@ -331,6 +331,8 @@ extern "C" HRESULT CoreDetect(
331 }
332
333 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN;
334 + pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
335 + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
336 }
337 }
338
@@ -342,7 +344,7 @@ extern "C" HRESULT CoreDetect(
344 {
345 pPackage = pEngineState->packages.rgPackages + iPackage;
346
345 - LogId(REPORT_STANDARD, MSG_DETECTED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingCacheStateToString(pPackage->cache));
347 + LogId(REPORT_STANDARD, MSG_DETECTED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingCacheStateToString(pPackage->cache), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->installRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->cacheRegistrationState));
348
349 if (BURN_PACKAGE_TYPE_MSI == pPackage->type)
350 {
@@ -565,7 +567,6 @@ extern "C" HRESULT CoreApply(
567 BOOL fApplyInitialize = FALSE;
568 BOOL fElevated = FALSE;
569 BOOL fRegistered = FALSE;
568 - BOOL fKeepRegistration = pEngineState->plan.fKeepRegistrationDefault;
570 BOOL fRollback = FALSE;
571 BOOL fSuspend = FALSE;
572 BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE;
@@ -652,9 +653,9 @@ extern "C" HRESULT CoreApply(
653 // Register.
654 if (pEngineState->plan.fRegister)
655 {
656 + fRegistered = TRUE;
657 hr = ApplyRegister(pEngineState);
658 ExitOnFailure(hr, "Failed to register bundle.");
657 - fRegistered = TRUE;
659 }
660
661 // Cache.
@@ -681,7 +682,7 @@ extern "C" HRESULT CoreApply(
682 // Execute.
683 if (pEngineState->plan.cExecuteActions)
684 {
684 - hr = ApplyExecute(pEngineState, hCacheThread, &cOverallProgressTicks, &fKeepRegistration, &fRollback, &fSuspend, &restart);
685 + hr = ApplyExecute(pEngineState, hCacheThread, &cOverallProgressTicks, &fRollback, &fSuspend, &restart);
686 UserExperienceExecutePhaseComplete(&pEngineState->userExperience, hr); // signal that execute completed.
687 }
688
@@ -711,7 +712,7 @@ LExit:
712 // Unregister.
713 if (fRegistered)
714 {
714 - ApplyUnregister(pEngineState, FAILED(hr) || fRollback, fKeepRegistration || pEngineState->plan.fDisallowRemoval, fSuspend, restart);
715 + ApplyUnregister(pEngineState, FAILED(hr) || fRollback, fSuspend, restart);
716 }
717
718 if (fElevated)
@@ -1611,6 +1612,11 @@ static HRESULT DetectPackagePayloadsCached(
1612
1613 pPackage->cache = cache;
1614
1615 + if (pPackage->fCanAffectRegistration)
1616 + {
1617 + pPackage->cacheRegistrationState = BURN_CACHE_STATE_NONE < pPackage->cache ? BURN_PACKAGE_REGISTRATION_STATE_PRESENT : BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
1618 + }
1619 +
1620 LExit:
1621 ReleaseStr(sczPayloadCachePath);
1622 ReleaseStr(sczCachePath);
@@ -1703,7 +1709,7 @@ static void LogPackages(
1709 const DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == action) ? pPackages->cPackages - 1 - i : i;
1710 const BURN_PACKAGE* pPackage = &pPackages->rgPackages[iPackage];
1711
1706 - LogId(REPORT_STANDARD, MSG_PLANNED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingBoolToString(pPackage->fAcquire), LoggingBoolToString(pPackage->fUncache), LoggingDependencyActionToString(pPackage->dependencyExecute));
1712 + LogId(REPORT_STANDARD, MSG_PLANNED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingBoolToString(pPackage->fAcquire), LoggingBoolToString(pPackage->fUncache), LoggingDependencyActionToString(pPackage->dependencyExecute), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedInstallRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedCacheRegistrationState));
1713 }
1714
1715 // Display related bundles last if caching, installing, modifying, or repairing.
src/engine/dependency.cpp
+29
@@ -708,6 +708,9 @@ static HRESULT DetectPackageDependents(
708 {
709 HRESULT hr = S_OK;
710 HKEY hkHive = pPackage->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
711 + BOOL fCanIgnorePresence = pPackage->fCanAffectRegistration && 0 < pPackage->cDependencyProviders &&
712 + (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->cacheRegistrationState || BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->installRegistrationState);
713 + BOOL fBundleRegisteredAsDependent = FALSE;
714
715 // There's currently no point in getting the dependents if the scope doesn't match,
716 // because they will just get ignored.
@@ -729,6 +732,20 @@ static HRESULT DetectPackageDependents(
732 {
733 pPackage->fPackageProviderExists = TRUE;
734 }
735 +
736 + if (fCanIgnorePresence && !fBundleRegisteredAsDependent)
737 + {
738 + for (DWORD iDependent = 0; iDependent < pProvider->cDependents; ++iDependent)
739 + {
740 + DEPENDENCY* pDependent = pProvider->rgDependents + iDependent;
741 +
742 + if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->sczId, -1, pDependent->sczKey, -1))
743 + {
744 + fBundleRegisteredAsDependent = TRUE;
745 + break;
746 + }
747 + }
748 + }
749 }
750 else
751 {
@@ -747,6 +764,18 @@ static HRESULT DetectPackageDependents(
764 pPackage->fPackageProviderExists = TRUE;
765 }
766
767 + if (fCanIgnorePresence && !fBundleRegisteredAsDependent)
768 + {
769 + if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->cacheRegistrationState)
770 + {
771 + pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED;
772 + }
773 + if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->installRegistrationState)
774 + {
775 + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED;
776 + }
777 + }
778 +
779 LExit:
780 return hr;
781 }
src/engine/detect.cpp
+2
@@ -63,6 +63,8 @@ extern "C" void DetectReset(
63
64 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN;
65 pPackage->fPackageProviderExists = FALSE;
66 + pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
67 + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
68
69 pPackage->cache = BURN_CACHE_STATE_NONE;
70 for (DWORD iPayload = 0; iPayload < pPackage->cPayloads; ++iPayload)
src/engine/engine.mc
+17 -2
@@ -188,7 +188,7 @@ MessageId=101
188 Severity=Success
189 SymbolicName=MSG_DETECTED_PACKAGE
190 Language=English
191 -Detected package: %1!ls!, state: %2!hs!, cached: %3!hs!
191 +Detected package: %1!ls!, state: %2!hs!, cached: %3!hs!, install registration state: %4!hs!, cache registration state: %5!hs!
192 .
193
194 MessageId=102
@@ -300,7 +300,7 @@ MessageId=201
300 Severity=Success
301 SymbolicName=MSG_PLANNED_PACKAGE
302 Language=English
303 -Planned package: %1!ls!, state: %2!hs!, default requested: %3!hs!, ba requested: %4!hs!, execute: %5!hs!, rollback: %6!hs!, cache: %7!hs!, uncache: %8!hs!, dependency: %9!hs!
303 +Planned package: %1!ls!, state: %2!hs!, default requested: %3!hs!, ba requested: %4!hs!, execute: %5!hs!, rollback: %6!hs!, cache: %7!hs!, uncache: %8!hs!, dependency: %9!hs!, expected install registration state: %10!hs!, expected cache registration state: %11!hs!
304 .
305
306 MessageId=202
@@ -829,6 +829,21 @@ Language=English
829 Session end, registration key: %1!ls!, resume: %2!hs!, restart: %3!hs!, disable resume: %4!hs!
830 .
831
832 +MessageId=373
833 +Severity=Success
834 +SymbolicName=MSG_POST_APPLY_CALCULATE_REGISTRATION
835 +Language=English
836 +Calculating whether to keep registration
837 +.
838 +
839 +
840 +MessageId=374
841 +Severity=Success
842 +SymbolicName=MSG_POST_APPLY_PACKAGE
843 +Language=English
844 + package: %1!ls!, install registration state: %2!hs!, cache registration state: %3!hs!
845 +.
846 +
847 MessageId=380
848 Severity=Warning
849 SymbolicName=MSG_APPLY_SKIPPED
src/engine/exeengine.cpp
+30
@@ -145,6 +145,11 @@ extern "C" HRESULT ExeEngineDetectPackage(
145 // update detect state
146 pPackage->currentState = fDetected ? BOOTSTRAPPER_PACKAGE_STATE_PRESENT : BOOTSTRAPPER_PACKAGE_STATE_ABSENT;
147
148 + if (pPackage->fCanAffectRegistration)
149 + {
150 + pPackage->installRegistrationState = BOOTSTRAPPER_PACKAGE_STATE_CACHED < pPackage->currentState ? BURN_PACKAGE_REGISTRATION_STATE_PRESENT : BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
151 + }
152 +
153 LExit:
154 return hr;
155 }
@@ -585,6 +590,31 @@ LExit:
590 return hr;
591 }
592
593 +extern "C" void ExeEngineUpdateInstallRegistrationState(
594 + __in BURN_EXECUTE_ACTION* pAction,
595 + __in HRESULT hrExecute
596 + )
597 +{
598 + BURN_PACKAGE* pPackage = pAction->exePackage.pPackage;
599 +
600 + if (FAILED(hrExecute) || !pPackage->fCanAffectRegistration)
601 + {
602 + ExitFunction();
603 + }
604 +
605 + if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pAction->exePackage.action)
606 + {
607 + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
608 + }
609 + else
610 + {
611 + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
612 + }
613 +
614 +LExit:
615 + return;
616 +}
617 +
618
619 // internal helper functions
620
src/engine/exeengine.h
+4
@@ -41,6 +41,10 @@ HRESULT ExeEngineExecutePackage(
41 __in LPVOID pvContext,
42 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
43 );
44 +void ExeEngineUpdateInstallRegistrationState(
45 + __in BURN_EXECUTE_ACTION* pAction,
46 + __in HRESULT hrExecute
47 + );
48
49
50 #if defined(__cplusplus)
src/engine/logging.cpp
+25
@@ -399,6 +399,31 @@ extern "C" LPCSTR LoggingPackageStateToString(
399 }
400 }
401
402 +extern "C" LPCSTR LoggingPackageRegistrationStateToString(
403 + __in BOOL fCanAffectRegistration,
404 + __in BURN_PACKAGE_REGISTRATION_STATE registrationState
405 + )
406 +{
407 + if (!fCanAffectRegistration)
408 + {
409 + return "(permanent)";
410 + }
411 +
412 + switch (registrationState)
413 + {
414 + case BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN:
415 + return "Unknown";
416 + case BURN_PACKAGE_REGISTRATION_STATE_IGNORED:
417 + return "Ignored";
418 + case BURN_PACKAGE_REGISTRATION_STATE_ABSENT:
419 + return "Absent";
420 + case BURN_PACKAGE_REGISTRATION_STATE_PRESENT:
421 + return "Present";
422 + default:
423 + return "Invalid";
424 + }
425 +}
426 +
427 extern "C" LPCSTR LoggingCacheStateToString(
428 __in BURN_CACHE_STATE cacheState
429 )
src/engine/logging.h
+5
@@ -89,6 +89,11 @@ LPCSTR LoggingPackageStateToString(
89 __in BOOTSTRAPPER_PACKAGE_STATE packageState
90 );
91
92 +LPCSTR LoggingPackageRegistrationStateToString(
93 + __in BOOL fCanAffectRegistration,
94 + __in BURN_PACKAGE_REGISTRATION_STATE registrationState
95 + );
96 +
97 LPCSTR LoggingCacheStateToString(
98 __in BURN_CACHE_STATE cacheState
99 );
src/engine/msiengine.cpp
+41
@@ -661,6 +661,11 @@ extern "C" HRESULT MsiEngineDetectPackage(
661 }
662 }
663
664 + if (pPackage->fCanAffectRegistration)
665 + {
666 + pPackage->installRegistrationState = BOOTSTRAPPER_PACKAGE_STATE_CACHED < pPackage->currentState ? BURN_PACKAGE_REGISTRATION_STATE_PRESENT : BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
667 + }
668 +
669 LExit:
670 ReleaseStr(sczInstalledLanguage);
671 ReleaseStr(sczInstalledVersion);
@@ -1397,6 +1402,42 @@ extern "C" HRESULT MsiEngineCalculateInstallUiLevel(
1402 return UserExperienceOnPlanMsiPackage(pUserExperience, wzPackageId, fExecute, actionState, pActionMsiProperty, pUiLevel, pfDisableExternalUiHandler);
1403 }
1404
1405 +extern "C" void MsiEngineUpdateInstallRegistrationState(
1406 + __in BURN_EXECUTE_ACTION* pAction,
1407 + __in HRESULT hrExecute,
1408 + __in BOOL fInsideMsiTransaction
1409 + )
1410 +{
1411 + BURN_PACKAGE_REGISTRATION_STATE newState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
1412 + BURN_PACKAGE* pPackage = pAction->msiPackage.pPackage;
1413 +
1414 + if (FAILED(hrExecute) || !pPackage->fCanAffectRegistration)
1415 + {
1416 + ExitFunction();
1417 + }
1418 +
1419 + if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pAction->msiPackage.action)
1420 + {
1421 + newState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
1422 + }
1423 + else
1424 + {
1425 + newState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
1426 + }
1427 +
1428 + if (fInsideMsiTransaction)
1429 + {
1430 + pPackage->transactionRegistrationState = newState;
1431 + }
1432 + else
1433 + {
1434 + pPackage->installRegistrationState = newState;
1435 + }
1436 +
1437 +LExit:
1438 + return;
1439 +}
1440 +
1441
1442 // internal helper functions
1443
src/engine/msiengine.h
+5
@@ -88,6 +88,11 @@ HRESULT MsiEngineCalculateInstallUiLevel(
88 __out INSTALLUILEVEL* pUiLevel,
89 __out BOOL* pfDisableExternalUiHandler
90 );
91 +void MsiEngineUpdateInstallRegistrationState(
92 + __in BURN_EXECUTE_ACTION* pAction,
93 + __in HRESULT hrExecute,
94 + __in BOOL fInsideMsiTransaction
95 + );
96
97 #if defined(__cplusplus)
98 }
src/engine/mspengine.cpp
+107 -2
@@ -200,20 +200,26 @@ extern "C" HRESULT MspEngineDetectPackage(
200 HRESULT hr = S_OK;
201 LPWSTR sczState = NULL;
202
203 + if (pPackage->fCanAffectRegistration)
204 + {
205 + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
206 + }
207 +
208 if (0 == pPackage->Msp.cTargetProductCodes)
209 {
210 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT;
211 }
212 else
213 {
209 - // Start the package state at the the highest state then loop through all the
214 + // Start the package state at the highest state then loop through all the
215 // target product codes and end up setting the current state to the lowest
211 - // package state applied to the the target product codes.
216 + // package state applied to the target product codes.
217 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED;
218
219 for (DWORD i = 0; i < pPackage->Msp.cTargetProductCodes; ++i)
220 {
221 BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + i;
222 + BOOL fInstalled = FALSE;
223
224 hr = WiuGetPatchInfoEx(pPackage->Msp.sczPatchCode, pTargetProduct->wzTargetProductCode, NULL, pTargetProduct->context, INSTALLPROPERTY_PATCHSTATE, &sczState);
225 if (SUCCEEDED(hr))
@@ -221,14 +227,17 @@ extern "C" HRESULT MspEngineDetectPackage(
227 switch (*sczState)
228 {
229 case '1':
230 + fInstalled = TRUE;
231 pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT;
232 break;
233
234 case '2':
235 + fInstalled = TRUE;
236 pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED;
237 break;
238
239 case '4':
240 + fInstalled = TRUE;
241 pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE;
242 break;
243
@@ -249,6 +258,16 @@ extern "C" HRESULT MspEngineDetectPackage(
258 pPackage->currentState = pTargetProduct->patchPackageState;
259 }
260
261 + if (pPackage->fCanAffectRegistration)
262 + {
263 + pTargetProduct->registrationState = fInstalled ? BURN_PACKAGE_REGISTRATION_STATE_PRESENT : BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
264 +
265 + if (fInstalled)
266 + {
267 + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
268 + }
269 + }
270 +
271 hr = UserExperienceOnDetectTargetMsiPackage(pUserExperience, pPackage->sczId, pTargetProduct->wzTargetProductCode, pTargetProduct->patchPackageState);
272 ExitOnRootFailure(hr, "BA aborted detect target MSI package.");
273 }
@@ -642,6 +661,92 @@ extern "C" void MspEngineSlipstreamUpdateState(
661 }
662 }
663
664 +extern "C" void MspEngineUpdateInstallRegistrationState(
665 + __in BURN_EXECUTE_ACTION* pAction,
666 + __in HRESULT hrExecute,
667 + __in BOOL fInsideMsiTransaction
668 + )
669 +{
670 + BURN_PACKAGE_REGISTRATION_STATE newState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
671 +
672 + if (FAILED(hrExecute))
673 + {
674 + ExitFunction();
675 + }
676 +
677 + if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pAction->mspTarget.action)
678 + {
679 + newState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
680 + }
681 + else
682 + {
683 + newState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
684 + }
685 +
686 + for (DWORD i = 0; i < pAction->mspTarget.cOrderedPatches; ++i)
687 + {
688 + BURN_ORDERED_PATCHES* pOrderedPatches = pAction->mspTarget.rgOrderedPatches + i;
689 + BURN_PACKAGE* pPackage = pOrderedPatches->pPackage;
690 + BURN_MSPTARGETPRODUCT* pTargetProduct = NULL;
691 +
692 + Assert(BURN_PACKAGE_TYPE_MSP == pPackage->type);
693 +
694 + if (!pPackage->fCanAffectRegistration)
695 + {
696 + continue;
697 + }
698 +
699 + for (DWORD j = 0; j < pPackage->Msp.cTargetProductCodes; ++j)
700 + {
701 + pTargetProduct = pPackage->Msp.rgTargetProducts + j;
702 + if (pAction->mspTarget.fPerMachineTarget == (MSIINSTALLCONTEXT_MACHINE == pTargetProduct->context) &&
703 + CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pAction->mspTarget.sczTargetProductCode, -1, pTargetProduct->wzTargetProductCode, -1))
704 + {
705 + break;
706 + }
707 +
708 + pTargetProduct = NULL;
709 + }
710 +
711 + if (!pTargetProduct)
712 + {
713 + AssertSz(pTargetProduct, "Ordered patch didn't have corresponding target product");
714 + continue;
715 + }
716 +
717 + if (fInsideMsiTransaction)
718 + {
719 + pTargetProduct->transactionRegistrationState = newState;
720 + }
721 + else
722 + {
723 + pTargetProduct->registrationState = newState;
724 + }
725 + }
726 +
727 +LExit:
728 + return;
729 +}
730 +
731 +extern "C" void MspEngineFinalizeInstallRegistrationState(
732 + __in BURN_PACKAGE* pPackage
733 + )
734 +{
735 + Assert(pPackage->fCanAffectRegistration);
736 + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
737 +
738 + for (DWORD i = 0; i < pPackage->Msp.cTargetProductCodes; ++i)
739 + {
740 + BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + i;
741 +
742 + if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pTargetProduct->registrationState)
743 + {
744 + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
745 + break;
746 + }
747 + }
748 +}
749 +
750
751 // internal helper functions
752
src/engine/mspengine.h
+8
@@ -62,6 +62,14 @@ void MspEngineSlipstreamUpdateState(
62 __in BOOTSTRAPPER_ACTION_STATE execute,
63 __in BOOTSTRAPPER_ACTION_STATE rollback
64 );
65 +void MspEngineUpdateInstallRegistrationState(
66 + __in BURN_EXECUTE_ACTION* pAction,
67 + __in HRESULT hrExecute,
68 + __in BOOL fInsideMsiTransaction
69 + );
70 +void MspEngineFinalizeInstallRegistrationState(
71 + __in BURN_PACKAGE* pPackage
72 + );
73
74
75 #if defined(__cplusplus)
src/engine/msuengine.cpp
+30
@@ -69,6 +69,11 @@ extern "C" HRESULT MsuEngineDetectPackage(
69 // update detect state
70 pPackage->currentState = fDetected ? BOOTSTRAPPER_PACKAGE_STATE_PRESENT : BOOTSTRAPPER_PACKAGE_STATE_ABSENT;
71
72 + if (pPackage->fCanAffectRegistration)
73 + {
74 + pPackage->installRegistrationState = BOOTSTRAPPER_PACKAGE_STATE_CACHED < pPackage->currentState ? BURN_PACKAGE_REGISTRATION_STATE_PRESENT : BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
75 + }
76 +
77 LExit:
78 return hr;
79 }
@@ -424,6 +429,31 @@ LExit:
429 return hr;
430 }
431
432 +extern "C" void MsuEngineUpdateInstallRegistrationState(
433 + __in BURN_EXECUTE_ACTION* pAction,
434 + __in HRESULT hrExecute
435 + )
436 +{
437 + BURN_PACKAGE* pPackage = pAction->msuPackage.pPackage;
438 +
439 + if (FAILED(hrExecute) || !pPackage->fCanAffectRegistration)
440 + {
441 + ExitFunction();
442 + }
443 +
444 + if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pAction->msuPackage.action)
445 + {
446 + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
447 + }
448 + else
449 + {
450 + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
451 + }
452 +
453 +LExit:
454 + return;
455 +}
456 +
457 static HRESULT EnsureWUServiceEnabled(
458 __in BOOL fStopWusaService,
459 __out SC_HANDLE* pschWu,
src/engine/msuengine.h
+4
@@ -41,6 +41,10 @@ HRESULT MsuEngineExecutePackage(
41 __in LPVOID pvContext,
42 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
43 );
44 +void MsuEngineUpdateInstallRegistrationState(
45 + __in BURN_EXECUTE_ACTION* pAction,
46 + __in HRESULT hrExecute
47 + );
48
49
50 #if defined(__cplusplus)
src/engine/package.cpp
+1
@@ -156,6 +156,7 @@ extern "C" HRESULT PackagesParseFromXml(
156 hr = XmlGetYesNoAttribute(pixnNode, L"Permanent", &pPackage->fUninstallable);
157 ExitOnFailure(hr, "Failed to get @Permanent.");
158 pPackage->fUninstallable = !pPackage->fUninstallable; // TODO: change "Uninstallable" variable name to permanent, until then Uninstallable is the opposite of Permanent so fix the variable.
159 + pPackage->fCanAffectRegistration = pPackage->fUninstallable;
160
161 // @Vital
162 hr = XmlGetYesNoAttribute(pixnNode, L"Vital", &pPackage->fVital);
src/engine/package.h
+18
@@ -78,6 +78,14 @@ enum BOOTSTRAPPER_FEATURE_ACTION
78 BOOTSTRAPPER_FEATURE_ACTION_REMOVE,
79 };
80
81 +enum BURN_PACKAGE_REGISTRATION_STATE
82 +{
83 + BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN,
84 + BURN_PACKAGE_REGISTRATION_STATE_IGNORED,
85 + BURN_PACKAGE_REGISTRATION_STATE_ABSENT,
86 + BURN_PACKAGE_REGISTRATION_STATE_PRESENT,
87 +};
88 +
89 // structs
90
91 typedef struct _BURN_EXE_EXIT_CODE
@@ -106,6 +114,9 @@ typedef struct _BURN_MSPTARGETPRODUCT
114 BOOTSTRAPPER_PACKAGE_STATE patchPackageState; // only valid after Detect.
115 BOOTSTRAPPER_ACTION_STATE execute; // only valid during Plan.
116 BOOTSTRAPPER_ACTION_STATE rollback; // only valid during Plan.
117 +
118 + BURN_PACKAGE_REGISTRATION_STATE registrationState; // initialized during Detect, updated during Apply.
119 + BURN_PACKAGE_REGISTRATION_STATE transactionRegistrationState;// only valid during Apply inside an MSI transaction.
120 } BURN_MSPTARGETPRODUCT;
121
122 typedef struct _BURN_MSIPROPERTY
@@ -190,6 +201,7 @@ typedef struct _BURN_PACKAGE
201 BOOL fPerMachine;
202 BOOL fUninstallable;
203 BOOL fVital;
204 + BOOL fCanAffectRegistration;
205
206 BURN_CACHE_TYPE cacheType;
207 LPWSTR sczCacheId;
@@ -216,6 +228,12 @@ typedef struct _BURN_PACKAGE
228 BOOL fDependencyManagerWasHere; // only valid during Plan.
229 HRESULT hrCacheResult; // only valid during Apply.
230
231 + BURN_PACKAGE_REGISTRATION_STATE cacheRegistrationState; // initialized during Detect, updated during Apply.
232 + BURN_PACKAGE_REGISTRATION_STATE installRegistrationState; // initialized during Detect, updated during Apply.
233 + BURN_PACKAGE_REGISTRATION_STATE expectedCacheRegistrationState; // only valid after Plan.
234 + BURN_PACKAGE_REGISTRATION_STATE expectedInstallRegistrationState;// only valid after Plan.
235 + BURN_PACKAGE_REGISTRATION_STATE transactionRegistrationState; // only valid during Apply inside an MSI transaction.
236 +
237 BURN_PACKAGE_PAYLOAD* rgPayloads;
238 DWORD cPayloads;
239
src/engine/plan.cpp
+60 -132
@@ -6,13 +6,6 @@
6
7 // internal struct definitions
8
9 -struct PLAN_NONPERMANENT_PACKAGE_INDICES
10 -{
11 - DWORD iAfterExecuteFirstNonPermanentPackage;
12 - DWORD iBeforeRollbackFirstNonPermanentPackage;
13 - DWORD iAfterExecuteLastNonPermanentPackage;
14 - DWORD iAfterRollbackLastNonPermanentPackage;
15 -};
9
10 // internal function definitions
11
@@ -39,8 +32,7 @@ static HRESULT ProcessPackage(
32 __in BOOTSTRAPPER_RELATION_TYPE relationType,
33 __in_z_opt LPCWSTR wzLayoutDirectory,
34 __inout HANDLE* phSyncpointEvent,
42 - __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary,
43 - __in_opt PLAN_NONPERMANENT_PACKAGE_INDICES* pNonpermanentPackageIndices
35 + __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary
36 );
37 static HRESULT ProcessPackageRollbackBoundary(
38 __in BURN_PLAN* pPlan,
@@ -479,7 +471,7 @@ extern "C" HRESULT PlanPackages(
471 __in BURN_PLAN* pPlan,
472 __in BURN_LOGGING* pLog,
473 __in BURN_VARIABLES* pVariables,
482 - __in BOOL fBundleInstalled,
474 + __in BOOL /*fBundleInstalled*/,
475 __in BOOTSTRAPPER_DISPLAY display,
476 __in BOOTSTRAPPER_RELATION_TYPE relationType,
477 __in_z_opt LPCWSTR wzLayoutDirectory,
@@ -490,12 +482,6 @@ extern "C" HRESULT PlanPackages(
482 BOOL fBundlePerMachine = pPlan->fPerMachine; // bundle is per-machine if plan starts per-machine.
483 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL;
484
493 - PLAN_NONPERMANENT_PACKAGE_INDICES nonpermanentPackageIndices;
494 - nonpermanentPackageIndices.iAfterExecuteFirstNonPermanentPackage = BURN_PLAN_INVALID_ACTION_INDEX;
495 - nonpermanentPackageIndices.iBeforeRollbackFirstNonPermanentPackage = BURN_PLAN_INVALID_ACTION_INDEX;
496 - nonpermanentPackageIndices.iAfterExecuteLastNonPermanentPackage = BURN_PLAN_INVALID_ACTION_INDEX;
497 - nonpermanentPackageIndices.iAfterRollbackLastNonPermanentPackage = BURN_PLAN_INVALID_ACTION_INDEX;
498 -
485 // Plan the packages.
486 for (DWORD i = 0; i < pPackages->cPackages; ++i)
487 {
@@ -518,34 +504,10 @@ extern "C" HRESULT PlanPackages(
504 }
505 }
506
521 - hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, relationType, wzLayoutDirectory, phSyncpointEvent, &pRollbackBoundary, &nonpermanentPackageIndices);
507 + hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, relationType, wzLayoutDirectory, phSyncpointEvent, &pRollbackBoundary);
508 ExitOnFailure(hr, "Failed to process package.");
509 }
510
525 - // Insert the "keep registration" and "remove registration" actions in the plan when installing the first time and anytime we are uninstalling respectively.
526 - if (!fBundleInstalled && (BOOTSTRAPPER_ACTION_INSTALL == pPlan->action || BOOTSTRAPPER_ACTION_MODIFY == pPlan->action || BOOTSTRAPPER_ACTION_REPAIR == pPlan->action))
527 - {
528 - if (BURN_PLAN_INVALID_ACTION_INDEX == nonpermanentPackageIndices.iAfterExecuteFirstNonPermanentPackage)
529 - {
530 - nonpermanentPackageIndices.iAfterExecuteFirstNonPermanentPackage = pPlan->cExecuteActions;
531 - nonpermanentPackageIndices.iBeforeRollbackFirstNonPermanentPackage = pPlan->cRollbackActions;
532 - }
533 -
534 - hr = PlanKeepRegistration(pPlan, nonpermanentPackageIndices.iAfterExecuteFirstNonPermanentPackage, nonpermanentPackageIndices.iBeforeRollbackFirstNonPermanentPackage);
535 - ExitOnFailure(hr, "Failed to plan install keep registration.");
536 - }
537 - else if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action)
538 - {
539 - if (BURN_PLAN_INVALID_ACTION_INDEX == nonpermanentPackageIndices.iAfterExecuteLastNonPermanentPackage)
540 - {
541 - nonpermanentPackageIndices.iAfterExecuteLastNonPermanentPackage = pPlan->cExecuteActions;
542 - nonpermanentPackageIndices.iAfterRollbackLastNonPermanentPackage = pPlan->cRollbackActions;
543 - }
544 -
545 - hr = PlanRemoveRegistration(pPlan, nonpermanentPackageIndices.iAfterExecuteLastNonPermanentPackage, nonpermanentPackageIndices.iAfterRollbackLastNonPermanentPackage);
546 - ExitOnFailure(hr, "Failed to plan uninstall remove registration.");
547 - }
548 -
511 // If we still have an open rollback boundary, complete it.
512 if (pRollbackBoundary)
513 {
@@ -572,9 +534,9 @@ LExit:
534 extern "C" HRESULT PlanRegistration(
535 __in BURN_PLAN* pPlan,
536 __in BURN_REGISTRATION* pRegistration,
575 - __in BOOTSTRAPPER_RESUME_TYPE resumeType,
537 + __in BOOTSTRAPPER_RESUME_TYPE /*resumeType*/,
538 __in BOOTSTRAPPER_RELATION_TYPE relationType,
577 - __out BOOL* pfContinuePlanning
539 + __inout BOOL* pfContinuePlanning
540 )
541 {
542 HRESULT hr = S_OK;
@@ -583,9 +545,6 @@ extern "C" HRESULT PlanRegistration(
545
546 pPlan->fRegister = TRUE; // register the bundle since we're modifying machine state.
547
586 - // Keep the registration if the bundle was already installed or we are planning after a restart.
587 - pPlan->fKeepRegistrationDefault = (pRegistration->fInstalled || BOOTSTRAPPER_RESUME_TYPE_REBOOT == resumeType);
588 -
548 pPlan->fDisallowRemoval = FALSE; // by default the bundle can be planned to be removed
549
550 if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action)
@@ -692,7 +651,7 @@ extern "C" HRESULT PlanRegistration(
651 pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE;
652 pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION;
653 }
695 - else if (BOOTSTRAPPER_ACTION_REPAIR == pPlan->action && !CacheBundleRunningFromCache()) // repairing but not not running from the cache.
654 + else if (BOOTSTRAPPER_ACTION_REPAIR == pPlan->action && !CacheBundleRunningFromCache()) // repairing but not running from the cache.
655 {
656 pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE;
657 pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION;
@@ -786,7 +745,7 @@ extern "C" HRESULT PlanPassThroughBundle(
745 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL;
746
747 // Plan passthrough package.
789 - hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, relationType, NULL, phSyncpointEvent, &pRollbackBoundary, NULL);
748 + hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, relationType, NULL, phSyncpointEvent, &pRollbackBoundary);
749 ExitOnFailure(hr, "Failed to process passthrough package.");
750
751 // If we still have an open rollback boundary, complete it.
@@ -820,7 +779,7 @@ extern "C" HRESULT PlanUpdateBundle(
779 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL;
780
781 // Plan update package.
823 - hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, relationType, NULL, phSyncpointEvent, &pRollbackBoundary, NULL);
782 + hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, relationType, NULL, phSyncpointEvent, &pRollbackBoundary);
783 ExitOnFailure(hr, "Failed to process update package.");
784
785 // If we still have an open rollback boundary, complete it.
@@ -849,8 +808,7 @@ static HRESULT ProcessPackage(
808 __in BOOTSTRAPPER_RELATION_TYPE relationType,
809 __in_z_opt LPCWSTR wzLayoutDirectory,
810 __inout HANDLE* phSyncpointEvent,
852 - __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary,
853 - __in_opt PLAN_NONPERMANENT_PACKAGE_INDICES* pNonpermanentPackageIndices
811 + __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary
812 )
813 {
814 HRESULT hr = S_OK;
@@ -871,6 +829,12 @@ static HRESULT ProcessPackage(
829 hr = ProcessPackageRollbackBoundary(pPlan, pEffectiveRollbackBoundary, ppRollbackBoundary);
830 ExitOnFailure(hr, "Failed to process package rollback boundary.");
831
832 + if (pPackage->fCanAffectRegistration)
833 + {
834 + pPackage->expectedCacheRegistrationState = pPackage->cacheRegistrationState;
835 + pPackage->expectedInstallRegistrationState = pPackage->installRegistrationState;
836 + }
837 +
838 // If the package is in a requested state, plan it.
839 if (BOOTSTRAPPER_REQUEST_STATE_NONE != pPackage->requested)
840 {
@@ -881,26 +845,19 @@ static HRESULT ProcessPackage(
845 }
846 else
847 {
884 - if (pPackage->fUninstallable && pNonpermanentPackageIndices)
885 - {
886 - if (BURN_PLAN_INVALID_ACTION_INDEX == pNonpermanentPackageIndices->iBeforeRollbackFirstNonPermanentPackage)
887 - {
888 - pNonpermanentPackageIndices->iBeforeRollbackFirstNonPermanentPackage = pPlan->cRollbackActions;
889 - }
890 - }
891 -
848 hr = PlanExecutePackage(fBundlePerMachine, display, pUX, pPlan, pPackage, pLog, pVariables, phSyncpointEvent);
849 ExitOnFailure(hr, "Failed to plan execute package.");
850
895 - if (pPackage->fUninstallable && pNonpermanentPackageIndices)
851 + if (pPackage->fCanAffectRegistration)
852 {
897 - if (BURN_PLAN_INVALID_ACTION_INDEX == pNonpermanentPackageIndices->iAfterExecuteFirstNonPermanentPackage)
853 + if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL < pPackage->execute)
854 {
899 - pNonpermanentPackageIndices->iAfterExecuteFirstNonPermanentPackage = pPlan->cExecuteActions - 1;
855 + pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
856 + }
857 + else if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pPackage->execute)
858 + {
859 + pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
860 }
901 -
902 - pNonpermanentPackageIndices->iAfterExecuteLastNonPermanentPackage = pPlan->cExecuteActions;
903 - pNonpermanentPackageIndices->iAfterRollbackLastNonPermanentPackage = pPlan->cRollbackActions;
861 }
862 }
863 }
@@ -920,6 +877,32 @@ static HRESULT ProcessPackage(
877 }
878 }
879
880 + if (pPackage->fCanAffectRegistration)
881 + {
882 + if (BURN_DEPENDENCY_ACTION_REGISTER == pPackage->dependencyExecute)
883 + {
884 + if (BURN_PACKAGE_REGISTRATION_STATE_IGNORED == pPackage->expectedCacheRegistrationState)
885 + {
886 + pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
887 + }
888 + if (BURN_PACKAGE_REGISTRATION_STATE_IGNORED == pPackage->expectedInstallRegistrationState)
889 + {
890 + pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
891 + }
892 + }
893 + else if (BURN_DEPENDENCY_ACTION_UNREGISTER == pPackage->dependencyExecute)
894 + {
895 + if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->expectedCacheRegistrationState)
896 + {
897 + pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED;
898 + }
899 + if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->expectedInstallRegistrationState)
900 + {
901 + pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED;
902 + }
903 + }
904 + }
905 +
906 // Add the checkpoint after each package and dependency registration action.
907 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute || BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->rollback || BURN_DEPENDENCY_ACTION_NONE != pPackage->dependencyExecute)
908 {
@@ -1572,6 +1555,11 @@ extern "C" HRESULT PlanCleanPackage(
1555 pCleanAction->pPackage = pPackage;
1556
1557 pPackage->fUncache = TRUE;
1558 +
1559 + if (pPackage->fCanAffectRegistration)
1560 + {
1561 + pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
1562 + }
1563 }
1564
1565 LExit:
@@ -1708,68 +1696,6 @@ LExit:
1696 return hr;
1697 }
1698
1711 -extern "C" HRESULT PlanKeepRegistration(
1712 - __in BURN_PLAN* pPlan,
1713 - __in DWORD iAfterExecutePackageAction,
1714 - __in DWORD iBeforeRollbackPackageAction
1715 - )
1716 -{
1717 - HRESULT hr = S_OK;
1718 - BURN_EXECUTE_ACTION* pAction = NULL;
1719 -
1720 - if (BURN_PLAN_INVALID_ACTION_INDEX != iAfterExecutePackageAction)
1721 - {
1722 - hr = PlanInsertExecuteAction(iAfterExecutePackageAction, pPlan, &pAction);
1723 - ExitOnFailure(hr, "Failed to insert keep registration execute action.");
1724 -
1725 - pAction->type = BURN_EXECUTE_ACTION_TYPE_REGISTRATION;
1726 - pAction->registration.fKeep = TRUE;
1727 - }
1728 -
1729 - if (BURN_PLAN_INVALID_ACTION_INDEX != iBeforeRollbackPackageAction)
1730 - {
1731 - hr = PlanInsertRollbackAction(iBeforeRollbackPackageAction, pPlan, &pAction);
1732 - ExitOnFailure(hr, "Failed to insert keep registration rollback action.");
1733 -
1734 - pAction->type = BURN_EXECUTE_ACTION_TYPE_REGISTRATION;
1735 - pAction->registration.fKeep = FALSE;
1736 - }
1737 -
1738 -LExit:
1739 - return hr;
1740 -}
1741 -
1742 -extern "C" HRESULT PlanRemoveRegistration(
1743 - __in BURN_PLAN* pPlan,
1744 - __in DWORD iAfterExecutePackageAction,
1745 - __in DWORD iAfterRollbackPackageAction
1746 - )
1747 -{
1748 - HRESULT hr = S_OK;
1749 - BURN_EXECUTE_ACTION* pAction = NULL;
1750 -
1751 - if (BURN_PLAN_INVALID_ACTION_INDEX != iAfterExecutePackageAction)
1752 - {
1753 - hr = PlanInsertExecuteAction(iAfterExecutePackageAction, pPlan, &pAction);
1754 - ExitOnFailure(hr, "Failed to insert remove registration execute action.");
1755 -
1756 - pAction->type = BURN_EXECUTE_ACTION_TYPE_REGISTRATION;
1757 - pAction->registration.fKeep = FALSE;
1758 - }
1759 -
1760 - if (BURN_PLAN_INVALID_ACTION_INDEX != iAfterRollbackPackageAction)
1761 - {
1762 - hr = PlanInsertRollbackAction(iAfterRollbackPackageAction, pPlan, &pAction);
1763 - ExitOnFailure(hr, "Failed to insert remove registration rollback action.");
1764 -
1765 - pAction->type = BURN_EXECUTE_ACTION_TYPE_REGISTRATION;
1766 - pAction->registration.fKeep = TRUE;
1767 - }
1768 -
1769 -LExit:
1770 - return hr;
1771 -}
1772 -
1699 extern "C" HRESULT PlanRollbackBoundaryBegin(
1700 __in BURN_PLAN* pPlan,
1701 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary
@@ -1925,6 +1851,8 @@ static void ResetPlannedPackageState(
1851 pPackage->dependencyExecute = BURN_DEPENDENCY_ACTION_NONE;
1852 pPackage->dependencyRollback = BURN_DEPENDENCY_ACTION_NONE;
1853 pPackage->fDependencyManagerWasHere = FALSE;
1854 + pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
1855 + pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
1856
1857 if (BURN_PACKAGE_TYPE_MSI == pPackage->type && pPackage->Msi.rgFeatures)
1858 {
@@ -2198,6 +2126,11 @@ static HRESULT AddCachePackageHelper(
2126 // did cache operations to verify the cache is valid so we did not plan the acquisition of the package.
2127 pPackage->fAcquire = (BURN_CACHE_STATE_COMPLETE != pPackage->cache);
2128
2129 + if (pPackage->fCanAffectRegistration)
2130 + {
2131 + pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
2132 + }
2133 +
2134 LExit:
2135 return hr;
2136 }
@@ -3118,10 +3051,6 @@ static void ExecuteActionLog(
3051 LogStringLine(PlanDumpLevel, "%ls action[%u]: MSU_PACKAGE package id: %ls, action: %hs, log path: %ls", wzBase, iAction, pAction->msuPackage.pPackage->sczId, LoggingActionStateToString(pAction->msuPackage.action), pAction->msuPackage.sczLogPath);
3052 break;
3053
3121 - case BURN_EXECUTE_ACTION_TYPE_REGISTRATION:
3122 - LogStringLine(PlanDumpLevel, "%ls action[%u]: REGISTRATION keep: %ls", wzBase, iAction, pAction->registration.fKeep ? L"yes" : L"no");
3123 - break;
3124 -
3054 case BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY:
3055 LogStringLine(PlanDumpLevel, "%ls action[%u]: ROLLBACK_BOUNDARY id: %ls, vital: %ls", wzBase, iAction, pAction->rollbackBoundary.pRollbackBoundary->sczId, pAction->rollbackBoundary.pRollbackBoundary->fVital ? L"yes" : L"no");
3056 break;
@@ -3157,7 +3086,6 @@ extern "C" void PlanDump(
3086 LogStringLine(PlanDumpLevel, "Plan action: %hs", LoggingBurnActionToString(pPlan->action));
3087 LogStringLine(PlanDumpLevel, " per-machine: %hs", LoggingTrueFalseToString(pPlan->fPerMachine));
3088 LogStringLine(PlanDumpLevel, " disable-rollback: %hs", LoggingTrueFalseToString(pPlan->fDisableRollback));
3160 - LogStringLine(PlanDumpLevel, " keep registration by default: %hs", LoggingTrueFalseToString(pPlan->fKeepRegistrationDefault));
3089 LogStringLine(PlanDumpLevel, " estimated size: %llu", pPlan->qwEstimatedSize);
3090
3091 LogStringLine(PlanDumpLevel, "Plan cache size: %llu", pPlan->qwCacheSizeTotal);
src/engine/plan.h
+1 -17
@@ -64,7 +64,6 @@ enum BURN_EXECUTE_ACTION_TYPE
64 BURN_EXECUTE_ACTION_TYPE_PACKAGE_PROVIDER,
65 BURN_EXECUTE_ACTION_TYPE_PACKAGE_DEPENDENCY,
66 BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY,
67 - BURN_EXECUTE_ACTION_TYPE_REGISTRATION,
67 BURN_EXECUTE_ACTION_TYPE_BEGIN_MSI_TRANSACTION,
68 BURN_EXECUTE_ACTION_TYPE_COMMIT_MSI_TRANSACTION,
69 };
@@ -281,10 +280,6 @@ typedef struct _BURN_EXECUTE_ACTION
280 BOOTSTRAPPER_ACTION_STATE action;
281 } msuPackage;
282 struct
284 - {
285 - BOOL fKeep;
286 - } registration;
287 - struct
283 {
284 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary;
285 } rollbackBoundary;
@@ -319,7 +314,6 @@ typedef struct _BURN_PLAN
314 BOOL fPerMachine;
315 BOOL fRegister;
316 DWORD dwRegistrationOperations;
322 - BOOL fKeepRegistrationDefault;
317 BOOL fDisallowRemoval;
318 BOOL fDisableRollback;
319
@@ -418,7 +412,7 @@ HRESULT PlanRegistration(
412 __in BURN_REGISTRATION* pRegistration,
413 __in BOOTSTRAPPER_RESUME_TYPE resumeType,
414 __in BOOTSTRAPPER_RELATION_TYPE relationType,
421 - __out BOOL* pfContinuePlanning
415 + __inout BOOL* pfContinuePlanning
416 );
417 HRESULT PlanPassThroughBundle(
418 __in BURN_USER_EXPERIENCE* pUX,
@@ -519,16 +513,6 @@ HRESULT PlanAppendRollbackAction(
513 __in BURN_PLAN* pPlan,
514 __out BURN_EXECUTE_ACTION** ppExecuteAction
515 );
522 -HRESULT PlanKeepRegistration(
523 - __in BURN_PLAN* pPlan,
524 - __in DWORD iAfterExecutePackageAction,
525 - __in DWORD iBeforeRollbackPackageAction
526 - );
527 -HRESULT PlanRemoveRegistration(
528 - __in BURN_PLAN* pPlan,
529 - __in DWORD iAfterExecutePackageAction,
530 - __in DWORD iAfterRollbackPackageAction
531 - );
516 HRESULT PlanRollbackBoundaryBegin(
517 __in BURN_PLAN* pPlan,
518 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary
src/test/BurnUnitTest/BurnTestFixture.h
+2
@@ -35,6 +35,8 @@ namespace Bootstrapper
35
36 LogInitialize(::GetModuleHandleW(NULL));
37
38 + LogSetLevel(REPORT_DEBUG, FALSE);
39 +
40 hr = LogOpen(NULL, L"BurnUnitTest", NULL, L"txt", FALSE, FALSE, NULL);
41 TestThrowOnFailure(hr, L"Failed to open log.");
42 }
src/test/BurnUnitTest/PlanTest.cpp
+201 -59
@@ -50,13 +50,12 @@ namespace Bootstrapper
50 Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_INSTALL, pPlan->action);
51 Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine);
52 Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback);
53 - Assert::Equal<BOOL>(FALSE, pPlan->fKeepRegistrationDefault);
53
54 BOOL fRollback = FALSE;
55 DWORD dwIndex = 0;
56 DWORD dwPackageStart = 0;
57 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
59 - dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", 6, 2, 33743, FALSE);
58 + dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, 6, 2, 33743, FALSE);
59 ValidateCacheAcquireContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE);
60 ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, dwPackageStart, 6);
61 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"PackageA", TRUE, FALSE, dwPackageStart);
@@ -64,7 +63,7 @@ namespace Bootstrapper
63 ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PackageA", FALSE);
64 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE);
65 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 9);
67 - dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageB", 14, 2, 33743, FALSE);
66 + dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageB", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, 14, 2, 33743, FALSE);
67 ValidateCacheAcquireContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", TRUE);
68 ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, dwPackageStart, 2);
69 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageB", L"PackageB", TRUE, FALSE, dwPackageStart);
@@ -72,7 +71,7 @@ namespace Bootstrapper
71 ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PackageB", FALSE);
72 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE);
73 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 14);
75 - dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageC", 22, 2, 33743, FALSE);
74 + dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageC", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, 22, 2, 33743, FALSE);
75 ValidateCacheAcquireContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", TRUE);
76 ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, dwPackageStart, 2);
77 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageC", L"PackageC", TRUE, FALSE, dwPackageStart);
@@ -99,9 +98,8 @@ namespace Bootstrapper
98 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
99 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER);
100 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
102 - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
101 + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
102 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
104 - ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, TRUE);
103 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", BURN_DEPENDENCY_ACTION_REGISTER);
104 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
105 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -113,7 +111,7 @@ namespace Bootstrapper
111 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
112 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
113 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageB", BURN_DEPENDENCY_ACTION_REGISTER);
116 - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageB", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
114 + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageB", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
115 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
116 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", BURN_DEPENDENCY_ACTION_REGISTER);
117 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -122,26 +120,25 @@ namespace Bootstrapper
120 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
121 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
122 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageC", BURN_DEPENDENCY_ACTION_REGISTER);
125 - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageC", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
123 + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageC", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
124 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
125 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageC", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", BURN_DEPENDENCY_ACTION_REGISTER);
126 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
127 ValidateExecuteCommitMsiTransaction(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ");
128 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
129 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[23].syncpoint.hEvent);
132 - ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
130 + ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN, BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
131 Assert::Equal(dwIndex, pPlan->cExecuteActions);
132
133 fRollback = TRUE;
134 dwIndex = 0;
135 dwExecuteCheckpointId = 2;
136 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
139 - ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, FALSE);
137 ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
138 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
139 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_UNREGISTER);
140 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
144 - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
141 + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
142 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
143 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", BURN_DEPENDENCY_ACTION_UNREGISTER);
144 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -166,7 +163,7 @@ namespace Bootstrapper
163 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
164 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
165 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
169 - ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
166 + ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN, BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
167 Assert::Equal(dwIndex, pPlan->cRollbackActions);
168
169 Assert::Equal(4ul, pPlan->cExecutePackagesTotal);
@@ -197,7 +194,6 @@ namespace Bootstrapper
194 Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_UNINSTALL, pPlan->action);
195 Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine);
196 Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback);
200 - Assert::Equal<BOOL>(TRUE, pPlan->fKeepRegistrationDefault);
197
198 BOOL fRollback = FALSE;
199 DWORD dwIndex = 0;
@@ -220,13 +216,13 @@ namespace Bootstrapper
216 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageC", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", BURN_DEPENDENCY_ACTION_UNREGISTER);
217 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
218 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageC", BURN_DEPENDENCY_ACTION_UNREGISTER);
223 - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageC", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
219 + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageC", BURN_PACKAGE_REGISTRATION_STATE_ABSENT, BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
220 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
221 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
222 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", BURN_DEPENDENCY_ACTION_UNREGISTER);
223 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
224 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageB", BURN_DEPENDENCY_ACTION_UNREGISTER);
229 - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageB", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
225 + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageB", BURN_PACKAGE_REGISTRATION_STATE_ABSENT, BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
226 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
227 ValidateExecuteCommitMsiTransaction(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ");
228 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -236,8 +232,7 @@ namespace Bootstrapper
232 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
233 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_UNREGISTER);
234 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
239 - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
240 - ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, FALSE);
235 + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_ABSENT, BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
236 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
237 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
238 Assert::Equal(dwIndex, pPlan->cExecuteActions);
@@ -263,9 +258,8 @@ namespace Bootstrapper
258 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
259 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER);
260 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
266 - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
261 + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_ABSENT, BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
262 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
268 - ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, TRUE);
263 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
264 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
265 Assert::Equal(dwIndex, pPlan->cRollbackActions);
@@ -274,9 +268,9 @@ namespace Bootstrapper
268 Assert::Equal(3ul, pPlan->cOverallProgressTicksTotal);
269
270 dwIndex = 0;
277 - ValidateCleanAction(pPlan, dwIndex++, L"PackageC");
278 - ValidateCleanAction(pPlan, dwIndex++, L"PackageB");
279 - ValidateCleanAction(pPlan, dwIndex++, L"PackageA");
271 + ValidateCleanAction(pPlan, dwIndex++, L"PackageC", BURN_PACKAGE_REGISTRATION_STATE_ABSENT);
272 + ValidateCleanAction(pPlan, dwIndex++, L"PackageB", BURN_PACKAGE_REGISTRATION_STATE_ABSENT);
273 + ValidateCleanAction(pPlan, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_ABSENT);
274 Assert::Equal(dwIndex, pPlan->cCleanActions);
275
276 UINT uIndex = 0;
@@ -306,13 +300,12 @@ namespace Bootstrapper
300 Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_CACHE, pPlan->action);
301 Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine);
302 Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback);
309 - Assert::Equal<BOOL>(FALSE, pPlan->fKeepRegistrationDefault);
303
304 BOOL fRollback = FALSE;
305 DWORD dwIndex = 0;
306 DWORD dwPackageStart = 0;
307 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
315 - dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", 5, 2, 33743, FALSE);
308 + dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, 5, 2, 33743, FALSE);
309 ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, BURN_PLAN_INVALID_ACTION_INDEX, 2);
310 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"PackageA", TRUE, FALSE, dwPackageStart);
311 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"cab9Ins_fTP3wNwq5Gxo41ch5VUPaQ", TRUE, FALSE, dwPackageStart);
@@ -378,13 +371,12 @@ namespace Bootstrapper
371 Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_INSTALL, pPlan->action);
372 Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine);
373 Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback);
381 - Assert::Equal<BOOL>(FALSE, pPlan->fKeepRegistrationDefault);
374
375 BOOL fRollback = FALSE;
376 DWORD dwIndex = 0;
377 DWORD dwPackageStart = 0;
378 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
387 - dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", 5, 2, 33743, FALSE);
379 + dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, 5, 2, 33743, FALSE);
380 ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, BURN_PLAN_INVALID_ACTION_INDEX, 2);
381 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"PackageA", TRUE, FALSE, dwPackageStart);
382 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"cab9Ins_fTP3wNwq5Gxo41ch5VUPaQ", TRUE, FALSE, dwPackageStart);
@@ -410,32 +402,30 @@ namespace Bootstrapper
402 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
403 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER);
404 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
413 - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
405 + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
406 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
415 - ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, TRUE);
407 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", BURN_DEPENDENCY_ACTION_REGISTER);
408 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
409 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
410 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[6].syncpoint.hEvent);
420 - ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
411 + ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN, BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
412 Assert::Equal(dwIndex, pPlan->cExecuteActions);
413
414 fRollback = TRUE;
415 dwIndex = 0;
416 dwExecuteCheckpointId = 2;
417 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
427 - ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, FALSE);
418 ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
419 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
420 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_UNREGISTER);
421 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
432 - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
422 + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
423 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
424 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", BURN_DEPENDENCY_ACTION_UNREGISTER);
425 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
426 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
427 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
438 - ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
428 + ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN, BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
429 Assert::Equal(dwIndex, pPlan->cRollbackActions);
430
431 Assert::Equal(2ul, pPlan->cExecutePackagesTotal);
@@ -449,6 +439,62 @@ namespace Bootstrapper
439 Assert::Equal(uIndex, pPlan->cPlannedProviders);
440 }
441
442 + [Fact]
443 + void SingleMsiInstalledWithNoInstalledPackagesModifyTest()
444 + {
445 + HRESULT hr = S_OK;
446 + BURN_ENGINE_STATE engineState = { };
447 + BURN_ENGINE_STATE* pEngineState = &engineState;
448 + BURN_PLAN* pPlan = &engineState.plan;
449 +
450 + InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState);
451 + PlanTestDetect(pEngineState);
452 +
453 + pEngineState->registration.fInstalled = TRUE;
454 +
455 + hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_MODIFY);
456 + NativeAssert::Succeeded(hr, "CorePlan failed");
457 +
458 + Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_MODIFY, pPlan->action);
459 + Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine);
460 + Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback);
461 +
462 + BOOL fRollback = FALSE;
463 + DWORD dwIndex = 0;
464 + Assert::Equal(dwIndex, pPlan->cCacheActions);
465 +
466 + fRollback = TRUE;
467 + dwIndex = 0;
468 + Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
469 +
470 + Assert::Equal(0ull, pPlan->qwEstimatedSize);
471 + Assert::Equal(0ull, pPlan->qwCacheSizeTotal);
472 +
473 + fRollback = FALSE;
474 + dwIndex = 0;
475 + DWORD dwExecuteCheckpointId = 1;
476 + ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
477 + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
478 + Assert::Equal(dwIndex, pPlan->cExecuteActions);
479 +
480 + fRollback = TRUE;
481 + dwIndex = 0;
482 + dwExecuteCheckpointId = 1;
483 + ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
484 + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
485 + Assert::Equal(dwIndex, pPlan->cRollbackActions);
486 +
487 + Assert::Equal(0ul, pPlan->cExecutePackagesTotal);
488 + Assert::Equal(0ul, pPlan->cOverallProgressTicksTotal);
489 +
490 + dwIndex = 0;
491 + Assert::Equal(dwIndex, pPlan->cCleanActions);
492 +
493 + UINT uIndex = 0;
494 + ValidatePlannedProvider(pPlan, uIndex++, L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", NULL);
495 + Assert::Equal(uIndex, pPlan->cPlannedProviders);
496 + }
497 +
498 [Fact]
499 void SingleMsiUninstallTest()
500 {
@@ -466,7 +512,6 @@ namespace Bootstrapper
512 Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_UNINSTALL, pPlan->action);
513 Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine);
514 Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback);
469 - Assert::Equal<BOOL>(TRUE, pPlan->fKeepRegistrationDefault);
515
516 BOOL fRollback = FALSE;
517 DWORD dwIndex = 0;
@@ -488,8 +533,7 @@ namespace Bootstrapper
533 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
534 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_UNREGISTER);
535 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
491 - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
492 - ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, FALSE);
536 + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_ABSENT, BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
537 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
538 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
539 Assert::Equal(dwIndex, pPlan->cExecuteActions);
@@ -502,9 +546,8 @@ namespace Bootstrapper
546 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
547 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER);
548 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
505 - ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
549 + ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_ABSENT, BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
550 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
507 - ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, TRUE);
551 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
552 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
553 Assert::Equal(dwIndex, pPlan->cRollbackActions);
@@ -513,7 +556,7 @@ namespace Bootstrapper
556 Assert::Equal(1ul, pPlan->cOverallProgressTicksTotal);
557
558 dwIndex = 0;
516 - ValidateCleanAction(pPlan, dwIndex++, L"PackageA");
559 + ValidateCleanAction(pPlan, dwIndex++, L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_ABSENT);
560 Assert::Equal(dwIndex, pPlan->cCleanActions);
561
562 UINT uIndex = 0;
@@ -522,6 +565,66 @@ namespace Bootstrapper
565 Assert::Equal(uIndex, pPlan->cPlannedProviders);
566 }
567
568 + [Fact]
569 + void SingleMsiUninstallTestFromUpgradeBundleWithSameExactPackage()
570 + {
571 + HRESULT hr = S_OK;
572 + BURN_ENGINE_STATE engineState = { };
573 + BURN_ENGINE_STATE* pEngineState = &engineState;
574 + BURN_PLAN* pPlan = &engineState.plan;
575 +
576 + InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState);
577 + DetectAsRelatedUpgradeBundle(&engineState, L"{02940F3E-C83E-452D-BFCF-C943777ACEAE}", L"2.0.0.0");
578 +
579 + hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_UNINSTALL);
580 + NativeAssert::Succeeded(hr, "CorePlan failed");
581 +
582 + Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_UNINSTALL, pPlan->action);
583 + Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine);
584 + Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback);
585 +
586 + BOOL fRollback = FALSE;
587 + DWORD dwIndex = 0;
588 + Assert::Equal(dwIndex, pPlan->cCacheActions);
589 +
590 + fRollback = TRUE;
591 + dwIndex = 0;
592 + Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
593 +
594 + Assert::Equal(0ull, pPlan->qwEstimatedSize);
595 + Assert::Equal(0ull, pPlan->qwCacheSizeTotal);
596 +
597 + fRollback = FALSE;
598 + dwIndex = 0;
599 + DWORD dwExecuteCheckpointId = 1;
600 + ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
601 + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
602 + ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", BURN_DEPENDENCY_ACTION_UNREGISTER);
603 + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
604 + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
605 + Assert::Equal(dwIndex, pPlan->cExecuteActions);
606 +
607 + fRollback = TRUE;
608 + dwIndex = 0;
609 + dwExecuteCheckpointId = 1;
610 + ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
611 + ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", BURN_DEPENDENCY_ACTION_REGISTER);
612 + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
613 + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
614 + ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
615 + Assert::Equal(dwIndex, pPlan->cRollbackActions);
616 +
617 + Assert::Equal(0ul, pPlan->cExecutePackagesTotal);
618 + Assert::Equal(0ul, pPlan->cOverallProgressTicksTotal);
619 +
620 + dwIndex = 0;
621 + Assert::Equal(dwIndex, pPlan->cCleanActions);
622 +
623 + UINT uIndex = 0;
624 + ValidatePlannedProvider(pPlan, uIndex++, L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", NULL);
625 + Assert::Equal(uIndex, pPlan->cPlannedProviders);
626 + }
627 +
628 private:
629 // This doesn't initialize everything, just enough for CorePlan to work.
630 void InitializeEngineStateForCorePlan(LPCWSTR wzManifestFileName, BURN_ENGINE_STATE* pEngineState)
@@ -586,12 +689,22 @@ namespace Bootstrapper
689 void DetectPackageAsAbsent(BURN_PACKAGE* pPackage)
690 {
691 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT;
692 + if (pPackage->fCanAffectRegistration)
693 + {
694 + pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
695 + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
696 + }
697 }
698
699 void DetectPackageAsPresentAndCached(BURN_PACKAGE* pPackage)
700 {
701 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT;
702 pPackage->cache = BURN_CACHE_STATE_COMPLETE;
703 + if (pPackage->fCanAffectRegistration)
704 + {
705 + pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
706 + pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
707 + }
708
709 for (DWORD i = 0; i < pPackage->cPayloads; ++i)
710 {
@@ -599,6 +712,19 @@ namespace Bootstrapper
712 }
713 }
714
715 + void DetectPackageDependent(BURN_PACKAGE* pPackage, LPCWSTR wzId)
716 + {
717 + HRESULT hr = S_OK;
718 +
719 + for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i)
720 + {
721 + BURN_DEPENDENCY_PROVIDER* pProvider = pPackage->rgDependencyProviders + i;
722 +
723 + hr = DepDependencyArrayAlloc(&pProvider->rgDependents, &pProvider->cDependents, wzId, NULL);
724 + NativeAssert::Succeeded(hr, "Failed to add package dependent");
725 + }
726 + }
727 +
728 void DetectPackagesAsAbsent(BURN_ENGINE_STATE* pEngineState)
729 {
730 PlanTestDetect(pEngineState);
@@ -620,6 +746,7 @@ namespace Bootstrapper
746 {
747 BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i;
748 DetectPackageAsPresentAndCached(pPackage);
749 + DetectPackageDependent(pPackage, pEngineState->registration.sczId);
750 }
751 }
752
@@ -639,11 +766,12 @@ namespace Bootstrapper
766 else
767 {
768 DetectPackageAsPresentAndCached(pPackage);
769 + DetectPackageDependent(pPackage, pEngineState->registration.sczId);
770 }
771 }
772 }
773
646 - HRESULT DetectUpgradeBundle(
774 + void DetectUpgradeBundle(
775 __in BURN_ENGINE_STATE* pEngineState,
776 __in LPCWSTR wzId,
777 __in LPCWSTR wzVersion
@@ -654,30 +782,48 @@ namespace Bootstrapper
782 BURN_DEPENDENCY_PROVIDER dependencyProvider = { };
783
784 hr = StrAllocString(&dependencyProvider.sczKey, wzId, 0);
657 - ExitOnFailure(hr, "Failed to copy provider key");
785 + NativeAssert::Succeeded(hr, "Failed to copy provider key");
786
787 dependencyProvider.fImported = TRUE;
788
789 hr = StrAllocString(&dependencyProvider.sczVersion, wzVersion, 0);
662 - ExitOnFailure(hr, "Failed to copy version");
790 + NativeAssert::Succeeded(hr, "Failed to copy version");
791
792 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pRelatedBundles->rgRelatedBundles), pRelatedBundles->cRelatedBundles + 1, sizeof(BURN_RELATED_BUNDLE), 5);
665 - ExitOnFailure(hr, "Failed to ensure there is space for related bundles.");
793 + NativeAssert::Succeeded(hr, "Failed to ensure there is space for related bundles.");
794
795 BURN_RELATED_BUNDLE* pRelatedBundle = pRelatedBundles->rgRelatedBundles + pRelatedBundles->cRelatedBundles;
796
797 hr = VerParseVersion(wzVersion, 0, FALSE, &pRelatedBundle->pVersion);
670 - ExitOnFailure(hr, "Failed to parse pseudo bundle version: %ls", wzVersion);
798 + NativeAssert::Succeeded(hr, "Failed to parse pseudo bundle version: %ls", wzVersion);
799
800 pRelatedBundle->relationType = BOOTSTRAPPER_RELATION_UPGRADE;
801
802 hr = PseudoBundleInitialize(0, &pRelatedBundle->package, TRUE, wzId, pRelatedBundle->relationType, BOOTSTRAPPER_PACKAGE_STATE_PRESENT, NULL, NULL, NULL, 0, FALSE, L"-quiet", L"-repair -quiet", L"-uninstall -quiet", &dependencyProvider, NULL, 0);
675 - ExitOnFailure(hr, "Failed to initialize related bundle to represent bundle: %ls", wzId);
803 + NativeAssert::Succeeded(hr, "Failed to initialize related bundle to represent bundle: %ls", wzId);
804
805 ++pRelatedBundles->cRelatedBundles;
806 + }
807 +
808 + void DetectAsRelatedUpgradeBundle(
809 + __in BURN_ENGINE_STATE* pEngineState,
810 + __in LPCWSTR wzId,
811 + __in LPCWSTR wzVersion
812 + )
813 + {
814 + HRESULT hr = StrAllocString(&pEngineState->registration.sczAncestors, wzId, 0);
815 + NativeAssert::Succeeded(hr, "Failed to set registration's ancestors");
816 +
817 + pEngineState->command.relationType = BOOTSTRAPPER_RELATION_UPGRADE;
818
679 - LExit:
680 - return hr;
819 + DetectPackagesAsPresentAndCached(pEngineState);
820 + DetectUpgradeBundle(pEngineState, wzId, wzVersion);
821 +
822 + for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i)
823 + {
824 + BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i;
825 + DetectPackageDependent(pPackage, wzId);
826 + }
827 }
828
829 void ValidateCacheAcquireContainer(
@@ -755,6 +901,7 @@ namespace Bootstrapper
901 __in BOOL fRollback,
902 __in DWORD dwIndex,
903 __in LPCWSTR wzPackageId,
904 + __in BURN_PACKAGE_REGISTRATION_STATE expectedCacheRegistrationState,
905 __in DWORD iPackageCompleteAction,
906 __in DWORD cCachePayloads,
907 __in DWORD64 qwCachePayloadSizeTotal,
@@ -764,6 +911,7 @@ namespace Bootstrapper
911 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
912 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_PACKAGE_START, pAction->type);
913 NativeAssert::StringEqual(wzPackageId, pAction->packageStart.pPackage->sczId);
914 + Assert::Equal<DWORD>(expectedCacheRegistrationState, pAction->packageStart.pPackage->expectedCacheRegistrationState);
915 Assert::Equal(iPackageCompleteAction, pAction->packageStart.iPackageCompleteAction);
916 Assert::Equal(cCachePayloads, pAction->packageStart.cCachePayloads);
917 Assert::Equal(qwCachePayloadSizeTotal, pAction->packageStart.qwCachePayloadSizeTotal);
@@ -815,7 +963,8 @@ namespace Bootstrapper
963 void ValidateCleanAction(
964 __in BURN_PLAN* pPlan,
965 __in DWORD dwIndex,
818 - __in LPCWSTR wzPackageId
966 + __in LPCWSTR wzPackageId,
967 + __in BURN_PACKAGE_REGISTRATION_STATE expectedCacheRegistrationState
968 )
969 {
970 Assert::InRange(dwIndex + 1ul, 1ul, pPlan->cCleanActions);
@@ -823,6 +972,7 @@ namespace Bootstrapper
972 BURN_CLEAN_ACTION* pCleanAction = pPlan->rgCleanActions + dwIndex;
973 Assert::NotEqual((DWORD_PTR)0, (DWORD_PTR)pCleanAction->pPackage);
974 NativeAssert::StringEqual(wzPackageId, pCleanAction->pPackage->sczId);
975 + Assert::Equal<DWORD>(expectedCacheRegistrationState, pCleanAction->pPackage->expectedCacheRegistrationState);
976 }
977
978 BURN_EXECUTE_ACTION* ValidateExecuteActionExists(BURN_PLAN* pPlan, BOOL fRollback, DWORD dwIndex)
@@ -872,6 +1022,7 @@ namespace Bootstrapper
1022 __in BOOL fRollback,
1023 __in DWORD dwIndex,
1024 __in LPCWSTR wzPackageId,
1025 + __in BURN_PACKAGE_REGISTRATION_STATE expectedInstallRegistrationState,
1026 __in BOOTSTRAPPER_ACTION_STATE action,
1027 __in LPCWSTR wzIgnoreDependencies
1028 )
@@ -879,6 +1030,7 @@ namespace Bootstrapper
1030 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
1031 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE, pAction->type);
1032 NativeAssert::StringEqual(wzPackageId, pAction->exePackage.pPackage->sczId);
1033 + Assert::Equal<DWORD>(expectedInstallRegistrationState, pAction->exePackage.pPackage->expectedInstallRegistrationState);
1034 Assert::Equal<DWORD>(action, pAction->exePackage.action);
1035 NativeAssert::StringEqual(wzIgnoreDependencies, pAction->exePackage.sczIgnoreDependencies);
1036 }
@@ -888,6 +1040,7 @@ namespace Bootstrapper
1040 __in BOOL fRollback,
1041 __in DWORD dwIndex,
1042 __in LPCWSTR wzPackageId,
1043 + __in BURN_PACKAGE_REGISTRATION_STATE expectedInstallRegistrationState,
1044 __in BOOTSTRAPPER_ACTION_STATE action,
1045 __in BURN_MSI_PROPERTY actionMsiProperty,
1046 __in DWORD uiLevel,
@@ -898,6 +1051,7 @@ namespace Bootstrapper
1051 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
1052 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE, pAction->type);
1053 NativeAssert::StringEqual(wzPackageId, pAction->msiPackage.pPackage->sczId);
1054 + Assert::Equal<DWORD>(expectedInstallRegistrationState, pAction->msiPackage.pPackage->expectedInstallRegistrationState);
1055 Assert::Equal<DWORD>(action, pAction->msiPackage.action);
1056 Assert::Equal<DWORD>(actionMsiProperty, pAction->msiPackage.actionMsiProperty);
1057 Assert::Equal<DWORD>(uiLevel, pAction->msiPackage.uiLevel);
@@ -936,18 +1090,6 @@ namespace Bootstrapper
1090 Assert::Equal<DWORD>(action, pAction->packageProvider.action);
1091 }
1092
939 - void ValidateExecuteRegistration(
940 - __in BURN_PLAN* pPlan,
941 - __in BOOL fRollback,
942 - __in DWORD dwIndex,
943 - __in BOOL fKeep
944 - )
945 - {
946 - BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
947 - Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_REGISTRATION, pAction->type);
948 - Assert::Equal<BOOL>(fKeep, pAction->registration.fKeep);
949 - }
950 -
1093 void ValidateExecuteRollbackBoundary(
1094 __in BURN_PLAN* pPlan,
1095 __in BOOL fRollback,