aboutsummaryrefslogtreecommitdiff
path: root/src/engine
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/apply.cpp247
-rw-r--r--src/engine/apply.h4
-rw-r--r--src/engine/core.cpp18
-rw-r--r--src/engine/dependency.cpp29
-rw-r--r--src/engine/detect.cpp2
-rw-r--r--src/engine/engine.mc19
-rw-r--r--src/engine/exeengine.cpp30
-rw-r--r--src/engine/exeengine.h4
-rw-r--r--src/engine/logging.cpp25
-rw-r--r--src/engine/logging.h5
-rw-r--r--src/engine/msiengine.cpp41
-rw-r--r--src/engine/msiengine.h5
-rw-r--r--src/engine/mspengine.cpp109
-rw-r--r--src/engine/mspengine.h8
-rw-r--r--src/engine/msuengine.cpp30
-rw-r--r--src/engine/msuengine.h4
-rw-r--r--src/engine/package.cpp1
-rw-r--r--src/engine/package.h18
-rw-r--r--src/engine/plan.cpp192
-rw-r--r--src/engine/plan.h18
20 files changed, 601 insertions, 208 deletions
diff --git a/src/engine/apply.cpp b/src/engine/apply.cpp
index 76831461..8d2f5757 100644
--- a/src/engine/apply.cpp
+++ b/src/engine/apply.cpp
@@ -46,6 +46,10 @@ static HRESULT WINAPI AuthenticationRequired(
46 __out BOOL* pfRetry 46 __out BOOL* pfRetry
47 ); 47 );
48 48
49static void CalculateKeepRegistration(
50 __in BURN_ENGINE_STATE* pEngineState,
51 __inout BOOL* pfKeepRegistration
52 );
49static HRESULT ExecuteDependentRegistrationActions( 53static HRESULT ExecuteDependentRegistrationActions(
50 __in HANDLE hPipe, 54 __in HANDLE hPipe,
51 __in const BURN_REGISTRATION* pRegistration, 55 __in const BURN_REGISTRATION* pRegistration,
@@ -141,7 +145,6 @@ static HRESULT DoExecuteAction(
141 __in BURN_EXECUTE_CONTEXT* pContext, 145 __in BURN_EXECUTE_CONTEXT* pContext,
142 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary, 146 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary,
143 __inout BURN_EXECUTE_ACTION_CHECKPOINT** ppCheckpoint, 147 __inout BURN_EXECUTE_ACTION_CHECKPOINT** ppCheckpoint,
144 __out BOOL* pfKeepRegistration,
145 __out BOOL* pfSuspend, 148 __out BOOL* pfSuspend,
146 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 149 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
147 ); 150 );
@@ -149,7 +152,6 @@ static HRESULT DoRollbackActions(
149 __in BURN_ENGINE_STATE* pEngineState, 152 __in BURN_ENGINE_STATE* pEngineState,
150 __in BURN_EXECUTE_CONTEXT* pContext, 153 __in BURN_EXECUTE_CONTEXT* pContext,
151 __in DWORD dwCheckpoint, 154 __in DWORD dwCheckpoint,
152 __out BOOL* pfKeepRegistration,
153 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 155 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
154 ); 156 );
155static HRESULT ExecuteExePackage( 157static HRESULT ExecuteExePackage(
@@ -165,6 +167,7 @@ static HRESULT ExecuteMsiPackage(
165 __in BURN_ENGINE_STATE* pEngineState, 167 __in BURN_ENGINE_STATE* pEngineState,
166 __in BURN_EXECUTE_ACTION* pExecuteAction, 168 __in BURN_EXECUTE_ACTION* pExecuteAction,
167 __in BURN_EXECUTE_CONTEXT* pContext, 169 __in BURN_EXECUTE_CONTEXT* pContext,
170 __in BOOL fInsideMsiTransaction,
168 __in BOOL fRollback, 171 __in BOOL fRollback,
169 __out BOOL* pfRetry, 172 __out BOOL* pfRetry,
170 __out BOOL* pfSuspend, 173 __out BOOL* pfSuspend,
@@ -174,6 +177,7 @@ static HRESULT ExecuteMspPackage(
174 __in BURN_ENGINE_STATE* pEngineState, 177 __in BURN_ENGINE_STATE* pEngineState,
175 __in BURN_EXECUTE_ACTION* pExecuteAction, 178 __in BURN_EXECUTE_ACTION* pExecuteAction,
176 __in BURN_EXECUTE_CONTEXT* pContext, 179 __in BURN_EXECUTE_CONTEXT* pContext,
180 __in BOOL fInsideMsiTransaction,
177 __in BOOL fRollback, 181 __in BOOL fRollback,
178 __out BOOL* pfRetry, 182 __out BOOL* pfRetry,
179 __out BOOL* pfSuspend, 183 __out BOOL* pfSuspend,
@@ -214,6 +218,10 @@ static HRESULT ExecuteMsiRollbackTransaction(
214 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary, 218 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary,
215 __in BURN_EXECUTE_CONTEXT* pContext 219 __in BURN_EXECUTE_CONTEXT* pContext
216 ); 220 );
221static void ResetTransactionRegistrationState(
222 __in BURN_ENGINE_STATE* pEngineState,
223 __in BOOL fCommit
224 );
217static HRESULT CleanPackage( 225static HRESULT CleanPackage(
218 __in HANDLE hElevatedPipe, 226 __in HANDLE hElevatedPipe,
219 __in BURN_PACKAGE* pPackage 227 __in BURN_PACKAGE* pPackage
@@ -282,6 +290,7 @@ extern "C" void ApplyReset(
282 { 290 {
283 BURN_PACKAGE* pPackage = pPackages->rgPackages + i; 291 BURN_PACKAGE* pPackage = pPackages->rgPackages + i;
284 pPackage->hrCacheResult = S_OK; 292 pPackage->hrCacheResult = S_OK;
293 pPackage->transactionRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
285 } 294 }
286} 295}
287 296
@@ -380,13 +389,15 @@ LExit:
380extern "C" HRESULT ApplyUnregister( 389extern "C" HRESULT ApplyUnregister(
381 __in BURN_ENGINE_STATE* pEngineState, 390 __in BURN_ENGINE_STATE* pEngineState,
382 __in BOOL fFailedOrRollback, 391 __in BOOL fFailedOrRollback,
383 __in BOOL fKeepRegistration,
384 __in BOOL fSuspend, 392 __in BOOL fSuspend,
385 __in BOOTSTRAPPER_APPLY_RESTART restart 393 __in BOOTSTRAPPER_APPLY_RESTART restart
386 ) 394 )
387{ 395{
388 HRESULT hr = S_OK; 396 HRESULT hr = S_OK;
389 BURN_RESUME_MODE resumeMode = BURN_RESUME_MODE_NONE; 397 BURN_RESUME_MODE resumeMode = BURN_RESUME_MODE_NONE;
398 BOOL fKeepRegistration = pEngineState->plan.fDisallowRemoval;
399
400 CalculateKeepRegistration(pEngineState, &fKeepRegistration);
390 401
391 hr = UserExperienceOnUnregisterBegin(&pEngineState->userExperience); 402 hr = UserExperienceOnUnregisterBegin(&pEngineState->userExperience);
392 ExitOnRootFailure(hr, "BA aborted unregister begin."); 403 ExitOnRootFailure(hr, "BA aborted unregister begin.");
@@ -443,7 +454,7 @@ extern "C" HRESULT ApplyCache(
443 __in BURN_PLAN* pPlan, 454 __in BURN_PLAN* pPlan,
444 __in HANDLE hPipe, 455 __in HANDLE hPipe,
445 __inout DWORD* pcOverallProgressTicks, 456 __inout DWORD* pcOverallProgressTicks,
446 __out BOOL* pfRollback 457 __inout BOOL* pfRollback
447 ) 458 )
448{ 459{
449 HRESULT hr = S_OK; 460 HRESULT hr = S_OK;
@@ -732,7 +743,6 @@ extern "C" HRESULT ApplyExecute(
732 __in BURN_ENGINE_STATE* pEngineState, 743 __in BURN_ENGINE_STATE* pEngineState,
733 __in_opt HANDLE hCacheThread, 744 __in_opt HANDLE hCacheThread,
734 __inout DWORD* pcOverallProgressTicks, 745 __inout DWORD* pcOverallProgressTicks,
735 __inout BOOL* pfKeepRegistration,
736 __out BOOL* pfRollback, 746 __out BOOL* pfRollback,
737 __out BOOL* pfSuspend, 747 __out BOOL* pfSuspend,
738 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 748 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
@@ -779,7 +789,7 @@ extern "C" HRESULT ApplyExecute(
779 } 789 }
780 790
781 // Execute the action. 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);
783 793
784 if (*pfSuspend || BOOTSTRAPPER_APPLY_RESTART_INITIATED == *pRestart) 794 if (*pfSuspend || BOOTSTRAPPER_APPLY_RESTART_INITIATED == *pRestart)
785 { 795 {
@@ -821,7 +831,7 @@ extern "C" HRESULT ApplyExecute(
821 // The action failed, roll back to previous rollback boundary. 831 // The action failed, roll back to previous rollback boundary.
822 if (pCheckpoint) 832 if (pCheckpoint)
823 { 833 {
824 hrRollback = DoRollbackActions(pEngineState, &context, pCheckpoint->dwId, pfKeepRegistration, pRestart); 834 hrRollback = DoRollbackActions(pEngineState, &context, pCheckpoint->dwId, pRestart);
825 IgnoreRollbackError(hrRollback, "Failed rollback actions"); 835 IgnoreRollbackError(hrRollback, "Failed rollback actions");
826 } 836 }
827 837
@@ -855,14 +865,46 @@ extern "C" void ApplyClean(
855 for (DWORD i = 0; i < pPlan->cCleanActions; ++i) 865 for (DWORD i = 0; i < pPlan->cCleanActions; ++i)
856 { 866 {
857 BURN_CLEAN_ACTION* pCleanAction = pPlan->rgCleanActions + i; 867 BURN_CLEAN_ACTION* pCleanAction = pPlan->rgCleanActions + i;
868 BURN_PACKAGE* pPackage = pCleanAction->pPackage;
858 869
859 hr = CleanPackage(hPipe, pCleanAction->pPackage); 870 hr = CleanPackage(hPipe, pPackage);
860 } 871 }
861} 872}
862 873
863 874
864// internal helper functions 875// internal helper functions
865 876
877static 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
866static HRESULT ExecuteDependentRegistrationActions( 908static HRESULT ExecuteDependentRegistrationActions(
867 __in HANDLE hPipe, 909 __in HANDLE hPipe,
868 __in const BURN_REGISTRATION* pRegistration, 910 __in const BURN_REGISTRATION* pRegistration,
@@ -1255,6 +1297,15 @@ static HRESULT LayoutOrCacheContainerOrPayload(
1255 LARGE_INTEGER liContainerOrPayloadSize = { }; 1297 LARGE_INTEGER liContainerOrPayloadSize = { };
1256 LARGE_INTEGER liZero = { }; 1298 LARGE_INTEGER liZero = { };
1257 BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT progress = { }; 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 }
1258 1309
1259 liContainerOrPayloadSize.QuadPart = pContainer ? pContainer->qwFileSize : pPayload->qwFileSize; 1310 liContainerOrPayloadSize.QuadPart = pContainer ? pContainer->qwFileSize : pPayload->qwFileSize;
1260 1311
@@ -1297,9 +1348,6 @@ static HRESULT LayoutOrCacheContainerOrPayload(
1297 } 1348 }
1298 else // complete the payload. 1349 else // complete the payload.
1299 { 1350 {
1300 Assert(!pContainer);
1301 Assert(pPackage);
1302
1303 hr = CacheCompletePayload(pPackage->fPerMachine, pPayload, pPackage->sczCacheId, wzUnverifiedPath, fMove); 1351 hr = CacheCompletePayload(pPackage->fPerMachine, pPayload, pPackage->sczCacheId, wzUnverifiedPath, fMove);
1304 } 1352 }
1305 1353
@@ -1307,6 +1355,11 @@ static HRESULT LayoutOrCacheContainerOrPayload(
1307 // will get. 1355 // will get.
1308 if (SUCCEEDED(hr)) 1356 if (SUCCEEDED(hr))
1309 { 1357 {
1358 if (fCanAffectRegistration)
1359 {
1360 pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
1361 }
1362
1310 CacheProgressRoutine(liContainerOrPayloadSize, liContainerOrPayloadSize, liZero, liZero, 0, 0, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, &progress); 1363 CacheProgressRoutine(liContainerOrPayloadSize, liContainerOrPayloadSize, liZero, liZero, 0, 0, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, &progress);
1311 if (progress.fCancel) 1364 if (progress.fCancel)
1312 { 1365 {
@@ -1639,7 +1692,6 @@ static HRESULT DoExecuteAction(
1639 __in BURN_EXECUTE_CONTEXT* pContext, 1692 __in BURN_EXECUTE_CONTEXT* pContext,
1640 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary, 1693 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary,
1641 __inout BURN_EXECUTE_ACTION_CHECKPOINT** ppCheckpoint, 1694 __inout BURN_EXECUTE_ACTION_CHECKPOINT** ppCheckpoint,
1642 __out BOOL* pfKeepRegistration,
1643 __out BOOL* pfSuspend, 1695 __out BOOL* pfSuspend,
1644 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 1696 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
1645 ) 1697 )
@@ -1651,11 +1703,14 @@ static HRESULT DoExecuteAction(
1651 BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE; 1703 BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE;
1652 BOOL fRetry = FALSE; 1704 BOOL fRetry = FALSE;
1653 BOOL fStopWusaService = FALSE; 1705 BOOL fStopWusaService = FALSE;
1706 BOOL fInsideMsiTransaction = FALSE;
1654 1707
1655 pContext->fRollback = FALSE; 1708 pContext->fRollback = FALSE;
1656 1709
1657 do 1710 do
1658 { 1711 {
1712 fInsideMsiTransaction = *ppRollbackBoundary && (*ppRollbackBoundary)->fActiveTransaction;
1713
1659 switch (pExecuteAction->type) 1714 switch (pExecuteAction->type)
1660 { 1715 {
1661 case BURN_EXECUTE_ACTION_TYPE_CHECKPOINT: 1716 case BURN_EXECUTE_ACTION_TYPE_CHECKPOINT:
@@ -1695,12 +1750,12 @@ static HRESULT DoExecuteAction(
1695 break; 1750 break;
1696 1751
1697 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: 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);
1699 ExitOnFailure(hr, "Failed to execute MSI package."); 1754 ExitOnFailure(hr, "Failed to execute MSI package.");
1700 break; 1755 break;
1701 1756
1702 case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET: 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);
1704 ExitOnFailure(hr, "Failed to execute MSP package."); 1759 ExitOnFailure(hr, "Failed to execute MSP package.");
1705 break; 1760 break;
1706 1761
@@ -1720,8 +1775,6 @@ static HRESULT DoExecuteAction(
1720 ExitOnFailure(hr, "Failed to execute dependency action."); 1775 ExitOnFailure(hr, "Failed to execute dependency action.");
1721 break; 1776 break;
1722 1777
1723 case BURN_EXECUTE_ACTION_TYPE_REGISTRATION:
1724 *pfKeepRegistration = pExecuteAction->registration.fKeep;
1725 break; 1778 break;
1726 1779
1727 case BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY: 1780 case BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY:
@@ -1757,7 +1810,6 @@ static HRESULT DoRollbackActions(
1757 __in BURN_ENGINE_STATE* pEngineState, 1810 __in BURN_ENGINE_STATE* pEngineState,
1758 __in BURN_EXECUTE_CONTEXT* pContext, 1811 __in BURN_EXECUTE_CONTEXT* pContext,
1759 __in DWORD dwCheckpoint, 1812 __in DWORD dwCheckpoint,
1760 __out BOOL* pfKeepRegistration,
1761 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 1813 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
1762 ) 1814 )
1763{ 1815{
@@ -1811,12 +1863,12 @@ static HRESULT DoRollbackActions(
1811 break; 1863 break;
1812 1864
1813 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: 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);
1815 IgnoreRollbackError(hr, "Failed to rollback MSI package."); 1867 IgnoreRollbackError(hr, "Failed to rollback MSI package.");
1816 break; 1868 break;
1817 1869
1818 case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET: 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);
1820 IgnoreRollbackError(hr, "Failed to rollback MSP package."); 1872 IgnoreRollbackError(hr, "Failed to rollback MSP package.");
1821 break; 1873 break;
1822 1874
@@ -1835,10 +1887,6 @@ static HRESULT DoRollbackActions(
1835 IgnoreRollbackError(hr, "Failed to rollback dependency action."); 1887 IgnoreRollbackError(hr, "Failed to rollback dependency action.");
1836 break; 1888 break;
1837 1889
1838 case BURN_EXECUTE_ACTION_TYPE_REGISTRATION:
1839 *pfKeepRegistration = pRollbackAction->registration.fKeep;
1840 break;
1841
1842 case BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY: 1890 case BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY:
1843 ExitFunction1(hr = S_OK); 1891 ExitFunction1(hr = S_OK);
1844 1892
@@ -1878,19 +1926,21 @@ static HRESULT ExecuteExePackage(
1878 GENERIC_EXECUTE_MESSAGE message = { }; 1926 GENERIC_EXECUTE_MESSAGE message = { };
1879 int nResult = 0; 1927 int nResult = 0;
1880 BOOL fBeginCalled = FALSE; 1928 BOOL fBeginCalled = FALSE;
1929 BOOL fExecuted = FALSE;
1930 BURN_PACKAGE* pPackage = pExecuteAction->exePackage.pPackage;
1881 1931
1882 if (FAILED(pExecuteAction->exePackage.pPackage->hrCacheResult)) 1932 if (FAILED(pPackage->hrCacheResult))
1883 { 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);
1885 ExitFunction1(hr = S_OK); 1935 ExitFunction1(hr = S_OK);
1886 } 1936 }
1887 1937
1888 Assert(pContext->fRollback == fRollback); 1938 Assert(pContext->fRollback == fRollback);
1889 pContext->pExecutingPackage = pExecuteAction->exePackage.pPackage; 1939 pContext->pExecutingPackage = pPackage;
1890 fBeginCalled = TRUE; 1940 fBeginCalled = TRUE;
1891 1941
1892 // Send package execute begin to BA. 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);
1894 ExitOnRootFailure(hr, "BA aborted execute EXE package begin."); 1944 ExitOnRootFailure(hr, "BA aborted execute EXE package begin.");
1895 1945
1896 message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; 1946 message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS;
@@ -1900,8 +1950,10 @@ static HRESULT ExecuteExePackage(
1900 hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwAllowedResults, nResult); 1950 hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwAllowedResults, nResult);
1901 ExitOnRootFailure(hr, "BA aborted EXE progress."); 1951 ExitOnRootFailure(hr, "BA aborted EXE progress.");
1902 1952
1953 fExecuted = TRUE;
1954
1903 // Execute package. 1955 // Execute package.
1904 if (pExecuteAction->exePackage.pPackage->fPerMachine) 1956 if (pPackage->fPerMachine)
1905 { 1957 {
1906 hrExecute = ElevationExecuteExePackage(pEngineState->companionConnection.hPipe, pExecuteAction, &pEngineState->variables, fRollback, GenericExecuteMessageHandler, pContext, pRestart); 1958 hrExecute = ElevationExecuteExePackage(pEngineState->companionConnection.hPipe, pExecuteAction, &pEngineState->variables, fRollback, GenericExecuteMessageHandler, pContext, pRestart);
1907 ExitOnFailure(hrExecute, "Failed to configure per-machine EXE package."); 1959 ExitOnFailure(hrExecute, "Failed to configure per-machine EXE package.");
@@ -1926,9 +1978,14 @@ static HRESULT ExecuteExePackage(
1926 ExitOnRootFailure(hr, "BA aborted EXE package execute progress."); 1978 ExitOnRootFailure(hr, "BA aborted EXE package execute progress.");
1927 1979
1928LExit: 1980LExit:
1981 if (fExecuted)
1982 {
1983 ExeEngineUpdateInstallRegistrationState(pExecuteAction, hrExecute);
1984 }
1985
1929 if (fBeginCalled) 1986 if (fBeginCalled)
1930 { 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);
1932 } 1989 }
1933 1990
1934 return hr; 1991 return hr;
@@ -1938,6 +1995,7 @@ static HRESULT ExecuteMsiPackage(
1938 __in BURN_ENGINE_STATE* pEngineState, 1995 __in BURN_ENGINE_STATE* pEngineState,
1939 __in BURN_EXECUTE_ACTION* pExecuteAction, 1996 __in BURN_EXECUTE_ACTION* pExecuteAction,
1940 __in BURN_EXECUTE_CONTEXT* pContext, 1997 __in BURN_EXECUTE_CONTEXT* pContext,
1998 __in BOOL fInsideMsiTransaction,
1941 __in BOOL fRollback, 1999 __in BOOL fRollback,
1942 __out BOOL* pfRetry, 2000 __out BOOL* pfRetry,
1943 __out BOOL* pfSuspend, 2001 __out BOOL* pfSuspend,
@@ -1947,23 +2005,27 @@ static HRESULT ExecuteMsiPackage(
1947 HRESULT hr = S_OK; 2005 HRESULT hr = S_OK;
1948 HRESULT hrExecute = S_OK; 2006 HRESULT hrExecute = S_OK;
1949 BOOL fBeginCalled = FALSE; 2007 BOOL fBeginCalled = FALSE;
2008 BOOL fExecuted = FALSE;
2009 BURN_PACKAGE* pPackage = pExecuteAction->msiPackage.pPackage;
1950 2010
1951 if (FAILED(pExecuteAction->msiPackage.pPackage->hrCacheResult)) 2011 if (FAILED(pPackage->hrCacheResult))
1952 { 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);
1954 ExitFunction1(hr = S_OK); 2014 ExitFunction1(hr = S_OK);
1955 } 2015 }
1956 2016
1957 Assert(pContext->fRollback == fRollback); 2017 Assert(pContext->fRollback == fRollback);
1958 pContext->pExecutingPackage = pExecuteAction->msiPackage.pPackage; 2018 pContext->pExecutingPackage = pPackage;
1959 fBeginCalled = TRUE; 2019 fBeginCalled = TRUE;
1960 2020
1961 // Send package execute begin to BA. 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);
1963 ExitOnRootFailure(hr, "BA aborted execute MSI package begin."); 2023 ExitOnRootFailure(hr, "BA aborted execute MSI package begin.");
1964 2024
2025 fExecuted = TRUE;
2026
1965 // execute package 2027 // execute package
1966 if (pExecuteAction->msiPackage.pPackage->fPerMachine) 2028 if (pPackage->fPerMachine)
1967 { 2029 {
1968 hrExecute = ElevationExecuteMsiPackage(pEngineState->companionConnection.hPipe, pEngineState->userExperience.hwndApply, pExecuteAction, &pEngineState->variables, fRollback, MsiExecuteMessageHandler, pContext, pRestart); 2030 hrExecute = ElevationExecuteMsiPackage(pEngineState->companionConnection.hPipe, pEngineState->userExperience.hwndApply, pExecuteAction, &pEngineState->variables, fRollback, MsiExecuteMessageHandler, pContext, pRestart);
1969 ExitOnFailure(hrExecute, "Failed to configure per-machine MSI package."); 2031 ExitOnFailure(hrExecute, "Failed to configure per-machine MSI package.");
@@ -1981,9 +2043,14 @@ static HRESULT ExecuteMsiPackage(
1981 ExitOnRootFailure(hr, "BA aborted MSI package execute progress."); 2043 ExitOnRootFailure(hr, "BA aborted MSI package execute progress.");
1982 2044
1983LExit: 2045LExit:
2046 if (fExecuted)
2047 {
2048 MsiEngineUpdateInstallRegistrationState(pExecuteAction, hrExecute, fInsideMsiTransaction);
2049 }
2050
1984 if (fBeginCalled) 2051 if (fBeginCalled)
1985 { 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);
1987 } 2054 }
1988 2055
1989 return hr; 2056 return hr;
@@ -1993,6 +2060,7 @@ static HRESULT ExecuteMspPackage(
1993 __in BURN_ENGINE_STATE* pEngineState, 2060 __in BURN_ENGINE_STATE* pEngineState,
1994 __in BURN_EXECUTE_ACTION* pExecuteAction, 2061 __in BURN_EXECUTE_ACTION* pExecuteAction,
1995 __in BURN_EXECUTE_CONTEXT* pContext, 2062 __in BURN_EXECUTE_CONTEXT* pContext,
2063 __in BOOL fInsideMsiTransaction,
1996 __in BOOL fRollback, 2064 __in BOOL fRollback,
1997 __out BOOL* pfRetry, 2065 __out BOOL* pfRetry,
1998 __out BOOL* pfSuspend, 2066 __out BOOL* pfSuspend,
@@ -2002,19 +2070,21 @@ static HRESULT ExecuteMspPackage(
2002 HRESULT hr = S_OK; 2070 HRESULT hr = S_OK;
2003 HRESULT hrExecute = S_OK; 2071 HRESULT hrExecute = S_OK;
2004 BOOL fBeginCalled = FALSE; 2072 BOOL fBeginCalled = FALSE;
2073 BOOL fExecuted = FALSE;
2074 BURN_PACKAGE* pPackage = pExecuteAction->mspTarget.pPackage;
2005 2075
2006 if (FAILED(pExecuteAction->mspTarget.pPackage->hrCacheResult)) 2076 if (FAILED(pPackage->hrCacheResult))
2007 { 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);
2009 ExitFunction1(hr = S_OK); 2079 ExitFunction1(hr = S_OK);
2010 } 2080 }
2011 2081
2012 Assert(pContext->fRollback == fRollback); 2082 Assert(pContext->fRollback == fRollback);
2013 pContext->pExecutingPackage = pExecuteAction->mspTarget.pPackage; 2083 pContext->pExecutingPackage = pPackage;
2014 fBeginCalled = TRUE; 2084 fBeginCalled = TRUE;
2015 2085
2016 // Send package execute begin to BA. 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);
2018 ExitOnRootFailure(hr, "BA aborted execute MSP package begin."); 2088 ExitOnRootFailure(hr, "BA aborted execute MSP package begin.");
2019 2089
2020 // Now send all the patches that target this product code. 2090 // Now send all the patches that target this product code.
@@ -2026,6 +2096,8 @@ static HRESULT ExecuteMspPackage(
2026 ExitOnRootFailure(hr, "BA aborted execute MSP target."); 2096 ExitOnRootFailure(hr, "BA aborted execute MSP target.");
2027 } 2097 }
2028 2098
2099 fExecuted = TRUE;
2100
2029 // execute package 2101 // execute package
2030 if (pExecuteAction->mspTarget.fPerMachineTarget) 2102 if (pExecuteAction->mspTarget.fPerMachineTarget)
2031 { 2103 {
@@ -2045,9 +2117,14 @@ static HRESULT ExecuteMspPackage(
2045 ExitOnRootFailure(hr, "BA aborted MSP package execute progress."); 2117 ExitOnRootFailure(hr, "BA aborted MSP package execute progress.");
2046 2118
2047LExit: 2119LExit:
2120 if (fExecuted)
2121 {
2122 MspEngineUpdateInstallRegistrationState(pExecuteAction, hrExecute, fInsideMsiTransaction);
2123 }
2124
2048 if (fBeginCalled) 2125 if (fBeginCalled)
2049 { 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);
2051 } 2128 }
2052 2129
2053 return hr; 2130 return hr;
@@ -2069,19 +2146,21 @@ static HRESULT ExecuteMsuPackage(
2069 GENERIC_EXECUTE_MESSAGE message = { }; 2146 GENERIC_EXECUTE_MESSAGE message = { };
2070 int nResult = 0; 2147 int nResult = 0;
2071 BOOL fBeginCalled = FALSE; 2148 BOOL fBeginCalled = FALSE;
2149 BOOL fExecuted = FALSE;
2150 BURN_PACKAGE* pPackage = pExecuteAction->msuPackage.pPackage;
2072 2151
2073 if (FAILED(pExecuteAction->msuPackage.pPackage->hrCacheResult)) 2152 if (FAILED(pPackage->hrCacheResult))
2074 { 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);
2076 ExitFunction1(hr = S_OK); 2155 ExitFunction1(hr = S_OK);
2077 } 2156 }
2078 2157
2079 Assert(pContext->fRollback == fRollback); 2158 Assert(pContext->fRollback == fRollback);
2080 pContext->pExecutingPackage = pExecuteAction->msuPackage.pPackage; 2159 pContext->pExecutingPackage = pPackage;
2081 fBeginCalled = TRUE; 2160 fBeginCalled = TRUE;
2082 2161
2083 // Send package execute begin to BA. 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);
2085 ExitOnRootFailure(hr, "BA aborted execute MSU package begin."); 2164 ExitOnRootFailure(hr, "BA aborted execute MSU package begin.");
2086 2165
2087 message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; 2166 message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS;
@@ -2091,8 +2170,10 @@ static HRESULT ExecuteMsuPackage(
2091 hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwAllowedResults, nResult); 2170 hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwAllowedResults, nResult);
2092 ExitOnRootFailure(hr, "BA aborted MSU progress."); 2171 ExitOnRootFailure(hr, "BA aborted MSU progress.");
2093 2172
2173 fExecuted = TRUE;
2174
2094 // execute package 2175 // execute package
2095 if (pExecuteAction->msuPackage.pPackage->fPerMachine) 2176 if (pPackage->fPerMachine)
2096 { 2177 {
2097 hrExecute = ElevationExecuteMsuPackage(pEngineState->companionConnection.hPipe, pExecuteAction, fRollback, fStopWusaService, GenericExecuteMessageHandler, pContext, pRestart); 2178 hrExecute = ElevationExecuteMsuPackage(pEngineState->companionConnection.hPipe, pExecuteAction, fRollback, fStopWusaService, GenericExecuteMessageHandler, pContext, pRestart);
2098 ExitOnFailure(hrExecute, "Failed to configure per-machine MSU package."); 2179 ExitOnFailure(hrExecute, "Failed to configure per-machine MSU package.");
@@ -2117,9 +2198,14 @@ static HRESULT ExecuteMsuPackage(
2117 ExitOnRootFailure(hr, "BA aborted MSU package execute progress."); 2198 ExitOnRootFailure(hr, "BA aborted MSU package execute progress.");
2118 2199
2119LExit: 2200LExit:
2201 if (fExecuted)
2202 {
2203 MsuEngineUpdateInstallRegistrationState(pExecuteAction, hrExecute);
2204 }
2205
2120 if (fBeginCalled) 2206 if (fBeginCalled)
2121 { 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);
2123 } 2209 }
2124 2210
2125 return hr; 2211 return hr;
@@ -2167,6 +2253,32 @@ static HRESULT ExecuteDependencyAction(
2167 ExitOnFailure(hr, "Failed to register the dependency on per-user package."); 2253 ExitOnFailure(hr, "Failed to register the dependency on per-user package.");
2168 } 2254 }
2169 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
2170LExit: 2282LExit:
2171 return hr; 2283 return hr;
2172} 2284}
@@ -2202,6 +2314,8 @@ static HRESULT ExecuteMsiBeginTransaction(
2202 if (SUCCEEDED(hr)) 2314 if (SUCCEEDED(hr))
2203 { 2315 {
2204 pRollbackBoundary->fActiveTransaction = TRUE; 2316 pRollbackBoundary->fActiveTransaction = TRUE;
2317
2318 ResetTransactionRegistrationState(pEngineState, FALSE);
2205 } 2319 }
2206 2320
2207LExit: 2321LExit:
@@ -2244,6 +2358,8 @@ static HRESULT ExecuteMsiCommitTransaction(
2244 if (SUCCEEDED(hr)) 2358 if (SUCCEEDED(hr))
2245 { 2359 {
2246 pRollbackBoundary->fActiveTransaction = FALSE; 2360 pRollbackBoundary->fActiveTransaction = FALSE;
2361
2362 ResetTransactionRegistrationState(pEngineState, TRUE);
2247 } 2363 }
2248 2364
2249LExit: 2365LExit:
@@ -2285,6 +2401,8 @@ static HRESULT ExecuteMsiRollbackTransaction(
2285LExit: 2401LExit:
2286 pRollbackBoundary->fActiveTransaction = FALSE; 2402 pRollbackBoundary->fActiveTransaction = FALSE;
2287 2403
2404 ResetTransactionRegistrationState(pEngineState, FALSE);
2405
2288 if (fBeginCalled) 2406 if (fBeginCalled)
2289 { 2407 {
2290 UserExperienceOnRollbackMsiTransactionComplete(&pEngineState->userExperience, pRollbackBoundary->sczId, hr); 2408 UserExperienceOnRollbackMsiTransactionComplete(&pEngineState->userExperience, pRollbackBoundary->sczId, hr);
@@ -2293,6 +2411,38 @@ LExit:
2293 return hr; 2411 return hr;
2294} 2412}
2295 2413
2414static 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
2296static HRESULT CleanPackage( 2446static HRESULT CleanPackage(
2297 __in HANDLE hElevatedPipe, 2447 __in HANDLE hElevatedPipe,
2298 __in BURN_PACKAGE* pPackage 2448 __in BURN_PACKAGE* pPackage
@@ -2309,6 +2459,11 @@ static HRESULT CleanPackage(
2309 hr = CacheRemovePackage(FALSE, pPackage->sczId, pPackage->sczCacheId); 2459 hr = CacheRemovePackage(FALSE, pPackage->sczId, pPackage->sczCacheId);
2310 } 2460 }
2311 2461
2462 if (pPackage->fCanAffectRegistration)
2463 {
2464 pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
2465 }
2466
2312 return hr; 2467 return hr;
2313} 2468}
2314 2469
diff --git a/src/engine/apply.h b/src/engine/apply.h
index 00e1fceb..548e147d 100644
--- a/src/engine/apply.h
+++ b/src/engine/apply.h
@@ -72,7 +72,6 @@ HRESULT ApplyRegister(
72HRESULT ApplyUnregister( 72HRESULT ApplyUnregister(
73 __in BURN_ENGINE_STATE* pEngineState, 73 __in BURN_ENGINE_STATE* pEngineState,
74 __in BOOL fFailedOrRollback, 74 __in BOOL fFailedOrRollback,
75 __in BOOL fRollback,
76 __in BOOL fSuspend, 75 __in BOOL fSuspend,
77 __in BOOTSTRAPPER_APPLY_RESTART restart 76 __in BOOTSTRAPPER_APPLY_RESTART restart
78 ); 77 );
@@ -83,13 +82,12 @@ HRESULT ApplyCache(
83 __in BURN_PLAN* pPlan, 82 __in BURN_PLAN* pPlan,
84 __in HANDLE hPipe, 83 __in HANDLE hPipe,
85 __inout DWORD* pcOverallProgressTicks, 84 __inout DWORD* pcOverallProgressTicks,
86 __out BOOL* pfRollback 85 __inout BOOL* pfRollback
87 ); 86 );
88HRESULT ApplyExecute( 87HRESULT ApplyExecute(
89 __in BURN_ENGINE_STATE* pEngineState, 88 __in BURN_ENGINE_STATE* pEngineState,
90 __in_opt HANDLE hCacheThread, 89 __in_opt HANDLE hCacheThread,
91 __inout DWORD* pcOverallProgressTicks, 90 __inout DWORD* pcOverallProgressTicks,
92 __inout BOOL* pfKeepRegistration,
93 __out BOOL* pfRollback, 91 __out BOOL* pfRollback,
94 __out BOOL* pfSuspend, 92 __out BOOL* pfSuspend,
95 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 93 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
diff --git a/src/engine/core.cpp b/src/engine/core.cpp
index a4c118a3..36471e93 100644
--- a/src/engine/core.cpp
+++ b/src/engine/core.cpp
@@ -331,6 +331,8 @@ extern "C" HRESULT CoreDetect(
331 } 331 }
332 332
333 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN; 333 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN;
334 pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
335 pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
334 } 336 }
335 } 337 }
336 338
@@ -342,7 +344,7 @@ extern "C" HRESULT CoreDetect(
342 { 344 {
343 pPackage = pEngineState->packages.rgPackages + iPackage; 345 pPackage = pEngineState->packages.rgPackages + iPackage;
344 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));
346 348
347 if (BURN_PACKAGE_TYPE_MSI == pPackage->type) 349 if (BURN_PACKAGE_TYPE_MSI == pPackage->type)
348 { 350 {
@@ -565,7 +567,6 @@ extern "C" HRESULT CoreApply(
565 BOOL fApplyInitialize = FALSE; 567 BOOL fApplyInitialize = FALSE;
566 BOOL fElevated = FALSE; 568 BOOL fElevated = FALSE;
567 BOOL fRegistered = FALSE; 569 BOOL fRegistered = FALSE;
568 BOOL fKeepRegistration = pEngineState->plan.fKeepRegistrationDefault;
569 BOOL fRollback = FALSE; 570 BOOL fRollback = FALSE;
570 BOOL fSuspend = FALSE; 571 BOOL fSuspend = FALSE;
571 BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE; 572 BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE;
@@ -652,9 +653,9 @@ extern "C" HRESULT CoreApply(
652 // Register. 653 // Register.
653 if (pEngineState->plan.fRegister) 654 if (pEngineState->plan.fRegister)
654 { 655 {
656 fRegistered = TRUE;
655 hr = ApplyRegister(pEngineState); 657 hr = ApplyRegister(pEngineState);
656 ExitOnFailure(hr, "Failed to register bundle."); 658 ExitOnFailure(hr, "Failed to register bundle.");
657 fRegistered = TRUE;
658 } 659 }
659 660
660 // Cache. 661 // Cache.
@@ -681,7 +682,7 @@ extern "C" HRESULT CoreApply(
681 // Execute. 682 // Execute.
682 if (pEngineState->plan.cExecuteActions) 683 if (pEngineState->plan.cExecuteActions)
683 { 684 {
684 hr = ApplyExecute(pEngineState, hCacheThread, &cOverallProgressTicks, &fKeepRegistration, &fRollback, &fSuspend, &restart); 685 hr = ApplyExecute(pEngineState, hCacheThread, &cOverallProgressTicks, &fRollback, &fSuspend, &restart);
685 UserExperienceExecutePhaseComplete(&pEngineState->userExperience, hr); // signal that execute completed. 686 UserExperienceExecutePhaseComplete(&pEngineState->userExperience, hr); // signal that execute completed.
686 } 687 }
687 688
@@ -711,7 +712,7 @@ LExit:
711 // Unregister. 712 // Unregister.
712 if (fRegistered) 713 if (fRegistered)
713 { 714 {
714 ApplyUnregister(pEngineState, FAILED(hr) || fRollback, fKeepRegistration || pEngineState->plan.fDisallowRemoval, fSuspend, restart); 715 ApplyUnregister(pEngineState, FAILED(hr) || fRollback, fSuspend, restart);
715 } 716 }
716 717
717 if (fElevated) 718 if (fElevated)
@@ -1611,6 +1612,11 @@ static HRESULT DetectPackagePayloadsCached(
1611 1612
1612 pPackage->cache = cache; 1613 pPackage->cache = cache;
1613 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
1614LExit: 1620LExit:
1615 ReleaseStr(sczPayloadCachePath); 1621 ReleaseStr(sczPayloadCachePath);
1616 ReleaseStr(sczCachePath); 1622 ReleaseStr(sczCachePath);
@@ -1703,7 +1709,7 @@ static void LogPackages(
1703 const DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == action) ? pPackages->cPackages - 1 - i : i; 1709 const DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == action) ? pPackages->cPackages - 1 - i : i;
1704 const BURN_PACKAGE* pPackage = &pPackages->rgPackages[iPackage]; 1710 const BURN_PACKAGE* pPackage = &pPackages->rgPackages[iPackage];
1705 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));
1707 } 1713 }
1708 1714
1709 // Display related bundles last if caching, installing, modifying, or repairing. 1715 // Display related bundles last if caching, installing, modifying, or repairing.
diff --git a/src/engine/dependency.cpp b/src/engine/dependency.cpp
index 1c33aaf2..a6a8fe4d 100644
--- a/src/engine/dependency.cpp
+++ b/src/engine/dependency.cpp
@@ -708,6 +708,9 @@ static HRESULT DetectPackageDependents(
708{ 708{
709 HRESULT hr = S_OK; 709 HRESULT hr = S_OK;
710 HKEY hkHive = pPackage->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 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;
711 714
712 // There's currently no point in getting the dependents if the scope doesn't match, 715 // There's currently no point in getting the dependents if the scope doesn't match,
713 // because they will just get ignored. 716 // because they will just get ignored.
@@ -729,6 +732,20 @@ static HRESULT DetectPackageDependents(
729 { 732 {
730 pPackage->fPackageProviderExists = TRUE; 733 pPackage->fPackageProviderExists = TRUE;
731 } 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 }
732 } 749 }
733 else 750 else
734 { 751 {
@@ -747,6 +764,18 @@ static HRESULT DetectPackageDependents(
747 pPackage->fPackageProviderExists = TRUE; 764 pPackage->fPackageProviderExists = TRUE;
748 } 765 }
749 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
750LExit: 779LExit:
751 return hr; 780 return hr;
752} 781}
diff --git a/src/engine/detect.cpp b/src/engine/detect.cpp
index ff6ba4d7..159df3d0 100644
--- a/src/engine/detect.cpp
+++ b/src/engine/detect.cpp
@@ -63,6 +63,8 @@ extern "C" void DetectReset(
63 63
64 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN; 64 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN;
65 pPackage->fPackageProviderExists = FALSE; 65 pPackage->fPackageProviderExists = FALSE;
66 pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
67 pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
66 68
67 pPackage->cache = BURN_CACHE_STATE_NONE; 69 pPackage->cache = BURN_CACHE_STATE_NONE;
68 for (DWORD iPayload = 0; iPayload < pPackage->cPayloads; ++iPayload) 70 for (DWORD iPayload = 0; iPayload < pPackage->cPayloads; ++iPayload)
diff --git a/src/engine/engine.mc b/src/engine/engine.mc
index d2135839..59a05676 100644
--- a/src/engine/engine.mc
+++ b/src/engine/engine.mc
@@ -188,7 +188,7 @@ MessageId=101
188Severity=Success 188Severity=Success
189SymbolicName=MSG_DETECTED_PACKAGE 189SymbolicName=MSG_DETECTED_PACKAGE
190Language=English 190Language=English
191Detected package: %1!ls!, state: %2!hs!, cached: %3!hs! 191Detected package: %1!ls!, state: %2!hs!, cached: %3!hs!, install registration state: %4!hs!, cache registration state: %5!hs!
192. 192.
193 193
194MessageId=102 194MessageId=102
@@ -300,7 +300,7 @@ MessageId=201
300Severity=Success 300Severity=Success
301SymbolicName=MSG_PLANNED_PACKAGE 301SymbolicName=MSG_PLANNED_PACKAGE
302Language=English 302Language=English
303Planned 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! 303Planned 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. 304.
305 305
306MessageId=202 306MessageId=202
@@ -829,6 +829,21 @@ Language=English
829Session end, registration key: %1!ls!, resume: %2!hs!, restart: %3!hs!, disable resume: %4!hs! 829Session end, registration key: %1!ls!, resume: %2!hs!, restart: %3!hs!, disable resume: %4!hs!
830. 830.
831 831
832MessageId=373
833Severity=Success
834SymbolicName=MSG_POST_APPLY_CALCULATE_REGISTRATION
835Language=English
836Calculating whether to keep registration
837.
838
839
840MessageId=374
841Severity=Success
842SymbolicName=MSG_POST_APPLY_PACKAGE
843Language=English
844 package: %1!ls!, install registration state: %2!hs!, cache registration state: %3!hs!
845.
846
832MessageId=380 847MessageId=380
833Severity=Warning 848Severity=Warning
834SymbolicName=MSG_APPLY_SKIPPED 849SymbolicName=MSG_APPLY_SKIPPED
diff --git a/src/engine/exeengine.cpp b/src/engine/exeengine.cpp
index fd33d926..1ca28473 100644
--- a/src/engine/exeengine.cpp
+++ b/src/engine/exeengine.cpp
@@ -145,6 +145,11 @@ extern "C" HRESULT ExeEngineDetectPackage(
145 // update detect state 145 // update detect state
146 pPackage->currentState = fDetected ? BOOTSTRAPPER_PACKAGE_STATE_PRESENT : BOOTSTRAPPER_PACKAGE_STATE_ABSENT; 146 pPackage->currentState = fDetected ? BOOTSTRAPPER_PACKAGE_STATE_PRESENT : BOOTSTRAPPER_PACKAGE_STATE_ABSENT;
147 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
148LExit: 153LExit:
149 return hr; 154 return hr;
150} 155}
@@ -585,6 +590,31 @@ LExit:
585 return hr; 590 return hr;
586} 591}
587 592
593extern "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
614LExit:
615 return;
616}
617
588 618
589// internal helper functions 619// internal helper functions
590 620
diff --git a/src/engine/exeengine.h b/src/engine/exeengine.h
index 402e51ed..1eac4232 100644
--- a/src/engine/exeengine.h
+++ b/src/engine/exeengine.h
@@ -41,6 +41,10 @@ HRESULT ExeEngineExecutePackage(
41 __in LPVOID pvContext, 41 __in LPVOID pvContext,
42 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 42 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
43 ); 43 );
44void ExeEngineUpdateInstallRegistrationState(
45 __in BURN_EXECUTE_ACTION* pAction,
46 __in HRESULT hrExecute
47 );
44 48
45 49
46#if defined(__cplusplus) 50#if defined(__cplusplus)
diff --git a/src/engine/logging.cpp b/src/engine/logging.cpp
index 9dca527a..a9646218 100644
--- a/src/engine/logging.cpp
+++ b/src/engine/logging.cpp
@@ -399,6 +399,31 @@ extern "C" LPCSTR LoggingPackageStateToString(
399 } 399 }
400} 400}
401 401
402extern "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
402extern "C" LPCSTR LoggingCacheStateToString( 427extern "C" LPCSTR LoggingCacheStateToString(
403 __in BURN_CACHE_STATE cacheState 428 __in BURN_CACHE_STATE cacheState
404 ) 429 )
diff --git a/src/engine/logging.h b/src/engine/logging.h
index b5c6c052..49a8ef5d 100644
--- a/src/engine/logging.h
+++ b/src/engine/logging.h
@@ -89,6 +89,11 @@ LPCSTR LoggingPackageStateToString(
89 __in BOOTSTRAPPER_PACKAGE_STATE packageState 89 __in BOOTSTRAPPER_PACKAGE_STATE packageState
90 ); 90 );
91 91
92LPCSTR LoggingPackageRegistrationStateToString(
93 __in BOOL fCanAffectRegistration,
94 __in BURN_PACKAGE_REGISTRATION_STATE registrationState
95 );
96
92LPCSTR LoggingCacheStateToString( 97LPCSTR LoggingCacheStateToString(
93 __in BURN_CACHE_STATE cacheState 98 __in BURN_CACHE_STATE cacheState
94 ); 99 );
diff --git a/src/engine/msiengine.cpp b/src/engine/msiengine.cpp
index 5bccb375..4fdf2b7a 100644
--- a/src/engine/msiengine.cpp
+++ b/src/engine/msiengine.cpp
@@ -661,6 +661,11 @@ extern "C" HRESULT MsiEngineDetectPackage(
661 } 661 }
662 } 662 }
663 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
664LExit: 669LExit:
665 ReleaseStr(sczInstalledLanguage); 670 ReleaseStr(sczInstalledLanguage);
666 ReleaseStr(sczInstalledVersion); 671 ReleaseStr(sczInstalledVersion);
@@ -1397,6 +1402,42 @@ extern "C" HRESULT MsiEngineCalculateInstallUiLevel(
1397 return UserExperienceOnPlanMsiPackage(pUserExperience, wzPackageId, fExecute, actionState, pActionMsiProperty, pUiLevel, pfDisableExternalUiHandler); 1402 return UserExperienceOnPlanMsiPackage(pUserExperience, wzPackageId, fExecute, actionState, pActionMsiProperty, pUiLevel, pfDisableExternalUiHandler);
1398} 1403}
1399 1404
1405extern "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
1437LExit:
1438 return;
1439}
1440
1400 1441
1401// internal helper functions 1442// internal helper functions
1402 1443
diff --git a/src/engine/msiengine.h b/src/engine/msiengine.h
index 1f450147..d1e46da8 100644
--- a/src/engine/msiengine.h
+++ b/src/engine/msiengine.h
@@ -88,6 +88,11 @@ HRESULT MsiEngineCalculateInstallUiLevel(
88 __out INSTALLUILEVEL* pUiLevel, 88 __out INSTALLUILEVEL* pUiLevel,
89 __out BOOL* pfDisableExternalUiHandler 89 __out BOOL* pfDisableExternalUiHandler
90 ); 90 );
91void MsiEngineUpdateInstallRegistrationState(
92 __in BURN_EXECUTE_ACTION* pAction,
93 __in HRESULT hrExecute,
94 __in BOOL fInsideMsiTransaction
95 );
91 96
92#if defined(__cplusplus) 97#if defined(__cplusplus)
93} 98}
diff --git a/src/engine/mspengine.cpp b/src/engine/mspengine.cpp
index c432b78b..c0329d79 100644
--- a/src/engine/mspengine.cpp
+++ b/src/engine/mspengine.cpp
@@ -200,20 +200,26 @@ extern "C" HRESULT MspEngineDetectPackage(
200 HRESULT hr = S_OK; 200 HRESULT hr = S_OK;
201 LPWSTR sczState = NULL; 201 LPWSTR sczState = NULL;
202 202
203 if (pPackage->fCanAffectRegistration)
204 {
205 pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
206 }
207
203 if (0 == pPackage->Msp.cTargetProductCodes) 208 if (0 == pPackage->Msp.cTargetProductCodes)
204 { 209 {
205 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT; 210 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT;
206 } 211 }
207 else 212 else
208 { 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
210 // target product codes and end up setting the current state to the lowest 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.
212 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED; 217 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED;
213 218
214 for (DWORD i = 0; i < pPackage->Msp.cTargetProductCodes; ++i) 219 for (DWORD i = 0; i < pPackage->Msp.cTargetProductCodes; ++i)
215 { 220 {
216 BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + i; 221 BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + i;
222 BOOL fInstalled = FALSE;
217 223
218 hr = WiuGetPatchInfoEx(pPackage->Msp.sczPatchCode, pTargetProduct->wzTargetProductCode, NULL, pTargetProduct->context, INSTALLPROPERTY_PATCHSTATE, &sczState); 224 hr = WiuGetPatchInfoEx(pPackage->Msp.sczPatchCode, pTargetProduct->wzTargetProductCode, NULL, pTargetProduct->context, INSTALLPROPERTY_PATCHSTATE, &sczState);
219 if (SUCCEEDED(hr)) 225 if (SUCCEEDED(hr))
@@ -221,14 +227,17 @@ extern "C" HRESULT MspEngineDetectPackage(
221 switch (*sczState) 227 switch (*sczState)
222 { 228 {
223 case '1': 229 case '1':
230 fInstalled = TRUE;
224 pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT; 231 pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT;
225 break; 232 break;
226 233
227 case '2': 234 case '2':
235 fInstalled = TRUE;
228 pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED; 236 pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED;
229 break; 237 break;
230 238
231 case '4': 239 case '4':
240 fInstalled = TRUE;
232 pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE; 241 pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE;
233 break; 242 break;
234 243
@@ -249,6 +258,16 @@ extern "C" HRESULT MspEngineDetectPackage(
249 pPackage->currentState = pTargetProduct->patchPackageState; 258 pPackage->currentState = pTargetProduct->patchPackageState;
250 } 259 }
251 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
252 hr = UserExperienceOnDetectTargetMsiPackage(pUserExperience, pPackage->sczId, pTargetProduct->wzTargetProductCode, pTargetProduct->patchPackageState); 271 hr = UserExperienceOnDetectTargetMsiPackage(pUserExperience, pPackage->sczId, pTargetProduct->wzTargetProductCode, pTargetProduct->patchPackageState);
253 ExitOnRootFailure(hr, "BA aborted detect target MSI package."); 272 ExitOnRootFailure(hr, "BA aborted detect target MSI package.");
254 } 273 }
@@ -642,6 +661,92 @@ extern "C" void MspEngineSlipstreamUpdateState(
642 } 661 }
643} 662}
644 663
664extern "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
727LExit:
728 return;
729}
730
731extern "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
645 750
646// internal helper functions 751// internal helper functions
647 752
diff --git a/src/engine/mspengine.h b/src/engine/mspengine.h
index e08fe992..7cc9a119 100644
--- a/src/engine/mspengine.h
+++ b/src/engine/mspengine.h
@@ -62,6 +62,14 @@ void MspEngineSlipstreamUpdateState(
62 __in BOOTSTRAPPER_ACTION_STATE execute, 62 __in BOOTSTRAPPER_ACTION_STATE execute,
63 __in BOOTSTRAPPER_ACTION_STATE rollback 63 __in BOOTSTRAPPER_ACTION_STATE rollback
64 ); 64 );
65void MspEngineUpdateInstallRegistrationState(
66 __in BURN_EXECUTE_ACTION* pAction,
67 __in HRESULT hrExecute,
68 __in BOOL fInsideMsiTransaction
69 );
70void MspEngineFinalizeInstallRegistrationState(
71 __in BURN_PACKAGE* pPackage
72 );
65 73
66 74
67#if defined(__cplusplus) 75#if defined(__cplusplus)
diff --git a/src/engine/msuengine.cpp b/src/engine/msuengine.cpp
index 641d55b1..b7a503ad 100644
--- a/src/engine/msuengine.cpp
+++ b/src/engine/msuengine.cpp
@@ -69,6 +69,11 @@ extern "C" HRESULT MsuEngineDetectPackage(
69 // update detect state 69 // update detect state
70 pPackage->currentState = fDetected ? BOOTSTRAPPER_PACKAGE_STATE_PRESENT : BOOTSTRAPPER_PACKAGE_STATE_ABSENT; 70 pPackage->currentState = fDetected ? BOOTSTRAPPER_PACKAGE_STATE_PRESENT : BOOTSTRAPPER_PACKAGE_STATE_ABSENT;
71 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
72LExit: 77LExit:
73 return hr; 78 return hr;
74} 79}
@@ -424,6 +429,31 @@ LExit:
424 return hr; 429 return hr;
425} 430}
426 431
432extern "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
453LExit:
454 return;
455}
456
427static HRESULT EnsureWUServiceEnabled( 457static HRESULT EnsureWUServiceEnabled(
428 __in BOOL fStopWusaService, 458 __in BOOL fStopWusaService,
429 __out SC_HANDLE* pschWu, 459 __out SC_HANDLE* pschWu,
diff --git a/src/engine/msuengine.h b/src/engine/msuengine.h
index d0323b06..7f57a084 100644
--- a/src/engine/msuengine.h
+++ b/src/engine/msuengine.h
@@ -41,6 +41,10 @@ HRESULT MsuEngineExecutePackage(
41 __in LPVOID pvContext, 41 __in LPVOID pvContext,
42 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 42 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
43 ); 43 );
44void MsuEngineUpdateInstallRegistrationState(
45 __in BURN_EXECUTE_ACTION* pAction,
46 __in HRESULT hrExecute
47 );
44 48
45 49
46#if defined(__cplusplus) 50#if defined(__cplusplus)
diff --git a/src/engine/package.cpp b/src/engine/package.cpp
index 701dda08..b27b1e07 100644
--- a/src/engine/package.cpp
+++ b/src/engine/package.cpp
@@ -156,6 +156,7 @@ extern "C" HRESULT PackagesParseFromXml(
156 hr = XmlGetYesNoAttribute(pixnNode, L"Permanent", &pPackage->fUninstallable); 156 hr = XmlGetYesNoAttribute(pixnNode, L"Permanent", &pPackage->fUninstallable);
157 ExitOnFailure(hr, "Failed to get @Permanent."); 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. 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;
159 160
160 // @Vital 161 // @Vital
161 hr = XmlGetYesNoAttribute(pixnNode, L"Vital", &pPackage->fVital); 162 hr = XmlGetYesNoAttribute(pixnNode, L"Vital", &pPackage->fVital);
diff --git a/src/engine/package.h b/src/engine/package.h
index 8f801e85..d3225fbc 100644
--- a/src/engine/package.h
+++ b/src/engine/package.h
@@ -78,6 +78,14 @@ enum BOOTSTRAPPER_FEATURE_ACTION
78 BOOTSTRAPPER_FEATURE_ACTION_REMOVE, 78 BOOTSTRAPPER_FEATURE_ACTION_REMOVE,
79}; 79};
80 80
81enum 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
81// structs 89// structs
82 90
83typedef struct _BURN_EXE_EXIT_CODE 91typedef struct _BURN_EXE_EXIT_CODE
@@ -106,6 +114,9 @@ typedef struct _BURN_MSPTARGETPRODUCT
106 BOOTSTRAPPER_PACKAGE_STATE patchPackageState; // only valid after Detect. 114 BOOTSTRAPPER_PACKAGE_STATE patchPackageState; // only valid after Detect.
107 BOOTSTRAPPER_ACTION_STATE execute; // only valid during Plan. 115 BOOTSTRAPPER_ACTION_STATE execute; // only valid during Plan.
108 BOOTSTRAPPER_ACTION_STATE rollback; // 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.
109} BURN_MSPTARGETPRODUCT; 120} BURN_MSPTARGETPRODUCT;
110 121
111typedef struct _BURN_MSIPROPERTY 122typedef struct _BURN_MSIPROPERTY
@@ -190,6 +201,7 @@ typedef struct _BURN_PACKAGE
190 BOOL fPerMachine; 201 BOOL fPerMachine;
191 BOOL fUninstallable; 202 BOOL fUninstallable;
192 BOOL fVital; 203 BOOL fVital;
204 BOOL fCanAffectRegistration;
193 205
194 BURN_CACHE_TYPE cacheType; 206 BURN_CACHE_TYPE cacheType;
195 LPWSTR sczCacheId; 207 LPWSTR sczCacheId;
@@ -216,6 +228,12 @@ typedef struct _BURN_PACKAGE
216 BOOL fDependencyManagerWasHere; // only valid during Plan. 228 BOOL fDependencyManagerWasHere; // only valid during Plan.
217 HRESULT hrCacheResult; // only valid during Apply. 229 HRESULT hrCacheResult; // only valid during Apply.
218 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
219 BURN_PACKAGE_PAYLOAD* rgPayloads; 237 BURN_PACKAGE_PAYLOAD* rgPayloads;
220 DWORD cPayloads; 238 DWORD cPayloads;
221 239
diff --git a/src/engine/plan.cpp b/src/engine/plan.cpp
index 6f5407b9..1aaec252 100644
--- a/src/engine/plan.cpp
+++ b/src/engine/plan.cpp
@@ -6,13 +6,6 @@
6 6
7// internal struct definitions 7// internal struct definitions
8 8
9struct PLAN_NONPERMANENT_PACKAGE_INDICES
10{
11 DWORD iAfterExecuteFirstNonPermanentPackage;
12 DWORD iBeforeRollbackFirstNonPermanentPackage;
13 DWORD iAfterExecuteLastNonPermanentPackage;
14 DWORD iAfterRollbackLastNonPermanentPackage;
15};
16 9
17// internal function definitions 10// internal function definitions
18 11
@@ -39,8 +32,7 @@ static HRESULT ProcessPackage(
39 __in BOOTSTRAPPER_RELATION_TYPE relationType, 32 __in BOOTSTRAPPER_RELATION_TYPE relationType,
40 __in_z_opt LPCWSTR wzLayoutDirectory, 33 __in_z_opt LPCWSTR wzLayoutDirectory,
41 __inout HANDLE* phSyncpointEvent, 34 __inout HANDLE* phSyncpointEvent,
42 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary, 35 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary
43 __in_opt PLAN_NONPERMANENT_PACKAGE_INDICES* pNonpermanentPackageIndices
44 ); 36 );
45static HRESULT ProcessPackageRollbackBoundary( 37static HRESULT ProcessPackageRollbackBoundary(
46 __in BURN_PLAN* pPlan, 38 __in BURN_PLAN* pPlan,
@@ -479,7 +471,7 @@ extern "C" HRESULT PlanPackages(
479 __in BURN_PLAN* pPlan, 471 __in BURN_PLAN* pPlan,
480 __in BURN_LOGGING* pLog, 472 __in BURN_LOGGING* pLog,
481 __in BURN_VARIABLES* pVariables, 473 __in BURN_VARIABLES* pVariables,
482 __in BOOL fBundleInstalled, 474 __in BOOL /*fBundleInstalled*/,
483 __in BOOTSTRAPPER_DISPLAY display, 475 __in BOOTSTRAPPER_DISPLAY display,
484 __in BOOTSTRAPPER_RELATION_TYPE relationType, 476 __in BOOTSTRAPPER_RELATION_TYPE relationType,
485 __in_z_opt LPCWSTR wzLayoutDirectory, 477 __in_z_opt LPCWSTR wzLayoutDirectory,
@@ -490,12 +482,6 @@ extern "C" HRESULT PlanPackages(
490 BOOL fBundlePerMachine = pPlan->fPerMachine; // bundle is per-machine if plan starts per-machine. 482 BOOL fBundlePerMachine = pPlan->fPerMachine; // bundle is per-machine if plan starts per-machine.
491 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL; 483 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL;
492 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
499 // Plan the packages. 485 // Plan the packages.
500 for (DWORD i = 0; i < pPackages->cPackages; ++i) 486 for (DWORD i = 0; i < pPackages->cPackages; ++i)
501 { 487 {
@@ -518,34 +504,10 @@ extern "C" HRESULT PlanPackages(
518 } 504 }
519 } 505 }
520 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);
522 ExitOnFailure(hr, "Failed to process package."); 508 ExitOnFailure(hr, "Failed to process package.");
523 } 509 }
524 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
549 // If we still have an open rollback boundary, complete it. 511 // If we still have an open rollback boundary, complete it.
550 if (pRollbackBoundary) 512 if (pRollbackBoundary)
551 { 513 {
@@ -572,9 +534,9 @@ LExit:
572extern "C" HRESULT PlanRegistration( 534extern "C" HRESULT PlanRegistration(
573 __in BURN_PLAN* pPlan, 535 __in BURN_PLAN* pPlan,
574 __in BURN_REGISTRATION* pRegistration, 536 __in BURN_REGISTRATION* pRegistration,
575 __in BOOTSTRAPPER_RESUME_TYPE resumeType, 537 __in BOOTSTRAPPER_RESUME_TYPE /*resumeType*/,
576 __in BOOTSTRAPPER_RELATION_TYPE relationType, 538 __in BOOTSTRAPPER_RELATION_TYPE relationType,
577 __out BOOL* pfContinuePlanning 539 __inout BOOL* pfContinuePlanning
578 ) 540 )
579{ 541{
580 HRESULT hr = S_OK; 542 HRESULT hr = S_OK;
@@ -583,9 +545,6 @@ extern "C" HRESULT PlanRegistration(
583 545
584 pPlan->fRegister = TRUE; // register the bundle since we're modifying machine state. 546 pPlan->fRegister = TRUE; // register the bundle since we're modifying machine state.
585 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
589 pPlan->fDisallowRemoval = FALSE; // by default the bundle can be planned to be removed 548 pPlan->fDisallowRemoval = FALSE; // by default the bundle can be planned to be removed
590 549
591 if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) 550 if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action)
@@ -692,7 +651,7 @@ extern "C" HRESULT PlanRegistration(
692 pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE; 651 pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE;
693 pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION; 652 pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION;
694 } 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.
696 { 655 {
697 pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE; 656 pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE;
698 pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION; 657 pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION;
@@ -786,7 +745,7 @@ extern "C" HRESULT PlanPassThroughBundle(
786 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL; 745 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL;
787 746
788 // Plan passthrough package. 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);
790 ExitOnFailure(hr, "Failed to process passthrough package."); 749 ExitOnFailure(hr, "Failed to process passthrough package.");
791 750
792 // If we still have an open rollback boundary, complete it. 751 // If we still have an open rollback boundary, complete it.
@@ -820,7 +779,7 @@ extern "C" HRESULT PlanUpdateBundle(
820 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL; 779 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL;
821 780
822 // Plan update package. 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);
824 ExitOnFailure(hr, "Failed to process update package."); 783 ExitOnFailure(hr, "Failed to process update package.");
825 784
826 // If we still have an open rollback boundary, complete it. 785 // If we still have an open rollback boundary, complete it.
@@ -849,8 +808,7 @@ static HRESULT ProcessPackage(
849 __in BOOTSTRAPPER_RELATION_TYPE relationType, 808 __in BOOTSTRAPPER_RELATION_TYPE relationType,
850 __in_z_opt LPCWSTR wzLayoutDirectory, 809 __in_z_opt LPCWSTR wzLayoutDirectory,
851 __inout HANDLE* phSyncpointEvent, 810 __inout HANDLE* phSyncpointEvent,
852 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary, 811 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary
853 __in_opt PLAN_NONPERMANENT_PACKAGE_INDICES* pNonpermanentPackageIndices
854 ) 812 )
855{ 813{
856 HRESULT hr = S_OK; 814 HRESULT hr = S_OK;
@@ -871,6 +829,12 @@ static HRESULT ProcessPackage(
871 hr = ProcessPackageRollbackBoundary(pPlan, pEffectiveRollbackBoundary, ppRollbackBoundary); 829 hr = ProcessPackageRollbackBoundary(pPlan, pEffectiveRollbackBoundary, ppRollbackBoundary);
872 ExitOnFailure(hr, "Failed to process package rollback boundary."); 830 ExitOnFailure(hr, "Failed to process package rollback boundary.");
873 831
832 if (pPackage->fCanAffectRegistration)
833 {
834 pPackage->expectedCacheRegistrationState = pPackage->cacheRegistrationState;
835 pPackage->expectedInstallRegistrationState = pPackage->installRegistrationState;
836 }
837
874 // If the package is in a requested state, plan it. 838 // If the package is in a requested state, plan it.
875 if (BOOTSTRAPPER_REQUEST_STATE_NONE != pPackage->requested) 839 if (BOOTSTRAPPER_REQUEST_STATE_NONE != pPackage->requested)
876 { 840 {
@@ -881,26 +845,19 @@ static HRESULT ProcessPackage(
881 } 845 }
882 else 846 else
883 { 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
892 hr = PlanExecutePackage(fBundlePerMachine, display, pUX, pPlan, pPackage, pLog, pVariables, phSyncpointEvent); 848 hr = PlanExecutePackage(fBundlePerMachine, display, pUX, pPlan, pPackage, pLog, pVariables, phSyncpointEvent);
893 ExitOnFailure(hr, "Failed to plan execute package."); 849 ExitOnFailure(hr, "Failed to plan execute package.");
894 850
895 if (pPackage->fUninstallable && pNonpermanentPackageIndices) 851 if (pPackage->fCanAffectRegistration)
896 { 852 {
897 if (BURN_PLAN_INVALID_ACTION_INDEX == pNonpermanentPackageIndices->iAfterExecuteFirstNonPermanentPackage) 853 if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL < pPackage->execute)
898 { 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;
900 } 860 }
901
902 pNonpermanentPackageIndices->iAfterExecuteLastNonPermanentPackage = pPlan->cExecuteActions;
903 pNonpermanentPackageIndices->iAfterRollbackLastNonPermanentPackage = pPlan->cRollbackActions;
904 } 861 }
905 } 862 }
906 } 863 }
@@ -920,6 +877,32 @@ static HRESULT ProcessPackage(
920 } 877 }
921 } 878 }
922 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
923 // Add the checkpoint after each package and dependency registration action. 906 // Add the checkpoint after each package and dependency registration action.
924 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute || BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->rollback || BURN_DEPENDENCY_ACTION_NONE != pPackage->dependencyExecute) 907 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute || BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->rollback || BURN_DEPENDENCY_ACTION_NONE != pPackage->dependencyExecute)
925 { 908 {
@@ -1572,6 +1555,11 @@ extern "C" HRESULT PlanCleanPackage(
1572 pCleanAction->pPackage = pPackage; 1555 pCleanAction->pPackage = pPackage;
1573 1556
1574 pPackage->fUncache = TRUE; 1557 pPackage->fUncache = TRUE;
1558
1559 if (pPackage->fCanAffectRegistration)
1560 {
1561 pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_ABSENT;
1562 }
1575 } 1563 }
1576 1564
1577LExit: 1565LExit:
@@ -1708,68 +1696,6 @@ LExit:
1708 return hr; 1696 return hr;
1709} 1697}
1710 1698
1711extern "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
1738LExit:
1739 return hr;
1740}
1741
1742extern "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
1769LExit:
1770 return hr;
1771}
1772
1773extern "C" HRESULT PlanRollbackBoundaryBegin( 1699extern "C" HRESULT PlanRollbackBoundaryBegin(
1774 __in BURN_PLAN* pPlan, 1700 __in BURN_PLAN* pPlan,
1775 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary 1701 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary
@@ -1925,6 +1851,8 @@ static void ResetPlannedPackageState(
1925 pPackage->dependencyExecute = BURN_DEPENDENCY_ACTION_NONE; 1851 pPackage->dependencyExecute = BURN_DEPENDENCY_ACTION_NONE;
1926 pPackage->dependencyRollback = BURN_DEPENDENCY_ACTION_NONE; 1852 pPackage->dependencyRollback = BURN_DEPENDENCY_ACTION_NONE;
1927 pPackage->fDependencyManagerWasHere = FALSE; 1853 pPackage->fDependencyManagerWasHere = FALSE;
1854 pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
1855 pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
1928 1856
1929 if (BURN_PACKAGE_TYPE_MSI == pPackage->type && pPackage->Msi.rgFeatures) 1857 if (BURN_PACKAGE_TYPE_MSI == pPackage->type && pPackage->Msi.rgFeatures)
1930 { 1858 {
@@ -2198,6 +2126,11 @@ static HRESULT AddCachePackageHelper(
2198 // did cache operations to verify the cache is valid so we did not plan the acquisition of the package. 2126 // did cache operations to verify the cache is valid so we did not plan the acquisition of the package.
2199 pPackage->fAcquire = (BURN_CACHE_STATE_COMPLETE != pPackage->cache); 2127 pPackage->fAcquire = (BURN_CACHE_STATE_COMPLETE != pPackage->cache);
2200 2128
2129 if (pPackage->fCanAffectRegistration)
2130 {
2131 pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
2132 }
2133
2201LExit: 2134LExit:
2202 return hr; 2135 return hr;
2203} 2136}
@@ -3118,10 +3051,6 @@ static void ExecuteActionLog(
3118 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); 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);
3119 break; 3052 break;
3120 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
3125 case BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY: 3054 case BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY:
3126 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"); 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");
3127 break; 3056 break;
@@ -3157,7 +3086,6 @@ extern "C" void PlanDump(
3157 LogStringLine(PlanDumpLevel, "Plan action: %hs", LoggingBurnActionToString(pPlan->action)); 3086 LogStringLine(PlanDumpLevel, "Plan action: %hs", LoggingBurnActionToString(pPlan->action));
3158 LogStringLine(PlanDumpLevel, " per-machine: %hs", LoggingTrueFalseToString(pPlan->fPerMachine)); 3087 LogStringLine(PlanDumpLevel, " per-machine: %hs", LoggingTrueFalseToString(pPlan->fPerMachine));
3159 LogStringLine(PlanDumpLevel, " disable-rollback: %hs", LoggingTrueFalseToString(pPlan->fDisableRollback)); 3088 LogStringLine(PlanDumpLevel, " disable-rollback: %hs", LoggingTrueFalseToString(pPlan->fDisableRollback));
3160 LogStringLine(PlanDumpLevel, " keep registration by default: %hs", LoggingTrueFalseToString(pPlan->fKeepRegistrationDefault));
3161 LogStringLine(PlanDumpLevel, " estimated size: %llu", pPlan->qwEstimatedSize); 3089 LogStringLine(PlanDumpLevel, " estimated size: %llu", pPlan->qwEstimatedSize);
3162 3090
3163 LogStringLine(PlanDumpLevel, "Plan cache size: %llu", pPlan->qwCacheSizeTotal); 3091 LogStringLine(PlanDumpLevel, "Plan cache size: %llu", pPlan->qwCacheSizeTotal);
diff --git a/src/engine/plan.h b/src/engine/plan.h
index 54189973..6c12b5fa 100644
--- a/src/engine/plan.h
+++ b/src/engine/plan.h
@@ -64,7 +64,6 @@ enum BURN_EXECUTE_ACTION_TYPE
64 BURN_EXECUTE_ACTION_TYPE_PACKAGE_PROVIDER, 64 BURN_EXECUTE_ACTION_TYPE_PACKAGE_PROVIDER,
65 BURN_EXECUTE_ACTION_TYPE_PACKAGE_DEPENDENCY, 65 BURN_EXECUTE_ACTION_TYPE_PACKAGE_DEPENDENCY,
66 BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY, 66 BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY,
67 BURN_EXECUTE_ACTION_TYPE_REGISTRATION,
68 BURN_EXECUTE_ACTION_TYPE_BEGIN_MSI_TRANSACTION, 67 BURN_EXECUTE_ACTION_TYPE_BEGIN_MSI_TRANSACTION,
69 BURN_EXECUTE_ACTION_TYPE_COMMIT_MSI_TRANSACTION, 68 BURN_EXECUTE_ACTION_TYPE_COMMIT_MSI_TRANSACTION,
70}; 69};
@@ -282,10 +281,6 @@ typedef struct _BURN_EXECUTE_ACTION
282 } msuPackage; 281 } msuPackage;
283 struct 282 struct
284 { 283 {
285 BOOL fKeep;
286 } registration;
287 struct
288 {
289 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary; 284 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary;
290 } rollbackBoundary; 285 } rollbackBoundary;
291 struct 286 struct
@@ -319,7 +314,6 @@ typedef struct _BURN_PLAN
319 BOOL fPerMachine; 314 BOOL fPerMachine;
320 BOOL fRegister; 315 BOOL fRegister;
321 DWORD dwRegistrationOperations; 316 DWORD dwRegistrationOperations;
322 BOOL fKeepRegistrationDefault;
323 BOOL fDisallowRemoval; 317 BOOL fDisallowRemoval;
324 BOOL fDisableRollback; 318 BOOL fDisableRollback;
325 319
@@ -418,7 +412,7 @@ HRESULT PlanRegistration(
418 __in BURN_REGISTRATION* pRegistration, 412 __in BURN_REGISTRATION* pRegistration,
419 __in BOOTSTRAPPER_RESUME_TYPE resumeType, 413 __in BOOTSTRAPPER_RESUME_TYPE resumeType,
420 __in BOOTSTRAPPER_RELATION_TYPE relationType, 414 __in BOOTSTRAPPER_RELATION_TYPE relationType,
421 __out BOOL* pfContinuePlanning 415 __inout BOOL* pfContinuePlanning
422 ); 416 );
423HRESULT PlanPassThroughBundle( 417HRESULT PlanPassThroughBundle(
424 __in BURN_USER_EXPERIENCE* pUX, 418 __in BURN_USER_EXPERIENCE* pUX,
@@ -519,16 +513,6 @@ HRESULT PlanAppendRollbackAction(
519 __in BURN_PLAN* pPlan, 513 __in BURN_PLAN* pPlan,
520 __out BURN_EXECUTE_ACTION** ppExecuteAction 514 __out BURN_EXECUTE_ACTION** ppExecuteAction
521 ); 515 );
522HRESULT PlanKeepRegistration(
523 __in BURN_PLAN* pPlan,
524 __in DWORD iAfterExecutePackageAction,
525 __in DWORD iBeforeRollbackPackageAction
526 );
527HRESULT PlanRemoveRegistration(
528 __in BURN_PLAN* pPlan,
529 __in DWORD iAfterExecutePackageAction,
530 __in DWORD iAfterRollbackPackageAction
531 );
532HRESULT PlanRollbackBoundaryBegin( 516HRESULT PlanRollbackBoundaryBegin(
533 __in BURN_PLAN* pPlan, 517 __in BURN_PLAN* pPlan,
534 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary 518 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary