aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2020-11-15 20:23:44 -0600
committerSean Hall <r.sean.hall@gmail.com>2020-11-17 19:06:00 -0600
commit846f5a033d346c1bac51c56d4936cd3118ebea7a (patch)
tree6370380f4aa18355feebc1a058f0793ad14cd899
parent0d873d28c2dd18444afa08b748e91f495ed1cf5c (diff)
downloadwix-846f5a033d346c1bac51c56d4936cd3118ebea7a.tar.gz
wix-846f5a033d346c1bac51c56d4936cd3118ebea7a.tar.bz2
wix-846f5a033d346c1bac51c56d4936cd3118ebea7a.zip
Clean up the elevation code for MSI transactions.
-rw-r--r--src/engine/apply.cpp232
-rw-r--r--src/engine/elevation.cpp178
-rw-r--r--src/engine/elevation.h17
-rw-r--r--src/engine/msiengine.cpp42
-rw-r--r--src/engine/msiengine.h5
5 files changed, 213 insertions, 261 deletions
diff --git a/src/engine/apply.cpp b/src/engine/apply.cpp
index 9a0f64e1..909fb159 100644
--- a/src/engine/apply.cpp
+++ b/src/engine/apply.cpp
@@ -198,6 +198,19 @@ static HRESULT ExecuteCompatiblePackageAction(
198 __in BURN_ENGINE_STATE* pEngineState, 198 __in BURN_ENGINE_STATE* pEngineState,
199 __in BURN_EXECUTE_ACTION* pAction 199 __in BURN_EXECUTE_ACTION* pAction
200 ); 200 );
201static HRESULT ExecuteMsiBeginTransaction(
202 __in BURN_ENGINE_STATE* pEngineState,
203 __in LPCWSTR wzName,
204 __in BURN_EXECUTE_CONTEXT* pContext
205 );
206static HRESULT ExecuteMsiCommitTransaction(
207 __in BURN_ENGINE_STATE* pEngineState,
208 __in BURN_EXECUTE_CONTEXT* pContext
209 );
210static HRESULT ExecuteMsiRollbackTransaction(
211 __in BURN_ENGINE_STATE* pEngineState,
212 __in BURN_EXECUTE_CONTEXT* pContext
213 );
201static HRESULT CleanPackage( 214static HRESULT CleanPackage(
202 __in HANDLE hElevatedPipe, 215 __in HANDLE hElevatedPipe,
203 __in BURN_PACKAGE* pPackage 216 __in BURN_PACKAGE* pPackage
@@ -228,30 +241,6 @@ static HRESULT ExecutePackageComplete(
228 __out BOOL* pfSuspend 241 __out BOOL* pfSuspend
229 ); 242 );
230 243
231static HRESULT DoMsiBeginTransaction(
232 __in BURN_EXECUTE_CONTEXT *context
233 , __in BURN_ENGINE_STATE* pEngineState
234);
235static HRESULT DoMsiCommitTransaction(
236 __in BURN_EXECUTE_CONTEXT *context
237 , __in BURN_ENGINE_STATE* pEngineState
238);
239static HRESULT DoMsiRollbackTransaction(
240 __in BURN_EXECUTE_CONTEXT *context
241 , __in BURN_ENGINE_STATE* pEngineState
242);
243static HRESULT ExecuteMsiBeginTransaction(
244 __in BURN_EXECUTE_CONTEXT* pContext
245 , __in BURN_ENGINE_STATE* pEngineState
246);
247static HRESULT ExecuteMsiCommitTransaction(
248 __in BURN_EXECUTE_CONTEXT* pContext
249 , __in BURN_ENGINE_STATE* pEngineState
250);
251static HRESULT ExecuteMsiRollbackTransaction(
252 __in BURN_EXECUTE_CONTEXT* pContext
253 , __in BURN_ENGINE_STATE* pEngineState
254);
255 244
256// function definitions 245// function definitions
257 246
@@ -773,7 +762,7 @@ extern "C" HRESULT ApplyExecute(
773 if (fInTransaction) 762 if (fInTransaction)
774 { 763 {
775 LogString(REPORT_STANDARD, "Committing MSI transaction\n"); 764 LogString(REPORT_STANDARD, "Committing MSI transaction\n");
776 hr = DoMsiCommitTransaction(&context, pEngineState); 765 hr = ExecuteMsiCommitTransaction(pEngineState, &context);
777 ExitOnFailure(hr, "Failed committing an MSI transaction"); 766 ExitOnFailure(hr, "Failed committing an MSI transaction");
778 fInTransaction = FALSE; 767 fInTransaction = FALSE;
779 } 768 }
@@ -789,7 +778,7 @@ extern "C" HRESULT ApplyExecute(
789 else 778 else
790 { 779 {
791 LogString(REPORT_STANDARD, "Starting a new MSI transaction\n"); 780 LogString(REPORT_STANDARD, "Starting a new MSI transaction\n");
792 hr = DoMsiBeginTransaction(&context, pEngineState); 781 hr = ExecuteMsiBeginTransaction(pEngineState, pExecuteAction->rollbackBoundary.pRollbackBoundary->sczId, &context);
793 ExitOnFailure(hr, "Failed beginning an MSI transaction"); 782 ExitOnFailure(hr, "Failed beginning an MSI transaction");
794 fInTransaction = TRUE; 783 fInTransaction = TRUE;
795 } 784 }
@@ -855,7 +844,7 @@ extern "C" HRESULT ApplyExecute(
855 if (fInTransaction) 844 if (fInTransaction)
856 { 845 {
857 LogString(REPORT_STANDARD, "Committing an MSI transaction\n"); 846 LogString(REPORT_STANDARD, "Committing an MSI transaction\n");
858 hr = DoMsiCommitTransaction(&context, pEngineState); 847 hr = ExecuteMsiCommitTransaction(pEngineState, &context);
859 ExitOnFailure(hr, "Failed committing an MSI transaction"); 848 ExitOnFailure(hr, "Failed committing an MSI transaction");
860 fInTransaction = FALSE; 849 fInTransaction = FALSE;
861 } 850 }
@@ -1658,127 +1647,6 @@ static void DoRollbackCache(
1658 } 1647 }
1659} 1648}
1660 1649
1661/* MSI Transactions:
1662 * All MSI/MSP/MSU packages wrapped in MsiBeginTranasaction-MsiEndTransaction pair are installed or uninstalled together.
1663*/
1664static HRESULT ExecuteMsiBeginTransaction(
1665 __in BURN_EXECUTE_CONTEXT* pContext
1666 , __in BURN_ENGINE_STATE* pEngineState
1667)
1668{
1669 HRESULT hr = S_OK;
1670 UINT uResult = ERROR_SUCCESS;
1671
1672 // Per user/machine context
1673 if (pEngineState->plan.fPerMachine)
1674 {
1675 hr = ElevationMsiBeginTransaction(pEngineState->companionConnection.hPipe, pEngineState->userExperience.hwndApply, pContext);
1676 ExitOnFailure(hr, "Failed to begin an MSI transaction.");
1677 }
1678 else
1679 {
1680 MSIHANDLE hMsiTrns = NULL;
1681 HANDLE hMsiTrnsEvent = NULL;
1682 uResult = MsiBeginTransaction(L"WiX", 0, &hMsiTrns, &hMsiTrnsEvent);
1683 ExitOnWin32Error(uResult, hr, "Failed beginning an MSI transaction");
1684 }
1685
1686LExit:
1687 return hr;
1688}
1689
1690static HRESULT ExecuteMsiCommitTransaction(
1691 __in BURN_EXECUTE_CONTEXT* pContext
1692 , __in BURN_ENGINE_STATE* pEngineState
1693)
1694{
1695 HRESULT hr = S_OK;
1696 UINT uResult = ERROR_SUCCESS;
1697
1698 // Per user/machine context
1699 if (pEngineState->plan.fPerMachine)
1700 {
1701 hr = ElevationMsiCommitTransaction(pEngineState->companionConnection.hPipe, pEngineState->userExperience.hwndApply, pContext);
1702 ExitOnFailure(hr, "Failed to commit an MSI transaction.");
1703 }
1704 else
1705 {
1706 uResult = MsiEndTransaction(MSITRANSACTIONSTATE_COMMIT);
1707 ExitOnWin32Error(uResult, hr, "Failed beginning an MSI transaction");
1708 }
1709
1710LExit:
1711 return hr;
1712}
1713
1714static HRESULT ExecuteMsiRollbackTransaction(
1715 __in BURN_EXECUTE_CONTEXT* pContext
1716 , __in BURN_ENGINE_STATE* pEngineState
1717)
1718{
1719 HRESULT hr = S_OK;
1720 UINT uResult = ERROR_SUCCESS;
1721
1722 // Per user/machine context
1723 if (pEngineState->plan.fPerMachine)
1724 {
1725 hr = ElevationMsiRollbackTransaction(pEngineState->companionConnection.hPipe, pEngineState->userExperience.hwndApply, pContext);
1726 ExitOnFailure(hr, "Failed to rollback an MSI transaction.");
1727 }
1728 else
1729 {
1730 uResult = MsiEndTransaction(MSITRANSACTIONSTATE_ROLLBACK);
1731 ExitOnWin32Error(uResult, hr, "Failed beginning an MSI transaction");
1732 }
1733
1734LExit:
1735 return hr;
1736}
1737
1738// Currently, supporting only elevated transactions.
1739static HRESULT DoMsiBeginTransaction(
1740 __in BURN_EXECUTE_CONTEXT *pContext
1741 , __in BURN_ENGINE_STATE* pEngineState
1742)
1743{
1744 HRESULT hr = S_OK;
1745
1746 hr = ExecuteMsiBeginTransaction(pContext, pEngineState);
1747 ExitOnFailure(hr, "Failed to execute EXE package.");
1748
1749LExit:
1750 return hr;
1751}
1752
1753static HRESULT DoMsiCommitTransaction(
1754 __in BURN_EXECUTE_CONTEXT *pContext
1755 , __in BURN_ENGINE_STATE* pEngineState
1756)
1757{
1758 HRESULT hr = S_OK;
1759
1760 hr = ExecuteMsiCommitTransaction(pContext, pEngineState);
1761 ExitOnFailure(hr, "Failed to execute EXE package.");
1762
1763LExit:
1764 return hr;
1765}
1766
1767static HRESULT DoMsiRollbackTransaction(
1768 __in BURN_EXECUTE_CONTEXT *pContext
1769 , __in BURN_ENGINE_STATE* pEngineState
1770)
1771{
1772 HRESULT hr = S_OK;
1773
1774 hr = ExecuteMsiRollbackTransaction(pContext, pEngineState);
1775 ExitOnFailure(hr, "Failed to execute EXE package.");
1776
1777LExit:
1778 return hr;
1779}
1780
1781
1782static HRESULT DoExecuteAction( 1650static HRESULT DoExecuteAction(
1783 __in BURN_ENGINE_STATE* pEngineState, 1651 __in BURN_ENGINE_STATE* pEngineState,
1784 __in BURN_EXECUTE_ACTION* pExecuteAction, 1652 __in BURN_EXECUTE_ACTION* pExecuteAction,
@@ -1904,7 +1772,7 @@ static HRESULT DoRollbackActions(
1904 __in BOOL fInTransaction, 1772 __in BOOL fInTransaction,
1905 __out BOOL* pfKeepRegistration, 1773 __out BOOL* pfKeepRegistration,
1906 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 1774 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
1907) 1775 )
1908{ 1776{
1909 HRESULT hr = S_OK; 1777 HRESULT hr = S_OK;
1910 DWORD iCheckpoint = 0; 1778 DWORD iCheckpoint = 0;
@@ -1916,7 +1784,7 @@ static HRESULT DoRollbackActions(
1916 // Rollback MSI transaction 1784 // Rollback MSI transaction
1917 if (fInTransaction) 1785 if (fInTransaction)
1918 { 1786 {
1919 hr = DoMsiRollbackTransaction(pContext, pEngineState); 1787 hr = ExecuteMsiRollbackTransaction(pEngineState, pContext);
1920 ExitOnFailure(hr, "Failed rolling back transaction"); 1788 ExitOnFailure(hr, "Failed rolling back transaction");
1921 } 1789 }
1922 1790
@@ -2364,6 +2232,70 @@ LExit:
2364 return hr; 2232 return hr;
2365} 2233}
2366 2234
2235static HRESULT ExecuteMsiBeginTransaction(
2236 __in BURN_ENGINE_STATE* pEngineState,
2237 __in LPCWSTR wzName,
2238 __in BURN_EXECUTE_CONTEXT* /*pContext*/
2239 )
2240{
2241 HRESULT hr = S_OK;
2242
2243 if (pEngineState->plan.fPerMachine)
2244 {
2245 hr = ElevationMsiBeginTransaction(pEngineState->companionConnection.hPipe, wzName);
2246 ExitOnFailure(hr, "Failed to begin an elevated MSI transaction.");
2247 }
2248 else
2249 {
2250 hr = MsiEngineBeginTransaction(wzName);
2251 }
2252
2253LExit:
2254 return hr;
2255}
2256
2257static HRESULT ExecuteMsiCommitTransaction(
2258 __in BURN_ENGINE_STATE* pEngineState,
2259 __in BURN_EXECUTE_CONTEXT* /*pContext*/
2260 )
2261{
2262 HRESULT hr = S_OK;
2263
2264 if (pEngineState->plan.fPerMachine)
2265 {
2266 hr = ElevationMsiCommitTransaction(pEngineState->companionConnection.hPipe);
2267 ExitOnFailure(hr, "Failed to commit an elevated MSI transaction.");
2268 }
2269 else
2270 {
2271 hr = MsiEngineCommitTransaction();
2272 }
2273
2274LExit:
2275 return hr;
2276}
2277
2278static HRESULT ExecuteMsiRollbackTransaction(
2279 __in BURN_ENGINE_STATE* pEngineState,
2280 __in BURN_EXECUTE_CONTEXT* /*pContext*/
2281 )
2282{
2283 HRESULT hr = S_OK;
2284
2285 if (pEngineState->plan.fPerMachine)
2286 {
2287 hr = ElevationMsiRollbackTransaction(pEngineState->companionConnection.hPipe);
2288 ExitOnFailure(hr, "Failed to rollback an elevated MSI transaction.");
2289 }
2290 else
2291 {
2292 hr = MsiEngineRollbackTransaction();
2293 }
2294
2295LExit:
2296 return hr;
2297}
2298
2367static HRESULT CleanPackage( 2299static HRESULT CleanPackage(
2368 __in HANDLE hElevatedPipe, 2300 __in HANDLE hElevatedPipe,
2369 __in BURN_PACKAGE* pPackage 2301 __in BURN_PACKAGE* pPackage
diff --git a/src/engine/elevation.cpp b/src/engine/elevation.cpp
index 9ce04630..81a48316 100644
--- a/src/engine/elevation.cpp
+++ b/src/engine/elevation.cpp
@@ -28,17 +28,15 @@ typedef enum _BURN_ELEVATION_MESSAGE_TYPE
28 BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_EMBEDDED_CHILD, 28 BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_EMBEDDED_CHILD,
29 BURN_ELEVATION_MESSAGE_TYPE_CLEAN_PACKAGE, 29 BURN_ELEVATION_MESSAGE_TYPE_CLEAN_PACKAGE,
30 BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE, 30 BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE,
31 BURN_ELEVATION_MESSAGE_TYPE_BEGIN_MSI_TRANSACTION,
32 BURN_ELEVATION_MESSAGE_TYPE_COMMIT_MSI_TRANSACTION,
33 BURN_ELEVATION_MESSAGE_TYPE_ROLLBACK_MSI_TRANSACTION,
31 34
32 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS, 35 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS,
33 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR, 36 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR,
34 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_MESSAGE, 37 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_MESSAGE,
35 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_FILES_IN_USE, 38 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_FILES_IN_USE,
36 BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE_PROCESSID, 39 BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE_PROCESSID,
37
38 BURN_ELEVATION_TRANSACTION_BEGIN,
39 BURN_ELEVATION_TRANSACTION_COMMIT,
40 BURN_ELEVATION_TRANSACTION_ROLLBACK
41
42} BURN_ELEVATION_MESSAGE_TYPE; 40} BURN_ELEVATION_MESSAGE_TYPE;
43 41
44 42
@@ -74,24 +72,11 @@ typedef struct _BURN_ELEVATION_CHILD_MESSAGE_CONTEXT
74 BURN_VARIABLES* pVariables; 72 BURN_VARIABLES* pVariables;
75 BURN_REGISTRATION* pRegistration; 73 BURN_REGISTRATION* pRegistration;
76 BURN_USER_EXPERIENCE* pUserExperience; 74 BURN_USER_EXPERIENCE* pUserExperience;
77
78 MSIHANDLE hMsiTrns;
79 HANDLE hMsiTrnsEvent;
80} BURN_ELEVATION_CHILD_MESSAGE_CONTEXT; 75} BURN_ELEVATION_CHILD_MESSAGE_CONTEXT;
81 76
82 77
83// internal function declarations 78// internal function declarations
84 79
85static HRESULT OnMsiBeginTransaction(
86 __in BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext
87);
88static HRESULT OnMsiCommitTransaction(
89 __in BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext
90);
91static HRESULT OnMsiRollbackTransaction(
92 __in BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext
93);
94
95static DWORD WINAPI ElevatedChildCacheThreadProc( 80static DWORD WINAPI ElevatedChildCacheThreadProc(
96 __in LPVOID lpThreadParameter 81 __in LPVOID lpThreadParameter
97 ); 82 );
@@ -248,6 +233,13 @@ static HRESULT OnLaunchApprovedExe(
248 __in BYTE* pbData, 233 __in BYTE* pbData,
249 __in DWORD cbData 234 __in DWORD cbData
250 ); 235 );
236static HRESULT OnMsiBeginTransaction(
237 __in BYTE* pbData,
238 __in DWORD cbData
239 );
240static HRESULT OnMsiCommitTransaction();
241static HRESULT OnMsiRollbackTransaction();
242
251 243
252 244
253// function definitions 245// function definitions
@@ -726,62 +718,56 @@ LExit:
726 718
727extern "C" HRESULT ElevationMsiBeginTransaction( 719extern "C" HRESULT ElevationMsiBeginTransaction(
728 __in HANDLE hPipe, 720 __in HANDLE hPipe,
729 __in_opt HWND hwndParent, 721 __in LPCWSTR wzName
730 __in LPVOID pvContext 722 )
731)
732{ 723{
733 UNREFERENCED_PARAMETER(hwndParent);
734 HRESULT hr = S_OK; 724 HRESULT hr = S_OK;
735 BURN_ELEVATION_MSI_MESSAGE_CONTEXT context = {}; 725 BYTE* pbData = NULL;
726 SIZE_T cbData = 0;
736 DWORD dwResult = ERROR_SUCCESS; 727 DWORD dwResult = ERROR_SUCCESS;
737 728
738 context.pvContext = pvContext; 729 // serialize message data
730 hr = BuffWriteString(&pbData, &cbData, wzName);
731 ExitOnFailure(hr, "Failed to write transaction name to message buffer.");
739 732
740 hr = PipeSendMessage(hPipe, BURN_ELEVATION_TRANSACTION_BEGIN, NULL, 0, NULL, &context, &dwResult); 733 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_BEGIN_MSI_TRANSACTION, NULL, 0, NULL, NULL, &dwResult);
741 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE message to per-machine process."); 734 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_BEGIN_MSI_TRANSACTION message to per-machine process.");
742 ExitOnWin32Error(dwResult, hr, "Failed beginning an elevated MSI transaction"); 735
736 hr = static_cast<HRESULT>(dwResult);
743 737
744LExit: 738LExit:
739 ReleaseBuffer(pbData);
740
745 return hr; 741 return hr;
746} 742}
747 743
748extern "C" HRESULT ElevationMsiCommitTransaction( 744extern "C" HRESULT ElevationMsiCommitTransaction(
749 __in HANDLE hPipe, 745 __in HANDLE hPipe
750 __in_opt HWND hwndParent, 746 )
751 __in LPVOID pvContext
752)
753{ 747{
754 UNREFERENCED_PARAMETER(hwndParent);
755 HRESULT hr = S_OK; 748 HRESULT hr = S_OK;
756 BURN_ELEVATION_MSI_MESSAGE_CONTEXT context = {};
757 DWORD dwResult = ERROR_SUCCESS; 749 DWORD dwResult = ERROR_SUCCESS;
758 750
759 context.pvContext = pvContext; 751 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_COMMIT_MSI_TRANSACTION, NULL, 0, NULL, NULL, &dwResult);
752 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_COMMIT_MSI_TRANSACTION message to per-machine process.");
760 753
761 hr = PipeSendMessage(hPipe, BURN_ELEVATION_TRANSACTION_COMMIT, NULL, 0, NULL, &context, &dwResult); 754 hr = static_cast<HRESULT>(dwResult);
762 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE message to per-machine process.");
763 ExitOnWin32Error(dwResult, hr, "Failed committing an elevated MSI transaction");
764 755
765LExit: 756LExit:
766 return hr; 757 return hr;
767} 758}
768 759
769extern "C" HRESULT ElevationMsiRollbackTransaction( 760extern "C" HRESULT ElevationMsiRollbackTransaction(
770 __in HANDLE hPipe, 761 __in HANDLE hPipe
771 __in_opt HWND hwndParent, 762 )
772 __in LPVOID pvContext
773)
774{ 763{
775 UNREFERENCED_PARAMETER(hwndParent);
776 HRESULT hr = S_OK; 764 HRESULT hr = S_OK;
777 BURN_ELEVATION_MSI_MESSAGE_CONTEXT context = {};
778 DWORD dwResult = ERROR_SUCCESS; 765 DWORD dwResult = ERROR_SUCCESS;
779 766
780 context.pvContext = pvContext; 767 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_ROLLBACK_MSI_TRANSACTION, NULL, 0, NULL, NULL, &dwResult);
768 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_ROLLBACK_MSI_TRANSACTION message to per-machine process.");
781 769
782 hr = PipeSendMessage(hPipe, BURN_ELEVATION_TRANSACTION_ROLLBACK, NULL, 0, NULL, &context, &dwResult); 770 hr = static_cast<HRESULT>(dwResult);
783 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE message to per-machine process.");
784 ExitOnWin32Error(dwResult, hr, "Failed rolling back an elevated MSI transaction");
785 771
786LExit: 772LExit:
787 return hr; 773 return hr;
@@ -1543,16 +1529,16 @@ static HRESULT ProcessElevatedChildMessage(
1543 1529
1544 switch (pMsg->dwMessage) 1530 switch (pMsg->dwMessage)
1545 { 1531 {
1546 case BURN_ELEVATION_TRANSACTION_BEGIN: 1532 case BURN_ELEVATION_MESSAGE_TYPE_BEGIN_MSI_TRANSACTION:
1547 hrResult = OnMsiBeginTransaction(pContext); 1533 hrResult = OnMsiBeginTransaction((BYTE*)pMsg->pvData, pMsg->cbData);
1548 break; 1534 break;
1549 1535
1550 case BURN_ELEVATION_TRANSACTION_COMMIT: 1536 case BURN_ELEVATION_MESSAGE_TYPE_COMMIT_MSI_TRANSACTION:
1551 hrResult = OnMsiCommitTransaction(pContext); 1537 hrResult = OnMsiCommitTransaction();
1552 break; 1538 break;
1553 1539
1554 case BURN_ELEVATION_TRANSACTION_ROLLBACK: 1540 case BURN_ELEVATION_MESSAGE_TYPE_ROLLBACK_MSI_TRANSACTION:
1555 hrResult = OnMsiRollbackTransaction(pContext); 1541 hrResult = OnMsiRollbackTransaction();
1556 break; 1542 break;
1557 1543
1558 case BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE: 1544 case BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE:
@@ -1690,53 +1676,6 @@ static HRESULT ProcessResult(
1690 return hr; 1676 return hr;
1691} 1677}
1692 1678
1693static HRESULT OnMsiBeginTransaction(
1694 __in BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext
1695)
1696{
1697 UINT uResult = ERROR_SUCCESS;
1698 HRESULT hr = S_OK;
1699
1700 pContext->hMsiTrns = NULL;
1701 pContext->hMsiTrnsEvent = NULL;
1702 uResult = MsiBeginTransaction(L"WiX", 0, &pContext->hMsiTrns, &pContext->hMsiTrnsEvent);
1703 ExitOnWin32Error(uResult, hr, "Failed beginning an MSI transaction");
1704
1705LExit:
1706 return hr;
1707}
1708
1709static HRESULT OnMsiCommitTransaction(
1710 __in BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext
1711)
1712{
1713 UINT uResult = ERROR_SUCCESS;
1714 HRESULT hr = S_OK;
1715
1716 uResult = MsiEndTransaction(MSITRANSACTIONSTATE_COMMIT);
1717 ExitOnWin32Error(uResult, hr, "Failed committing an MSI transaction");
1718
1719LExit:
1720 pContext->hMsiTrns = NULL;
1721 pContext->hMsiTrnsEvent = NULL;
1722 return hr;
1723}
1724
1725static HRESULT OnMsiRollbackTransaction(
1726 __in BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext
1727) {
1728 UINT uResult = ERROR_SUCCESS;
1729 HRESULT hr = S_OK;
1730
1731 uResult = MsiEndTransaction(MSITRANSACTIONSTATE_ROLLBACK);
1732 ExitOnWin32Error(uResult, hr, "Failed rolling back an MSI transaction");
1733
1734LExit:
1735 pContext->hMsiTrns = NULL;
1736 pContext->hMsiTrnsEvent = NULL;
1737 return hr;
1738}
1739
1740static HRESULT OnApplyInitialize( 1679static HRESULT OnApplyInitialize(
1741 __in BURN_VARIABLES* pVariables, 1680 __in BURN_VARIABLES* pVariables,
1742 __in BURN_REGISTRATION* pRegistration, 1681 __in BURN_REGISTRATION* pRegistration,
@@ -2845,3 +2784,42 @@ LExit:
2845 ApprovedExesUninitializeLaunch(pLaunchApprovedExe); 2784 ApprovedExesUninitializeLaunch(pLaunchApprovedExe);
2846 return hr; 2785 return hr;
2847} 2786}
2787
2788static HRESULT OnMsiBeginTransaction(
2789 __in BYTE* pbData,
2790 __in DWORD cbData
2791 )
2792{
2793 HRESULT hr = S_OK;
2794 SIZE_T iData = 0;
2795 LPWSTR sczName = NULL;
2796
2797 // Deserialize message data.
2798 hr = BuffReadString(pbData, cbData, &iData, &sczName);
2799 ExitOnFailure(hr, "Failed to read transaction name.");
2800
2801 hr = MsiEngineBeginTransaction(sczName);
2802
2803LExit:
2804 ReleaseStr(sczName);
2805
2806 return hr;
2807}
2808
2809static HRESULT OnMsiCommitTransaction()
2810{
2811 HRESULT hr = S_OK;
2812
2813 hr = MsiEngineCommitTransaction();
2814
2815 return hr;
2816}
2817
2818static HRESULT OnMsiRollbackTransaction()
2819{
2820 HRESULT hr = S_OK;
2821
2822 hr = MsiEngineRollbackTransaction();
2823
2824 return hr;
2825}
diff --git a/src/engine/elevation.h b/src/engine/elevation.h
index d82d9b1c..975981da 100644
--- a/src/engine/elevation.h
+++ b/src/engine/elevation.h
@@ -159,19 +159,14 @@ HRESULT ElevationChildResumeAutomaticUpdates();
159 159
160HRESULT ElevationMsiBeginTransaction( 160HRESULT ElevationMsiBeginTransaction(
161 __in HANDLE hPipe, 161 __in HANDLE hPipe,
162 __in_opt HWND hwndParent, 162 __in LPCWSTR wzName
163 __in LPVOID pvContext 163 );
164);
165HRESULT ElevationMsiCommitTransaction( 164HRESULT ElevationMsiCommitTransaction(
166 __in HANDLE hPipe, 165 __in HANDLE hPipe
167 __in_opt HWND hwndParent, 166 );
168 __in LPVOID pvContext
169);
170HRESULT ElevationMsiRollbackTransaction( 167HRESULT ElevationMsiRollbackTransaction(
171 __in HANDLE hPipe, 168 __in HANDLE hPipe
172 __in_opt HWND hwndParent, 169 );
173 __in LPVOID pvContext
174);
175 170
176#ifdef __cplusplus 171#ifdef __cplusplus
177} 172}
diff --git a/src/engine/msiengine.cpp b/src/engine/msiengine.cpp
index c20e2ef8..fcd8817d 100644
--- a/src/engine/msiengine.cpp
+++ b/src/engine/msiengine.cpp
@@ -1137,6 +1137,48 @@ LExit:
1137 return hr; 1137 return hr;
1138} 1138}
1139 1139
1140extern "C" HRESULT MsiEngineBeginTransaction(
1141 __in LPCWSTR wzName
1142 )
1143{
1144 HRESULT hr = S_OK;
1145 UINT uResult = ERROR_SUCCESS;
1146 MSIHANDLE hTransactionHandle = NULL;
1147 HANDLE hChangeOfOwnerEvent = NULL;
1148
1149 uResult = ::MsiBeginTransaction(wzName, 0, &hTransactionHandle, &hChangeOfOwnerEvent);
1150 ExitOnWin32Error(uResult, hr, "Failed to begin an MSI transaction");
1151
1152LExit:
1153 return hr;
1154}
1155
1156extern "C" HRESULT MsiEngineCommitTransaction()
1157{
1158 HRESULT hr = S_OK;
1159 UINT uResult = ERROR_SUCCESS;
1160
1161 uResult = ::MsiEndTransaction(MSITRANSACTIONSTATE_COMMIT);
1162 ExitOnWin32Error(uResult, hr, "Failed to commit the MSI transaction");
1163
1164LExit:
1165
1166 return hr;
1167}
1168
1169extern "C" HRESULT MsiEngineRollbackTransaction()
1170{
1171 HRESULT hr = S_OK;
1172 UINT uResult = ERROR_SUCCESS;
1173
1174 uResult = ::MsiEndTransaction(MSITRANSACTIONSTATE_ROLLBACK);
1175 ExitOnWin32Error(uResult, hr, "Failed to rollback the MSI transaction");
1176
1177LExit:
1178
1179 return hr;
1180}
1181
1140extern "C" HRESULT MsiEngineExecutePackage( 1182extern "C" HRESULT MsiEngineExecutePackage(
1141 __in_opt HWND hwndParent, 1183 __in_opt HWND hwndParent,
1142 __in BURN_EXECUTE_ACTION* pExecuteAction, 1184 __in BURN_EXECUTE_ACTION* pExecuteAction,
diff --git a/src/engine/msiengine.h b/src/engine/msiengine.h
index 64bddcf0..63393006 100644
--- a/src/engine/msiengine.h
+++ b/src/engine/msiengine.h
@@ -52,6 +52,11 @@ HRESULT MsiEngineAddCompatiblePackage(
52 __in const BURN_PACKAGE* pPackage, 52 __in const BURN_PACKAGE* pPackage,
53 __out_opt BURN_PACKAGE** ppCompatiblePackage 53 __out_opt BURN_PACKAGE** ppCompatiblePackage
54 ); 54 );
55HRESULT MsiEngineBeginTransaction(
56 __in LPCWSTR wzName
57 );
58HRESULT MsiEngineCommitTransaction();
59HRESULT MsiEngineRollbackTransaction();
55HRESULT MsiEngineExecutePackage( 60HRESULT MsiEngineExecutePackage(
56 __in_opt HWND hwndParent, 61 __in_opt HWND hwndParent,
57 __in BURN_EXECUTE_ACTION* pExecuteAction, 62 __in BURN_EXECUTE_ACTION* pExecuteAction,