aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2020-11-15 21:38:57 -0600
committerSean Hall <r.sean.hall@gmail.com>2020-11-17 19:06:00 -0600
commite71de85e4ec2899ecd01ac236603cf1dddc4a6c7 (patch)
treeb1537ce17314dc073a9fd3d7d4925f215990be13
parent846f5a033d346c1bac51c56d4936cd3118ebea7a (diff)
downloadwix-e71de85e4ec2899ecd01ac236603cf1dddc4a6c7.tar.gz
wix-e71de85e4ec2899ecd01ac236603cf1dddc4a6c7.tar.bz2
wix-e71de85e4ec2899ecd01ac236603cf1dddc4a6c7.zip
Use plan to decide when to begin, commit, or rollback MSI transactions
-rw-r--r--src/engine/apply.cpp194
-rw-r--r--src/engine/msiengine.cpp5
-rw-r--r--src/engine/msiengine.h1
-rw-r--r--src/engine/mspengine.cpp5
-rw-r--r--src/engine/mspengine.h1
-rw-r--r--src/engine/package.h1
-rw-r--r--src/engine/plan.cpp86
-rw-r--r--src/engine/plan.h20
-rw-r--r--src/test/BurnUnitTest/PlanTest.cpp62
9 files changed, 226 insertions, 149 deletions
diff --git a/src/engine/apply.cpp b/src/engine/apply.cpp
index 909fb159..53422807 100644
--- a/src/engine/apply.cpp
+++ b/src/engine/apply.cpp
@@ -3,6 +3,12 @@
3#include "precomp.h" 3#include "precomp.h"
4 4
5 5
6#ifdef DEBUG
7 #define IgnoreRollbackError(x, f, ...) if (FAILED(x)) { TraceError(x, f, __VA_ARGS__); }
8#else
9 #define IgnoreRollbackError(x, f, ...)
10#endif
11
6const DWORD BURN_CACHE_MAX_RECOMMENDED_VERIFY_TRYAGAIN_ATTEMPTS = 2; 12const DWORD BURN_CACHE_MAX_RECOMMENDED_VERIFY_TRYAGAIN_ATTEMPTS = 2;
7 13
8// structs 14// structs
@@ -134,7 +140,7 @@ static HRESULT DoExecuteAction(
134 __in_opt HANDLE hCacheThread, 140 __in_opt HANDLE hCacheThread,
135 __in BURN_EXECUTE_CONTEXT* pContext, 141 __in BURN_EXECUTE_CONTEXT* pContext,
136 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary, 142 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary,
137 __out DWORD* pdwCheckpoint, 143 __inout BURN_EXECUTE_ACTION_CHECKPOINT** ppCheckpoint,
138 __out BOOL* pfKeepRegistration, 144 __out BOOL* pfKeepRegistration,
139 __out BOOL* pfSuspend, 145 __out BOOL* pfSuspend,
140 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 146 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
@@ -143,7 +149,6 @@ static HRESULT DoRollbackActions(
143 __in BURN_ENGINE_STATE* pEngineState, 149 __in BURN_ENGINE_STATE* pEngineState,
144 __in BURN_EXECUTE_CONTEXT* pContext, 150 __in BURN_EXECUTE_CONTEXT* pContext,
145 __in DWORD dwCheckpoint, 151 __in DWORD dwCheckpoint,
146 __in BOOL fInTransaction,
147 __out BOOL* pfKeepRegistration, 152 __out BOOL* pfKeepRegistration,
148 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 153 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
149 ); 154 );
@@ -200,15 +205,17 @@ static HRESULT ExecuteCompatiblePackageAction(
200 ); 205 );
201static HRESULT ExecuteMsiBeginTransaction( 206static HRESULT ExecuteMsiBeginTransaction(
202 __in BURN_ENGINE_STATE* pEngineState, 207 __in BURN_ENGINE_STATE* pEngineState,
203 __in LPCWSTR wzName, 208 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary,
204 __in BURN_EXECUTE_CONTEXT* pContext 209 __in BURN_EXECUTE_CONTEXT* pContext
205 ); 210 );
206static HRESULT ExecuteMsiCommitTransaction( 211static HRESULT ExecuteMsiCommitTransaction(
207 __in BURN_ENGINE_STATE* pEngineState, 212 __in BURN_ENGINE_STATE* pEngineState,
213 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary,
208 __in BURN_EXECUTE_CONTEXT* pContext 214 __in BURN_EXECUTE_CONTEXT* pContext
209 ); 215 );
210static HRESULT ExecuteMsiRollbackTransaction( 216static HRESULT ExecuteMsiRollbackTransaction(
211 __in BURN_ENGINE_STATE* pEngineState, 217 __in BURN_ENGINE_STATE* pEngineState,
218 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary,
212 __in BURN_EXECUTE_CONTEXT* pContext 219 __in BURN_EXECUTE_CONTEXT* pContext
213 ); 220 );
214static HRESULT CleanPackage( 221static HRESULT CleanPackage(
@@ -732,11 +739,11 @@ extern "C" HRESULT ApplyExecute(
732 ) 739 )
733{ 740{
734 HRESULT hr = S_OK; 741 HRESULT hr = S_OK;
735 DWORD dwCheckpoint = 0; 742 HRESULT hrRollback = S_OK;
743 BURN_EXECUTE_ACTION_CHECKPOINT* pCheckpoint = NULL;
736 BURN_EXECUTE_CONTEXT context = { }; 744 BURN_EXECUTE_CONTEXT context = { };
737 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL; 745 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL;
738 BOOL fSeekNextRollbackBoundary = FALSE; 746 BOOL fSeekNextRollbackBoundary = FALSE;
739 BOOL fInTransaction = FALSE;
740 747
741 context.pUX = &pEngineState->userExperience; 748 context.pUX = &pEngineState->userExperience;
742 context.cExecutePackagesTotal = pEngineState->plan.cExecutePackagesTotal; 749 context.cExecutePackagesTotal = pEngineState->plan.cExecutePackagesTotal;
@@ -755,36 +762,6 @@ extern "C" HRESULT ApplyExecute(
755 continue; 762 continue;
756 } 763 }
757 764
758 // Transaction end/start
759 if (BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY == pExecuteAction->type)
760 {
761 // End previous transaction
762 if (fInTransaction)
763 {
764 LogString(REPORT_STANDARD, "Committing MSI transaction\n");
765 hr = ExecuteMsiCommitTransaction(pEngineState, &context);
766 ExitOnFailure(hr, "Failed committing an MSI transaction");
767 fInTransaction = FALSE;
768 }
769
770 // Start New transaction
771 if (!fInTransaction && pExecuteAction->rollbackBoundary.pRollbackBoundary && pExecuteAction->rollbackBoundary.pRollbackBoundary->fTransaction)
772 {
773 // Transactions don't go together with DisableRollback.
774 if (pEngineState->fDisableRollback)
775 {
776 LogString(REPORT_STANDARD, "Ignoring Transaction flag due to DisableRollback flag\n");
777 }
778 else
779 {
780 LogString(REPORT_STANDARD, "Starting a new MSI transaction\n");
781 hr = ExecuteMsiBeginTransaction(pEngineState, pExecuteAction->rollbackBoundary.pRollbackBoundary->sczId, &context);
782 ExitOnFailure(hr, "Failed beginning an MSI transaction");
783 fInTransaction = TRUE;
784 }
785 }
786 }
787
788 // If we are seeking the next rollback boundary, skip if this action wasn't it. 765 // If we are seeking the next rollback boundary, skip if this action wasn't it.
789 if (fSeekNextRollbackBoundary) 766 if (fSeekNextRollbackBoundary)
790 { 767 {
@@ -799,11 +776,11 @@ extern "C" HRESULT ApplyExecute(
799 } 776 }
800 777
801 // Execute the action. 778 // Execute the action.
802 hr = DoExecuteAction(pEngineState, pExecuteAction, hCacheThread, &context, &pRollbackBoundary, &dwCheckpoint, pfKeepRegistration, pfSuspend, pRestart); 779 hr = DoExecuteAction(pEngineState, pExecuteAction, hCacheThread, &context, &pRollbackBoundary, &pCheckpoint, pfKeepRegistration, pfSuspend, pRestart);
803 780
804 if (*pfSuspend || BOOTSTRAPPER_APPLY_RESTART_INITIATED == *pRestart) 781 if (*pfSuspend || BOOTSTRAPPER_APPLY_RESTART_INITIATED == *pRestart)
805 { 782 {
806 if (fInTransaction) 783 if (pCheckpoint && pCheckpoint->pActiveRollbackBoundary && pCheckpoint->pActiveRollbackBoundary->fActiveTransaction)
807 { 784 {
808 hr = E_INVALIDSTATE; 785 hr = E_INVALIDSTATE;
809 LogString(REPORT_ERROR, "Ilegal state: Reboot requested within an MSI transaction. Transaction will rollback."); 786 LogString(REPORT_ERROR, "Ilegal state: Reboot requested within an MSI transaction. Transaction will rollback.");
@@ -816,37 +793,43 @@ extern "C" HRESULT ApplyExecute(
816 793
817 if (FAILED(hr)) 794 if (FAILED(hr))
818 { 795 {
819 // If we failed, but rollback is disabled just bail with our error code. 796 // If rollback is disabled, keep what we have and always end execution here.
820 if (pEngineState->fDisableRollback) 797 if (pEngineState->plan.fDisableRollback)
821 { 798 {
799 if (pCheckpoint && pCheckpoint->pActiveRollbackBoundary && pCheckpoint->pActiveRollbackBoundary->fActiveTransaction)
800 {
801 hrRollback = ExecuteMsiCommitTransaction(pEngineState, pCheckpoint->pActiveRollbackBoundary, &context);
802 IgnoreRollbackError(hrRollback, "Failed commit transaction from disable rollback");
803 }
804
822 *pfRollback = TRUE; 805 *pfRollback = TRUE;
823 break; 806 break;
824 } 807 }
825 else // the action failed, roll back to previous rollback boundary. 808
809 // If inside a MSI transaction, roll it back.
810 if (pCheckpoint && pCheckpoint->pActiveRollbackBoundary && pCheckpoint->pActiveRollbackBoundary->fActiveTransaction)
826 { 811 {
827 HRESULT hrRollback = DoRollbackActions(pEngineState, &context, dwCheckpoint, fInTransaction, pfKeepRegistration, pRestart); 812 hrRollback = ExecuteMsiRollbackTransaction(pEngineState, pCheckpoint->pActiveRollbackBoundary, &context);
828 UNREFERENCED_PARAMETER(hrRollback); 813 IgnoreRollbackError(hrRollback, "Failed rolling back transaction");
829 fInTransaction = FALSE; 814 }
830 815
831 // If the rollback boundary is vital, end execution here. 816 // The action failed, roll back to previous rollback boundary.
832 if (pRollbackBoundary && pRollbackBoundary->fVital) 817 if (pCheckpoint)
833 { 818 {
834 *pfRollback = TRUE; 819 hrRollback = DoRollbackActions(pEngineState, &context, pCheckpoint->dwId, pfKeepRegistration, pRestart);
835 break; 820 IgnoreRollbackError(hrRollback, "Failed rollback actions");
836 } 821 }
837 822
838 // Move forward to next rollback boundary. 823 // If the rollback boundary is vital, end execution here.
839 fSeekNextRollbackBoundary = TRUE; 824 if (pRollbackBoundary && pRollbackBoundary->fVital)
825 {
826 *pfRollback = TRUE;
827 break;
840 } 828 }
841 }
842 }
843 829
844 if (fInTransaction) 830 // Move forward to next rollback boundary.
845 { 831 fSeekNextRollbackBoundary = TRUE;
846 LogString(REPORT_STANDARD, "Committing an MSI transaction\n"); 832 }
847 hr = ExecuteMsiCommitTransaction(pEngineState, &context);
848 ExitOnFailure(hr, "Failed committing an MSI transaction");
849 fInTransaction = FALSE;
850 } 833 }
851 834
852LExit: 835LExit:
@@ -1653,7 +1636,7 @@ static HRESULT DoExecuteAction(
1653 __in_opt HANDLE hCacheThread, 1636 __in_opt HANDLE hCacheThread,
1654 __in BURN_EXECUTE_CONTEXT* pContext, 1637 __in BURN_EXECUTE_CONTEXT* pContext,
1655 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary, 1638 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary,
1656 __out DWORD* pdwCheckpoint, 1639 __inout BURN_EXECUTE_ACTION_CHECKPOINT** ppCheckpoint,
1657 __out BOOL* pfKeepRegistration, 1640 __out BOOL* pfKeepRegistration,
1658 __out BOOL* pfSuspend, 1641 __out BOOL* pfSuspend,
1659 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 1642 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
@@ -1674,7 +1657,7 @@ static HRESULT DoExecuteAction(
1674 switch (pExecuteAction->type) 1657 switch (pExecuteAction->type)
1675 { 1658 {
1676 case BURN_EXECUTE_ACTION_TYPE_CHECKPOINT: 1659 case BURN_EXECUTE_ACTION_TYPE_CHECKPOINT:
1677 *pdwCheckpoint = pExecuteAction->checkpoint.dwId; 1660 *ppCheckpoint = &pExecuteAction->checkpoint;
1678 break; 1661 break;
1679 1662
1680 case BURN_EXECUTE_ACTION_TYPE_WAIT_SYNCPOINT: 1663 case BURN_EXECUTE_ACTION_TYPE_WAIT_SYNCPOINT:
@@ -1748,6 +1731,18 @@ static HRESULT DoExecuteAction(
1748 *ppRollbackBoundary = pExecuteAction->rollbackBoundary.pRollbackBoundary; 1731 *ppRollbackBoundary = pExecuteAction->rollbackBoundary.pRollbackBoundary;
1749 break; 1732 break;
1750 1733
1734 case BURN_EXECUTE_ACTION_TYPE_BEGIN_MSI_TRANSACTION:
1735 LogString(REPORT_STANDARD, "Starting a new MSI transaction\n");
1736 hr = ExecuteMsiBeginTransaction(pEngineState, pExecuteAction->msiTransaction.pRollbackBoundary, pContext);
1737 ExitOnFailure(hr, "Failed to execute begin MSI transaction action.");
1738 break;
1739
1740 case BURN_EXECUTE_ACTION_TYPE_COMMIT_MSI_TRANSACTION:
1741 LogString(REPORT_STANDARD, "Committing MSI transaction\n");
1742 hr = ExecuteMsiCommitTransaction(pEngineState, pExecuteAction->msiTransaction.pRollbackBoundary, pContext);
1743 ExitOnFailure(hr, "Failed to execute commit MSI transaction action.");
1744 break;
1745
1751 case BURN_EXECUTE_ACTION_TYPE_SERVICE_STOP: __fallthrough; 1746 case BURN_EXECUTE_ACTION_TYPE_SERVICE_STOP: __fallthrough;
1752 case BURN_EXECUTE_ACTION_TYPE_SERVICE_START: __fallthrough; 1747 case BURN_EXECUTE_ACTION_TYPE_SERVICE_START: __fallthrough;
1753 default: 1748 default:
@@ -1769,7 +1764,6 @@ static HRESULT DoRollbackActions(
1769 __in BURN_ENGINE_STATE* pEngineState, 1764 __in BURN_ENGINE_STATE* pEngineState,
1770 __in BURN_EXECUTE_CONTEXT* pContext, 1765 __in BURN_EXECUTE_CONTEXT* pContext,
1771 __in DWORD dwCheckpoint, 1766 __in DWORD dwCheckpoint,
1772 __in BOOL fInTransaction,
1773 __out BOOL* pfKeepRegistration, 1767 __out BOOL* pfKeepRegistration,
1774 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 1768 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
1775 ) 1769 )
@@ -1781,13 +1775,6 @@ static HRESULT DoRollbackActions(
1781 1775
1782 pContext->fRollback = TRUE; 1776 pContext->fRollback = TRUE;
1783 1777
1784 // Rollback MSI transaction
1785 if (fInTransaction)
1786 {
1787 hr = ExecuteMsiRollbackTransaction(pEngineState, pContext);
1788 ExitOnFailure(hr, "Failed rolling back transaction");
1789 }
1790
1791 // scan to last checkpoint 1778 // scan to last checkpoint
1792 for (DWORD i = 0; i < pEngineState->plan.cRollbackActions; ++i) 1779 for (DWORD i = 0; i < pEngineState->plan.cRollbackActions; ++i)
1793 { 1780 {
@@ -1827,53 +1814,32 @@ static HRESULT DoRollbackActions(
1827 1814
1828 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: 1815 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
1829 hr = ExecuteExePackage(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart); 1816 hr = ExecuteExePackage(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart);
1830 TraceError(hr, "Failed to rollback EXE package."); 1817 IgnoreRollbackError(hr, "Failed to rollback EXE package.");
1831 hr = S_OK;
1832 break; 1818 break;
1833 1819
1834 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: 1820 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
1835 if (fInTransaction)
1836 {
1837 LogString(REPORT_STANDARD, "Skipping rolling back an MSI package- already done in transaction rollback\n");
1838 break;
1839 }
1840 hr = ExecuteMsiPackage(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart); 1821 hr = ExecuteMsiPackage(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart);
1841 TraceError(hr, "Failed to rollback MSI package."); 1822 IgnoreRollbackError(hr, "Failed to rollback MSI package.");
1842 hr = S_OK;
1843 break; 1823 break;
1844 1824
1845 case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET: 1825 case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET:
1846 if (fInTransaction)
1847 {
1848 LogString(REPORT_STANDARD, "Skipping rolling back an MSP package- already done in transaction rollback\n");
1849 break;
1850 }
1851 hr = ExecuteMspPackage(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart); 1826 hr = ExecuteMspPackage(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart);
1852 TraceError(hr, "Failed to rollback MSP package."); 1827 IgnoreRollbackError(hr, "Failed to rollback MSP package.");
1853 hr = S_OK;
1854 break; 1828 break;
1855 1829
1856 case BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE: 1830 case BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE:
1857 if (fInTransaction)
1858 {
1859 LogString(REPORT_STANDARD, "Skipping rolling back an MSU package- already done in transaction rollback\n");
1860 break;
1861 }
1862 hr = ExecuteMsuPackage(pEngineState, pRollbackAction, pContext, TRUE, FALSE, &fRetryIgnored, &fSuspendIgnored, &restart); 1831 hr = ExecuteMsuPackage(pEngineState, pRollbackAction, pContext, TRUE, FALSE, &fRetryIgnored, &fSuspendIgnored, &restart);
1863 TraceError(hr, "Failed to rollback MSU package."); 1832 IgnoreRollbackError(hr, "Failed to rollback MSU package.");
1864 hr = S_OK;
1865 break; 1833 break;
1866 1834
1867 case BURN_EXECUTE_ACTION_TYPE_PACKAGE_PROVIDER: 1835 case BURN_EXECUTE_ACTION_TYPE_PACKAGE_PROVIDER:
1868 hr = ExecutePackageProviderAction(pEngineState, pRollbackAction, pContext); 1836 hr = ExecutePackageProviderAction(pEngineState, pRollbackAction, pContext);
1869 TraceError(hr, "Failed to rollback package provider action."); 1837 IgnoreRollbackError(hr, "Failed to rollback package provider action.");
1870 hr = S_OK;
1871 break; 1838 break;
1872 1839
1873 case BURN_EXECUTE_ACTION_TYPE_PACKAGE_DEPENDENCY: 1840 case BURN_EXECUTE_ACTION_TYPE_PACKAGE_DEPENDENCY:
1874 hr = ExecuteDependencyAction(pEngineState, pRollbackAction, pContext); 1841 hr = ExecuteDependencyAction(pEngineState, pRollbackAction, pContext);
1875 TraceError(hr, "Failed to rollback dependency action."); 1842 IgnoreRollbackError(hr, "Failed to rollback dependency action.");
1876 hr = S_OK;
1877 break; 1843 break;
1878 1844
1879 case BURN_EXECUTE_ACTION_TYPE_REGISTRATION: 1845 case BURN_EXECUTE_ACTION_TYPE_REGISTRATION:
@@ -1885,6 +1851,7 @@ static HRESULT DoRollbackActions(
1885 1851
1886 case BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE: 1852 case BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE:
1887 hr = CleanPackage(pEngineState->companionConnection.hPipe, pRollbackAction->uncachePackage.pPackage); 1853 hr = CleanPackage(pEngineState->companionConnection.hPipe, pRollbackAction->uncachePackage.pPackage);
1854 IgnoreRollbackError(hr, "Failed to uncache package for rollback.");
1888 break; 1855 break;
1889 1856
1890 case BURN_EXECUTE_ACTION_TYPE_SERVICE_STOP: __fallthrough; 1857 case BURN_EXECUTE_ACTION_TYPE_SERVICE_STOP: __fallthrough;
@@ -2234,20 +2201,30 @@ LExit:
2234 2201
2235static HRESULT ExecuteMsiBeginTransaction( 2202static HRESULT ExecuteMsiBeginTransaction(
2236 __in BURN_ENGINE_STATE* pEngineState, 2203 __in BURN_ENGINE_STATE* pEngineState,
2237 __in LPCWSTR wzName, 2204 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary,
2238 __in BURN_EXECUTE_CONTEXT* /*pContext*/ 2205 __in BURN_EXECUTE_CONTEXT* /*pContext*/
2239 ) 2206 )
2240{ 2207{
2241 HRESULT hr = S_OK; 2208 HRESULT hr = S_OK;
2242 2209
2210 if (pRollbackBoundary->fActiveTransaction)
2211 {
2212 ExitFunction1(hr = E_INVALIDSTATE);
2213 }
2214
2243 if (pEngineState->plan.fPerMachine) 2215 if (pEngineState->plan.fPerMachine)
2244 { 2216 {
2245 hr = ElevationMsiBeginTransaction(pEngineState->companionConnection.hPipe, wzName); 2217 hr = ElevationMsiBeginTransaction(pEngineState->companionConnection.hPipe, pRollbackBoundary->sczId);
2246 ExitOnFailure(hr, "Failed to begin an elevated MSI transaction."); 2218 ExitOnFailure(hr, "Failed to begin an elevated MSI transaction.");
2247 } 2219 }
2248 else 2220 else
2249 { 2221 {
2250 hr = MsiEngineBeginTransaction(wzName); 2222 hr = MsiEngineBeginTransaction(pRollbackBoundary->sczId);
2223 }
2224
2225 if (SUCCEEDED(hr))
2226 {
2227 pRollbackBoundary->fActiveTransaction = TRUE;
2251 } 2228 }
2252 2229
2253LExit: 2230LExit:
@@ -2256,11 +2233,17 @@ LExit:
2256 2233
2257static HRESULT ExecuteMsiCommitTransaction( 2234static HRESULT ExecuteMsiCommitTransaction(
2258 __in BURN_ENGINE_STATE* pEngineState, 2235 __in BURN_ENGINE_STATE* pEngineState,
2236 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary,
2259 __in BURN_EXECUTE_CONTEXT* /*pContext*/ 2237 __in BURN_EXECUTE_CONTEXT* /*pContext*/
2260 ) 2238 )
2261{ 2239{
2262 HRESULT hr = S_OK; 2240 HRESULT hr = S_OK;
2263 2241
2242 if (!pRollbackBoundary->fActiveTransaction)
2243 {
2244 ExitFunction1(hr = E_INVALIDSTATE);
2245 }
2246
2264 if (pEngineState->plan.fPerMachine) 2247 if (pEngineState->plan.fPerMachine)
2265 { 2248 {
2266 hr = ElevationMsiCommitTransaction(pEngineState->companionConnection.hPipe); 2249 hr = ElevationMsiCommitTransaction(pEngineState->companionConnection.hPipe);
@@ -2271,17 +2254,28 @@ static HRESULT ExecuteMsiCommitTransaction(
2271 hr = MsiEngineCommitTransaction(); 2254 hr = MsiEngineCommitTransaction();
2272 } 2255 }
2273 2256
2257 if (SUCCEEDED(hr))
2258 {
2259 pRollbackBoundary->fActiveTransaction = FALSE;
2260 }
2261
2274LExit: 2262LExit:
2275 return hr; 2263 return hr;
2276} 2264}
2277 2265
2278static HRESULT ExecuteMsiRollbackTransaction( 2266static HRESULT ExecuteMsiRollbackTransaction(
2279 __in BURN_ENGINE_STATE* pEngineState, 2267 __in BURN_ENGINE_STATE* pEngineState,
2268 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary,
2280 __in BURN_EXECUTE_CONTEXT* /*pContext*/ 2269 __in BURN_EXECUTE_CONTEXT* /*pContext*/
2281 ) 2270 )
2282{ 2271{
2283 HRESULT hr = S_OK; 2272 HRESULT hr = S_OK;
2284 2273
2274 if (!pRollbackBoundary->fActiveTransaction)
2275 {
2276 ExitFunction();
2277 }
2278
2285 if (pEngineState->plan.fPerMachine) 2279 if (pEngineState->plan.fPerMachine)
2286 { 2280 {
2287 hr = ElevationMsiRollbackTransaction(pEngineState->companionConnection.hPipe); 2281 hr = ElevationMsiRollbackTransaction(pEngineState->companionConnection.hPipe);
@@ -2293,6 +2287,8 @@ static HRESULT ExecuteMsiRollbackTransaction(
2293 } 2287 }
2294 2288
2295LExit: 2289LExit:
2290 pRollbackBoundary->fActiveTransaction = FALSE;
2291
2296 return hr; 2292 return hr;
2297} 2293}
2298 2294
diff --git a/src/engine/msiengine.cpp b/src/engine/msiengine.cpp
index fcd8817d..b056cb7e 100644
--- a/src/engine/msiengine.cpp
+++ b/src/engine/msiengine.cpp
@@ -717,7 +717,8 @@ extern "C" HRESULT MsiEnginePlanCalculatePackage(
717 __in BURN_PACKAGE* pPackage, 717 __in BURN_PACKAGE* pPackage,
718 __in BURN_VARIABLES* pVariables, 718 __in BURN_VARIABLES* pVariables,
719 __in BURN_USER_EXPERIENCE* pUserExperience, 719 __in BURN_USER_EXPERIENCE* pUserExperience,
720 __out BOOL* pfBARequestedCache 720 __in BOOL fInsideMsiTransaction,
721 __out_opt BOOL* pfBARequestedCache
721 ) 722 )
722{ 723{
723 Trace(REPORT_STANDARD, "Planning MSI package 0x%p", pPackage); 724 Trace(REPORT_STANDARD, "Planning MSI package 0x%p", pPackage);
@@ -853,7 +854,7 @@ extern "C" HRESULT MsiEnginePlanCalculatePackage(
853 } 854 }
854 855
855 // Calculate the rollback action if there is an execute action. 856 // Calculate the rollback action if there is an execute action.
856 if (BOOTSTRAPPER_ACTION_STATE_NONE != execute) 857 if (BOOTSTRAPPER_ACTION_STATE_NONE != execute && !fInsideMsiTransaction)
857 { 858 {
858 switch (BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN != pPackage->expected ? pPackage->expected : pPackage->currentState) 859 switch (BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN != pPackage->expected ? pPackage->expected : pPackage->currentState)
859 { 860 {
diff --git a/src/engine/msiengine.h b/src/engine/msiengine.h
index 63393006..76030528 100644
--- a/src/engine/msiengine.h
+++ b/src/engine/msiengine.h
@@ -35,6 +35,7 @@ HRESULT MsiEnginePlanCalculatePackage(
35 __in BURN_PACKAGE* pPackage, 35 __in BURN_PACKAGE* pPackage,
36 __in BURN_VARIABLES* pVariables, 36 __in BURN_VARIABLES* pVariables,
37 __in BURN_USER_EXPERIENCE* pUserExperience, 37 __in BURN_USER_EXPERIENCE* pUserExperience,
38 __in BOOL fInsideMsiTransaction,
38 __out_opt BOOL* pfBARequestedCache 39 __out_opt BOOL* pfBARequestedCache
39 ); 40 );
40HRESULT MsiEnginePlanAddPackage( 41HRESULT MsiEnginePlanAddPackage(
diff --git a/src/engine/mspengine.cpp b/src/engine/mspengine.cpp
index 0854862b..e14173d1 100644
--- a/src/engine/mspengine.cpp
+++ b/src/engine/mspengine.cpp
@@ -266,6 +266,7 @@ LExit:
266extern "C" HRESULT MspEnginePlanCalculatePackage( 266extern "C" HRESULT MspEnginePlanCalculatePackage(
267 __in BURN_PACKAGE* pPackage, 267 __in BURN_PACKAGE* pPackage,
268 __in BURN_USER_EXPERIENCE* pUserExperience, 268 __in BURN_USER_EXPERIENCE* pUserExperience,
269 __in BOOL fInsideMsiTransaction,
269 __out BOOL* pfBARequestedCache 270 __out BOOL* pfBARequestedCache
270 ) 271 )
271{ 272{
@@ -329,7 +330,7 @@ extern "C" HRESULT MspEnginePlanCalculatePackage(
329 } 330 }
330 331
331 // Calculate the rollback action if there is an execute action. 332 // Calculate the rollback action if there is an execute action.
332 if (BOOTSTRAPPER_ACTION_STATE_NONE != execute) 333 if (BOOTSTRAPPER_ACTION_STATE_NONE != execute && !fInsideMsiTransaction)
333 { 334 {
334 switch (BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN != pPackage->expected ? pPackage->expected : pPackage->currentState) 335 switch (BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN != pPackage->expected ? pPackage->expected : pPackage->currentState)
335 { 336 {
@@ -442,7 +443,7 @@ extern "C" HRESULT MspEnginePlanAddPackage(
442 if (BOOTSTRAPPER_ACTION_STATE_NONE != pTargetProduct->rollback) 443 if (BOOTSTRAPPER_ACTION_STATE_NONE != pTargetProduct->rollback)
443 { 444 {
444 hr = PlanTargetProduct(display, pUserExperience, TRUE, pPlan, pLog, pVariables, pTargetProduct->rollback, pPackage, pTargetProduct, hCacheEvent); 445 hr = PlanTargetProduct(display, pUserExperience, TRUE, pPlan, pLog, pVariables, pTargetProduct->rollback, pPackage, pTargetProduct, hCacheEvent);
445 ExitOnFailure(hr, "Failed to plan rollack target product."); 446 ExitOnFailure(hr, "Failed to plan rollback target product.");
446 } 447 }
447 } 448 }
448 449
diff --git a/src/engine/mspengine.h b/src/engine/mspengine.h
index 1f0c31df..e08fe992 100644
--- a/src/engine/mspengine.h
+++ b/src/engine/mspengine.h
@@ -35,6 +35,7 @@ HRESULT MspEngineDetectPackage(
35HRESULT MspEnginePlanCalculatePackage( 35HRESULT MspEnginePlanCalculatePackage(
36 __in BURN_PACKAGE* pPackage, 36 __in BURN_PACKAGE* pPackage,
37 __in BURN_USER_EXPERIENCE* pUserExperience, 37 __in BURN_USER_EXPERIENCE* pUserExperience,
38 __in BOOL fInsideMsiTransaction,
38 __out_opt BOOL* pfBARequestedCache 39 __out_opt BOOL* pfBARequestedCache
39 ); 40 );
40HRESULT MspEnginePlanAddPackage( 41HRESULT MspEnginePlanAddPackage(
diff --git a/src/engine/package.h b/src/engine/package.h
index c5873765..f3e817eb 100644
--- a/src/engine/package.h
+++ b/src/engine/package.h
@@ -155,6 +155,7 @@ typedef struct _BURN_ROLLBACK_BOUNDARY
155 LPWSTR sczId; 155 LPWSTR sczId;
156 BOOL fVital; 156 BOOL fVital;
157 BOOL fTransaction; 157 BOOL fTransaction;
158 BOOL fActiveTransaction; // only valid during Apply.
158} BURN_ROLLBACK_BOUNDARY; 159} BURN_ROLLBACK_BOUNDARY;
159 160
160typedef struct _BURN_PATCH_TARGETCODE 161typedef struct _BURN_PATCH_TARGETCODE
diff --git a/src/engine/plan.cpp b/src/engine/plan.cpp
index e2a3437d..22b7033e 100644
--- a/src/engine/plan.cpp
+++ b/src/engine/plan.cpp
@@ -23,9 +23,12 @@ static void UninitializeCacheAction(
23static void ResetPlannedPackageState( 23static void ResetPlannedPackageState(
24 __in BURN_PACKAGE* pPackage 24 __in BURN_PACKAGE* pPackage
25 ); 25 );
26static void ResetPlannedRollbackBoundaryState(
27 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary
28 );
26static HRESULT ProcessPackage( 29static HRESULT ProcessPackage(
27 __in BOOL fBundlePerMachine, 30 __in BOOL fBundlePerMachine,
28 __in BURN_PACKAGE* pCompatiblePackageParent, 31 __in_opt BURN_PACKAGE* pCompatiblePackageParent,
29 __in BURN_USER_EXPERIENCE* pUX, 32 __in BURN_USER_EXPERIENCE* pUX,
30 __in BURN_PLAN* pPlan, 33 __in BURN_PLAN* pPlan,
31 __in BURN_PACKAGE* pPackage, 34 __in BURN_PACKAGE* pPackage,
@@ -153,6 +156,7 @@ static HRESULT CalculateExecuteActions(
153 __in BURN_USER_EXPERIENCE* pUserExperience, 156 __in BURN_USER_EXPERIENCE* pUserExperience,
154 __in BURN_PACKAGE* pPackage, 157 __in BURN_PACKAGE* pPackage,
155 __in BURN_VARIABLES* pVariables, 158 __in BURN_VARIABLES* pVariables,
159 __in_opt BURN_ROLLBACK_BOUNDARY* pActiveRollbackBoundary,
156 __out_opt BOOL* pfBARequestedCache 160 __out_opt BOOL* pfBARequestedCache
157 ); 161 );
158static BOOL NeedsCache( 162static BOOL NeedsCache(
@@ -263,6 +267,15 @@ extern "C" void PlanReset(
263 ResetPlannedPackageState(&pPackages->rgPackages[i]); 267 ResetPlannedPackageState(&pPackages->rgPackages[i]);
264 } 268 }
265 } 269 }
270
271 // Reset the planned state for each rollback boundary.
272 if (pPackages->rgRollbackBoundaries)
273 {
274 for (DWORD i = 0; i < pPackages->cRollbackBoundaries; ++i)
275 {
276 ResetPlannedRollbackBoundaryState(&pPackages->rgRollbackBoundaries[i]);
277 }
278 }
266} 279}
267 280
268extern "C" void PlanUninitializeExecuteAction( 281extern "C" void PlanUninitializeExecuteAction(
@@ -853,7 +866,7 @@ LExit:
853 866
854static HRESULT ProcessPackage( 867static HRESULT ProcessPackage(
855 __in BOOL fBundlePerMachine, 868 __in BOOL fBundlePerMachine,
856 __in BURN_PACKAGE* pCompatiblePackageParent, 869 __in_opt BURN_PACKAGE* pCompatiblePackageParent,
857 __in BURN_USER_EXPERIENCE* pUX, 870 __in BURN_USER_EXPERIENCE* pUX,
858 __in BURN_PLAN* pPlan, 871 __in BURN_PLAN* pPlan,
859 __in BURN_PACKAGE* pPackage, 872 __in BURN_PACKAGE* pPackage,
@@ -1069,7 +1082,7 @@ extern "C" HRESULT PlanCachePackage(
1069 BOOL fBARequestedCache = FALSE; 1082 BOOL fBARequestedCache = FALSE;
1070 1083
1071 // Calculate the execute actions because we need them to decide whether the package should be cached. 1084 // Calculate the execute actions because we need them to decide whether the package should be cached.
1072 hr = CalculateExecuteActions(pUserExperience, pPackage, pVariables, &fBARequestedCache); 1085 hr = CalculateExecuteActions(pUserExperience, pPackage, pVariables, pPlan->pActiveRollbackBoundary, &fBARequestedCache);
1073 ExitOnFailure(hr, "Failed to calculate execute actions for package: %ls", pPackage->sczId); 1086 ExitOnFailure(hr, "Failed to calculate execute actions for package: %ls", pPackage->sczId);
1074 1087
1075 if (fBARequestedCache || NeedsCache(pPlan, pPackage)) 1088 if (fBARequestedCache || NeedsCache(pPlan, pPackage))
@@ -1105,7 +1118,7 @@ extern "C" HRESULT PlanExecutePackage(
1105 HRESULT hr = S_OK; 1118 HRESULT hr = S_OK;
1106 BOOL fBARequestedCache = FALSE; 1119 BOOL fBARequestedCache = FALSE;
1107 1120
1108 hr = CalculateExecuteActions(pUserExperience, pPackage, pVariables, &fBARequestedCache); 1121 hr = CalculateExecuteActions(pUserExperience, pPackage, pVariables, pPlan->pActiveRollbackBoundary, &fBARequestedCache);
1109 ExitOnFailure(hr, "Failed to calculate plan actions for package: %ls", pPackage->sczId); 1122 ExitOnFailure(hr, "Failed to calculate plan actions for package: %ls", pPackage->sczId);
1110 1123
1111 // Calculate package states based on reference count and plan certain dependency actions prior to planning the package execute action. 1124 // Calculate package states based on reference count and plan certain dependency actions prior to planning the package execute action.
@@ -1631,6 +1644,7 @@ extern "C" HRESULT PlanExecuteCheckpoint(
1631 1644
1632 pAction->type = BURN_EXECUTE_ACTION_TYPE_CHECKPOINT; 1645 pAction->type = BURN_EXECUTE_ACTION_TYPE_CHECKPOINT;
1633 pAction->checkpoint.dwId = dwCheckpointId; 1646 pAction->checkpoint.dwId = dwCheckpointId;
1647 pAction->checkpoint.pActiveRollbackBoundary = pPlan->pActiveRollbackBoundary;
1634 1648
1635 // rollback checkpoint 1649 // rollback checkpoint
1636 hr = PlanAppendRollbackAction(pPlan, &pAction); 1650 hr = PlanAppendRollbackAction(pPlan, &pAction);
@@ -1638,6 +1652,7 @@ extern "C" HRESULT PlanExecuteCheckpoint(
1638 1652
1639 pAction->type = BURN_EXECUTE_ACTION_TYPE_CHECKPOINT; 1653 pAction->type = BURN_EXECUTE_ACTION_TYPE_CHECKPOINT;
1640 pAction->checkpoint.dwId = dwCheckpointId; 1654 pAction->checkpoint.dwId = dwCheckpointId;
1655 pAction->checkpoint.pActiveRollbackBoundary = pPlan->pActiveRollbackBoundary;
1641 1656
1642LExit: 1657LExit:
1643 return hr; 1658 return hr;
@@ -1783,6 +1798,9 @@ extern "C" HRESULT PlanRollbackBoundaryBegin(
1783 HRESULT hr = S_OK; 1798 HRESULT hr = S_OK;
1784 BURN_EXECUTE_ACTION* pExecuteAction = NULL; 1799 BURN_EXECUTE_ACTION* pExecuteAction = NULL;
1785 1800
1801 AssertSz(!pPlan->pActiveRollbackBoundary, "PlanRollbackBoundaryBegin called without completing previous RollbackBoundary");
1802 pPlan->pActiveRollbackBoundary = pRollbackBoundary;
1803
1786 // Add begin rollback boundary to execute plan. 1804 // Add begin rollback boundary to execute plan.
1787 hr = PlanAppendExecuteAction(pPlan, &pExecuteAction); 1805 hr = PlanAppendExecuteAction(pPlan, &pExecuteAction);
1788 ExitOnFailure(hr, "Failed to append rollback boundary begin action."); 1806 ExitOnFailure(hr, "Failed to append rollback boundary begin action.");
@@ -1797,6 +1815,19 @@ extern "C" HRESULT PlanRollbackBoundaryBegin(
1797 pExecuteAction->type = BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY; 1815 pExecuteAction->type = BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY;
1798 pExecuteAction->rollbackBoundary.pRollbackBoundary = pRollbackBoundary; 1816 pExecuteAction->rollbackBoundary.pRollbackBoundary = pRollbackBoundary;
1799 1817
1818 // Add begin MSI transaction to execute plan.
1819 if (pRollbackBoundary->fTransaction)
1820 {
1821 hr = PlanExecuteCheckpoint(pPlan);
1822 ExitOnFailure(hr, "Failed to append checkpoint before MSI transaction begin action.");
1823
1824 hr = PlanAppendExecuteAction(pPlan, &pExecuteAction);
1825 ExitOnFailure(hr, "Failed to append MSI transaction begin action.");
1826
1827 pExecuteAction->type = BURN_EXECUTE_ACTION_TYPE_BEGIN_MSI_TRANSACTION;
1828 pExecuteAction->msiTransaction.pRollbackBoundary = pRollbackBoundary;
1829 }
1830
1800LExit: 1831LExit:
1801 return hr; 1832 return hr;
1802} 1833}
@@ -1807,22 +1838,24 @@ extern "C" HRESULT PlanRollbackBoundaryComplete(
1807{ 1838{
1808 HRESULT hr = S_OK; 1839 HRESULT hr = S_OK;
1809 BURN_EXECUTE_ACTION* pExecuteAction = NULL; 1840 BURN_EXECUTE_ACTION* pExecuteAction = NULL;
1810 DWORD dwCheckpointId = 0; 1841 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = pPlan->pActiveRollbackBoundary;
1811 1842
1812 // Add checkpoints. 1843 AssertSz(pRollbackBoundary, "PlanRollbackBoundaryComplete called without an active RollbackBoundary");
1813 dwCheckpointId = GetNextCheckpointId(pPlan);
1814 1844
1815 hr = PlanAppendExecuteAction(pPlan, &pExecuteAction); 1845 if (pRollbackBoundary && pRollbackBoundary->fTransaction)
1816 ExitOnFailure(hr, "Failed to append execute action."); 1846 {
1847 // Add commit MSI transaction to execute plan.
1848 hr = PlanAppendExecuteAction(pPlan, &pExecuteAction);
1849 ExitOnFailure(hr, "Failed to append MSI transaction commit action.");
1817 1850
1818 pExecuteAction->type = BURN_EXECUTE_ACTION_TYPE_CHECKPOINT; 1851 pExecuteAction->type = BURN_EXECUTE_ACTION_TYPE_COMMIT_MSI_TRANSACTION;
1819 pExecuteAction->checkpoint.dwId = dwCheckpointId; 1852 pExecuteAction->msiTransaction.pRollbackBoundary = pRollbackBoundary;
1853 }
1820 1854
1821 hr = PlanAppendRollbackAction(pPlan, &pExecuteAction); 1855 pPlan->pActiveRollbackBoundary = NULL;
1822 ExitOnFailure(hr, "Failed to append rollback action.");
1823 1856
1824 pExecuteAction->type = BURN_EXECUTE_ACTION_TYPE_CHECKPOINT; 1857 // Add checkpoints.
1825 pExecuteAction->checkpoint.dwId = dwCheckpointId; 1858 hr = PlanExecuteCheckpoint(pPlan);
1826 1859
1827LExit: 1860LExit:
1828 return hr; 1861 return hr;
@@ -1936,6 +1969,13 @@ static void ResetPlannedPackageState(
1936 } 1969 }
1937} 1970}
1938 1971
1972static void ResetPlannedRollbackBoundaryState(
1973 __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary
1974 )
1975{
1976 pRollbackBoundary->fActiveTransaction = FALSE;
1977}
1978
1939static HRESULT GetActionDefaultRequestState( 1979static HRESULT GetActionDefaultRequestState(
1940 __in BOOTSTRAPPER_ACTION action, 1980 __in BOOTSTRAPPER_ACTION action,
1941 __in BOOL fPermanent, 1981 __in BOOL fPermanent,
@@ -2848,10 +2888,12 @@ static HRESULT CalculateExecuteActions(
2848 __in BURN_USER_EXPERIENCE* pUserExperience, 2888 __in BURN_USER_EXPERIENCE* pUserExperience,
2849 __in BURN_PACKAGE* pPackage, 2889 __in BURN_PACKAGE* pPackage,
2850 __in BURN_VARIABLES* pVariables, 2890 __in BURN_VARIABLES* pVariables,
2891 __in_opt BURN_ROLLBACK_BOUNDARY* pActiveRollbackBoundary,
2851 __out_opt BOOL* pfBARequestedCache 2892 __out_opt BOOL* pfBARequestedCache
2852 ) 2893 )
2853{ 2894{
2854 HRESULT hr = S_OK; 2895 HRESULT hr = S_OK;
2896 BOOL fInsideMsiTransaction = pActiveRollbackBoundary && pActiveRollbackBoundary->fTransaction;
2855 2897
2856 // Calculate execute actions. 2898 // Calculate execute actions.
2857 switch (pPackage->type) 2899 switch (pPackage->type)
@@ -2861,11 +2903,11 @@ static HRESULT CalculateExecuteActions(
2861 break; 2903 break;
2862 2904
2863 case BURN_PACKAGE_TYPE_MSI: 2905 case BURN_PACKAGE_TYPE_MSI:
2864 hr = MsiEnginePlanCalculatePackage(pPackage, pVariables, pUserExperience, pfBARequestedCache); 2906 hr = MsiEnginePlanCalculatePackage(pPackage, pVariables, pUserExperience, fInsideMsiTransaction, pfBARequestedCache);
2865 break; 2907 break;
2866 2908
2867 case BURN_PACKAGE_TYPE_MSP: 2909 case BURN_PACKAGE_TYPE_MSP:
2868 hr = MspEnginePlanCalculatePackage(pPackage, pUserExperience, pfBARequestedCache); 2910 hr = MspEnginePlanCalculatePackage(pPackage, pUserExperience, fInsideMsiTransaction, pfBARequestedCache);
2869 break; 2911 break;
2870 2912
2871 case BURN_PACKAGE_TYPE_MSU: 2913 case BURN_PACKAGE_TYPE_MSU:
@@ -3065,7 +3107,7 @@ static void ExecuteActionLog(
3065 switch (pAction->type) 3107 switch (pAction->type)
3066 { 3108 {
3067 case BURN_EXECUTE_ACTION_TYPE_CHECKPOINT: 3109 case BURN_EXECUTE_ACTION_TYPE_CHECKPOINT:
3068 LogStringLine(REPORT_STANDARD, "%ls action[%u]: CHECKPOINT id: %u", wzBase, iAction, pAction->checkpoint.dwId); 3110 LogStringLine(REPORT_STANDARD, "%ls action[%u]: CHECKPOINT id: %u, msi transaction id: %ls", wzBase, iAction, pAction->checkpoint.dwId, pAction->checkpoint.pActiveRollbackBoundary && pAction->checkpoint.pActiveRollbackBoundary->fTransaction ? pAction->checkpoint.pActiveRollbackBoundary->sczId : L"(none)");
3069 break; 3111 break;
3070 3112
3071 case BURN_EXECUTE_ACTION_TYPE_PACKAGE_PROVIDER: 3113 case BURN_EXECUTE_ACTION_TYPE_PACKAGE_PROVIDER:
@@ -3120,6 +3162,14 @@ static void ExecuteActionLog(
3120 LogStringLine(REPORT_STANDARD, "%ls action[%u]: COMPATIBLE_PACKAGE reference id: %ls, installed ProductCode: %ls", wzBase, iAction, pAction->compatiblePackage.pReferencePackage->sczId, pAction->compatiblePackage.sczInstalledProductCode); 3162 LogStringLine(REPORT_STANDARD, "%ls action[%u]: COMPATIBLE_PACKAGE reference id: %ls, installed ProductCode: %ls", wzBase, iAction, pAction->compatiblePackage.pReferencePackage->sczId, pAction->compatiblePackage.sczInstalledProductCode);
3121 break; 3163 break;
3122 3164
3165 case BURN_EXECUTE_ACTION_TYPE_BEGIN_MSI_TRANSACTION:
3166 LogStringLine(REPORT_STANDARD, "%ls action[%u]: BEGIN_MSI_TRANSACTION id: %ls", wzBase, iAction, pAction->msiTransaction.pRollbackBoundary->sczId);
3167 break;
3168
3169 case BURN_EXECUTE_ACTION_TYPE_COMMIT_MSI_TRANSACTION:
3170 LogStringLine(REPORT_STANDARD, "%ls action[%u]: COMMIT_MSI_TRANSACTION id: %ls", wzBase, iAction, pAction->msiTransaction.pRollbackBoundary->sczId);
3171 break;
3172
3123 default: 3173 default:
3124 AssertSz(FALSE, "Unknown execute action type."); 3174 AssertSz(FALSE, "Unknown execute action type.");
3125 break; 3175 break;
diff --git a/src/engine/plan.h b/src/engine/plan.h
index 5fddd72f..407c1d48 100644
--- a/src/engine/plan.h
+++ b/src/engine/plan.h
@@ -68,6 +68,8 @@ enum BURN_EXECUTE_ACTION_TYPE
68 BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY, 68 BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY,
69 BURN_EXECUTE_ACTION_TYPE_REGISTRATION, 69 BURN_EXECUTE_ACTION_TYPE_REGISTRATION,
70 BURN_EXECUTE_ACTION_TYPE_COMPATIBLE_PACKAGE, 70 BURN_EXECUTE_ACTION_TYPE_COMPATIBLE_PACKAGE,
71 BURN_EXECUTE_ACTION_TYPE_BEGIN_MSI_TRANSACTION,
72 BURN_EXECUTE_ACTION_TYPE_COMMIT_MSI_TRANSACTION,
71}; 73};
72 74
73enum BURN_CLEAN_ACTION_TYPE 75enum BURN_CLEAN_ACTION_TYPE
@@ -214,16 +216,19 @@ typedef struct _BURN_ORDERED_PATCHES
214 BURN_PACKAGE* pPackage; 216 BURN_PACKAGE* pPackage;
215} BURN_ORDERED_PATCHES; 217} BURN_ORDERED_PATCHES;
216 218
219typedef struct _BURN_EXECUTE_ACTION_CHECKPOINT
220{
221 DWORD dwId;
222 BURN_ROLLBACK_BOUNDARY* pActiveRollbackBoundary;
223} BURN_EXECUTE_ACTION_CHECKPOINT;
224
217typedef struct _BURN_EXECUTE_ACTION 225typedef struct _BURN_EXECUTE_ACTION
218{ 226{
219 BURN_EXECUTE_ACTION_TYPE type; 227 BURN_EXECUTE_ACTION_TYPE type;
220 BOOL fDeleted; // used to skip an action after it was planned since deleting actions out of the plan is too hard. 228 BOOL fDeleted; // used to skip an action after it was planned since deleting actions out of the plan is too hard.
221 union 229 union
222 { 230 {
223 struct 231 BURN_EXECUTE_ACTION_CHECKPOINT checkpoint;
224 {
225 DWORD dwId;
226 } checkpoint;
227 struct 232 struct
228 { 233 {
229 HANDLE hEvent; 234 HANDLE hEvent;
@@ -307,6 +312,10 @@ typedef struct _BURN_EXECUTE_ACTION
307 LPWSTR sczInstalledProductCode; 312 LPWSTR sczInstalledProductCode;
308 VERUTIL_VERSION* pInstalledVersion; 313 VERUTIL_VERSION* pInstalledVersion;
309 } compatiblePackage; 314 } compatiblePackage;
315 struct
316 {
317 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary;
318 } msiTransaction;
310 }; 319 };
311} BURN_EXECUTE_ACTION; 320} BURN_EXECUTE_ACTION;
312 321
@@ -368,7 +377,8 @@ typedef struct _BURN_PLAN
368 DWORD cPayloadProgress; 377 DWORD cPayloadProgress;
369 STRINGDICT_HANDLE shPayloadProgress; 378 STRINGDICT_HANDLE shPayloadProgress;
370 379
371 DWORD dwNextCheckpointId; 380 DWORD dwNextCheckpointId; // for plan internal use
381 BURN_ROLLBACK_BOUNDARY* pActiveRollbackBoundary; // for plan internal use
372} BURN_PLAN; 382} BURN_PLAN;
373 383
374 384
diff --git a/src/test/BurnUnitTest/PlanTest.cpp b/src/test/BurnUnitTest/PlanTest.cpp
index 86bc646b..d3b10678 100644
--- a/src/test/BurnUnitTest/PlanTest.cpp
+++ b/src/test/BurnUnitTest/PlanTest.cpp
@@ -173,7 +173,7 @@ namespace Bootstrapper
173 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"cab1QmlL013Hqv_44W64R0cvnHn_2c", TRUE, FALSE, dwPackageStart); 173 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"cab1QmlL013Hqv_44W64R0cvnHn_2c", TRUE, FALSE, dwPackageStart);
174 ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PackageA", FALSE); 174 ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PackageA", FALSE);
175 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE); 175 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE);
176 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 8); 176 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 9);
177 dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageB", 14, 2, 33753, FALSE); 177 dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageB", 14, 2, 33753, FALSE);
178 ValidateCacheAcquireContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", TRUE); 178 ValidateCacheAcquireContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", TRUE);
179 ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, dwPackageStart, 2); 179 ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, dwPackageStart, 2);
@@ -195,10 +195,6 @@ namespace Bootstrapper
195 dwIndex = 0; 195 dwIndex = 0;
196 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 196 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
197 ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageA", FALSE); 197 ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageA", FALSE);
198 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 8);
199 ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageB", FALSE);
200 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 14);
201 ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageC", FALSE);
202 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 198 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
203 199
204 Assert::Equal(106166ull, pPlan->qwEstimatedSize); 200 Assert::Equal(106166ull, pPlan->qwEstimatedSize);
@@ -220,30 +216,31 @@ namespace Bootstrapper
220 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 216 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
221 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 217 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
222 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ", TRUE, TRUE); 218 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ", TRUE, TRUE);
219 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
220 ValidateExecuteBeginMsiTransaction(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ");
223 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[15].syncpoint.hEvent); 221 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[15].syncpoint.hEvent);
224 dwExecuteCheckpointId = 9; 222 dwExecuteCheckpointId += 1; // cache checkpoints
225 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 223 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
226 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 224 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
227 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageB", BURN_DEPENDENCY_ACTION_REGISTER); 225 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageB", BURN_DEPENDENCY_ACTION_REGISTER);
228 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
229 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageB", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0); 226 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageB", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
230 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 227 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
231 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_REGISTER); 228 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_REGISTER);
232 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 229 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
233 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[23].syncpoint.hEvent); 230 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[23].syncpoint.hEvent);
234 dwExecuteCheckpointId = 15; 231 dwExecuteCheckpointId += 1; // cache checkpoints
235 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 232 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
236 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 233 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
237 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageC", BURN_DEPENDENCY_ACTION_REGISTER); 234 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageC", BURN_DEPENDENCY_ACTION_REGISTER);
238 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
239 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageC", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0); 235 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageC", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
240 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 236 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
241 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageC", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_REGISTER); 237 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageC", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_REGISTER);
242 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 238 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
239 ValidateExecuteCommitMsiTransaction(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ");
243 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 240 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
244 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[23].syncpoint.hEvent); 241 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[23].syncpoint.hEvent);
245 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL); 242 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
246 Assert::Equal(34ul, pPlan->cExecuteActions); 243 Assert::Equal(dwIndex, pPlan->cExecuteActions);
247 244
248 fRollback = TRUE; 245 fRollback = TRUE;
249 dwIndex = 0; 246 dwIndex = 0;
@@ -261,29 +258,26 @@ namespace Bootstrapper
261 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 258 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
262 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 259 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
263 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ", TRUE, TRUE); 260 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ", TRUE, TRUE);
261 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
264 ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PackageB"); 262 ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PackageB");
265 dwExecuteCheckpointId = 9; 263 dwExecuteCheckpointId += 1; // cache checkpoints
266 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 264 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
267 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageB", BURN_DEPENDENCY_ACTION_UNREGISTER); 265 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageB", BURN_DEPENDENCY_ACTION_UNREGISTER);
268 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 266 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
269 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageB", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
270 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
271 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_UNREGISTER); 267 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_UNREGISTER);
272 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 268 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
273 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 269 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
274 ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PackageC"); 270 ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PackageC");
275 dwExecuteCheckpointId = 15; 271 dwExecuteCheckpointId += 1; // cache checkpoints
276 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 272 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
277 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageC", BURN_DEPENDENCY_ACTION_UNREGISTER); 273 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageC", BURN_DEPENDENCY_ACTION_UNREGISTER);
278 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 274 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
279 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageC", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
280 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
281 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageC", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_UNREGISTER); 275 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageC", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_UNREGISTER);
282 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 276 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
283 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 277 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
284 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 278 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
285 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL); 279 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
286 Assert::Equal(33ul, pPlan->cRollbackActions); 280 Assert::Equal(dwIndex, pPlan->cRollbackActions);
287 281
288 Assert::Equal(4ul, pPlan->cExecutePackagesTotal); 282 Assert::Equal(4ul, pPlan->cExecutePackagesTotal);
289 Assert::Equal(7ul, pPlan->cOverallProgressTicksTotal); 283 Assert::Equal(7ul, pPlan->cOverallProgressTicksTotal);
@@ -331,19 +325,20 @@ namespace Bootstrapper
331 DWORD dwExecuteCheckpointId = 1; 325 DWORD dwExecuteCheckpointId = 1;
332 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ", TRUE, TRUE); 326 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ", TRUE, TRUE);
333 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 327 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
328 ValidateExecuteBeginMsiTransaction(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ");
329 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
334 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageC", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_UNREGISTER); 330 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageC", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_UNREGISTER);
335 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 331 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
336 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageC", BURN_DEPENDENCY_ACTION_UNREGISTER); 332 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageC", BURN_DEPENDENCY_ACTION_UNREGISTER);
337 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
338 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageC", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0); 333 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageC", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
339 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 334 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
340 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 335 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
341 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_UNREGISTER); 336 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_UNREGISTER);
342 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 337 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
343 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageB", BURN_DEPENDENCY_ACTION_UNREGISTER); 338 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageB", BURN_DEPENDENCY_ACTION_UNREGISTER);
344 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
345 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageB", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0); 339 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageB", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
346 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 340 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
341 ValidateExecuteCommitMsiTransaction(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ");
347 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 342 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
348 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 343 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
349 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 344 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -361,19 +356,16 @@ namespace Bootstrapper
361 dwIndex = 0; 356 dwIndex = 0;
362 dwExecuteCheckpointId = 1; 357 dwExecuteCheckpointId = 1;
363 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ", TRUE, TRUE); 358 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ", TRUE, TRUE);
359 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
364 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageC", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_REGISTER); 360 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageC", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_REGISTER);
365 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 361 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
366 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageC", BURN_DEPENDENCY_ACTION_REGISTER); 362 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageC", BURN_DEPENDENCY_ACTION_REGISTER);
367 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 363 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
368 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageC", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
369 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
370 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 364 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
371 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_REGISTER); 365 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_REGISTER);
372 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 366 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
373 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageB", BURN_DEPENDENCY_ACTION_REGISTER); 367 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageB", BURN_DEPENDENCY_ACTION_REGISTER);
374 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 368 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
375 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageB", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
376 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
377 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 369 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
378 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 370 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
379 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 371 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
@@ -818,6 +810,18 @@ namespace Bootstrapper
818 return (fRollback ? pPlan->rgRollbackActions : pPlan->rgExecuteActions) + dwIndex; 810 return (fRollback ? pPlan->rgRollbackActions : pPlan->rgExecuteActions) + dwIndex;
819 } 811 }
820 812
813 void ValidateExecuteBeginMsiTransaction(
814 __in BURN_PLAN* pPlan,
815 __in BOOL fRollback,
816 __in DWORD dwIndex,
817 __in LPCWSTR wzRollbackBoundaryId
818 )
819 {
820 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
821 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_BEGIN_MSI_TRANSACTION, pAction->type);
822 NativeAssert::StringEqual(wzRollbackBoundaryId, pAction->msiTransaction.pRollbackBoundary->sczId);
823 }
824
821 void ValidateExecuteCheckpoint( 825 void ValidateExecuteCheckpoint(
822 __in BURN_PLAN* pPlan, 826 __in BURN_PLAN* pPlan,
823 __in BOOL fRollback, 827 __in BOOL fRollback,
@@ -830,6 +834,18 @@ namespace Bootstrapper
830 Assert::Equal(dwId, pAction->checkpoint.dwId); 834 Assert::Equal(dwId, pAction->checkpoint.dwId);
831 } 835 }
832 836
837 void ValidateExecuteCommitMsiTransaction(
838 __in BURN_PLAN* pPlan,
839 __in BOOL fRollback,
840 __in DWORD dwIndex,
841 __in LPCWSTR wzRollbackBoundaryId
842 )
843 {
844 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
845 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_COMMIT_MSI_TRANSACTION, pAction->type);
846 NativeAssert::StringEqual(wzRollbackBoundaryId, pAction->msiTransaction.pRollbackBoundary->sczId);
847 }
848
833 void ValidateExecuteExePackage( 849 void ValidateExecuteExePackage(
834 __in BURN_PLAN* pPlan, 850 __in BURN_PLAN* pPlan,
835 __in BOOL fRollback, 851 __in BOOL fRollback,