diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2022-09-02 16:12:42 -0500 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2022-09-03 15:29:26 -0500 |
commit | 237bdc6a97c0dd455da99c16e6b3b7cac4c79e86 (patch) | |
tree | 1f2c789a7aa752e068fac8a4ca08815d13bf527a /src/burn | |
parent | 7728e34e48a4fdb710ecc92dd8dca833bff3993f (diff) | |
download | wix-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.h | 16 | ||||
-rw-r--r-- | src/burn/engine/core.cpp | 7 | ||||
-rw-r--r-- | src/burn/engine/core.h | 1 | ||||
-rw-r--r-- | src/burn/engine/elevation.cpp | 7 | ||||
-rw-r--r-- | src/burn/engine/elevation.h | 1 | ||||
-rw-r--r-- | src/burn/engine/engine.cpp | 23 | ||||
-rw-r--r-- | src/burn/engine/platform.h | 16 | ||||
-rw-r--r-- | src/burn/engine/variable.cpp | 25 | ||||
-rw-r--r-- | src/burn/test/BurnUnitTest/ElevationTest.cpp | 2 | ||||
-rw-r--r-- | src/burn/test/BurnUnitTest/ExitCodeTest.cpp | 2 | ||||
-rw-r--r-- | src/burn/test/BurnUnitTest/VariableTest.cpp | 1 |
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 @@ | |||
6 | extern "C" { | 6 | extern "C" { |
7 | #endif | 7 | #endif |
8 | 8 | ||
9 | // constants | ||
10 | |||
11 | enum 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 | ||
27 | typedef struct _BOOTSTRAPPER_ENGINE_CONTEXT | 11 | typedef 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 | ||
594 | extern "C" HRESULT CoreElevate( | 594 | extern "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 | ); |
252 | HRESULT CoreElevate( | 252 | HRESULT 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 | ); |
256 | HRESULT CoreApply( | 257 | HRESULT 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 | ||
403 | extern "C" HRESULT ElevationElevate( | 403 | extern "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. |
11 | HRESULT ElevationElevate( | 11 | HRESULT 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 | ); |
15 | HRESULT ElevationApplyInitialize( | 16 | HRESULT 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 | ||
1149 | LExit: | 1133 | LExit: |
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 @@ | |||
8 | extern "C" { | 8 | extern "C" { |
9 | #endif | 9 | #endif |
10 | 10 | ||
11 | // constants | ||
12 | |||
13 | enum 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 | ||
13 | enum BURN_MODE; | 29 | enum 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 | ); |
156 | static HRESULT InitializeVariableProcessTokenPrivilege( | ||
157 | __in DWORD_PTR dwpData, | ||
158 | __inout BURN_VARIANT* pValue | ||
159 | ); | ||
156 | static HRESULT InitializeSystemLanguageID( | 160 | static 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 | ||
2173 | static 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 | |||
2189 | LExit: | ||
2190 | return hr; | ||
2191 | } | ||
2192 | |||
2168 | static HRESULT InitializeSystemLanguageID( | 2193 | static 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")); |