diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2020-11-15 21:38:57 -0600 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2020-11-17 19:06:00 -0600 |
commit | e71de85e4ec2899ecd01ac236603cf1dddc4a6c7 (patch) | |
tree | b1537ce17314dc073a9fd3d7d4925f215990be13 | |
parent | 846f5a033d346c1bac51c56d4936cd3118ebea7a (diff) | |
download | wix-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.cpp | 194 | ||||
-rw-r--r-- | src/engine/msiengine.cpp | 5 | ||||
-rw-r--r-- | src/engine/msiengine.h | 1 | ||||
-rw-r--r-- | src/engine/mspengine.cpp | 5 | ||||
-rw-r--r-- | src/engine/mspengine.h | 1 | ||||
-rw-r--r-- | src/engine/package.h | 1 | ||||
-rw-r--r-- | src/engine/plan.cpp | 86 | ||||
-rw-r--r-- | src/engine/plan.h | 20 | ||||
-rw-r--r-- | src/test/BurnUnitTest/PlanTest.cpp | 62 |
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 | |||
6 | const DWORD BURN_CACHE_MAX_RECOMMENDED_VERIFY_TRYAGAIN_ATTEMPTS = 2; | 12 | const 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 | ); |
201 | static HRESULT ExecuteMsiBeginTransaction( | 206 | static 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 | ); |
206 | static HRESULT ExecuteMsiCommitTransaction( | 211 | static 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 | ); |
210 | static HRESULT ExecuteMsiRollbackTransaction( | 216 | static 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 | ); |
214 | static HRESULT CleanPackage( | 221 | static 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 | ||
852 | LExit: | 835 | LExit: |
@@ -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 | ||
2235 | static HRESULT ExecuteMsiBeginTransaction( | 2202 | static 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 | ||
2253 | LExit: | 2230 | LExit: |
@@ -2256,11 +2233,17 @@ LExit: | |||
2256 | 2233 | ||
2257 | static HRESULT ExecuteMsiCommitTransaction( | 2234 | static 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 | |||
2274 | LExit: | 2262 | LExit: |
2275 | return hr; | 2263 | return hr; |
2276 | } | 2264 | } |
2277 | 2265 | ||
2278 | static HRESULT ExecuteMsiRollbackTransaction( | 2266 | static 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 | ||
2295 | LExit: | 2289 | LExit: |
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 | ); |
40 | HRESULT MsiEnginePlanAddPackage( | 41 | HRESULT 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: | |||
266 | extern "C" HRESULT MspEnginePlanCalculatePackage( | 266 | extern "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( | |||
35 | HRESULT MspEnginePlanCalculatePackage( | 35 | HRESULT 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 | ); |
40 | HRESULT MspEnginePlanAddPackage( | 41 | HRESULT 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 | ||
160 | typedef struct _BURN_PATCH_TARGETCODE | 161 | typedef 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( | |||
23 | static void ResetPlannedPackageState( | 23 | static void ResetPlannedPackageState( |
24 | __in BURN_PACKAGE* pPackage | 24 | __in BURN_PACKAGE* pPackage |
25 | ); | 25 | ); |
26 | static void ResetPlannedRollbackBoundaryState( | ||
27 | __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary | ||
28 | ); | ||
26 | static HRESULT ProcessPackage( | 29 | static 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 | ); |
158 | static BOOL NeedsCache( | 162 | static 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 | ||
268 | extern "C" void PlanUninitializeExecuteAction( | 281 | extern "C" void PlanUninitializeExecuteAction( |
@@ -853,7 +866,7 @@ LExit: | |||
853 | 866 | ||
854 | static HRESULT ProcessPackage( | 867 | static 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 | ||
1642 | LExit: | 1657 | LExit: |
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 | |||
1800 | LExit: | 1831 | LExit: |
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 | ||
1827 | LExit: | 1860 | LExit: |
1828 | return hr; | 1861 | return hr; |
@@ -1936,6 +1969,13 @@ static void ResetPlannedPackageState( | |||
1936 | } | 1969 | } |
1937 | } | 1970 | } |
1938 | 1971 | ||
1972 | static void ResetPlannedRollbackBoundaryState( | ||
1973 | __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary | ||
1974 | ) | ||
1975 | { | ||
1976 | pRollbackBoundary->fActiveTransaction = FALSE; | ||
1977 | } | ||
1978 | |||
1939 | static HRESULT GetActionDefaultRequestState( | 1979 | static 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 | ||
73 | enum BURN_CLEAN_ACTION_TYPE | 75 | enum 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 | ||
219 | typedef struct _BURN_EXECUTE_ACTION_CHECKPOINT | ||
220 | { | ||
221 | DWORD dwId; | ||
222 | BURN_ROLLBACK_BOUNDARY* pActiveRollbackBoundary; | ||
223 | } BURN_EXECUTE_ACTION_CHECKPOINT; | ||
224 | |||
217 | typedef struct _BURN_EXECUTE_ACTION | 225 | typedef 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, |