aboutsummaryrefslogtreecommitdiff
path: root/src/ext/Msmq/ca/mqutilexec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ext/Msmq/ca/mqutilexec.cpp')
-rw-r--r--src/ext/Msmq/ca/mqutilexec.cpp380
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
8struct 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
19PCA_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
35static HRESULT CreateSidFromDomainRidPair(
36 PSID pDomainSid,
37 DWORD dwRid,
38 PSID* ppSid
39 );
40static HRESULT InitLsaUnicodeString(
41 PLSA_UNICODE_STRING plusStr,
42 LPCWSTR pwzStr,
43 DWORD dwLen
44 );
45static void FreeLsaUnicodeString(
46 PLSA_UNICODE_STRING plusStr
47 );
48
49
50// function definitions
51
52HRESULT 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
93LExit:
94 return hr;
95}
96
97HRESULT 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
166LExit:
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
181HRESULT 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
229LExit:
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
244HRESULT 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
269LExit:
270 return hr;
271}
272
273HRESULT 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
296LExit:
297 return hr;
298}
299
300
301// helper function definitions
302
303static 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
347LExit:
348 return hr;
349}
350
351static 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
370LExit:
371 return hr;
372}
373
374static void FreeLsaUnicodeString(
375 PLSA_UNICODE_STRING plusStr
376 )
377{
378 if (plusStr->Buffer)
379 ::HeapFree(::GetProcessHeap(), 0, plusStr->Buffer);
380}