diff options
Diffstat (limited to 'src/ext/Msmq/ca/mqutilexec.cpp')
-rw-r--r-- | src/ext/Msmq/ca/mqutilexec.cpp | 380 |
1 files changed, 380 insertions, 0 deletions
diff --git a/src/ext/Msmq/ca/mqutilexec.cpp b/src/ext/Msmq/ca/mqutilexec.cpp new file mode 100644 index 00000000..a9c56e02 --- /dev/null +++ b/src/ext/Msmq/ca/mqutilexec.cpp | |||
@@ -0,0 +1,380 @@ | |||
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 | |||
6 | // private structs | ||
7 | |||
8 | struct PCA_WELLKNOWN_SID | ||
9 | { | ||
10 | LPCWSTR pwzName; | ||
11 | SID_IDENTIFIER_AUTHORITY iaIdentifierAuthority; | ||
12 | BYTE nSubAuthorityCount; | ||
13 | DWORD dwSubAuthority[8]; | ||
14 | }; | ||
15 | |||
16 | |||
17 | // well known SIDs | ||
18 | |||
19 | PCA_WELLKNOWN_SID wsWellKnownSids[] = { | ||
20 | {L"\\Everyone", SECURITY_WORLD_SID_AUTHORITY, 1, {SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0}}, | ||
21 | {L"\\Administrators", SECURITY_NT_AUTHORITY, 2, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0}}, | ||
22 | {L"\\LocalSystem", SECURITY_NT_AUTHORITY, 1, {SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0}}, | ||
23 | {L"\\LocalService", SECURITY_NT_AUTHORITY, 1, {SECURITY_LOCAL_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0}}, | ||
24 | {L"\\NetworkService", SECURITY_NT_AUTHORITY, 1, {SECURITY_NETWORK_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0}}, | ||
25 | {L"\\AuthenticatedUser", SECURITY_NT_AUTHORITY, 1, {SECURITY_AUTHENTICATED_USER_RID, 0, 0, 0, 0, 0, 0, 0}}, | ||
26 | {L"\\Guests", SECURITY_NT_AUTHORITY, 2, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS, 0, 0, 0, 0, 0, 0}}, | ||
27 | {L"\\Users", SECURITY_NT_AUTHORITY, 2, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0}}, | ||
28 | {L"\\CREATOR OWNER", SECURITY_NT_AUTHORITY, 1, {SECURITY_CREATOR_OWNER_RID, 0, 0, 0, 0, 0, 0, 0}}, | ||
29 | {NULL, SECURITY_NULL_SID_AUTHORITY, 0, {0, 0, 0, 0, 0, 0, 0, 0}} | ||
30 | }; | ||
31 | |||
32 | |||
33 | // prototypes for private helper functions | ||
34 | |||
35 | static HRESULT CreateSidFromDomainRidPair( | ||
36 | PSID pDomainSid, | ||
37 | DWORD dwRid, | ||
38 | PSID* ppSid | ||
39 | ); | ||
40 | static HRESULT InitLsaUnicodeString( | ||
41 | PLSA_UNICODE_STRING plusStr, | ||
42 | LPCWSTR pwzStr, | ||
43 | DWORD dwLen | ||
44 | ); | ||
45 | static void FreeLsaUnicodeString( | ||
46 | PLSA_UNICODE_STRING plusStr | ||
47 | ); | ||
48 | |||
49 | |||
50 | // function definitions | ||
51 | |||
52 | HRESULT PcaActionDataMessage( | ||
53 | DWORD cArgs, | ||
54 | ... | ||
55 | ) | ||
56 | { | ||
57 | HRESULT hr = S_OK; | ||
58 | UINT er = ERROR_SUCCESS; | ||
59 | |||
60 | PMSIHANDLE hRec; | ||
61 | va_list args; | ||
62 | |||
63 | // record | ||
64 | hRec = ::MsiCreateRecord(cArgs); | ||
65 | ExitOnNull(hRec, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
66 | |||
67 | va_start(args, cArgs); | ||
68 | for (DWORD i = 1; i <= cArgs; i++) | ||
69 | { | ||
70 | LPCWSTR pwzArg = va_arg(args, WCHAR*); | ||
71 | if (pwzArg && *pwzArg) | ||
72 | { | ||
73 | er = ::MsiRecordSetStringW(hRec, i, pwzArg); | ||
74 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set record field string"); | ||
75 | } | ||
76 | } | ||
77 | va_end(args); | ||
78 | |||
79 | // message | ||
80 | er = WcaProcessMessage(INSTALLMESSAGE_ACTIONDATA, hRec); | ||
81 | if (0 == er || IDOK == er || IDYES == er) | ||
82 | { | ||
83 | hr = S_OK; | ||
84 | } | ||
85 | else if (ERROR_INSTALL_USEREXIT == er || IDABORT == er || IDCANCEL == er) | ||
86 | { | ||
87 | WcaSetReturnValue(ERROR_INSTALL_USEREXIT); // note that the user said exit | ||
88 | hr = S_FALSE; | ||
89 | } | ||
90 | else | ||
91 | hr = E_UNEXPECTED; | ||
92 | |||
93 | LExit: | ||
94 | return hr; | ||
95 | } | ||
96 | |||
97 | HRESULT PcaAccountNameToSid( | ||
98 | LPCWSTR pwzAccountName, | ||
99 | PSID* ppSid | ||
100 | ) | ||
101 | { | ||
102 | HRESULT hr = S_OK; | ||
103 | UINT er = ERROR_SUCCESS; | ||
104 | NTSTATUS st = 0; | ||
105 | |||
106 | PSID pSid = NULL; | ||
107 | LSA_OBJECT_ATTRIBUTES loaAttributes; | ||
108 | LSA_HANDLE lsahPolicy = NULL; | ||
109 | LSA_UNICODE_STRING lusName; | ||
110 | PLSA_REFERENCED_DOMAIN_LIST plrdsDomains = NULL; | ||
111 | PLSA_TRANSLATED_SID pltsSid = NULL; | ||
112 | |||
113 | ::ZeroMemory(&loaAttributes, sizeof(loaAttributes)); | ||
114 | ::ZeroMemory(&lusName, sizeof(lusName)); | ||
115 | |||
116 | // identify well known SIDs | ||
117 | for (PCA_WELLKNOWN_SID* pWS = wsWellKnownSids; pWS->pwzName; pWS++) | ||
118 | { | ||
119 | if (0 == lstrcmpiW(pwzAccountName, pWS->pwzName)) | ||
120 | { | ||
121 | // allocate SID buffer | ||
122 | pSid = (PSID)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, ::GetSidLengthRequired(pWS->nSubAuthorityCount)); | ||
123 | ExitOnNull(pSid, hr, E_OUTOFMEMORY, "Failed to allocate buffer for SID"); | ||
124 | |||
125 | // initialize SID | ||
126 | ::InitializeSid(pSid, &pWS->iaIdentifierAuthority, pWS->nSubAuthorityCount); | ||
127 | |||
128 | // copy sub autorities | ||
129 | for (DWORD i = 0; i < pWS->nSubAuthorityCount; i++) | ||
130 | *::GetSidSubAuthority(pSid, i) = pWS->dwSubAuthority[i]; | ||
131 | |||
132 | break; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | // lookup name | ||
137 | if (!pSid) | ||
138 | { | ||
139 | // open policy handle | ||
140 | st = ::LsaOpenPolicy(NULL, &loaAttributes, POLICY_ALL_ACCESS, &lsahPolicy); | ||
141 | er = ::LsaNtStatusToWinError(st); | ||
142 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to open policy handle"); | ||
143 | |||
144 | // create account name lsa unicode string | ||
145 | hr = InitLsaUnicodeString(&lusName, pwzAccountName, wcslen(pwzAccountName)); | ||
146 | ExitOnFailure(hr, "Failed to initialize account name string"); | ||
147 | |||
148 | // lookup name | ||
149 | st = ::LsaLookupNames(lsahPolicy, 1, &lusName, &plrdsDomains, &pltsSid); | ||
150 | er = ::LsaNtStatusToWinError(st); | ||
151 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to lookup account names"); | ||
152 | |||
153 | if (SidTypeDomain == pltsSid->Use) | ||
154 | ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Domain SIDs not supported"); | ||
155 | |||
156 | // convert sid | ||
157 | hr = CreateSidFromDomainRidPair(plrdsDomains->Domains[pltsSid->DomainIndex].Sid, pltsSid->RelativeId, &pSid); | ||
158 | ExitOnFailure(hr, "Failed to convert SID"); | ||
159 | } | ||
160 | |||
161 | *ppSid = pSid; | ||
162 | pSid = NULL; | ||
163 | |||
164 | hr = S_OK; | ||
165 | |||
166 | LExit: | ||
167 | // clean up | ||
168 | if (pSid) | ||
169 | ::HeapFree(::GetProcessHeap(), 0, pSid); | ||
170 | if (lsahPolicy) | ||
171 | ::LsaClose(lsahPolicy); | ||
172 | if (plrdsDomains) | ||
173 | ::LsaFreeMemory(plrdsDomains); | ||
174 | if (pltsSid) | ||
175 | ::LsaFreeMemory(pltsSid); | ||
176 | FreeLsaUnicodeString(&lusName); | ||
177 | |||
178 | return hr; | ||
179 | } | ||
180 | |||
181 | HRESULT PcaSidToAccountName( | ||
182 | PSID pSid, | ||
183 | LPWSTR* ppwzAccountName | ||
184 | ) | ||
185 | { | ||
186 | HRESULT hr = S_OK; | ||
187 | UINT er = ERROR_SUCCESS; | ||
188 | NTSTATUS st = 0; | ||
189 | |||
190 | LSA_OBJECT_ATTRIBUTES loaAttributes; | ||
191 | LSA_HANDLE lsahPolicy = NULL; | ||
192 | PLSA_REFERENCED_DOMAIN_LIST plrdsDomains = NULL; | ||
193 | PLSA_TRANSLATED_NAME pltnName = NULL; | ||
194 | |||
195 | LPWSTR pwzDomain = NULL; | ||
196 | LPWSTR pwzName = NULL; | ||
197 | |||
198 | ::ZeroMemory(&loaAttributes, sizeof(loaAttributes)); | ||
199 | |||
200 | // open policy handle | ||
201 | st = ::LsaOpenPolicy(NULL, &loaAttributes, POLICY_ALL_ACCESS, &lsahPolicy); | ||
202 | er = ::LsaNtStatusToWinError(st); | ||
203 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to open policy handle"); | ||
204 | |||
205 | // lookup SID | ||
206 | st = ::LsaLookupSids(lsahPolicy, 1, &pSid, &plrdsDomains, &pltnName); | ||
207 | er = ::LsaNtStatusToWinError(st); | ||
208 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to lookup SID"); | ||
209 | |||
210 | if (SidTypeDomain == pltnName->Use) | ||
211 | ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Domain SIDs not supported"); | ||
212 | |||
213 | // format account name string | ||
214 | if (SidTypeWellKnownGroup != pltnName->Use) | ||
215 | { | ||
216 | PLSA_UNICODE_STRING plusDomain = &plrdsDomains->Domains[pltnName->DomainIndex].Name; | ||
217 | hr = StrAllocString(&pwzDomain, plusDomain->Buffer, plusDomain->Length / sizeof(WCHAR)); | ||
218 | ExitOnFailure(hr, "Failed to allocate name string"); | ||
219 | } | ||
220 | |||
221 | hr = StrAllocString(&pwzName, pltnName->Name.Buffer, pltnName->Name.Length / sizeof(WCHAR)); | ||
222 | ExitOnFailure(hr, "Failed to allocate domain string"); | ||
223 | |||
224 | hr = StrAllocFormatted(ppwzAccountName, L"%s\\%s", pwzDomain ? pwzDomain : L"", pwzName); | ||
225 | ExitOnFailure(hr, "Failed to format account name string"); | ||
226 | |||
227 | hr = S_OK; | ||
228 | |||
229 | LExit: | ||
230 | // clean up | ||
231 | if (lsahPolicy) | ||
232 | ::LsaClose(lsahPolicy); | ||
233 | if (plrdsDomains) | ||
234 | ::LsaFreeMemory(plrdsDomains); | ||
235 | if (pltnName) | ||
236 | ::LsaFreeMemory(pltnName); | ||
237 | |||
238 | ReleaseStr(pwzDomain); | ||
239 | ReleaseStr(pwzName); | ||
240 | |||
241 | return hr; | ||
242 | } | ||
243 | |||
244 | HRESULT PcaBuildAccountName( | ||
245 | LPCWSTR pwzDomain, | ||
246 | LPCWSTR pwzName, | ||
247 | LPWSTR* ppwzAccount | ||
248 | ) | ||
249 | { | ||
250 | HRESULT hr = S_OK; | ||
251 | |||
252 | WCHAR wzComputerName[MAX_COMPUTERNAME_LENGTH + 1]; | ||
253 | ::ZeroMemory(wzComputerName, sizeof(wzComputerName)); | ||
254 | |||
255 | // if domain is '.', get computer name | ||
256 | if (0 == lstrcmpW(pwzDomain, L".")) | ||
257 | { | ||
258 | DWORD dwSize = countof(wzComputerName); | ||
259 | if (!::GetComputerNameW(wzComputerName, &dwSize)) | ||
260 | ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to get computer name"); | ||
261 | } | ||
262 | |||
263 | // build account name | ||
264 | hr = StrAllocFormatted(ppwzAccount, L"%s\\%s", *wzComputerName ? wzComputerName : pwzDomain, pwzName); | ||
265 | ExitOnFailure(hr, "Failed to build domain user name"); | ||
266 | |||
267 | hr = S_OK; | ||
268 | |||
269 | LExit: | ||
270 | return hr; | ||
271 | } | ||
272 | |||
273 | HRESULT PcaGuidFromString( | ||
274 | LPCWSTR pwzGuid, | ||
275 | LPGUID pGuid | ||
276 | ) | ||
277 | { | ||
278 | HRESULT hr = S_OK; | ||
279 | |||
280 | int cch = 0; | ||
281 | |||
282 | WCHAR wz[39]; | ||
283 | ::ZeroMemory(wz, sizeof(wz)); | ||
284 | |||
285 | cch = lstrlenW(pwzGuid); | ||
286 | |||
287 | if (38 == cch && L'{' == pwzGuid[0] && L'}' == pwzGuid[37]) | ||
288 | StringCchCopyW(wz, countof(wz), pwzGuid); | ||
289 | else if (36 == cch) | ||
290 | StringCchPrintfW(wz, countof(wz), L"{%s}", pwzGuid); | ||
291 | else | ||
292 | ExitFunction1(hr = E_INVALIDARG); | ||
293 | |||
294 | hr = ::CLSIDFromString(wz, pGuid); | ||
295 | |||
296 | LExit: | ||
297 | return hr; | ||
298 | } | ||
299 | |||
300 | |||
301 | // helper function definitions | ||
302 | |||
303 | static HRESULT CreateSidFromDomainRidPair( | ||
304 | PSID pDomainSid, | ||
305 | DWORD dwRid, | ||
306 | PSID* ppSid | ||
307 | ) | ||
308 | { | ||
309 | HRESULT hr = S_OK; | ||
310 | |||
311 | PSID pSid = NULL; | ||
312 | |||
313 | // get domain SID sub authority count | ||
314 | UCHAR ucSubAuthorityCount = *::GetSidSubAuthorityCount(pDomainSid); | ||
315 | |||
316 | // allocate SID buffer | ||
317 | DWORD dwLengthRequired = ::GetSidLengthRequired(ucSubAuthorityCount + (UCHAR)1); | ||
318 | if (*ppSid) | ||
319 | { | ||
320 | SIZE_T ccb = ::HeapSize(::GetProcessHeap(), 0, *ppSid); | ||
321 | if (-1 == ccb) | ||
322 | ExitOnFailure(hr = E_FAIL, "Failed to get size of SID buffer"); | ||
323 | |||
324 | if (ccb < dwLengthRequired) | ||
325 | { | ||
326 | pSid = (PSID)::HeapReAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, *ppSid, dwLengthRequired); | ||
327 | ExitOnNull(pSid, hr, E_OUTOFMEMORY, "Failed to reallocate buffer for SID, len: %d", dwLengthRequired); | ||
328 | *ppSid = pSid; | ||
329 | } | ||
330 | } | ||
331 | else | ||
332 | { | ||
333 | *ppSid = (PSID)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, dwLengthRequired); | ||
334 | ExitOnNull(*ppSid, hr, E_OUTOFMEMORY, "Failed to allocate buffer for SID, len: %d", dwLengthRequired); | ||
335 | } | ||
336 | |||
337 | ::InitializeSid(*ppSid, ::GetSidIdentifierAuthority(pDomainSid), ucSubAuthorityCount + (UCHAR)1); | ||
338 | |||
339 | // copy sub autorities | ||
340 | DWORD i = 0; | ||
341 | for (; i < ucSubAuthorityCount; i++) | ||
342 | *::GetSidSubAuthority(*ppSid, i) = *::GetSidSubAuthority(pDomainSid, i); | ||
343 | *::GetSidSubAuthority(*ppSid, i) = dwRid; | ||
344 | |||
345 | hr = S_OK; | ||
346 | |||
347 | LExit: | ||
348 | return hr; | ||
349 | } | ||
350 | |||
351 | static HRESULT InitLsaUnicodeString( | ||
352 | PLSA_UNICODE_STRING plusStr, | ||
353 | LPCWSTR pwzStr, | ||
354 | DWORD dwLen | ||
355 | ) | ||
356 | { | ||
357 | HRESULT hr = S_OK; | ||
358 | |||
359 | plusStr->Length = (USHORT)dwLen * sizeof(WCHAR); | ||
360 | plusStr->MaximumLength = (USHORT)(dwLen + 1) * sizeof(WCHAR); | ||
361 | |||
362 | plusStr->Buffer = (WCHAR*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR) * (dwLen + 1)); | ||
363 | ExitOnNull(plusStr->Buffer, hr, E_OUTOFMEMORY, "Failed to allocate account name string"); | ||
364 | |||
365 | hr = StringCchCopyW(plusStr->Buffer, dwLen + 1, pwzStr); | ||
366 | ExitOnFailure(hr, "Failed to copy buffer"); | ||
367 | |||
368 | hr = S_OK; | ||
369 | |||
370 | LExit: | ||
371 | return hr; | ||
372 | } | ||
373 | |||
374 | static void FreeLsaUnicodeString( | ||
375 | PLSA_UNICODE_STRING plusStr | ||
376 | ) | ||
377 | { | ||
378 | if (plusStr->Buffer) | ||
379 | ::HeapFree(::GetProcessHeap(), 0, plusStr->Buffer); | ||
380 | } | ||