aboutsummaryrefslogtreecommitdiff
path: root/src/ext/ComPlus/ca/cputilexec.cpp
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2021-05-04 11:41:55 -0700
committerRob Mensching <rob@firegiant.com>2021-05-04 11:41:55 -0700
commit337124bed6a57b40fca11c5c2f5b554f570522a6 (patch)
tree06e8552b11852309a2275e4bd63ee61320061876 /src/ext/ComPlus/ca/cputilexec.cpp
parenteab57c2ddebc3dc8cebc22f5337f50062f415c0d (diff)
downloadwix-337124bed6a57b40fca11c5c2f5b554f570522a6.tar.gz
wix-337124bed6a57b40fca11c5c2f5b554f570522a6.tar.bz2
wix-337124bed6a57b40fca11c5c2f5b554f570522a6.zip
Move ComPlus.wixext into ext
Diffstat (limited to 'src/ext/ComPlus/ca/cputilexec.cpp')
-rw-r--r--src/ext/ComPlus/ca/cputilexec.cpp1881
1 files changed, 1881 insertions, 0 deletions
diff --git a/src/ext/ComPlus/ca/cputilexec.cpp b/src/ext/ComPlus/ca/cputilexec.cpp
new file mode 100644
index 00000000..1c2c8b93
--- /dev/null
+++ b/src/ext/ComPlus/ca/cputilexec.cpp
@@ -0,0 +1,1881 @@
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 CPI_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
19CPI_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 FindUserCollectionObjectIndex(
36 ICatalogCollection* piColl,
37 PSID pSid,
38 int* pi
39 );
40static HRESULT CreateSidFromDomainRidPair(
41 PSID pDomainSid,
42 DWORD dwRid,
43 PSID* ppSid
44 );
45static HRESULT InitLsaUnicodeString(
46 PLSA_UNICODE_STRING plusStr,
47 LPCWSTR pwzStr,
48 DWORD dwLen
49 );
50static void FreeLsaUnicodeString(
51 PLSA_UNICODE_STRING plusStr
52 );
53static HRESULT WriteFileAll(
54 HANDLE hFile,
55 PBYTE pbBuffer,
56 DWORD dwBufferLength
57 );
58static HRESULT ReadFileAll(
59 HANDLE hFile,
60 PBYTE pbBuffer,
61 DWORD dwBufferLength
62 );
63
64
65// variables
66
67static ICOMAdminCatalog* gpiCatalog;
68
69
70// function definitions
71
72void CpiExecInitialize()
73{
74 // collections
75 gpiCatalog = NULL;
76}
77
78void CpiExecFinalize()
79{
80 // collections
81 ReleaseObject(gpiCatalog);
82}
83
84HRESULT CpiActionStartMessage(
85 LPWSTR* ppwzActionData,
86 BOOL fSuppress
87 )
88{
89 HRESULT hr = S_OK;
90 UINT er = ERROR_SUCCESS;
91
92 PMSIHANDLE hRec;
93
94 LPWSTR pwzData = NULL;
95
96 // create record
97 hRec = ::MsiCreateRecord(3);
98 ExitOnNull(hRec, hr, E_OUTOFMEMORY, "Failed to create record");
99
100 // action name
101 hr = WcaReadStringFromCaData(ppwzActionData, &pwzData);
102 ExitOnFailure(hr, "Failed to action name");
103
104 er = ::MsiRecordSetStringW(hRec, 1, pwzData);
105 ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set action name");
106
107 // description
108 hr = WcaReadStringFromCaData(ppwzActionData, &pwzData);
109 ExitOnFailure(hr, "Failed to description");
110
111 er = ::MsiRecordSetStringW(hRec, 2, pwzData);
112 ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set description");
113
114 // template
115 hr = WcaReadStringFromCaData(ppwzActionData, &pwzData);
116 ExitOnFailure(hr, "Failed to template");
117
118 er = ::MsiRecordSetStringW(hRec, 3, pwzData);
119 ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set template");
120
121 // message
122 if (!fSuppress)
123 {
124 er = WcaProcessMessage(INSTALLMESSAGE_ACTIONSTART, hRec);
125 if (0 == er || IDOK == er || IDYES == er)
126 {
127 hr = S_OK;
128 }
129 else if (IDABORT == er || IDCANCEL == er)
130 {
131 WcaSetReturnValue(ERROR_INSTALL_USEREXIT); // note that the user said exit
132 hr = S_FALSE;
133 }
134 else
135 hr = E_UNEXPECTED;
136 }
137
138LExit:
139 // clean up
140 ReleaseStr(pwzData);
141
142 return hr;
143}
144
145HRESULT CpiActionDataMessage(
146 DWORD cArgs,
147 ...
148 )
149{
150 HRESULT hr = S_OK;
151 UINT er = ERROR_SUCCESS;
152
153 PMSIHANDLE hRec;
154 va_list args;
155
156 // record
157 hRec = ::MsiCreateRecord(cArgs);
158 ExitOnNull(hRec, hr, E_OUTOFMEMORY, "Failed to create record");
159
160 va_start(args, cArgs);
161 for (DWORD i = 1; i <= cArgs; i++)
162 {
163 LPCWSTR pwzArg = va_arg(args, WCHAR*);
164 if (pwzArg && *pwzArg)
165 {
166 er = ::MsiRecordSetStringW(hRec, i, pwzArg);
167 ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set record field string");
168 }
169 }
170 va_end(args);
171
172 // message
173 er = WcaProcessMessage(INSTALLMESSAGE_ACTIONDATA, hRec);
174 if (0 == er || IDOK == er || IDYES == er)
175 {
176 hr = S_OK;
177 }
178 else if (IDABORT == er || IDCANCEL == er)
179 {
180 WcaSetReturnValue(ERROR_INSTALL_USEREXIT); // note that the user said exit
181 hr = S_FALSE;
182 }
183 else
184 hr = E_UNEXPECTED;
185
186LExit:
187 return hr;
188}
189
190HRESULT CpiExecGetAdminCatalog(
191 ICOMAdminCatalog** ppiCatalog
192 )
193{
194 HRESULT hr = S_OK;
195
196 if (!gpiCatalog)
197 {
198 // get collection
199 hr = ::CoCreateInstance(CLSID_COMAdminCatalog, NULL, CLSCTX_ALL, IID_ICOMAdminCatalog, (void**)&gpiCatalog);
200 ExitOnFailure(hr, "Failed to create COM+ admin catalog object");
201 }
202
203 // return value
204 gpiCatalog->AddRef();
205 *ppiCatalog = gpiCatalog;
206
207 hr = S_OK;
208
209LExit:
210 return hr;
211}
212
213HRESULT CpiLogCatalogErrorInfo()
214{
215 HRESULT hr = S_OK;
216
217 ICOMAdminCatalog* piCatalog = NULL;
218 ICatalogCollection* piErrColl = NULL;
219 IDispatch* piDisp = NULL;
220 ICatalogObject* piObj = NULL;
221
222 LPWSTR pwzName = NULL;
223 LPWSTR pwzErrorCode = NULL;
224 LPWSTR pwzMajorRef = NULL;
225 LPWSTR pwzMinorRef = NULL;
226
227 // get catalog
228 hr = CpiExecGetAdminCatalog(&piCatalog);
229 ExitOnFailure(hr, "Failed to get COM+ admin catalog");
230
231 // get error info collection
232 hr = CpiExecGetCatalogCollection(L"ErrorInfo", &piErrColl);
233 ExitOnFailure(hr, "Failed to get error info collection");
234
235 // loop objects
236 long lCnt;
237 hr = piErrColl->get_Count(&lCnt);
238 ExitOnFailure(hr, "Failed to get to number of items in collection");
239
240 for (long i = 0; i < lCnt; i++)
241 {
242 // get ICatalogObject interface
243 hr = piErrColl->get_Item(i, &piDisp);
244 ExitOnFailure(hr, "Failed to get item from partitions collection");
245
246 hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj);
247 ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface");
248
249 // get properties
250 hr = CpiGetCollectionObjectValue(piObj, L"Name", &pwzName);
251 ExitOnFailure(hr, "Failed to get name");
252 hr = CpiGetCollectionObjectValue(piObj, L"ErrorCode", &pwzErrorCode);
253 ExitOnFailure(hr, "Failed to get error code");
254 hr = CpiGetCollectionObjectValue(piObj, L"MajorRef", &pwzMajorRef);
255 ExitOnFailure(hr, "Failed to get major ref");
256 hr = CpiGetCollectionObjectValue(piObj, L"MinorRef", &pwzMinorRef);
257 ExitOnFailure(hr, "Failed to get minor ref");
258
259 // write to log
260 WcaLog(LOGMSG_STANDARD, "ErrorInfo: Name='%S', ErrorCode='%S', MajorRef='%S', MinorRef='%S'",
261 pwzName, pwzErrorCode, pwzMajorRef, pwzMinorRef);
262
263 // clean up
264 ReleaseNullObject(piDisp);
265 ReleaseNullObject(piObj);
266 }
267
268 hr = S_OK;
269
270LExit:
271 // clean up
272 ReleaseObject(piCatalog);
273 ReleaseObject(piErrColl);
274 ReleaseObject(piDisp);
275 ReleaseObject(piObj);
276
277 ReleaseStr(pwzName);
278 ReleaseStr(pwzErrorCode);
279 ReleaseStr(pwzMajorRef);
280 ReleaseStr(pwzMinorRef);
281
282 return hr;
283}
284
285HRESULT CpiExecGetCatalogCollection(
286 LPCWSTR pwzName,
287 ICatalogCollection** ppiColl
288 )
289{
290 HRESULT hr = S_OK;
291
292 ICOMAdminCatalog* piCatalog = NULL;
293 IDispatch* piDisp = NULL;
294
295 BSTR bstrName = NULL;
296
297 // copy name string
298 bstrName = ::SysAllocString(pwzName);
299 ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for collection name");
300
301 // get catalog
302 hr = CpiExecGetAdminCatalog(&piCatalog);
303 ExitOnFailure(hr, "Failed to get COM+ admin catalog");
304
305 // get collecton from catalog
306 hr = piCatalog->GetCollection(bstrName, &piDisp);
307 ExitOnFailure(hr, "Failed to get collection");
308
309 hr = piDisp->QueryInterface(IID_ICatalogCollection, (void**)ppiColl);
310 ExitOnFailure(hr, "Failed to get IID_ICatalogCollection interface");
311
312 // populate collection
313 hr = (*ppiColl)->Populate();
314 if (COMADMIN_E_OBJECTERRORS == hr)
315 CpiLogCatalogErrorInfo();
316 ExitOnFailure(hr, "Failed to populate collection");
317
318 hr = S_OK;
319
320LExit:
321 // clean up
322 ReleaseObject(piCatalog);
323 ReleaseObject(piDisp);
324 ReleaseBSTR(bstrName);
325
326 return hr;
327}
328
329HRESULT CpiExecGetCatalogCollection(
330 ICatalogCollection* piColl,
331 ICatalogObject* piObj,
332 LPCWSTR pwzName,
333 ICatalogCollection** ppiColl
334 )
335{
336 HRESULT hr = S_OK;
337
338 ICOMAdminCatalog* piCatalog = NULL;
339 IDispatch* piDisp = NULL;
340
341 BSTR bstrName = NULL;
342
343 VARIANT vtKey;
344 ::VariantInit(&vtKey);
345
346 // copy name string
347 bstrName = ::SysAllocString(pwzName);
348 ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for collection name");
349
350 // get catalog
351 hr = CpiExecGetAdminCatalog(&piCatalog);
352 ExitOnFailure(hr, "Failed to get COM+ admin catalog");
353
354 // get key
355 hr = piObj->get_Key(&vtKey);
356 ExitOnFailure(hr, "Failed to get object key");
357
358 // get collecton from catalog
359 hr = piColl->GetCollection(bstrName, vtKey, &piDisp);
360 ExitOnFailure(hr, "Failed to get collection");
361
362 hr = piDisp->QueryInterface(IID_ICatalogCollection, (void**)ppiColl);
363 ExitOnFailure(hr, "Failed to get IID_ICatalogCollection interface");
364
365 // populate collection
366 hr = (*ppiColl)->Populate();
367 if (COMADMIN_E_OBJECTERRORS == hr)
368 CpiLogCatalogErrorInfo();
369 ExitOnFailure(hr, "Failed to populate collection");
370
371 hr = S_OK;
372
373LExit:
374 // clean up
375 ReleaseObject(piCatalog);
376 ReleaseObject(piDisp);
377 ReleaseBSTR(bstrName);
378 ::VariantClear(&vtKey);
379
380 return hr;
381}
382
383HRESULT CpiAddCollectionObject(
384 ICatalogCollection* piColl,
385 ICatalogObject** ppiObj
386 )
387{
388 HRESULT hr = S_OK;
389
390 IDispatch* piDisp = NULL;
391
392 hr = piColl->Add(&piDisp);
393 ExitOnFailure(hr, "Failed to add object to collection");
394
395 hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)ppiObj);
396 ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface");
397
398 hr = S_OK;
399
400LExit:
401 // clean up
402 ReleaseObject(piDisp);
403
404 return hr;
405}
406
407HRESULT CpiPutCollectionObjectValue(
408 ICatalogObject* piObj,
409 LPCWSTR pwzPropName,
410 LPCWSTR pwzValue
411 )
412{
413 HRESULT hr = S_OK;
414
415 BSTR bstrPropName = NULL;
416
417 VARIANT vtVal;
418 ::VariantInit(&vtVal);
419
420 // allocate property name string
421 bstrPropName = ::SysAllocString(pwzPropName);
422 ExitOnNull(bstrPropName, hr, E_OUTOFMEMORY, "Failed to allocate property name string");
423
424 // prepare value variant
425 vtVal.vt = VT_BSTR;
426 vtVal.bstrVal = ::SysAllocString(pwzValue);
427 ExitOnNull(vtVal.bstrVal, hr, E_OUTOFMEMORY, "Failed to allocate property value string");
428
429 // put value
430 hr = piObj->put_Value(bstrPropName, vtVal);
431 ExitOnFailure(hr, "Failed to put property value");
432
433 hr = S_OK;
434
435LExit:
436 // clean up
437 ReleaseBSTR(bstrPropName);
438 ::VariantClear(&vtVal);
439
440 return hr;
441}
442
443HRESULT CpiPutCollectionObjectValues(
444 ICatalogObject* piObj,
445 CPI_PROPERTY* pPropList
446 )
447{
448 HRESULT hr = S_OK;
449
450 for (CPI_PROPERTY* pItm = pPropList; pItm; pItm = pItm->pNext)
451 {
452 // set property
453 hr = CpiPutCollectionObjectValue(piObj, pItm->wzName, pItm->pwzValue);
454 ExitOnFailure(hr, "Failed to set object property value, name: %S", pItm->wzName);
455 }
456
457 hr = S_OK;
458
459LExit:
460 return hr;
461}
462
463HRESULT CpiGetCollectionObjectValue(
464 ICatalogObject* piObj,
465 LPCWSTR szPropName,
466 LPWSTR* ppwzValue
467 )
468{
469 HRESULT hr = S_OK;
470
471 BSTR bstrPropName = NULL;
472
473 VARIANT vtVal;
474 ::VariantInit(&vtVal);
475
476 // allocate property name string
477 bstrPropName = ::SysAllocString(szPropName);
478 ExitOnNull(bstrPropName, hr, E_OUTOFMEMORY, "Failed to allocate property name string");
479
480 // get value
481 hr = piObj->get_Value(bstrPropName, &vtVal);
482 ExitOnFailure(hr, "Failed to get property value");
483
484 hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR);
485 ExitOnFailure(hr, "Failed to change variant type");
486
487 hr = StrAllocString(ppwzValue, vtVal.bstrVal, ::SysStringLen(vtVal.bstrVal));
488 ExitOnFailure(hr, "Failed to allocate memory for value string");
489
490 hr = S_OK;
491
492LExit:
493 // clean up
494 ReleaseBSTR(bstrPropName);
495 ::VariantClear(&vtVal);
496
497 return hr;
498}
499
500HRESULT CpiResetObjectProperty(
501 ICatalogCollection* piColl,
502 ICatalogObject* piObj,
503 LPCWSTR pwzPropName
504 )
505{
506 HRESULT hr = S_OK;
507
508 BSTR bstrPropName = NULL;
509
510 long lChanges = 0;
511
512 VARIANT vtVal;
513 ::VariantInit(&vtVal);
514
515 // allocate property name string
516 bstrPropName = ::SysAllocString(pwzPropName);
517 ExitOnNull(bstrPropName, hr, E_OUTOFMEMORY, "Failed to allocate deleteable property name string");
518
519 // get value
520 hr = piObj->get_Value(bstrPropName, &vtVal);
521 ExitOnFailure(hr, "Failed to get deleteable property value");
522
523 hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BOOL);
524 ExitOnFailure(hr, "Failed to change variant type");
525
526 // if the deleteable property is set
527 if (VARIANT_FALSE == vtVal.boolVal)
528 {
529 // clear property
530 vtVal.boolVal = VARIANT_TRUE;
531
532 hr = piObj->put_Value(bstrPropName, vtVal);
533 ExitOnFailure(hr, "Failed to get property value");
534
535 // save changes
536 hr = piColl->SaveChanges(&lChanges);
537 if (COMADMIN_E_OBJECTERRORS == hr)
538 CpiLogCatalogErrorInfo();
539 ExitOnFailure(hr, "Failed to save changes");
540 }
541
542 hr = S_OK;
543
544LExit:
545 // clean up
546 ReleaseBSTR(bstrPropName);
547 ::VariantClear(&vtVal);
548
549 return hr;
550}
551
552HRESULT CpiRemoveCollectionObject(
553 ICatalogCollection* piColl,
554 LPCWSTR pwzID,
555 LPCWSTR pwzName,
556 BOOL fResetDeleteable
557 )
558{
559 HRESULT hr = S_OK;
560
561 IDispatch* piDisp = NULL;
562 ICatalogObject* piObj = NULL;
563
564 BOOL fMatch = FALSE;
565
566 VARIANT vtVal;
567 ::VariantInit(&vtVal);
568
569 long lCnt;
570 hr = piColl->get_Count(&lCnt);
571 ExitOnFailure(hr, "Failed to get to number of items in collection");
572
573 for (long i = 0; i < lCnt; i++)
574 {
575 // get ICatalogObject interface
576 hr = piColl->get_Item(i, &piDisp);
577 ExitOnFailure(hr, "Failed to get object from collection");
578
579 hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj);
580 ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface");
581
582 // compare id
583 if (pwzID && *pwzID)
584 {
585 hr = piObj->get_Key(&vtVal);
586 ExitOnFailure(hr, "Failed to get key");
587
588 hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR);
589 ExitOnFailure(hr, "Failed to change variant type");
590
591 if (0 == lstrcmpiW(vtVal.bstrVal, pwzID))
592 fMatch = TRUE;
593
594 ::VariantClear(&vtVal);
595 }
596
597 // compare name
598 if (pwzName && *pwzName)
599 {
600 hr = piObj->get_Name(&vtVal);
601 ExitOnFailure(hr, "Failed to get name");
602
603 hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR);
604 ExitOnFailure(hr, "Failed to change variant type");
605
606 if (0 == lstrcmpW(vtVal.bstrVal, pwzName))
607 fMatch = TRUE;
608
609 ::VariantClear(&vtVal);
610 }
611
612 // if it's a match, remove it
613 if (fMatch)
614 {
615 if (fResetDeleteable)
616 {
617 // reset deleteable property, if set
618 hr = CpiResetObjectProperty(piColl, piObj, L"Deleteable");
619 ExitOnFailure(hr, "Failed to reset deleteable property");
620 }
621
622 hr = piColl->Remove(i);
623 ExitOnFailure(hr, "Failed to remove item from collection");
624 break;
625 }
626
627 // release interface pointers
628 ReleaseNullObject(piDisp);
629 ReleaseNullObject(piObj);
630 }
631
632 hr = S_OK;
633
634LExit:
635 // clean up
636 ReleaseObject(piDisp);
637 ReleaseObject(piObj);
638
639 ::VariantClear(&vtVal);
640
641 return hr;
642}
643
644HRESULT CpiRemoveUserCollectionObject(
645 ICatalogCollection* piColl,
646 PSID pSid
647 )
648{
649 HRESULT hr = S_OK;
650
651 int i = 0;
652
653 // find index
654 hr = FindUserCollectionObjectIndex(piColl, pSid, &i);
655 ExitOnFailure(hr, "Failed to find user collection index");
656
657 if (S_FALSE == hr)
658 ExitFunction(); // not found, exit with hr = S_FALSE
659
660 // remove object
661 hr = piColl->Remove(i);
662 ExitOnFailure(hr, "Failed to remove object from collection");
663
664 hr = S_OK;
665
666LExit:
667 return hr;
668}
669
670HRESULT CpiFindCollectionObjectByStringKey(
671 ICatalogCollection* piColl,
672 LPCWSTR pwzKey,
673 ICatalogObject** ppiObj
674 )
675{
676 HRESULT hr = S_OK;
677
678 IDispatch* piDisp = NULL;
679 ICatalogObject* piObj = NULL;
680
681 VARIANT vtVal;
682 ::VariantInit(&vtVal);
683
684 long lCnt;
685 hr = piColl->get_Count(&lCnt);
686 ExitOnFailure(hr, "Failed to get to number of items in collection");
687
688 for (long i = 0; i < lCnt; i++)
689 {
690 // get ICatalogObject interface
691 hr = piColl->get_Item(i, &piDisp);
692 ExitOnFailure(hr, "Failed to get object from collection");
693
694 hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj);
695 ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface");
696
697 // compare key
698 hr = piObj->get_Key(&vtVal);
699 ExitOnFailure(hr, "Failed to get key");
700
701 hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR);
702 ExitOnFailure(hr, "Failed to change variant type");
703
704 if (0 == lstrcmpiW(vtVal.bstrVal, pwzKey))
705 {
706 if (ppiObj)
707 {
708 *ppiObj = piObj;
709 piObj = NULL;
710 }
711 ExitFunction1(hr = S_OK);
712 }
713
714 // clean up
715 ReleaseNullObject(piDisp);
716 ReleaseNullObject(piObj);
717
718 ::VariantClear(&vtVal);
719 }
720
721 hr = S_FALSE;
722
723LExit:
724 // clean up
725 ReleaseObject(piDisp);
726 ReleaseObject(piObj);
727
728 ::VariantClear(&vtVal);
729
730 return hr;
731}
732
733HRESULT CpiFindCollectionObjectByIntegerKey(
734 ICatalogCollection* piColl,
735 long lKey,
736 ICatalogObject** ppiObj
737 )
738{
739 HRESULT hr = S_OK;
740
741 IDispatch* piDisp = NULL;
742 ICatalogObject* piObj = NULL;
743
744 VARIANT vtVal;
745 ::VariantInit(&vtVal);
746
747 long lCnt;
748 hr = piColl->get_Count(&lCnt);
749 ExitOnFailure(hr, "Failed to get to number of items in collection");
750
751 for (long i = 0; i < lCnt; i++)
752 {
753 // get ICatalogObject interface
754 hr = piColl->get_Item(i, &piDisp);
755 ExitOnFailure(hr, "Failed to get object from collection");
756
757 hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj);
758 ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface");
759
760 // compare key
761 hr = piObj->get_Key(&vtVal);
762 ExitOnFailure(hr, "Failed to get key");
763
764 hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_I4);
765 ExitOnFailure(hr, "Failed to change variant type");
766
767 if (vtVal.lVal == lKey)
768 {
769 if (ppiObj)
770 {
771 *ppiObj = piObj;
772 piObj = NULL;
773 }
774 ExitFunction1(hr = S_OK);
775 }
776
777 // clean up
778 ReleaseNullObject(piDisp);
779 ReleaseNullObject(piObj);
780
781 ::VariantClear(&vtVal);
782 }
783
784 hr = S_FALSE;
785
786LExit:
787 // clean up
788 ReleaseObject(piDisp);
789 ReleaseObject(piObj);
790
791 ::VariantClear(&vtVal);
792
793 return hr;
794}
795
796HRESULT CpiFindCollectionObjectByName(
797 ICatalogCollection* piColl,
798 LPCWSTR pwzName,
799 ICatalogObject** ppiObj
800 )
801{
802 HRESULT hr = S_OK;
803
804 IDispatch* piDisp = NULL;
805 ICatalogObject* piObj = NULL;
806
807 VARIANT vtVal;
808 ::VariantInit(&vtVal);
809
810 long lCnt;
811 hr = piColl->get_Count(&lCnt);
812 ExitOnFailure(hr, "Failed to get to number of items in collection");
813
814 for (long i = 0; i < lCnt; i++)
815 {
816 // get ICatalogObject interface
817 hr = piColl->get_Item(i, &piDisp);
818 ExitOnFailure(hr, "Failed to get object from collection");
819
820 hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj);
821 ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface");
822
823 // compare key
824 hr = piObj->get_Name(&vtVal);
825 ExitOnFailure(hr, "Failed to get key");
826
827 hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR);
828 ExitOnFailure(hr, "Failed to change variant type");
829
830 if (0 == lstrcmpW(vtVal.bstrVal, pwzName))
831 {
832 if (ppiObj)
833 {
834 *ppiObj = piObj;
835 piObj = NULL;
836 }
837 ExitFunction1(hr = S_OK);
838 }
839
840 // clean up
841 ReleaseNullObject(piDisp);
842 ReleaseNullObject(piObj);
843
844 ::VariantClear(&vtVal);
845 }
846
847 hr = S_FALSE;
848
849LExit:
850 // clean up
851 ReleaseObject(piDisp);
852 ReleaseObject(piObj);
853
854 ::VariantClear(&vtVal);
855
856 return hr;
857}
858
859HRESULT CpiFindUserCollectionObject(
860 ICatalogCollection* piColl,
861 PSID pSid,
862 ICatalogObject** ppiObj
863 )
864{
865 HRESULT hr = S_OK;
866
867 int i = 0;
868
869 IDispatch* piDisp = NULL;
870
871 // find index
872 hr = FindUserCollectionObjectIndex(piColl, pSid, &i);
873 ExitOnFailure(hr, "Failed to find user collection index");
874
875 if (S_FALSE == hr)
876 ExitFunction(); // not found, exit with hr = S_FALSE
877
878 // get object
879 if (ppiObj)
880 {
881 hr = piColl->get_Item(i, &piDisp);
882 ExitOnFailure(hr, "Failed to get object from collection");
883
884 hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)ppiObj);
885 ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface");
886 }
887
888 hr = S_OK;
889
890LExit:
891 // clean up
892 ReleaseObject(piDisp);
893
894 return hr;
895}
896
897HRESULT CpiExecGetPartitionsCollection(
898 ICatalogCollection** ppiPartColl
899 )
900{
901 HRESULT hr = S_OK;
902
903 // get collection
904 hr = CpiExecGetCatalogCollection(L"Partitions", ppiPartColl);
905 ExitOnFailure(hr, "Failed to get catalog collection");
906
907 hr = S_OK;
908
909LExit:
910 return hr;
911}
912
913HRESULT CpiGetPartitionRolesCollection(
914 LPCWSTR pwzPartID,
915 ICatalogCollection** ppiRolesColl
916 )
917{
918 HRESULT hr = S_OK;
919
920 ICatalogCollection* piPartColl = NULL;
921 ICatalogObject* piPartObj = NULL;
922
923 // get partitions collection
924 hr = CpiExecGetPartitionsCollection(&piPartColl);
925 ExitOnFailure(hr, "Failed to get partitions collection");
926
927 if (S_FALSE == hr)
928 ExitFunction(); // partitions collection not found, exit with hr = S_FALSE
929
930 // find object
931 hr = CpiFindCollectionObjectByStringKey(piPartColl, pwzPartID, &piPartObj);
932 ExitOnFailure(hr, "Failed to find collection object");
933
934 if (S_FALSE == hr)
935 ExitFunction(); // partition not found, exit with hr = S_FALSE
936
937 // get roles collection
938 hr = CpiExecGetCatalogCollection(piPartColl, piPartObj, L"RolesForPartition", ppiRolesColl);
939 ExitOnFailure(hr, "Failed to get catalog collection");
940
941 hr = S_OK;
942
943LExit:
944 // clean up
945 ReleaseObject(piPartColl);
946 ReleaseObject(piPartObj);
947
948 return hr;
949}
950
951HRESULT CpiGetUsersInPartitionRoleCollection(
952 LPCWSTR pwzPartID,
953 LPCWSTR pwzRoleName,
954 ICatalogCollection** ppiUsrInRoleColl
955 )
956{
957 HRESULT hr = S_OK;
958
959 ICatalogCollection* piRoleColl = NULL;
960 ICatalogObject* piRoleObj = NULL;
961
962 // get roles collection
963 hr = CpiGetPartitionRolesCollection(pwzPartID, &piRoleColl);
964 ExitOnFailure(hr, "Failed to get roles collection");
965
966 if (S_FALSE == hr)
967 ExitFunction(); // partition roles collection not found, exit with hr = S_FALSE
968
969 // find object
970 hr = CpiFindCollectionObjectByName(piRoleColl, pwzRoleName, &piRoleObj);
971 ExitOnFailure(hr, "Failed to find collection object");
972
973 if (S_FALSE == hr)
974 ExitFunction(); // user not found, exit with hr = S_FALSE
975
976 // get roles collection
977 hr = CpiExecGetCatalogCollection(piRoleColl, piRoleObj, L"UsersInPartitionRole", ppiUsrInRoleColl);
978 ExitOnFailure(hr, "Failed to get catalog collection");
979
980 hr = S_OK;
981
982LExit:
983 // clean up
984 ReleaseObject(piRoleColl);
985 ReleaseObject(piRoleObj);
986
987 return hr;
988}
989
990HRESULT CpiGetPartitionUsersCollection(
991 ICatalogCollection** ppiUserColl
992 )
993{
994 HRESULT hr = S_OK;
995
996 // get roles collection
997 hr = CpiExecGetCatalogCollection(L"PartitionUsers", ppiUserColl);
998 ExitOnFailure(hr, "Failed to get catalog collection");
999
1000 hr = S_OK;
1001
1002LExit:
1003 return hr;
1004}
1005
1006HRESULT CpiExecGetApplicationsCollection(
1007 LPCWSTR pwzPartID,
1008 ICatalogCollection** ppiAppColl
1009 )
1010{
1011 HRESULT hr = S_OK;
1012
1013 ICOMAdminCatalog* piCatalog = NULL;
1014 ICOMAdminCatalog2* piCatalog2 = NULL;
1015 BSTR bstrGlobPartID = NULL;
1016
1017 ICatalogCollection* piPartColl = NULL;
1018 ICatalogObject* piPartObj = NULL;
1019
1020 // get catalog
1021 hr = CpiExecGetAdminCatalog(&piCatalog);
1022 ExitOnFailure(hr, "Failed to get COM+ admin catalog");
1023
1024 // get ICOMAdminCatalog2 interface
1025 hr = piCatalog->QueryInterface(IID_ICOMAdminCatalog2, (void**)&piCatalog2);
1026
1027 // COM+ 1.5 or later
1028 if (E_NOINTERFACE != hr)
1029 {
1030 ExitOnFailure(hr, "Failed to get IID_ICOMAdminCatalog2 interface");
1031
1032 // partition id
1033 if (!pwzPartID || !*pwzPartID)
1034 {
1035 // get global partition id
1036 hr = piCatalog2->get_GlobalPartitionID(&bstrGlobPartID);
1037 ExitOnFailure(hr, "Failed to get global partition id");
1038 }
1039
1040 // get partitions collection
1041 hr = CpiExecGetPartitionsCollection(&piPartColl);
1042 ExitOnFailure(hr, "Failed to get partitions collection");
1043
1044 // find object
1045 hr = CpiFindCollectionObjectByStringKey(piPartColl, bstrGlobPartID ? bstrGlobPartID : pwzPartID, &piPartObj);
1046 ExitOnFailure(hr, "Failed to find collection object");
1047
1048 if (S_FALSE == hr)
1049 ExitFunction(); // partition not found, exit with hr = S_FALSE
1050
1051 // get applications collection
1052 hr = CpiExecGetCatalogCollection(piPartColl, piPartObj, L"Applications", ppiAppColl);
1053 ExitOnFailure(hr, "Failed to get catalog collection for partition");
1054 }
1055
1056 // COM+ pre 1.5
1057 else
1058 {
1059 // this version of COM+ does not support partitions, make sure a partition was not specified
1060 if (pwzPartID && *pwzPartID)
1061 ExitOnFailure(hr = E_FAIL, "Partitions are not supported by this version of COM+");
1062
1063 // get applications collection
1064 hr = CpiExecGetCatalogCollection(L"Applications", ppiAppColl);
1065 ExitOnFailure(hr, "Failed to get catalog collection");
1066 }
1067
1068 hr = S_OK;
1069
1070LExit:
1071 // clean up
1072 ReleaseObject(piCatalog);
1073 ReleaseObject(piCatalog2);
1074 ReleaseBSTR(bstrGlobPartID);
1075
1076 ReleaseObject(piPartColl);
1077 ReleaseObject(piPartObj);
1078
1079 return hr;
1080}
1081
1082HRESULT CpiGetRolesCollection(
1083 LPCWSTR pwzPartID,
1084 LPCWSTR pwzAppID,
1085 ICatalogCollection** ppiRolesColl
1086 )
1087{
1088 HRESULT hr = S_OK;
1089
1090 ICatalogCollection* piAppColl = NULL;
1091 ICatalogObject* piAppObj = NULL;
1092
1093 // get applications collection
1094 hr = CpiExecGetApplicationsCollection(pwzPartID, &piAppColl);
1095 ExitOnFailure(hr, "Failed to get applications collection");
1096
1097 if (S_FALSE == hr)
1098 ExitFunction(); // applications collection not found, exit with hr = S_FALSE
1099
1100 // find object
1101 hr = CpiFindCollectionObjectByStringKey(piAppColl, pwzAppID, &piAppObj);
1102 ExitOnFailure(hr, "Failed to find collection object");
1103
1104 if (S_FALSE == hr)
1105 ExitFunction(); // application not found, exit with hr = S_FALSE
1106
1107 // get roles collection
1108 hr = CpiExecGetCatalogCollection(piAppColl, piAppObj, L"Roles", ppiRolesColl);
1109 ExitOnFailure(hr, "Failed to catalog collection");
1110
1111 hr = S_OK;
1112
1113LExit:
1114 // clean up
1115 ReleaseObject(piAppColl);
1116 ReleaseObject(piAppObj);
1117
1118 return hr;
1119}
1120
1121HRESULT CpiGetUsersInRoleCollection(
1122 LPCWSTR pwzPartID,
1123 LPCWSTR pwzAppID,
1124 LPCWSTR pwzRoleName,
1125 ICatalogCollection** ppiUsrInRoleColl
1126 )
1127{
1128 HRESULT hr = S_OK;
1129
1130 ICatalogCollection* piRoleColl = NULL;
1131 ICatalogObject* piRoleObj = NULL;
1132
1133 // get roles collection
1134 hr = CpiGetRolesCollection(pwzPartID, pwzAppID, &piRoleColl);
1135 ExitOnFailure(hr, "Failed to get roles collection");
1136
1137 if (S_FALSE == hr)
1138 ExitFunction(); // roles collection not found, exit with hr = S_FALSE
1139
1140 // find object
1141 hr = CpiFindCollectionObjectByName(piRoleColl, pwzRoleName, &piRoleObj);
1142 ExitOnFailure(hr, "Failed to find collection object");
1143
1144 if (S_FALSE == hr)
1145 ExitFunction(); // role not found, exit with hr = S_FALSE
1146
1147 // get roles collection
1148 hr = CpiExecGetCatalogCollection(piRoleColl, piRoleObj, L"UsersInRole", ppiUsrInRoleColl);
1149 ExitOnFailure(hr, "Failed to get catalog collection");
1150
1151 hr = S_OK;
1152
1153LExit:
1154 // clean up
1155 ReleaseObject(piRoleColl);
1156 ReleaseObject(piRoleObj);
1157
1158 return hr;
1159}
1160
1161HRESULT CpiGetComponentsCollection(
1162 LPCWSTR pwzPartID,
1163 LPCWSTR pwzAppID,
1164 ICatalogCollection** ppiCompsColl
1165 )
1166{
1167 HRESULT hr = S_OK;
1168
1169 ICatalogCollection* piAppColl = NULL;
1170 ICatalogObject* piAppObj = NULL;
1171
1172 // get applications collection
1173 hr = CpiExecGetApplicationsCollection(pwzPartID, &piAppColl);
1174 ExitOnFailure(hr, "Failed to get applications collection");
1175
1176 if (S_FALSE == hr)
1177 ExitFunction(); // applications collection not found, exit with hr = S_FALSE
1178
1179 // find object
1180 hr = CpiFindCollectionObjectByStringKey(piAppColl, pwzAppID, &piAppObj);
1181 ExitOnFailure(hr, "Failed to find collection object");
1182
1183 if (S_FALSE == hr)
1184 ExitFunction(); // application not found, exit with hr = S_FALSE
1185
1186 // get components collection
1187 hr = CpiExecGetCatalogCollection(piAppColl, piAppObj, L"Components", ppiCompsColl);
1188 ExitOnFailure(hr, "Failed to get catalog collection");
1189
1190 hr = S_OK;
1191
1192LExit:
1193 // clean up
1194 ReleaseObject(piAppColl);
1195 ReleaseObject(piAppObj);
1196
1197 return hr;
1198}
1199
1200HRESULT CpiGetInterfacesCollection(
1201 ICatalogCollection* piCompColl,
1202 ICatalogObject* piCompObj,
1203 ICatalogCollection** ppiIntfColl
1204 )
1205{
1206 HRESULT hr = S_OK;
1207
1208 // get interfaces collection
1209 hr = CpiExecGetCatalogCollection(piCompColl, piCompObj, L"InterfacesForComponent", ppiIntfColl);
1210 ExitOnFailure(hr, "Failed to get catalog collection");
1211
1212 hr = S_OK;
1213
1214LExit:
1215 return hr;
1216}
1217
1218HRESULT CpiGetMethodsCollection(
1219 ICatalogCollection* piIntfColl,
1220 ICatalogObject* piIntfObj,
1221 ICatalogCollection** ppiMethColl
1222 )
1223{
1224 HRESULT hr = S_OK;
1225
1226 // get interfaces collection
1227 hr = CpiExecGetCatalogCollection(piIntfColl, piIntfObj, L"MethodsForInterface", ppiMethColl);
1228 ExitOnFailure(hr, "Failed to get catalog collection");
1229
1230 hr = S_OK;
1231
1232LExit:
1233 return hr;
1234}
1235
1236HRESULT CpiGetSubscriptionsCollection(
1237 LPCWSTR pwzPartID,
1238 LPCWSTR pwzAppID,
1239 LPCWSTR pwzCompCLSID,
1240 ICatalogCollection** ppiSubsColl
1241 )
1242{
1243 HRESULT hr = S_OK;
1244
1245 ICatalogCollection* piCompColl = NULL;
1246 ICatalogObject* piCompObj = NULL;
1247
1248 // get components collection
1249 hr = CpiGetComponentsCollection(pwzPartID, pwzAppID, &piCompColl);
1250 ExitOnFailure(hr, "Failed to get components collection");
1251
1252 if (S_FALSE == hr)
1253 ExitFunction(); // components collection not found, exit with hr = S_FALSE
1254
1255 // find object
1256 hr = CpiFindCollectionObjectByStringKey(piCompColl, pwzCompCLSID, &piCompObj);
1257 ExitOnFailure(hr, "Failed to find collection object");
1258
1259 if (S_FALSE == hr)
1260 ExitFunction(); // component not found, exit with hr = S_FALSE
1261
1262 // get subscriptions collection
1263 hr = CpiExecGetCatalogCollection(piCompColl, piCompObj, L"SubscriptionsForComponent", ppiSubsColl);
1264 ExitOnFailure(hr, "Failed to get catalog collection");
1265
1266 hr = S_OK;
1267
1268LExit:
1269 // clean up
1270 ReleaseObject(piCompColl);
1271 ReleaseObject(piCompObj);
1272
1273 return hr;
1274}
1275
1276HRESULT CpiReadPropertyList(
1277 LPWSTR* ppwzData,
1278 CPI_PROPERTY** ppPropList
1279 )
1280{
1281 HRESULT hr = S_OK;
1282
1283 CPI_PROPERTY* pItm = NULL;
1284 LPWSTR pwzName = NULL;
1285
1286 // clear list if it already contains items
1287 if (*ppPropList)
1288 CpiFreePropertyList(*ppPropList);
1289 *ppPropList = NULL;
1290
1291 // read property count
1292 int iPropCnt = 0;
1293 hr = WcaReadIntegerFromCaData(ppwzData, &iPropCnt);
1294 ExitOnFailure(hr, "Failed to read property count");
1295
1296 for (int i = 0; i < iPropCnt; i++)
1297 {
1298 // allocate new element
1299 pItm = (CPI_PROPERTY*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PROPERTY));
1300 if (!pItm)
1301 ExitFunction1(hr = E_OUTOFMEMORY);
1302
1303 // Name
1304 hr = WcaReadStringFromCaData(ppwzData, &pwzName);
1305 ExitOnFailure(hr, "Failed to read name");
1306 StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzName);
1307
1308 // Value
1309 hr = WcaReadStringFromCaData(ppwzData, &pItm->pwzValue);
1310 ExitOnFailure(hr, "Failed to read property value");
1311
1312 // add to list
1313 if (*ppPropList)
1314 pItm->pNext = *ppPropList;
1315 *ppPropList = pItm;
1316 pItm = NULL;
1317 }
1318
1319 hr = S_OK;
1320
1321LExit:
1322 // clean up
1323 ReleaseStr(pwzName);
1324
1325 if (pItm)
1326 CpiFreePropertyList(pItm);
1327
1328 return hr;
1329}
1330
1331void CpiFreePropertyList(
1332 CPI_PROPERTY* pList
1333 )
1334{
1335 while (pList)
1336 {
1337 ReleaseStr(pList->pwzValue);
1338
1339 CPI_PROPERTY* pDelete = pList;
1340 pList = pList->pNext;
1341 ::HeapFree(::GetProcessHeap(), 0, pDelete);
1342 }
1343}
1344
1345HRESULT CpiWriteKeyToRollbackFile(
1346 HANDLE hFile,
1347 LPCWSTR pwzKey
1348 )
1349{
1350 HRESULT hr = S_OK;
1351
1352 WCHAR wzKey[MAX_DARWIN_KEY + 1];
1353 ::ZeroMemory(wzKey, sizeof(wzKey));
1354 hr = StringCchCopyW(wzKey, countof(wzKey), pwzKey);
1355 ExitOnFailure(hr, "Failed to copy key");
1356
1357 hr = WriteFileAll(hFile, (PBYTE)wzKey, MAX_DARWIN_KEY * sizeof(WCHAR));
1358 ExitOnFailure(hr, "Failed to write buffer");
1359
1360 FlushFileBuffers(hFile);
1361
1362 hr = S_OK;
1363
1364LExit:
1365 return hr;
1366}
1367
1368HRESULT CpiWriteIntegerToRollbackFile(
1369 HANDLE hFile,
1370 int i
1371 )
1372{
1373 HRESULT hr = S_OK;
1374
1375 hr = WriteFileAll(hFile, (PBYTE)&i, sizeof(int));
1376 ExitOnFailure(hr, "Failed to write buffer");
1377
1378 FlushFileBuffers(hFile);
1379
1380 hr = S_OK;
1381
1382LExit:
1383 return hr;
1384}
1385
1386HRESULT CpiReadRollbackDataList(
1387 HANDLE hFile,
1388 CPI_ROLLBACK_DATA** pprdList
1389 )
1390{
1391 HRESULT hr = S_OK;
1392
1393 int iCount;
1394
1395 CPI_ROLLBACK_DATA* pItm = NULL;
1396
1397 // read count
1398 hr = ReadFileAll(hFile, (PBYTE)&iCount, sizeof(int));
1399 if (HRESULT_FROM_WIN32(ERROR_HANDLE_EOF) == hr)
1400 ExitFunction1(hr = S_OK); // EOF reached, nothing left to read
1401 ExitOnFailure(hr, "Failed to read count");
1402
1403 for (int i = 0; i < iCount; i++)
1404 {
1405 // allocate new element
1406 pItm = (CPI_ROLLBACK_DATA*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_ROLLBACK_DATA));
1407 if (!pItm)
1408 ExitFunction1(hr = E_OUTOFMEMORY);
1409
1410 // read from file
1411 hr = ReadFileAll(hFile, (PBYTE)pItm->wzKey, MAX_DARWIN_KEY * sizeof(WCHAR));
1412 if (HRESULT_FROM_WIN32(ERROR_HANDLE_EOF) == hr)
1413 break; // EOF reached, nothing left to read
1414 ExitOnFailure(hr, "Failed to read key");
1415
1416 hr = ReadFileAll(hFile, (PBYTE)&pItm->iStatus, sizeof(int));
1417 if (HRESULT_FROM_WIN32(ERROR_HANDLE_EOF) == hr)
1418 pItm->iStatus = 0; // EOF reached, the operation was interupted; set status to zero
1419 else
1420 ExitOnFailure(hr, "Failed to read status");
1421
1422 // add to list
1423 if (*pprdList)
1424 pItm->pNext = *pprdList;
1425 *pprdList = pItm;
1426 pItm = NULL;
1427 }
1428
1429 hr = S_OK;
1430
1431LExit:
1432 // clean up
1433 if (pItm)
1434 CpiFreeRollbackDataList(pItm);
1435
1436 return hr;
1437}
1438
1439void CpiFreeRollbackDataList(
1440 CPI_ROLLBACK_DATA* pList
1441 )
1442{
1443 while (pList)
1444 {
1445 CPI_ROLLBACK_DATA* pDelete = pList;
1446 pList = pList->pNext;
1447 ::HeapFree(::GetProcessHeap(), 0, pDelete);
1448 }
1449}
1450
1451HRESULT CpiFindRollbackStatus(
1452 CPI_ROLLBACK_DATA* pList,
1453 LPCWSTR pwzKey,
1454 int* piStatus
1455 )
1456{
1457 HRESULT hr = S_OK;
1458
1459 for (; pList; pList = pList->pNext)
1460 {
1461 if (0 == lstrcmpW(pList->wzKey, pwzKey))
1462 {
1463 *piStatus = pList->iStatus;
1464 ExitFunction1(hr = S_OK);
1465 }
1466 }
1467
1468 hr = S_FALSE;
1469
1470LExit:
1471 return hr;
1472}
1473
1474HRESULT CpiAccountNameToSid(
1475 LPCWSTR pwzAccountName,
1476 PSID* ppSid
1477 )
1478{
1479 HRESULT hr = S_OK;
1480 UINT er = ERROR_SUCCESS;
1481 NTSTATUS st = 0;
1482
1483 PSID pSid = NULL;
1484 LSA_OBJECT_ATTRIBUTES loaAttributes;
1485 LSA_HANDLE lsahPolicy = NULL;
1486 LSA_UNICODE_STRING lusName;
1487 PLSA_REFERENCED_DOMAIN_LIST plrdsDomains = NULL;
1488 PLSA_TRANSLATED_SID pltsSid = NULL;
1489
1490 ::ZeroMemory(&loaAttributes, sizeof(loaAttributes));
1491 ::ZeroMemory(&lusName, sizeof(lusName));
1492
1493 // identify well known SIDs
1494 for (CPI_WELLKNOWN_SID* pWS = wsWellKnownSids; pWS->pwzName; pWS++)
1495 {
1496 if (0 == lstrcmpiW(pwzAccountName, pWS->pwzName))
1497 {
1498 // allocate SID buffer
1499 pSid = (PSID)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, ::GetSidLengthRequired(pWS->nSubAuthorityCount));
1500 ExitOnNull(pSid, hr, E_OUTOFMEMORY, "Failed to allocate buffer for SID");
1501
1502 // initialize SID
1503 ::InitializeSid(pSid, &pWS->iaIdentifierAuthority, pWS->nSubAuthorityCount);
1504
1505 // copy sub autorities
1506 for (DWORD i = 0; i < pWS->nSubAuthorityCount; i++)
1507 *::GetSidSubAuthority(pSid, i) = pWS->dwSubAuthority[i];
1508
1509 break;
1510 }
1511 }
1512
1513 // lookup name
1514 if (!pSid)
1515 {
1516 // open policy handle
1517 st = ::LsaOpenPolicy(NULL, &loaAttributes, POLICY_ALL_ACCESS, &lsahPolicy);
1518 er = ::LsaNtStatusToWinError(st);
1519 ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to open policy handle");
1520
1521 // create account name lsa unicode string
1522 hr = InitLsaUnicodeString(&lusName, pwzAccountName, (DWORD)wcslen(pwzAccountName));
1523 ExitOnFailure(hr, "Failed to initialize account name string");
1524
1525 // lookup name
1526 st = ::LsaLookupNames(lsahPolicy, 1, &lusName, &plrdsDomains, &pltsSid);
1527 er = ::LsaNtStatusToWinError(st);
1528 ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to lookup account names");
1529
1530 if (SidTypeDomain == pltsSid->Use)
1531 ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Domain SIDs not supported");
1532
1533 // convert sid
1534 hr = CreateSidFromDomainRidPair(plrdsDomains->Domains[pltsSid->DomainIndex].Sid, pltsSid->RelativeId, &pSid);
1535 ExitOnFailure(hr, "Failed to convert SID");
1536 }
1537
1538 *ppSid = pSid;
1539 pSid = NULL;
1540
1541 hr = S_OK;
1542
1543LExit:
1544 // clean up
1545 if (pSid)
1546 ::HeapFree(::GetProcessHeap(), 0, pSid);
1547 if (lsahPolicy)
1548 ::LsaClose(lsahPolicy);
1549 if (plrdsDomains)
1550 ::LsaFreeMemory(plrdsDomains);
1551 if (pltsSid)
1552 ::LsaFreeMemory(pltsSid);
1553 FreeLsaUnicodeString(&lusName);
1554
1555 return hr;
1556}
1557
1558HRESULT CpiSidToAccountName(
1559 PSID pSid,
1560 LPWSTR* ppwzAccountName
1561 )
1562{
1563 HRESULT hr = S_OK;
1564 UINT er = ERROR_SUCCESS;
1565 NTSTATUS st = 0;
1566
1567 LSA_OBJECT_ATTRIBUTES loaAttributes;
1568 LSA_HANDLE lsahPolicy = NULL;
1569 PLSA_REFERENCED_DOMAIN_LIST plrdsDomains = NULL;
1570 PLSA_TRANSLATED_NAME pltnName = NULL;
1571
1572 LPWSTR pwzDomain = NULL;
1573 LPWSTR pwzName = NULL;
1574
1575 ::ZeroMemory(&loaAttributes, sizeof(loaAttributes));
1576
1577 // open policy handle
1578 st = ::LsaOpenPolicy(NULL, &loaAttributes, POLICY_ALL_ACCESS, &lsahPolicy);
1579 er = ::LsaNtStatusToWinError(st);
1580 ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to open policy handle");
1581
1582 // lookup SID
1583 st = ::LsaLookupSids(lsahPolicy, 1, &pSid, &plrdsDomains, &pltnName);
1584 er = ::LsaNtStatusToWinError(st);
1585 ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed lookup SID");
1586
1587 if (SidTypeDomain == pltnName->Use)
1588 ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Domain SIDs not supported");
1589
1590 // format account name string
1591 if (SidTypeWellKnownGroup != pltnName->Use)
1592 {
1593 PLSA_UNICODE_STRING plusDomain = &plrdsDomains->Domains[pltnName->DomainIndex].Name;
1594 hr = StrAllocString(&pwzDomain, plusDomain->Buffer, plusDomain->Length / sizeof(WCHAR));
1595 ExitOnFailure(hr, "Failed to allocate name string");
1596 }
1597
1598 hr = StrAllocString(&pwzName, pltnName->Name.Buffer, pltnName->Name.Length / sizeof(WCHAR));
1599 ExitOnFailure(hr, "Failed to allocate domain string");
1600
1601 hr = StrAllocFormatted(ppwzAccountName, L"%s\\%s", pwzDomain ? pwzDomain : L"", pwzName);
1602 ExitOnFailure(hr, "Failed to format account name string");
1603
1604 hr = S_OK;
1605
1606LExit:
1607 // clean up
1608 if (lsahPolicy)
1609 ::LsaClose(lsahPolicy);
1610 if (plrdsDomains)
1611 ::LsaFreeMemory(plrdsDomains);
1612 if (pltnName)
1613 ::LsaFreeMemory(pltnName);
1614
1615 ReleaseStr(pwzDomain);
1616 ReleaseStr(pwzName);
1617
1618 return hr;
1619}
1620
1621// helper function definitions
1622
1623static HRESULT FindUserCollectionObjectIndex(
1624 ICatalogCollection* piColl,
1625 PSID pSid,
1626 int* pi
1627 )
1628{
1629 HRESULT hr = S_OK;
1630 UINT er = ERROR_SUCCESS;
1631 NTSTATUS st = 0;
1632
1633 long i = 0;
1634 long lCollCnt = 0;
1635
1636 LSA_OBJECT_ATTRIBUTES loaAttributes;
1637 LSA_HANDLE lsahPolicy = NULL;
1638 PLSA_UNICODE_STRING plusNames = NULL;
1639 PLSA_REFERENCED_DOMAIN_LIST plrdsDomains = NULL;
1640 PLSA_TRANSLATED_SID pltsSids = NULL;
1641
1642 IDispatch* piDisp = NULL;
1643 ICatalogObject* piObj = NULL;
1644 VARIANT vtVal;
1645
1646 PSID pTmpSid = NULL;
1647
1648 PLSA_TRANSLATED_SID pltsSid;
1649
1650 ::VariantInit(&vtVal);
1651 ::ZeroMemory(&loaAttributes, sizeof(loaAttributes));
1652
1653 // open policy handle
1654 st = ::LsaOpenPolicy(NULL, &loaAttributes, POLICY_ALL_ACCESS, &lsahPolicy);
1655 er = ::LsaNtStatusToWinError(st);
1656 ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to open policy handle");
1657
1658 // get number of elements in collection
1659 hr = piColl->get_Count(&lCollCnt);
1660 ExitOnFailure(hr, "Failed to get to number of objects in collection");
1661
1662 if (0 == lCollCnt)
1663 ExitFunction1(hr = S_FALSE); // not found
1664
1665 // allocate name buffer
1666 plusNames = (PLSA_UNICODE_STRING)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LSA_UNICODE_STRING) * lCollCnt);
1667 ExitOnNull(plusNames, hr, E_OUTOFMEMORY, "Failed to allocate names buffer");
1668
1669 // get accounts in collection
1670 for (i = 0; i < lCollCnt; i++)
1671 {
1672 // get ICatalogObject interface
1673 hr = piColl->get_Item(i, &piDisp);
1674 ExitOnFailure(hr, "Failed to get object from collection");
1675
1676 hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj);
1677 ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface");
1678
1679 // get value
1680 hr = piObj->get_Key(&vtVal);
1681 ExitOnFailure(hr, "Failed to get key");
1682
1683 hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR);
1684 ExitOnFailure(hr, "Failed to change variant type");
1685
1686 // copy account name string
1687 hr = InitLsaUnicodeString(&plusNames[i], vtVal.bstrVal, ::SysStringLen(vtVal.bstrVal));
1688 ExitOnFailure(hr, "Failed to initialize account name string");
1689
1690 // clean up
1691 ReleaseNullObject(piDisp);
1692 ReleaseNullObject(piObj);
1693 ::VariantClear(&vtVal);
1694 }
1695
1696 // lookup names
1697 st = ::LsaLookupNames(lsahPolicy, lCollCnt, plusNames, &plrdsDomains, &pltsSids);
1698 er = ::LsaNtStatusToWinError(st);
1699 if (ERROR_NONE_MAPPED != er && ERROR_SOME_NOT_MAPPED != er)
1700 ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to lookup account names");
1701
1702 // compare SIDs
1703 for (i = 0; i < lCollCnt; i++)
1704 {
1705 // get SID
1706 pltsSid = &pltsSids[i];
1707 if (SidTypeDomain == pltsSid->Use || SidTypeInvalid == pltsSid->Use || SidTypeUnknown == pltsSid->Use)
1708 continue; // ignore...
1709
1710 hr = CreateSidFromDomainRidPair(plrdsDomains->Domains[pltsSid->DomainIndex].Sid, pltsSid->RelativeId, &pTmpSid);
1711 ExitOnFailure(hr, "Failed to convert SID");
1712
1713 // compare SIDs
1714 if (::EqualSid(pSid, pTmpSid))
1715 {
1716 *pi = i;
1717 ExitFunction1(hr = S_OK);
1718 }
1719 }
1720
1721 if (ERROR_NONE_MAPPED == er || ERROR_SOME_NOT_MAPPED == er)
1722 hr = HRESULT_FROM_WIN32(er);
1723 else
1724 hr = S_FALSE; // not found
1725
1726LExit:
1727 // clean up
1728 ReleaseObject(piDisp);
1729 ReleaseObject(piObj);
1730 ::VariantClear(&vtVal);
1731
1732 if (plusNames)
1733 {
1734 for (i = 0; i < lCollCnt; i++)
1735 FreeLsaUnicodeString(&plusNames[i]);
1736 ::HeapFree(::GetProcessHeap(), 0, plusNames);
1737 }
1738
1739 if (lsahPolicy)
1740 ::LsaClose(lsahPolicy);
1741 if (plrdsDomains)
1742 ::LsaFreeMemory(plrdsDomains);
1743 if (pltsSids)
1744 ::LsaFreeMemory(pltsSids);
1745
1746 if (pTmpSid)
1747 ::HeapFree(::GetProcessHeap(), 0, pTmpSid);
1748
1749 return hr;
1750}
1751
1752static HRESULT CreateSidFromDomainRidPair(
1753 PSID pDomainSid,
1754 DWORD dwRid,
1755 PSID* ppSid
1756 )
1757{
1758 HRESULT hr = S_OK;
1759 PSID pSid = NULL;
1760
1761 // get domain SID sub authority count
1762 UCHAR ucSubAuthorityCount = *::GetSidSubAuthorityCount(pDomainSid);
1763
1764 // allocate SID buffer
1765 DWORD dwLengthRequired = ::GetSidLengthRequired(ucSubAuthorityCount + (UCHAR)1);
1766 if (*ppSid)
1767 {
1768 SIZE_T ccb = ::HeapSize(::GetProcessHeap(), 0, *ppSid);
1769 if (-1 == ccb)
1770 ExitOnFailure(hr = E_FAIL, "Failed to get size of SID buffer");
1771
1772 if (ccb < dwLengthRequired)
1773 {
1774 pSid = (PSID)::HeapReAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, *ppSid, dwLengthRequired);
1775 ExitOnNull(pSid, hr, E_OUTOFMEMORY, "Failed to reallocate buffer for SID, len: %d", dwLengthRequired);
1776 *ppSid = pSid;
1777 }
1778 }
1779 else
1780 {
1781 *ppSid = (PSID)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, dwLengthRequired);
1782 ExitOnNull(*ppSid, hr, E_OUTOFMEMORY, "Failed to allocate buffer for SID, len: %d", dwLengthRequired);
1783 }
1784
1785 ::InitializeSid(*ppSid, ::GetSidIdentifierAuthority(pDomainSid), ucSubAuthorityCount + (UCHAR)1);
1786
1787 // copy sub autorities
1788 DWORD i = 0;
1789 for (; i < ucSubAuthorityCount; i++)
1790 *::GetSidSubAuthority(*ppSid, i) = *::GetSidSubAuthority(pDomainSid, i);
1791 *::GetSidSubAuthority(*ppSid, i) = dwRid;
1792
1793 hr = S_OK;
1794
1795LExit:
1796 return hr;
1797}
1798
1799static HRESULT InitLsaUnicodeString(
1800 PLSA_UNICODE_STRING plusStr,
1801 LPCWSTR pwzStr,
1802 DWORD dwLen
1803 )
1804{
1805 HRESULT hr = S_OK;
1806
1807 plusStr->Length = (USHORT)dwLen * sizeof(WCHAR);
1808 plusStr->MaximumLength = (USHORT)(dwLen + 1) * sizeof(WCHAR);
1809
1810 plusStr->Buffer = (WCHAR*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR) * (dwLen + 1));
1811 ExitOnNull(plusStr->Buffer, hr, E_OUTOFMEMORY, "Failed to allocate account name string");
1812
1813 hr = StringCchCopyW(plusStr->Buffer, dwLen + 1, pwzStr);
1814 ExitOnFailure(hr, "Failed to copy buffer");
1815
1816 hr = S_OK;
1817
1818LExit:
1819 return hr;
1820}
1821
1822static void FreeLsaUnicodeString(
1823 PLSA_UNICODE_STRING plusStr
1824 )
1825{
1826 if (plusStr->Buffer)
1827 ::HeapFree(::GetProcessHeap(), 0, plusStr->Buffer);
1828}
1829
1830static HRESULT WriteFileAll(
1831 HANDLE hFile,
1832 PBYTE pbBuffer,
1833 DWORD dwBufferLength
1834 )
1835{
1836 HRESULT hr = S_OK;
1837
1838 DWORD dwBytesWritten;
1839
1840 while (dwBufferLength)
1841 {
1842 if (!::WriteFile(hFile, pbBuffer, dwBufferLength, &dwBytesWritten, NULL))
1843 ExitFunction1(hr = HRESULT_FROM_WIN32(::GetLastError()));
1844
1845 dwBufferLength -= dwBytesWritten;
1846 pbBuffer += dwBytesWritten;
1847 }
1848
1849 hr = S_OK;
1850
1851LExit:
1852 return hr;
1853}
1854
1855static HRESULT ReadFileAll(
1856 HANDLE hFile,
1857 PBYTE pbBuffer,
1858 DWORD dwBufferLength
1859 )
1860{
1861 HRESULT hr = S_OK;
1862
1863 DWORD dwBytesRead;
1864
1865 while (dwBufferLength)
1866 {
1867 if (!::ReadFile(hFile, pbBuffer, dwBufferLength, &dwBytesRead, NULL))
1868 ExitFunction1(hr = HRESULT_FROM_WIN32(::GetLastError()));
1869
1870 if (0 == dwBytesRead)
1871 ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_HANDLE_EOF));
1872
1873 dwBufferLength -= dwBytesRead;
1874 pbBuffer += dwBytesRead;
1875 }
1876
1877 hr = S_OK;
1878
1879LExit:
1880 return hr;
1881}