aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2020-11-16 19:05:29 -0600
committerSean Hall <r.sean.hall@gmail.com>2020-11-17 19:06:00 -0600
commit7d45238e97c35ccea1f77be9065b9a3ed9213bfb (patch)
tree92a482536f944347ab9be9f1321c400d900e1cc2
parent7a942746bc535d319bdfa7f17025347ac6913ba2 (diff)
downloadwix-7d45238e97c35ccea1f77be9065b9a3ed9213bfb.tar.gz
wix-7d45238e97c35ccea1f77be9065b9a3ed9213bfb.tar.bz2
wix-7d45238e97c35ccea1f77be9065b9a3ed9213bfb.zip
Add logging and BA messages around MSI transactions.
-rw-r--r--src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h77
-rw-r--r--src/engine/apply.cpp47
-rw-r--r--src/engine/elevation.cpp70
-rw-r--r--src/engine/elevation.h6
-rw-r--r--src/engine/engine.mc42
-rw-r--r--src/engine/msiengine.cpp20
-rw-r--r--src/engine/msiengine.h8
-rw-r--r--src/engine/userexperience.cpp142
-rw-r--r--src/engine/userexperience.h33
9 files changed, 414 insertions, 31 deletions
diff --git a/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h b/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
index 77d5b2c6..cfbb0571 100644
--- a/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
+++ b/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
@@ -135,6 +135,12 @@ enum BOOTSTRAPPER_APPLICATION_MESSAGE
135 BOOTSTRAPPER_APPLICATION_MESSAGE_ONLAUNCHAPPROVEDEXEBEGIN, 135 BOOTSTRAPPER_APPLICATION_MESSAGE_ONLAUNCHAPPROVEDEXEBEGIN,
136 BOOTSTRAPPER_APPLICATION_MESSAGE_ONLAUNCHAPPROVEDEXECOMPLETE, 136 BOOTSTRAPPER_APPLICATION_MESSAGE_ONLAUNCHAPPROVEDEXECOMPLETE,
137 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANMSIPACKAGE, 137 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANMSIPACKAGE,
138 BOOTSTRAPPER_APPLICATION_MESSAGE_ONBEGINMSITRANSACTIONBEGIN,
139 BOOTSTRAPPER_APPLICATION_MESSAGE_ONBEGINMSITRANSACTIONCOMPLETE,
140 BOOTSTRAPPER_APPLICATION_MESSAGE_ONCOMMITMSITRANSACTIONBEGIN,
141 BOOTSTRAPPER_APPLICATION_MESSAGE_ONCOMMITMSITRANSACTIONCOMPLETE,
142 BOOTSTRAPPER_APPLICATION_MESSAGE_ONROLLBACKMSITRANSACTIONBEGIN,
143 BOOTSTRAPPER_APPLICATION_MESSAGE_ONROLLBACKMSITRANSACTIONCOMPLETE,
138}; 144};
139 145
140enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION 146enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION
@@ -274,6 +280,30 @@ struct BA_ONAPPLYCOMPLETE_RESULTS
274 BOOTSTRAPPER_APPLYCOMPLETE_ACTION action; 280 BOOTSTRAPPER_APPLYCOMPLETE_ACTION action;
275}; 281};
276 282
283struct BA_ONBEGINMSITRANSACTIONBEGIN_ARGS
284{
285 DWORD cbSize;
286 LPCWSTR wzTransactionId;
287};
288
289struct BA_ONBEGINMSITRANSACTIONBEGIN_RESULTS
290{
291 DWORD cbSize;
292 BOOL fCancel;
293};
294
295struct BA_ONBEGINMSITRANSACTIONCOMPLETE_ARGS
296{
297 DWORD cbSize;
298 LPCWSTR wzTransactionId;
299 HRESULT hrStatus;
300};
301
302struct BA_ONBEGINMSITRANSACTIONCOMPLETE_RESULTS
303{
304 DWORD cbSize;
305};
306
277struct BA_ONCACHEACQUIREBEGIN_ARGS 307struct BA_ONCACHEACQUIREBEGIN_ARGS
278{ 308{
279 DWORD cbSize; 309 DWORD cbSize;
@@ -398,6 +428,30 @@ struct BA_ONCACHEVERIFYCOMPLETE_RESULTS
398 BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION action; 428 BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION action;
399}; 429};
400 430
431struct BA_ONCOMMITMSITRANSACTIONBEGIN_ARGS
432{
433 DWORD cbSize;
434 LPCWSTR wzTransactionId;
435};
436
437struct BA_ONCOMMITMSITRANSACTIONBEGIN_RESULTS
438{
439 DWORD cbSize;
440 BOOL fCancel;
441};
442
443struct BA_ONCOMMITMSITRANSACTIONCOMPLETE_ARGS
444{
445 DWORD cbSize;
446 LPCWSTR wzTransactionId;
447 HRESULT hrStatus;
448};
449
450struct BA_ONCOMMITMSITRANSACTIONCOMPLETE_RESULTS
451{
452 DWORD cbSize;
453};
454
401struct BA_ONDETECTBEGIN_ARGS 455struct BA_ONDETECTBEGIN_ARGS
402{ 456{
403 DWORD cbSize; 457 DWORD cbSize;
@@ -963,6 +1017,29 @@ struct BA_ONRESOLVESOURCE_RESULTS
963 BOOL fCancel; 1017 BOOL fCancel;
964}; 1018};
965 1019
1020struct BA_ONROLLBACKMSITRANSACTIONBEGIN_ARGS
1021{
1022 DWORD cbSize;
1023 LPCWSTR wzTransactionId;
1024};
1025
1026struct BA_ONROLLBACKMSITRANSACTIONBEGIN_RESULTS
1027{
1028 DWORD cbSize;
1029};
1030
1031struct BA_ONROLLBACKMSITRANSACTIONCOMPLETE_ARGS
1032{
1033 DWORD cbSize;
1034 LPCWSTR wzTransactionId;
1035 HRESULT hrStatus;
1036};
1037
1038struct BA_ONROLLBACKMSITRANSACTIONCOMPLETE_RESULTS
1039{
1040 DWORD cbSize;
1041};
1042
966struct BA_ONSHUTDOWN_ARGS 1043struct BA_ONSHUTDOWN_ARGS
967{ 1044{
968 DWORD cbSize; 1045 DWORD cbSize;
diff --git a/src/engine/apply.cpp b/src/engine/apply.cpp
index 53422807..833d750c 100644
--- a/src/engine/apply.cpp
+++ b/src/engine/apply.cpp
@@ -783,7 +783,7 @@ extern "C" HRESULT ApplyExecute(
783 if (pCheckpoint && pCheckpoint->pActiveRollbackBoundary && pCheckpoint->pActiveRollbackBoundary->fActiveTransaction) 783 if (pCheckpoint && pCheckpoint->pActiveRollbackBoundary && pCheckpoint->pActiveRollbackBoundary->fActiveTransaction)
784 { 784 {
785 hr = E_INVALIDSTATE; 785 hr = E_INVALIDSTATE;
786 LogString(REPORT_ERROR, "Ilegal state: Reboot requested within an MSI transaction. Transaction will rollback."); 786 LogId(REPORT_ERROR, MSG_RESTART_REQUEST_DURING_MSI_TRANSACTION, pCheckpoint->pActiveRollbackBoundary->sczId);
787 } 787 }
788 else 788 else
789 { 789 {
@@ -796,6 +796,8 @@ extern "C" HRESULT ApplyExecute(
796 // If rollback is disabled, keep what we have and always end execution here. 796 // If rollback is disabled, keep what we have and always end execution here.
797 if (pEngineState->plan.fDisableRollback) 797 if (pEngineState->plan.fDisableRollback)
798 { 798 {
799 LogId(REPORT_WARNING, MSG_PLAN_ROLLBACK_DISABLED);
800
799 if (pCheckpoint && pCheckpoint->pActiveRollbackBoundary && pCheckpoint->pActiveRollbackBoundary->fActiveTransaction) 801 if (pCheckpoint && pCheckpoint->pActiveRollbackBoundary && pCheckpoint->pActiveRollbackBoundary->fActiveTransaction)
800 { 802 {
801 hrRollback = ExecuteMsiCommitTransaction(pEngineState, pCheckpoint->pActiveRollbackBoundary, &context); 803 hrRollback = ExecuteMsiCommitTransaction(pEngineState, pCheckpoint->pActiveRollbackBoundary, &context);
@@ -1732,13 +1734,11 @@ static HRESULT DoExecuteAction(
1732 break; 1734 break;
1733 1735
1734 case BURN_EXECUTE_ACTION_TYPE_BEGIN_MSI_TRANSACTION: 1736 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 hr = ExecuteMsiBeginTransaction(pEngineState, pExecuteAction->msiTransaction.pRollbackBoundary, pContext);
1737 ExitOnFailure(hr, "Failed to execute begin MSI transaction action."); 1738 ExitOnFailure(hr, "Failed to execute begin MSI transaction action.");
1738 break; 1739 break;
1739 1740
1740 case BURN_EXECUTE_ACTION_TYPE_COMMIT_MSI_TRANSACTION: 1741 case BURN_EXECUTE_ACTION_TYPE_COMMIT_MSI_TRANSACTION:
1741 LogString(REPORT_STANDARD, "Committing MSI transaction\n");
1742 hr = ExecuteMsiCommitTransaction(pEngineState, pExecuteAction->msiTransaction.pRollbackBoundary, pContext); 1742 hr = ExecuteMsiCommitTransaction(pEngineState, pExecuteAction->msiTransaction.pRollbackBoundary, pContext);
1743 ExitOnFailure(hr, "Failed to execute commit MSI transaction action."); 1743 ExitOnFailure(hr, "Failed to execute commit MSI transaction action.");
1744 break; 1744 break;
@@ -1899,7 +1899,7 @@ static HRESULT ExecuteExePackage(
1899 fBeginCalled = TRUE; 1899 fBeginCalled = TRUE;
1900 1900
1901 // Send package execute begin to BA. 1901 // Send package execute begin to BA.
1902 hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pExecuteAction->exePackage.pPackage->sczId, !fRollback, pExecuteAction->exePackage.action, INSTALLUILEVEL_NOCHANGE, false); 1902 hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pExecuteAction->exePackage.pPackage->sczId, !fRollback, pExecuteAction->exePackage.action, INSTALLUILEVEL_NOCHANGE, FALSE);
1903 ExitOnRootFailure(hr, "BA aborted execute EXE package begin."); 1903 ExitOnRootFailure(hr, "BA aborted execute EXE package begin.");
1904 1904
1905 message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; 1905 message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS;
@@ -2090,7 +2090,7 @@ static HRESULT ExecuteMsuPackage(
2090 fBeginCalled = TRUE; 2090 fBeginCalled = TRUE;
2091 2091
2092 // Send package execute begin to BA. 2092 // Send package execute begin to BA.
2093 hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pExecuteAction->msuPackage.pPackage->sczId, !fRollback, pExecuteAction->msuPackage.action, INSTALLUILEVEL_NOCHANGE, false); 2093 hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pExecuteAction->msuPackage.pPackage->sczId, !fRollback, pExecuteAction->msuPackage.action, INSTALLUILEVEL_NOCHANGE, FALSE);
2094 ExitOnRootFailure(hr, "BA aborted execute MSU package begin."); 2094 ExitOnRootFailure(hr, "BA aborted execute MSU package begin.");
2095 2095
2096 message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; 2096 message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS;
@@ -2206,12 +2206,17 @@ static HRESULT ExecuteMsiBeginTransaction(
2206 ) 2206 )
2207{ 2207{
2208 HRESULT hr = S_OK; 2208 HRESULT hr = S_OK;
2209 BOOL fBeginCalled = FALSE;
2209 2210
2210 if (pRollbackBoundary->fActiveTransaction) 2211 if (pRollbackBoundary->fActiveTransaction)
2211 { 2212 {
2212 ExitFunction1(hr = E_INVALIDSTATE); 2213 ExitFunction1(hr = E_INVALIDSTATE);
2213 } 2214 }
2214 2215
2216 fBeginCalled = TRUE;
2217 hr = UserExperienceOnBeginMsiTransactionBegin(&pEngineState->userExperience, pRollbackBoundary->sczId);
2218 ExitOnRootFailure(hr, "BA aborted execute begin MSI transaction.");
2219
2215 if (pEngineState->plan.fPerMachine) 2220 if (pEngineState->plan.fPerMachine)
2216 { 2221 {
2217 hr = ElevationMsiBeginTransaction(pEngineState->companionConnection.hPipe, pRollbackBoundary->sczId); 2222 hr = ElevationMsiBeginTransaction(pEngineState->companionConnection.hPipe, pRollbackBoundary->sczId);
@@ -2228,6 +2233,11 @@ static HRESULT ExecuteMsiBeginTransaction(
2228 } 2233 }
2229 2234
2230LExit: 2235LExit:
2236 if (fBeginCalled)
2237 {
2238 UserExperienceOnBeginMsiTransactionComplete(&pEngineState->userExperience, pRollbackBoundary->sczId, hr);
2239 }
2240
2231 return hr; 2241 return hr;
2232} 2242}
2233 2243
@@ -2238,20 +2248,25 @@ static HRESULT ExecuteMsiCommitTransaction(
2238 ) 2248 )
2239{ 2249{
2240 HRESULT hr = S_OK; 2250 HRESULT hr = S_OK;
2251 BOOL fBeginCalled = FALSE;
2241 2252
2242 if (!pRollbackBoundary->fActiveTransaction) 2253 if (!pRollbackBoundary->fActiveTransaction)
2243 { 2254 {
2244 ExitFunction1(hr = E_INVALIDSTATE); 2255 ExitFunction1(hr = E_INVALIDSTATE);
2245 } 2256 }
2246 2257
2258 fBeginCalled = TRUE;
2259 hr = UserExperienceOnCommitMsiTransactionBegin(&pEngineState->userExperience, pRollbackBoundary->sczId);
2260 ExitOnRootFailure(hr, "BA aborted execute commit MSI transaction.");
2261
2247 if (pEngineState->plan.fPerMachine) 2262 if (pEngineState->plan.fPerMachine)
2248 { 2263 {
2249 hr = ElevationMsiCommitTransaction(pEngineState->companionConnection.hPipe); 2264 hr = ElevationMsiCommitTransaction(pEngineState->companionConnection.hPipe, pRollbackBoundary->sczId);
2250 ExitOnFailure(hr, "Failed to commit an elevated MSI transaction."); 2265 ExitOnFailure(hr, "Failed to commit an elevated MSI transaction.");
2251 } 2266 }
2252 else 2267 else
2253 { 2268 {
2254 hr = MsiEngineCommitTransaction(); 2269 hr = MsiEngineCommitTransaction(pRollbackBoundary->sczId);
2255 } 2270 }
2256 2271
2257 if (SUCCEEDED(hr)) 2272 if (SUCCEEDED(hr))
@@ -2260,6 +2275,11 @@ static HRESULT ExecuteMsiCommitTransaction(
2260 } 2275 }
2261 2276
2262LExit: 2277LExit:
2278 if (fBeginCalled)
2279 {
2280 UserExperienceOnCommitMsiTransactionComplete(&pEngineState->userExperience, pRollbackBoundary->sczId, hr);
2281 }
2282
2263 return hr; 2283 return hr;
2264} 2284}
2265 2285
@@ -2270,25 +2290,34 @@ static HRESULT ExecuteMsiRollbackTransaction(
2270 ) 2290 )
2271{ 2291{
2272 HRESULT hr = S_OK; 2292 HRESULT hr = S_OK;
2293 BOOL fBeginCalled = FALSE;
2273 2294
2274 if (!pRollbackBoundary->fActiveTransaction) 2295 if (!pRollbackBoundary->fActiveTransaction)
2275 { 2296 {
2276 ExitFunction(); 2297 ExitFunction();
2277 } 2298 }
2278 2299
2300 fBeginCalled = TRUE;
2301 UserExperienceOnRollbackMsiTransactionBegin(&pEngineState->userExperience, pRollbackBoundary->sczId);
2302
2279 if (pEngineState->plan.fPerMachine) 2303 if (pEngineState->plan.fPerMachine)
2280 { 2304 {
2281 hr = ElevationMsiRollbackTransaction(pEngineState->companionConnection.hPipe); 2305 hr = ElevationMsiRollbackTransaction(pEngineState->companionConnection.hPipe, pRollbackBoundary->sczId);
2282 ExitOnFailure(hr, "Failed to rollback an elevated MSI transaction."); 2306 ExitOnFailure(hr, "Failed to rollback an elevated MSI transaction.");
2283 } 2307 }
2284 else 2308 else
2285 { 2309 {
2286 hr = MsiEngineRollbackTransaction(); 2310 hr = MsiEngineRollbackTransaction(pRollbackBoundary->sczId);
2287 } 2311 }
2288 2312
2289LExit: 2313LExit:
2290 pRollbackBoundary->fActiveTransaction = FALSE; 2314 pRollbackBoundary->fActiveTransaction = FALSE;
2291 2315
2316 if (fBeginCalled)
2317 {
2318 UserExperienceOnRollbackMsiTransactionComplete(&pEngineState->userExperience, pRollbackBoundary->sczId, hr);
2319 }
2320
2292 return hr; 2321 return hr;
2293} 2322}
2294 2323
diff --git a/src/engine/elevation.cpp b/src/engine/elevation.cpp
index 81a48316..1d0e1f1d 100644
--- a/src/engine/elevation.cpp
+++ b/src/engine/elevation.cpp
@@ -237,8 +237,14 @@ static HRESULT OnMsiBeginTransaction(
237 __in BYTE* pbData, 237 __in BYTE* pbData,
238 __in DWORD cbData 238 __in DWORD cbData
239 ); 239 );
240static HRESULT OnMsiCommitTransaction(); 240static HRESULT OnMsiCommitTransaction(
241static HRESULT OnMsiRollbackTransaction(); 241 __in BYTE* pbData,
242 __in DWORD cbData
243 );
244static HRESULT OnMsiRollbackTransaction(
245 __in BYTE* pbData,
246 __in DWORD cbData
247 );
242 248
243 249
244 250
@@ -730,7 +736,7 @@ extern "C" HRESULT ElevationMsiBeginTransaction(
730 hr = BuffWriteString(&pbData, &cbData, wzName); 736 hr = BuffWriteString(&pbData, &cbData, wzName);
731 ExitOnFailure(hr, "Failed to write transaction name to message buffer."); 737 ExitOnFailure(hr, "Failed to write transaction name to message buffer.");
732 738
733 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_BEGIN_MSI_TRANSACTION, NULL, 0, NULL, NULL, &dwResult); 739 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_BEGIN_MSI_TRANSACTION, pbData, cbData, NULL, NULL, &dwResult);
734 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_BEGIN_MSI_TRANSACTION message to per-machine process."); 740 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_BEGIN_MSI_TRANSACTION message to per-machine process.");
735 741
736 hr = static_cast<HRESULT>(dwResult); 742 hr = static_cast<HRESULT>(dwResult);
@@ -742,13 +748,20 @@ LExit:
742} 748}
743 749
744extern "C" HRESULT ElevationMsiCommitTransaction( 750extern "C" HRESULT ElevationMsiCommitTransaction(
745 __in HANDLE hPipe 751 __in HANDLE hPipe,
752 __in LPCWSTR wzName
746 ) 753 )
747{ 754{
748 HRESULT hr = S_OK; 755 HRESULT hr = S_OK;
756 BYTE* pbData = NULL;
757 SIZE_T cbData = 0;
749 DWORD dwResult = ERROR_SUCCESS; 758 DWORD dwResult = ERROR_SUCCESS;
750 759
751 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_COMMIT_MSI_TRANSACTION, NULL, 0, NULL, NULL, &dwResult); 760 // serialize message data
761 hr = BuffWriteString(&pbData, &cbData, wzName);
762 ExitOnFailure(hr, "Failed to write transaction name to message buffer.");
763
764 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_COMMIT_MSI_TRANSACTION, pbData, cbData, NULL, NULL, &dwResult);
752 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_COMMIT_MSI_TRANSACTION message to per-machine process."); 765 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_COMMIT_MSI_TRANSACTION message to per-machine process.");
753 766
754 hr = static_cast<HRESULT>(dwResult); 767 hr = static_cast<HRESULT>(dwResult);
@@ -758,13 +771,20 @@ LExit:
758} 771}
759 772
760extern "C" HRESULT ElevationMsiRollbackTransaction( 773extern "C" HRESULT ElevationMsiRollbackTransaction(
761 __in HANDLE hPipe 774 __in HANDLE hPipe,
775 __in LPCWSTR wzName
762 ) 776 )
763{ 777{
764 HRESULT hr = S_OK; 778 HRESULT hr = S_OK;
779 BYTE* pbData = NULL;
780 SIZE_T cbData = 0;
765 DWORD dwResult = ERROR_SUCCESS; 781 DWORD dwResult = ERROR_SUCCESS;
766 782
767 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_ROLLBACK_MSI_TRANSACTION, NULL, 0, NULL, NULL, &dwResult); 783 // serialize message data
784 hr = BuffWriteString(&pbData, &cbData, wzName);
785 ExitOnFailure(hr, "Failed to write transaction name to message buffer.");
786
787 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_ROLLBACK_MSI_TRANSACTION, pbData, cbData, NULL, NULL, &dwResult);
768 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_ROLLBACK_MSI_TRANSACTION message to per-machine process."); 788 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_ROLLBACK_MSI_TRANSACTION message to per-machine process.");
769 789
770 hr = static_cast<HRESULT>(dwResult); 790 hr = static_cast<HRESULT>(dwResult);
@@ -1534,11 +1554,11 @@ static HRESULT ProcessElevatedChildMessage(
1534 break; 1554 break;
1535 1555
1536 case BURN_ELEVATION_MESSAGE_TYPE_COMMIT_MSI_TRANSACTION: 1556 case BURN_ELEVATION_MESSAGE_TYPE_COMMIT_MSI_TRANSACTION:
1537 hrResult = OnMsiCommitTransaction(); 1557 hrResult = OnMsiCommitTransaction((BYTE*)pMsg->pvData, pMsg->cbData);
1538 break; 1558 break;
1539 1559
1540 case BURN_ELEVATION_MESSAGE_TYPE_ROLLBACK_MSI_TRANSACTION: 1560 case BURN_ELEVATION_MESSAGE_TYPE_ROLLBACK_MSI_TRANSACTION:
1541 hrResult = OnMsiRollbackTransaction(); 1561 hrResult = OnMsiRollbackTransaction((BYTE*)pMsg->pvData, pMsg->cbData);
1542 break; 1562 break;
1543 1563
1544 case BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE: 1564 case BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE:
@@ -2806,20 +2826,44 @@ LExit:
2806 return hr; 2826 return hr;
2807} 2827}
2808 2828
2809static HRESULT OnMsiCommitTransaction() 2829static HRESULT OnMsiCommitTransaction(
2830 __in BYTE* pbData,
2831 __in DWORD cbData
2832 )
2810{ 2833{
2811 HRESULT hr = S_OK; 2834 HRESULT hr = S_OK;
2835 SIZE_T iData = 0;
2836 LPWSTR sczName = NULL;
2837
2838 // Deserialize message data.
2839 hr = BuffReadString(pbData, cbData, &iData, &sczName);
2840 ExitOnFailure(hr, "Failed to read transaction name.");
2812 2841
2813 hr = MsiEngineCommitTransaction(); 2842 hr = MsiEngineCommitTransaction(sczName);
2843
2844LExit:
2845 ReleaseStr(sczName);
2814 2846
2815 return hr; 2847 return hr;
2816} 2848}
2817 2849
2818static HRESULT OnMsiRollbackTransaction() 2850static HRESULT OnMsiRollbackTransaction(
2851 __in BYTE* pbData,
2852 __in DWORD cbData
2853 )
2819{ 2854{
2820 HRESULT hr = S_OK; 2855 HRESULT hr = S_OK;
2856 SIZE_T iData = 0;
2857 LPWSTR sczName = NULL;
2858
2859 // Deserialize message data.
2860 hr = BuffReadString(pbData, cbData, &iData, &sczName);
2861 ExitOnFailure(hr, "Failed to read transaction name.");
2821 2862
2822 hr = MsiEngineRollbackTransaction(); 2863 hr = MsiEngineRollbackTransaction(sczName);
2864
2865LExit:
2866 ReleaseStr(sczName);
2823 2867
2824 return hr; 2868 return hr;
2825} 2869}
diff --git a/src/engine/elevation.h b/src/engine/elevation.h
index 975981da..96111ae2 100644
--- a/src/engine/elevation.h
+++ b/src/engine/elevation.h
@@ -162,10 +162,12 @@ HRESULT ElevationMsiBeginTransaction(
162 __in LPCWSTR wzName 162 __in LPCWSTR wzName
163 ); 163 );
164HRESULT ElevationMsiCommitTransaction( 164HRESULT ElevationMsiCommitTransaction(
165 __in HANDLE hPipe 165 __in HANDLE hPipe,
166 __in LPCWSTR wzName
166 ); 167 );
167HRESULT ElevationMsiRollbackTransaction( 168HRESULT ElevationMsiRollbackTransaction(
168 __in HANDLE hPipe 169 __in HANDLE hPipe,
170 __in LPCWSTR wzName
169 ); 171 );
170 172
171#ifdef __cplusplus 173#ifdef __cplusplus
diff --git a/src/engine/engine.mc b/src/engine/engine.mc
index 4bb517f8..b36a9527 100644
--- a/src/engine/engine.mc
+++ b/src/engine/engine.mc
@@ -843,6 +843,48 @@ Language=English
843Ignoring application request to cancel from %1!ls! during rollback. 843Ignoring application request to cancel from %1!ls! during rollback.
844. 844.
845 845
846MessageId=382
847Severity=Warning
848SymbolicName=MSG_PLAN_ROLLBACK_DISABLED
849Language=English
850Rollback is disabled for this bundle.
851.
852
853MessageId=383
854Severity=Error
855SymbolicName=MSG_MSI_TRANSACTIONS_DISABLED
856Language=English
857Windows Installer rollback is disabled on this computer. It must be enabled for this bundle to proceed.
858.
859
860MessageId=384
861Severity=Success
862SymbolicName=MSG_MSI_TRANSACTION_BEGIN
863Language=English
864Starting a new MSI transaction, id: %1!ls!
865.
866
867MessageId=385
868Severity=Success
869SymbolicName=MSG_MSI_TRANSACTION_COMMIT
870Language=English
871Committing MSI transaction, id: %1!ls!
872.
873
874MessageId=386
875Severity=Warning
876SymbolicName=MSG_MSI_TRANSACTION_ROLLBACK
877Language=English
878Rolling back MSI transaction, id: %1!ls!
879.
880
881MessageId=387
882Severity=Error
883SymbolicName=MSG_RESTART_REQUEST_DURING_MSI_TRANSACTION
884Language=English
885Illegal state: Reboot requested within an MSI transaction, id: %1!ls!
886.
887
846MessageId=399 888MessageId=399
847Severity=Success 889Severity=Success
848SymbolicName=MSG_APPLY_COMPLETE 890SymbolicName=MSG_APPLY_COMPLETE
diff --git a/src/engine/msiengine.cpp b/src/engine/msiengine.cpp
index b056cb7e..c298e219 100644
--- a/src/engine/msiengine.cpp
+++ b/src/engine/msiengine.cpp
@@ -1147,18 +1147,30 @@ extern "C" HRESULT MsiEngineBeginTransaction(
1147 MSIHANDLE hTransactionHandle = NULL; 1147 MSIHANDLE hTransactionHandle = NULL;
1148 HANDLE hChangeOfOwnerEvent = NULL; 1148 HANDLE hChangeOfOwnerEvent = NULL;
1149 1149
1150 LogId(REPORT_STANDARD, MSG_MSI_TRANSACTION_BEGIN, wzName);
1151
1150 uResult = ::MsiBeginTransaction(wzName, 0, &hTransactionHandle, &hChangeOfOwnerEvent); 1152 uResult = ::MsiBeginTransaction(wzName, 0, &hTransactionHandle, &hChangeOfOwnerEvent);
1153
1154 if (ERROR_ROLLBACK_DISABLED == uResult)
1155 {
1156 LogId(REPORT_ERROR, MSG_MSI_TRANSACTIONS_DISABLED);
1157 }
1158
1151 ExitOnWin32Error(uResult, hr, "Failed to begin an MSI transaction"); 1159 ExitOnWin32Error(uResult, hr, "Failed to begin an MSI transaction");
1152 1160
1153LExit: 1161LExit:
1154 return hr; 1162 return hr;
1155} 1163}
1156 1164
1157extern "C" HRESULT MsiEngineCommitTransaction() 1165extern "C" HRESULT MsiEngineCommitTransaction(
1166 __in LPCWSTR wzName
1167 )
1158{ 1168{
1159 HRESULT hr = S_OK; 1169 HRESULT hr = S_OK;
1160 UINT uResult = ERROR_SUCCESS; 1170 UINT uResult = ERROR_SUCCESS;
1161 1171
1172 LogId(REPORT_STANDARD, MSG_MSI_TRANSACTION_COMMIT, wzName);
1173
1162 uResult = ::MsiEndTransaction(MSITRANSACTIONSTATE_COMMIT); 1174 uResult = ::MsiEndTransaction(MSITRANSACTIONSTATE_COMMIT);
1163 ExitOnWin32Error(uResult, hr, "Failed to commit the MSI transaction"); 1175 ExitOnWin32Error(uResult, hr, "Failed to commit the MSI transaction");
1164 1176
@@ -1167,11 +1179,15 @@ LExit:
1167 return hr; 1179 return hr;
1168} 1180}
1169 1181
1170extern "C" HRESULT MsiEngineRollbackTransaction() 1182extern "C" HRESULT MsiEngineRollbackTransaction(
1183 __in LPCWSTR wzName
1184 )
1171{ 1185{
1172 HRESULT hr = S_OK; 1186 HRESULT hr = S_OK;
1173 UINT uResult = ERROR_SUCCESS; 1187 UINT uResult = ERROR_SUCCESS;
1174 1188
1189 LogId(REPORT_WARNING, MSG_MSI_TRANSACTION_ROLLBACK, wzName);
1190
1175 uResult = ::MsiEndTransaction(MSITRANSACTIONSTATE_ROLLBACK); 1191 uResult = ::MsiEndTransaction(MSITRANSACTIONSTATE_ROLLBACK);
1176 ExitOnWin32Error(uResult, hr, "Failed to rollback the MSI transaction"); 1192 ExitOnWin32Error(uResult, hr, "Failed to rollback the MSI transaction");
1177 1193
diff --git a/src/engine/msiengine.h b/src/engine/msiengine.h
index 76030528..c7cc3bef 100644
--- a/src/engine/msiengine.h
+++ b/src/engine/msiengine.h
@@ -56,8 +56,12 @@ HRESULT MsiEngineAddCompatiblePackage(
56HRESULT MsiEngineBeginTransaction( 56HRESULT MsiEngineBeginTransaction(
57 __in LPCWSTR wzName 57 __in LPCWSTR wzName
58 ); 58 );
59HRESULT MsiEngineCommitTransaction(); 59HRESULT MsiEngineCommitTransaction(
60HRESULT MsiEngineRollbackTransaction(); 60 __in LPCWSTR wzName
61 );
62HRESULT MsiEngineRollbackTransaction(
63 __in LPCWSTR wzName
64 );
61HRESULT MsiEngineExecutePackage( 65HRESULT MsiEngineExecutePackage(
62 __in_opt HWND hwndParent, 66 __in_opt HWND hwndParent,
63 __in BURN_EXECUTE_ACTION* pExecuteAction, 67 __in BURN_EXECUTE_ACTION* pExecuteAction,
diff --git a/src/engine/userexperience.cpp b/src/engine/userexperience.cpp
index 5f18cdbc..08451f93 100644
--- a/src/engine/userexperience.cpp
+++ b/src/engine/userexperience.cpp
@@ -348,6 +348,55 @@ LExit:
348 return hr; 348 return hr;
349} 349}
350 350
351EXTERN_C BAAPI UserExperienceOnBeginMsiTransactionBegin(
352 __in BURN_USER_EXPERIENCE* pUserExperience,
353 __in LPCWSTR wzTransactionId
354 )
355{
356 HRESULT hr = S_OK;
357 BA_ONBEGINMSITRANSACTIONBEGIN_ARGS args = { };
358 BA_ONBEGINMSITRANSACTIONBEGIN_RESULTS results = { };
359
360 args.cbSize = sizeof(args);
361 args.wzTransactionId = wzTransactionId;
362
363 results.cbSize = sizeof(results);
364
365 hr = pUserExperience->pfnBAProc(BOOTSTRAPPER_APPLICATION_MESSAGE_ONBEGINMSITRANSACTIONBEGIN, &args, &results, pUserExperience->pvBAProcContext);
366 ExitOnFailure(hr, "BA OnBeginMsiTransactionBegin failed.");
367
368 if (results.fCancel)
369 {
370 hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
371 }
372
373LExit:
374 return hr;
375}
376
377EXTERN_C BAAPI UserExperienceOnBeginMsiTransactionComplete(
378 __in BURN_USER_EXPERIENCE* pUserExperience,
379 __in LPCWSTR wzTransactionId,
380 __in HRESULT hrStatus
381 )
382{
383 HRESULT hr = S_OK;
384 BA_ONBEGINMSITRANSACTIONCOMPLETE_ARGS args = { };
385 BA_ONBEGINMSITRANSACTIONCOMPLETE_RESULTS results = { };
386
387 args.cbSize = sizeof(args);
388 args.wzTransactionId = wzTransactionId;
389 args.hrStatus = hrStatus;
390
391 results.cbSize = sizeof(results);
392
393 hr = pUserExperience->pfnBAProc(BOOTSTRAPPER_APPLICATION_MESSAGE_ONBEGINMSITRANSACTIONCOMPLETE, &args, &results, pUserExperience->pvBAProcContext);
394 ExitOnFailure(hr, "BA OnBeginMsiTransactionComplete failed.");
395
396LExit:
397 return hr;
398}
399
351EXTERN_C BAAPI UserExperienceOnCacheAcquireBegin( 400EXTERN_C BAAPI UserExperienceOnCacheAcquireBegin(
352 __in BURN_USER_EXPERIENCE* pUserExperience, 401 __in BURN_USER_EXPERIENCE* pUserExperience,
353 __in_z_opt LPCWSTR wzPackageOrContainerId, 402 __in_z_opt LPCWSTR wzPackageOrContainerId,
@@ -614,6 +663,55 @@ LExit:
614 return hr; 663 return hr;
615} 664}
616 665
666EXTERN_C BAAPI UserExperienceOnCommitMsiTransactionBegin(
667 __in BURN_USER_EXPERIENCE* pUserExperience,
668 __in LPCWSTR wzTransactionId
669 )
670{
671 HRESULT hr = S_OK;
672 BA_ONCOMMITMSITRANSACTIONBEGIN_ARGS args = { };
673 BA_ONCOMMITMSITRANSACTIONBEGIN_RESULTS results = { };
674
675 args.cbSize = sizeof(args);
676 args.wzTransactionId = wzTransactionId;
677
678 results.cbSize = sizeof(results);
679
680 hr = pUserExperience->pfnBAProc(BOOTSTRAPPER_APPLICATION_MESSAGE_ONCOMMITMSITRANSACTIONBEGIN, &args, &results, pUserExperience->pvBAProcContext);
681 ExitOnFailure(hr, "BA OnCommitMsiTransactionBegin failed.");
682
683 if (results.fCancel)
684 {
685 hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
686 }
687
688LExit:
689 return hr;
690}
691
692EXTERN_C BAAPI UserExperienceOnCommitMsiTransactionComplete(
693 __in BURN_USER_EXPERIENCE* pUserExperience,
694 __in LPCWSTR wzTransactionId,
695 __in HRESULT hrStatus
696 )
697{
698 HRESULT hr = S_OK;
699 BA_ONCOMMITMSITRANSACTIONCOMPLETE_ARGS args = { };
700 BA_ONCOMMITMSITRANSACTIONCOMPLETE_RESULTS results = { };
701
702 args.cbSize = sizeof(args);
703 args.wzTransactionId = wzTransactionId;
704 args.hrStatus = hrStatus;
705
706 results.cbSize = sizeof(results);
707
708 hr = pUserExperience->pfnBAProc(BOOTSTRAPPER_APPLICATION_MESSAGE_ONCOMMITMSITRANSACTIONCOMPLETE, &args, &results, pUserExperience->pvBAProcContext);
709 ExitOnFailure(hr, "BA OnCommitMsiTransactionComplete failed.");
710
711LExit:
712 return hr;
713}
714
617EXTERN_C BAAPI UserExperienceOnDetectBegin( 715EXTERN_C BAAPI UserExperienceOnDetectBegin(
618 __in BURN_USER_EXPERIENCE* pUserExperience, 716 __in BURN_USER_EXPERIENCE* pUserExperience,
619 __in BOOL fInstalled, 717 __in BOOL fInstalled,
@@ -1799,6 +1897,50 @@ LExit:
1799 return hr; 1897 return hr;
1800} 1898}
1801 1899
1900EXTERN_C BAAPI UserExperienceOnRollbackMsiTransactionBegin(
1901 __in BURN_USER_EXPERIENCE* pUserExperience,
1902 __in LPCWSTR wzTransactionId
1903 )
1904{
1905 HRESULT hr = S_OK;
1906 BA_ONROLLBACKMSITRANSACTIONBEGIN_ARGS args = { };
1907 BA_ONROLLBACKMSITRANSACTIONBEGIN_RESULTS results = { };
1908
1909 args.cbSize = sizeof(args);
1910 args.wzTransactionId = wzTransactionId;
1911
1912 results.cbSize = sizeof(results);
1913
1914 hr = pUserExperience->pfnBAProc(BOOTSTRAPPER_APPLICATION_MESSAGE_ONROLLBACKMSITRANSACTIONBEGIN, &args, &results, pUserExperience->pvBAProcContext);
1915 ExitOnFailure(hr, "BA OnRollbackMsiTransactionBegin failed.");
1916
1917LExit:
1918 return hr;
1919}
1920
1921EXTERN_C BAAPI UserExperienceOnRollbackMsiTransactionComplete(
1922 __in BURN_USER_EXPERIENCE* pUserExperience,
1923 __in LPCWSTR wzTransactionId,
1924 __in HRESULT hrStatus
1925 )
1926{
1927 HRESULT hr = S_OK;
1928 BA_ONROLLBACKMSITRANSACTIONCOMPLETE_ARGS args = { };
1929 BA_ONROLLBACKMSITRANSACTIONCOMPLETE_RESULTS results = { };
1930
1931 args.cbSize = sizeof(args);
1932 args.wzTransactionId = wzTransactionId;
1933 args.hrStatus = hrStatus;
1934
1935 results.cbSize = sizeof(results);
1936
1937 hr = pUserExperience->pfnBAProc(BOOTSTRAPPER_APPLICATION_MESSAGE_ONROLLBACKMSITRANSACTIONCOMPLETE, &args, &results, pUserExperience->pvBAProcContext);
1938 ExitOnFailure(hr, "BA OnRollbackMsiTransactionComplete failed.");
1939
1940LExit:
1941 return hr;
1942}
1943
1802EXTERN_C BAAPI UserExperienceOnShutdown( 1944EXTERN_C BAAPI UserExperienceOnShutdown(
1803 __in BURN_USER_EXPERIENCE* pUserExperience, 1945 __in BURN_USER_EXPERIENCE* pUserExperience,
1804 __inout BOOTSTRAPPER_SHUTDOWN_ACTION* pAction 1946 __inout BOOTSTRAPPER_SHUTDOWN_ACTION* pAction
diff --git a/src/engine/userexperience.h b/src/engine/userexperience.h
index 0ebd1b68..387ed62b 100644
--- a/src/engine/userexperience.h
+++ b/src/engine/userexperience.h
@@ -108,7 +108,16 @@ BAAPI UserExperienceOnApplyComplete(
108 __in HRESULT hrStatus, 108 __in HRESULT hrStatus,
109 __in BOOTSTRAPPER_APPLY_RESTART restart, 109 __in BOOTSTRAPPER_APPLY_RESTART restart,
110 __inout BOOTSTRAPPER_APPLYCOMPLETE_ACTION* pAction 110 __inout BOOTSTRAPPER_APPLYCOMPLETE_ACTION* pAction
111); 111 );
112BAAPI UserExperienceOnBeginMsiTransactionBegin(
113 __in BURN_USER_EXPERIENCE* pUserExperience,
114 __in LPCWSTR wzTransactionId
115 );
116BAAPI UserExperienceOnBeginMsiTransactionComplete(
117 __in BURN_USER_EXPERIENCE* pUserExperience,
118 __in LPCWSTR wzTransactionId,
119 __in HRESULT hrStatus
120 );
112BAAPI UserExperienceOnCacheAcquireBegin( 121BAAPI UserExperienceOnCacheAcquireBegin(
113 __in BURN_USER_EXPERIENCE* pUserExperience, 122 __in BURN_USER_EXPERIENCE* pUserExperience,
114 __in_z_opt LPCWSTR wzPackageOrContainerId, 123 __in_z_opt LPCWSTR wzPackageOrContainerId,
@@ -162,6 +171,15 @@ BAAPI UserExperienceOnCacheVerifyComplete(
162 __in HRESULT hrStatus, 171 __in HRESULT hrStatus,
163 __inout BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION* pAction 172 __inout BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION* pAction
164 ); 173 );
174BAAPI UserExperienceOnCommitMsiTransactionBegin(
175 __in BURN_USER_EXPERIENCE* pUserExperience,
176 __in LPCWSTR wzTransactionId
177 );
178BAAPI UserExperienceOnCommitMsiTransactionComplete(
179 __in BURN_USER_EXPERIENCE* pUserExperience,
180 __in LPCWSTR wzTransactionId,
181 __in HRESULT hrStatus
182 );
165BAAPI UserExperienceOnDetectBegin( 183BAAPI UserExperienceOnDetectBegin(
166 __in BURN_USER_EXPERIENCE* pUserExperience, 184 __in BURN_USER_EXPERIENCE* pUserExperience,
167 __in BOOL fInstalled, 185 __in BOOL fInstalled,
@@ -272,7 +290,7 @@ BAAPI UserExperienceOnExecuteBegin(
272BAAPI UserExperienceOnExecuteComplete( 290BAAPI UserExperienceOnExecuteComplete(
273 __in BURN_USER_EXPERIENCE* pUserExperience, 291 __in BURN_USER_EXPERIENCE* pUserExperience,
274 __in HRESULT hrStatus 292 __in HRESULT hrStatus
275); 293 );
276BAAPI UserExperienceOnExecuteFilesInUse( 294BAAPI UserExperienceOnExecuteFilesInUse(
277 __in BURN_USER_EXPERIENCE* pUserExperience, 295 __in BURN_USER_EXPERIENCE* pUserExperience,
278 __in_z LPCWSTR wzPackageId, 296 __in_z LPCWSTR wzPackageId,
@@ -315,7 +333,7 @@ BAAPI UserExperienceOnExecuteProgress(
315 __in_z LPCWSTR wzPackageId, 333 __in_z LPCWSTR wzPackageId,
316 __in DWORD dwProgressPercentage, 334 __in DWORD dwProgressPercentage,
317 __in DWORD dwOverallPercentage, 335 __in DWORD dwOverallPercentage,
318 __inout int* pnResult 336 __out int* pnResult
319 ); 337 );
320BAAPI UserExperienceOnLaunchApprovedExeBegin( 338BAAPI UserExperienceOnLaunchApprovedExeBegin(
321 __in BURN_USER_EXPERIENCE* pUserExperience 339 __in BURN_USER_EXPERIENCE* pUserExperience
@@ -411,6 +429,15 @@ BAAPI UserExperienceOnResolveSource(
411 __in_z_opt LPCWSTR wzDownloadSource, 429 __in_z_opt LPCWSTR wzDownloadSource,
412 __inout BOOTSTRAPPER_RESOLVESOURCE_ACTION* pAction 430 __inout BOOTSTRAPPER_RESOLVESOURCE_ACTION* pAction
413 ); 431 );
432BAAPI UserExperienceOnRollbackMsiTransactionBegin(
433 __in BURN_USER_EXPERIENCE* pUserExperience,
434 __in LPCWSTR wzTransactionId
435 );
436BAAPI UserExperienceOnRollbackMsiTransactionComplete(
437 __in BURN_USER_EXPERIENCE* pUserExperience,
438 __in LPCWSTR wzTransactionId,
439 __in HRESULT hrStatus
440 );
414BAAPI UserExperienceOnShutdown( 441BAAPI UserExperienceOnShutdown(
415 __in BURN_USER_EXPERIENCE* pUserExperience, 442 __in BURN_USER_EXPERIENCE* pUserExperience,
416 __inout BOOTSTRAPPER_SHUTDOWN_ACTION* pAction 443 __inout BOOTSTRAPPER_SHUTDOWN_ACTION* pAction