main
cpp 757 lines 21.7 KB
Raw
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 CPI_PARTITION_ATTRIBUTES
9 {
10 int iActionType;
11 int iActionCost;
12 LPWSTR pwzKey;
13 LPWSTR pwzID;
14 LPWSTR pwzName;
15 CPI_PROPERTY* pPropList;
16 };
17
18 struct CPI_PARTITION_USER_ATTRIBUTES
19 {
20 int iActionType;
21 int iActionCost;
22 LPWSTR pwzKey;
23 LPWSTR pwzAccount;
24 LPWSTR pwzPartID;
25 };
26
27
28 // prototypes for private helper functions
29
30 static HRESULT ReadPartitionAttributes(
31 LPWSTR* ppwzData,
32 CPI_PARTITION_ATTRIBUTES* pAttrs
33 );
34 static void FreePartitionAttributes(
35 CPI_PARTITION_ATTRIBUTES* pAttrs
36 );
37 static HRESULT CpiEnsurePartitionsEnabled();
38 static HRESULT CreatePartition(
39 CPI_PARTITION_ATTRIBUTES* pAttrs
40 );
41 static HRESULT RemovePartition(
42 CPI_PARTITION_ATTRIBUTES* pAttrs
43 );
44 static HRESULT ReadPartitionUserAttributes(
45 LPWSTR* ppwzData,
46 CPI_PARTITION_USER_ATTRIBUTES* pAttrs
47 );
48 static void FreePartitionUserAttributes(
49 CPI_PARTITION_USER_ATTRIBUTES* pAttrs
50 );
51 static HRESULT CreatePartitionUser(
52 CPI_PARTITION_USER_ATTRIBUTES* pAttrs
53 );
54 static HRESULT RemovePartitionUser(
55 CPI_PARTITION_USER_ATTRIBUTES* pAttrs
56 );
57
58
59 // function definitions
60
61 HRESULT CpiConfigurePartitions(
62 LPWSTR* ppwzData,
63 HANDLE hRollbackFile
64 )
65 {
66 HRESULT hr = S_OK;
67
68 CPI_PARTITION_ATTRIBUTES attrs;
69 ::ZeroMemory(&attrs, sizeof(attrs));
70
71 // read action text
72 hr = CpiActionStartMessage(ppwzData, FALSE);
73 ExitOnFailure(hr, "Failed to send action start message");
74
75 // get partition count
76 int iCnt = 0;
77 hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
78 ExitOnFailure(hr, "Failed to read count");
79
80 // write count to rollback file
81 hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt);
82 ExitOnFailure(hr, "Failed to write count to rollback file");
83
84 for (int i = 0; i < iCnt; i++)
85 {
86 // read partition attributes from CustomActionData
87 hr = ReadPartitionAttributes(ppwzData, &attrs);
88 ExitOnFailure(hr, "Failed to read attributes");
89
90 // progress message
91 hr = CpiActionDataMessage(1, attrs.pwzName);
92 ExitOnFailure(hr, "Failed to send progress messages");
93
94 if (S_FALSE == hr)
95 ExitFunction();
96
97 // write key to rollback file
98 hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey);
99 ExitOnFailure(hr, "Failed to write key to rollback file");
100
101 // action
102 switch (attrs.iActionType)
103 {
104 case atCreate:
105 hr = CreatePartition(&attrs);
106 ExitOnFailure(hr, "Failed to create partition, key: %S", attrs.pwzKey);
107 break;
108 case atRemove:
109 hr = RemovePartition(&attrs);
110 ExitOnFailure(hr, "Failed to remove partition, key: %S", attrs.pwzKey);
111 break;
112 }
113
114 // write completion status to rollback file
115 hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1);
116 ExitOnFailure(hr, "Failed to write completion status to rollback file");
117
118 // progress
119 hr = WcaProgressMessage(attrs.iActionCost, FALSE);
120 ExitOnFailure(hr, "Failed to update progress");
121 }
122
123 hr = S_OK;
124
125 LExit:
126 // clean up
127 FreePartitionAttributes(&attrs);
128
129 return hr;
130 }
131
132 HRESULT CpiRollbackConfigurePartitions(
133 LPWSTR* ppwzData,
134 CPI_ROLLBACK_DATA* pRollbackDataList
135 )
136 {
137 HRESULT hr = S_OK;
138
139 int iRollbackStatus;
140
141 CPI_PARTITION_ATTRIBUTES attrs;
142 ::ZeroMemory(&attrs, sizeof(attrs));
143
144 // read action text
145 hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList);
146 ExitOnFailure(hr, "Failed to send action start message");
147
148 // get count
149 int iCnt = 0;
150 hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
151 ExitOnFailure(hr, "Failed to read count");
152
153 for (int i = 0; i < iCnt; i++)
154 {
155 // read partition attributes from CustomActionData
156 hr = ReadPartitionAttributes(ppwzData, &attrs);
157 ExitOnFailure(hr, "Failed to read attributes");
158
159 // rollback status
160 hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus);
161
162 if (S_FALSE == hr)
163 continue; // not found, nothing to rollback
164
165 // progress message
166 hr = CpiActionDataMessage(1, attrs.pwzName);
167 ExitOnFailure(hr, "Failed to send progress messages");
168
169 if (S_FALSE == hr)
170 ExitFunction();
171
172 // action
173 switch (attrs.iActionType)
174 {
175 case atCreate:
176 hr = CreatePartition(&attrs);
177 if (FAILED(hr))
178 WcaLog(LOGMSG_STANDARD, "Failed to create partition, hr: 0x%x, key: %S", hr, attrs.pwzKey);
179 break;
180 case atRemove:
181 hr = RemovePartition(&attrs);
182 if (FAILED(hr))
183 WcaLog(LOGMSG_STANDARD, "Failed to remove partition, hr: 0x%x, key: %S", hr, attrs.pwzKey);
184 break;
185 }
186
187 // check rollback status
188 if (0 == iRollbackStatus)
189 continue; // operation did not complete, skip progress
190
191 // progress
192 hr = WcaProgressMessage(attrs.iActionCost, FALSE);
193 ExitOnFailure(hr, "Failed to update progress");
194 }
195
196 hr = S_OK;
197
198 LExit:
199 // clean up
200 FreePartitionAttributes(&attrs);
201
202 return hr;
203 }
204
205 HRESULT CpiConfigurePartitionUsers(
206 LPWSTR* ppwzData,
207 HANDLE hRollbackFile
208 )
209 {
210 HRESULT hr = S_OK;
211
212 CPI_PARTITION_USER_ATTRIBUTES attrs;
213 ::ZeroMemory(&attrs, sizeof(attrs));
214
215 // read action text
216 hr = CpiActionStartMessage(ppwzData, FALSE);
217 ExitOnFailure(hr, "Failed to send action start message");
218
219 // get partition count
220 int iCnt = 0;
221 hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
222 ExitOnFailure(hr, "Failed to read count");
223
224 // write count to rollback file
225 hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt);
226 ExitOnFailure(hr, "Failed to write count to rollback file");
227
228 for (int i = 0; i < iCnt; i++)
229 {
230 // read partition attributes from CustomActionData
231 hr = ReadPartitionUserAttributes(ppwzData, &attrs);
232 ExitOnFailure(hr, "Failed to read attributes");
233
234 // progress message
235 hr = CpiActionDataMessage(1, attrs.pwzAccount);
236 ExitOnFailure(hr, "Failed to send progress messages");
237
238 if (S_FALSE == hr)
239 ExitFunction();
240
241 // write key to rollback file
242 hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey);
243 ExitOnFailure(hr, "Failed to write key to rollback file");
244
245 // action
246 switch (attrs.iActionType)
247 {
248 case atCreate:
249 hr = CreatePartitionUser(&attrs);
250 ExitOnFailure(hr, "Failed to create partition user, key: %S", attrs.pwzKey);
251 break;
252 case atRemove:
253 hr = RemovePartitionUser(&attrs);
254 ExitOnFailure(hr, "Failed to remove partition user, key: %S", attrs.pwzKey);
255 break;
256 }
257
258 // write completion status to rollback file
259 hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1);
260 ExitOnFailure(hr, "Failed to write completion status to rollback file");
261
262 // progress
263 hr = WcaProgressMessage(attrs.iActionCost, FALSE);
264 ExitOnFailure(hr, "Failed to update progress");
265 }
266
267 hr = S_OK;
268
269 LExit:
270 // clean up
271 FreePartitionUserAttributes(&attrs);
272
273 return hr;
274 }
275
276 HRESULT CpiRollbackConfigurePartitionUsers(
277 LPWSTR* ppwzData,
278 CPI_ROLLBACK_DATA* pRollbackDataList
279 )
280 {
281 HRESULT hr = S_OK;
282
283 int iRollbackStatus;
284
285 CPI_PARTITION_USER_ATTRIBUTES attrs;
286 ::ZeroMemory(&attrs, sizeof(attrs));
287
288 // read action text
289 hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList);
290 ExitOnFailure(hr, "Failed to send action start message");
291
292 // get count
293 int iCnt = 0;
294 hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
295 ExitOnFailure(hr, "Failed to read count");
296
297 for (int i = 0; i < iCnt; i++)
298 {
299 // read partition attributes from CustomActionData
300 hr = ReadPartitionUserAttributes(ppwzData, &attrs);
301 ExitOnFailure(hr, "Failed to read attributes");
302
303 // rollback status
304 hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus);
305
306 if (S_FALSE == hr)
307 continue; // not found, nothing to rollback
308
309 // progress message
310 hr = CpiActionDataMessage(1, attrs.pwzAccount);
311 ExitOnFailure(hr, "Failed to send progress messages");
312
313 if (S_FALSE == hr)
314 ExitFunction();
315
316 // action
317 switch (attrs.iActionType)
318 {
319 case atCreate:
320 hr = CreatePartitionUser(&attrs);
321 ExitOnFailure(hr, "Failed to create partition user, key: %S", attrs.pwzKey);
322 break;
323 case atRemove:
324 hr = RemovePartitionUser(&attrs);
325 ExitOnFailure(hr, "Failed to remove partition user, key: %S", attrs.pwzKey);
326 break;
327 }
328
329 // check rollback status
330 if (0 == iRollbackStatus)
331 continue; // operation did not complete, skip progress
332
333 // progress
334 hr = WcaProgressMessage(attrs.iActionCost, FALSE);
335 ExitOnFailure(hr, "Failed to update progress");
336 }
337
338 hr = S_OK;
339
340 LExit:
341 // clean up
342 FreePartitionUserAttributes(&attrs);
343
344 return hr;
345 }
346
347
348 // helper function definitions
349
350 static HRESULT ReadPartitionAttributes(
351 LPWSTR* ppwzData,
352 CPI_PARTITION_ATTRIBUTES* pAttrs
353 )
354 {
355 HRESULT hr = S_OK;
356
357 hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType);
358 ExitOnFailure(hr, "Failed to read action type");
359 hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost);
360 ExitOnFailure(hr, "Failed to read action cost");
361 hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey);
362 ExitOnFailure(hr, "Failed to read key");
363 hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzID);
364 ExitOnFailure(hr, "Failed to read id");
365 hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzName);
366 ExitOnFailure(hr, "Failed to read name");
367 hr = CpiReadPropertyList(ppwzData, &pAttrs->pPropList);
368 ExitOnFailure(hr, "Failed to read properties");
369
370 hr = S_OK;
371
372 LExit:
373 return hr;
374 }
375
376 static void FreePartitionAttributes(
377 CPI_PARTITION_ATTRIBUTES* pAttrs
378 )
379 {
380 ReleaseStr(pAttrs->pwzKey);
381 ReleaseStr(pAttrs->pwzID);
382 ReleaseStr(pAttrs->pwzName);
383
384 if (pAttrs->pPropList)
385 CpiFreePropertyList(pAttrs->pPropList);
386 }
387
388 static HRESULT CpiEnsurePartitionsEnabled()
389 {
390 HRESULT hr = S_OK;
391
392 ICatalogCollection* piLocalComputerColl = NULL;
393 IDispatch* piDisp = NULL;
394 ICatalogObject* piLocalComputerObj = NULL;
395 VARIANT vtVal;
396 BSTR bsPartitionsEnabledName = ::SysAllocString(L"PartitionsEnabled");
397 long numChanges = 0;
398
399 ::VariantInit(&vtVal);
400
401 // get collection
402 hr = CpiExecGetCatalogCollection(L"LocalComputer", &piLocalComputerColl);
403 ExitOnFailure(hr, "Failed to get catalog collection");
404
405 // find object, there will be only one in the LocalComputer collection
406 hr = piLocalComputerColl->get_Item(0, &piDisp);
407 ExitOnFailure(hr, "Failed to get object from collection");
408
409 hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piLocalComputerObj);
410 ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface");
411
412 // and then we get the value of the PartitionsEnabled property
413 hr = piLocalComputerObj->get_Value(bsPartitionsEnabledName, &vtVal);
414 if (!vtVal.boolVal)
415 {
416 vtVal.boolVal = true;
417 hr = piLocalComputerObj->put_Value(bsPartitionsEnabledName, vtVal);
418 ExitOnFailure(hr, "Failed to put value to Enable COM+ PartitionsEnabled property");
419 hr = piLocalComputerColl->SaveChanges(&numChanges);
420 ExitOnFailure(hr, "Failed to save PartitionsEnabled property");
421
422 // we'll read back the hopefully updated values of the PartitionsEnabled property
423 // if it's still False, then we're on a Windows Desktop that doesn't allow Partitions
424 // (as of Windows Server2003 Microsoft limited Partitions to only ServerOS platforms)
425 hr = piLocalComputerObj->get_Value(bsPartitionsEnabledName, &vtVal);
426 ExitOnFailure(hr, "Failed to read PartitionsEnabled property");
427 }
428
429 if (vtVal.boolVal)
430 {
431 // everything went well, we have the Partitioning available
432 hr = S_OK;
433 }
434 else
435 {
436 // we're on a Desktop OS, or couldn't otherwise enable partitioning
437 WcaLog(LOGMSG_STANDARD, "Failed to Enable COM+ PartitionEnabled property. This suggests Partitioning was attempted on a Desktop OS, which is not supported");
438 hr = S_FALSE;
439 }
440
441 LExit:
442 // clean up
443 ReleaseObject(piLocalComputerColl);
444 ReleaseObject(piLocalComputerObj);
445 ReleaseBSTR(bsPartitionsEnabledName);
446 ::VariantClear(&vtVal);
447
448 return hr;
449 }
450
451 static HRESULT CreatePartition(
452 CPI_PARTITION_ATTRIBUTES* pAttrs
453 )
454 {
455 HRESULT hr = S_OK;
456
457 ICatalogCollection* piPartColl = NULL;
458 ICatalogObject* piPartObj = NULL;
459
460 long lChanges = 0;
461
462 // log
463 WcaLog(LOGMSG_VERBOSE, "Creating partition, key: %S", pAttrs->pwzKey);
464
465 // get partitions collection
466 hr = CpiExecGetPartitionsCollection(&piPartColl);
467 ExitOnFailure(hr, "Failed to get partitions collection");
468
469 // check if partition exists
470 hr = CpiFindCollectionObjectByStringKey(piPartColl, pAttrs->pwzID, &piPartObj);
471 ExitOnFailure(hr, "Failed to find partition");
472
473 if (S_FALSE == hr)
474 {
475 hr = CpiEnsurePartitionsEnabled();
476 ExitOnFailure(hr, "Failed to enable partitions");
477
478 // create partition
479 hr = CpiAddCollectionObject(piPartColl, &piPartObj);
480 ExitOnFailure(hr, "Failed to add partition to collection");
481
482 hr = CpiPutCollectionObjectValue(piPartObj, L"ID", pAttrs->pwzID);
483 ExitOnFailure(hr, "Failed to set partition id property");
484
485 hr = CpiPutCollectionObjectValue(piPartObj, L"Name", pAttrs->pwzName);
486 ExitOnFailure(hr, "Failed to set partition name property");
487 }
488
489 // properties
490 hr = CpiPutCollectionObjectValues(piPartObj, pAttrs->pPropList);
491 ExitOnFailure(hr, "Failed to write properties");
492
493 // save changes
494 hr = piPartColl->SaveChanges(&lChanges);
495 if (COMADMIN_E_OBJECTERRORS == hr)
496 CpiLogCatalogErrorInfo();
497 ExitOnFailure(hr, "Failed to save changes");
498
499 // log
500 WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey);
501
502 hr = S_OK;
503
504 LExit:
505 // clean up
506 ReleaseObject(piPartColl);
507 ReleaseObject(piPartObj);
508
509 return hr;
510 }
511
512 static HRESULT RemovePartition(
513 CPI_PARTITION_ATTRIBUTES* pAttrs
514 )
515 {
516 HRESULT hr = S_OK;
517
518 ICatalogCollection* piPartColl = NULL;
519
520 long lChanges = 0;
521
522 // log
523 WcaLog(LOGMSG_VERBOSE, "Removing partition, key: %S", pAttrs->pwzKey);
524
525 // get partitions collection
526 hr = CpiExecGetPartitionsCollection(&piPartColl);
527 ExitOnFailure(hr, "Failed to get partitions collection");
528
529 // remove
530 hr = CpiRemoveCollectionObject(piPartColl, pAttrs->pwzID, NULL, TRUE);
531 ExitOnFailure(hr, "Failed to remove partition");
532
533 if (S_FALSE == hr)
534 {
535 // partition not found
536 WcaLog(LOGMSG_VERBOSE, "Partition not found, nothing to delete, key: %S", pAttrs->pwzKey);
537 ExitFunction1(hr = S_OK);
538 }
539
540 // save changes
541 hr = piPartColl->SaveChanges(&lChanges);
542 if (COMADMIN_E_OBJECTERRORS == hr)
543 CpiLogCatalogErrorInfo();
544 ExitOnFailure(hr, "Failed to save changes");
545
546 // log
547 WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey);
548
549 hr = S_OK;
550
551 LExit:
552 // clean up
553 ReleaseObject(piPartColl);
554
555 return hr;
556 }
557
558 static HRESULT ReadPartitionUserAttributes(
559 LPWSTR* ppwzData,
560 CPI_PARTITION_USER_ATTRIBUTES* pAttrs
561 )
562 {
563 HRESULT hr = S_OK;
564
565 hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType);
566 ExitOnFailure(hr, "Failed to read action type");
567 hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost);
568 ExitOnFailure(hr, "Failed to read action cost");
569 hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey);
570 ExitOnFailure(hr, "Failed to read key");
571 hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAccount);
572 ExitOnFailure(hr, "Failed to read account name");
573 hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID);
574 ExitOnFailure(hr, "Failed to read partition id");
575
576 hr = S_OK;
577
578 LExit:
579 return hr;
580 }
581
582 static void FreePartitionUserAttributes(
583 CPI_PARTITION_USER_ATTRIBUTES* pAttrs
584 )
585 {
586 ReleaseStr(pAttrs->pwzKey);
587 ReleaseStr(pAttrs->pwzAccount);
588 ReleaseStr(pAttrs->pwzPartID);
589 }
590
591 static HRESULT CreatePartitionUser(
592 CPI_PARTITION_USER_ATTRIBUTES* pAttrs
593 )
594 {
595 HRESULT hr = S_OK;
596 UINT er = ERROR_SUCCESS;
597
598 ICatalogCollection* piUserColl = NULL;
599 ICatalogObject* piUserObj = NULL;
600
601 PSID pSid = NULL;
602 long lChanges = 0;
603
604 // log
605 WcaLog(LOGMSG_VERBOSE, "Setting default partition for user, key: %S", pAttrs->pwzKey);
606
607 // get partition users collection
608 hr = CpiGetPartitionUsersCollection(&piUserColl);
609 ExitOnFailure(hr, "Failed to get partition users collection");
610
611 // get SID for account
612 do {
613 er = ERROR_SUCCESS;
614 hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid);
615 if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK))
616 {
617 WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount);
618 er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
619 switch (er)
620 {
621 case IDABORT:
622 ExitFunction(); // exit with error code from CpiAccountNameToSid()
623 case IDRETRY:
624 break;
625 case IDIGNORE:
626 default:
627 ExitFunction1(hr = S_OK);
628 }
629 }
630 else
631 ExitOnFailure(hr, "Failed to get SID for account");
632 } while (IDRETRY == er);
633
634 // remove any existing entry
635 hr = CpiRemoveUserCollectionObject(piUserColl, pSid);
636 if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr)
637 {
638 WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr);
639 hr = S_FALSE;
640 }
641 else
642 ExitOnFailure(hr, "Failed to remove user");
643
644 if (S_OK == hr)
645 WcaLog(LOGMSG_VERBOSE, "Existing default partition for user was removed, key: %S", pAttrs->pwzKey);
646
647 // add partition user
648 hr = CpiAddCollectionObject(piUserColl, &piUserObj);
649 ExitOnFailure(hr, "Failed to add partition to collection");
650
651 hr = CpiPutCollectionObjectValue(piUserObj, L"AccountName", pAttrs->pwzAccount);
652 ExitOnFailure(hr, "Failed to set account name property");
653
654 hr = CpiPutCollectionObjectValue(piUserObj, L"DefaultPartitionID", pAttrs->pwzPartID);
655 ExitOnFailure(hr, "Failed to set default partition id property");
656
657 // save changes
658 hr = piUserColl->SaveChanges(&lChanges);
659 if (COMADMIN_E_OBJECTERRORS == hr)
660 CpiLogCatalogErrorInfo();
661 ExitOnFailure(hr, "Failed to save changes");
662
663 // log
664 WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey);
665
666 hr = S_OK;
667
668 LExit:
669 // clean up
670 ReleaseObject(piUserColl);
671 ReleaseObject(piUserObj);
672
673 if (pSid)
674 ::HeapFree(::GetProcessHeap(), 0, pSid);
675
676 return hr;
677 }
678
679 static HRESULT RemovePartitionUser(
680 CPI_PARTITION_USER_ATTRIBUTES* pAttrs
681 )
682 {
683 HRESULT hr = S_OK;
684 UINT er = ERROR_SUCCESS;
685
686 ICatalogCollection* piUserColl = NULL;
687
688 PSID pSid = NULL;
689 long lChanges = 0;
690
691 // log
692 WcaLog(LOGMSG_VERBOSE, "Removing default partition for user, key: %S", pAttrs->pwzKey);
693
694 // get partition users collection
695 hr = CpiGetPartitionUsersCollection(&piUserColl);
696 ExitOnFailure(hr, "Failed to get partition users collection");
697
698 // get SID for account
699 do {
700 er = ERROR_SUCCESS;
701 hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid);
702 if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK))
703 {
704 WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount);
705 er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
706 switch (er)
707 {
708 case IDABORT:
709 ExitFunction(); // exit with error code from CpiAccountNameToSid()
710 case IDRETRY:
711 break;
712 case IDIGNORE:
713 default:
714 ExitFunction1(hr = S_OK);
715 }
716 }
717 else
718 ExitOnFailure(hr, "Failed to get SID for account");
719 } while (IDRETRY == er);
720
721 // remove
722 hr = CpiRemoveUserCollectionObject(piUserColl, pSid);
723 if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr)
724 {
725 WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr);
726 hr = S_FALSE;
727 }
728 else
729 ExitOnFailure(hr, "Failed to remove user");
730
731 if (S_FALSE == hr)
732 {
733 // user not found
734 WcaLog(LOGMSG_VERBOSE, "Default partition for user not found, nothing to delete, key: %S", pAttrs->pwzKey);
735 ExitFunction1(hr = S_OK);
736 }
737
738 // save changes
739 hr = piUserColl->SaveChanges(&lChanges);
740 if (COMADMIN_E_OBJECTERRORS == hr)
741 CpiLogCatalogErrorInfo();
742 ExitOnFailure(hr, "Failed to save changes");
743
744 // log
745 WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey);
746
747 hr = S_OK;
748
749 LExit:
750 // clean up
751 ReleaseObject(piUserColl);
752
753 if (pSid)
754 ::HeapFree(::GetProcessHeap(), 0, pSid);
755
756 return hr;
757 }