diff options
author | Rob Mensching <rob@firegiant.com> | 2021-05-04 11:41:55 -0700 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2021-05-04 11:41:55 -0700 |
commit | 337124bed6a57b40fca11c5c2f5b554f570522a6 (patch) | |
tree | 06e8552b11852309a2275e4bd63ee61320061876 /src/ext/ComPlus/ca/cppartsched.cpp | |
parent | eab57c2ddebc3dc8cebc22f5337f50062f415c0d (diff) | |
download | wix-337124bed6a57b40fca11c5c2f5b554f570522a6.tar.gz wix-337124bed6a57b40fca11c5c2f5b554f570522a6.tar.bz2 wix-337124bed6a57b40fca11c5c2f5b554f570522a6.zip |
Move ComPlus.wixext into ext
Diffstat (limited to 'src/ext/ComPlus/ca/cppartsched.cpp')
-rw-r--r-- | src/ext/ComPlus/ca/cppartsched.cpp | 912 |
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 | |||
8 | LPCWSTR vcsPartitionQuery = | ||
9 | L"SELECT `Partition`, `Component_`, `Id`, `Name` FROM `ComPlusPartition`"; | ||
10 | enum ePartitionQuery { pqPartition = 1, pqComponent, pqID, pqName }; | ||
11 | |||
12 | LPCWSTR vcsPartitionPropertyQuery = | ||
13 | L"SELECT `Name`, `Value` FROM `ComPlusPartitionProperty` WHERE `Partition_` = ?"; | ||
14 | |||
15 | LPCWSTR vcsPartitionUserQuery = | ||
16 | L"SELECT `PartitionUser`, `Partition_`, `ComPlusPartitionUser`.`Component_`, `Domain`, `Name` FROM `ComPlusPartitionUser`, `User` WHERE `User_` = `User`"; | ||
17 | enum ePartitionUserQuery { puqPartitionUser = 1, puqPartition, puqComponent, puqDomain, puqName }; | ||
18 | |||
19 | |||
20 | // property definitions | ||
21 | |||
22 | CPI_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 | |||
33 | static void FreePartition( | ||
34 | CPI_PARTITION* pItm | ||
35 | ); | ||
36 | static void FreePartitionUser( | ||
37 | CPI_PARTITION_USER* pItm | ||
38 | ); | ||
39 | static HRESULT AddPartitionToActionData( | ||
40 | CPI_PARTITION* pItm, | ||
41 | int iActionType, | ||
42 | int iActionCost, | ||
43 | LPWSTR* ppwzActionData | ||
44 | ); | ||
45 | static HRESULT AddPartitionUserToActionData( | ||
46 | CPI_PARTITION_USER* pItm, | ||
47 | int iActionType, | ||
48 | int iActionCost, | ||
49 | LPWSTR* ppwzActionData | ||
50 | ); | ||
51 | |||
52 | |||
53 | // function definitions | ||
54 | |||
55 | void 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 | |||
69 | HRESULT 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 | |||
169 | LExit: | ||
170 | // clean up | ||
171 | if (pItm) | ||
172 | FreePartition(pItm); | ||
173 | |||
174 | ReleaseStr(pwzData); | ||
175 | |||
176 | return hr; | ||
177 | } | ||
178 | |||
179 | HRESULT 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 | |||
314 | LExit: | ||
315 | // clean up | ||
316 | ReleaseObject(piPartColl); | ||
317 | ReleaseObject(piPartObj); | ||
318 | |||
319 | return hr; | ||
320 | } | ||
321 | |||
322 | HRESULT 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 | |||
372 | LExit: | ||
373 | // clean up | ||
374 | ReleaseObject(piPartColl); | ||
375 | ReleaseObject(piPartObj); | ||
376 | |||
377 | return hr; | ||
378 | } | ||
379 | |||
380 | void CpiPartitionAddReferenceInstall( | ||
381 | CPI_PARTITION* pItm | ||
382 | ) | ||
383 | { | ||
384 | pItm->fReferencedForInstall = TRUE; | ||
385 | } | ||
386 | |||
387 | void CpiPartitionAddReferenceUninstall( | ||
388 | CPI_PARTITION* pItm | ||
389 | ) | ||
390 | { | ||
391 | pItm->fReferencedForUninstall = TRUE; | ||
392 | } | ||
393 | |||
394 | HRESULT 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 | |||
442 | LExit: | ||
443 | return hr; | ||
444 | } | ||
445 | |||
446 | HRESULT 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 | |||
489 | LExit: | ||
490 | return hr; | ||
491 | } | ||
492 | |||
493 | HRESULT 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 | |||
511 | HRESULT 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 | |||
553 | LExit: | ||
554 | // clean up | ||
555 | ReleaseObject(piPartColl); | ||
556 | ReleaseObject(piPartObj); | ||
557 | |||
558 | return hr; | ||
559 | } | ||
560 | |||
561 | HRESULT 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 | |||
600 | LExit: | ||
601 | // clean up | ||
602 | ReleaseObject(piPartColl); | ||
603 | ReleaseObject(piPartObj); | ||
604 | |||
605 | return hr; | ||
606 | } | ||
607 | |||
608 | void 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 | |||
622 | HRESULT 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 | |||
714 | LExit: | ||
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 | |||
726 | HRESULT 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 | |||
774 | LExit: | ||
775 | return hr; | ||
776 | } | ||
777 | |||
778 | HRESULT 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 | |||
821 | LExit: | ||
822 | return hr; | ||
823 | } | ||
824 | |||
825 | |||
826 | // helper function definitions | ||
827 | |||
828 | static 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 | |||
841 | static void FreePartitionUser( | ||
842 | CPI_PARTITION_USER* pItm | ||
843 | ) | ||
844 | { | ||
845 | ReleaseStr(pItm->pwzAccount); | ||
846 | |||
847 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
848 | } | ||
849 | |||
850 | static 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 | |||
879 | LExit: | ||
880 | return hr; | ||
881 | } | ||
882 | |||
883 | static 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 | |||
910 | LExit: | ||
911 | return hr; | ||
912 | } | ||