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/cpasmsched.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/cpasmsched.cpp')
-rw-r--r-- | src/ext/ComPlus/ca/cpasmsched.cpp | 2135 |
1 files changed, 2135 insertions, 0 deletions
diff --git a/src/ext/ComPlus/ca/cpasmsched.cpp b/src/ext/ComPlus/ca/cpasmsched.cpp new file mode 100644 index 00000000..2d0573a5 --- /dev/null +++ b/src/ext/ComPlus/ca/cpasmsched.cpp | |||
@@ -0,0 +1,2135 @@ | |||
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 vcsMsiAssemblyNameQuery = | ||
9 | L"SELECT `Name`, `Value` FROM `MsiAssemblyName` WHERE `Component_` = ?"; | ||
10 | enum eMsiAssemblyNameQuery { manqName = 1, manqValue }; | ||
11 | |||
12 | LPCWSTR vcsModuleQuery = | ||
13 | L"SELECT `ModuleID` FROM `ModuleSignature`"; | ||
14 | enum eModuleQuery { mqModule = 1 }; | ||
15 | |||
16 | LPCWSTR vcsAssemblyQuery = | ||
17 | L"SELECT `Assembly`, `Component_`, `Application_`, `AssemblyName`, `DllPath`, `TlbPath`, `PSDllPath`, `Attributes` FROM `ComPlusAssembly`"; | ||
18 | enum eAssemblyQuery { aqAssembly = 1, aqComponent, aqApplication, aqAssemblyName, aqDllPath, aqTlbPath, aqPSDllPath, aqAttributes }; | ||
19 | |||
20 | LPCWSTR vcsComponentQuery = | ||
21 | L"SELECT `ComPlusComponent`, `CLSID` FROM `ComPlusComponent` WHERE `Assembly_` = ?"; | ||
22 | enum eComponentQuery { cqComponent = 1, cqCLSID }; | ||
23 | |||
24 | LPCWSTR vcsComponentPropertyQuery = | ||
25 | L"SELECT `Name`, `Value` FROM `ComPlusComponentProperty` WHERE `ComPlusComponent_` = ?"; | ||
26 | |||
27 | LPCWSTR vcsInterfaceQuery = | ||
28 | L"SELECT `Interface`, `IID` FROM `ComPlusInterface` WHERE `ComPlusComponent_` = ?"; | ||
29 | enum eInterfaceQuery { iqInterface = 1, iqIID }; | ||
30 | |||
31 | LPCWSTR vcsInterfacePropertyQuery = | ||
32 | L"SELECT `Name`, `Value` FROM `ComPlusInterfaceProperty` WHERE `Interface_` = ?"; | ||
33 | |||
34 | LPCWSTR vcsMethodQuery = | ||
35 | L"SELECT `Method`, `Index`, `Name` FROM `ComPlusMethod` WHERE `Interface_` = ?"; | ||
36 | enum eMethodQuery { mqMethod = 1, mqIndex, mqName }; | ||
37 | |||
38 | LPCWSTR vcsMethodPropertyQuery = | ||
39 | L"SELECT `Name`, `Value` FROM `ComPlusMethodProperty` WHERE `Method_` = ?"; | ||
40 | |||
41 | LPCWSTR vcsRoleForComponentQuery = | ||
42 | L"SELECT `RoleForComponent`, `ApplicationRole_`, `Component_` FROM `ComPlusRoleForComponent` WHERE `ComPlusComponent_` = ?"; | ||
43 | LPCWSTR vcsRoleForInterfaceQuery = | ||
44 | L"SELECT `RoleForInterface`, `ApplicationRole_`, `Component_` FROM `ComPlusRoleForInterface` WHERE `Interface_` = ?"; | ||
45 | LPCWSTR vcsRoleForMethodQuery = | ||
46 | L"SELECT `RoleForMethod`, `ApplicationRole_`, `Component_` FROM `ComPlusRoleForMethod` WHERE `Method_` = ?"; | ||
47 | |||
48 | enum eRoleAssignmentQuery { raqKey = 1, raqApplicationRole, raqComponent }; | ||
49 | |||
50 | LPCWSTR vcsModuleComponentsQuery = | ||
51 | L"SELECT `Component`, `ModuleID` FROM `ModuleComponents`"; | ||
52 | LPCWSTR vcsModuleDependencyQuery = | ||
53 | L"SELECT `ModuleID`, `RequiredID` FROM `ModuleDependency`"; | ||
54 | LPCWSTR vcsAssemblyDependencyQuery = | ||
55 | L"SELECT `Assembly_`, `RequiredAssembly_` FROM `ComPlusAssemblyDependency`"; | ||
56 | |||
57 | enum eKeyPairQuery { kpqFirstKey = 1, kpqSecondKey }; | ||
58 | |||
59 | |||
60 | // private structs | ||
61 | |||
62 | struct CPI_KEY_PAIR | ||
63 | { | ||
64 | WCHAR wzFirstKey[MAX_DARWIN_KEY + 1]; | ||
65 | WCHAR wzSecondKey[MAX_DARWIN_KEY + 1]; | ||
66 | |||
67 | CPI_KEY_PAIR* pNext; | ||
68 | }; | ||
69 | |||
70 | struct CPI_DEPENDENCY_CHAIN | ||
71 | { | ||
72 | LPCWSTR pwzKey; | ||
73 | |||
74 | CPI_DEPENDENCY_CHAIN* pPrev; | ||
75 | }; | ||
76 | |||
77 | struct CPI_MODULE | ||
78 | { | ||
79 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
80 | |||
81 | CPI_MODULE* pPrev; | ||
82 | CPI_MODULE* pNext; | ||
83 | }; | ||
84 | |||
85 | struct CPI_MODULE_LIST | ||
86 | { | ||
87 | CPI_MODULE* pFirst; | ||
88 | CPI_MODULE* pLast; | ||
89 | }; | ||
90 | |||
91 | |||
92 | // property definitions | ||
93 | |||
94 | CPI_PROPERTY_DEFINITION pdlComponentProperties[] = | ||
95 | { | ||
96 | {L"AllowInprocSubscribers", cpptBoolean, 500}, | ||
97 | {L"ComponentAccessChecksEnabled", cpptBoolean, 500}, | ||
98 | {L"ComponentTransactionTimeout", cpptInteger, 500}, | ||
99 | {L"ComponentTransactionTimeoutEnabled", cpptBoolean, 500}, | ||
100 | {L"COMTIIntrinsics", cpptBoolean, 500}, | ||
101 | {L"ConstructionEnabled", cpptBoolean, 500}, | ||
102 | {L"ConstructorString", cpptString, 500}, | ||
103 | {L"CreationTimeout", cpptInteger, 500}, | ||
104 | {L"Description", cpptString, 500}, | ||
105 | {L"EventTrackingEnabled", cpptBoolean, 500}, | ||
106 | {L"ExceptionClass", cpptString, 500}, | ||
107 | {L"FireInParallel", cpptBoolean, 500}, | ||
108 | {L"IISIntrinsics", cpptBoolean, 500}, | ||
109 | {L"InitializesServerApplication", cpptBoolean, 500}, | ||
110 | {L"IsEnabled", cpptBoolean, 501}, | ||
111 | {L"IsPrivateComponent", cpptBoolean, 501}, | ||
112 | {L"JustInTimeActivation", cpptBoolean, 500}, | ||
113 | {L"LoadBalancingSupported", cpptBoolean, 500}, | ||
114 | {L"MaxPoolSize", cpptInteger, 500}, | ||
115 | {L"MinPoolSize", cpptInteger, 500}, | ||
116 | {L"MultiInterfacePublisherFilterCLSID", cpptString, 500}, | ||
117 | {L"MustRunInClientContext", cpptBoolean, 500}, | ||
118 | {L"MustRunInDefaultContext", cpptBoolean, 501}, | ||
119 | {L"ObjectPoolingEnabled", cpptBoolean, 500}, | ||
120 | {L"PublisherID", cpptString, 500}, | ||
121 | {L"SoapAssemblyName", cpptString, 502}, | ||
122 | {L"SoapTypeName", cpptString, 502}, | ||
123 | {L"Synchronization", cpptInteger, 500}, | ||
124 | {L"Transaction", cpptInteger, 500}, | ||
125 | {L"TxIsolationLevel", cpptInteger, 501}, | ||
126 | {NULL, cpptNone, 0} | ||
127 | }; | ||
128 | |||
129 | CPI_PROPERTY_DEFINITION pdlInterfaceProperties[] = | ||
130 | { | ||
131 | {L"Description", cpptString, 500}, | ||
132 | {L"QueuingEnabled", cpptBoolean, 500}, | ||
133 | {NULL, cpptNone, 0} | ||
134 | }; | ||
135 | |||
136 | CPI_PROPERTY_DEFINITION pdlMethodProperties[] = | ||
137 | { | ||
138 | {L"AutoComplete", cpptBoolean, 500}, | ||
139 | {L"Description", cpptString, 500}, | ||
140 | {NULL, cpptNone, 0} | ||
141 | }; | ||
142 | |||
143 | |||
144 | // prototypes for private helper functions | ||
145 | |||
146 | static HRESULT GetAssemblyName( | ||
147 | LPCWSTR pwzComponent, | ||
148 | LPWSTR* ppwzAssemblyName | ||
149 | ); | ||
150 | static HRESULT KeyPairsRead( | ||
151 | LPCWSTR pwzQuery, | ||
152 | CPI_KEY_PAIR** ppKeyPairList | ||
153 | ); | ||
154 | static HRESULT ModulesRead( | ||
155 | CPI_MODULE_LIST* pModList | ||
156 | ); | ||
157 | static HRESULT AssembliesRead( | ||
158 | CPI_KEY_PAIR* pModCompList, | ||
159 | CPI_APPLICATION_LIST* pAppList, | ||
160 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
161 | CPI_ASSEMBLY_LIST* pAsmList | ||
162 | ); | ||
163 | static HRESULT ComponentsRead( | ||
164 | LPCWSTR pwzAsmKey, | ||
165 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
166 | CPI_ASSEMBLY* pAsm | ||
167 | ); | ||
168 | static HRESULT InterfacesRead( | ||
169 | LPCWSTR pwzCompKey, | ||
170 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
171 | CPI_ASSEMBLY* pAsm, | ||
172 | CPISCHED_COMPONENT* pComp | ||
173 | ); | ||
174 | static HRESULT MethodsRead( | ||
175 | LPCWSTR pwzIntfKey, | ||
176 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
177 | CPI_ASSEMBLY* pAsm, | ||
178 | CPISCHED_INTERFACE* pIntf | ||
179 | ); | ||
180 | static HRESULT RoleAssignmentsRead( | ||
181 | LPCWSTR pwzQuery, | ||
182 | LPCWSTR pwzKey, | ||
183 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
184 | CPISCHED_ROLE_ASSIGNMENT** ppRoleList, | ||
185 | int* piInstallCount, | ||
186 | int* piUninstallCount | ||
187 | ); | ||
188 | static HRESULT TopSortModuleList( | ||
189 | CPI_KEY_PAIR* pDepList, | ||
190 | CPI_MODULE_LIST* pList | ||
191 | ); | ||
192 | static HRESULT SwapDependentModules( | ||
193 | CPI_DEPENDENCY_CHAIN* pdcPrev, | ||
194 | CPI_KEY_PAIR* pDepList, | ||
195 | CPI_MODULE_LIST* pList, | ||
196 | CPI_MODULE* pRoot, | ||
197 | CPI_MODULE* pItm | ||
198 | ); | ||
199 | static HRESULT ModuleFindByKey( | ||
200 | CPI_MODULE* pItm, | ||
201 | LPCWSTR pwzKey, | ||
202 | BOOL fReverse, | ||
203 | CPI_MODULE** ppItm | ||
204 | ); | ||
205 | static void SortAssemblyListByModule( | ||
206 | CPI_MODULE_LIST* pModList, | ||
207 | CPI_ASSEMBLY_LIST* pAsmList | ||
208 | ); | ||
209 | static HRESULT TopSortAssemblyList( | ||
210 | CPI_KEY_PAIR* pDepList, | ||
211 | CPI_ASSEMBLY_LIST* pList | ||
212 | ); | ||
213 | static HRESULT SwapDependentAssemblies( | ||
214 | CPI_DEPENDENCY_CHAIN* pdcPrev, | ||
215 | CPI_KEY_PAIR* pDepList, | ||
216 | CPI_ASSEMBLY_LIST* pList, | ||
217 | CPI_ASSEMBLY* pRoot, | ||
218 | CPI_ASSEMBLY* pItm | ||
219 | ); | ||
220 | static HRESULT AssemblyFindByKey( | ||
221 | CPI_ASSEMBLY* pItm, | ||
222 | LPCWSTR pwzKey, | ||
223 | BOOL fReverse, | ||
224 | CPI_ASSEMBLY** ppItm | ||
225 | ); | ||
226 | static HRESULT AddAssemblyToActionData( | ||
227 | CPI_ASSEMBLY* pItm, | ||
228 | BOOL fInstall, | ||
229 | int iActionType, | ||
230 | int iActionCost, | ||
231 | LPWSTR* ppwzActionData | ||
232 | ); | ||
233 | static HRESULT AddRoleAssignmentsToActionData( | ||
234 | CPI_ASSEMBLY* pItm, | ||
235 | BOOL fInstall, | ||
236 | int iActionType, | ||
237 | int iActionCost, | ||
238 | LPWSTR* ppwzActionData | ||
239 | ); | ||
240 | static HRESULT AddComponentToActionData( | ||
241 | CPISCHED_COMPONENT* pItm, | ||
242 | BOOL fInstall, | ||
243 | BOOL fProps, | ||
244 | BOOL fRoles, | ||
245 | LPWSTR* ppwzActionData | ||
246 | ); | ||
247 | static HRESULT AddInterfaceToActionData( | ||
248 | CPISCHED_INTERFACE* pItm, | ||
249 | BOOL fInstall, | ||
250 | BOOL fProps, | ||
251 | BOOL fRoles, | ||
252 | LPWSTR* ppwzActionData | ||
253 | ); | ||
254 | static HRESULT AddMethodToActionData( | ||
255 | CPISCHED_METHOD* pItm, | ||
256 | BOOL fInstall, | ||
257 | BOOL fProps, | ||
258 | BOOL fRoles, | ||
259 | LPWSTR* ppwzActionData | ||
260 | ); | ||
261 | static HRESULT AddRolesToActionData( | ||
262 | int iRoleInstallCount, | ||
263 | int iRoleUninstallCount, | ||
264 | CPISCHED_ROLE_ASSIGNMENT* pRoleList, | ||
265 | BOOL fInstall, | ||
266 | BOOL fRoles, | ||
267 | LPWSTR* ppwzActionData | ||
268 | ); | ||
269 | static HRESULT KeyPairFindByFirstKey( | ||
270 | CPI_KEY_PAIR* pList, | ||
271 | LPCWSTR pwzKey, | ||
272 | CPI_KEY_PAIR** ppItm | ||
273 | ); | ||
274 | static void AssemblyFree( | ||
275 | CPI_ASSEMBLY* pItm | ||
276 | ); | ||
277 | static void KeyPairsFreeList( | ||
278 | CPI_KEY_PAIR* pList | ||
279 | ); | ||
280 | void ModuleListFree( | ||
281 | CPI_MODULE_LIST* pList | ||
282 | ); | ||
283 | static void ModuleFree( | ||
284 | CPI_MODULE* pItm | ||
285 | ); | ||
286 | static void ComponentsFreeList( | ||
287 | CPISCHED_COMPONENT* pList | ||
288 | ); | ||
289 | static void InterfacesFreeList( | ||
290 | CPISCHED_INTERFACE* pList | ||
291 | ); | ||
292 | static void MethodsFreeList( | ||
293 | CPISCHED_METHOD* pList | ||
294 | ); | ||
295 | static void RoleAssignmentsFreeList( | ||
296 | CPISCHED_ROLE_ASSIGNMENT* pList | ||
297 | ); | ||
298 | |||
299 | |||
300 | // function definitions | ||
301 | |||
302 | void CpiAssemblyListFree( | ||
303 | CPI_ASSEMBLY_LIST* pList | ||
304 | ) | ||
305 | { | ||
306 | CPI_ASSEMBLY* pItm = pList->pFirst; | ||
307 | |||
308 | while (pItm) | ||
309 | { | ||
310 | CPI_ASSEMBLY* pDelete = pItm; | ||
311 | pItm = pItm->pNext; | ||
312 | AssemblyFree(pDelete); | ||
313 | } | ||
314 | } | ||
315 | |||
316 | HRESULT CpiAssembliesRead( | ||
317 | CPI_APPLICATION_LIST* pAppList, | ||
318 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
319 | CPI_ASSEMBLY_LIST* pAsmList | ||
320 | ) | ||
321 | { | ||
322 | HRESULT hr = S_OK; | ||
323 | CPI_MODULE_LIST modList; | ||
324 | CPI_KEY_PAIR* pModCompList = NULL; | ||
325 | CPI_KEY_PAIR* pModDepList = NULL; | ||
326 | CPI_KEY_PAIR* pAsmDepList = NULL; | ||
327 | |||
328 | ::ZeroMemory(&modList, sizeof(CPI_MODULE_LIST)); | ||
329 | |||
330 | BOOL fModuleSignatureTable = (S_OK == WcaTableExists(L"ModuleSignature")); | ||
331 | BOOL fModuleComponentsTable = (S_OK == WcaTableExists(L"ModuleComponents")); | ||
332 | BOOL fModuleDependencyTable = (S_OK == WcaTableExists(L"ModuleDependency")); | ||
333 | |||
334 | // read modules | ||
335 | if (fModuleSignatureTable) | ||
336 | { | ||
337 | hr = ModulesRead(&modList); | ||
338 | ExitOnFailure(hr, "Failed to read ModuleSignature table"); | ||
339 | } | ||
340 | |||
341 | // read module components | ||
342 | if (fModuleComponentsTable) | ||
343 | { | ||
344 | hr = KeyPairsRead(vcsModuleComponentsQuery, &pModCompList); | ||
345 | ExitOnFailure(hr, "Failed to read ModuleComponents table"); | ||
346 | } | ||
347 | |||
348 | // read module dependencies | ||
349 | if (fModuleDependencyTable) | ||
350 | { | ||
351 | hr = KeyPairsRead(vcsModuleDependencyQuery, &pModDepList); | ||
352 | ExitOnFailure(hr, "Failed to read ModuleDependency table"); | ||
353 | } | ||
354 | |||
355 | // read assemblies | ||
356 | hr = AssembliesRead(pModCompList, pAppList, pAppRoleList, pAsmList); | ||
357 | ExitOnFailure(hr, "Failed to read ComPlusAssembly table"); | ||
358 | |||
359 | // read assembly dependencies | ||
360 | if (CpiTableExists(cptComPlusAssemblyDependency)) | ||
361 | { | ||
362 | hr = KeyPairsRead(vcsAssemblyDependencyQuery, &pAsmDepList); | ||
363 | ExitOnFailure(hr, "Failed to read ComPlusAssemblyDependency table"); | ||
364 | } | ||
365 | |||
366 | // sort modules | ||
367 | if (modList.pFirst && pModDepList) | ||
368 | { | ||
369 | hr = TopSortModuleList(pModDepList, &modList); | ||
370 | ExitOnFailure(hr, "Failed to sort modules"); | ||
371 | } | ||
372 | |||
373 | // sort assemblies by module | ||
374 | if (pAsmList->pFirst && modList.pFirst && pModDepList) | ||
375 | SortAssemblyListByModule(&modList, pAsmList); | ||
376 | |||
377 | // sort assemblies by dependency | ||
378 | if (pAsmList->pFirst && pAsmDepList) | ||
379 | { | ||
380 | hr = TopSortAssemblyList(pAsmDepList, pAsmList); | ||
381 | ExitOnFailure(hr, "Failed to sort assemblies"); | ||
382 | } | ||
383 | |||
384 | hr = S_OK; | ||
385 | |||
386 | LExit: | ||
387 | // clean up | ||
388 | ModuleListFree(&modList); | ||
389 | if (pModCompList) | ||
390 | KeyPairsFreeList(pModCompList); | ||
391 | if (pModDepList) | ||
392 | KeyPairsFreeList(pModDepList); | ||
393 | if (pAsmDepList) | ||
394 | KeyPairsFreeList(pAsmDepList); | ||
395 | |||
396 | return hr; | ||
397 | } | ||
398 | |||
399 | HRESULT CpiAssembliesVerifyInstall( | ||
400 | CPI_ASSEMBLY_LIST* pList | ||
401 | ) | ||
402 | { | ||
403 | HRESULT hr = S_OK; | ||
404 | |||
405 | for (CPI_ASSEMBLY* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
406 | { | ||
407 | // assemblies that are being installed | ||
408 | if (!pItm->fReferencedForInstall && !pItm->iRoleAssignmentsInstallCount && !WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
409 | continue; | ||
410 | |||
411 | // if the assembly is referensed, it must be installed | ||
412 | if ((pItm->fReferencedForInstall || pItm->iRoleAssignmentsInstallCount) && !CpiWillBeInstalled(pItm->isInstalled, pItm->isAction)) | ||
413 | MessageExitOnFailure(hr = E_FAIL, msierrComPlusAssemblyDependency, "An assembly is used by another entity being installed, but is not installed itself, key: %S", pItm->wzKey); | ||
414 | } | ||
415 | |||
416 | hr = S_OK; | ||
417 | |||
418 | LExit: | ||
419 | return hr; | ||
420 | } | ||
421 | |||
422 | HRESULT CpiAssembliesVerifyUninstall( | ||
423 | CPI_ASSEMBLY_LIST* pList | ||
424 | ) | ||
425 | { | ||
426 | HRESULT hr = S_OK; | ||
427 | |||
428 | for (CPI_ASSEMBLY* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
429 | { | ||
430 | // assemblies that are being uninstalled | ||
431 | if (!pItm->fReferencedForUninstall && !pItm->iRoleAssignmentsUninstallCount && (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction) && !WcaIsReInstalling(pItm->isInstalled, pItm->isAction))) | ||
432 | continue; | ||
433 | |||
434 | // if the application is not present, there is no need to remove the components | ||
435 | if (pItm->pApplication && pItm->pApplication->fObjectNotFound) | ||
436 | { | ||
437 | pItm->fIgnore = TRUE; | ||
438 | pList->iUninstallCount--; // elements with the fIgnore flag set will not be scheduled for uninstall | ||
439 | pList->iRoleUninstallCount--; | ||
440 | } | ||
441 | } | ||
442 | |||
443 | hr = S_OK; | ||
444 | |||
445 | //LExit: | ||
446 | return hr; | ||
447 | } | ||
448 | |||
449 | HRESULT CpiAssembliesInstall( | ||
450 | CPI_ASSEMBLY_LIST* pList, | ||
451 | int iRunMode, | ||
452 | LPWSTR* ppwzActionData, | ||
453 | int* piProgress | ||
454 | ) | ||
455 | { | ||
456 | HRESULT hr = S_OK; | ||
457 | |||
458 | int iActionType; | ||
459 | int iCount = 0; | ||
460 | |||
461 | // add action text | ||
462 | hr = CpiAddActionTextToActionData(L"RegisterComPlusAssemblies", ppwzActionData); | ||
463 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
464 | |||
465 | // assembly count | ||
466 | switch (iRunMode) | ||
467 | { | ||
468 | case rmDeferred: | ||
469 | iCount = pList->iInstallCount - pList->iCommitCount; | ||
470 | break; | ||
471 | case rmCommit: | ||
472 | iCount = pList->iCommitCount; | ||
473 | break; | ||
474 | case rmRollback: | ||
475 | iCount = pList->iInstallCount; | ||
476 | break; | ||
477 | } | ||
478 | |||
479 | // add assembly count to action data | ||
480 | hr = WcaWriteIntegerToCaData(iCount, ppwzActionData); | ||
481 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
482 | |||
483 | // add assemblies to custom action data in forward order | ||
484 | for (CPI_ASSEMBLY* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
485 | { | ||
486 | // assemblies that are being installed, or contains roll assignments to install | ||
487 | if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
488 | continue; | ||
489 | |||
490 | // assemblies that are being installed must be scheduled during the right type of action | ||
491 | BOOL fRunInCommit = 0 != (pItm->iAttributes & aaRunInCommit); | ||
492 | if (((rmCommit == iRunMode && !fRunInCommit) || (rmDeferred == iRunMode && fRunInCommit))) | ||
493 | continue; | ||
494 | |||
495 | // action type | ||
496 | if (rmRollback == iRunMode) | ||
497 | { | ||
498 | if (CpiIsInstalled(pItm->isInstalled)) | ||
499 | iActionType = atNoOp; | ||
500 | else | ||
501 | iActionType = atRemove; | ||
502 | } | ||
503 | else | ||
504 | iActionType = atCreate; | ||
505 | |||
506 | // add to action data | ||
507 | hr = AddAssemblyToActionData(pItm, TRUE, iActionType, COST_ASSEMBLY_REGISTER, ppwzActionData); | ||
508 | ExitOnFailure(hr, "Failed to add assembly to custom action data, key: %S", pItm->wzKey); | ||
509 | } | ||
510 | |||
511 | // add progress tics | ||
512 | if (piProgress) | ||
513 | *piProgress += COST_ASSEMBLY_REGISTER * iCount; | ||
514 | |||
515 | hr = S_OK; | ||
516 | |||
517 | LExit: | ||
518 | return hr; | ||
519 | } | ||
520 | |||
521 | HRESULT CpiAssembliesUninstall( | ||
522 | CPI_ASSEMBLY_LIST* pList, | ||
523 | int iRunMode, | ||
524 | LPWSTR* ppwzActionData, | ||
525 | int* piProgress | ||
526 | ) | ||
527 | { | ||
528 | HRESULT hr = S_OK; | ||
529 | |||
530 | int iActionType; | ||
531 | |||
532 | // add action text | ||
533 | hr = CpiAddActionTextToActionData(L"UnregisterComPlusAssemblies", ppwzActionData); | ||
534 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
535 | |||
536 | // add assembly count to action data | ||
537 | hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); | ||
538 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
539 | |||
540 | // add assemblies to custom action data in reverse order | ||
541 | for (CPI_ASSEMBLY* pItm = pList->pLast; pItm; pItm = pItm->pPrev) | ||
542 | { | ||
543 | // assemblies that are being uninstalled | ||
544 | if (pItm->fIgnore || (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction) && !WcaIsReInstalling(pItm->isInstalled, pItm->isAction))) | ||
545 | continue; | ||
546 | |||
547 | // action type | ||
548 | if (rmRollback == iRunMode) | ||
549 | iActionType = atCreate; | ||
550 | else | ||
551 | iActionType = atRemove; | ||
552 | |||
553 | // add to action data | ||
554 | hr = AddAssemblyToActionData(pItm, FALSE, iActionType, COST_ASSEMBLY_UNREGISTER, ppwzActionData); | ||
555 | ExitOnFailure(hr, "Failed to add assembly to custom action data, key: %S", pItm->wzKey); | ||
556 | } | ||
557 | |||
558 | // add progress tics | ||
559 | if (piProgress) | ||
560 | *piProgress += COST_ASSEMBLY_UNREGISTER * pList->iUninstallCount; | ||
561 | |||
562 | hr = S_OK; | ||
563 | |||
564 | LExit: | ||
565 | return hr; | ||
566 | } | ||
567 | |||
568 | HRESULT CpiRoleAssignmentsInstall( | ||
569 | CPI_ASSEMBLY_LIST* pList, | ||
570 | int iRunMode, | ||
571 | LPWSTR* ppwzActionData, | ||
572 | int* piProgress | ||
573 | ) | ||
574 | { | ||
575 | HRESULT hr = S_OK; | ||
576 | |||
577 | int iActionType; | ||
578 | int iCount = 0; | ||
579 | |||
580 | // add action text | ||
581 | hr = CpiAddActionTextToActionData(L"AddComPlusRoleAssignments", ppwzActionData); | ||
582 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
583 | |||
584 | // assembly count | ||
585 | switch (iRunMode) | ||
586 | { | ||
587 | case rmDeferred: | ||
588 | iCount = pList->iRoleInstallCount - pList->iRoleCommitCount; | ||
589 | break; | ||
590 | case rmCommit: | ||
591 | iCount = pList->iRoleCommitCount; | ||
592 | break; | ||
593 | case rmRollback: | ||
594 | iCount = pList->iRoleInstallCount; | ||
595 | break; | ||
596 | } | ||
597 | |||
598 | // add assembly count to action data | ||
599 | hr = WcaWriteIntegerToCaData(iCount, ppwzActionData); | ||
600 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
601 | |||
602 | // add assemblies to custom action data in forward order | ||
603 | for (CPI_ASSEMBLY* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
604 | { | ||
605 | // assemblies that are being installed, or contains roll assignments to install | ||
606 | if (!pItm->iRoleAssignmentsInstallCount) | ||
607 | continue; | ||
608 | |||
609 | // assemblies that are being installed must be scheduled during the right type of action | ||
610 | BOOL fRunInCommit = 0 != (pItm->iAttributes & aaRunInCommit); | ||
611 | if (((rmCommit == iRunMode && !fRunInCommit) || (rmDeferred == iRunMode && fRunInCommit))) | ||
612 | continue; | ||
613 | |||
614 | // action type | ||
615 | if (rmRollback == iRunMode) | ||
616 | { | ||
617 | if (CpiIsInstalled(pItm->isInstalled)) | ||
618 | iActionType = atNoOp; | ||
619 | else | ||
620 | iActionType = atRemove; | ||
621 | } | ||
622 | else | ||
623 | iActionType = atCreate; | ||
624 | |||
625 | // add to action data | ||
626 | hr = AddRoleAssignmentsToActionData(pItm, TRUE, iActionType, COST_ROLLASSIGNMENT_CREATE, ppwzActionData); | ||
627 | ExitOnFailure(hr, "Failed to add assembly to custom action data, key: %S", pItm->wzKey); | ||
628 | |||
629 | // add progress tics | ||
630 | if (piProgress) | ||
631 | *piProgress += COST_ROLLASSIGNMENT_CREATE * pItm->iRoleAssignmentsInstallCount; | ||
632 | } | ||
633 | |||
634 | hr = S_OK; | ||
635 | |||
636 | LExit: | ||
637 | return hr; | ||
638 | } | ||
639 | |||
640 | HRESULT CpiRoleAssignmentsUninstall( | ||
641 | CPI_ASSEMBLY_LIST* pList, | ||
642 | int iRunMode, | ||
643 | LPWSTR* ppwzActionData, | ||
644 | int* piProgress | ||
645 | ) | ||
646 | { | ||
647 | HRESULT hr = S_OK; | ||
648 | |||
649 | int iActionType; | ||
650 | |||
651 | // add action text | ||
652 | hr = CpiAddActionTextToActionData(L"RemoveComPlusRoleAssignments", ppwzActionData); | ||
653 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
654 | |||
655 | // add assembly count to action data | ||
656 | hr = WcaWriteIntegerToCaData(pList->iRoleUninstallCount, ppwzActionData); | ||
657 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
658 | |||
659 | // add assemblies to custom action data in reverse order | ||
660 | for (CPI_ASSEMBLY* pItm = pList->pLast; pItm; pItm = pItm->pPrev) | ||
661 | { | ||
662 | // assemblies that are being uninstalled | ||
663 | if (pItm->fIgnore || !pItm->iRoleAssignmentsUninstallCount) | ||
664 | continue; | ||
665 | |||
666 | // action type | ||
667 | if (rmRollback == iRunMode) | ||
668 | iActionType = atCreate; | ||
669 | else | ||
670 | iActionType = atRemove; | ||
671 | |||
672 | // add to action data | ||
673 | hr = AddRoleAssignmentsToActionData(pItm, FALSE, iActionType, COST_ROLLASSIGNMENT_DELETE, ppwzActionData); | ||
674 | ExitOnFailure(hr, "Failed to add assembly to custom action data, key: %S", pItm->wzKey); | ||
675 | |||
676 | // add progress tics | ||
677 | if (piProgress) | ||
678 | *piProgress += COST_ROLLASSIGNMENT_DELETE * pItm->iRoleAssignmentsUninstallCount; | ||
679 | } | ||
680 | |||
681 | hr = S_OK; | ||
682 | |||
683 | LExit: | ||
684 | return hr; | ||
685 | } | ||
686 | |||
687 | HRESULT CpiGetSubscriptionsCollForComponent( | ||
688 | CPI_ASSEMBLY* pAsm, | ||
689 | CPISCHED_COMPONENT* pComp, | ||
690 | ICatalogCollection** ppiSubsColl | ||
691 | ) | ||
692 | { | ||
693 | HRESULT hr = S_OK; | ||
694 | |||
695 | ICatalogCollection* piCompColl = NULL; | ||
696 | ICatalogObject* piCompObj = NULL; | ||
697 | |||
698 | // get applications collection | ||
699 | if (!pComp->piSubsColl) | ||
700 | { | ||
701 | // get components collection for application | ||
702 | hr = CpiGetComponentsCollForApplication(pAsm->pApplication, &piCompColl); | ||
703 | ExitOnFailure(hr, "Failed to get components collection for application"); | ||
704 | |||
705 | if (S_FALSE == hr) | ||
706 | ExitFunction(); // exit with hr = S_FALSE | ||
707 | |||
708 | // find component object | ||
709 | hr = CpiFindCollectionObject(piCompColl, pComp->wzCLSID, NULL, &piCompObj); | ||
710 | ExitOnFailure(hr, "Failed to find component object"); | ||
711 | |||
712 | if (S_FALSE == hr) | ||
713 | ExitFunction(); // exit with hr = S_FALSE | ||
714 | |||
715 | // get roles collection | ||
716 | hr = CpiSchedGetCatalogCollection(piCompColl, piCompObj, L"SubscriptionsForComponent", &pComp->piSubsColl); | ||
717 | ExitOnFailure(hr, "Failed to get subscriptions collection"); | ||
718 | } | ||
719 | |||
720 | // return value | ||
721 | *ppiSubsColl = pComp->piSubsColl; | ||
722 | (*ppiSubsColl)->AddRef(); | ||
723 | |||
724 | hr = S_OK; | ||
725 | |||
726 | LExit: | ||
727 | // clean up | ||
728 | ReleaseObject(piCompColl); | ||
729 | ReleaseObject(piCompObj); | ||
730 | |||
731 | return hr; | ||
732 | } | ||
733 | |||
734 | |||
735 | // helper function definitions | ||
736 | |||
737 | static HRESULT GetAssemblyName( | ||
738 | LPCWSTR pwzComponent, | ||
739 | LPWSTR* ppwzAssemblyName | ||
740 | ) | ||
741 | { | ||
742 | HRESULT hr = S_OK; | ||
743 | |||
744 | PMSIHANDLE hView, hRecKey, hRec; | ||
745 | |||
746 | LPWSTR pwzKey = NULL; | ||
747 | |||
748 | LPWSTR pwzName = NULL; | ||
749 | LPWSTR pwzVersion = NULL; | ||
750 | LPWSTR pwzCulture = NULL; | ||
751 | LPWSTR pwzPublicKeyToken = NULL; | ||
752 | |||
753 | // create parameter record | ||
754 | hRecKey = ::MsiCreateRecord(1); | ||
755 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
756 | hr = WcaSetRecordString(hRecKey, 1, pwzComponent); | ||
757 | ExitOnFailure(hr, "Failed to set record string"); | ||
758 | |||
759 | // open view | ||
760 | hr = WcaOpenView(vcsMsiAssemblyNameQuery, &hView); | ||
761 | ExitOnFailure(hr, "Failed to open view on MsiAssemblyName table"); | ||
762 | hr = WcaExecuteView(hView, hRecKey); | ||
763 | ExitOnFailure(hr, "Failed to execute view on MsiAssemblyName table"); | ||
764 | |||
765 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
766 | { | ||
767 | // read key | ||
768 | hr = WcaGetRecordString(hRec, manqName, &pwzKey); | ||
769 | ExitOnFailure(hr, "Failed to get name"); | ||
770 | |||
771 | // read value | ||
772 | if (0 == lstrcmpiW(L"name", pwzKey)) | ||
773 | hr = WcaGetRecordString(hRec, manqValue, &pwzName); | ||
774 | else if (0 == lstrcmpiW(L"version", pwzKey)) | ||
775 | hr = WcaGetRecordString(hRec, manqValue, &pwzVersion); | ||
776 | else if (0 == lstrcmpiW(L"culture", pwzKey)) | ||
777 | hr = WcaGetRecordString(hRec, manqValue, &pwzCulture); | ||
778 | else if (0 == lstrcmpiW(L"publicKeyToken", pwzKey)) | ||
779 | hr = WcaGetRecordString(hRec, manqValue, &pwzPublicKeyToken); | ||
780 | else | ||
781 | { | ||
782 | WcaLog(LOGMSG_VERBOSE, "Unknown name in MsiAssemblyName table: %S, %S", pwzComponent, pwzKey); | ||
783 | hr = S_OK; | ||
784 | } | ||
785 | |||
786 | ExitOnFailure(hr, "Failed to get value"); | ||
787 | } | ||
788 | |||
789 | if (E_NOMOREITEMS != hr) | ||
790 | ExitOnFailure(hr, "Failed to fetch record"); | ||
791 | |||
792 | // verify | ||
793 | if (!(pwzName && *pwzName) || !(pwzVersion && *pwzVersion)) | ||
794 | ExitOnFailure(hr = E_FAIL, "Incomplete assembly name"); | ||
795 | |||
796 | // build name string | ||
797 | hr = StrAllocFormatted(ppwzAssemblyName, L"%s, Version=%s, Culture=%s, PublicKeyToken=%s", | ||
798 | pwzName, pwzVersion, | ||
799 | pwzCulture && *pwzCulture ? pwzCulture : L"Neutral", | ||
800 | pwzPublicKeyToken && *pwzPublicKeyToken ? pwzPublicKeyToken : L"null"); | ||
801 | ExitOnFailure(hr, "Failed to build assembly name string"); | ||
802 | |||
803 | hr = S_OK; | ||
804 | |||
805 | LExit: | ||
806 | // clean up | ||
807 | ReleaseStr(pwzKey); | ||
808 | ReleaseStr(pwzName); | ||
809 | ReleaseStr(pwzVersion); | ||
810 | ReleaseStr(pwzCulture); | ||
811 | ReleaseStr(pwzPublicKeyToken); | ||
812 | |||
813 | return hr; | ||
814 | } | ||
815 | |||
816 | static HRESULT KeyPairsRead( | ||
817 | LPCWSTR pwzQuery, | ||
818 | CPI_KEY_PAIR** ppKeyPairList | ||
819 | ) | ||
820 | { | ||
821 | HRESULT hr = S_OK; | ||
822 | |||
823 | PMSIHANDLE hView, hRec; | ||
824 | |||
825 | CPI_KEY_PAIR* pItm = NULL; | ||
826 | LPWSTR pwzData = NULL; | ||
827 | |||
828 | // loop through all dependencies | ||
829 | hr = WcaOpenExecuteView(pwzQuery, &hView); | ||
830 | ExitOnFailure(hr, "Failed to execute view on table"); | ||
831 | |||
832 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
833 | { | ||
834 | // create entry | ||
835 | pItm = (CPI_KEY_PAIR*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_KEY_PAIR)); | ||
836 | if (!pItm) | ||
837 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
838 | |||
839 | // get key | ||
840 | hr = WcaGetRecordString(hRec, kpqFirstKey, &pwzData); | ||
841 | ExitOnFailure(hr, "Failed to get first key"); | ||
842 | StringCchCopyW(pItm->wzFirstKey, countof(pItm->wzFirstKey), pwzData); | ||
843 | |||
844 | // get key | ||
845 | hr = WcaGetRecordString(hRec, kpqSecondKey, &pwzData); | ||
846 | ExitOnFailure(hr, "Failed to get second key"); | ||
847 | StringCchCopyW(pItm->wzSecondKey, countof(pItm->wzSecondKey), pwzData); | ||
848 | |||
849 | // add entry | ||
850 | if (*ppKeyPairList) | ||
851 | pItm->pNext = *ppKeyPairList; | ||
852 | *ppKeyPairList = pItm; | ||
853 | pItm = NULL; | ||
854 | } | ||
855 | |||
856 | if (E_NOMOREITEMS == hr) | ||
857 | hr = S_OK; | ||
858 | |||
859 | LExit: | ||
860 | // clean up | ||
861 | if (pItm) | ||
862 | KeyPairsFreeList(pItm); | ||
863 | |||
864 | ReleaseStr(pwzData); | ||
865 | |||
866 | return hr; | ||
867 | } | ||
868 | |||
869 | static HRESULT ModulesRead( | ||
870 | CPI_MODULE_LIST* pModList | ||
871 | ) | ||
872 | { | ||
873 | HRESULT hr = S_OK; | ||
874 | |||
875 | PMSIHANDLE hView, hRec; | ||
876 | |||
877 | CPI_MODULE* pItm = NULL; | ||
878 | LPWSTR pwzData = NULL; | ||
879 | |||
880 | // loop through all modules | ||
881 | hr = WcaOpenExecuteView(vcsModuleQuery, &hView); | ||
882 | ExitOnFailure(hr, "Failed to execute view on ModuleSignature table"); | ||
883 | |||
884 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
885 | { | ||
886 | // create entry | ||
887 | pItm = (CPI_MODULE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_MODULE)); | ||
888 | if (!pItm) | ||
889 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
890 | |||
891 | // get key | ||
892 | hr = WcaGetRecordString(hRec, mqModule, &pwzData); | ||
893 | ExitOnFailure(hr, "Failed to get key"); | ||
894 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
895 | |||
896 | // add entry | ||
897 | if (pModList->pLast) | ||
898 | { | ||
899 | pModList->pLast->pNext = pItm; | ||
900 | pItm->pPrev = pModList->pLast; | ||
901 | } | ||
902 | else | ||
903 | pModList->pFirst = pItm; | ||
904 | pModList->pLast = pItm; | ||
905 | pItm = NULL; | ||
906 | } | ||
907 | |||
908 | if (E_NOMOREITEMS == hr) | ||
909 | hr = S_OK; | ||
910 | |||
911 | LExit: | ||
912 | // clean up | ||
913 | if (pItm) | ||
914 | ModuleFree(pItm); | ||
915 | |||
916 | ReleaseStr(pwzData); | ||
917 | |||
918 | return hr; | ||
919 | } | ||
920 | |||
921 | static HRESULT AssembliesRead( | ||
922 | CPI_KEY_PAIR* pModCompList, | ||
923 | CPI_APPLICATION_LIST* pAppList, | ||
924 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
925 | CPI_ASSEMBLY_LIST* pAsmList | ||
926 | ) | ||
927 | { | ||
928 | HRESULT hr = S_OK; | ||
929 | UINT er = ERROR_SUCCESS; | ||
930 | |||
931 | PMSIHANDLE hView, hRec; | ||
932 | |||
933 | CPI_ASSEMBLY* pItm = NULL; | ||
934 | CPI_KEY_PAIR* pModComp; | ||
935 | LPWSTR pwzData = NULL; | ||
936 | LPWSTR pwzComponent = NULL; | ||
937 | BOOL fMatchingArchitecture = FALSE; | ||
938 | |||
939 | // loop through all assemblies | ||
940 | hr = WcaOpenExecuteView(vcsAssemblyQuery, &hView); | ||
941 | ExitOnFailure(hr, "Failed to execute view on ComPlusAssembly table"); | ||
942 | |||
943 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
944 | { | ||
945 | // get component | ||
946 | hr = WcaGetRecordString(hRec, aqComponent, &pwzComponent); | ||
947 | ExitOnFailure(hr, "Failed to get component"); | ||
948 | |||
949 | // check if the component is our processor architecture | ||
950 | hr = CpiVerifyComponentArchitecure(pwzComponent, &fMatchingArchitecture); | ||
951 | ExitOnFailure(hr, "Failed to get component architecture."); | ||
952 | |||
953 | if (!fMatchingArchitecture) | ||
954 | { | ||
955 | continue; // not the same architecture, ignore | ||
956 | } | ||
957 | |||
958 | // create entry | ||
959 | pItm = (CPI_ASSEMBLY*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_ASSEMBLY)); | ||
960 | if (!pItm) | ||
961 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
962 | |||
963 | // get component install state | ||
964 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzComponent, &pItm->isInstalled, &pItm->isAction); | ||
965 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state"); | ||
966 | |||
967 | // get key | ||
968 | hr = WcaGetRecordString(hRec, aqAssembly, &pwzData); | ||
969 | ExitOnFailure(hr, "Failed to get key"); | ||
970 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
971 | |||
972 | // get attributes | ||
973 | hr = WcaGetRecordInteger(hRec, aqAttributes, &pItm->iAttributes); | ||
974 | ExitOnFailure(hr, "Failed to get attributes"); | ||
975 | |||
976 | // get assembly name | ||
977 | hr = WcaGetRecordFormattedString(hRec, aqAssemblyName, &pItm->pwzAssemblyName); | ||
978 | ExitOnFailure(hr, "Failed to get assembly name"); | ||
979 | |||
980 | if (!*pItm->pwzAssemblyName && (pItm->iAttributes & aaPathFromGAC)) | ||
981 | { | ||
982 | // get assembly name for component | ||
983 | hr = GetAssemblyName(pwzComponent, &pItm->pwzAssemblyName); | ||
984 | ExitOnFailure(hr, "Failed to get assembly name for component"); | ||
985 | } | ||
986 | |||
987 | // get dll path | ||
988 | hr = WcaGetRecordFormattedString(hRec, aqDllPath, &pItm->pwzDllPath); | ||
989 | ExitOnFailure(hr, "Failed to get assembly dll path"); | ||
990 | |||
991 | // get module | ||
992 | // TODO: if there is a very large number of components belonging to modules, this search might be slow | ||
993 | hr = KeyPairFindByFirstKey(pModCompList, pwzData, &pModComp); | ||
994 | |||
995 | if (S_OK == hr) | ||
996 | StringCchCopyW(pItm->wzModule, countof(pItm->wzModule), pModComp->wzSecondKey); | ||
997 | |||
998 | // get application | ||
999 | hr = WcaGetRecordString(hRec, aqApplication, &pwzData); | ||
1000 | ExitOnFailure(hr, "Failed to get application"); | ||
1001 | |||
1002 | if (pwzData && *pwzData) | ||
1003 | { | ||
1004 | hr = CpiApplicationFindByKey(pAppList, pwzData, &pItm->pApplication); | ||
1005 | if (S_FALSE == hr) | ||
1006 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
1007 | ExitOnFailure(hr, "Failed to find application, key: %S", pwzData); | ||
1008 | } | ||
1009 | |||
1010 | // get tlb path | ||
1011 | hr = WcaGetRecordFormattedString(hRec, aqTlbPath, &pItm->pwzTlbPath); | ||
1012 | ExitOnFailure(hr, "Failed to get assembly tlb path"); | ||
1013 | |||
1014 | // get proxy-stub dll path | ||
1015 | hr = WcaGetRecordFormattedString(hRec, aqPSDllPath, &pItm->pwzPSDllPath); | ||
1016 | ExitOnFailure(hr, "Failed to get assembly proxy-stub DLL path"); | ||
1017 | |||
1018 | // read components | ||
1019 | if (CpiTableExists(cptComPlusComponent)) | ||
1020 | { | ||
1021 | hr = ComponentsRead(pItm->wzKey, pAppRoleList, pItm); | ||
1022 | ExitOnFailure(hr, "Failed to read components for assembly"); | ||
1023 | } | ||
1024 | |||
1025 | // set references & increment counters | ||
1026 | if (WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
1027 | { | ||
1028 | pAsmList->iInstallCount++; | ||
1029 | if (pItm->iAttributes & aaRunInCommit) | ||
1030 | pAsmList->iCommitCount++; | ||
1031 | } | ||
1032 | if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction) || WcaIsReInstalling(pItm->isInstalled, pItm->isAction)) | ||
1033 | pAsmList->iUninstallCount++; | ||
1034 | |||
1035 | if (pItm->iRoleAssignmentsInstallCount) | ||
1036 | { | ||
1037 | pAsmList->iRoleInstallCount++; | ||
1038 | if (pItm->iAttributes & aaRunInCommit) | ||
1039 | pAsmList->iRoleCommitCount++; | ||
1040 | } | ||
1041 | if (pItm->iRoleAssignmentsUninstallCount) | ||
1042 | pAsmList->iRoleUninstallCount++; | ||
1043 | |||
1044 | if (pItm->pApplication) | ||
1045 | { | ||
1046 | if (pItm->iRoleAssignmentsInstallCount || WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
1047 | CpiApplicationAddReferenceInstall(pItm->pApplication); | ||
1048 | if (pItm->iRoleAssignmentsUninstallCount || WcaIsUninstalling(pItm->isInstalled, pItm->isAction) || WcaIsReInstalling(pItm->isInstalled, pItm->isAction)) | ||
1049 | CpiApplicationAddReferenceUninstall(pItm->pApplication); | ||
1050 | } | ||
1051 | |||
1052 | // add entry | ||
1053 | if (pAsmList->pLast) | ||
1054 | { | ||
1055 | pAsmList->pLast->pNext = pItm; | ||
1056 | pItm->pPrev = pAsmList->pLast; | ||
1057 | } | ||
1058 | else | ||
1059 | pAsmList->pFirst = pItm; | ||
1060 | pAsmList->pLast = pItm; | ||
1061 | pItm = NULL; | ||
1062 | } | ||
1063 | |||
1064 | if (E_NOMOREITEMS == hr) | ||
1065 | hr = S_OK; | ||
1066 | |||
1067 | LExit: | ||
1068 | // clean up | ||
1069 | if (pItm) | ||
1070 | AssemblyFree(pItm); | ||
1071 | |||
1072 | ReleaseStr(pwzData); | ||
1073 | ReleaseStr(pwzComponent); | ||
1074 | |||
1075 | return hr; | ||
1076 | } | ||
1077 | |||
1078 | static HRESULT TopSortModuleList( | ||
1079 | CPI_KEY_PAIR* pDepList, | ||
1080 | CPI_MODULE_LIST* pList | ||
1081 | ) | ||
1082 | { | ||
1083 | HRESULT hr = S_OK; | ||
1084 | |||
1085 | // top sort list | ||
1086 | for (CPI_MODULE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
1087 | { | ||
1088 | // append module | ||
1089 | hr = SwapDependentModules(NULL, pDepList, pList, pItm, pItm); | ||
1090 | ExitOnFailure(hr, "Failed to swap dependent modules"); | ||
1091 | } | ||
1092 | |||
1093 | hr = S_OK; | ||
1094 | |||
1095 | LExit: | ||
1096 | return hr; | ||
1097 | } | ||
1098 | |||
1099 | static HRESULT SwapDependentModules( | ||
1100 | CPI_DEPENDENCY_CHAIN* pdcPrev, // list containing the entire dependency chain | ||
1101 | CPI_KEY_PAIR* pDepList, // module dependency list | ||
1102 | CPI_MODULE_LIST* pList, // module list being sorted | ||
1103 | CPI_MODULE* pRoot, // first module in the chain | ||
1104 | CPI_MODULE* pItm // current module to test for dependencies | ||
1105 | ) | ||
1106 | { | ||
1107 | HRESULT hr = S_OK; | ||
1108 | |||
1109 | CPI_MODULE* pDepItm; | ||
1110 | |||
1111 | // find dependencies | ||
1112 | for (CPI_KEY_PAIR* pDep = pDepList; pDep; pDep = pDep->pNext) | ||
1113 | { | ||
1114 | if (0 == lstrcmpW(pItm->wzKey, pDep->wzFirstKey)) | ||
1115 | { | ||
1116 | CPI_DEPENDENCY_CHAIN dcItm; | ||
1117 | dcItm.pwzKey = pItm->wzKey; | ||
1118 | dcItm.pPrev = pdcPrev; | ||
1119 | |||
1120 | // check for circular dependencies | ||
1121 | for (CPI_DEPENDENCY_CHAIN* pdcItm = &dcItm; pdcItm; pdcItm = pdcItm->pPrev) | ||
1122 | { | ||
1123 | if (0 == lstrcmpW(pdcItm->pwzKey, pDep->wzSecondKey)) | ||
1124 | { | ||
1125 | // circular dependency found | ||
1126 | ExitOnFailure(hr = E_FAIL, "Circular module dependency found, key: %S", pDep->wzSecondKey); | ||
1127 | } | ||
1128 | } | ||
1129 | |||
1130 | // make sure the item is not already in the list | ||
1131 | hr = ModuleFindByKey(pRoot->pPrev, pDep->wzSecondKey, TRUE, &pDepItm); // find in reverse order | ||
1132 | |||
1133 | if (S_OK == hr) | ||
1134 | continue; // item found, move on | ||
1135 | |||
1136 | // find item in the list | ||
1137 | hr = ModuleFindByKey(pRoot->pNext, pDep->wzSecondKey, FALSE, &pDepItm); // find in forward order | ||
1138 | |||
1139 | if (S_FALSE == hr) | ||
1140 | { | ||
1141 | // not found | ||
1142 | ExitOnFailure(hr = E_FAIL, "Module dependency not found, key: %S", pDep->wzSecondKey); | ||
1143 | } | ||
1144 | |||
1145 | // if this item in turn has dependencies, they have to be swaped first | ||
1146 | hr = SwapDependentModules(&dcItm, pDepList, pList, pRoot, pDepItm); | ||
1147 | ExitOnFailure(hr, "Failed to swap dependent module"); | ||
1148 | |||
1149 | // remove item from its current position | ||
1150 | pDepItm->pPrev->pNext = pDepItm->pNext; // pDepItm can never be the first item, no need to check pPrev | ||
1151 | if (pDepItm->pNext) | ||
1152 | pDepItm->pNext->pPrev = pDepItm->pPrev; | ||
1153 | else | ||
1154 | { | ||
1155 | pList->pLast = pDepItm->pPrev; | ||
1156 | pList->pLast->pNext = NULL; | ||
1157 | } | ||
1158 | |||
1159 | // insert before the current item | ||
1160 | if (pRoot->pPrev) | ||
1161 | pRoot->pPrev->pNext = pDepItm; | ||
1162 | else | ||
1163 | pList->pFirst = pDepItm; | ||
1164 | pDepItm->pPrev = pRoot->pPrev; | ||
1165 | pRoot->pPrev = pDepItm; | ||
1166 | pDepItm->pNext = pRoot; | ||
1167 | } | ||
1168 | } | ||
1169 | |||
1170 | hr = S_OK; | ||
1171 | |||
1172 | LExit: | ||
1173 | return hr; | ||
1174 | } | ||
1175 | |||
1176 | static HRESULT ModuleFindByKey( | ||
1177 | CPI_MODULE* pItm, | ||
1178 | LPCWSTR pwzKey, | ||
1179 | BOOL fReverse, | ||
1180 | CPI_MODULE** ppItm | ||
1181 | ) | ||
1182 | { | ||
1183 | for (; pItm; pItm = fReverse ? pItm->pPrev : pItm->pNext) | ||
1184 | { | ||
1185 | if (0 == lstrcmpW(pItm->wzKey, pwzKey)) | ||
1186 | { | ||
1187 | *ppItm = pItm; | ||
1188 | return S_OK; | ||
1189 | } | ||
1190 | } | ||
1191 | |||
1192 | return S_FALSE; | ||
1193 | } | ||
1194 | |||
1195 | static void SortAssemblyListByModule( | ||
1196 | CPI_MODULE_LIST* pModList, | ||
1197 | CPI_ASSEMBLY_LIST* pAsmList | ||
1198 | ) | ||
1199 | { | ||
1200 | CPI_ASSEMBLY* pMoved = NULL; // first moved item | ||
1201 | |||
1202 | // loop modules in reverse order | ||
1203 | for (CPI_MODULE* pMod = pModList->pLast; pMod; pMod = pMod->pPrev) | ||
1204 | { | ||
1205 | // loop assemblies in forward order, starting with the first unmoved item | ||
1206 | CPI_ASSEMBLY* pAsm = pMoved ? pMoved->pNext : pAsmList->pFirst; | ||
1207 | while (pAsm) | ||
1208 | { | ||
1209 | CPI_ASSEMBLY* pNext = pAsm->pNext; | ||
1210 | |||
1211 | // check if assembly belongs to the current module | ||
1212 | if (0 == lstrcmpW(pMod->wzKey, pAsm->wzModule)) | ||
1213 | { | ||
1214 | // if the item is not already first in the list | ||
1215 | if (pAsm->pPrev) | ||
1216 | { | ||
1217 | // remove item from it's current position | ||
1218 | pAsm->pPrev->pNext = pAsm->pNext; | ||
1219 | if (pAsm->pNext) | ||
1220 | pAsm->pNext->pPrev = pAsm->pPrev; | ||
1221 | else | ||
1222 | pAsmList->pLast = pAsm->pPrev; | ||
1223 | |||
1224 | // insert item first in the list | ||
1225 | pAsmList->pFirst->pPrev = pAsm; | ||
1226 | pAsm->pNext = pAsmList->pFirst; | ||
1227 | pAsm->pPrev = NULL; | ||
1228 | pAsmList->pFirst = pAsm; | ||
1229 | } | ||
1230 | |||
1231 | // if we haven't moved any items yet, this is the first moved item | ||
1232 | if (!pMoved) | ||
1233 | pMoved = pAsm; | ||
1234 | } | ||
1235 | |||
1236 | pAsm = pNext; | ||
1237 | } | ||
1238 | } | ||
1239 | } | ||
1240 | |||
1241 | static HRESULT TopSortAssemblyList( | ||
1242 | CPI_KEY_PAIR* pDepList, | ||
1243 | CPI_ASSEMBLY_LIST* pList | ||
1244 | ) | ||
1245 | { | ||
1246 | HRESULT hr = S_OK; | ||
1247 | |||
1248 | // top sort list | ||
1249 | for (CPI_ASSEMBLY* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
1250 | { | ||
1251 | // append module | ||
1252 | hr = SwapDependentAssemblies(NULL, pDepList, pList, pItm, pItm); | ||
1253 | ExitOnFailure(hr, "Failed to swap dependent assemblies"); | ||
1254 | } | ||
1255 | |||
1256 | hr = S_OK; | ||
1257 | |||
1258 | LExit: | ||
1259 | return hr; | ||
1260 | } | ||
1261 | |||
1262 | static HRESULT SwapDependentAssemblies( | ||
1263 | CPI_DEPENDENCY_CHAIN* pdcPrev, // list containing the entire dependency chain | ||
1264 | CPI_KEY_PAIR* pDepList, // assembly dependency list | ||
1265 | CPI_ASSEMBLY_LIST* pList, // assembly list being sorted | ||
1266 | CPI_ASSEMBLY* pRoot, // first assembly in the chain | ||
1267 | CPI_ASSEMBLY* pItm // current assembly to test for dependencies | ||
1268 | ) | ||
1269 | { | ||
1270 | HRESULT hr = S_OK; | ||
1271 | |||
1272 | CPI_ASSEMBLY* pDepItm; | ||
1273 | |||
1274 | // find dependencies | ||
1275 | for (CPI_KEY_PAIR* pDep = pDepList; pDep; pDep = pDep->pNext) | ||
1276 | { | ||
1277 | if (0 == lstrcmpW(pItm->wzKey, pDep->wzFirstKey)) | ||
1278 | { | ||
1279 | CPI_DEPENDENCY_CHAIN dcItm; | ||
1280 | dcItm.pwzKey = pItm->wzKey; | ||
1281 | dcItm.pPrev = pdcPrev; | ||
1282 | |||
1283 | // check for circular dependencies | ||
1284 | for (CPI_DEPENDENCY_CHAIN* pdcItm = &dcItm; pdcItm; pdcItm = pdcItm->pPrev) | ||
1285 | { | ||
1286 | if (0 == lstrcmpW(pdcItm->pwzKey, pDep->wzSecondKey)) | ||
1287 | { | ||
1288 | // circular dependency found | ||
1289 | ExitOnFailure(hr = E_FAIL, "Circular assembly dependency found, key: %S", pDep->wzSecondKey); | ||
1290 | } | ||
1291 | } | ||
1292 | |||
1293 | // make sure the item is not already in the list | ||
1294 | hr = AssemblyFindByKey(pRoot->pPrev, pDep->wzSecondKey, TRUE, &pDepItm); // find in reverse order | ||
1295 | |||
1296 | if (S_OK == hr) | ||
1297 | continue; // item found, move on | ||
1298 | |||
1299 | // find item in the list | ||
1300 | hr = AssemblyFindByKey(pRoot->pNext, pDep->wzSecondKey, FALSE, &pDepItm); // find in forward order | ||
1301 | |||
1302 | if (S_FALSE == hr) | ||
1303 | { | ||
1304 | // not found | ||
1305 | ExitOnFailure(hr = E_FAIL, "Assembly dependency not found, key: %S", pDep->wzSecondKey); | ||
1306 | } | ||
1307 | |||
1308 | // if the root item belongs to a module, this item must also belong to the same module | ||
1309 | if (*pItm->wzModule) | ||
1310 | { | ||
1311 | if (0 != lstrcmpW(pDepItm->wzModule, pItm->wzModule)) | ||
1312 | ExitOnFailure(hr = E_FAIL, "An assembly dependency can only exist between two assemblies not belonging to modules, or belonging to the same module. assembly: %S, required assembly: %S", pItm->wzKey, pDepItm->wzKey); | ||
1313 | } | ||
1314 | |||
1315 | // if this item in turn has dependencies, they have to be swaped first | ||
1316 | hr = SwapDependentAssemblies(&dcItm, pDepList, pList, pRoot, pDepItm); | ||
1317 | ExitOnFailure(hr, "Failed to swap dependent assemblies"); | ||
1318 | |||
1319 | // remove item from its current position | ||
1320 | pDepItm->pPrev->pNext = pDepItm->pNext; // pDepItm can never be the first item, no need to check pPrev | ||
1321 | if (pDepItm->pNext) | ||
1322 | pDepItm->pNext->pPrev = pDepItm->pPrev; | ||
1323 | else | ||
1324 | { | ||
1325 | pList->pLast = pDepItm->pPrev; | ||
1326 | pList->pLast->pNext = NULL; | ||
1327 | } | ||
1328 | |||
1329 | // insert before the current item | ||
1330 | if (pRoot->pPrev) | ||
1331 | pRoot->pPrev->pNext = pDepItm; | ||
1332 | else | ||
1333 | pList->pFirst = pDepItm; | ||
1334 | pDepItm->pPrev = pRoot->pPrev; | ||
1335 | pRoot->pPrev = pDepItm; | ||
1336 | pDepItm->pNext = pRoot; | ||
1337 | } | ||
1338 | } | ||
1339 | |||
1340 | hr = S_OK; | ||
1341 | |||
1342 | LExit: | ||
1343 | return hr; | ||
1344 | } | ||
1345 | |||
1346 | static HRESULT AssemblyFindByKey( | ||
1347 | CPI_ASSEMBLY* pItm, | ||
1348 | LPCWSTR pwzKey, | ||
1349 | BOOL fReverse, | ||
1350 | CPI_ASSEMBLY** ppItm | ||
1351 | ) | ||
1352 | { | ||
1353 | for (; pItm; pItm = fReverse ? pItm->pPrev : pItm->pNext) | ||
1354 | { | ||
1355 | if (0 == lstrcmpW(pItm->wzKey, pwzKey)) | ||
1356 | { | ||
1357 | *ppItm = pItm; | ||
1358 | return S_OK; | ||
1359 | } | ||
1360 | } | ||
1361 | |||
1362 | return S_FALSE; | ||
1363 | } | ||
1364 | |||
1365 | static HRESULT ComponentsRead( | ||
1366 | LPCWSTR pwzAsmKey, | ||
1367 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
1368 | CPI_ASSEMBLY* pAsm | ||
1369 | ) | ||
1370 | { | ||
1371 | HRESULT hr = S_OK; | ||
1372 | PMSIHANDLE hView; | ||
1373 | PMSIHANDLE hRec; | ||
1374 | PMSIHANDLE hRecKey; | ||
1375 | CPISCHED_COMPONENT* pItm = NULL; | ||
1376 | LPWSTR pwzData = NULL; | ||
1377 | |||
1378 | // create parameter record | ||
1379 | hRecKey = ::MsiCreateRecord(1); | ||
1380 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
1381 | hr = WcaSetRecordString(hRecKey, 1, pwzAsmKey); | ||
1382 | ExitOnFailure(hr, "Failed to set record string"); | ||
1383 | |||
1384 | // open view | ||
1385 | hr = WcaOpenView(vcsComponentQuery, &hView); | ||
1386 | ExitOnFailure(hr, "Failed to open view on ComPlusComponent table"); | ||
1387 | hr = WcaExecuteView(hView, hRecKey); | ||
1388 | ExitOnFailure(hr, "Failed to execute view on ComPlusComponent table"); | ||
1389 | |||
1390 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
1391 | { | ||
1392 | // create entry | ||
1393 | pItm = (CPISCHED_COMPONENT*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPISCHED_COMPONENT)); | ||
1394 | if (!pItm) | ||
1395 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
1396 | |||
1397 | // get key | ||
1398 | hr = WcaGetRecordString(hRec, cqComponent, &pwzData); | ||
1399 | ExitOnFailure(hr, "Failed to get key"); | ||
1400 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
1401 | |||
1402 | // get clsid | ||
1403 | hr = WcaGetRecordFormattedString(hRec, cqCLSID, &pwzData); | ||
1404 | ExitOnFailure(hr, "Failed to get clsid"); | ||
1405 | StringCchCopyW(pItm->wzCLSID, countof(pItm->wzCLSID), pwzData); | ||
1406 | |||
1407 | // read properties | ||
1408 | if (CpiTableExists(cptComPlusComponentProperty)) | ||
1409 | { | ||
1410 | hr = CpiPropertiesRead(vcsComponentPropertyQuery, pItm->wzKey, pdlComponentProperties, &pItm->pProperties, &pItm->iPropertyCount); | ||
1411 | ExitOnFailure(hr, "Failed to get component properties"); | ||
1412 | } | ||
1413 | |||
1414 | // read roles | ||
1415 | if (CpiTableExists(cptComPlusRoleForComponent)) | ||
1416 | { | ||
1417 | hr = RoleAssignmentsRead(vcsRoleForComponentQuery, pItm->wzKey, pAppRoleList, &pItm->pRoles, &pItm->iRoleInstallCount, &pItm->iRoleUninstallCount); | ||
1418 | ExitOnFailure(hr, "Failed to get roles for component"); | ||
1419 | } | ||
1420 | |||
1421 | if (pItm->iRoleInstallCount) | ||
1422 | pAsm->iRoleAssignmentsInstallCount++; | ||
1423 | if (pItm->iRoleUninstallCount) | ||
1424 | pAsm->iRoleAssignmentsUninstallCount++; | ||
1425 | |||
1426 | // read interfaces | ||
1427 | if (CpiTableExists(cptComPlusInterface)) | ||
1428 | { | ||
1429 | hr = InterfacesRead(pItm->wzKey, pAppRoleList, pAsm, pItm); | ||
1430 | ExitOnFailure(hr, "Failed to get interfaces for component"); | ||
1431 | } | ||
1432 | |||
1433 | // add entry | ||
1434 | pAsm->iComponentCount++; | ||
1435 | if (pAsm->pComponents) | ||
1436 | pItm->pNext = pAsm->pComponents; | ||
1437 | pAsm->pComponents = pItm; | ||
1438 | pItm = NULL; | ||
1439 | } | ||
1440 | |||
1441 | if (E_NOMOREITEMS == hr) | ||
1442 | hr = S_OK; | ||
1443 | |||
1444 | LExit: | ||
1445 | // clean up | ||
1446 | if (pItm) | ||
1447 | ComponentsFreeList(pItm); | ||
1448 | |||
1449 | ReleaseStr(pwzData); | ||
1450 | |||
1451 | return hr; | ||
1452 | } | ||
1453 | |||
1454 | static HRESULT InterfacesRead( | ||
1455 | LPCWSTR pwzCompKey, | ||
1456 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
1457 | CPI_ASSEMBLY* pAsm, | ||
1458 | CPISCHED_COMPONENT* pComp | ||
1459 | ) | ||
1460 | { | ||
1461 | HRESULT hr = S_OK; | ||
1462 | PMSIHANDLE hView; | ||
1463 | PMSIHANDLE hRec; | ||
1464 | PMSIHANDLE hRecKey; | ||
1465 | CPISCHED_INTERFACE* pItm = NULL; | ||
1466 | LPWSTR pwzData = NULL; | ||
1467 | |||
1468 | // create parameter record | ||
1469 | hRecKey = ::MsiCreateRecord(1); | ||
1470 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
1471 | hr = WcaSetRecordString(hRecKey, 1, pwzCompKey); | ||
1472 | ExitOnFailure(hr, "Failed to set record string"); | ||
1473 | |||
1474 | // open view | ||
1475 | hr = WcaOpenView(vcsInterfaceQuery, &hView); | ||
1476 | ExitOnFailure(hr, "Failed to open view on ComPlusInterface table"); | ||
1477 | hr = WcaExecuteView(hView, hRecKey); | ||
1478 | ExitOnFailure(hr, "Failed to execute view on ComPlusInterface table"); | ||
1479 | |||
1480 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
1481 | { | ||
1482 | // create entry | ||
1483 | pItm = (CPISCHED_INTERFACE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPISCHED_INTERFACE)); | ||
1484 | if (!pItm) | ||
1485 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
1486 | |||
1487 | // get key | ||
1488 | hr = WcaGetRecordString(hRec, iqInterface, &pwzData); | ||
1489 | ExitOnFailure(hr, "Failed to get key"); | ||
1490 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
1491 | |||
1492 | // get iid | ||
1493 | hr = WcaGetRecordFormattedString(hRec, iqIID, &pwzData); | ||
1494 | ExitOnFailure(hr, "Failed to get iid"); | ||
1495 | StringCchCopyW(pItm->wzIID, countof(pItm->wzIID), pwzData); | ||
1496 | |||
1497 | // read properties | ||
1498 | if (CpiTableExists(cptComPlusInterfaceProperty)) | ||
1499 | { | ||
1500 | hr = CpiPropertiesRead(vcsInterfacePropertyQuery, pItm->wzKey, pdlInterfaceProperties, &pItm->pProperties, &pItm->iPropertyCount); | ||
1501 | ExitOnFailure(hr, "Failed to get interface properties"); | ||
1502 | } | ||
1503 | |||
1504 | // read roles | ||
1505 | if (CpiTableExists(cptComPlusRoleForInterface)) | ||
1506 | { | ||
1507 | hr = RoleAssignmentsRead(vcsRoleForInterfaceQuery, pItm->wzKey, pAppRoleList, &pItm->pRoles, &pItm->iRoleInstallCount, &pItm->iRoleUninstallCount); | ||
1508 | ExitOnFailure(hr, "Failed to get roles for interface"); | ||
1509 | } | ||
1510 | |||
1511 | if (pItm->iRoleInstallCount) | ||
1512 | pAsm->iRoleAssignmentsInstallCount++; | ||
1513 | if (pItm->iRoleUninstallCount) | ||
1514 | pAsm->iRoleAssignmentsUninstallCount++; | ||
1515 | |||
1516 | // read methods | ||
1517 | if (CpiTableExists(cptComPlusMethod)) | ||
1518 | { | ||
1519 | hr = MethodsRead(pItm->wzKey, pAppRoleList, pAsm, pItm); | ||
1520 | ExitOnFailure(hr, "Failed to get methods for interface"); | ||
1521 | } | ||
1522 | |||
1523 | // add entry | ||
1524 | pComp->iInterfaceCount++; | ||
1525 | if (pComp->pInterfaces) | ||
1526 | pItm->pNext = pComp->pInterfaces; | ||
1527 | pComp->pInterfaces = pItm; | ||
1528 | pItm = NULL; | ||
1529 | } | ||
1530 | |||
1531 | if (E_NOMOREITEMS == hr) | ||
1532 | hr = S_OK; | ||
1533 | |||
1534 | LExit: | ||
1535 | // clean up | ||
1536 | if (pItm) | ||
1537 | InterfacesFreeList(pItm); | ||
1538 | |||
1539 | ReleaseStr(pwzData); | ||
1540 | |||
1541 | return hr; | ||
1542 | } | ||
1543 | |||
1544 | static HRESULT MethodsRead( | ||
1545 | LPCWSTR pwzIntfKey, | ||
1546 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
1547 | CPI_ASSEMBLY* pAsm, | ||
1548 | CPISCHED_INTERFACE* pIntf | ||
1549 | ) | ||
1550 | { | ||
1551 | HRESULT hr = S_OK; | ||
1552 | PMSIHANDLE hView, hRec, hRecKey; | ||
1553 | CPISCHED_METHOD* pItm = NULL; | ||
1554 | LPWSTR pwzData = NULL; | ||
1555 | |||
1556 | // create parameter record | ||
1557 | hRecKey = ::MsiCreateRecord(1); | ||
1558 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
1559 | hr = WcaSetRecordString(hRecKey, 1, pwzIntfKey); | ||
1560 | ExitOnFailure(hr, "Failed to set record string"); | ||
1561 | |||
1562 | // open view | ||
1563 | hr = WcaOpenView(vcsMethodQuery, &hView); | ||
1564 | ExitOnFailure(hr, "Failed to open view on ComPlusMethod table"); | ||
1565 | hr = WcaExecuteView(hView, hRecKey); | ||
1566 | ExitOnFailure(hr, "Failed to execute view on ComPlusMethod table"); | ||
1567 | |||
1568 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
1569 | { | ||
1570 | // create entry | ||
1571 | pItm = (CPISCHED_METHOD*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPISCHED_METHOD)); | ||
1572 | if (!pItm) | ||
1573 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
1574 | |||
1575 | // get key | ||
1576 | hr = WcaGetRecordString(hRec, iqInterface, &pwzData); | ||
1577 | ExitOnFailure(hr, "Failed to get key"); | ||
1578 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
1579 | |||
1580 | // get index | ||
1581 | hr = WcaGetRecordFormattedString(hRec, mqIndex, &pwzData); | ||
1582 | ExitOnFailure(hr, "Failed to get index"); | ||
1583 | StringCchCopyW(pItm->wzIndex, countof(pItm->wzIndex), pwzData); | ||
1584 | |||
1585 | // get name | ||
1586 | hr = WcaGetRecordFormattedString(hRec, mqName, &pwzData); | ||
1587 | ExitOnFailure(hr, "Failed to get name"); | ||
1588 | StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData); | ||
1589 | |||
1590 | // either an index or a name must be provided | ||
1591 | if (!*pItm->wzIndex && !*pItm->wzName) | ||
1592 | ExitOnFailure(hr = E_FAIL, "A method must have either an index or a name associated, key: %S", pItm->wzKey); | ||
1593 | |||
1594 | // read properties | ||
1595 | if (CpiTableExists(cptComPlusMethodProperty)) | ||
1596 | { | ||
1597 | hr = CpiPropertiesRead(vcsMethodPropertyQuery, pItm->wzKey, pdlMethodProperties, &pItm->pProperties, &pItm->iPropertyCount); | ||
1598 | ExitOnFailure(hr, "Failed to get method properties"); | ||
1599 | } | ||
1600 | |||
1601 | // read roles | ||
1602 | if (CpiTableExists(cptComPlusRoleForMethod)) | ||
1603 | { | ||
1604 | hr = RoleAssignmentsRead(vcsRoleForMethodQuery, pItm->wzKey, pAppRoleList, &pItm->pRoles, &pItm->iRoleInstallCount, &pItm->iRoleUninstallCount); | ||
1605 | ExitOnFailure(hr, "Failed to get roles for method"); | ||
1606 | } | ||
1607 | |||
1608 | if (pItm->iRoleInstallCount) | ||
1609 | pAsm->iRoleAssignmentsInstallCount++; | ||
1610 | if (pItm->iRoleUninstallCount) | ||
1611 | pAsm->iRoleAssignmentsUninstallCount++; | ||
1612 | |||
1613 | // add entry | ||
1614 | pIntf->iMethodCount++; | ||
1615 | if (pIntf->pMethods) | ||
1616 | pItm->pNext = pIntf->pMethods; | ||
1617 | pIntf->pMethods = pItm; | ||
1618 | pItm = NULL; | ||
1619 | } | ||
1620 | |||
1621 | if (E_NOMOREITEMS == hr) | ||
1622 | hr = S_OK; | ||
1623 | |||
1624 | LExit: | ||
1625 | // clean up | ||
1626 | if (pItm) | ||
1627 | MethodsFreeList(pItm); | ||
1628 | |||
1629 | ReleaseStr(pwzData); | ||
1630 | |||
1631 | return hr; | ||
1632 | } | ||
1633 | |||
1634 | static HRESULT RoleAssignmentsRead( | ||
1635 | LPCWSTR pwzQuery, | ||
1636 | LPCWSTR pwzKey, | ||
1637 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
1638 | CPISCHED_ROLE_ASSIGNMENT** ppRoleList, | ||
1639 | int* piInstallCount, | ||
1640 | int* piUninstallCount | ||
1641 | ) | ||
1642 | { | ||
1643 | HRESULT hr = S_OK; | ||
1644 | UINT er = ERROR_SUCCESS; | ||
1645 | |||
1646 | PMSIHANDLE hView, hRec, hRecKey; | ||
1647 | |||
1648 | CPISCHED_ROLE_ASSIGNMENT* pItm = NULL; | ||
1649 | LPWSTR pwzData = NULL; | ||
1650 | BOOL fMatchingArchitecture = FALSE; | ||
1651 | |||
1652 | // create parameter record | ||
1653 | hRecKey = ::MsiCreateRecord(1); | ||
1654 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
1655 | hr = WcaSetRecordString(hRecKey, 1, pwzKey); | ||
1656 | ExitOnFailure(hr, "Failed to set record string"); | ||
1657 | |||
1658 | // open view | ||
1659 | hr = WcaOpenView(pwzQuery, &hView); | ||
1660 | ExitOnFailure(hr, "Failed to open view on role assignment table"); | ||
1661 | hr = WcaExecuteView(hView, hRecKey); | ||
1662 | ExitOnFailure(hr, "Failed to execute view on role assignment table"); | ||
1663 | |||
1664 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
1665 | { | ||
1666 | // get component | ||
1667 | hr = WcaGetRecordString(hRec, raqComponent, &pwzData); | ||
1668 | ExitOnFailure(hr, "Failed to get assembly component"); | ||
1669 | |||
1670 | // check if the component is our processor architecture | ||
1671 | hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture); | ||
1672 | ExitOnFailure(hr, "Failed to get component architecture."); | ||
1673 | |||
1674 | if (!fMatchingArchitecture) | ||
1675 | { | ||
1676 | continue; // not the same architecture, ignore | ||
1677 | } | ||
1678 | |||
1679 | // create entry | ||
1680 | pItm = (CPISCHED_ROLE_ASSIGNMENT*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPISCHED_ROLE_ASSIGNMENT)); | ||
1681 | if (!pItm) | ||
1682 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
1683 | |||
1684 | // get component install state | ||
1685 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction); | ||
1686 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state"); | ||
1687 | |||
1688 | // get key | ||
1689 | hr = WcaGetRecordString(hRec, raqKey, &pwzData); | ||
1690 | ExitOnFailure(hr, "Failed to get key"); | ||
1691 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
1692 | |||
1693 | // get application role | ||
1694 | hr = WcaGetRecordString(hRec, raqApplicationRole, &pwzData); | ||
1695 | ExitOnFailure(hr, "Failed to get application role"); | ||
1696 | |||
1697 | hr = CpiApplicationRoleFindByKey(pAppRoleList, pwzData, &pItm->pApplicationRole); | ||
1698 | if (S_FALSE == hr) | ||
1699 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
1700 | ExitOnFailure(hr, "Failed to find application, key: %S", pwzData); | ||
1701 | |||
1702 | // set references & increment counters | ||
1703 | if (WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
1704 | { | ||
1705 | CpiApplicationRoleAddReferenceInstall(pItm->pApplicationRole); | ||
1706 | ++*piInstallCount; | ||
1707 | } | ||
1708 | if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
1709 | { | ||
1710 | CpiApplicationRoleAddReferenceUninstall(pItm->pApplicationRole); | ||
1711 | ++*piUninstallCount; | ||
1712 | } | ||
1713 | |||
1714 | // add entry | ||
1715 | if (*ppRoleList) | ||
1716 | pItm->pNext = *ppRoleList; | ||
1717 | *ppRoleList = pItm; | ||
1718 | pItm = NULL; | ||
1719 | } | ||
1720 | |||
1721 | if (E_NOMOREITEMS == hr) | ||
1722 | hr = S_OK; | ||
1723 | |||
1724 | LExit: | ||
1725 | // clean up | ||
1726 | if (pItm) | ||
1727 | RoleAssignmentsFreeList(pItm); | ||
1728 | |||
1729 | ReleaseStr(pwzData); | ||
1730 | |||
1731 | return hr; | ||
1732 | } | ||
1733 | |||
1734 | static HRESULT AddAssemblyToActionData( | ||
1735 | CPI_ASSEMBLY* pItm, | ||
1736 | BOOL fInstall, | ||
1737 | int iActionType, | ||
1738 | int iActionCost, | ||
1739 | LPWSTR* ppwzActionData | ||
1740 | ) | ||
1741 | { | ||
1742 | HRESULT hr = S_OK; | ||
1743 | |||
1744 | // add action information to custom action data | ||
1745 | hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); | ||
1746 | ExitOnFailure(hr, "Failed to add action type to custom action data"); | ||
1747 | hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); | ||
1748 | ExitOnFailure(hr, "Failed to add action cost to custom action data"); | ||
1749 | |||
1750 | // add assembly information to custom action data | ||
1751 | hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); | ||
1752 | ExitOnFailure(hr, "Failed to add assembly key to custom action data"); | ||
1753 | hr = WcaWriteStringToCaData(pItm->pwzAssemblyName, ppwzActionData); | ||
1754 | ExitOnFailure(hr, "Failed to add assembly name to custom action data"); | ||
1755 | hr = WcaWriteStringToCaData(pItm->pwzDllPath, ppwzActionData); | ||
1756 | ExitOnFailure(hr, "Failed to add assembly dll path to custom action data"); | ||
1757 | hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->pwzTlbPath : L"", ppwzActionData); | ||
1758 | ExitOnFailure(hr, "Failed to add assembly tlb path to custom action data"); | ||
1759 | hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->pwzPSDllPath : L"", ppwzActionData); | ||
1760 | ExitOnFailure(hr, "Failed to add assembly proxy-stub dll path to custom action data"); | ||
1761 | hr = WcaWriteIntegerToCaData(pItm->iAttributes, ppwzActionData); | ||
1762 | ExitOnFailure(hr, "Failed to add assembly attributes to custom action data"); | ||
1763 | |||
1764 | // add application information to custom action data | ||
1765 | hr = WcaWriteStringToCaData(pItm->pApplication ? pItm->pApplication->wzID : L"", ppwzActionData); | ||
1766 | ExitOnFailure(hr, "Failed to add application id to custom action data"); | ||
1767 | |||
1768 | // add partition information to custom action data | ||
1769 | LPCWSTR pwzPartID = pItm->pApplication && pItm->pApplication->pPartition ? pItm->pApplication->pPartition->wzID : L""; | ||
1770 | hr = WcaWriteStringToCaData(pwzPartID, ppwzActionData); | ||
1771 | ExitOnFailure(hr, "Failed to add partition id to custom action data"); | ||
1772 | |||
1773 | // add components to custom action data | ||
1774 | // | ||
1775 | // components are needed acording to the following table: | ||
1776 | // | ||
1777 | // Native .NET | ||
1778 | // -------------------------------------------- | ||
1779 | // NoOp | No | No | ||
1780 | // Create | Yes | Yes | ||
1781 | // Remove | Yes | No | ||
1782 | // | ||
1783 | int iCompCount = (atCreate == iActionType || (atRemove == iActionType && 0 == (pItm->iAttributes & aaDotNetAssembly))) ? pItm->iComponentCount : 0; | ||
1784 | hr = WcaWriteIntegerToCaData(iCompCount, ppwzActionData); | ||
1785 | ExitOnFailure(hr, "Failed to add component count to custom action data, key: %S", pItm->wzKey); | ||
1786 | |||
1787 | if (iCompCount) | ||
1788 | { | ||
1789 | for (CPISCHED_COMPONENT* pComp = pItm->pComponents; pComp; pComp = pComp->pNext) | ||
1790 | { | ||
1791 | hr = AddComponentToActionData(pComp, fInstall, atCreate == iActionType, FALSE, ppwzActionData); | ||
1792 | ExitOnFailure(hr, "Failed to add component to custom action data, component: %S", pComp->wzKey); | ||
1793 | } | ||
1794 | } | ||
1795 | |||
1796 | hr = S_OK; | ||
1797 | |||
1798 | LExit: | ||
1799 | return hr; | ||
1800 | } | ||
1801 | |||
1802 | static HRESULT AddRoleAssignmentsToActionData( | ||
1803 | CPI_ASSEMBLY* pItm, | ||
1804 | BOOL fInstall, | ||
1805 | int iActionType, | ||
1806 | int iActionCost, | ||
1807 | LPWSTR* ppwzActionData | ||
1808 | ) | ||
1809 | { | ||
1810 | HRESULT hr = S_OK; | ||
1811 | |||
1812 | // add action information to custom action data | ||
1813 | hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); | ||
1814 | ExitOnFailure(hr, "Failed to add action type to custom action data"); | ||
1815 | hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); | ||
1816 | ExitOnFailure(hr, "Failed to add action cost to custom action data"); | ||
1817 | |||
1818 | // add assembly information to custom action data | ||
1819 | hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); | ||
1820 | ExitOnFailure(hr, "Failed to add assembly key to custom action data"); | ||
1821 | hr = WcaWriteIntegerToCaData(fInstall ? pItm->iRoleAssignmentsInstallCount : pItm->iRoleAssignmentsUninstallCount, ppwzActionData); | ||
1822 | ExitOnFailure(hr, "Failed to add role assignments count to custom action data"); | ||
1823 | |||
1824 | // add application information to custom action data | ||
1825 | hr = WcaWriteStringToCaData(pItm->pApplication ? pItm->pApplication->wzID : L"", ppwzActionData); | ||
1826 | ExitOnFailure(hr, "Failed to add application id to custom action data"); | ||
1827 | |||
1828 | // add partition information to custom action data | ||
1829 | LPCWSTR pwzPartID = pItm->pApplication && pItm->pApplication->pPartition ? pItm->pApplication->pPartition->wzID : L""; | ||
1830 | hr = WcaWriteStringToCaData(pwzPartID, ppwzActionData); | ||
1831 | ExitOnFailure(hr, "Failed to add partition id to custom action data"); | ||
1832 | |||
1833 | // add components to custom action data | ||
1834 | hr = WcaWriteIntegerToCaData(pItm->iComponentCount, ppwzActionData); | ||
1835 | ExitOnFailure(hr, "Failed to add component count to custom action data"); | ||
1836 | |||
1837 | for (CPISCHED_COMPONENT* pComp = pItm->pComponents; pComp; pComp = pComp->pNext) | ||
1838 | { | ||
1839 | hr = AddComponentToActionData(pComp, fInstall, FALSE, TRUE, ppwzActionData); | ||
1840 | ExitOnFailure(hr, "Failed to add component to custom action data, component: %S", pComp->wzKey); | ||
1841 | } | ||
1842 | |||
1843 | hr = S_OK; | ||
1844 | |||
1845 | LExit: | ||
1846 | return hr; | ||
1847 | } | ||
1848 | |||
1849 | static HRESULT AddComponentToActionData( | ||
1850 | CPISCHED_COMPONENT* pItm, | ||
1851 | BOOL fInstall, | ||
1852 | BOOL fProps, | ||
1853 | BOOL fRoles, | ||
1854 | LPWSTR* ppwzActionData | ||
1855 | ) | ||
1856 | { | ||
1857 | HRESULT hr = S_OK; | ||
1858 | |||
1859 | // add component information to custom action data | ||
1860 | hr = WcaWriteStringToCaData(pItm->wzCLSID, ppwzActionData); | ||
1861 | ExitOnFailure(hr, "Failed to add component CLSID to custom action data"); | ||
1862 | |||
1863 | // add properties to custom action data | ||
1864 | hr = CpiAddPropertiesToActionData(fProps ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData); | ||
1865 | ExitOnFailure(hr, "Failed to add properties to custom action data"); | ||
1866 | |||
1867 | // add roles to custom action data | ||
1868 | hr = AddRolesToActionData(pItm->iRoleInstallCount, pItm->iRoleUninstallCount, pItm->pRoles, fInstall, fRoles, ppwzActionData); | ||
1869 | ExitOnFailure(hr, "Failed to add roles to custom action data"); | ||
1870 | |||
1871 | // add interfaces to custom action data | ||
1872 | int iIntfCount = (fProps || fRoles) ? pItm->iInterfaceCount : 0; | ||
1873 | hr = WcaWriteIntegerToCaData(iIntfCount, ppwzActionData); | ||
1874 | ExitOnFailure(hr, "Failed to add interface count to custom action data"); | ||
1875 | |||
1876 | if (iIntfCount) | ||
1877 | { | ||
1878 | for (CPISCHED_INTERFACE* pIntf = pItm->pInterfaces; pIntf; pIntf = pIntf->pNext) | ||
1879 | { | ||
1880 | hr = AddInterfaceToActionData(pIntf, fInstall, fProps, fRoles, ppwzActionData); | ||
1881 | ExitOnFailure(hr, "Failed to add interface custom action data, interface: %S", pIntf->wzKey); | ||
1882 | } | ||
1883 | } | ||
1884 | |||
1885 | hr = S_OK; | ||
1886 | |||
1887 | LExit: | ||
1888 | return hr; | ||
1889 | } | ||
1890 | |||
1891 | static HRESULT AddInterfaceToActionData( | ||
1892 | CPISCHED_INTERFACE* pItm, | ||
1893 | BOOL fInstall, | ||
1894 | BOOL fProps, | ||
1895 | BOOL fRoles, | ||
1896 | LPWSTR* ppwzActionData | ||
1897 | ) | ||
1898 | { | ||
1899 | HRESULT hr = S_OK; | ||
1900 | |||
1901 | // add interface information to custom action data | ||
1902 | hr = WcaWriteStringToCaData(pItm->wzIID, ppwzActionData); | ||
1903 | ExitOnFailure(hr, "Failed to add interface IID to custom action data"); | ||
1904 | |||
1905 | // add properties to custom action data | ||
1906 | hr = CpiAddPropertiesToActionData(fProps ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData); | ||
1907 | ExitOnFailure(hr, "Failed to add properties to custom action data"); | ||
1908 | |||
1909 | // add roles to custom action data | ||
1910 | hr = AddRolesToActionData(pItm->iRoleInstallCount, pItm->iRoleUninstallCount, pItm->pRoles, fInstall, fRoles, ppwzActionData); | ||
1911 | ExitOnFailure(hr, "Failed to add roles to custom action data"); | ||
1912 | |||
1913 | // add methods to custom action data | ||
1914 | hr = WcaWriteIntegerToCaData(pItm->iMethodCount, ppwzActionData); | ||
1915 | ExitOnFailure(hr, "Failed to add method count to custom action data"); | ||
1916 | |||
1917 | for (CPISCHED_METHOD* pMeth = pItm->pMethods; pMeth; pMeth = pMeth->pNext) | ||
1918 | { | ||
1919 | hr = AddMethodToActionData(pMeth, fInstall, fProps, fRoles, ppwzActionData); | ||
1920 | ExitOnFailure(hr, "Failed to add method custom action data, method: %S", pMeth->wzKey); | ||
1921 | } | ||
1922 | |||
1923 | hr = S_OK; | ||
1924 | |||
1925 | LExit: | ||
1926 | return hr; | ||
1927 | } | ||
1928 | |||
1929 | static HRESULT AddMethodToActionData( | ||
1930 | CPISCHED_METHOD* pItm, | ||
1931 | BOOL fInstall, | ||
1932 | BOOL fProps, | ||
1933 | BOOL fRoles, | ||
1934 | LPWSTR* ppwzActionData | ||
1935 | ) | ||
1936 | { | ||
1937 | HRESULT hr = S_OK; | ||
1938 | |||
1939 | // add interface information to custom action data | ||
1940 | hr = WcaWriteStringToCaData(pItm->wzIndex, ppwzActionData); | ||
1941 | ExitOnFailure(hr, "Failed to add method index to custom action data"); | ||
1942 | |||
1943 | hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData); | ||
1944 | ExitOnFailure(hr, "Failed to add method name to custom action data"); | ||
1945 | |||
1946 | // add properties to custom action data | ||
1947 | hr = CpiAddPropertiesToActionData(fProps ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData); | ||
1948 | ExitOnFailure(hr, "Failed to add properties to custom action data"); | ||
1949 | |||
1950 | // add roles to custom action data | ||
1951 | hr = AddRolesToActionData(pItm->iRoleInstallCount, pItm->iRoleUninstallCount, pItm->pRoles, fInstall, fRoles, ppwzActionData); | ||
1952 | ExitOnFailure(hr, "Failed to add roles to custom action data"); | ||
1953 | |||
1954 | hr = S_OK; | ||
1955 | |||
1956 | LExit: | ||
1957 | return hr; | ||
1958 | } | ||
1959 | |||
1960 | static HRESULT AddRolesToActionData( | ||
1961 | int iRoleInstallCount, | ||
1962 | int iRoleUninstallCount, | ||
1963 | CPISCHED_ROLE_ASSIGNMENT* pRoleList, | ||
1964 | BOOL fInstall, | ||
1965 | BOOL fRoles, | ||
1966 | LPWSTR* ppwzActionData | ||
1967 | ) | ||
1968 | { | ||
1969 | HRESULT hr = S_OK; | ||
1970 | |||
1971 | int iRoleCount = fRoles ? (fInstall ? iRoleInstallCount : iRoleUninstallCount) : 0; | ||
1972 | hr = WcaWriteIntegerToCaData(iRoleCount, ppwzActionData); | ||
1973 | ExitOnFailure(hr, "Failed to add role count to custom action data"); | ||
1974 | |||
1975 | if (iRoleCount) | ||
1976 | { | ||
1977 | for (CPISCHED_ROLE_ASSIGNMENT* pRole = pRoleList; pRole; pRole = pRole->pNext) | ||
1978 | { | ||
1979 | // make sure the install state matches the create flag | ||
1980 | if (fInstall ? !WcaIsInstalling(pRole->isInstalled, pRole->isAction) : !WcaIsUninstalling(pRole->isInstalled, pRole->isAction)) | ||
1981 | continue; | ||
1982 | |||
1983 | hr = WcaWriteStringToCaData(pRole->pApplicationRole->wzKey, ppwzActionData); | ||
1984 | ExitOnFailure(hr, "Failed to add key to custom action data, role: %S", pRole->wzKey); | ||
1985 | |||
1986 | hr = WcaWriteStringToCaData(pRole->pApplicationRole->wzName, ppwzActionData); | ||
1987 | ExitOnFailure(hr, "Failed to add role name to custom action data, role: %S", pRole->wzKey); | ||
1988 | } | ||
1989 | } | ||
1990 | |||
1991 | hr = S_OK; | ||
1992 | |||
1993 | LExit: | ||
1994 | return hr; | ||
1995 | } | ||
1996 | |||
1997 | static HRESULT KeyPairFindByFirstKey( | ||
1998 | CPI_KEY_PAIR* pList, | ||
1999 | LPCWSTR pwzKey, | ||
2000 | CPI_KEY_PAIR** ppItm | ||
2001 | ) | ||
2002 | { | ||
2003 | for (; pList; pList = pList->pNext) | ||
2004 | { | ||
2005 | if (0 == lstrcmpW(pList->wzFirstKey, pwzKey)) | ||
2006 | { | ||
2007 | *ppItm = pList; | ||
2008 | return S_OK; | ||
2009 | } | ||
2010 | } | ||
2011 | |||
2012 | return S_FALSE; | ||
2013 | } | ||
2014 | |||
2015 | static void AssemblyFree( | ||
2016 | CPI_ASSEMBLY* pItm | ||
2017 | ) | ||
2018 | { | ||
2019 | ReleaseStr(pItm->pwzAssemblyName); | ||
2020 | ReleaseStr(pItm->pwzDllPath); | ||
2021 | ReleaseStr(pItm->pwzTlbPath); | ||
2022 | ReleaseStr(pItm->pwzPSDllPath); | ||
2023 | |||
2024 | if (pItm->pComponents) | ||
2025 | ComponentsFreeList(pItm->pComponents); | ||
2026 | |||
2027 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
2028 | } | ||
2029 | |||
2030 | static void KeyPairsFreeList( | ||
2031 | CPI_KEY_PAIR* pList | ||
2032 | ) | ||
2033 | { | ||
2034 | while (pList) | ||
2035 | { | ||
2036 | CPI_KEY_PAIR* pDelete = pList; | ||
2037 | pList = pList->pNext; | ||
2038 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
2039 | } | ||
2040 | } | ||
2041 | |||
2042 | void ModuleListFree( | ||
2043 | CPI_MODULE_LIST* pList | ||
2044 | ) | ||
2045 | { | ||
2046 | CPI_MODULE* pItm = pList->pFirst; | ||
2047 | |||
2048 | while (pItm) | ||
2049 | { | ||
2050 | CPI_MODULE* pDelete = pItm; | ||
2051 | pItm = pItm->pNext; | ||
2052 | ModuleFree(pDelete); | ||
2053 | } | ||
2054 | } | ||
2055 | |||
2056 | static void ModuleFree( | ||
2057 | CPI_MODULE* pItm | ||
2058 | ) | ||
2059 | { | ||
2060 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
2061 | } | ||
2062 | |||
2063 | static void ComponentsFreeList( | ||
2064 | CPISCHED_COMPONENT* pList | ||
2065 | ) | ||
2066 | { | ||
2067 | while (pList) | ||
2068 | { | ||
2069 | if (pList->pProperties) | ||
2070 | CpiPropertiesFreeList(pList->pProperties); | ||
2071 | |||
2072 | if (pList->pRoles) | ||
2073 | RoleAssignmentsFreeList(pList->pRoles); | ||
2074 | |||
2075 | if (pList->pInterfaces) | ||
2076 | InterfacesFreeList(pList->pInterfaces); | ||
2077 | |||
2078 | ReleaseObject(pList->piSubsColl); | ||
2079 | |||
2080 | CPISCHED_COMPONENT* pDelete = pList; | ||
2081 | pList = pList->pNext; | ||
2082 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
2083 | } | ||
2084 | } | ||
2085 | |||
2086 | static void InterfacesFreeList( | ||
2087 | CPISCHED_INTERFACE* pList | ||
2088 | ) | ||
2089 | { | ||
2090 | while (pList) | ||
2091 | { | ||
2092 | if (pList->pProperties) | ||
2093 | CpiPropertiesFreeList(pList->pProperties); | ||
2094 | |||
2095 | if (pList->pRoles) | ||
2096 | RoleAssignmentsFreeList(pList->pRoles); | ||
2097 | |||
2098 | if (pList->pMethods) | ||
2099 | MethodsFreeList(pList->pMethods); | ||
2100 | |||
2101 | CPISCHED_INTERFACE* pDelete = pList; | ||
2102 | pList = pList->pNext; | ||
2103 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
2104 | } | ||
2105 | } | ||
2106 | |||
2107 | static void MethodsFreeList( | ||
2108 | CPISCHED_METHOD* pList | ||
2109 | ) | ||
2110 | { | ||
2111 | while (pList) | ||
2112 | { | ||
2113 | if (pList->pProperties) | ||
2114 | CpiPropertiesFreeList(pList->pProperties); | ||
2115 | |||
2116 | if (pList->pRoles) | ||
2117 | RoleAssignmentsFreeList(pList->pRoles); | ||
2118 | |||
2119 | CPISCHED_METHOD* pDelete = pList; | ||
2120 | pList = pList->pNext; | ||
2121 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
2122 | } | ||
2123 | } | ||
2124 | |||
2125 | static void RoleAssignmentsFreeList( | ||
2126 | CPISCHED_ROLE_ASSIGNMENT* pList | ||
2127 | ) | ||
2128 | { | ||
2129 | while (pList) | ||
2130 | { | ||
2131 | CPISCHED_ROLE_ASSIGNMENT* pDelete = pList; | ||
2132 | pList = pList->pNext; | ||
2133 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
2134 | } | ||
2135 | } | ||