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/libs | |
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/libs')
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/inc/procutil.h | 16 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/procutil.cpp | 106 | ||||
-rw-r--r-- | src/libs/dutil/test/DUtilUnitTest/ProcUtilTest.cpp | 28 |
3 files changed, 129 insertions, 21 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/procutil.h b/src/libs/dutil/WixToolset.DUtil/inc/procutil.h index d61d91b5..6a641a5b 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/procutil.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/procutil.h | |||
@@ -23,9 +23,21 @@ HRESULT DAPI ProcSystem( | |||
23 | __out BOOL* pfSystem | 23 | __out BOOL* pfSystem |
24 | ); | 24 | ); |
25 | 25 | ||
26 | HRESULT DAPI ProcTokenUser( | 26 | HRESULT DAPI ProcGetTokenInformation( |
27 | __in HANDLE hProcess, | 27 | __in HANDLE hProcess, |
28 | __out TOKEN_USER** ppTokenUser | 28 | __in TOKEN_INFORMATION_CLASS tokenInformationClass, |
29 | __out LPVOID* ppvTokenInformation | ||
30 | ); | ||
31 | |||
32 | HRESULT DAPI ProcHasPrivilege( | ||
33 | __in HANDLE hProcess, | ||
34 | __in LPCWSTR wzPrivilegeName, | ||
35 | __out BOOL* pfHasPrivilege | ||
36 | ); | ||
37 | |||
38 | HRESULT DAPI ProcEnablePrivilege( | ||
39 | __in HANDLE hProcess, | ||
40 | __in LPCWSTR wzPrivilegeName | ||
29 | ); | 41 | ); |
30 | 42 | ||
31 | HRESULT DAPI ProcWow64( | 43 | HRESULT DAPI ProcWow64( |
diff --git a/src/libs/dutil/WixToolset.DUtil/procutil.cpp b/src/libs/dutil/WixToolset.DUtil/procutil.cpp index 29f575ae..376aec6d 100644 --- a/src/libs/dutil/WixToolset.DUtil/procutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/procutil.cpp | |||
@@ -85,7 +85,7 @@ extern "C" HRESULT DAPI ProcSystem( | |||
85 | HRESULT hr = S_OK; | 85 | HRESULT hr = S_OK; |
86 | TOKEN_USER* pTokenUser = NULL; | 86 | TOKEN_USER* pTokenUser = NULL; |
87 | 87 | ||
88 | hr = ProcTokenUser(hProcess, &pTokenUser); | 88 | hr = ProcGetTokenInformation(hProcess, TokenUser, reinterpret_cast<LPVOID*>(&pTokenUser)); |
89 | ProcExitOnFailure(hr, "Failed to get TokenUser from process token."); | 89 | ProcExitOnFailure(hr, "Failed to get TokenUser from process token."); |
90 | 90 | ||
91 | *pfSystem = ::IsWellKnownSid(pTokenUser->User.Sid, WinLocalSystemSid); | 91 | *pfSystem = ::IsWellKnownSid(pTokenUser->User.Sid, WinLocalSystemSid); |
@@ -96,15 +96,16 @@ LExit: | |||
96 | return hr; | 96 | return hr; |
97 | } | 97 | } |
98 | 98 | ||
99 | extern "C" HRESULT DAPI ProcTokenUser( | 99 | extern "C" HRESULT DAPI ProcGetTokenInformation( |
100 | __in HANDLE hProcess, | 100 | __in HANDLE hProcess, |
101 | __out TOKEN_USER** ppTokenUser | 101 | __in TOKEN_INFORMATION_CLASS tokenInformationClass, |
102 | __out LPVOID* ppvTokenInformation | ||
102 | ) | 103 | ) |
103 | { | 104 | { |
104 | HRESULT hr = S_OK; | 105 | HRESULT hr = S_OK; |
105 | DWORD er = ERROR_SUCCESS; | 106 | DWORD er = ERROR_SUCCESS; |
106 | HANDLE hToken = NULL; | 107 | HANDLE hToken = NULL; |
107 | TOKEN_USER* pTokenUser = NULL; | 108 | LPVOID pvTokenInformation = NULL; |
108 | DWORD cbToken = 0; | 109 | DWORD cbToken = 0; |
109 | 110 | ||
110 | if (!::OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) | 111 | if (!::OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) |
@@ -112,33 +113,104 @@ extern "C" HRESULT DAPI ProcTokenUser( | |||
112 | ProcExitWithLastError(hr, "Failed to open process token."); | 113 | ProcExitWithLastError(hr, "Failed to open process token."); |
113 | } | 114 | } |
114 | 115 | ||
115 | if (::GetTokenInformation(hToken, TokenUser, pTokenUser, 0, &cbToken)) | 116 | if (!::GetTokenInformation(hToken, tokenInformationClass, pvTokenInformation, 0, &cbToken)) |
116 | { | ||
117 | er = ERROR_SUCCESS; | ||
118 | } | ||
119 | else | ||
120 | { | 117 | { |
121 | er = ::GetLastError(); | 118 | er = ::GetLastError(); |
122 | } | 119 | } |
123 | 120 | ||
124 | if (er != ERROR_INSUFFICIENT_BUFFER) | 121 | if (er != ERROR_INSUFFICIENT_BUFFER) |
125 | { | 122 | { |
126 | ProcExitOnWin32Error(er, hr, "Failed to get user from process token size."); | 123 | ProcExitOnWin32Error(er, hr, "Failed to get information from process token size."); |
127 | } | 124 | } |
128 | 125 | ||
129 | pTokenUser = reinterpret_cast<TOKEN_USER*>(MemAlloc(cbToken, TRUE)); | 126 | pvTokenInformation = MemAlloc(cbToken, TRUE); |
130 | ProcExitOnNull(pTokenUser, hr, E_OUTOFMEMORY, "Failed to allocate token information."); | 127 | ProcExitOnNull(pvTokenInformation, hr, E_OUTOFMEMORY, "Failed to allocate token information."); |
131 | 128 | ||
132 | if (!::GetTokenInformation(hToken, TokenUser, pTokenUser, cbToken, &cbToken)) | 129 | if (!::GetTokenInformation(hToken, tokenInformationClass, pvTokenInformation, cbToken, &cbToken)) |
133 | { | 130 | { |
134 | ProcExitWithLastError(hr, "Failed to get user from process token."); | 131 | ProcExitWithLastError(hr, "Failed to get information from process token."); |
135 | } | 132 | } |
136 | 133 | ||
137 | *ppTokenUser = pTokenUser; | 134 | *ppvTokenInformation = pvTokenInformation; |
138 | pTokenUser = NULL; | 135 | pvTokenInformation = NULL; |
136 | |||
137 | LExit: | ||
138 | ReleaseMem(pvTokenInformation); | ||
139 | ReleaseHandle(hToken); | ||
140 | |||
141 | return hr; | ||
142 | } | ||
143 | |||
144 | extern "C" HRESULT DAPI ProcHasPrivilege( | ||
145 | __in HANDLE hProcess, | ||
146 | __in LPCWSTR wzPrivilegeName, | ||
147 | __out BOOL* pfHasPrivilege | ||
148 | ) | ||
149 | { | ||
150 | HRESULT hr = S_OK; | ||
151 | TOKEN_PRIVILEGES* pTokenPrivileges = NULL; | ||
152 | LUID luidPrivilege = { }; | ||
153 | |||
154 | *pfHasPrivilege = FALSE; | ||
155 | |||
156 | if (!::LookupPrivilegeValueW(NULL, wzPrivilegeName, &luidPrivilege)) | ||
157 | { | ||
158 | ProcExitWithLastError(hr, "Failed to get privilege LUID: %ls", wzPrivilegeName); | ||
159 | } | ||
160 | |||
161 | hr = ProcGetTokenInformation(hProcess, TokenPrivileges, reinterpret_cast<LPVOID*>(&pTokenPrivileges)); | ||
162 | ProcExitOnFailure(hr, "Failed to get token privilege information."); | ||
163 | |||
164 | for (DWORD i = 0; i < pTokenPrivileges->PrivilegeCount; ++i) | ||
165 | { | ||
166 | LUID* pTokenLuid = &pTokenPrivileges->Privileges[i].Luid; | ||
167 | |||
168 | if (luidPrivilege.LowPart == pTokenLuid->LowPart && luidPrivilege.HighPart == pTokenLuid->HighPart) | ||
169 | { | ||
170 | *pfHasPrivilege = TRUE; | ||
171 | break; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | LExit: | ||
176 | ReleaseMem(pTokenPrivileges); | ||
177 | |||
178 | return hr; | ||
179 | } | ||
180 | |||
181 | extern "C" HRESULT DAPI ProcEnablePrivilege( | ||
182 | __in HANDLE hProcess, | ||
183 | __in LPCWSTR wzPrivilegeName | ||
184 | ) | ||
185 | { | ||
186 | HRESULT hr = S_OK; | ||
187 | HANDLE hToken = NULL; | ||
188 | TOKEN_PRIVILEGES priv = { }; | ||
189 | |||
190 | priv.PrivilegeCount = 1; | ||
191 | priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; | ||
192 | |||
193 | if (!::LookupPrivilegeValueW(NULL, wzPrivilegeName, &priv.Privileges[0].Luid)) | ||
194 | { | ||
195 | ProcExitWithLastError(hr, "Failed to get privilege LUID: %ls", wzPrivilegeName); | ||
196 | } | ||
197 | |||
198 | if (!::OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken)) | ||
199 | { | ||
200 | ProcExitWithLastError(hr, "Failed to get process token to adjust privileges."); | ||
201 | } | ||
202 | |||
203 | if (!::AdjustTokenPrivileges(hToken, FALSE, &priv, sizeof(TOKEN_PRIVILEGES), NULL, 0)) | ||
204 | { | ||
205 | ProcExitWithLastError(hr, "Failed to adjust token to add privilege: %ls", wzPrivilegeName); | ||
206 | } | ||
207 | |||
208 | if (ERROR_NOT_ALL_ASSIGNED == ::GetLastError()) | ||
209 | { | ||
210 | hr = S_FALSE; | ||
211 | } | ||
139 | 212 | ||
140 | LExit: | 213 | LExit: |
141 | ReleaseMem(pTokenUser); | ||
142 | ReleaseHandle(hToken); | 214 | ReleaseHandle(hToken); |
143 | 215 | ||
144 | return hr; | 216 | return hr; |
diff --git a/src/libs/dutil/test/DUtilUnitTest/ProcUtilTest.cpp b/src/libs/dutil/test/DUtilUnitTest/ProcUtilTest.cpp index 297d90f4..8672ed38 100644 --- a/src/libs/dutil/test/DUtilUnitTest/ProcUtilTest.cpp +++ b/src/libs/dutil/test/DUtilUnitTest/ProcUtilTest.cpp | |||
@@ -6,6 +6,7 @@ using namespace System; | |||
6 | using namespace System::Security::Principal; | 6 | using namespace System::Security::Principal; |
7 | using namespace Xunit; | 7 | using namespace Xunit; |
8 | using namespace WixBuildTools::TestSupport; | 8 | using namespace WixBuildTools::TestSupport; |
9 | using namespace WixBuildTools::TestSupport::XunitExtensions; | ||
9 | 10 | ||
10 | namespace DutilTests | 11 | namespace DutilTests |
11 | { | 12 | { |
@@ -13,7 +14,7 @@ namespace DutilTests | |||
13 | { | 14 | { |
14 | public: | 15 | public: |
15 | [Fact] | 16 | [Fact] |
16 | void ProcTokenUserTest() | 17 | void ProcGetTokenInformationTest() |
17 | { | 18 | { |
18 | HRESULT hr = S_OK; | 19 | HRESULT hr = S_OK; |
19 | TOKEN_USER* pTokenUser = NULL; | 20 | TOKEN_USER* pTokenUser = NULL; |
@@ -21,7 +22,7 @@ namespace DutilTests | |||
21 | 22 | ||
22 | try | 23 | try |
23 | { | 24 | { |
24 | hr = ProcTokenUser(::GetCurrentProcess(), &pTokenUser); | 25 | hr = ProcGetTokenInformation(::GetCurrentProcess(), TokenUser, reinterpret_cast<LPVOID*>(&pTokenUser)); |
25 | NativeAssert::Succeeded(hr, "Failed to get TokenUser for current process."); | 26 | NativeAssert::Succeeded(hr, "Failed to get TokenUser for current process."); |
26 | 27 | ||
27 | if (!::ConvertSidToStringSidW(pTokenUser->User.Sid, &sczSid)) | 28 | if (!::ConvertSidToStringSidW(pTokenUser->User.Sid, &sczSid)) |
@@ -38,5 +39,28 @@ namespace DutilTests | |||
38 | ReleaseStr(sczSid); | 39 | ReleaseStr(sczSid); |
39 | } | 40 | } |
40 | } | 41 | } |
42 | |||
43 | [SkippableFact] | ||
44 | void ProcHasPrivilegeTest() | ||
45 | { | ||
46 | HRESULT hr = S_OK; | ||
47 | BOOL fHasPrivilege = FALSE; | ||
48 | |||
49 | hr = ProcHasPrivilege(::GetCurrentProcess(), SE_CREATE_TOKEN_NAME, &fHasPrivilege); | ||
50 | NativeAssert::Succeeded(hr, "Failed to check privilege for current process."); | ||
51 | |||
52 | if (fHasPrivilege) | ||
53 | { | ||
54 | WixAssert::Skip("Didn't expect process to have SE_CREATE_TOKEN_NAME privilege"); | ||
55 | } | ||
56 | |||
57 | hr = ProcHasPrivilege(::GetCurrentProcess(), SE_INC_WORKING_SET_NAME, &fHasPrivilege); | ||
58 | NativeAssert::Succeeded(hr, "Failed to check privilege for current process."); | ||
59 | |||
60 | if (!fHasPrivilege) | ||
61 | { | ||
62 | WixAssert::Skip("Expected process to have SE_INC_WORKING_SET_NAME privilege"); | ||
63 | } | ||
64 | } | ||
41 | }; | 65 | }; |
42 | } | 66 | } |