aboutsummaryrefslogtreecommitdiff
path: root/src/burn
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-09-02 16:12:42 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-09-03 15:29:26 -0500
commit237bdc6a97c0dd455da99c16e6b3b7cac4c79e86 (patch)
tree1f2c789a7aa752e068fac8a4ca08815d13bf527a /src/burn
parent7728e34e48a4fdb710ecc92dd8dca833bff3993f (diff)
downloadwix-237bdc6a97c0dd455da99c16e6b3b7cac4c79e86.tar.gz
wix-237bdc6a97c0dd455da99c16e6b3b7cac4c79e86.tar.bz2
wix-237bdc6a97c0dd455da99c16e6b3b7cac4c79e86.zip
Add WixCanRestart and make wixstdba elevate for restart when required.
Fixes 5499
Diffstat (limited to 'src/burn')
-rw-r--r--src/burn/engine/EngineForApplication.h16
-rw-r--r--src/burn/engine/core.cpp7
-rw-r--r--src/burn/engine/core.h1
-rw-r--r--src/burn/engine/elevation.cpp7
-rw-r--r--src/burn/engine/elevation.h1
-rw-r--r--src/burn/engine/engine.cpp23
-rw-r--r--src/burn/engine/platform.h16
-rw-r--r--src/burn/engine/variable.cpp25
-rw-r--r--src/burn/test/BurnUnitTest/ElevationTest.cpp2
-rw-r--r--src/burn/test/BurnUnitTest/ExitCodeTest.cpp2
-rw-r--r--src/burn/test/BurnUnitTest/VariableTest.cpp1
11 files changed, 59 insertions, 42 deletions
diff --git a/src/burn/engine/EngineForApplication.h b/src/burn/engine/EngineForApplication.h
index e5e8f6d7..d25a7e51 100644
--- a/src/burn/engine/EngineForApplication.h
+++ b/src/burn/engine/EngineForApplication.h
@@ -6,22 +6,6 @@
6extern "C" { 6extern "C" {
7#endif 7#endif
8 8
9// constants
10
11enum WM_BURN
12{
13 WM_BURN_FIRST = WM_APP + 0xFFF, // this enum value must always be first.
14
15 WM_BURN_DETECT,
16 WM_BURN_PLAN,
17 WM_BURN_ELEVATE,
18 WM_BURN_APPLY,
19 WM_BURN_LAUNCH_APPROVED_EXE,
20 WM_BURN_QUIT,
21
22 WM_BURN_LAST, // this enum value must always be last.
23};
24
25// structs 9// structs
26 10
27typedef struct _BOOTSTRAPPER_ENGINE_CONTEXT 11typedef struct _BOOTSTRAPPER_ENGINE_CONTEXT
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index c8dce17b..93b9c002 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -593,6 +593,7 @@ LExit:
593 593
594extern "C" HRESULT CoreElevate( 594extern "C" HRESULT CoreElevate(
595 __in BURN_ENGINE_STATE* pEngineState, 595 __in BURN_ENGINE_STATE* pEngineState,
596 __in WM_BURN reason,
596 __in_opt HWND hwndParent 597 __in_opt HWND hwndParent
597 ) 598 )
598{ 599{
@@ -608,7 +609,7 @@ extern "C" HRESULT CoreElevate(
608 ExitOnFailure(hr, "Failed to cache engine to working directory."); 609 ExitOnFailure(hr, "Failed to cache engine to working directory.");
609 } 610 }
610 611
611 hr = ElevationElevate(pEngineState, hwndParent); 612 hr = ElevationElevate(pEngineState, reason, hwndParent);
612 if (E_SUSPECTED_AV_INTERFERENCE == hr && 1 > cAVRetryAttempts) 613 if (E_SUSPECTED_AV_INTERFERENCE == hr && 1 > cAVRetryAttempts)
613 { 614 {
614 ++cAVRetryAttempts; 615 ++cAVRetryAttempts;
@@ -720,7 +721,7 @@ extern "C" HRESULT CoreApply(
720 // Elevate. 721 // Elevate.
721 if (pEngineState->plan.fPerMachine) 722 if (pEngineState->plan.fPerMachine)
722 { 723 {
723 hr = CoreElevate(pEngineState, pEngineState->userExperience.hwndApply); 724 hr = CoreElevate(pEngineState, WM_BURN_APPLY, pEngineState->userExperience.hwndApply);
724 ExitOnFailure(hr, "Failed to elevate."); 725 ExitOnFailure(hr, "Failed to elevate.");
725 726
726 hr = ElevationApplyInitialize(pEngineState->companionConnection.hPipe, &pEngineState->userExperience, &pEngineState->variables, &pEngineState->plan); 727 hr = ElevationApplyInitialize(pEngineState->companionConnection.hPipe, &pEngineState->userExperience, &pEngineState->variables, &pEngineState->plan);
@@ -872,7 +873,7 @@ extern "C" HRESULT CoreLaunchApprovedExe(
872 ExitOnRootFailure(hr, "BA aborted LaunchApprovedExe begin."); 873 ExitOnRootFailure(hr, "BA aborted LaunchApprovedExe begin.");
873 874
874 // Elevate. 875 // Elevate.
875 hr = CoreElevate(pEngineState, pLaunchApprovedExe->hwndParent); 876 hr = CoreElevate(pEngineState, WM_BURN_LAUNCH_APPROVED_EXE, pLaunchApprovedExe->hwndParent);
876 ExitOnFailure(hr, "Failed to elevate."); 877 ExitOnFailure(hr, "Failed to elevate.");
877 878
878 // Launch. 879 // Launch.
diff --git a/src/burn/engine/core.h b/src/burn/engine/core.h
index 812b40b1..3e636640 100644
--- a/src/burn/engine/core.h
+++ b/src/burn/engine/core.h
@@ -251,6 +251,7 @@ HRESULT CorePlan(
251 ); 251 );
252HRESULT CoreElevate( 252HRESULT CoreElevate(
253 __in BURN_ENGINE_STATE* pEngineState, 253 __in BURN_ENGINE_STATE* pEngineState,
254 __in WM_BURN reason,
254 __in_opt HWND hwndParent 255 __in_opt HWND hwndParent
255 ); 256 );
256HRESULT CoreApply( 257HRESULT CoreApply(
diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp
index 4d2e8544..7fd372b0 100644
--- a/src/burn/engine/elevation.cpp
+++ b/src/burn/engine/elevation.cpp
@@ -402,6 +402,7 @@ static HRESULT ElevatedOnExecuteActionComplete(
402 402
403extern "C" HRESULT ElevationElevate( 403extern "C" HRESULT ElevationElevate(
404 __in BURN_ENGINE_STATE* pEngineState, 404 __in BURN_ENGINE_STATE* pEngineState,
405 __in WM_BURN reason,
405 __in_opt HWND hwndParent 406 __in_opt HWND hwndParent
406 ) 407 )
407{ 408{
@@ -450,7 +451,11 @@ extern "C" HRESULT ElevationElevate(
450 else if (HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr) 451 else if (HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr)
451 { 452 {
452 // The user clicked "Cancel" on the elevation prompt or the elevation prompt timed out, provide the notification with the option to retry. 453 // The user clicked "Cancel" on the elevation prompt or the elevation prompt timed out, provide the notification with the option to retry.
453 hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT); 454 if (WM_BURN_APPLY == reason)
455 {
456 hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
457 }
458
454 nResult = UserExperienceSendError(&pEngineState->userExperience, BOOTSTRAPPER_ERROR_TYPE_ELEVATE, NULL, hr, NULL, MB_ICONERROR | MB_RETRYCANCEL, IDNOACTION); 459 nResult = UserExperienceSendError(&pEngineState->userExperience, BOOTSTRAPPER_ERROR_TYPE_ELEVATE, NULL, hr, NULL, MB_ICONERROR | MB_RETRYCANCEL, IDNOACTION);
455 } 460 }
456 } while (IDRETRY == nResult); 461 } while (IDRETRY == nResult);
diff --git a/src/burn/engine/elevation.h b/src/burn/engine/elevation.h
index 0d15b470..810287a3 100644
--- a/src/burn/engine/elevation.h
+++ b/src/burn/engine/elevation.h
@@ -10,6 +10,7 @@ extern "C" {
10// Parent (per-user process) side functions. 10// Parent (per-user process) side functions.
11HRESULT ElevationElevate( 11HRESULT ElevationElevate(
12 __in BURN_ENGINE_STATE* pEngineState, 12 __in BURN_ENGINE_STATE* pEngineState,
13 __in WM_BURN reason,
13 __in_opt HWND hwndParent 14 __in_opt HWND hwndParent
14 ); 15 );
15HRESULT ElevationApplyInitialize( 16HRESULT ElevationApplyInitialize(
diff --git a/src/burn/engine/engine.cpp b/src/burn/engine/engine.cpp
index 89082a88..48196655 100644
--- a/src/burn/engine/engine.cpp
+++ b/src/burn/engine/engine.cpp
@@ -893,7 +893,7 @@ static HRESULT ProcessMessage(
893 break; 893 break;
894 894
895 case WM_BURN_ELEVATE: 895 case WM_BURN_ELEVATE:
896 hr = CoreElevate(pEngineState, reinterpret_cast<HWND>(pmsg->lParam)); 896 hr = CoreElevate(pEngineState, WM_BURN_ELEVATE, reinterpret_cast<HWND>(pmsg->lParam));
897 break; 897 break;
898 898
899 case WM_BURN_APPLY: 899 case WM_BURN_APPLY:
@@ -1069,26 +1069,10 @@ static HRESULT Restart(
1069 ) 1069 )
1070{ 1070{
1071 HRESULT hr = S_OK; 1071 HRESULT hr = S_OK;
1072 HANDLE hProcessToken = NULL;
1073 TOKEN_PRIVILEGES priv = { };
1074 DWORD dwRetries = 0; 1072 DWORD dwRetries = 0;
1075 1073
1076 if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hProcessToken)) 1074 hr = ProcEnablePrivilege(::GetCurrentProcess(), SE_SHUTDOWN_NAME);
1077 { 1075 ExitOnFailure(hr, "Failed to enable shutdown privilege in process token.");
1078 ExitWithLastError(hr, "Failed to get process token.");
1079 }
1080
1081 priv.PrivilegeCount = 1;
1082 priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
1083 if (!::LookupPrivilegeValueW(NULL, L"SeShutdownPrivilege", &priv.Privileges[0].Luid))
1084 {
1085 ExitWithLastError(hr, "Failed to get shutdown privilege LUID.");
1086 }
1087
1088 if (!::AdjustTokenPrivileges(hProcessToken, FALSE, &priv, sizeof(TOKEN_PRIVILEGES), NULL, 0))
1089 {
1090 ExitWithLastError(hr, "Failed to adjust token to add shutdown privileges.");
1091 }
1092 1076
1093 pEngineState->fRestarting = TRUE; 1077 pEngineState->fRestarting = TRUE;
1094 CoreUpdateRestartState(pEngineState, BURN_RESTART_STATE_REQUESTING); 1078 CoreUpdateRestartState(pEngineState, BURN_RESTART_STATE_REQUESTING);
@@ -1147,7 +1131,6 @@ static HRESULT Restart(
1147 } 1131 }
1148 1132
1149LExit: 1133LExit:
1150 ReleaseHandle(hProcessToken);
1151 return hr; 1134 return hr;
1152} 1135}
1153 1136
diff --git a/src/burn/engine/platform.h b/src/burn/engine/platform.h
index 49d8f3e9..60184c23 100644
--- a/src/burn/engine/platform.h
+++ b/src/burn/engine/platform.h
@@ -8,6 +8,22 @@
8extern "C" { 8extern "C" {
9#endif 9#endif
10 10
11// constants
12
13enum WM_BURN
14{
15 WM_BURN_FIRST = WM_APP + 0xFFF, // this enum value must always be first.
16
17 WM_BURN_DETECT,
18 WM_BURN_PLAN,
19 WM_BURN_ELEVATE,
20 WM_BURN_APPLY,
21 WM_BURN_LAUNCH_APPROVED_EXE,
22 WM_BURN_QUIT,
23
24 WM_BURN_LAST, // this enum value must always be last.
25};
26
11// forward declare 27// forward declare
12 28
13enum BURN_MODE; 29enum BURN_MODE;
diff --git a/src/burn/engine/variable.cpp b/src/burn/engine/variable.cpp
index 81fa31b7..3947e29e 100644
--- a/src/burn/engine/variable.cpp
+++ b/src/burn/engine/variable.cpp
@@ -153,6 +153,10 @@ static HRESULT InitializeVariablePrivileged(
153 __in DWORD_PTR dwpData, 153 __in DWORD_PTR dwpData,
154 __inout BURN_VARIANT* pValue 154 __inout BURN_VARIANT* pValue
155 ); 155 );
156static HRESULT InitializeVariableProcessTokenPrivilege(
157 __in DWORD_PTR dwpData,
158 __inout BURN_VARIANT* pValue
159 );
156static HRESULT InitializeSystemLanguageID( 160static HRESULT InitializeSystemLanguageID(
157 __in DWORD_PTR dwpData, 161 __in DWORD_PTR dwpData,
158 __inout BURN_VARIANT* pValue 162 __inout BURN_VARIANT* pValue
@@ -284,6 +288,7 @@ extern "C" HRESULT VariableInitialize(
284 {L"WindowsFolder", InitializeVariableCsidlFolder, CSIDL_WINDOWS}, 288 {L"WindowsFolder", InitializeVariableCsidlFolder, CSIDL_WINDOWS},
285 {L"WindowsVolume", InitializeVariableWindowsVolumeFolder, 0}, 289 {L"WindowsVolume", InitializeVariableWindowsVolumeFolder, 0},
286 {BURN_BUNDLE_ACTION, InitializeVariableNumeric, 0, FALSE, TRUE}, 290 {BURN_BUNDLE_ACTION, InitializeVariableNumeric, 0, FALSE, TRUE},
291 {L"WixCanRestart", InitializeVariableProcessTokenPrivilege, (DWORD_PTR)SE_SHUTDOWN_NAME},
287 {BURN_BUNDLE_COMMAND_LINE_ACTION, InitializeVariableNumeric, 0, FALSE, TRUE}, 292 {BURN_BUNDLE_COMMAND_LINE_ACTION, InitializeVariableNumeric, 0, FALSE, TRUE},
288 {BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, InitializeVariableString, NULL, FALSE, TRUE}, 293 {BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, InitializeVariableString, NULL, FALSE, TRUE},
289 {BURN_BUNDLE_EXECUTE_PACKAGE_ACTION, InitializeVariableString, NULL, FALSE, TRUE}, 294 {BURN_BUNDLE_EXECUTE_PACKAGE_ACTION, InitializeVariableString, NULL, FALSE, TRUE},
@@ -2165,6 +2170,26 @@ LExit:
2165 return hr; 2170 return hr;
2166} 2171}
2167 2172
2173static HRESULT InitializeVariableProcessTokenPrivilege(
2174 __in DWORD_PTR dwpData,
2175 __inout BURN_VARIANT* pValue
2176 )
2177{
2178 HRESULT hr = S_OK;
2179 BOOL fHasPrivilege = FALSE;
2180 LPCWSTR wzPrivilegeName = (LPCWSTR)dwpData;
2181
2182 hr = ProcHasPrivilege(::GetCurrentProcess(), wzPrivilegeName, &fHasPrivilege);
2183 ExitOnFailure(hr, "Failed to check if process token has privilege: %ls.", wzPrivilegeName);
2184
2185 // set value
2186 hr = BVariantSetNumeric(pValue, fHasPrivilege);
2187 ExitOnFailure(hr, "Failed to set variant value.");
2188
2189LExit:
2190 return hr;
2191}
2192
2168static HRESULT InitializeSystemLanguageID( 2193static HRESULT InitializeSystemLanguageID(
2169 __in DWORD_PTR dwpData, 2194 __in DWORD_PTR dwpData,
2170 __inout BURN_VARIANT* pValue 2195 __inout BURN_VARIANT* pValue
diff --git a/src/burn/test/BurnUnitTest/ElevationTest.cpp b/src/burn/test/BurnUnitTest/ElevationTest.cpp
index 8d4cc7ff..713d9e07 100644
--- a/src/burn/test/BurnUnitTest/ElevationTest.cpp
+++ b/src/burn/test/BurnUnitTest/ElevationTest.cpp
@@ -68,7 +68,7 @@ namespace Bootstrapper
68 // 68 //
69 // per-user side setup 69 // per-user side setup
70 // 70 //
71 hr = ElevationElevate(&engineState, NULL); 71 hr = ElevationElevate(&engineState, WM_BURN_ELEVATE, NULL);
72 TestThrowOnFailure(hr, L"Failed to elevate."); 72 TestThrowOnFailure(hr, L"Failed to elevate.");
73 73
74 // post execute message 74 // post execute message
diff --git a/src/burn/test/BurnUnitTest/ExitCodeTest.cpp b/src/burn/test/BurnUnitTest/ExitCodeTest.cpp
index d7d91d06..465ee04b 100644
--- a/src/burn/test/BurnUnitTest/ExitCodeTest.cpp
+++ b/src/burn/test/BurnUnitTest/ExitCodeTest.cpp
@@ -118,7 +118,7 @@ static void LoadEngineState(
118 // 118 //
119 LoadEngineState(&engineState); 119 LoadEngineState(&engineState);
120 120
121 hr = ElevationElevate(&engineState, NULL); 121 hr = ElevationElevate(&engineState, WM_BURN_ELEVATE, NULL);
122 TestThrowOnFailure(hr, L"Failed to elevate."); 122 TestThrowOnFailure(hr, L"Failed to elevate.");
123 123
124 for (DWORD i = 0; i < countof(rgExitCodeItems); ++i) 124 for (DWORD i = 0; i < countof(rgExitCodeItems); ++i)
diff --git a/src/burn/test/BurnUnitTest/VariableTest.cpp b/src/burn/test/BurnUnitTest/VariableTest.cpp
index 8ee6e179..b373ae8e 100644
--- a/src/burn/test/BurnUnitTest/VariableTest.cpp
+++ b/src/burn/test/BurnUnitTest/VariableTest.cpp
@@ -564,6 +564,7 @@ namespace Bootstrapper
564 VariableGetNumericHelper(&variables, L"TerminalServer"); 564 VariableGetNumericHelper(&variables, L"TerminalServer");
565 VariableGetNumericHelper(&variables, L"UserUILanguageID"); 565 VariableGetNumericHelper(&variables, L"UserUILanguageID");
566 VariableGetNumericHelper(&variables, L"UserLanguageID"); 566 VariableGetNumericHelper(&variables, L"UserLanguageID");
567 VariableGetNumericHelper(&variables, L"WixCanRestart");
567 568
568 // known folders 569 // known folders
569 Assert::Equal<String^>(Environment::GetFolderPath(Environment::SpecialFolder::ApplicationData) + "\\", VariableGetStringHelper(&variables, L"AppDataFolder")); 570 Assert::Equal<String^>(Environment::GetFolderPath(Environment::SpecialFolder::ApplicationData) + "\\", VariableGetStringHelper(&variables, L"AppDataFolder"));