aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-08-25 15:06:04 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-08-26 10:03:37 -0500
commita37208d9a26ec7886870cc17f0726676a285bf7f (patch)
treee620e863cd16801d126cee93eaca7b63293914cf
parent6bd9fb04a9a8c1805a3e909583cca85c54dea7e4 (diff)
downloadwix-a37208d9a26ec7886870cc17f0726676a285bf7f.tar.gz
wix-a37208d9a26ec7886870cc17f0726676a285bf7f.tar.bz2
wix-a37208d9a26ec7886870cc17f0726676a285bf7f.zip
Make sure error codes are translated correctly for per-machine packages.
-rw-r--r--src/burn/engine/bundlepackageengine.cpp2
-rw-r--r--src/burn/engine/elevation.cpp300
-rw-r--r--src/burn/engine/engine.mc7
-rw-r--r--src/burn/engine/exeengine.cpp7
-rw-r--r--src/burn/engine/exeengine.h1
-rw-r--r--src/burn/engine/logging.cpp19
-rw-r--r--src/burn/engine/logging.h4
-rw-r--r--src/burn/engine/pipe.cpp2
-rw-r--r--src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj1
-rw-r--r--src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj.filters3
-rw-r--r--src/burn/test/BurnUnitTest/ExitCodeTest.cpp361
-rw-r--r--src/burn/test/BurnUnitTest/precomp.h1
-rw-r--r--src/internal/WixBuildTools.TestSupport/XunitExtensions/SpecificReturnCodeException.cs9
-rw-r--r--src/internal/WixBuildTools.TestSupport/XunitExtensions/WixAssert.cs2
14 files changed, 554 insertions, 165 deletions
diff --git a/src/burn/engine/bundlepackageengine.cpp b/src/burn/engine/bundlepackageengine.cpp
index 8896fdd0..95f5acbc 100644
--- a/src/burn/engine/bundlepackageengine.cpp
+++ b/src/burn/engine/bundlepackageengine.cpp
@@ -1014,7 +1014,7 @@ static HRESULT ExecuteBundle(
1014 ExitOnFailure(hr, "Failed to run BUNDLE process"); 1014 ExitOnFailure(hr, "Failed to run BUNDLE process");
1015 } 1015 }
1016 1016
1017 hr = ExeEngineHandleExitCode(pPackage->Bundle.rgExitCodes, pPackage->Bundle.cExitCodes, dwExitCode, pRestart); 1017 hr = ExeEngineHandleExitCode(pPackage->Bundle.rgExitCodes, pPackage->Bundle.cExitCodes, pPackage->sczId, dwExitCode, pRestart);
1018 ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode); 1018 ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode);
1019 1019
1020LExit: 1020LExit:
diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp
index adc3aad9..c27289c5 100644
--- a/src/burn/engine/elevation.cpp
+++ b/src/burn/engine/elevation.cpp
@@ -53,6 +53,7 @@ typedef enum _BURN_ELEVATION_MESSAGE_TYPE
53 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_NETFX_FILES_IN_USE, 53 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_NETFX_FILES_IN_USE,
54 BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE_PROCESSID, 54 BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE_PROCESSID,
55 BURN_ELEVATION_MESSAGE_TYPE_PROGRESS_ROUTINE, 55 BURN_ELEVATION_MESSAGE_TYPE_PROGRESS_ROUTINE,
56 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ACTION_COMPLETE,
56} BURN_ELEVATION_MESSAGE_TYPE; 57} BURN_ELEVATION_MESSAGE_TYPE;
57 58
58 59
@@ -76,12 +77,14 @@ typedef struct _BURN_ELEVATION_GENERIC_MESSAGE_CONTEXT
76{ 77{
77 PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler; 78 PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler;
78 LPVOID pvContext; 79 LPVOID pvContext;
80 BOOTSTRAPPER_APPLY_RESTART restart;
79} BURN_ELEVATION_GENERIC_MESSAGE_CONTEXT; 81} BURN_ELEVATION_GENERIC_MESSAGE_CONTEXT;
80 82
81typedef struct _BURN_ELEVATION_MSI_MESSAGE_CONTEXT 83typedef struct _BURN_ELEVATION_MSI_MESSAGE_CONTEXT
82{ 84{
83 PFN_MSIEXECUTEMESSAGEHANDLER pfnMessageHandler; 85 PFN_MSIEXECUTEMESSAGEHANDLER pfnMessageHandler;
84 LPVOID pvContext; 86 LPVOID pvContext;
87 BOOTSTRAPPER_APPLY_RESTART restart;
85} BURN_ELEVATION_MSI_MESSAGE_CONTEXT; 88} BURN_ELEVATION_MSI_MESSAGE_CONTEXT;
86 89
87typedef struct _BURN_ELEVATION_LAUNCH_APPROVED_EXE_MESSAGE_CONTEXT 90typedef struct _BURN_ELEVATION_LAUNCH_APPROVED_EXE_MESSAGE_CONTEXT
@@ -166,9 +169,11 @@ static HRESULT ProcessElevatedChildCacheMessage(
166 __in_opt LPVOID pvContext, 169 __in_opt LPVOID pvContext,
167 __out DWORD* pdwResult 170 __out DWORD* pdwResult
168 ); 171 );
169static HRESULT ProcessResult( 172static HRESULT ProcessExecuteActionCompleteMessage(
170 __in DWORD dwResult, 173 __in BYTE* pbData,
171 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 174 __in DWORD cbData,
175 __out BOOTSTRAPPER_APPLY_RESTART* pRestart,
176 __out DWORD* pdwResult
172 ); 177 );
173static HRESULT OnApplyInitialize( 178static HRESULT OnApplyInitialize(
174 __in HANDLE hPipe, 179 __in HANDLE hPipe,
@@ -246,7 +251,8 @@ static HRESULT OnExecuteRelatedBundle(
246 __in BURN_RELATED_BUNDLES* pRelatedBundles, 251 __in BURN_RELATED_BUNDLES* pRelatedBundles,
247 __in BURN_VARIABLES* pVariables, 252 __in BURN_VARIABLES* pVariables,
248 __in BYTE* pbData, 253 __in BYTE* pbData,
249 __in SIZE_T cbData 254 __in SIZE_T cbData,
255 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
250 ); 256 );
251static HRESULT OnExecuteBundlePackage( 257static HRESULT OnExecuteBundlePackage(
252 __in HANDLE hPipe, 258 __in HANDLE hPipe,
@@ -254,7 +260,8 @@ static HRESULT OnExecuteBundlePackage(
254 __in BURN_PACKAGES* pPackages, 260 __in BURN_PACKAGES* pPackages,
255 __in BURN_VARIABLES* pVariables, 261 __in BURN_VARIABLES* pVariables,
256 __in BYTE* pbData, 262 __in BYTE* pbData,
257 __in SIZE_T cbData 263 __in SIZE_T cbData,
264 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
258 ); 265 );
259static HRESULT OnExecuteExePackage( 266static HRESULT OnExecuteExePackage(
260 __in HANDLE hPipe, 267 __in HANDLE hPipe,
@@ -262,7 +269,8 @@ static HRESULT OnExecuteExePackage(
262 __in BURN_PACKAGES* pPackages, 269 __in BURN_PACKAGES* pPackages,
263 __in BURN_VARIABLES* pVariables, 270 __in BURN_VARIABLES* pVariables,
264 __in BYTE* pbData, 271 __in BYTE* pbData,
265 __in SIZE_T cbData 272 __in SIZE_T cbData,
273 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
266 ); 274 );
267static HRESULT OnExecuteMsiPackage( 275static HRESULT OnExecuteMsiPackage(
268 __in HANDLE hPipe, 276 __in HANDLE hPipe,
@@ -270,7 +278,8 @@ static HRESULT OnExecuteMsiPackage(
270 __in BURN_PACKAGES* pPackages, 278 __in BURN_PACKAGES* pPackages,
271 __in BURN_VARIABLES* pVariables, 279 __in BURN_VARIABLES* pVariables,
272 __in BYTE* pbData, 280 __in BYTE* pbData,
273 __in SIZE_T cbData 281 __in SIZE_T cbData,
282 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
274 ); 283 );
275static HRESULT OnExecuteMspPackage( 284static HRESULT OnExecuteMspPackage(
276 __in HANDLE hPipe, 285 __in HANDLE hPipe,
@@ -278,7 +287,8 @@ static HRESULT OnExecuteMspPackage(
278 __in BURN_PACKAGES* pPackages, 287 __in BURN_PACKAGES* pPackages,
279 __in BURN_VARIABLES* pVariables, 288 __in BURN_VARIABLES* pVariables,
280 __in BYTE* pbData, 289 __in BYTE* pbData,
281 __in SIZE_T cbData 290 __in SIZE_T cbData,
291 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
282 ); 292 );
283static HRESULT OnExecuteMsuPackage( 293static HRESULT OnExecuteMsuPackage(
284 __in HANDLE hPipe, 294 __in HANDLE hPipe,
@@ -286,7 +296,8 @@ static HRESULT OnExecuteMsuPackage(
286 __in BURN_PACKAGES* pPackages, 296 __in BURN_PACKAGES* pPackages,
287 __in BURN_VARIABLES* pVariables, 297 __in BURN_VARIABLES* pVariables,
288 __in BYTE* pbData, 298 __in BYTE* pbData,
289 __in SIZE_T cbData 299 __in SIZE_T cbData,
300 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
290 ); 301 );
291static HRESULT OnUninstallMsiCompatiblePackage( 302static HRESULT OnUninstallMsiCompatiblePackage(
292 __in HANDLE hPipe, 303 __in HANDLE hPipe,
@@ -294,7 +305,8 @@ static HRESULT OnUninstallMsiCompatiblePackage(
294 __in BURN_PACKAGES* pPackages, 305 __in BURN_PACKAGES* pPackages,
295 __in BURN_VARIABLES* pVariables, 306 __in BURN_VARIABLES* pVariables,
296 __in BYTE* pbData, 307 __in BYTE* pbData,
297 __in SIZE_T cbData 308 __in SIZE_T cbData,
309 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
298 ); 310 );
299static HRESULT OnExecutePackageProviderAction( 311static HRESULT OnExecutePackageProviderAction(
300 __in BURN_PACKAGES* pPackages, 312 __in BURN_PACKAGES* pPackages,
@@ -380,6 +392,10 @@ static HRESULT ElevatedOnSystemRestorePointComplete(
380 __in HANDLE hPipe, 392 __in HANDLE hPipe,
381 __in HRESULT hrStatus 393 __in HRESULT hrStatus
382 ); 394 );
395static HRESULT ElevatedOnExecuteActionComplete(
396 __in HANDLE hPipe,
397 __in BOOTSTRAPPER_APPLY_RESTART restart
398 );
383 399
384 400
385// function definitions 401// function definitions
@@ -868,7 +884,8 @@ extern "C" HRESULT ElevationExecuteRelatedBundle(
868 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult); 884 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult);
869 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE message to per-machine process."); 885 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE message to per-machine process.");
870 886
871 hr = ProcessResult(dwResult, pRestart); 887 hr = static_cast<HRESULT>(dwResult);
888 *pRestart = context.restart;
872 889
873LExit: 890LExit:
874 ReleaseBuffer(pbData); 891 ReleaseBuffer(pbData);
@@ -931,7 +948,8 @@ extern "C" HRESULT ElevationExecuteBundlePackage(
931 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_BUNDLE_PACKAGE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult); 948 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_BUNDLE_PACKAGE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult);
932 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_BUNDLE_PACKAGE message to per-machine process."); 949 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_BUNDLE_PACKAGE message to per-machine process.");
933 950
934 hr = ProcessResult(dwResult, pRestart); 951 hr = static_cast<HRESULT>(dwResult);
952 *pRestart = context.restart;
935 953
936LExit: 954LExit:
937 ReleaseBuffer(pbData); 955 ReleaseBuffer(pbData);
@@ -985,7 +1003,8 @@ extern "C" HRESULT ElevationExecuteExePackage(
985 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult); 1003 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult);
986 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE message to per-machine process."); 1004 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE message to per-machine process.");
987 1005
988 hr = ProcessResult(dwResult, pRestart); 1006 hr = static_cast<HRESULT>(dwResult);
1007 *pRestart = context.restart;
989 1008
990LExit: 1009LExit:
991 ReleaseBuffer(pbData); 1010 ReleaseBuffer(pbData);
@@ -1155,7 +1174,8 @@ extern "C" HRESULT ElevationExecuteMsiPackage(
1155 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE, pbData, cbData, ProcessMsiPackageMessages, &context, &dwResult); 1174 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE, pbData, cbData, ProcessMsiPackageMessages, &context, &dwResult);
1156 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE message to per-machine process."); 1175 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE message to per-machine process.");
1157 1176
1158 hr = ProcessResult(dwResult, pRestart); 1177 hr = static_cast<HRESULT>(dwResult);
1178 *pRestart = context.restart;
1159 1179
1160LExit: 1180LExit:
1161 ReleaseBuffer(pbData); 1181 ReleaseBuffer(pbData);
@@ -1234,7 +1254,8 @@ extern "C" HRESULT ElevationExecuteMspPackage(
1234 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE, pbData, cbData, ProcessMsiPackageMessages, &context, &dwResult); 1254 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE, pbData, cbData, ProcessMsiPackageMessages, &context, &dwResult);
1235 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE message to per-machine process."); 1255 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE message to per-machine process.");
1236 1256
1237 hr = ProcessResult(dwResult, pRestart); 1257 hr = static_cast<HRESULT>(dwResult);
1258 *pRestart = context.restart;
1238 1259
1239LExit: 1260LExit:
1240 ReleaseBuffer(pbData); 1261 ReleaseBuffer(pbData);
@@ -1285,7 +1306,8 @@ extern "C" HRESULT ElevationExecuteMsuPackage(
1285 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSU_PACKAGE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult); 1306 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSU_PACKAGE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult);
1286 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSU_PACKAGE message to per-machine process."); 1307 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSU_PACKAGE message to per-machine process.");
1287 1308
1288 hr = ProcessResult(dwResult, pRestart); 1309 hr = static_cast<HRESULT>(dwResult);
1310 *pRestart = context.restart;
1289 1311
1290LExit: 1312LExit:
1291 ReleaseBuffer(pbData); 1313 ReleaseBuffer(pbData);
@@ -1337,7 +1359,8 @@ extern "C" HRESULT ElevationUninstallMsiCompatiblePackage(
1337 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_UNINSTALL_MSI_COMPATIBLE_PACKAGE, pbData, cbData, ProcessMsiPackageMessages, &context, &dwResult); 1359 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_UNINSTALL_MSI_COMPATIBLE_PACKAGE, pbData, cbData, ProcessMsiPackageMessages, &context, &dwResult);
1338 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_UNINSTALL_MSI_COMPATIBLE_PACKAGE message to per-machine process."); 1360 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_UNINSTALL_MSI_COMPATIBLE_PACKAGE message to per-machine process.");
1339 1361
1340 hr = ProcessResult(dwResult, pRestart); 1362 hr = static_cast<HRESULT>(dwResult);
1363 *pRestart = context.restart;
1341 1364
1342LExit: 1365LExit:
1343 ReleaseBuffer(pbData); 1366 ReleaseBuffer(pbData);
@@ -1355,7 +1378,6 @@ extern "C" HRESULT ElevationExecutePackageProviderAction(
1355 BYTE* pbData = NULL; 1378 BYTE* pbData = NULL;
1356 SIZE_T cbData = 0; 1379 SIZE_T cbData = 0;
1357 DWORD dwResult = 0; 1380 DWORD dwResult = 0;
1358 BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE;
1359 1381
1360 // Serialize the message data. 1382 // Serialize the message data.
1361 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->packageProvider.pPackage->sczId); 1383 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->packageProvider.pPackage->sczId);
@@ -1377,9 +1399,6 @@ extern "C" HRESULT ElevationExecutePackageProviderAction(
1377 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_PROVIDER, pbData, cbData, NULL, NULL, &dwResult); 1399 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_PROVIDER, pbData, cbData, NULL, NULL, &dwResult);
1378 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_PROVIDER message to per-machine process."); 1400 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_PROVIDER message to per-machine process.");
1379 1401
1380 // Ignore the restart since this action only results in registry writes.
1381 hr = ProcessResult(dwResult, &restart);
1382
1383LExit: 1402LExit:
1384 ReleaseBuffer(pbData); 1403 ReleaseBuffer(pbData);
1385 1404
@@ -1396,7 +1415,6 @@ extern "C" HRESULT ElevationExecutePackageDependencyAction(
1396 BYTE* pbData = NULL; 1415 BYTE* pbData = NULL;
1397 SIZE_T cbData = 0; 1416 SIZE_T cbData = 0;
1398 DWORD dwResult = 0; 1417 DWORD dwResult = 0;
1399 BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE;
1400 1418
1401 // Serialize the message data. 1419 // Serialize the message data.
1402 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->packageDependency.pPackage->sczId); 1420 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->packageDependency.pPackage->sczId);
@@ -1421,9 +1439,6 @@ extern "C" HRESULT ElevationExecutePackageDependencyAction(
1421 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_DEPENDENCY, pbData, cbData, NULL, NULL, &dwResult); 1439 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_DEPENDENCY, pbData, cbData, NULL, NULL, &dwResult);
1422 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_DEPENDENCY message to per-machine process."); 1440 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_DEPENDENCY message to per-machine process.");
1423 1441
1424 // Ignore the restart since this action only results in registry writes.
1425 hr = ProcessResult(dwResult, &restart);
1426
1427LExit: 1442LExit:
1428 ReleaseBuffer(pbData); 1443 ReleaseBuffer(pbData);
1429 1444
@@ -1839,6 +1854,14 @@ static HRESULT ProcessGenericExecuteMessages(
1839 LPWSTR* rgwzFiles = NULL; 1854 LPWSTR* rgwzFiles = NULL;
1840 GENERIC_EXECUTE_MESSAGE message = { }; 1855 GENERIC_EXECUTE_MESSAGE message = { };
1841 1856
1857 if (BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ACTION_COMPLETE == pMsg->dwMessage)
1858 {
1859 hr = ProcessExecuteActionCompleteMessage((BYTE*)pMsg->pvData, pMsg->cbData, &pContext->restart, pdwResult);
1860 ExitOnFailure(hr, "Failed to process BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ACTION_COMPLETE message.");
1861
1862 ExitFunction();
1863 }
1864
1842 hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.dwUIHint); 1865 hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.dwUIHint);
1843 ExitOnFailure(hr, "Failed to allowed results."); 1866 ExitOnFailure(hr, "Failed to allowed results.");
1844 1867
@@ -1939,6 +1962,14 @@ static HRESULT ProcessMsiPackageMessages(
1939 LPWSTR sczMessage = NULL; 1962 LPWSTR sczMessage = NULL;
1940 BOOL fRestartManager = FALSE; 1963 BOOL fRestartManager = FALSE;
1941 1964
1965 if (BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ACTION_COMPLETE == pMsg->dwMessage)
1966 {
1967 hr = ProcessExecuteActionCompleteMessage((BYTE*)pMsg->pvData, pMsg->cbData, &pContext->restart, pdwResult);
1968 ExitOnFailure(hr, "Failed to process BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ACTION_COMPLETE message.");
1969
1970 ExitFunction();
1971 }
1972
1942 // Read MSI extended message data. 1973 // Read MSI extended message data.
1943 hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &cMsiData); 1974 hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &cMsiData);
1944 ExitOnFailure(hr, "Failed to read MSI data count."); 1975 ExitOnFailure(hr, "Failed to read MSI data count.");
@@ -2102,7 +2133,8 @@ static HRESULT ProcessElevatedChildMessage(
2102 HRESULT hr = S_OK; 2133 HRESULT hr = S_OK;
2103 BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext = static_cast<BURN_ELEVATION_CHILD_MESSAGE_CONTEXT*>(pvContext); 2134 BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext = static_cast<BURN_ELEVATION_CHILD_MESSAGE_CONTEXT*>(pvContext);
2104 HRESULT hrResult = S_OK; 2135 HRESULT hrResult = S_OK;
2105 DWORD dwPid = 0; 2136 BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE;
2137 BOOL fSendRestart = FALSE;
2106 2138
2107 switch (pMsg->dwMessage) 2139 switch (pMsg->dwMessage)
2108 { 2140 {
@@ -2143,27 +2175,33 @@ static HRESULT ProcessElevatedChildMessage(
2143 break; 2175 break;
2144 2176
2145 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE: 2177 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE:
2146 hrResult = OnExecuteRelatedBundle(pContext->hPipe, pContext->pCache, &pContext->pRegistration->relatedBundles, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); 2178 hrResult = OnExecuteRelatedBundle(pContext->hPipe, pContext->pCache, &pContext->pRegistration->relatedBundles, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData, &restart);
2179 fSendRestart = TRUE;
2147 break; 2180 break;
2148 2181
2149 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_BUNDLE_PACKAGE: 2182 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_BUNDLE_PACKAGE:
2150 hrResult = OnExecuteBundlePackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); 2183 hrResult = OnExecuteBundlePackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData, &restart);
2184 fSendRestart = TRUE;
2151 break; 2185 break;
2152 2186
2153 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE: 2187 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE:
2154 hrResult = OnExecuteExePackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); 2188 hrResult = OnExecuteExePackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData, &restart);
2189 fSendRestart = TRUE;
2155 break; 2190 break;
2156 2191
2157 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE: 2192 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE:
2158 hrResult = OnExecuteMsiPackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); 2193 hrResult = OnExecuteMsiPackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData, &restart);
2194 fSendRestart = TRUE;
2159 break; 2195 break;
2160 2196
2161 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE: 2197 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE:
2162 hrResult = OnExecuteMspPackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); 2198 hrResult = OnExecuteMspPackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData, &restart);
2199 fSendRestart = TRUE;
2163 break; 2200 break;
2164 2201
2165 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSU_PACKAGE: 2202 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSU_PACKAGE:
2166 hrResult = OnExecuteMsuPackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); 2203 hrResult = OnExecuteMsuPackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData, &restart);
2204 fSendRestart = TRUE;
2167 break; 2205 break;
2168 2206
2169 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_PROVIDER: 2207 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_PROVIDER:
@@ -2183,7 +2221,8 @@ static HRESULT ProcessElevatedChildMessage(
2183 break; 2221 break;
2184 2222
2185 case BURN_ELEVATION_MESSAGE_TYPE_UNINSTALL_MSI_COMPATIBLE_PACKAGE: 2223 case BURN_ELEVATION_MESSAGE_TYPE_UNINSTALL_MSI_COMPATIBLE_PACKAGE:
2186 hrResult = OnUninstallMsiCompatiblePackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); 2224 hrResult = OnUninstallMsiCompatiblePackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData, &restart);
2225 fSendRestart = TRUE;
2187 break; 2226 break;
2188 2227
2189 case BURN_ELEVATION_MESSAGE_TYPE_CLEAN_COMPATIBLE_PACKAGE: 2228 case BURN_ELEVATION_MESSAGE_TYPE_CLEAN_COMPATIBLE_PACKAGE:
@@ -2191,11 +2230,16 @@ static HRESULT ProcessElevatedChildMessage(
2191 break; 2230 break;
2192 2231
2193 default: 2232 default:
2194 hr = E_INVALIDARG; 2233 ExitWithRootFailure(hr, E_INVALIDARG, "Unexpected elevated message sent to child process, msg: %u", pMsg->dwMessage);
2195 ExitOnRootFailure(hr, "Unexpected elevated message sent to child process, msg: %u", pMsg->dwMessage);
2196 } 2234 }
2197 2235
2198 *pdwResult = dwPid ? dwPid : (DWORD)hrResult; 2236 if (fSendRestart)
2237 {
2238 hr = ElevatedOnExecuteActionComplete(pContext->hPipe, restart);
2239 ExitOnFailure(hr, "ElevatedOnExecuteActionComplete failed.");
2240 }
2241
2242 *pdwResult = (DWORD)hrResult;
2199 2243
2200LExit: 2244LExit:
2201 return hr; 2245 return hr;
@@ -2245,23 +2289,22 @@ LExit:
2245 return hr; 2289 return hr;
2246} 2290}
2247 2291
2248static HRESULT ProcessResult( 2292static HRESULT ProcessExecuteActionCompleteMessage(
2249 __in DWORD dwResult, 2293 __in BYTE* pbData,
2250 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 2294 __in DWORD cbData,
2295 __out BOOTSTRAPPER_APPLY_RESTART* pRestart,
2296 __out DWORD* pdwResult
2251 ) 2297 )
2252{ 2298{
2253 HRESULT hr = static_cast<HRESULT>(dwResult); 2299 HRESULT hr = S_OK;
2254 if (HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED) == hr) 2300 SIZE_T iData = 0;
2255 { 2301
2256 *pRestart = BOOTSTRAPPER_APPLY_RESTART_REQUIRED; 2302 hr = BuffReadNumber(pbData, cbData, &iData, reinterpret_cast<DWORD*>(pRestart));
2257 hr = S_OK; 2303 ExitOnFailure(hr, "Failed to read execute action restart result.");
2258 } 2304
2259 else if (HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED) == hr) 2305 *pdwResult = (DWORD)hr;
2260 {
2261 *pRestart = BOOTSTRAPPER_APPLY_RESTART_INITIATED;
2262 hr = S_OK;
2263 }
2264 2306
2307LExit:
2265 return hr; 2308 return hr;
2266} 2309}
2267 2310
@@ -2759,7 +2802,8 @@ static HRESULT OnExecuteRelatedBundle(
2759 __in BURN_RELATED_BUNDLES* pRelatedBundles, 2802 __in BURN_RELATED_BUNDLES* pRelatedBundles,
2760 __in BURN_VARIABLES* pVariables, 2803 __in BURN_VARIABLES* pVariables,
2761 __in BYTE* pbData, 2804 __in BYTE* pbData,
2762 __in SIZE_T cbData 2805 __in SIZE_T cbData,
2806 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
2763 ) 2807 )
2764{ 2808{
2765 HRESULT hr = S_OK; 2809 HRESULT hr = S_OK;
@@ -2771,7 +2815,7 @@ static HRESULT OnExecuteRelatedBundle(
2771 LPWSTR sczIgnoreDependencies = NULL; 2815 LPWSTR sczIgnoreDependencies = NULL;
2772 LPWSTR sczAncestors = NULL; 2816 LPWSTR sczAncestors = NULL;
2773 LPWSTR sczEngineWorkingDirectory = NULL; 2817 LPWSTR sczEngineWorkingDirectory = NULL;
2774 BOOTSTRAPPER_APPLY_RESTART bundleRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; 2818 *pRestart = BOOTSTRAPPER_APPLY_RESTART_NONE;
2775 2819
2776 executeAction.type = BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE; 2820 executeAction.type = BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE;
2777 2821
@@ -2826,7 +2870,7 @@ static HRESULT OnExecuteRelatedBundle(
2826 } 2870 }
2827 2871
2828 // Execute related bundle. 2872 // Execute related bundle.
2829 hr = BundlePackageEngineExecuteRelatedBundle(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, &bundleRestart); 2873 hr = BundlePackageEngineExecuteRelatedBundle(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, pRestart);
2830 ExitOnFailure(hr, "Failed to execute related bundle."); 2874 ExitOnFailure(hr, "Failed to execute related bundle.");
2831 2875
2832LExit: 2876LExit:
@@ -2836,18 +2880,6 @@ LExit:
2836 ReleaseStr(sczPackage); 2880 ReleaseStr(sczPackage);
2837 PlanUninitializeExecuteAction(&executeAction); 2881 PlanUninitializeExecuteAction(&executeAction);
2838 2882
2839 if (SUCCEEDED(hr))
2840 {
2841 if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == bundleRestart)
2842 {
2843 hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED);
2844 }
2845 else if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == bundleRestart)
2846 {
2847 hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED);
2848 }
2849 }
2850
2851 return hr; 2883 return hr;
2852} 2884}
2853 2885
@@ -2857,7 +2889,8 @@ static HRESULT OnExecuteBundlePackage(
2857 __in BURN_PACKAGES* pPackages, 2889 __in BURN_PACKAGES* pPackages,
2858 __in BURN_VARIABLES* pVariables, 2890 __in BURN_VARIABLES* pVariables,
2859 __in BYTE* pbData, 2891 __in BYTE* pbData,
2860 __in SIZE_T cbData 2892 __in SIZE_T cbData,
2893 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
2861 ) 2894 )
2862{ 2895{
2863 HRESULT hr = S_OK; 2896 HRESULT hr = S_OK;
@@ -2869,7 +2902,7 @@ static HRESULT OnExecuteBundlePackage(
2869 LPWSTR sczIgnoreDependencies = NULL; 2902 LPWSTR sczIgnoreDependencies = NULL;
2870 LPWSTR sczAncestors = NULL; 2903 LPWSTR sczAncestors = NULL;
2871 LPWSTR sczEngineWorkingDirectory = NULL; 2904 LPWSTR sczEngineWorkingDirectory = NULL;
2872 BOOTSTRAPPER_APPLY_RESTART bundleRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; 2905 *pRestart = BOOTSTRAPPER_APPLY_RESTART_NONE;
2873 2906
2874 executeAction.type = BURN_EXECUTE_ACTION_TYPE_BUNDLE_PACKAGE; 2907 executeAction.type = BURN_EXECUTE_ACTION_TYPE_BUNDLE_PACKAGE;
2875 2908
@@ -2930,7 +2963,7 @@ static HRESULT OnExecuteBundlePackage(
2930 } 2963 }
2931 2964
2932 // Execute BUNDLE package. 2965 // Execute BUNDLE package.
2933 hr = BundlePackageEngineExecutePackage(&executeAction, pCache, pVariables, fRollback, fCacheAvailable, GenericExecuteMessageHandler, hPipe, &bundleRestart); 2966 hr = BundlePackageEngineExecutePackage(&executeAction, pCache, pVariables, fRollback, fCacheAvailable, GenericExecuteMessageHandler, hPipe, pRestart);
2934 ExitOnFailure(hr, "Failed to execute BUNDLE package."); 2967 ExitOnFailure(hr, "Failed to execute BUNDLE package.");
2935 2968
2936LExit: 2969LExit:
@@ -2940,18 +2973,6 @@ LExit:
2940 ReleaseStr(sczPackage); 2973 ReleaseStr(sczPackage);
2941 PlanUninitializeExecuteAction(&executeAction); 2974 PlanUninitializeExecuteAction(&executeAction);
2942 2975
2943 if (SUCCEEDED(hr))
2944 {
2945 if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == bundleRestart)
2946 {
2947 hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED);
2948 }
2949 else if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == bundleRestart)
2950 {
2951 hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED);
2952 }
2953 }
2954
2955 return hr; 2976 return hr;
2956} 2977}
2957 2978
@@ -2961,7 +2982,8 @@ static HRESULT OnExecuteExePackage(
2961 __in BURN_PACKAGES* pPackages, 2982 __in BURN_PACKAGES* pPackages,
2962 __in BURN_VARIABLES* pVariables, 2983 __in BURN_VARIABLES* pVariables,
2963 __in BYTE* pbData, 2984 __in BYTE* pbData,
2964 __in SIZE_T cbData 2985 __in SIZE_T cbData,
2986 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
2965 ) 2987 )
2966{ 2988{
2967 HRESULT hr = S_OK; 2989 HRESULT hr = S_OK;
@@ -2971,7 +2993,7 @@ static HRESULT OnExecuteExePackage(
2971 BURN_EXECUTE_ACTION executeAction = { }; 2993 BURN_EXECUTE_ACTION executeAction = { };
2972 LPWSTR sczAncestors = NULL; 2994 LPWSTR sczAncestors = NULL;
2973 LPWSTR sczEngineWorkingDirectory = NULL; 2995 LPWSTR sczEngineWorkingDirectory = NULL;
2974 BOOTSTRAPPER_APPLY_RESTART exeRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; 2996 *pRestart = BOOTSTRAPPER_APPLY_RESTART_NONE;
2975 2997
2976 executeAction.type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE; 2998 executeAction.type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE;
2977 2999
@@ -3016,7 +3038,7 @@ static HRESULT OnExecuteExePackage(
3016 } 3038 }
3017 3039
3018 // Execute EXE package. 3040 // Execute EXE package.
3019 hr = ExeEngineExecutePackage(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, &exeRestart); 3041 hr = ExeEngineExecutePackage(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, pRestart);
3020 ExitOnFailure(hr, "Failed to execute EXE package."); 3042 ExitOnFailure(hr, "Failed to execute EXE package.");
3021 3043
3022LExit: 3044LExit:
@@ -3025,18 +3047,6 @@ LExit:
3025 ReleaseStr(sczPackage); 3047 ReleaseStr(sczPackage);
3026 PlanUninitializeExecuteAction(&executeAction); 3048 PlanUninitializeExecuteAction(&executeAction);
3027 3049
3028 if (SUCCEEDED(hr))
3029 {
3030 if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == exeRestart)
3031 {
3032 hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED);
3033 }
3034 else if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == exeRestart)
3035 {
3036 hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED);
3037 }
3038 }
3039
3040 return hr; 3050 return hr;
3041} 3051}
3042 3052
@@ -3046,7 +3056,8 @@ static HRESULT OnExecuteMsiPackage(
3046 __in BURN_PACKAGES* pPackages, 3056 __in BURN_PACKAGES* pPackages,
3047 __in BURN_VARIABLES* pVariables, 3057 __in BURN_VARIABLES* pVariables,
3048 __in BYTE* pbData, 3058 __in BYTE* pbData,
3049 __in SIZE_T cbData 3059 __in SIZE_T cbData,
3060 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
3050 ) 3061 )
3051{ 3062{
3052 HRESULT hr = S_OK; 3063 HRESULT hr = S_OK;
@@ -3055,7 +3066,7 @@ static HRESULT OnExecuteMsiPackage(
3055 HWND hwndParent = NULL; 3066 HWND hwndParent = NULL;
3056 BOOL fRollback = FALSE; 3067 BOOL fRollback = FALSE;
3057 BURN_EXECUTE_ACTION executeAction = { }; 3068 BURN_EXECUTE_ACTION executeAction = { };
3058 BOOTSTRAPPER_APPLY_RESTART msiRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; 3069 *pRestart = BOOTSTRAPPER_APPLY_RESTART_NONE;
3059 3070
3060 executeAction.type = BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE; 3071 executeAction.type = BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE;
3061 3072
@@ -3124,25 +3135,13 @@ static HRESULT OnExecuteMsiPackage(
3124 } 3135 }
3125 3136
3126 // Execute MSI package. 3137 // Execute MSI package.
3127 hr = MsiEngineExecutePackage(hwndParent, &executeAction, pCache, pVariables, fRollback, MsiExecuteMessageHandler, hPipe, &msiRestart); 3138 hr = MsiEngineExecutePackage(hwndParent, &executeAction, pCache, pVariables, fRollback, MsiExecuteMessageHandler, hPipe, pRestart);
3128 ExitOnFailure(hr, "Failed to execute MSI package."); 3139 ExitOnFailure(hr, "Failed to execute MSI package.");
3129 3140
3130LExit: 3141LExit:
3131 ReleaseStr(sczPackage); 3142 ReleaseStr(sczPackage);
3132 PlanUninitializeExecuteAction(&executeAction); 3143 PlanUninitializeExecuteAction(&executeAction);
3133 3144
3134 if (SUCCEEDED(hr))
3135 {
3136 if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == msiRestart)
3137 {
3138 hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED);
3139 }
3140 else if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == msiRestart)
3141 {
3142 hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED);
3143 }
3144 }
3145
3146 return hr; 3145 return hr;
3147} 3146}
3148 3147
@@ -3152,7 +3151,8 @@ static HRESULT OnExecuteMspPackage(
3152 __in BURN_PACKAGES* pPackages, 3151 __in BURN_PACKAGES* pPackages,
3153 __in BURN_VARIABLES* pVariables, 3152 __in BURN_VARIABLES* pVariables,
3154 __in BYTE* pbData, 3153 __in BYTE* pbData,
3155 __in SIZE_T cbData 3154 __in SIZE_T cbData,
3155 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
3156 ) 3156 )
3157{ 3157{
3158 HRESULT hr = S_OK; 3158 HRESULT hr = S_OK;
@@ -3161,7 +3161,7 @@ static HRESULT OnExecuteMspPackage(
3161 HWND hwndParent = NULL; 3161 HWND hwndParent = NULL;
3162 BOOL fRollback = FALSE; 3162 BOOL fRollback = FALSE;
3163 BURN_EXECUTE_ACTION executeAction = { }; 3163 BURN_EXECUTE_ACTION executeAction = { };
3164 BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE; 3164 *pRestart = BOOTSTRAPPER_APPLY_RESTART_NONE;
3165 3165
3166 executeAction.type = BURN_EXECUTE_ACTION_TYPE_MSP_TARGET; 3166 executeAction.type = BURN_EXECUTE_ACTION_TYPE_MSP_TARGET;
3167 3167
@@ -3228,25 +3228,13 @@ static HRESULT OnExecuteMspPackage(
3228 } 3228 }
3229 3229
3230 // Execute MSP package. 3230 // Execute MSP package.
3231 hr = MspEngineExecutePackage(hwndParent, &executeAction, pCache, pVariables, fRollback, MsiExecuteMessageHandler, hPipe, &restart); 3231 hr = MspEngineExecutePackage(hwndParent, &executeAction, pCache, pVariables, fRollback, MsiExecuteMessageHandler, hPipe, pRestart);
3232 ExitOnFailure(hr, "Failed to execute MSP package."); 3232 ExitOnFailure(hr, "Failed to execute MSP package.");
3233 3233
3234LExit: 3234LExit:
3235 ReleaseStr(sczPackage); 3235 ReleaseStr(sczPackage);
3236 PlanUninitializeExecuteAction(&executeAction); 3236 PlanUninitializeExecuteAction(&executeAction);
3237 3237
3238 if (SUCCEEDED(hr))
3239 {
3240 if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == restart)
3241 {
3242 hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED);
3243 }
3244 else if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == restart)
3245 {
3246 hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED);
3247 }
3248 }
3249
3250 return hr; 3238 return hr;
3251} 3239}
3252 3240
@@ -3256,7 +3244,8 @@ static HRESULT OnExecuteMsuPackage(
3256 __in BURN_PACKAGES* pPackages, 3244 __in BURN_PACKAGES* pPackages,
3257 __in BURN_VARIABLES* pVariables, 3245 __in BURN_VARIABLES* pVariables,
3258 __in BYTE* pbData, 3246 __in BYTE* pbData,
3259 __in SIZE_T cbData 3247 __in SIZE_T cbData,
3248 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
3260 ) 3249 )
3261{ 3250{
3262 HRESULT hr = S_OK; 3251 HRESULT hr = S_OK;
@@ -3265,7 +3254,7 @@ static HRESULT OnExecuteMsuPackage(
3265 DWORD dwRollback = 0; 3254 DWORD dwRollback = 0;
3266 DWORD dwStopWusaService = 0; 3255 DWORD dwStopWusaService = 0;
3267 BURN_EXECUTE_ACTION executeAction = { }; 3256 BURN_EXECUTE_ACTION executeAction = { };
3268 BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE; 3257 *pRestart = BOOTSTRAPPER_APPLY_RESTART_NONE;
3269 3258
3270 executeAction.type = BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE; 3259 executeAction.type = BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE;
3271 3260
@@ -3294,25 +3283,13 @@ static HRESULT OnExecuteMsuPackage(
3294 } 3283 }
3295 3284
3296 // execute MSU package 3285 // execute MSU package
3297 hr = MsuEngineExecutePackage(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), static_cast<BOOL>(dwStopWusaService), GenericExecuteMessageHandler, hPipe, &restart); 3286 hr = MsuEngineExecutePackage(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), static_cast<BOOL>(dwStopWusaService), GenericExecuteMessageHandler, hPipe, pRestart);
3298 ExitOnFailure(hr, "Failed to execute MSU package."); 3287 ExitOnFailure(hr, "Failed to execute MSU package.");
3299 3288
3300LExit: 3289LExit:
3301 ReleaseStr(sczPackage); 3290 ReleaseStr(sczPackage);
3302 PlanUninitializeExecuteAction(&executeAction); 3291 PlanUninitializeExecuteAction(&executeAction);
3303 3292
3304 if (SUCCEEDED(hr))
3305 {
3306 if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == restart)
3307 {
3308 hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED);
3309 }
3310 else if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == restart)
3311 {
3312 hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED);
3313 }
3314 }
3315
3316 return hr; 3293 return hr;
3317} 3294}
3318 3295
@@ -3322,7 +3299,8 @@ static HRESULT OnUninstallMsiCompatiblePackage(
3322 __in BURN_PACKAGES* pPackages, 3299 __in BURN_PACKAGES* pPackages,
3323 __in BURN_VARIABLES* pVariables, 3300 __in BURN_VARIABLES* pVariables,
3324 __in BYTE* pbData, 3301 __in BYTE* pbData,
3325 __in SIZE_T cbData 3302 __in SIZE_T cbData,
3303 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
3326 ) 3304 )
3327{ 3305{
3328 HRESULT hr = S_OK; 3306 HRESULT hr = S_OK;
@@ -3334,7 +3312,7 @@ static HRESULT OnUninstallMsiCompatiblePackage(
3334 BURN_EXECUTE_ACTION executeAction = { }; 3312 BURN_EXECUTE_ACTION executeAction = { };
3335 BURN_PACKAGE* pPackage = NULL; 3313 BURN_PACKAGE* pPackage = NULL;
3336 BURN_COMPATIBLE_PACKAGE* pCompatiblePackage = NULL; 3314 BURN_COMPATIBLE_PACKAGE* pCompatiblePackage = NULL;
3337 BOOTSTRAPPER_APPLY_RESTART msiRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; 3315 *pRestart = BOOTSTRAPPER_APPLY_RESTART_NONE;
3338 3316
3339 executeAction.type = BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE; 3317 executeAction.type = BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE;
3340 3318
@@ -3375,26 +3353,14 @@ static HRESULT OnUninstallMsiCompatiblePackage(
3375 } 3353 }
3376 3354
3377 // Uninstall MSI compatible package. 3355 // Uninstall MSI compatible package.
3378 hr = MsiEngineUninstallCompatiblePackage(hwndParent, &executeAction, pCache, pVariables, fRollback, MsiExecuteMessageHandler, hPipe, &msiRestart); 3356 hr = MsiEngineUninstallCompatiblePackage(hwndParent, &executeAction, pCache, pVariables, fRollback, MsiExecuteMessageHandler, hPipe, pRestart);
3379 ExitOnFailure(hr, "Failed to execute MSI package."); 3357 ExitOnFailure(hr, "Failed to execute compatible MSI package.");
3380 3358
3381LExit: 3359LExit:
3382 ReleaseStr(sczPackageId); 3360 ReleaseStr(sczPackageId);
3383 ReleaseStr(sczCompatiblePackageId); 3361 ReleaseStr(sczCompatiblePackageId);
3384 PlanUninitializeExecuteAction(&executeAction); 3362 PlanUninitializeExecuteAction(&executeAction);
3385 3363
3386 if (SUCCEEDED(hr))
3387 {
3388 if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == msiRestart)
3389 {
3390 hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED);
3391 }
3392 else if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == msiRestart)
3393 {
3394 hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED);
3395 }
3396 }
3397
3398 return hr; 3364 return hr;
3399} 3365}
3400 3366
@@ -4096,3 +4062,25 @@ LExit:
4096 4062
4097 return hr; 4063 return hr;
4098} 4064}
4065
4066static HRESULT ElevatedOnExecuteActionComplete(
4067 __in HANDLE hPipe,
4068 __in BOOTSTRAPPER_APPLY_RESTART restart
4069 )
4070{
4071 HRESULT hr = S_OK;
4072 BYTE* pbSendData = NULL;
4073 SIZE_T cbSendData = 0;
4074 DWORD dwResult = 0;
4075
4076 hr = BuffWriteNumber(&pbSendData, &cbSendData, restart);
4077 ExitOnFailure(hr, "Failed to write the restart type to message buffer.");
4078
4079 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ACTION_COMPLETE, pbSendData, cbSendData, NULL, NULL, &dwResult);
4080 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ACTION_COMPLETE message to per-user process.");
4081
4082LExit:
4083 ReleaseBuffer(pbSendData);
4084
4085 return hr;
4086}
diff --git a/src/burn/engine/engine.mc b/src/burn/engine/engine.mc
index 08269ea0..41c17270 100644
--- a/src/burn/engine/engine.mc
+++ b/src/burn/engine/engine.mc
@@ -982,6 +982,13 @@ Language=English
982Skipping rollback of package: %1!ls! due to abandoning its process. Continuing... 982Skipping rollback of package: %1!ls! due to abandoning its process. Continuing...
983. 983.
984 984
985MessageId=366
986Severity=Success
987SymbolicName=MSG_EXECUTE_PACKAGE_PROCESS_EXITED
988Language=English
989The process for package: %1!ls! exited with code: %2!u!. The exit code has been translated to type: %3!hs! and restart: %4!hs!.
990.
991
985MessageId=370 992MessageId=370
986Severity=Success 993Severity=Success
987SymbolicName=MSG_SESSION_BEGIN 994SymbolicName=MSG_SESSION_BEGIN
diff --git a/src/burn/engine/exeengine.cpp b/src/burn/engine/exeengine.cpp
index b4898d42..3cb9c72a 100644
--- a/src/burn/engine/exeengine.cpp
+++ b/src/burn/engine/exeengine.cpp
@@ -648,7 +648,7 @@ extern "C" HRESULT ExeEngineExecutePackage(
648 ExitOnFailure(hr, "Failed to run EXE process"); 648 ExitOnFailure(hr, "Failed to run EXE process");
649 } 649 }
650 650
651 hr = ExeEngineHandleExitCode(pPackage->Exe.rgExitCodes, pPackage->Exe.cExitCodes, dwExitCode, pRestart); 651 hr = ExeEngineHandleExitCode(pPackage->Exe.rgExitCodes, pPackage->Exe.cExitCodes, pPackage->sczId, dwExitCode, pRestart);
652 ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode); 652 ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode);
653 653
654LExit: 654LExit:
@@ -759,7 +759,7 @@ extern "C" HRESULT ExeEngineRunProcess(
759 hr = (IDOK == nResult || IDNOACTION == nResult) ? S_OK : IDCANCEL == nResult ? HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) : HRESULT_FROM_WIN32(ERROR_INSTALL_FAILURE); 759 hr = (IDOK == nResult || IDNOACTION == nResult) ? S_OK : IDCANCEL == nResult ? HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) : HRESULT_FROM_WIN32(ERROR_INSTALL_FAILURE);
760 ExitOnRootFailure(hr, "Bootstrapper application aborted during package process progress."); 760 ExitOnRootFailure(hr, "Bootstrapper application aborted during package process progress.");
761 761
762 hr = ProcWaitForCompletion(pi.hProcess, 500, pdwExitCode); 762 hr = CoreWaitForProcCompletion(pi.hProcess, 500, pdwExitCode);
763 if (HRESULT_FROM_WIN32(WAIT_TIMEOUT) != hr) 763 if (HRESULT_FROM_WIN32(WAIT_TIMEOUT) != hr)
764 { 764 {
765 ExitOnFailure(hr, "Failed to wait for executable to complete: %ls", wzExecutablePath); 765 ExitOnFailure(hr, "Failed to wait for executable to complete: %ls", wzExecutablePath);
@@ -948,6 +948,7 @@ LExit:
948extern "C" HRESULT ExeEngineHandleExitCode( 948extern "C" HRESULT ExeEngineHandleExitCode(
949 __in BURN_EXE_EXIT_CODE* rgCustomExitCodes, 949 __in BURN_EXE_EXIT_CODE* rgCustomExitCodes,
950 __in DWORD cCustomExitCodes, 950 __in DWORD cCustomExitCodes,
951 __in_z LPCWSTR wzId,
951 __in DWORD dwExitCode, 952 __in DWORD dwExitCode,
952 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 953 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
953 ) 954 )
@@ -1029,6 +1030,8 @@ extern "C" HRESULT ExeEngineHandleExitCode(
1029 } 1030 }
1030 1031
1031//LExit: 1032//LExit:
1033 LogId(REPORT_STANDARD, MSG_EXECUTE_PACKAGE_PROCESS_EXITED, wzId, dwExitCode, LoggingExitCodeTypeToString(typeCode), LoggingRestartToString(*pRestart));
1034
1032 return hr; 1035 return hr;
1033} 1036}
1034 1037
diff --git a/src/burn/engine/exeengine.h b/src/burn/engine/exeengine.h
index b74d5c9a..75eb9dc2 100644
--- a/src/burn/engine/exeengine.h
+++ b/src/burn/engine/exeengine.h
@@ -69,6 +69,7 @@ HRESULT ExeEngineParseCommandLineArgumentsFromXml(
69HRESULT ExeEngineHandleExitCode( 69HRESULT ExeEngineHandleExitCode(
70 __in BURN_EXE_EXIT_CODE* rgCustomExitCodes, 70 __in BURN_EXE_EXIT_CODE* rgCustomExitCodes,
71 __in DWORD cCustomExitCodes, 71 __in DWORD cCustomExitCodes,
72 __in_z LPCWSTR wzId,
72 __in DWORD dwExitCode, 73 __in DWORD dwExitCode,
73 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 74 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
74 ); 75 );
diff --git a/src/burn/engine/logging.cpp b/src/burn/engine/logging.cpp
index 885e2c84..38c9d2d5 100644
--- a/src/burn/engine/logging.cpp
+++ b/src/burn/engine/logging.cpp
@@ -531,6 +531,25 @@ extern "C" LPCSTR LoggingTrueFalseToString(
531 return "false"; 531 return "false";
532} 532}
533 533
534extern "C" LPCSTR LoggingExitCodeTypeToString(
535 __in BURN_EXE_EXIT_CODE_TYPE exitCodeType
536 )
537{
538 switch (exitCodeType)
539 {
540 case BURN_EXE_EXIT_CODE_TYPE_SUCCESS:
541 return "Success";
542 case BURN_EXE_EXIT_CODE_TYPE_ERROR:
543 return "Error";
544 case BURN_EXE_EXIT_CODE_TYPE_SCHEDULE_REBOOT:
545 return "ScheduleReboot";
546 case BURN_EXE_EXIT_CODE_TYPE_FORCE_REBOOT:
547 return "ForceReboot";
548 default:
549 return "Invalid";
550 }
551}
552
534extern "C" LPCSTR LoggingPackageStateToString( 553extern "C" LPCSTR LoggingPackageStateToString(
535 __in BOOTSTRAPPER_PACKAGE_STATE packageState 554 __in BOOTSTRAPPER_PACKAGE_STATE packageState
536 ) 555 )
diff --git a/src/burn/engine/logging.h b/src/burn/engine/logging.h
index 5597bb57..1b4a7b7f 100644
--- a/src/burn/engine/logging.h
+++ b/src/burn/engine/logging.h
@@ -112,6 +112,10 @@ LPCSTR LoggingTrueFalseToString(
112 __in BOOL f 112 __in BOOL f
113 ); 113 );
114 114
115LPCSTR LoggingExitCodeTypeToString(
116 __in BURN_EXE_EXIT_CODE_TYPE exitCodeType
117 );
118
115LPCSTR LoggingPackageStateToString( 119LPCSTR LoggingPackageStateToString(
116 __in BOOTSTRAPPER_PACKAGE_STATE packageState 120 __in BOOTSTRAPPER_PACKAGE_STATE packageState
117 ); 121 );
diff --git a/src/burn/engine/pipe.cpp b/src/burn/engine/pipe.cpp
index 19bdcaa2..5003622c 100644
--- a/src/burn/engine/pipe.cpp
+++ b/src/burn/engine/pipe.cpp
@@ -495,7 +495,7 @@ extern "C" HRESULT PipeTerminateChildProcess(
495 HRESULT hrDebug = S_OK; 495 HRESULT hrDebug = S_OK;
496 496
497 hrDebug = CoreWaitForProcCompletion(pConnection->hProcess, 0, &dwChildExitCode); 497 hrDebug = CoreWaitForProcCompletion(pConnection->hProcess, 0, &dwChildExitCode);
498 if (E_ACCESSDENIED != hrDebug) // if the other process is elevated and we are not, then we'll get ERROR_ACCESS_DENIED. 498 if (E_ACCESSDENIED != hrDebug && FAILED(hrDebug)) // if the other process is elevated and we are not, then we'll get ERROR_ACCESS_DENIED.
499 { 499 {
500 TraceError(hrDebug, "Failed to wait for child process completion."); 500 TraceError(hrDebug, "Failed to wait for child process completion.");
501 } 501 }
diff --git a/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj b/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj
index 04491608..fe86f042 100644
--- a/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj
+++ b/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj
@@ -48,6 +48,7 @@
48 <ClCompile Include="CacheTest.cpp" /> 48 <ClCompile Include="CacheTest.cpp" />
49 <ClCompile Include="ElevationTest.cpp" /> 49 <ClCompile Include="ElevationTest.cpp" />
50 <ClCompile Include="EmbeddedTest.cpp" /> 50 <ClCompile Include="EmbeddedTest.cpp" />
51 <ClCompile Include="ExitCodeTest.cpp" />
51 <ClCompile Include="LoggingTest.cpp" /> 52 <ClCompile Include="LoggingTest.cpp" />
52 <ClCompile Include="ManifestHelpers.cpp" /> 53 <ClCompile Include="ManifestHelpers.cpp" />
53 <ClCompile Include="ManifestTest.cpp" /> 54 <ClCompile Include="ManifestTest.cpp" />
diff --git a/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj.filters b/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj.filters
index 19061009..82725436 100644
--- a/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj.filters
+++ b/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj.filters
@@ -27,6 +27,9 @@
27 <ClCompile Include="EmbeddedTest.cpp"> 27 <ClCompile Include="EmbeddedTest.cpp">
28 <Filter>Source Files</Filter> 28 <Filter>Source Files</Filter>
29 </ClCompile> 29 </ClCompile>
30 <ClCompile Include="ExitCodeTest.cpp">
31 <Filter>Source Files</Filter>
32 </ClCompile>
30 <ClCompile Include="LoggingTest.cpp"> 33 <ClCompile Include="LoggingTest.cpp">
31 <Filter>Source Files</Filter> 34 <Filter>Source Files</Filter>
32 </ClCompile> 35 </ClCompile>
diff --git a/src/burn/test/BurnUnitTest/ExitCodeTest.cpp b/src/burn/test/BurnUnitTest/ExitCodeTest.cpp
new file mode 100644
index 00000000..2c32c6ab
--- /dev/null
+++ b/src/burn/test/BurnUnitTest/ExitCodeTest.cpp
@@ -0,0 +1,361 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3#include "precomp.h"
4
5
6namespace Microsoft
7{
8namespace Tools
9{
10namespace WindowsInstallerXml
11{
12namespace Test
13{
14namespace Bootstrapper
15{
16 using namespace System;
17 using namespace System::IO;
18 using namespace System::Threading;
19 using namespace Xunit;
20
21struct EXIT_CODE_ITEM
22{
23 DWORD dwExitCode;
24 HRESULT hrExpectedResult;
25 BOOTSTRAPPER_APPLY_RESTART expectedRestart;
26 LPCWSTR wzPackageId;
27 HRESULT hrResultPerUser;
28 BOOTSTRAPPER_APPLY_RESTART restartPerUser;
29 HRESULT hrResultPerMachine;
30 BOOTSTRAPPER_APPLY_RESTART restartPerMachine;
31};
32
33static BOOL STDAPICALLTYPE ExitCodeTest_ShellExecuteExW(
34 __inout LPSHELLEXECUTEINFOW lpExecInfo
35 );
36static DWORD CALLBACK ExitCodeTest_ElevationThreadProc(
37 __in LPVOID lpThreadParameter
38 );
39static BOOL STDAPICALLTYPE ExitCodeTest_CreateProcessW(
40 __in_opt LPCWSTR lpApplicationName,
41 __inout_opt LPWSTR lpCommandLine,
42 __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
43 __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
44 __in BOOL bInheritHandles,
45 __in DWORD dwCreationFlags,
46 __in_opt LPVOID lpEnvironment,
47 __in_opt LPCWSTR lpCurrentDirectory,
48 __in LPSTARTUPINFOW lpStartupInfo,
49 __out LPPROCESS_INFORMATION lpProcessInformation
50 );
51static DWORD CALLBACK ExitCodeTest_PackageThreadProc(
52 __in LPVOID lpThreadParameter
53 );
54static int ExitCodeTest_GenericMessageHandler(
55 __in GENERIC_EXECUTE_MESSAGE* pMessage,
56 __in LPVOID pvContext
57 );
58static void LoadEngineState(
59 __in BURN_ENGINE_STATE* pEngineState
60 );
61
62 public ref class ExitCodeTest : BurnUnitTest
63 {
64 public:
65 ExitCodeTest(BurnTestFixture^ fixture) : BurnUnitTest(fixture)
66 {
67 }
68
69 [Fact]
70 void ExitCodeHandlingTest()
71 {
72 HRESULT hr = S_OK;
73 BURN_ENGINE_STATE engineState = { };
74 BURN_PIPE_CONNECTION* pConnection = &engineState.companionConnection;
75 EXIT_CODE_ITEM rgExitCodeItems[] =
76 {
77 { 0, S_OK, BOOTSTRAPPER_APPLY_RESTART_NONE, L"Standard" },
78 { 1, HRESULT_FROM_WIN32(1), BOOTSTRAPPER_APPLY_RESTART_NONE, L"Standard" },
79 { ERROR_SUCCESS_REBOOT_REQUIRED, S_OK, BOOTSTRAPPER_APPLY_RESTART_REQUIRED, L"Standard" },
80 { (DWORD)HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED), S_OK, BOOTSTRAPPER_APPLY_RESTART_REQUIRED, L"Standard" },
81 { ERROR_SUCCESS_RESTART_REQUIRED, S_OK, BOOTSTRAPPER_APPLY_RESTART_REQUIRED, L"Standard" },
82 { (DWORD)HRESULT_FROM_WIN32(ERROR_SUCCESS_RESTART_REQUIRED), S_OK, BOOTSTRAPPER_APPLY_RESTART_REQUIRED, L"Standard" },
83 { ERROR_SUCCESS_REBOOT_INITIATED, S_OK, BOOTSTRAPPER_APPLY_RESTART_INITIATED, L"Standard" },
84 { (DWORD)HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED), S_OK, BOOTSTRAPPER_APPLY_RESTART_INITIATED, L"Standard" },
85 { 0, E_FAIL, BOOTSTRAPPER_APPLY_RESTART_NONE, L"Custom" },
86 { 1, S_OK, BOOTSTRAPPER_APPLY_RESTART_NONE, L"Custom" },
87 { 3, S_OK, BOOTSTRAPPER_APPLY_RESTART_REQUIRED, L"Custom" },
88 { 4, S_OK, BOOTSTRAPPER_APPLY_RESTART_INITIATED, L"Custom" },
89 { ERROR_SUCCESS_REBOOT_REQUIRED, HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED), BOOTSTRAPPER_APPLY_RESTART_NONE, L"Custom" },
90 { (DWORD)HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED), HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED), BOOTSTRAPPER_APPLY_RESTART_NONE, L"Custom" },
91 { ERROR_SUCCESS_RESTART_REQUIRED, HRESULT_FROM_WIN32(ERROR_SUCCESS_RESTART_REQUIRED), BOOTSTRAPPER_APPLY_RESTART_NONE, L"Custom" },
92 { (DWORD)HRESULT_FROM_WIN32(ERROR_SUCCESS_RESTART_REQUIRED), HRESULT_FROM_WIN32(ERROR_SUCCESS_RESTART_REQUIRED), BOOTSTRAPPER_APPLY_RESTART_NONE, L"Custom" },
93 { ERROR_SUCCESS_REBOOT_INITIATED, HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED), BOOTSTRAPPER_APPLY_RESTART_NONE, L"Custom" },
94 { (DWORD)HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED), HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED), BOOTSTRAPPER_APPLY_RESTART_NONE, L"Custom" },
95 };
96
97 engineState.sczBundleEngineWorkingPath = L"tests\\ignore\\this\\path\\to\\burn.exe";
98
99 try
100 {
101 ShelFunctionOverride(ExitCodeTest_ShellExecuteExW);
102 CoreFunctionOverride(ExitCodeTest_CreateProcessW, ThrdWaitForCompletion);
103
104 //
105 // per-user side setup
106 //
107 LoadEngineState(&engineState);
108
109 hr = ElevationElevate(&engineState, NULL);
110 TestThrowOnFailure(hr, L"Failed to elevate.");
111
112 for (DWORD i = 0; i < countof(rgExitCodeItems); ++i)
113 {
114 // "run" the package both per-user and per-machine
115 ExecuteExePackage(&engineState, rgExitCodeItems + i);
116 }
117
118 //
119 // initiate termination
120 //
121 hr = PipeTerminateChildProcess(pConnection, 0, FALSE);
122 TestThrowOnFailure(hr, L"Failed to terminate elevated process.");
123
124 // check results
125 for (DWORD i = 0; i < countof(rgExitCodeItems); ++i)
126 {
127 EXIT_CODE_ITEM* pExitCode = rgExitCodeItems + i;
128 String^ packageId = gcnew String(pExitCode->wzPackageId);
129 String^ exitCodeString = ((UInt32)pExitCode->dwExitCode).ToString();
130
131 NativeAssert::SpecificReturnCode(pExitCode->hrExpectedResult, pExitCode->hrResultPerMachine, L"Per-machine package: {0}, exit code: {1}", packageId, exitCodeString);
132 Assert::True(pExitCode->expectedRestart == pExitCode->restartPerMachine, String::Format("Per-machine package: {0}, exit code: {1}, expected restart type '{2}' but got '{3}'", packageId, exitCodeString, gcnew String(LoggingRestartToString(pExitCode->expectedRestart)), gcnew String(LoggingRestartToString(pExitCode->restartPerMachine))));
133
134 NativeAssert::SpecificReturnCode(pExitCode->hrExpectedResult, pExitCode->hrResultPerUser, L"Per-user package: {0}, exit code: {1}", packageId, exitCodeString);
135 Assert::True(pExitCode->expectedRestart == pExitCode->restartPerUser, String::Format("Per-user package: {0}, exit code: {1}, expected restart type '{2}' but got '{3}'", packageId, exitCodeString, gcnew String(LoggingRestartToString(pExitCode->expectedRestart)), gcnew String(LoggingRestartToString(pExitCode->restartPerUser))));
136 }
137 }
138 finally
139 {
140 VariablesUninitialize(&engineState.variables);
141 PipeConnectionUninitialize(pConnection);
142 }
143 }
144
145 private:
146 void ExecuteExePackage(
147 __in BURN_ENGINE_STATE* pEngineState,
148 __in EXIT_CODE_ITEM* pExitCode
149 )
150 {
151 HRESULT hr = S_OK;
152 LPWSTR sczExitCode = NULL;
153 BURN_PACKAGE* pPackage = NULL;
154 BURN_EXECUTE_ACTION executeAction = { };
155 BURN_PIPE_CONNECTION* pConnection = &pEngineState->companionConnection;
156 BOOL fRollback = FALSE;
157
158 hr = PackageFindById(&pEngineState->packages, pExitCode->wzPackageId, &pPackage);
159 TestThrowOnFailure(hr, L"Failed to find package.");
160
161 executeAction.type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE;
162 executeAction.exePackage.action = BOOTSTRAPPER_ACTION_STATE_INSTALL;
163 executeAction.exePackage.pPackage = pPackage;
164
165 try
166 {
167 hr = StrAllocFormatted(&sczExitCode, L"%u", pExitCode->dwExitCode);
168 TestThrowOnFailure(hr, L"Failed to convert exit code to string.");
169
170 hr = VariableSetString(&pEngineState->variables, L"ExeExitCode", sczExitCode, FALSE, FALSE);
171 TestThrowOnFailure(hr, L"Failed to set variable.");
172
173 pExitCode->hrResultPerMachine = ElevationExecuteExePackage(pConnection->hPipe, &executeAction, &pEngineState->variables, fRollback, ExitCodeTest_GenericMessageHandler, NULL, &pExitCode->restartPerMachine);
174
175 pExitCode->hrResultPerUser = ExeEngineExecutePackage(&executeAction, &pEngineState->cache, &pEngineState->variables, fRollback, ExitCodeTest_GenericMessageHandler, NULL, &pExitCode->restartPerUser);
176 }
177 finally
178 {
179 ReleaseStr(sczExitCode);
180 }
181 }
182 };
183
184
185static BOOL STDAPICALLTYPE ExitCodeTest_ShellExecuteExW(
186 __inout LPSHELLEXECUTEINFOW lpExecInfo
187 )
188{
189 HRESULT hr = S_OK;
190 LPWSTR scz = NULL;
191
192 hr = StrAllocString(&scz, lpExecInfo->lpParameters, 0);
193 ExitOnFailure(hr, "Failed to copy arguments.");
194
195 // Pretend this thread is the elevated process.
196 lpExecInfo->hProcess = ::CreateThread(NULL, 0, ExitCodeTest_ElevationThreadProc, scz, 0, NULL);
197 ExitOnNullWithLastError(lpExecInfo->hProcess, hr, "Failed to create thread.");
198 scz = NULL;
199
200LExit:
201 ReleaseStr(scz);
202
203 return SUCCEEDED(hr);
204}
205
206static DWORD CALLBACK ExitCodeTest_ElevationThreadProc(
207 __in LPVOID lpThreadParameter
208 )
209{
210 HRESULT hr = S_OK;
211 LPWSTR sczArguments = (LPWSTR)lpThreadParameter;
212 BURN_ENGINE_STATE engineState = { };
213 BURN_PIPE_CONNECTION* pConnection = &engineState.companionConnection;
214 HANDLE hLock = NULL;
215 DWORD dwChildExitCode = 0;
216 BOOL fRestart = FALSE;
217 BOOL fApplying = FALSE;
218
219 LoadEngineState(&engineState);
220
221 StrAlloc(&pConnection->sczName, MAX_PATH);
222 StrAlloc(&pConnection->sczSecret, MAX_PATH);
223
224 // parse command line arguments
225 if (3 != swscanf_s(sczArguments, L"-q -burn.elevated %s %s %u", pConnection->sczName, MAX_PATH, pConnection->sczSecret, MAX_PATH, &pConnection->dwProcessId))
226 {
227 hr = E_INVALIDARG;
228 ExitOnFailure(hr, "Failed to parse argument string.");
229 }
230
231 // set up connection with per-user process
232 hr = PipeChildConnect(pConnection, TRUE);
233 ExitOnFailure(hr, "Failed to connect to per-user process.");
234
235 hr = ElevationChildPumpMessages(pConnection->hPipe, pConnection->hCachePipe, &engineState.approvedExes, &engineState.cache, &engineState.containers, &engineState.packages, &engineState.payloads, &engineState.variables, &engineState.registration, &engineState.userExperience, &hLock, &dwChildExitCode, &fRestart, &fApplying);
236 ExitOnFailure(hr, "Failed while pumping messages in child 'process'.");
237
238LExit:
239 PipeConnectionUninitialize(pConnection);
240 VariablesUninitialize(&engineState.variables);
241 ReleaseStr(sczArguments);
242
243 return FAILED(hr) ? (DWORD)hr : dwChildExitCode;
244}
245
246static BOOL STDAPICALLTYPE ExitCodeTest_CreateProcessW(
247 __in_opt LPCWSTR /*lpApplicationName*/,
248 __inout_opt LPWSTR lpCommandLine,
249 __in_opt LPSECURITY_ATTRIBUTES /*lpProcessAttributes*/,
250 __in_opt LPSECURITY_ATTRIBUTES /*lpThreadAttributes*/,
251 __in BOOL /*bInheritHandles*/,
252 __in DWORD /*dwCreationFlags*/,
253 __in_opt LPVOID /*lpEnvironment*/,
254 __in_opt LPCWSTR /*lpCurrentDirectory*/,
255 __in LPSTARTUPINFOW /*lpStartupInfo*/,
256 __out LPPROCESS_INFORMATION lpProcessInformation
257 )
258{
259 HRESULT hr = S_OK;
260 LPWSTR scz = NULL;
261 LPCWSTR wzArgs = lpCommandLine;
262
263 hr = StrAllocString(&scz, wzArgs, 0);
264 ExitOnFailure(hr, "Failed to copy arguments.");
265
266 // Pretend this thread is the package process.
267 lpProcessInformation->hProcess = ::CreateThread(NULL, 0, ExitCodeTest_PackageThreadProc, scz, 0, NULL);
268 ExitOnNullWithLastError(lpProcessInformation->hProcess, hr, "Failed to create thread.");
269
270 scz = NULL;
271
272LExit:
273 ReleaseStr(scz);
274
275 return SUCCEEDED(hr);
276}
277
278static DWORD CALLBACK ExitCodeTest_PackageThreadProc(
279 __in LPVOID lpThreadParameter
280 )
281{
282 HRESULT hr = S_OK;
283 LPWSTR sczArguments = (LPWSTR)lpThreadParameter;
284 int argc = 0;
285 LPWSTR* argv = NULL;
286 DWORD dwResult = 0;
287
288 hr = AppParseCommandLine(sczArguments, &argc, &argv);
289 ExitOnFailure(hr, "Failed to parse command line: %ls", sczArguments);
290
291 hr = StrStringToUInt32(argv[1], 0, reinterpret_cast<UINT*>(&dwResult));
292 ExitOnFailure(hr, "Failed to convert %ls to DWORD.", argv[1]);
293
294LExit:
295 AppFreeCommandLineArgs(argv);
296 ReleaseStr(sczArguments);
297
298 return FAILED(hr) ? (DWORD)hr : dwResult;
299}
300
301static int ExitCodeTest_GenericMessageHandler(
302 __in GENERIC_EXECUTE_MESSAGE* /*pMessage*/,
303 __in LPVOID /*pvContext*/
304 )
305{
306 return IDNOACTION;
307}
308
309static void LoadEngineState(
310 __in BURN_ENGINE_STATE* pEngineState
311 )
312{
313 HRESULT hr = S_OK;
314 IXMLDOMElement* pixeBundle = NULL;
315
316 LPCWSTR wzDocument =
317 L"<BurnManifest>"
318 L" <Payload Id='test.exe' FilePath='test.exe' Packaging='external' SourcePath='test.exe' Hash='000000000000' FileSize='1' />"
319 L" <Chain>"
320 L" <ExePackage Id='Custom' Cache='remove' CacheId='test.exe' InstallSize='1' Size='1' PerMachine='no' Permanent='yes' Vital='yes' DetectCondition='' InstallArguments='[ExeExitCode]' UninstallArguments='' Uninstallable='no' RepairArguments='' Repairable='no' Protocol='none' DetectionType='condition'>"
321 L" <ExitCode Code='0' Type='2' />"
322 L" <ExitCode Code='3' Type='3' />"
323 L" <ExitCode Code='4' Type='4' />"
324 L" <ExitCode Code='3010' Type='2' />"
325 L" <ExitCode Code='-2147021886' Type='2' />"
326 L" <ExitCode Code='3011' Type='2' />"
327 L" <ExitCode Code='-2147021885' Type='2' />"
328 L" <ExitCode Code='1641' Type='2' />"
329 L" <ExitCode Code='-2147023255' Type='2' />"
330 L" <ExitCode Code='*' Type='1' />"
331 L" <PayloadRef Id='test.exe' />"
332 L" </ExePackage>"
333 L" <ExePackage Id='Standard' Cache='remove' CacheId='test.exe' InstallSize='1' Size='1' PerMachine='no' Permanent='yes' Vital='yes' DetectCondition='' InstallArguments='[ExeExitCode]' UninstallArguments='' Uninstallable='no' RepairArguments='' Repairable='no' Protocol='none' DetectionType='condition'>"
334 L" <PayloadRef Id='test.exe' />"
335 L" </ExePackage>"
336 L" </Chain>"
337 L"</BurnManifest>";
338
339 VariableInitialize(&pEngineState->variables);
340
341 PipeConnectionInitialize(&pEngineState->companionConnection);
342
343 hr = CacheInitialize(&pEngineState->cache, &pEngineState->internalCommand);
344 TestThrowOnFailure(hr, "CacheInitialize failed.");
345
346 // load XML document
347 LoadBundleXmlHelper(wzDocument, &pixeBundle);
348
349 hr = PayloadsParseFromXml(&pEngineState->payloads, &pEngineState->containers, &pEngineState->layoutPayloads, pixeBundle);
350 TestThrowOnFailure(hr, "Failed to parse payloads from manifest.");
351
352 hr = PackagesParseFromXml(&pEngineState->packages, &pEngineState->payloads, pixeBundle);
353 TestThrowOnFailure(hr, "Failed to parse packages from manifest.");
354
355 ReleaseObject(pixeBundle);
356}
357}
358}
359}
360}
361}
diff --git a/src/burn/test/BurnUnitTest/precomp.h b/src/burn/test/BurnUnitTest/precomp.h
index 84e989a4..2b90cb58 100644
--- a/src/burn/test/BurnUnitTest/precomp.h
+++ b/src/burn/test/BurnUnitTest/precomp.h
@@ -13,6 +13,7 @@
13#include "wininet.h" 13#include "wininet.h"
14 14
15#include <dutil.h> 15#include <dutil.h>
16#include <apputil.h>
16#include <verutil.h> 17#include <verutil.h>
17#include <cryputil.h> 18#include <cryputil.h>
18#include <dlutil.h> 19#include <dlutil.h>
diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SpecificReturnCodeException.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SpecificReturnCodeException.cs
index c66890f8..c703e90a 100644
--- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SpecificReturnCodeException.cs
+++ b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SpecificReturnCodeException.cs
@@ -7,11 +7,12 @@ namespace WixBuildTools.TestSupport
7 7
8 public class SpecificReturnCodeException : XunitException 8 public class SpecificReturnCodeException : XunitException
9 { 9 {
10 public SpecificReturnCodeException(int hr, string userMessage) 10 public SpecificReturnCodeException(int hrExpected, int hr, string userMessage)
11 : base(String.Format("WixAssert.SpecificReturnCode() Failure\r\n" + 11 : base(String.Format("WixAssert.SpecificReturnCode() Failure\r\n" +
12 "HRESULT: 0x{0:X8}\r\n" + 12 "Expected HRESULT: 0x{0:X8}\r\n" +
13 "Message: {1}", 13 "Actual HRESULT: 0x{1:X8}\r\n" +
14 hr, userMessage)) 14 "Message: {2}",
15 hrExpected, hr, userMessage))
15 { 16 {
16 this.HResult = hr; 17 this.HResult = hr;
17 } 18 }
diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/WixAssert.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/WixAssert.cs
index d8d02746..a8513bfb 100644
--- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/WixAssert.cs
+++ b/src/internal/WixBuildTools.TestSupport/XunitExtensions/WixAssert.cs
@@ -58,7 +58,7 @@ namespace WixBuildTools.TestSupport
58 { 58 {
59 if (hrExpected != hr) 59 if (hrExpected != hr)
60 { 60 {
61 throw new SpecificReturnCodeException(hr, String.Format(format, formatArgs)); 61 throw new SpecificReturnCodeException(hrExpected, hr, String.Format(format, formatArgs));
62 } 62 }
63 } 63 }
64 64