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/cpappsched.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/cpappsched.cpp')
-rw-r--r-- | src/ext/ComPlus/ca/cpappsched.cpp | 752 |
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 | |||
8 | LPCWSTR vcsApplicationQuery = | ||
9 | L"SELECT `Application`, `Component_`, `Partition_`, `Id`, `Name` FROM `ComPlusApplication`"; | ||
10 | enum eApplicationQuery { aqApplication = 1, aqComponent, aqPartition, aqID, aqName }; | ||
11 | |||
12 | LPCWSTR vcsApplicationPropertyQuery = | ||
13 | L"SELECT `Name`, `Value` FROM `ComPlusApplicationProperty` WHERE `Application_` = ?"; | ||
14 | |||
15 | |||
16 | // property definitions | ||
17 | |||
18 | CPI_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 | |||
69 | static void FreeApplication( | ||
70 | CPI_APPLICATION* pItm | ||
71 | ); | ||
72 | static HRESULT FindObjectForApplication( | ||
73 | CPI_APPLICATION* pItm, | ||
74 | BOOL fFindId, | ||
75 | BOOL fFindName, | ||
76 | ICatalogObject** ppiAppObj | ||
77 | ); | ||
78 | static HRESULT AddApplicationToActionData( | ||
79 | CPI_APPLICATION* pItm, | ||
80 | int iActionType, | ||
81 | int iActionCost, | ||
82 | LPWSTR* ppwzActionData | ||
83 | ); | ||
84 | |||
85 | |||
86 | // function definitions | ||
87 | |||
88 | void 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 | |||
102 | HRESULT 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 | |||
233 | LExit: | ||
234 | // clean up | ||
235 | if (pItm) | ||
236 | FreeApplication(pItm); | ||
237 | |||
238 | ReleaseStr(pwzData); | ||
239 | |||
240 | return hr; | ||
241 | } | ||
242 | |||
243 | HRESULT 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 | |||
370 | LExit: | ||
371 | // clean up | ||
372 | ReleaseObject(piAppObj); | ||
373 | |||
374 | return hr; | ||
375 | } | ||
376 | |||
377 | HRESULT 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 | |||
419 | LExit: | ||
420 | // clean up | ||
421 | ReleaseObject(piAppObj); | ||
422 | |||
423 | return hr; | ||
424 | } | ||
425 | |||
426 | void CpiApplicationAddReferenceInstall( | ||
427 | CPI_APPLICATION* pItm | ||
428 | ) | ||
429 | { | ||
430 | pItm->fReferencedForInstall = TRUE; | ||
431 | if (pItm->pPartition) | ||
432 | CpiPartitionAddReferenceInstall(pItm->pPartition); | ||
433 | } | ||
434 | |||
435 | void CpiApplicationAddReferenceUninstall( | ||
436 | CPI_APPLICATION* pItm | ||
437 | ) | ||
438 | { | ||
439 | pItm->fReferencedForUninstall = TRUE; | ||
440 | if (pItm->pPartition) | ||
441 | CpiPartitionAddReferenceUninstall(pItm->pPartition); | ||
442 | } | ||
443 | |||
444 | HRESULT 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 | |||
492 | LExit: | ||
493 | return hr; | ||
494 | } | ||
495 | |||
496 | HRESULT 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 | |||
539 | LExit: | ||
540 | return hr; | ||
541 | } | ||
542 | |||
543 | HRESULT 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 | |||
561 | HRESULT 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 | |||
606 | LExit: | ||
607 | // clean up | ||
608 | ReleaseObject(piAppColl); | ||
609 | ReleaseObject(piAppObj); | ||
610 | |||
611 | return hr; | ||
612 | } | ||
613 | |||
614 | HRESULT 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 | |||
659 | LExit: | ||
660 | // clean up | ||
661 | ReleaseObject(piAppColl); | ||
662 | ReleaseObject(piAppObj); | ||
663 | |||
664 | return hr; | ||
665 | } | ||
666 | |||
667 | |||
668 | // helper function definitions | ||
669 | |||
670 | static 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 | |||
683 | static 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 | |||
710 | LExit: | ||
711 | // clean up | ||
712 | ReleaseObject(piAppColl); | ||
713 | |||
714 | return hr; | ||
715 | } | ||
716 | |||
717 | static 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 | |||
750 | LExit: | ||
751 | return hr; | ||
752 | } | ||