aboutsummaryrefslogtreecommitdiff
path: root/src/ext/ComPlus/ca/cpappsched.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/cpappsched.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/cpappsched.cpp')
-rw-r--r--src/ext/ComPlus/ca/cpappsched.cpp752
1 files changed, 752 insertions, 0 deletions
diff --git a/src/ext/ComPlus/ca/cpappsched.cpp b/src/ext/ComPlus/ca/cpappsched.cpp
new file mode 100644
index 00000000..1fb2203b
--- /dev/null
+++ b/src/ext/ComPlus/ca/cpappsched.cpp
@@ -0,0 +1,752 @@
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 vcsApplicationQuery =
9 L"SELECT `Application`, `Component_`, `Partition_`, `Id`, `Name` FROM `ComPlusApplication`";
10enum eApplicationQuery { aqApplication = 1, aqComponent, aqPartition, aqID, aqName };
11
12LPCWSTR vcsApplicationPropertyQuery =
13 L"SELECT `Name`, `Value` FROM `ComPlusApplicationProperty` WHERE `Application_` = ?";
14
15
16// property definitions
17
18CPI_PROPERTY_DEFINITION pdlApplicationProperties[] =
19{
20 {L"3GigSupportEnabled", cpptBoolean, 500},
21 {L"AccessChecksLevel", cpptInteger, 500},
22 {L"Activation", cpptInteger, 500},
23 {L"ApplicationAccessChecksEnabled", cpptBoolean, 500},
24 {L"ApplicationDirectory", cpptString, 501},
25 {L"Authentication", cpptInteger, 500},
26 {L"AuthenticationCapability", cpptInteger, 500},
27 {L"Changeable", cpptBoolean, 500},
28 {L"CommandLine", cpptString, 500},
29 {L"ConcurrentApps", cpptInteger, 501},
30 {L"CreatedBy", cpptString, 500},
31 {L"CRMEnabled", cpptBoolean, 500},
32 {L"CRMLogFile", cpptString, 500},
33 {L"Deleteable", cpptBoolean, 500},
34 {L"Description", cpptString, 500},
35 {L"DumpEnabled", cpptBoolean, 501},
36 {L"DumpOnException", cpptBoolean, 501},
37 {L"DumpOnFailfast", cpptBoolean, 501},
38 {L"DumpPath", cpptString, 501},
39 {L"EventsEnabled", cpptBoolean, 500},
40 {L"Identity", cpptString, 500},
41 {L"ImpersonationLevel", cpptInteger, 500},
42 {L"IsEnabled", cpptBoolean, 501},
43 {L"MaxDumpCount", cpptInteger, 501},
44 {L"Password", cpptString, 500},
45 {L"QCAuthenticateMsgs", cpptInteger, 501},
46 {L"QCListenerMaxThreads", cpptInteger, 501},
47 {L"QueueListenerEnabled", cpptBoolean, 500},
48 {L"QueuingEnabled", cpptBoolean, 500},
49 {L"RecycleActivationLimit", cpptInteger, 501},
50 {L"RecycleCallLimit", cpptInteger, 501},
51 {L"RecycleExpirationTimeout", cpptInteger, 501},
52 {L"RecycleLifetimeLimit", cpptInteger, 501},
53 {L"RecycleMemoryLimit", cpptInteger, 501},
54 {L"Replicable", cpptBoolean, 501},
55 {L"RunForever", cpptBoolean, 500},
56 {L"ShutdownAfter", cpptInteger, 500},
57 {L"SoapActivated", cpptBoolean, 502},
58 {L"SoapBaseUrl", cpptString, 502},
59 {L"SoapMailTo", cpptString, 502},
60 {L"SoapVRoot", cpptString, 502},
61 {L"SRPEnabled", cpptBoolean, 501},
62 {L"SRPTrustLevel", cpptInteger, 501},
63 {NULL, cpptNone, 0}
64};
65
66
67// prototypes for private helper functions
68
69static void FreeApplication(
70 CPI_APPLICATION* pItm
71 );
72static HRESULT FindObjectForApplication(
73 CPI_APPLICATION* pItm,
74 BOOL fFindId,
75 BOOL fFindName,
76 ICatalogObject** ppiAppObj
77 );
78static HRESULT AddApplicationToActionData(
79 CPI_APPLICATION* pItm,
80 int iActionType,
81 int iActionCost,
82 LPWSTR* ppwzActionData
83 );
84
85
86// function definitions
87
88void CpiApplicationListFree(
89 CPI_APPLICATION_LIST* pList
90 )
91{
92 CPI_APPLICATION* pItm = pList->pFirst;
93
94 while (pItm)
95 {
96 CPI_APPLICATION* pDelete = pItm;
97 pItm = pItm->pNext;
98 FreeApplication(pDelete);
99 }
100}
101
102HRESULT CpiApplicationsRead(
103 CPI_PARTITION_LIST* pPartList,
104 CPI_APPLICATION_LIST* pAppList
105 )
106{
107 HRESULT hr = S_OK;
108 UINT er = ERROR_SUCCESS;
109
110 int iVersionNT = 0;
111
112 PMSIHANDLE hView, hRec;
113
114 CPI_APPLICATION* pItm = NULL;
115 LPWSTR pwzData = NULL;
116 BOOL fMatchingArchitecture = FALSE;
117
118 // get NT version
119 hr = WcaGetIntProperty(L"VersionNT", &iVersionNT);
120 ExitOnFailure(hr, "Failed to get VersionNT property");
121
122 // loop through all applications
123 hr = WcaOpenExecuteView(vcsApplicationQuery, &hView);
124 ExitOnFailure(hr, "Failed to execute view on ComPlusApplication table");
125
126 while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
127 {
128 // get component
129 hr = WcaGetRecordString(hRec, aqComponent, &pwzData);
130 ExitOnFailure(hr, "Failed to get component");
131
132 // check if the component is our processor architecture
133 if (pwzData && *pwzData)
134 {
135 hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture);
136 ExitOnFailure(hr, "Failed to get component architecture.");
137
138 if (!fMatchingArchitecture)
139 {
140 continue; // not the same architecture, ignore
141 }
142 }
143
144 // create entry
145 pItm = (CPI_APPLICATION*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_APPLICATION));
146 if (!pItm)
147 ExitFunction1(hr = E_OUTOFMEMORY);
148
149 // get component install state
150 if (pwzData && *pwzData)
151 {
152 pItm->fHasComponent = TRUE;
153
154 er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction);
155 ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state");
156 }
157
158 // get key
159 hr = WcaGetRecordString(hRec, aqApplication, &pwzData);
160 ExitOnFailure(hr, "Failed to get key");
161 StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);
162
163 // get partition
164 if (502 <= iVersionNT)
165 {
166 hr = WcaGetRecordString(hRec, aqPartition, &pwzData);
167 ExitOnFailure(hr, "Failed to get partition");
168
169 if (pwzData && *pwzData)
170 {
171 hr = CpiPartitionFindByKey(pPartList, pwzData, &pItm->pPartition);
172 ExitOnFailure(hr, "Failed to find partition, key: %S", pwzData);
173 }
174 }
175
176 // get id
177 hr = WcaGetRecordFormattedString(hRec, aqID, &pwzData);
178 ExitOnFailure(hr, "Failed to get id");
179
180 if (pwzData && *pwzData)
181 {
182 hr = PcaGuidToRegFormat(pwzData, pItm->wzID, countof(pItm->wzID));
183 ExitOnFailure(hr, "Failed to parse id guid value, key: %S, value: '%S'", pItm->wzKey, pwzData);
184 }
185
186 // get name
187 hr = WcaGetRecordFormattedString(hRec, aqName, &pwzData);
188 ExitOnFailure(hr, "Failed to get name");
189 StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData);
190
191 // if application is a locater, either an id or a name must be provided
192 if (!pItm->fHasComponent && !*pItm->wzID && !*pItm->wzName)
193 ExitOnFailure(hr = E_FAIL, "An application locater must have either an id or a name associated, key: %S", pItm->wzKey);
194
195 // if application is not a locater, an name must be provided
196 if (pItm->fHasComponent && !*pItm->wzName)
197 ExitOnFailure(hr = E_FAIL, "An application must have a name associated, key: %S", pItm->wzKey);
198
199 // get properties
200 if (CpiTableExists(cptComPlusApplicationProperty) && pItm->fHasComponent)
201 {
202 hr = CpiPropertiesRead(vcsApplicationPropertyQuery, pItm->wzKey, pdlApplicationProperties, &pItm->pProperties, &pItm->iPropertyCount);
203 ExitOnFailure(hr, "Failed to get properties");
204 }
205
206 // set references & increment counters
207 if (pItm->fHasComponent)
208 {
209 if (WcaIsInstalling(pItm->isInstalled, pItm->isAction))
210 {
211 if (pItm->pPartition)
212 CpiPartitionAddReferenceInstall(pItm->pPartition);
213 pAppList->iInstallCount++;
214 }
215 if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
216 {
217 if (pItm->pPartition)
218 CpiPartitionAddReferenceUninstall(pItm->pPartition);
219 pAppList->iUninstallCount++;
220 }
221 }
222
223 // add entry
224 if (pAppList->pFirst)
225 pItm->pNext = pAppList->pFirst;
226 pAppList->pFirst = pItm;
227 pItm = NULL;
228 }
229
230 if (E_NOMOREITEMS == hr)
231 hr = S_OK;
232
233LExit:
234 // clean up
235 if (pItm)
236 FreeApplication(pItm);
237
238 ReleaseStr(pwzData);
239
240 return hr;
241}
242
243HRESULT CpiApplicationsVerifyInstall(
244 CPI_APPLICATION_LIST* pList
245 )
246{
247 HRESULT hr = S_OK;
248 UINT er = ERROR_SUCCESS;
249
250 ICatalogObject* piAppObj = NULL;
251
252 for (CPI_APPLICATION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
253 {
254 // referenced locaters or applications that are being installed
255 if (!pItm->fReferencedForInstall && !(pItm->fHasComponent && WcaIsInstalling(pItm->isInstalled, pItm->isAction)))
256 continue;
257
258 // if the application is referensed and is not a locater, it must be installed
259 if (pItm->fReferencedForInstall && pItm->fHasComponent && !CpiWillBeInstalled(pItm->isInstalled, pItm->isAction))
260 MessageExitOnFailure(hr = E_FAIL, msierrComPlusApplicationDependency, "An application is used by another entity being installed, but is not installed itself, key: %S", pItm->wzKey);
261
262 // application is supposed to exist
263 if (!pItm->fHasComponent || CpiIsInstalled(pItm->isInstalled))
264 {
265 // get collection object for application
266 hr = FindObjectForApplication(pItm, 0 != *pItm->wzID, 0 == *pItm->wzID, &piAppObj);
267 ExitOnFailure(hr, "Failed to find collection object for application");
268
269 // if the application was found
270 if (S_OK == hr)
271 {
272 // if we don't have an id, copy id from object
273 if (!*pItm->wzID)
274 {
275 hr = CpiGetKeyForObject(piAppObj, pItm->wzID, countof(pItm->wzID));
276 ExitOnFailure(hr, "Failed to get id");
277 }
278 }
279
280 // if the application was not found
281 else
282 {
283 // if the application is a locater, this is an error
284 if (!pItm->fHasComponent)
285 MessageExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), msierrComPlusApplicationNotFound, "An application required by this installation was not found, key: %S", pItm->wzKey);
286
287 // create a new id if one is missing
288 if (!*pItm->wzID)
289 {
290 hr = CpiCreateId(pItm->wzID, countof(pItm->wzID));
291 ExitOnFailure(hr, "Failed to create id");
292 }
293 }
294 }
295
296 // application is supposed to be created
297 else
298 {
299 // check for conflicts
300 do {
301 if (*pItm->wzID)
302 {
303 // find applications with conflicting id
304 hr = FindObjectForApplication(pItm, TRUE, FALSE, &piAppObj);
305 ExitOnFailure(hr, "Failed to find collection object for application");
306
307 if (S_FALSE == hr)
308 {
309 // find applications with conflicting name
310 hr = FindObjectForApplication(pItm, FALSE, TRUE, &piAppObj);
311 ExitOnFailure(hr, "Failed to find collection object for application");
312
313 if (S_OK == hr)
314 // "A application with a conflictiong name exists. retry cancel"
315 er = WcaErrorMessage(msierrComPlusApplicationNameConflict, hr, INSTALLMESSAGE_ERROR | MB_RETRYCANCEL, 0);
316 else
317 break; // no conflicting entry found, break loop
318 }
319 else
320 // "A application with a conflicting id exists. abort retry ignore"
321 er = WcaErrorMessage(msierrComPlusApplicationIdConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
322 }
323 else
324 {
325 // find applications with conflicting name
326 hr = FindObjectForApplication(pItm, FALSE, TRUE, &piAppObj);
327 ExitOnFailure(hr, "Failed to find collection object for application");
328
329 if (S_OK == hr)
330 // "A subscription with a conflictiong name exists. abort retry ignore"
331 er = WcaErrorMessage(msierrComPlusApplicationNameConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
332 else
333 break; // no conflicting entry found, break loop
334 }
335
336 switch (er)
337 {
338 case IDCANCEL:
339 case IDABORT:
340 ExitOnFailure(hr = E_FAIL, "An application with a conflictiong name or id exists, key: %S", pItm->wzKey);
341 break;
342 case IDRETRY:
343 break;
344 case IDIGNORE:
345 default:
346 // if we don't have an id, copy id from object
347 if (!*pItm->wzID)
348 {
349 hr = CpiGetKeyForObject(piAppObj, pItm->wzID, countof(pItm->wzID));
350 ExitOnFailure(hr, "Failed to get id");
351 }
352 hr = S_FALSE; // indicate that this is not a conflict
353 }
354 } while (S_OK == hr); // hr = S_FALSE if we don't have any conflicts
355
356 // create a new id if one is missing
357 if (!*pItm->wzID)
358 {
359 hr = CpiCreateId(pItm->wzID, countof(pItm->wzID));
360 ExitOnFailure(hr, "Failed to create id");
361 }
362 }
363
364 // clean up
365 ReleaseNullObject(piAppObj);
366 }
367
368 hr = S_OK;
369
370LExit:
371 // clean up
372 ReleaseObject(piAppObj);
373
374 return hr;
375}
376
377HRESULT CpiApplicationsVerifyUninstall(
378 CPI_APPLICATION_LIST* pList
379 )
380{
381 HRESULT hr = S_OK;
382 ICatalogObject* piAppObj = NULL;
383
384 for (CPI_APPLICATION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
385 {
386 // referenced locaters or applications that are being installed
387 if (!pItm->fReferencedForUninstall && !(pItm->fHasComponent && WcaIsUninstalling(pItm->isInstalled, pItm->isAction)))
388 continue;
389
390 // get collection object for application
391 hr = FindObjectForApplication(pItm, 0 != *pItm->wzID, 0 == *pItm->wzID, &piAppObj);
392 ExitOnFailure(hr, "Failed to find collection object for application");
393
394 // if the application was found
395 if (S_OK == hr)
396 {
397 // if we don't have an id, copy id from object
398 if (!*pItm->wzID)
399 {
400 hr = CpiGetKeyForObject(piAppObj, pItm->wzID, countof(pItm->wzID));
401 ExitOnFailure(hr, "Failed to get id");
402 }
403 }
404
405 // if the application was not found
406 else
407 {
408 pItm->fObjectNotFound = TRUE;
409 if (pItm->fHasComponent)
410 pList->iUninstallCount--; // elements with the fObjectNotFound flag set will not be scheduled for uninstall
411 }
412
413 // clean up
414 ReleaseNullObject(piAppObj);
415 }
416
417 hr = S_OK;
418
419LExit:
420 // clean up
421 ReleaseObject(piAppObj);
422
423 return hr;
424}
425
426void CpiApplicationAddReferenceInstall(
427 CPI_APPLICATION* pItm
428 )
429{
430 pItm->fReferencedForInstall = TRUE;
431 if (pItm->pPartition)
432 CpiPartitionAddReferenceInstall(pItm->pPartition);
433}
434
435void CpiApplicationAddReferenceUninstall(
436 CPI_APPLICATION* pItm
437 )
438{
439 pItm->fReferencedForUninstall = TRUE;
440 if (pItm->pPartition)
441 CpiPartitionAddReferenceUninstall(pItm->pPartition);
442}
443
444HRESULT CpiApplicationsInstall(
445 CPI_APPLICATION_LIST* pList,
446 int iRunMode,
447 LPWSTR* ppwzActionData,
448 int* piProgress
449 )
450{
451 HRESULT hr = S_OK;
452
453 int iActionType;
454
455 // add action text
456 hr = CpiAddActionTextToActionData(L"CreateComPlusApplications", ppwzActionData);
457 ExitOnFailure(hr, "Failed to add action text to custom action data");
458
459 // add applicaton count to action data
460 hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData);
461 ExitOnFailure(hr, "Failed to add count to custom action data");
462
463 // add applications to custom action data
464 for (CPI_APPLICATION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
465 {
466 // applications that are being installed only
467 if (!pItm->fHasComponent || !WcaIsInstalling(pItm->isInstalled, pItm->isAction))
468 continue;
469
470 // action type
471 if (rmRollback == iRunMode)
472 {
473 if (CpiIsInstalled(pItm->isInstalled))
474 iActionType = atNoOp;
475 else
476 iActionType = atRemove;
477 }
478 else
479 iActionType = atCreate;
480
481 // add to action data
482 hr = AddApplicationToActionData(pItm, iActionType, COST_APPLICATION_CREATE, ppwzActionData);
483 ExitOnFailure(hr, "Failed to add applicaton to custom action data, key: %S", pItm->wzKey);
484 }
485
486 // add progress tics
487 if (piProgress)
488 *piProgress += COST_APPLICATION_CREATE * pList->iInstallCount;
489
490 hr = S_OK;
491
492LExit:
493 return hr;
494}
495
496HRESULT CpiApplicationsUninstall(
497 CPI_APPLICATION_LIST* pList,
498 int iRunMode,
499 LPWSTR* ppwzActionData,
500 int* piProgress
501 )
502{
503 HRESULT hr = S_OK;
504
505 int iActionType;
506
507 // add action text
508 hr = CpiAddActionTextToActionData(L"RemoveComPlusApplications", ppwzActionData);
509 ExitOnFailure(hr, "Failed to add action text to custom action data");
510
511 // add applicaton count to action data
512 hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData);
513 ExitOnFailure(hr, "Failed to add count to custom action data");
514
515 // add applications to custom action data
516 for (CPI_APPLICATION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
517 {
518 // applications that are being uninstalled only
519 if (!pItm->fHasComponent || !WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
520 continue;
521
522 // action type
523 if (rmRollback == iRunMode)
524 iActionType = atCreate;
525 else
526 iActionType = atRemove;
527
528 // add to action data
529 hr = AddApplicationToActionData(pItm, iActionType, COST_APPLICATION_DELETE, ppwzActionData);
530 ExitOnFailure(hr, "Failed to add applicaton to custom action data, key: %S", pItm->wzKey);
531 }
532
533 // add progress tics
534 if (piProgress)
535 *piProgress += COST_APPLICATION_DELETE * pList->iUninstallCount;
536
537 hr = S_OK;
538
539LExit:
540 return hr;
541}
542
543HRESULT CpiApplicationFindByKey(
544 CPI_APPLICATION_LIST* pList,
545 LPCWSTR pwzKey,
546 CPI_APPLICATION** ppApp
547 )
548{
549 for (CPI_APPLICATION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
550 {
551 if (0 == lstrcmpW(pItm->wzKey, pwzKey))
552 {
553 *ppApp = pItm;
554 return S_OK;
555 }
556 }
557
558 return S_FALSE;
559}
560
561HRESULT CpiGetRolesCollForApplication(
562 CPI_APPLICATION* pApp,
563 ICatalogCollection** ppiRolesColl
564 )
565{
566 HRESULT hr = S_OK;
567
568 ICatalogCollection* piAppColl = NULL;
569 ICatalogObject* piAppObj = NULL;
570
571 // if a previous attempt to locate the collection object failed
572 if (pApp->fObjectNotFound)
573 ExitFunction1(hr = S_FALSE);
574
575 // get applications collection
576 if (!pApp->piRolesColl)
577 {
578 // get applications collection
579 if (pApp->pPartition)
580 hr = CpiGetApplicationsCollForPartition(pApp->pPartition, &piAppColl);
581 else
582 hr = CpiSchedGetApplicationsCollection(&piAppColl);
583 ExitOnFailure(hr, "Failed to get applications collection");
584
585 if (S_FALSE == hr)
586 ExitFunction(); // exit with hr = S_FALSE
587
588 // find application object
589 hr = CpiFindCollectionObject(piAppColl, pApp->wzID, *pApp->wzID ? NULL : pApp->wzName, &piAppObj);
590 ExitOnFailure(hr, "Failed to find application object");
591
592 if (S_FALSE == hr)
593 ExitFunction(); // exit with hr = S_FALSE
594
595 // get roles collection
596 hr = CpiSchedGetCatalogCollection(piAppColl, piAppObj, L"Roles", &pApp->piRolesColl);
597 ExitOnFailure(hr, "Failed to get roles collection");
598 }
599
600 // return value
601 *ppiRolesColl = pApp->piRolesColl;
602 (*ppiRolesColl)->AddRef();
603
604 hr = S_OK;
605
606LExit:
607 // clean up
608 ReleaseObject(piAppColl);
609 ReleaseObject(piAppObj);
610
611 return hr;
612}
613
614HRESULT CpiGetComponentsCollForApplication(
615 CPI_APPLICATION* pApp,
616 ICatalogCollection** ppiCompsColl
617 )
618{
619 HRESULT hr = S_OK;
620
621 ICatalogCollection* piAppColl = NULL;
622 ICatalogObject* piAppObj = NULL;
623
624 // if a previous attempt to locate the collection object failed
625 if (pApp->fObjectNotFound)
626 ExitFunction1(hr = S_FALSE);
627
628 // get applications collection
629 if (!pApp->piCompsColl)
630 {
631 // get applications collection
632 if (pApp->pPartition)
633 hr = CpiGetApplicationsCollForPartition(pApp->pPartition, &piAppColl);
634 else
635 hr = CpiSchedGetApplicationsCollection(&piAppColl);
636 ExitOnFailure(hr, "Failed to get applications collection");
637
638 if (S_FALSE == hr)
639 ExitFunction(); // exit with hr = S_FALSE
640
641 // find application object
642 hr = CpiFindCollectionObject(piAppColl, pApp->wzID, *pApp->wzID ? NULL : pApp->wzName, &piAppObj);
643 ExitOnFailure(hr, "Failed to find application object");
644
645 if (S_FALSE == hr)
646 ExitFunction(); // exit with hr = S_FALSE
647
648 // get roles collection
649 hr = CpiSchedGetCatalogCollection(piAppColl, piAppObj, L"Components", &pApp->piCompsColl);
650 ExitOnFailure(hr, "Failed to get components collection");
651 }
652
653 // return value
654 *ppiCompsColl = pApp->piCompsColl;
655 (*ppiCompsColl)->AddRef();
656
657 hr = S_OK;
658
659LExit:
660 // clean up
661 ReleaseObject(piAppColl);
662 ReleaseObject(piAppObj);
663
664 return hr;
665}
666
667
668// helper function definitions
669
670static void FreeApplication(
671 CPI_APPLICATION* pItm
672 )
673{
674 if (pItm->pProperties)
675 CpiPropertiesFreeList(pItm->pProperties);
676
677 ReleaseObject(pItm->piRolesColl);
678 ReleaseObject(pItm->piCompsColl);
679
680 ::HeapFree(::GetProcessHeap(), 0, pItm);
681}
682
683static HRESULT FindObjectForApplication(
684 CPI_APPLICATION* pItm,
685 BOOL fFindId,
686 BOOL fFindName,
687 ICatalogObject** ppiAppObj
688 )
689{
690 HRESULT hr = S_OK;
691
692 ICatalogCollection* piAppColl = NULL;
693
694 // get applications collection
695 if (pItm->pPartition)
696 hr = CpiGetApplicationsCollForPartition(pItm->pPartition, &piAppColl);
697 else
698 hr = CpiSchedGetApplicationsCollection(&piAppColl);
699 ExitOnFailure(hr, "Failed to get applications collection");
700
701 if (S_FALSE == hr)
702 ExitFunction(); // exit with hr = S_FALSE
703
704 // find application object
705 hr = CpiFindCollectionObject(piAppColl, fFindId ? pItm->wzID : NULL, fFindName ? pItm->wzName : NULL, ppiAppObj);
706 ExitOnFailure(hr, "Failed to find application object");
707
708 // exit with hr from CpiFindCollectionObject()
709
710LExit:
711 // clean up
712 ReleaseObject(piAppColl);
713
714 return hr;
715}
716
717static HRESULT AddApplicationToActionData(
718 CPI_APPLICATION* pItm,
719 int iActionType,
720 int iActionCost,
721 LPWSTR* ppwzActionData
722 )
723{
724 HRESULT hr = S_OK;
725
726 // add action information to custom action data
727 hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData);
728 ExitOnFailure(hr, "Failed to add action type to custom action data");
729 hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData);
730 ExitOnFailure(hr, "Failed to add action cost to custom action data");
731
732 // add application information to custom action data
733 hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData);
734 ExitOnFailure(hr, "Failed to add application key to custom action data");
735 hr = WcaWriteStringToCaData(pItm->wzID, ppwzActionData);
736 ExitOnFailure(hr, "Failed to add application id to custom action data");
737 hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData);
738 ExitOnFailure(hr, "Failed to add application name to custom action data");
739
740 // add partition information to custom action data
741 hr = WcaWriteStringToCaData(pItm->pPartition ? pItm->pPartition->wzID : L"", ppwzActionData);
742 ExitOnFailure(hr, "Failed to add partition id to custom action data");
743
744 // add properties to custom action data
745 hr = CpiAddPropertiesToActionData(atCreate == iActionType ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData);
746 ExitOnFailure(hr, "Failed to add properties to custom action data");
747
748 hr = S_OK;
749
750LExit:
751 return hr;
752}