aboutsummaryrefslogtreecommitdiff
path: root/src/ext/ComPlus/ca/cppartsched.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ext/ComPlus/ca/cppartsched.cpp')
-rw-r--r--src/ext/ComPlus/ca/cppartsched.cpp912
1 files changed, 912 insertions, 0 deletions
diff --git a/src/ext/ComPlus/ca/cppartsched.cpp b/src/ext/ComPlus/ca/cppartsched.cpp
new file mode 100644
index 00000000..7cd98791
--- /dev/null
+++ b/src/ext/ComPlus/ca/cppartsched.cpp
@@ -0,0 +1,912 @@
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// sql queries
7
8LPCWSTR vcsPartitionQuery =
9 L"SELECT `Partition`, `Component_`, `Id`, `Name` FROM `ComPlusPartition`";
10enum ePartitionQuery { pqPartition = 1, pqComponent, pqID, pqName };
11
12LPCWSTR vcsPartitionPropertyQuery =
13 L"SELECT `Name`, `Value` FROM `ComPlusPartitionProperty` WHERE `Partition_` = ?";
14
15LPCWSTR vcsPartitionUserQuery =
16 L"SELECT `PartitionUser`, `Partition_`, `ComPlusPartitionUser`.`Component_`, `Domain`, `Name` FROM `ComPlusPartitionUser`, `User` WHERE `User_` = `User`";
17enum ePartitionUserQuery { puqPartitionUser = 1, puqPartition, puqComponent, puqDomain, puqName };
18
19
20// property definitions
21
22CPI_PROPERTY_DEFINITION pdlPartitionProperties[] =
23{
24 {L"Changeable", cpptBoolean, 502},
25 {L"Deleteable", cpptBoolean, 502},
26 {L"Description", cpptString, 502},
27 {NULL, cpptNone, 0}
28};
29
30
31// prototypes for private helper functions
32
33static void FreePartition(
34 CPI_PARTITION* pItm
35 );
36static void FreePartitionUser(
37 CPI_PARTITION_USER* pItm
38 );
39static HRESULT AddPartitionToActionData(
40 CPI_PARTITION* pItm,
41 int iActionType,
42 int iActionCost,
43 LPWSTR* ppwzActionData
44 );
45static HRESULT AddPartitionUserToActionData(
46 CPI_PARTITION_USER* pItm,
47 int iActionType,
48 int iActionCost,
49 LPWSTR* ppwzActionData
50 );
51
52
53// function definitions
54
55void CpiPartitionListFree(
56 CPI_PARTITION_LIST* pList
57 )
58{
59 CPI_PARTITION* pItm = pList->pFirst;
60
61 while (pItm)
62 {
63 CPI_PARTITION* pDelete = pItm;
64 pItm = pItm->pNext;
65 FreePartition(pDelete);
66 }
67}
68
69HRESULT CpiPartitionsRead(
70 CPI_PARTITION_LIST* pPartList
71 )
72{
73 HRESULT hr = S_OK;
74 UINT er = ERROR_SUCCESS;
75
76 PMSIHANDLE hView, hRec;
77
78 CPI_PARTITION* pItm = NULL;
79 LPWSTR pwzData = NULL;
80 BOOL fMatchingArchitecture = FALSE;
81
82 // loop through all partitions
83 hr = WcaOpenExecuteView(vcsPartitionQuery, &hView);
84 ExitOnFailure(hr, "Failed to execute view on ComPlusPartition table");
85
86 while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
87 {
88 // get component
89 hr = WcaGetRecordString(hRec, pqComponent, &pwzData);
90 ExitOnFailure(hr, "Failed to get component");
91
92 // check if the component is our processor architecture
93 if (pwzData && *pwzData)
94 {
95 hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture);
96 ExitOnFailure(hr, "Failed to get component architecture.");
97
98 if (!fMatchingArchitecture)
99 {
100 continue; // not the same architecture, ignore
101 }
102 }
103
104 // create entry
105 pItm = (CPI_PARTITION*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PARTITION));
106 if (!pItm)
107 ExitFunction1(hr = E_OUTOFMEMORY);
108
109 // get component install state
110 if (pwzData && *pwzData)
111 {
112 pItm->fHasComponent = TRUE;
113
114 er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction);
115 ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state");
116 }
117
118 // get key
119 hr = WcaGetRecordString(hRec, pqPartition, &pwzData);
120 ExitOnFailure(hr, "Failed to get key");
121 StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);
122
123 // get id
124 hr = WcaGetRecordFormattedString(hRec, pqID, &pwzData);
125 ExitOnFailure(hr, "Failed to get id");
126
127 if (pwzData && *pwzData)
128 {
129 hr = PcaGuidToRegFormat(pwzData, pItm->wzID, countof(pItm->wzID));
130 ExitOnFailure(hr, "Failed to parse id guid value, key: %S, value: '%S'", pItm->wzKey, pwzData);
131 }
132
133 // get name
134 hr = WcaGetRecordFormattedString(hRec, pqName, &pwzData);
135 ExitOnFailure(hr, "Failed to get name");
136 StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData);
137
138 // if partition is a locater, either an id or a name must be provided
139 if (!pItm->fHasComponent && !*pItm->wzID && !*pItm->wzName)
140 ExitOnFailure(hr = E_FAIL, "A partition locater must have either an id or a name associated, key: %S", pItm->wzKey);
141
142 // if partition is not a locater, an name must be provided
143 if (pItm->fHasComponent && !*pItm->wzName)
144 ExitOnFailure(hr = E_FAIL, "A partition must have a name associated, key: %S", pItm->wzKey);
145
146 // get properties
147 if (CpiTableExists(cptComPlusPartitionProperty) && pItm->fHasComponent)
148 {
149 hr = CpiPropertiesRead(vcsPartitionPropertyQuery, pItm->wzKey, pdlPartitionProperties, &pItm->pProperties, &pItm->iPropertyCount);
150 ExitOnFailure(hr, "Failed to get properties");
151 }
152
153 // increment counters
154 if (pItm->fHasComponent && WcaIsInstalling(pItm->isInstalled, pItm->isAction))
155 pPartList->iInstallCount++;
156 if (pItm->fHasComponent && WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
157 pPartList->iUninstallCount++;
158
159 // add entry
160 if (pPartList->pFirst)
161 pItm->pNext = pPartList->pFirst;
162 pPartList->pFirst = pItm;
163 pItm = NULL;
164 }
165
166 if (E_NOMOREITEMS == hr)
167 hr = S_OK;
168
169LExit:
170 // clean up
171 if (pItm)
172 FreePartition(pItm);
173
174 ReleaseStr(pwzData);
175
176 return hr;
177}
178
179HRESULT CpiPartitionsVerifyInstall(
180 CPI_PARTITION_LIST* pList
181 )
182{
183 HRESULT hr = S_OK;
184 UINT er = ERROR_SUCCESS;
185
186 ICatalogCollection* piPartColl = NULL;
187 ICatalogObject* piPartObj = NULL;
188
189 for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
190 {
191 // referenced locaters or partitions that are being installed
192 if (!pItm->fReferencedForInstall && !(pItm->fHasComponent && WcaIsInstalling(pItm->isInstalled, pItm->isAction)))
193 continue;
194
195 // if the partition is referensed and is not a locater, it must be installed
196 if (pItm->fReferencedForInstall && pItm->fHasComponent && !CpiWillBeInstalled(pItm->isInstalled, pItm->isAction))
197 MessageExitOnFailure(hr = E_FAIL, msierrComPlusPartitionDependency, "A partition is used by another entity being installed, but is not installed itself, key: %S", pItm->wzKey);
198
199 // get partitions collection
200 if (!piPartColl)
201 {
202 hr = CpiSchedGetPartitionsCollection(&piPartColl);
203 ExitOnFailure(hr, "Failed to get partitions collection");
204 }
205
206 // partition is supposed to exist
207 if (!pItm->fHasComponent || CpiIsInstalled(pItm->isInstalled))
208 {
209 // get collection object for partition
210 hr = CpiFindCollectionObject(piPartColl, pItm->wzID, *pItm->wzID ? NULL : pItm->wzName, &piPartObj);
211 ExitOnFailure(hr, "Failed to find collection object for partition");
212
213 // if the partition was found
214 if (S_OK == hr)
215 {
216 // if we don't have an id, copy id from object
217 if (!*pItm->wzID)
218 {
219 hr = CpiGetKeyForObject(piPartObj, pItm->wzID, countof(pItm->wzID));
220 ExitOnFailure(hr, "Failed to get id");
221 }
222 }
223
224 // if the partition was not found
225 else
226 {
227 // if the application is a locater, this is an error
228 if (!pItm->fHasComponent)
229 MessageExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), msierrComPlusPartitionNotFound, "A partition required by this installation was not found, key: %S", pItm->wzKey);
230
231 // create a new id if one is missing
232 if (!*pItm->wzID)
233 {
234 hr = CpiCreateId(pItm->wzID, countof(pItm->wzID));
235 ExitOnFailure(hr, "Failed to create id");
236 }
237 }
238 }
239
240 // partition is supposed to be created
241 else
242 {
243 // check for conflicts
244 do {
245 if (*pItm->wzID)
246 {
247 // find partitions with conflicting id
248 hr = CpiFindCollectionObject(piPartColl, pItm->wzID, NULL, &piPartObj);
249 ExitOnFailure(hr, "Failed to find collection object for partition");
250
251 if (S_FALSE == hr)
252 {
253 // find partitions with conflicting name
254 hr = CpiFindCollectionObject(piPartColl, NULL, pItm->wzName, &piPartObj);
255 ExitOnFailure(hr, "Failed to find collection object for partition");
256
257 if (S_OK == hr)
258 // "A partition with a conflictiong name exists. retry cancel"
259 er = WcaErrorMessage(msierrComPlusPartitionNameConflict, hr, INSTALLMESSAGE_ERROR | MB_RETRYCANCEL, 0);
260 else
261 break; // no conflicting entry found, break loop
262 }
263 else
264 // "A partition with a conflicting id exists. abort retry ignore"
265 er = WcaErrorMessage(msierrComPlusPartitionIdConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
266 }
267 else
268 {
269 // find partitions with conflicting name
270 hr = CpiFindCollectionObject(piPartColl, NULL, pItm->wzName, &piPartObj);
271 ExitOnFailure(hr, "Failed to find collection object for partition");
272
273 if (S_OK == hr)
274 // "A partition with a conflictiong name exists. abort retry ignore"
275 er = WcaErrorMessage(msierrComPlusPartitionNameConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
276 else
277 break; // no conflicting entry found, break loop
278 }
279
280 switch (er)
281 {
282 case IDCANCEL:
283 case IDABORT:
284 ExitOnFailure(hr = E_FAIL, "A partition with a conflictiong name or id exists, key: %S", pItm->wzKey);
285 break;
286 case IDRETRY:
287 break;
288 case IDIGNORE:
289 default:
290 // if we don't have an id, copy id from object
291 if (!*pItm->wzID)
292 {
293 hr = CpiGetKeyForObject(piPartObj, pItm->wzID, countof(pItm->wzID));
294 ExitOnFailure(hr, "Failed to get id");
295 }
296 hr = S_FALSE; // indicate that this is not a conflict
297 }
298 } while (S_OK == hr); // hr = S_FALSE if we don't have any conflicts
299
300 // create a new id if one is missing
301 if (!*pItm->wzID)
302 {
303 hr = CpiCreateId(pItm->wzID, countof(pItm->wzID));
304 ExitOnFailure(hr, "Failed to create id");
305 }
306 }
307
308 // clean up
309 ReleaseNullObject(piPartObj);
310 }
311
312 hr = S_OK;
313
314LExit:
315 // clean up
316 ReleaseObject(piPartColl);
317 ReleaseObject(piPartObj);
318
319 return hr;
320}
321
322HRESULT CpiPartitionsVerifyUninstall(
323 CPI_PARTITION_LIST* pList
324 )
325{
326 HRESULT hr = S_OK;
327 ICatalogCollection* piPartColl = NULL;
328 ICatalogObject* piPartObj = NULL;
329
330 for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
331 {
332 // referenced locaters or partitions that are being uninstalled
333 if (!pItm->fReferencedForUninstall && !(pItm->fHasComponent && WcaIsUninstalling(pItm->isInstalled, pItm->isAction)))
334 continue;
335
336 // get partitions collection
337 if (!piPartColl)
338 {
339 hr = CpiSchedGetPartitionsCollection(&piPartColl);
340 ExitOnFailure(hr, "Failed to get partitions collection");
341 }
342
343 // get collection object for partition
344 hr = CpiFindCollectionObject(piPartColl, pItm->wzID, *pItm->wzID ? NULL : pItm->wzName, &piPartObj);
345 ExitOnFailure(hr, "Failed to find collection object for partition");
346
347 // if the partition was found
348 if (S_OK == hr)
349 {
350 // if we don't have an id, copy id from object
351 if (!*pItm->wzID)
352 {
353 hr = CpiGetKeyForObject(piPartObj, pItm->wzID, countof(pItm->wzID));
354 ExitOnFailure(hr, "Failed to get id");
355 }
356 }
357
358 // if the partition was not found
359 else
360 {
361 pItm->fObjectNotFound = TRUE;
362 if (pItm->fHasComponent)
363 pList->iUninstallCount--; // elements with the fObjectNotFound flag set will not be scheduled for uninstall
364 }
365
366 // clean up
367 ReleaseNullObject(piPartObj);
368 }
369
370 hr = S_OK;
371
372LExit:
373 // clean up
374 ReleaseObject(piPartColl);
375 ReleaseObject(piPartObj);
376
377 return hr;
378}
379
380void CpiPartitionAddReferenceInstall(
381 CPI_PARTITION* pItm
382 )
383{
384 pItm->fReferencedForInstall = TRUE;
385}
386
387void CpiPartitionAddReferenceUninstall(
388 CPI_PARTITION* pItm
389 )
390{
391 pItm->fReferencedForUninstall = TRUE;
392}
393
394HRESULT CpiPartitionsInstall(
395 CPI_PARTITION_LIST* pList,
396 int iRunMode,
397 LPWSTR* ppwzActionData,
398 int* piProgress
399 )
400{
401 HRESULT hr = S_OK;
402
403 int iActionType;
404
405 // add action text
406 hr = CpiAddActionTextToActionData(L"CreateComPlusPartitions", ppwzActionData);
407 ExitOnFailure(hr, "Failed to add action text to custom action data");
408
409 // add partition count to action data
410 hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData);
411 ExitOnFailure(hr, "Failed to add count to custom action data");
412
413 // add applications to custom action data
414 for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
415 {
416 // partitions that are being installed only
417 if (!pItm->fHasComponent || !WcaIsInstalling(pItm->isInstalled, pItm->isAction))
418 continue;
419
420 // action type
421 if (rmRollback == iRunMode)
422 {
423 if (CpiIsInstalled(pItm->isInstalled))
424 iActionType = atNoOp;
425 else
426 iActionType = atRemove;
427 }
428 else
429 iActionType = atCreate;
430
431 // add to action data
432 hr = AddPartitionToActionData(pItm, iActionType, COST_PARTITION_CREATE, ppwzActionData);
433 ExitOnFailure(hr, "Failed to add partition to custom action data, key: %S", pItm->wzKey);
434 }
435
436 // add progress tics
437 if (piProgress)
438 *piProgress += COST_PARTITION_CREATE * pList->iInstallCount;
439
440 hr = S_OK;
441
442LExit:
443 return hr;
444}
445
446HRESULT CpiPartitionsUninstall(
447 CPI_PARTITION_LIST* pList,
448 int iRunMode,
449 LPWSTR* ppwzActionData,
450 int* piProgress
451 )
452{
453 HRESULT hr = S_OK;
454
455 int iActionType;
456
457 // add action text
458 hr = CpiAddActionTextToActionData(L"RemoveComPlusPartitions", ppwzActionData);
459 ExitOnFailure(hr, "Failed to add action text to custom action data");
460
461 // add partition count to action data
462 hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData);
463 ExitOnFailure(hr, "Failed to add count to custom action data");
464
465 // add partitions to custom action data
466 for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
467 {
468 // partitions that are being uninstalled only
469 if (!pItm->fHasComponent || pItm->fObjectNotFound || !WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
470 continue;
471
472 // action type
473 if (rmRollback == iRunMode)
474 iActionType = atCreate;
475 else
476 iActionType = atRemove;
477
478 // add to action data
479 hr = AddPartitionToActionData(pItm, iActionType, COST_PARTITION_DELETE, ppwzActionData);
480 ExitOnFailure(hr, "Failed to add partition to custom action data, key:", pItm->wzKey);
481 }
482
483 // add progress tics
484 if (piProgress)
485 *piProgress += COST_PARTITION_DELETE * pList->iUninstallCount;
486
487 hr = S_OK;
488
489LExit:
490 return hr;
491}
492
493HRESULT CpiPartitionFindByKey(
494 CPI_PARTITION_LIST* pList,
495 LPCWSTR wzKey,
496 CPI_PARTITION** ppItm
497 )
498{
499 for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
500 {
501 if (0 == lstrcmpW(pItm->wzKey, wzKey))
502 {
503 *ppItm = pItm;
504 return S_OK;
505 }
506 }
507
508 return S_FALSE;
509}
510
511HRESULT CpiGetApplicationsCollForPartition(
512 CPI_PARTITION* pPart,
513 ICatalogCollection** ppiAppColl
514 )
515{
516 HRESULT hr = S_OK;
517
518 ICatalogCollection* piPartColl = NULL;
519 ICatalogObject* piPartObj = NULL;
520
521 // if a previous attempt to locate the collection object failed
522 if (pPart->fObjectNotFound)
523 ExitFunction1(hr = S_FALSE);
524
525 // get applications collection
526 if (!pPart->piApplicationsColl)
527 {
528 // get partitions collection from catalog
529 hr = CpiSchedGetPartitionsCollection(&piPartColl);
530 ExitOnFailure(hr, "Failed to get partitions collection");
531
532 // find application object
533 hr = CpiFindCollectionObject(piPartColl, pPart->wzID, *pPart->wzID ? NULL : pPart->wzName, &piPartObj);
534 ExitOnFailure(hr, "Failed to find partition object");
535
536 if (S_FALSE == hr)
537 {
538 pPart->fObjectNotFound = TRUE;
539 ExitFunction(); // exit with hr = S_FALSE
540 }
541
542 // get roles collection
543 hr = CpiSchedGetCatalogCollection(piPartColl, piPartObj, L"Applications", &pPart->piApplicationsColl);
544 ExitOnFailure(hr, "Failed to get applications collection");
545 }
546
547 // return value
548 *ppiAppColl = pPart->piApplicationsColl;
549 (*ppiAppColl)->AddRef();
550
551 hr = S_OK;
552
553LExit:
554 // clean up
555 ReleaseObject(piPartColl);
556 ReleaseObject(piPartObj);
557
558 return hr;
559}
560
561HRESULT CpiGetRolesCollForPartition(
562 CPI_PARTITION* pPart,
563 ICatalogCollection** ppiRolesColl
564 )
565{
566 HRESULT hr = S_OK;
567
568 ICatalogCollection* piPartColl = NULL;
569 ICatalogObject* piPartObj = NULL;
570
571 // if a previous attempt to locate the collection object failed
572 if (pPart->fObjectNotFound)
573 ExitFunction1(hr = S_FALSE);
574
575 // get applications collection
576 if (!pPart->piRolesColl)
577 {
578 // get partitions collection from catalog
579 hr = CpiSchedGetPartitionsCollection(&piPartColl);
580 ExitOnFailure(hr, "Failed to get partitions collection");
581
582 // find partition object
583 hr = CpiFindCollectionObject(piPartColl, pPart->wzID, *pPart->wzID ? NULL : pPart->wzName, &piPartObj);
584 ExitOnFailure(hr, "Failed to find partition object");
585
586 if (S_FALSE == hr)
587 ExitFunction(); // exit with hr = S_FALSE
588
589 // get roles collection
590 hr = CpiSchedGetCatalogCollection(piPartColl, piPartObj, L"RolesForPartition", &pPart->piRolesColl);
591 ExitOnFailure(hr, "Failed to get roles collection");
592 }
593
594 // return value
595 *ppiRolesColl = pPart->piRolesColl;
596 (*ppiRolesColl)->AddRef();
597
598 hr = S_OK;
599
600LExit:
601 // clean up
602 ReleaseObject(piPartColl);
603 ReleaseObject(piPartObj);
604
605 return hr;
606}
607
608void CpiPartitionUserListFree(
609 CPI_PARTITION_USER_LIST* pList
610 )
611{
612 CPI_PARTITION_USER* pItm = pList->pFirst;
613
614 while (pItm)
615 {
616 CPI_PARTITION_USER* pDelete = pItm;
617 pItm = pItm->pNext;
618 FreePartitionUser(pDelete);
619 }
620}
621
622HRESULT CpiPartitionUsersRead(
623 CPI_PARTITION_LIST* pPartList,
624 CPI_PARTITION_USER_LIST* pPartUsrList
625 )
626{
627 HRESULT hr = S_OK;
628 UINT er = ERROR_SUCCESS;
629
630 PMSIHANDLE hView, hRec;
631
632 CPI_PARTITION_USER* pItm = NULL;
633 LPWSTR pwzData = NULL;
634 LPWSTR pwzDomain = NULL;
635 LPWSTR pwzName = NULL;
636 BOOL fMatchingArchitecture = FALSE;
637
638 // loop through all partition users
639 hr = WcaOpenExecuteView(vcsPartitionUserQuery, &hView);
640 ExitOnFailure(hr, "Failed to execute view on ComPlusPartitionUser table");
641
642 while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
643 {
644 // get component
645 hr = WcaGetRecordString(hRec, puqComponent, &pwzData);
646 ExitOnFailure(hr, "Failed to get component");
647
648 // check if the component is our processor architecture
649 hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture);
650 ExitOnFailure(hr, "Failed to get component architecture.");
651
652 if (!fMatchingArchitecture)
653 {
654 continue; // not the same architecture, ignore
655 }
656
657 // create entry
658 pItm = (CPI_PARTITION_USER*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PARTITION_USER));
659 if (!pItm)
660 ExitFunction1(hr = E_OUTOFMEMORY);
661
662 // get component install state
663 er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction);
664 ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state");
665
666 // get key
667 hr = WcaGetRecordString(hRec, puqPartitionUser, &pwzData);
668 ExitOnFailure(hr, "Failed to get key");
669 StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);
670
671 // get partition
672 hr = WcaGetRecordString(hRec, puqPartition, &pwzData);
673 ExitOnFailure(hr, "Failed to get partition");
674
675 hr = CpiPartitionFindByKey(pPartList, pwzData, &pItm->pPartition);
676 if (S_FALSE == hr)
677 hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
678 ExitOnFailure(hr, "Failed to find partition, key: %S", pwzData);
679
680 // get user domain
681 hr = WcaGetRecordFormattedString(hRec, puqDomain, &pwzDomain);
682 ExitOnFailure(hr, "Failed to get user domain");
683
684 // get user name
685 hr = WcaGetRecordFormattedString(hRec, puqName, &pwzName);
686 ExitOnFailure(hr, "Failed to get user name");
687
688 // build account name
689 hr = CpiBuildAccountName(pwzDomain, pwzName, &pItm->pwzAccount);
690 ExitOnFailure(hr, "Failed to build account name");
691
692 // set references & increment counters
693 if (WcaIsInstalling(pItm->isInstalled, pItm->isAction))
694 {
695 pItm->pPartition->fReferencedForInstall = TRUE;
696 pPartUsrList->iInstallCount++;
697 }
698 if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
699 {
700 pItm->pPartition->fReferencedForUninstall = TRUE;
701 pPartUsrList->iUninstallCount++;
702 }
703
704 // add entry
705 if (pPartUsrList->pFirst)
706 pItm->pNext = pPartUsrList->pFirst;
707 pPartUsrList->pFirst = pItm;
708 pItm = NULL;
709 }
710
711 if (E_NOMOREITEMS == hr)
712 hr = S_OK;
713
714LExit:
715 // clean up
716 if (pItm)
717 FreePartitionUser(pItm);
718
719 ReleaseStr(pwzData);
720 ReleaseStr(pwzDomain);
721 ReleaseStr(pwzName);
722
723 return hr;
724}
725
726HRESULT CpiPartitionUsersInstall(
727 CPI_PARTITION_USER_LIST* pList,
728 int iRunMode,
729 LPWSTR* ppwzActionData,
730 int* piProgress
731 )
732{
733 HRESULT hr = S_OK;
734
735 int iActionType;
736
737 // add action text
738 hr = CpiAddActionTextToActionData(L"AddComPlusPartitionUsers", ppwzActionData);
739 ExitOnFailure(hr, "Failed to add action text to custom action data");
740
741 // add partition count to action data
742 hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData);
743 ExitOnFailure(hr, "Failed to add count to custom action data");
744
745 // add applications to custom action data
746 for (CPI_PARTITION_USER* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
747 {
748 // partitions that are being installed only
749 if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction))
750 continue;
751
752 // action type
753 if (rmRollback == iRunMode)
754 {
755 if (CpiIsInstalled(pItm->isInstalled))
756 iActionType = atNoOp;
757 else
758 iActionType = atRemove;
759 }
760 else
761 iActionType = atCreate;
762
763 // add to action data
764 hr = AddPartitionUserToActionData(pItm, iActionType, COST_PARTITION_USER_CREATE, ppwzActionData);
765 ExitOnFailure(hr, "Failed to add partition user to custom action data, key: %S", pItm->wzKey);
766 }
767
768 // add progress tics
769 if (piProgress)
770 *piProgress += COST_PARTITION_USER_CREATE * pList->iInstallCount;
771
772 hr = S_OK;
773
774LExit:
775 return hr;
776}
777
778HRESULT CpiPartitionUsersUninstall(
779 CPI_PARTITION_USER_LIST* pList,
780 int iRunMode,
781 LPWSTR* ppwzActionData,
782 int* piProgress
783 )
784{
785 HRESULT hr = S_OK;
786
787 int iActionType;
788
789 // add action text
790 hr = CpiAddActionTextToActionData(L"RemoveComPlusPartitionUsers", ppwzActionData);
791 ExitOnFailure(hr, "Failed to add action text to custom action data");
792
793 // add partition count to action data
794 hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData);
795 ExitOnFailure(hr, "Failed to add count to custom action data");
796
797 // add partitions to custom action data
798 for (CPI_PARTITION_USER* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
799 {
800 // partitions that are being uninstalled only
801 if (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
802 continue;
803
804 // action type
805 if (rmRollback == iRunMode)
806 iActionType = atCreate;
807 else
808 iActionType = atRemove;
809
810 // add to action data
811 hr = AddPartitionUserToActionData(pItm, iActionType, COST_PARTITION_USER_DELETE, ppwzActionData);
812 ExitOnFailure(hr, "Failed to add partition user to custom action data, key: %S", pItm->wzKey);
813 }
814
815 // add progress tics
816 if (piProgress)
817 *piProgress += COST_PARTITION_USER_DELETE * pList->iUninstallCount;
818
819 hr = S_OK;
820
821LExit:
822 return hr;
823}
824
825
826// helper function definitions
827
828static void FreePartition(
829 CPI_PARTITION* pItm
830 )
831{
832 if (pItm->pProperties)
833 CpiPropertiesFreeList(pItm->pProperties);
834
835 ReleaseObject(pItm->piApplicationsColl);
836 ReleaseObject(pItm->piRolesColl);
837
838 ::HeapFree(::GetProcessHeap(), 0, pItm);
839}
840
841static void FreePartitionUser(
842 CPI_PARTITION_USER* pItm
843 )
844{
845 ReleaseStr(pItm->pwzAccount);
846
847 ::HeapFree(::GetProcessHeap(), 0, pItm);
848}
849
850static HRESULT AddPartitionToActionData(
851 CPI_PARTITION* pItm,
852 int iActionType,
853 int iActionCost,
854 LPWSTR* ppwzActionData
855 )
856{
857 HRESULT hr = S_OK;
858
859 // add action information to custom action data
860 hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData);
861 ExitOnFailure(hr, "Failed to add action type to custom action data");
862 hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData);
863 ExitOnFailure(hr, "Failed to add action cost to custom action data");
864
865 // add partition information to custom action data
866 hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData);
867 ExitOnFailure(hr, "Failed to add partition key to custom action data");
868 hr = WcaWriteStringToCaData(pItm->wzID, ppwzActionData);
869 ExitOnFailure(hr, "Failed to add partition id to custom action data");
870 hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData);
871 ExitOnFailure(hr, "Failed to add partition name to custom action data");
872
873 // add properties to custom action data
874 hr = CpiAddPropertiesToActionData(atCreate == iActionType ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData);
875 ExitOnFailure(hr, "Failed to add properties to custom action data");
876
877 hr = S_OK;
878
879LExit:
880 return hr;
881}
882
883static HRESULT AddPartitionUserToActionData(
884 CPI_PARTITION_USER* pItm,
885 int iActionType,
886 int iActionCost,
887 LPWSTR* ppwzActionData
888 )
889{
890 HRESULT hr = S_OK;
891
892 // add action information to custom action data
893 hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData);
894 ExitOnFailure(hr, "Failed to add action type to custom action data");
895 hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData);
896 ExitOnFailure(hr, "Failed to add action cost to custom action data");
897
898 // add partition user information to custom action data
899 hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData);
900 ExitOnFailure(hr, "Failed to add partition user key to custom action data");
901 hr = WcaWriteStringToCaData(pItm->pwzAccount, ppwzActionData);
902 ExitOnFailure(hr, "Failed to add user account to custom action data");
903
904 // add partition information to custom action data
905 hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->pPartition->wzID : L"", ppwzActionData);
906 ExitOnFailure(hr, "Failed to add partition id to custom action data");
907
908 hr = S_OK;
909
910LExit:
911 return hr;
912}