aboutsummaryrefslogtreecommitdiff
path: root/src/libs
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/libs
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/libs')
-rw-r--r--src/libs/dutil/WixToolset.DUtil/inc/procutil.h16
-rw-r--r--src/libs/dutil/WixToolset.DUtil/procutil.cpp106
-rw-r--r--src/libs/dutil/test/DUtilUnitTest/ProcUtilTest.cpp28
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
26HRESULT DAPI ProcTokenUser( 26HRESULT 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
32HRESULT DAPI ProcHasPrivilege(
33 __in HANDLE hProcess,
34 __in LPCWSTR wzPrivilegeName,
35 __out BOOL* pfHasPrivilege
36 );
37
38HRESULT DAPI ProcEnablePrivilege(
39 __in HANDLE hProcess,
40 __in LPCWSTR wzPrivilegeName
29 ); 41 );
30 42
31HRESULT DAPI ProcWow64( 43HRESULT 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
99extern "C" HRESULT DAPI ProcTokenUser( 99extern "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
137LExit:
138 ReleaseMem(pvTokenInformation);
139 ReleaseHandle(hToken);
140
141 return hr;
142}
143
144extern "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
175LExit:
176 ReleaseMem(pTokenPrivileges);
177
178 return hr;
179}
180
181extern "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
140LExit: 213LExit:
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;
6using namespace System::Security::Principal; 6using namespace System::Security::Principal;
7using namespace Xunit; 7using namespace Xunit;
8using namespace WixBuildTools::TestSupport; 8using namespace WixBuildTools::TestSupport;
9using namespace WixBuildTools::TestSupport::XunitExtensions;
9 10
10namespace DutilTests 11namespace 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}