diff options
Diffstat (limited to 'src/ca/cpasmexec.cpp')
-rw-r--r-- | src/ca/cpasmexec.cpp | 1888 |
1 files changed, 1888 insertions, 0 deletions
diff --git a/src/ca/cpasmexec.cpp b/src/ca/cpasmexec.cpp new file mode 100644 index 00000000..339c08e1 --- /dev/null +++ b/src/ca/cpasmexec.cpp | |||
@@ -0,0 +1,1888 @@ | |||
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 | // GAC related declarations | ||
7 | |||
8 | typedef struct _FUSION_INSTALL_REFERENCE_ | ||
9 | { | ||
10 | DWORD cbSize; | ||
11 | DWORD dwFlags; | ||
12 | GUID guidScheme; | ||
13 | LPCWSTR szIdentifier; | ||
14 | LPCWSTR szNonCannonicalData; | ||
15 | } FUSION_INSTALL_REFERENCE; | ||
16 | |||
17 | typedef struct _FUSION_INSTALL_REFERENCE_ *LPFUSION_INSTALL_REFERENCE; | ||
18 | |||
19 | typedef const FUSION_INSTALL_REFERENCE *LPCFUSION_INSTALL_REFERENCE; | ||
20 | |||
21 | typedef struct _ASSEMBLY_INFO | ||
22 | { | ||
23 | ULONG cbAssemblyInfo; | ||
24 | DWORD dwAssemblyFlags; | ||
25 | ULARGE_INTEGER uliAssemblySizeInKB; | ||
26 | LPWSTR pszCurrentAssemblyPathBuf; | ||
27 | ULONG cchBuf; | ||
28 | } ASSEMBLY_INFO; | ||
29 | |||
30 | typedef interface IAssemblyCacheItem IAssemblyCacheItem; | ||
31 | |||
32 | MIDL_INTERFACE("e707dcde-d1cd-11d2-bab9-00c04f8eceae") | ||
33 | IAssemblyCache : public IUnknown | ||
34 | { | ||
35 | public: | ||
36 | virtual HRESULT STDMETHODCALLTYPE UninstallAssembly( | ||
37 | /* [in] */ DWORD dwFlags, | ||
38 | /* [in] */ LPCWSTR pszAssemblyName, | ||
39 | /* [in] */ LPCFUSION_INSTALL_REFERENCE pRefData, | ||
40 | /* [optional][out] */ ULONG *pulDisposition) = 0; | ||
41 | |||
42 | virtual HRESULT STDMETHODCALLTYPE QueryAssemblyInfo( | ||
43 | /* [in] */ DWORD dwFlags, | ||
44 | /* [in] */ LPCWSTR pszAssemblyName, | ||
45 | /* [out][in] */ ASSEMBLY_INFO *pAsmInfo) = 0; | ||
46 | |||
47 | virtual HRESULT STDMETHODCALLTYPE CreateAssemblyCacheItem( | ||
48 | /* [in] */ DWORD dwFlags, | ||
49 | /* [in] */ PVOID pvReserved, | ||
50 | /* [out] */ IAssemblyCacheItem **ppAsmItem, | ||
51 | /* [optional][in] */ LPCWSTR pszAssemblyName) = 0; | ||
52 | |||
53 | virtual HRESULT STDMETHODCALLTYPE CreateAssemblyScavenger( | ||
54 | /* [out] */ IUnknown **ppUnkReserved) = 0; | ||
55 | |||
56 | virtual HRESULT STDMETHODCALLTYPE InstallAssembly( | ||
57 | /* [in] */ DWORD dwFlags, | ||
58 | /* [in] */ LPCWSTR pszManifestFilePath, | ||
59 | /* [in] */ LPCFUSION_INSTALL_REFERENCE pRefData) = 0; | ||
60 | }; | ||
61 | |||
62 | typedef HRESULT (__stdcall *LoadLibraryShimFunc)(LPCWSTR szDllName, LPCWSTR szVersion, LPVOID pvReserved, HMODULE *phModDll); | ||
63 | typedef HRESULT (__stdcall *CreateAssemblyCacheFunc)(IAssemblyCache **ppAsmCache, DWORD dwReserved); | ||
64 | |||
65 | |||
66 | // RegistrationHelper related declarations | ||
67 | |||
68 | static const GUID CLSID_RegistrationHelper = | ||
69 | { 0x89a86e7b, 0xc229, 0x4008, { 0x9b, 0xaa, 0x2f, 0x5c, 0x84, 0x11, 0xd7, 0xe0 } }; | ||
70 | |||
71 | enum eInstallationFlags { | ||
72 | ifConfigureComponentsOnly = 16, | ||
73 | ifFindOrCreateTargetApplication = 4, | ||
74 | ifExpectExistingTypeLib = 1 | ||
75 | }; | ||
76 | |||
77 | |||
78 | // private constants | ||
79 | |||
80 | enum eAssemblyAttributes | ||
81 | { | ||
82 | aaEventClass = (1 << 0), | ||
83 | aaDotNetAssembly = (1 << 1), | ||
84 | aaPathFromGAC = (1 << 2), | ||
85 | aaRunInCommit = (1 << 3) | ||
86 | }; | ||
87 | |||
88 | |||
89 | // private structs | ||
90 | |||
91 | struct CPI_ROLE_ASSIGNMENT | ||
92 | { | ||
93 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
94 | WCHAR wzRoleName[MAX_DARWIN_COLUMN + 1]; | ||
95 | |||
96 | CPI_ROLE_ASSIGNMENT* pNext; | ||
97 | }; | ||
98 | |||
99 | struct CPI_METHOD | ||
100 | { | ||
101 | WCHAR wzIndex[11 + 1]; | ||
102 | WCHAR wzName[MAX_DARWIN_COLUMN + 1]; | ||
103 | |||
104 | CPI_PROPERTY* pPropertyList; | ||
105 | CPI_ROLE_ASSIGNMENT* pRoleAssignmentList; | ||
106 | |||
107 | CPI_METHOD* pNext; | ||
108 | }; | ||
109 | |||
110 | struct CPI_INTERFACE | ||
111 | { | ||
112 | WCHAR wzIID[CPI_MAX_GUID + 1]; | ||
113 | |||
114 | CPI_PROPERTY* pPropertyList; | ||
115 | CPI_ROLE_ASSIGNMENT* pRoleAssignmentList; | ||
116 | CPI_METHOD* pMethodList; | ||
117 | |||
118 | CPI_INTERFACE* pNext; | ||
119 | }; | ||
120 | |||
121 | struct CPI_COMPONENT | ||
122 | { | ||
123 | WCHAR wzCLSID[CPI_MAX_GUID + 1]; | ||
124 | |||
125 | CPI_PROPERTY* pPropertyList; | ||
126 | CPI_ROLE_ASSIGNMENT* pRoleAssignmentList; | ||
127 | CPI_INTERFACE* pInterfaceList; | ||
128 | |||
129 | CPI_COMPONENT* pNext; | ||
130 | }; | ||
131 | |||
132 | struct CPI_ASSEMBLY_ATTRIBUTES | ||
133 | { | ||
134 | int iActionType; | ||
135 | int iActionCost; | ||
136 | LPWSTR pwzKey; | ||
137 | LPWSTR pwzAssemblyName; | ||
138 | LPWSTR pwzDllPath; | ||
139 | LPWSTR pwzTlbPath; | ||
140 | LPWSTR pwzPSDllPath; | ||
141 | LPWSTR pwzAppID; | ||
142 | LPWSTR pwzPartID; | ||
143 | int iAttributes; | ||
144 | CPI_COMPONENT* pCompList; | ||
145 | }; | ||
146 | |||
147 | struct CPI_ROLE_ASSIGNMENTS_ATTRIBUTES | ||
148 | { | ||
149 | int iActionType; | ||
150 | int iActionCost; | ||
151 | LPWSTR pwzKey; | ||
152 | LPWSTR pwzAppID; | ||
153 | LPWSTR pwzPartID; | ||
154 | int iRoleCount; | ||
155 | CPI_COMPONENT* pCompList; | ||
156 | }; | ||
157 | |||
158 | |||
159 | // prototypes for private helper functions | ||
160 | |||
161 | static HRESULT RegisterAssembly( | ||
162 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
163 | ); | ||
164 | static HRESULT UnregisterAssembly( | ||
165 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
166 | ); | ||
167 | static void InitAssemblyExec(); | ||
168 | static void UninitAssemblyExec(); | ||
169 | static HRESULT GetRegistrationHelper( | ||
170 | IDispatch** ppiRegHlp | ||
171 | ); | ||
172 | static HRESULT GetAssemblyCacheObject( | ||
173 | IAssemblyCache** ppAssemblyCache | ||
174 | ); | ||
175 | static HRESULT GetAssemblyPathFromGAC( | ||
176 | LPCWSTR pwzAssemblyName, | ||
177 | LPWSTR* ppwzAssemblyPath | ||
178 | ); | ||
179 | static HRESULT RegisterDotNetAssembly( | ||
180 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
181 | ); | ||
182 | static HRESULT RegisterNativeAssembly( | ||
183 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
184 | ); | ||
185 | static HRESULT UnregisterDotNetAssembly( | ||
186 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
187 | ); | ||
188 | static HRESULT RemoveComponents( | ||
189 | ICatalogCollection* piCompColl, | ||
190 | CPI_COMPONENT* pCompList | ||
191 | ); | ||
192 | static HRESULT ReadAssemblyAttributes( | ||
193 | LPWSTR* ppwzData, | ||
194 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
195 | ); | ||
196 | static void FreeAssemblyAttributes( | ||
197 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
198 | ); | ||
199 | static HRESULT ReadRoleAssignmentsAttributes( | ||
200 | LPWSTR* ppwzData, | ||
201 | CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs | ||
202 | ); | ||
203 | static void FreeRoleAssignmentsAttributes( | ||
204 | CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs | ||
205 | ); | ||
206 | static HRESULT ConfigureComponents( | ||
207 | LPCWSTR pwzPartID, | ||
208 | LPCWSTR pwzAppID, | ||
209 | CPI_COMPONENT* pCompList, | ||
210 | BOOL fCreate, | ||
211 | BOOL fProgress | ||
212 | ); | ||
213 | static HRESULT ConfigureInterfaces( | ||
214 | ICatalogCollection* piCompColl, | ||
215 | ICatalogObject* piCompObj, | ||
216 | CPI_INTERFACE* pIntfList, | ||
217 | BOOL fCreate | ||
218 | ); | ||
219 | static HRESULT ConfigureMethods( | ||
220 | ICatalogCollection* piIntfColl, | ||
221 | ICatalogObject* piIntfObj, | ||
222 | CPI_METHOD* pMethList, | ||
223 | BOOL fCreate | ||
224 | ); | ||
225 | static HRESULT ConfigureRoleAssignments( | ||
226 | LPCWSTR pwzCollName, | ||
227 | ICatalogCollection* piCompColl, | ||
228 | ICatalogObject* piCompObj, | ||
229 | CPI_ROLE_ASSIGNMENT* pRoleList, | ||
230 | BOOL fCreate | ||
231 | ); | ||
232 | static HRESULT ReadComponentList( | ||
233 | LPWSTR* ppwzData, | ||
234 | CPI_COMPONENT** ppCompList | ||
235 | ); | ||
236 | static HRESULT ReadInterfaceList( | ||
237 | LPWSTR* ppwzData, | ||
238 | CPI_INTERFACE** ppIntfList | ||
239 | ); | ||
240 | static HRESULT ReadMethodList( | ||
241 | LPWSTR* ppwzData, | ||
242 | CPI_METHOD** ppMethList | ||
243 | ); | ||
244 | static HRESULT ReadRoleAssignmentList( | ||
245 | LPWSTR* ppwzData, | ||
246 | CPI_ROLE_ASSIGNMENT** ppRoleList | ||
247 | ); | ||
248 | static void FreeComponentList( | ||
249 | CPI_COMPONENT* pList | ||
250 | ); | ||
251 | static void FreeInterfaceList( | ||
252 | CPI_INTERFACE* pList | ||
253 | ); | ||
254 | static void FreeMethodList( | ||
255 | CPI_METHOD* pList | ||
256 | ); | ||
257 | static void FreeRoleAssignmentList( | ||
258 | CPI_ROLE_ASSIGNMENT* pList | ||
259 | ); | ||
260 | |||
261 | |||
262 | // variables | ||
263 | |||
264 | static IDispatch* gpiRegHlp; | ||
265 | static IAssemblyCache* gpAssemblyCache; | ||
266 | static HMODULE ghMscoree; | ||
267 | static HMODULE ghFusion; | ||
268 | |||
269 | |||
270 | // function definitions | ||
271 | |||
272 | HRESULT CpiConfigureAssemblies( | ||
273 | LPWSTR* ppwzData, | ||
274 | HANDLE hRollbackFile | ||
275 | ) | ||
276 | { | ||
277 | HRESULT hr = S_OK; | ||
278 | |||
279 | CPI_ASSEMBLY_ATTRIBUTES attrs; | ||
280 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
281 | |||
282 | // initialize | ||
283 | InitAssemblyExec(); | ||
284 | |||
285 | // read action text | ||
286 | hr = CpiActionStartMessage(ppwzData, FALSE); | ||
287 | ExitOnFailure(hr, "Failed to send action start message"); | ||
288 | |||
289 | // get count | ||
290 | int iCnt = 0; | ||
291 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
292 | ExitOnFailure(hr, "Failed to read count"); | ||
293 | |||
294 | // write count to rollback file | ||
295 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); | ||
296 | ExitOnFailure(hr, "Failed to write count to rollback file"); | ||
297 | |||
298 | for (int i = 0; i < iCnt; i++) | ||
299 | { | ||
300 | // read attributes from CustomActionData | ||
301 | hr = ReadAssemblyAttributes(ppwzData, &attrs); | ||
302 | ExitOnFailure(hr, "Failed to read assembly attributes"); | ||
303 | |||
304 | // write key to rollback file | ||
305 | hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); | ||
306 | ExitOnFailure(hr, "Failed to write key to rollback file"); | ||
307 | |||
308 | // action | ||
309 | switch (attrs.iActionType) | ||
310 | { | ||
311 | case atCreate: | ||
312 | hr = RegisterAssembly(&attrs); | ||
313 | ExitOnFailure(hr, "Failed to register assembly, key: %S", attrs.pwzKey); | ||
314 | break; | ||
315 | case atRemove: | ||
316 | hr = UnregisterAssembly(&attrs); | ||
317 | ExitOnFailure(hr, "Failed to unregister assembly, key: %S", attrs.pwzKey); | ||
318 | break; | ||
319 | default: | ||
320 | hr = S_OK; | ||
321 | break; | ||
322 | } | ||
323 | |||
324 | if (S_FALSE == hr) | ||
325 | ExitFunction(); // aborted by user | ||
326 | |||
327 | // write completion status to rollback file | ||
328 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); | ||
329 | ExitOnFailure(hr, "Failed to write completion status to rollback file"); | ||
330 | |||
331 | // progress | ||
332 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
333 | ExitOnFailure(hr, "Failed to update progress"); | ||
334 | } | ||
335 | |||
336 | hr = S_OK; | ||
337 | |||
338 | LExit: | ||
339 | // clean up | ||
340 | FreeAssemblyAttributes(&attrs); | ||
341 | |||
342 | // uninitialize | ||
343 | UninitAssemblyExec(); | ||
344 | |||
345 | return hr; | ||
346 | } | ||
347 | |||
348 | HRESULT CpiRollbackConfigureAssemblies( | ||
349 | LPWSTR* ppwzData, | ||
350 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
351 | ) | ||
352 | { | ||
353 | HRESULT hr = S_OK; | ||
354 | |||
355 | int iRollbackStatus; | ||
356 | |||
357 | CPI_ASSEMBLY_ATTRIBUTES attrs; | ||
358 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
359 | |||
360 | // initialize | ||
361 | InitAssemblyExec(); | ||
362 | |||
363 | // read action text | ||
364 | hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); | ||
365 | ExitOnFailure(hr, "Failed to send action start message"); | ||
366 | |||
367 | // get count | ||
368 | int iCnt = 0; | ||
369 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
370 | ExitOnFailure(hr, "Failed to read count"); | ||
371 | |||
372 | for (int i = 0; i < iCnt; i++) | ||
373 | { | ||
374 | // read attributes from CustomActionData | ||
375 | hr = ReadAssemblyAttributes(ppwzData, &attrs); | ||
376 | ExitOnFailure(hr, "Failed to read assembly attributes"); | ||
377 | |||
378 | // rollback status | ||
379 | hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); | ||
380 | |||
381 | if (S_FALSE == hr) | ||
382 | continue; // not found, nothing to rollback | ||
383 | |||
384 | // action | ||
385 | switch (attrs.iActionType) | ||
386 | { | ||
387 | case atCreate: | ||
388 | hr = RegisterAssembly(&attrs); | ||
389 | if (FAILED(hr)) | ||
390 | WcaLog(LOGMSG_STANDARD, "Failed to register assembly, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
391 | break; | ||
392 | case atRemove: | ||
393 | hr = UnregisterAssembly(&attrs); | ||
394 | if (FAILED(hr)) | ||
395 | WcaLog(LOGMSG_STANDARD, "Failed to unregister assembly, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
396 | break; | ||
397 | } | ||
398 | |||
399 | // check rollback status | ||
400 | if (0 == iRollbackStatus) | ||
401 | continue; // operation did not complete, skip progress | ||
402 | |||
403 | // progress | ||
404 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
405 | ExitOnFailure(hr, "Failed to update progress"); | ||
406 | } | ||
407 | |||
408 | hr = S_OK; | ||
409 | |||
410 | LExit: | ||
411 | // clean up | ||
412 | FreeAssemblyAttributes(&attrs); | ||
413 | |||
414 | // uninitialize | ||
415 | UninitAssemblyExec(); | ||
416 | |||
417 | return hr; | ||
418 | } | ||
419 | |||
420 | HRESULT CpiConfigureRoleAssignments( | ||
421 | LPWSTR* ppwzData, | ||
422 | HANDLE hRollbackFile | ||
423 | ) | ||
424 | { | ||
425 | HRESULT hr = S_OK; | ||
426 | |||
427 | CPI_ROLE_ASSIGNMENTS_ATTRIBUTES attrs; | ||
428 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
429 | |||
430 | // read action text | ||
431 | hr = CpiActionStartMessage(ppwzData, FALSE); | ||
432 | ExitOnFailure(hr, "Failed to send action start message"); | ||
433 | |||
434 | // get count | ||
435 | int iCnt = 0; | ||
436 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
437 | ExitOnFailure(hr, "Failed to read count"); | ||
438 | |||
439 | // write count to rollback file | ||
440 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); | ||
441 | ExitOnFailure(hr, "Failed to write count to rollback file"); | ||
442 | |||
443 | for (int i = 0; i < iCnt; i++) | ||
444 | { | ||
445 | // read attributes from CustomActionData | ||
446 | hr = ReadRoleAssignmentsAttributes(ppwzData, &attrs); | ||
447 | ExitOnFailure(hr, "Failed to read role assignments attributes"); | ||
448 | |||
449 | // write key to rollback file | ||
450 | hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); | ||
451 | ExitOnFailure(hr, "Failed to write key to rollback file"); | ||
452 | |||
453 | // action | ||
454 | if (atNoOp != attrs.iActionType) | ||
455 | { | ||
456 | hr = ConfigureComponents(attrs.pwzPartID, attrs.pwzAppID, attrs.pCompList, atCreate == attrs.iActionType, TRUE); | ||
457 | ExitOnFailure(hr, "Failed to configure components"); | ||
458 | |||
459 | if (S_FALSE == hr) | ||
460 | ExitFunction(); // aborted by user | ||
461 | } | ||
462 | |||
463 | // write completion status to rollback file | ||
464 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); | ||
465 | ExitOnFailure(hr, "Failed to write completion status to rollback file"); | ||
466 | |||
467 | // progress | ||
468 | hr = WcaProgressMessage(attrs.iActionCost * attrs.iRoleCount, FALSE); | ||
469 | ExitOnFailure(hr, "Failed to update progress"); | ||
470 | } | ||
471 | |||
472 | hr = S_OK; | ||
473 | |||
474 | LExit: | ||
475 | // clean up | ||
476 | FreeRoleAssignmentsAttributes(&attrs); | ||
477 | |||
478 | return hr; | ||
479 | } | ||
480 | |||
481 | HRESULT CpiRollbackConfigureRoleAssignments( | ||
482 | LPWSTR* ppwzData, | ||
483 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
484 | ) | ||
485 | { | ||
486 | HRESULT hr = S_OK; | ||
487 | |||
488 | int iRollbackStatus; | ||
489 | |||
490 | CPI_ROLE_ASSIGNMENTS_ATTRIBUTES attrs; | ||
491 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
492 | |||
493 | // read action text | ||
494 | hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); | ||
495 | ExitOnFailure(hr, "Failed to send action start message"); | ||
496 | |||
497 | // get count | ||
498 | int iCnt = 0; | ||
499 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
500 | ExitOnFailure(hr, "Failed to read count"); | ||
501 | |||
502 | for (int i = 0; i < iCnt; i++) | ||
503 | { | ||
504 | // read attributes from CustomActionData | ||
505 | hr = ReadRoleAssignmentsAttributes(ppwzData, &attrs); | ||
506 | ExitOnFailure(hr, "Failed to read role assignments attributes"); | ||
507 | |||
508 | // rollback status | ||
509 | hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); | ||
510 | |||
511 | if (S_FALSE == hr) | ||
512 | continue; // not found, nothing to rollback | ||
513 | |||
514 | // action | ||
515 | if (atNoOp != attrs.iActionType) | ||
516 | { | ||
517 | hr = ConfigureComponents(attrs.pwzPartID, attrs.pwzAppID, attrs.pCompList, atCreate == attrs.iActionType, TRUE); | ||
518 | ExitOnFailure(hr, "Failed to configure components"); | ||
519 | |||
520 | if (S_FALSE == hr) | ||
521 | ExitFunction(); // aborted by user | ||
522 | } | ||
523 | |||
524 | // check rollback status | ||
525 | if (0 == iRollbackStatus) | ||
526 | continue; // operation did not complete, skip progress | ||
527 | |||
528 | // progress | ||
529 | hr = WcaProgressMessage(attrs.iActionCost * attrs.iRoleCount, FALSE); | ||
530 | ExitOnFailure(hr, "Failed to update progress"); | ||
531 | } | ||
532 | |||
533 | hr = S_OK; | ||
534 | |||
535 | LExit: | ||
536 | // clean up | ||
537 | FreeRoleAssignmentsAttributes(&attrs); | ||
538 | |||
539 | return hr; | ||
540 | } | ||
541 | |||
542 | |||
543 | // helper function definitions | ||
544 | |||
545 | static HRESULT RegisterAssembly( | ||
546 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
547 | ) | ||
548 | { | ||
549 | HRESULT hr = S_OK; | ||
550 | |||
551 | // progress message | ||
552 | hr = CpiActionDataMessage(1, (pAttrs->iAttributes & aaPathFromGAC) ? pAttrs->pwzAssemblyName : pAttrs->pwzDllPath); | ||
553 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
554 | |||
555 | if (S_FALSE == hr) | ||
556 | ExitFunction(); // aborted by user | ||
557 | |||
558 | // log | ||
559 | WcaLog(LOGMSG_VERBOSE, "Registering assembly, key: %S", pAttrs->pwzKey); | ||
560 | |||
561 | // extract path from GAC | ||
562 | if (pAttrs->iAttributes & aaPathFromGAC) | ||
563 | { | ||
564 | hr = GetAssemblyPathFromGAC(pAttrs->pwzAssemblyName, &pAttrs->pwzDllPath); | ||
565 | if (S_FALSE == hr) | ||
566 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
567 | ExitOnFailure(hr, "Failed to get path for assembly from GAC"); | ||
568 | |||
569 | // log | ||
570 | WcaLog(LOGMSG_VERBOSE, "Assembly path extracted from GAC, key: %S, path: '%S'", pAttrs->pwzKey, pAttrs->pwzDllPath); | ||
571 | } | ||
572 | |||
573 | // .net assembly | ||
574 | if (pAttrs->iAttributes & aaDotNetAssembly) | ||
575 | { | ||
576 | hr = RegisterDotNetAssembly(pAttrs); | ||
577 | ExitOnFailure(hr, "Failed to register .NET assembly"); | ||
578 | } | ||
579 | |||
580 | // native assembly | ||
581 | else | ||
582 | { | ||
583 | hr = RegisterNativeAssembly(pAttrs); | ||
584 | ExitOnFailure(hr, "Failed to register native assembly"); | ||
585 | } | ||
586 | |||
587 | // configure components | ||
588 | if (pAttrs->pCompList) | ||
589 | { | ||
590 | hr = ConfigureComponents(pAttrs->pwzPartID, pAttrs->pwzAppID, pAttrs->pCompList, TRUE, FALSE); | ||
591 | ExitOnFailure(hr, "Failed to configure components"); | ||
592 | } | ||
593 | |||
594 | hr = S_OK; | ||
595 | |||
596 | LExit: | ||
597 | return hr; | ||
598 | } | ||
599 | |||
600 | static HRESULT UnregisterAssembly( | ||
601 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
602 | ) | ||
603 | { | ||
604 | HRESULT hr = S_OK; | ||
605 | |||
606 | long lChanges = 0; | ||
607 | |||
608 | ICatalogCollection* piColl = NULL; | ||
609 | ICatalogObject* piObj = NULL; | ||
610 | |||
611 | // progress message | ||
612 | hr = CpiActionDataMessage(1, (pAttrs->iAttributes & aaPathFromGAC) ? pAttrs->pwzAssemblyName : pAttrs->pwzDllPath); | ||
613 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
614 | |||
615 | if (S_FALSE == hr) | ||
616 | ExitFunction(); // aborted by user | ||
617 | |||
618 | // log | ||
619 | WcaLog(LOGMSG_VERBOSE, "Unregistering assembly, key: %S", pAttrs->pwzKey); | ||
620 | |||
621 | // extract path from GAC | ||
622 | if (pAttrs->iAttributes & aaPathFromGAC) | ||
623 | { | ||
624 | hr = GetAssemblyPathFromGAC(pAttrs->pwzAssemblyName, &pAttrs->pwzDllPath); | ||
625 | ExitOnFailure(hr, "Failed to get path for assembly from GAC"); | ||
626 | |||
627 | if (S_FALSE == hr) | ||
628 | { | ||
629 | WcaLog(LOGMSG_VERBOSE, "Unable to locate assembly in GAC, assembly will not be unregistered from COM+, key: %S", pAttrs->pwzKey); | ||
630 | ExitFunction1(hr = S_OK); | ||
631 | } | ||
632 | |||
633 | // log | ||
634 | WcaLog(LOGMSG_VERBOSE, "Assembly path extracted from GAC, key: %S, path: '%S'", pAttrs->pwzKey, pAttrs->pwzDllPath); | ||
635 | } | ||
636 | |||
637 | // .NET assembly | ||
638 | if (pAttrs->iAttributes & aaDotNetAssembly) | ||
639 | { | ||
640 | if (pAttrs->pwzAppID && *pAttrs->pwzAppID) | ||
641 | { | ||
642 | // When unregistering a .net assembly using the RegistrationHelper class, and the application is | ||
643 | // left empty after all components in the assembly are removed, the RegistrationHelper class also | ||
644 | // attempts to remove the application for some reason. However, it does not handle the situation | ||
645 | // when the application has its deleteable property set to false, and will simply fail if this is | ||
646 | // the case. This is the reason we are clearing the deleatable property of the application here. | ||
647 | // | ||
648 | // TODO: handle rollbacks | ||
649 | |||
650 | // get applications collection | ||
651 | hr = CpiGetApplicationsCollection(pAttrs->pwzPartID, &piColl); | ||
652 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
653 | |||
654 | if (S_FALSE == hr) | ||
655 | { | ||
656 | // applications collection not found | ||
657 | WcaLog(LOGMSG_VERBOSE, "Unable to retrieve applications collection, nothing to delete, key: %S", pAttrs->pwzKey); | ||
658 | ExitFunction1(hr = S_OK); | ||
659 | } | ||
660 | |||
661 | // find application object | ||
662 | hr = CpiFindCollectionObjectByStringKey(piColl, pAttrs->pwzAppID, &piObj); | ||
663 | ExitOnFailure(hr, "Failed to find application object"); | ||
664 | |||
665 | if (S_FALSE == hr) | ||
666 | { | ||
667 | // application not found | ||
668 | WcaLog(LOGMSG_VERBOSE, "Unable to find application object, nothing to delete, key: %S", pAttrs->pwzKey); | ||
669 | ExitFunction1(hr = S_OK); | ||
670 | } | ||
671 | |||
672 | // reset deleteable property | ||
673 | hr = CpiResetObjectProperty(piColl, piObj, L"Deleteable"); | ||
674 | ExitOnFailure(hr, "Failed to reset deleteable property"); | ||
675 | } | ||
676 | |||
677 | // unregister assembly | ||
678 | hr = UnregisterDotNetAssembly(pAttrs); | ||
679 | ExitOnFailure(hr, "Failed to unregister .NET assembly"); | ||
680 | } | ||
681 | |||
682 | // native assembly | ||
683 | else | ||
684 | { | ||
685 | // get components collection | ||
686 | hr = CpiGetComponentsCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, &piColl); | ||
687 | ExitOnFailure(hr, "Failed to get components collection"); | ||
688 | |||
689 | if (S_FALSE == hr) | ||
690 | { | ||
691 | // components collection not found | ||
692 | WcaLog(LOGMSG_VERBOSE, "Unable to retrieve components collection, nothing to delete, key: %S", pAttrs->pwzKey); | ||
693 | ExitFunction1(hr = S_OK); | ||
694 | } | ||
695 | |||
696 | // remove components | ||
697 | hr = RemoveComponents(piColl, pAttrs->pCompList); | ||
698 | ExitOnFailure(hr, "Failed to get remove components"); | ||
699 | |||
700 | // save changes | ||
701 | hr = piColl->SaveChanges(&lChanges); | ||
702 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
703 | CpiLogCatalogErrorInfo(); | ||
704 | ExitOnFailure(hr, "Failed to save changes"); | ||
705 | } | ||
706 | |||
707 | hr = S_OK; | ||
708 | |||
709 | LExit: | ||
710 | // clean up | ||
711 | ReleaseObject(piColl); | ||
712 | ReleaseObject(piObj); | ||
713 | |||
714 | return hr; | ||
715 | } | ||
716 | |||
717 | static void InitAssemblyExec() | ||
718 | { | ||
719 | gpiRegHlp = NULL; | ||
720 | gpAssemblyCache = NULL; | ||
721 | ghMscoree = NULL; | ||
722 | ghFusion = NULL; | ||
723 | } | ||
724 | |||
725 | static void UninitAssemblyExec() | ||
726 | { | ||
727 | ReleaseObject(gpiRegHlp); | ||
728 | ReleaseObject(gpAssemblyCache); | ||
729 | if (ghFusion) | ||
730 | ::FreeLibrary(ghFusion); | ||
731 | if (ghMscoree) | ||
732 | ::FreeLibrary(ghMscoree); | ||
733 | } | ||
734 | |||
735 | static HRESULT GetRegistrationHelper( | ||
736 | IDispatch** ppiRegHlp | ||
737 | ) | ||
738 | { | ||
739 | HRESULT hr = S_OK; | ||
740 | |||
741 | if (!gpiRegHlp) | ||
742 | { | ||
743 | // create registration helper object | ||
744 | hr = ::CoCreateInstance(CLSID_RegistrationHelper, NULL, CLSCTX_ALL, IID_IDispatch, (void**)&gpiRegHlp); | ||
745 | ExitOnFailure(hr, "Failed to create registration helper object"); | ||
746 | } | ||
747 | |||
748 | gpiRegHlp->AddRef(); | ||
749 | *ppiRegHlp = gpiRegHlp; | ||
750 | |||
751 | hr = S_OK; | ||
752 | |||
753 | LExit: | ||
754 | return hr; | ||
755 | } | ||
756 | |||
757 | static HRESULT GetAssemblyCacheObject( | ||
758 | IAssemblyCache** ppAssemblyCache | ||
759 | ) | ||
760 | { | ||
761 | HRESULT hr = S_OK; | ||
762 | |||
763 | if (!gpAssemblyCache) | ||
764 | { | ||
765 | // mscoree.dll | ||
766 | if (!ghMscoree) | ||
767 | { | ||
768 | // load mscoree.dll | ||
769 | ghMscoree = ::LoadLibraryW(L"mscoree.dll"); | ||
770 | ExitOnNull(ghMscoree, hr, E_FAIL, "Failed to load mscoree.dll"); | ||
771 | } | ||
772 | |||
773 | // fusion.dll | ||
774 | if (!ghFusion) | ||
775 | { | ||
776 | // get LoadLibraryShim function address | ||
777 | LoadLibraryShimFunc pfnLoadLibraryShim = (LoadLibraryShimFunc)::GetProcAddress(ghMscoree, "LoadLibraryShim"); | ||
778 | ExitOnNull(pfnLoadLibraryShim, hr, HRESULT_FROM_WIN32(::GetLastError()), "Failed get address for LoadLibraryShim() function"); | ||
779 | |||
780 | // load fusion.dll | ||
781 | hr = pfnLoadLibraryShim(L"fusion.dll", NULL, NULL, &ghFusion); | ||
782 | ExitOnFailure(hr, "Failed to load fusion.dll"); | ||
783 | } | ||
784 | |||
785 | // get CreateAssemblyCache function address | ||
786 | CreateAssemblyCacheFunc pfnCreateAssemblyCache = (CreateAssemblyCacheFunc)::GetProcAddress(ghFusion, "CreateAssemblyCache"); | ||
787 | ExitOnNull(pfnCreateAssemblyCache, hr, HRESULT_FROM_WIN32(::GetLastError()), "Failed get address for CreateAssemblyCache() function"); | ||
788 | |||
789 | // create AssemblyCache object | ||
790 | hr = pfnCreateAssemblyCache(&gpAssemblyCache, 0); | ||
791 | ExitOnFailure(hr, "Failed to create AssemblyCache object"); | ||
792 | } | ||
793 | |||
794 | gpAssemblyCache->AddRef(); | ||
795 | *ppAssemblyCache = gpAssemblyCache; | ||
796 | |||
797 | hr = S_OK; | ||
798 | |||
799 | LExit: | ||
800 | return hr; | ||
801 | } | ||
802 | |||
803 | static HRESULT GetAssemblyPathFromGAC( | ||
804 | LPCWSTR pwzAssemblyName, | ||
805 | LPWSTR* ppwzAssemblyPath | ||
806 | ) | ||
807 | { | ||
808 | HRESULT hr = S_OK; | ||
809 | |||
810 | IAssemblyCache* pAssemblyCache = NULL; | ||
811 | |||
812 | ASSEMBLY_INFO assemblyInfo; | ||
813 | WCHAR wzPathBuf[MAX_PATH]; | ||
814 | |||
815 | ::ZeroMemory(&assemblyInfo, sizeof(ASSEMBLY_INFO)); | ||
816 | ::ZeroMemory(wzPathBuf, countof(wzPathBuf)); | ||
817 | |||
818 | // get AssemblyCache object | ||
819 | hr = GetAssemblyCacheObject(&pAssemblyCache); | ||
820 | ExitOnFailure(hr, "Failed to get AssemblyCache object"); | ||
821 | |||
822 | // get assembly info | ||
823 | assemblyInfo.cbAssemblyInfo = sizeof(ASSEMBLY_INFO); | ||
824 | assemblyInfo.pszCurrentAssemblyPathBuf = wzPathBuf; | ||
825 | assemblyInfo.cchBuf = countof(wzPathBuf); | ||
826 | |||
827 | hr = pAssemblyCache->QueryAssemblyInfo(0, pwzAssemblyName, &assemblyInfo); | ||
828 | if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) | ||
829 | ExitFunction1(hr = S_FALSE); | ||
830 | ExitOnFailure(hr, "Failed to get assembly info"); | ||
831 | |||
832 | // copy assembly path | ||
833 | hr = StrAllocString(ppwzAssemblyPath, wzPathBuf, 0); | ||
834 | ExitOnFailure(hr, "Failed to copy assembly path"); | ||
835 | |||
836 | hr = S_OK; | ||
837 | |||
838 | LExit: | ||
839 | // clean up | ||
840 | ReleaseObject(pAssemblyCache); | ||
841 | |||
842 | return hr; | ||
843 | } | ||
844 | |||
845 | static HRESULT RegisterDotNetAssembly( | ||
846 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
847 | ) | ||
848 | { | ||
849 | HRESULT hr = S_OK; | ||
850 | |||
851 | IDispatch* piRegHlp = NULL; | ||
852 | |||
853 | DISPID dispid; | ||
854 | BSTR bstrMember = NULL; | ||
855 | |||
856 | long lInstallationFlags = 0; | ||
857 | |||
858 | VARIANTARG rgvarg[5]; | ||
859 | DISPPARAMS dispparams; | ||
860 | EXCEPINFO excepInfo; | ||
861 | |||
862 | BSTR bstrPartName = NULL; | ||
863 | BSTR bstrAppName = NULL; | ||
864 | BSTR bstrDllPath = NULL; | ||
865 | BSTR bstrTlbPath = NULL; | ||
866 | |||
867 | ::ZeroMemory(rgvarg, sizeof(rgvarg)); | ||
868 | ::ZeroMemory(&dispparams, sizeof(dispparams)); | ||
869 | ::ZeroMemory(&excepInfo, sizeof(excepInfo)); | ||
870 | |||
871 | bstrMember = ::SysAllocString(L"InstallAssembly_2"); | ||
872 | ExitOnNull(bstrMember, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for method name"); | ||
873 | |||
874 | // create BSTRs for parameters | ||
875 | if (pAttrs->pwzPartID && *pAttrs->pwzPartID) | ||
876 | { | ||
877 | bstrPartName = ::SysAllocString(pAttrs->pwzPartID); | ||
878 | ExitOnNull(bstrPartName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for partition id"); | ||
879 | } | ||
880 | |||
881 | if (pAttrs->pwzAppID && *pAttrs->pwzAppID) | ||
882 | { | ||
883 | bstrAppName = ::SysAllocString(pAttrs->pwzAppID); | ||
884 | ExitOnNull(bstrAppName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for application id"); | ||
885 | } | ||
886 | |||
887 | bstrDllPath = ::SysAllocString(pAttrs->pwzDllPath); | ||
888 | ExitOnNull(bstrDllPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for dll path"); | ||
889 | |||
890 | if (pAttrs->pwzTlbPath && *pAttrs->pwzTlbPath) | ||
891 | { | ||
892 | bstrTlbPath = ::SysAllocString(pAttrs->pwzTlbPath); | ||
893 | ExitOnNull(bstrTlbPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for tlb path"); | ||
894 | } | ||
895 | |||
896 | // get registration helper object | ||
897 | hr = GetRegistrationHelper(&piRegHlp); | ||
898 | ExitOnFailure(hr, "Failed to get registration helper object"); | ||
899 | |||
900 | // get dispatch id of InstallAssembly() method | ||
901 | hr = piRegHlp->GetIDsOfNames(IID_NULL, &bstrMember, 1, LOCALE_USER_DEFAULT, &dispid); | ||
902 | ExitOnFailure(hr, "Failed to get dispatch id of InstallAssembly() method"); | ||
903 | |||
904 | // set installation flags | ||
905 | lInstallationFlags = ifExpectExistingTypeLib; | ||
906 | |||
907 | if (!bstrAppName) | ||
908 | lInstallationFlags |= ifFindOrCreateTargetApplication; | ||
909 | |||
910 | // invoke InstallAssembly() method | ||
911 | rgvarg[0].vt = VT_I4; | ||
912 | rgvarg[0].lVal = lInstallationFlags; | ||
913 | rgvarg[1].vt = VT_BYREF|VT_BSTR; | ||
914 | rgvarg[1].pbstrVal = &bstrTlbPath; | ||
915 | rgvarg[2].vt = VT_BSTR; | ||
916 | rgvarg[2].bstrVal = bstrPartName; | ||
917 | rgvarg[3].vt = VT_BYREF|VT_BSTR; | ||
918 | rgvarg[3].pbstrVal = &bstrAppName; | ||
919 | rgvarg[4].vt = VT_BSTR; | ||
920 | rgvarg[4].bstrVal = bstrDllPath; | ||
921 | dispparams.rgvarg = rgvarg; | ||
922 | dispparams.cArgs = 5; | ||
923 | dispparams.cNamedArgs = 0; | ||
924 | |||
925 | hr = piRegHlp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, NULL, &excepInfo, NULL); | ||
926 | if (DISP_E_EXCEPTION == hr) | ||
927 | { | ||
928 | // log exception information | ||
929 | if (!excepInfo.pfnDeferredFillIn || (excepInfo.pfnDeferredFillIn && SUCCEEDED(excepInfo.pfnDeferredFillIn(&excepInfo)))) | ||
930 | { | ||
931 | WcaLog(LOGMSG_STANDARD, "ExceptionInfo: Code='%hu', Source='%S', Description='%S', HelpFile='%S', HelpContext='%u'", | ||
932 | excepInfo.wCode, excepInfo.bstrSource, | ||
933 | excepInfo.bstrDescription ? excepInfo.bstrDescription : L"", | ||
934 | excepInfo.bstrHelpFile ? excepInfo.bstrHelpFile : L"", | ||
935 | excepInfo.dwHelpContext); | ||
936 | } | ||
937 | } | ||
938 | ExitOnFailure(hr, "Failed to invoke RegistrationHelper.InstallAssembly() method"); | ||
939 | |||
940 | hr = S_OK; | ||
941 | |||
942 | LExit: | ||
943 | // clean up | ||
944 | ReleaseObject(piRegHlp); | ||
945 | |||
946 | ReleaseBSTR(bstrMember); | ||
947 | |||
948 | ReleaseBSTR(excepInfo.bstrSource); | ||
949 | ReleaseBSTR(excepInfo.bstrDescription); | ||
950 | ReleaseBSTR(excepInfo.bstrHelpFile); | ||
951 | |||
952 | ReleaseBSTR(bstrPartName); | ||
953 | ReleaseBSTR(bstrAppName); | ||
954 | ReleaseBSTR(bstrDllPath); | ||
955 | ReleaseBSTR(bstrTlbPath); | ||
956 | |||
957 | return hr; | ||
958 | } | ||
959 | |||
960 | static HRESULT RegisterNativeAssembly( | ||
961 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
962 | ) | ||
963 | { | ||
964 | HRESULT hr = S_OK; | ||
965 | |||
966 | ICOMAdminCatalog* piCatalog = NULL; | ||
967 | ICOMAdminCatalog2* piCatalog2 = NULL; | ||
968 | BSTR bstrGlobPartID = NULL; | ||
969 | |||
970 | BSTR bstrPartID = NULL; | ||
971 | BSTR bstrAppID = NULL; | ||
972 | BSTR bstrDllPath = NULL; | ||
973 | BSTR bstrTlbPath = NULL; | ||
974 | BSTR bstrPSDllPath = NULL; | ||
975 | |||
976 | // create BSTRs for parameters | ||
977 | if (pAttrs->pwzPartID && *pAttrs->pwzPartID) | ||
978 | { | ||
979 | bstrPartID = ::SysAllocString(pAttrs->pwzPartID); | ||
980 | ExitOnNull(bstrPartID, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for partition id"); | ||
981 | } | ||
982 | |||
983 | bstrAppID = ::SysAllocString(pAttrs->pwzAppID); | ||
984 | ExitOnNull(bstrAppID, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for application id"); | ||
985 | |||
986 | bstrDllPath = ::SysAllocString(pAttrs->pwzDllPath); | ||
987 | ExitOnNull(bstrDllPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for dll path"); | ||
988 | |||
989 | bstrTlbPath = ::SysAllocString(pAttrs->pwzTlbPath ? pAttrs->pwzTlbPath : L""); | ||
990 | ExitOnNull(bstrTlbPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for tlb path"); | ||
991 | |||
992 | bstrPSDllPath = ::SysAllocString(pAttrs->pwzPSDllPath ? pAttrs->pwzPSDllPath : L""); | ||
993 | ExitOnNull(bstrPSDllPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for tlb path"); | ||
994 | |||
995 | // get catalog | ||
996 | hr = CpiGetAdminCatalog(&piCatalog); | ||
997 | ExitOnFailure(hr, "Failed to get COM+ admin catalog"); | ||
998 | |||
999 | // get ICOMAdminCatalog2 interface | ||
1000 | hr = piCatalog->QueryInterface(IID_ICOMAdminCatalog2, (void**)&piCatalog2); | ||
1001 | |||
1002 | // COM+ 1.5 or later | ||
1003 | if (E_NOINTERFACE != hr) | ||
1004 | { | ||
1005 | ExitOnFailure(hr, "Failed to get IID_ICOMAdminCatalog2 interface"); | ||
1006 | |||
1007 | // partition id | ||
1008 | if (!bstrPartID) | ||
1009 | { | ||
1010 | // get global partition id | ||
1011 | hr = piCatalog2->get_GlobalPartitionID(&bstrGlobPartID); | ||
1012 | ExitOnFailure(hr, "Failed to get global partition id"); | ||
1013 | } | ||
1014 | |||
1015 | // set current partition | ||
1016 | hr = piCatalog2->put_CurrentPartition(bstrPartID ? bstrPartID : bstrGlobPartID); | ||
1017 | ExitOnFailure(hr, "Failed to set current partition"); | ||
1018 | } | ||
1019 | |||
1020 | // COM+ pre 1.5 | ||
1021 | else | ||
1022 | { | ||
1023 | // this version of COM+ does not support partitions, make sure a partition was not specified | ||
1024 | if (bstrPartID) | ||
1025 | ExitOnFailure(hr = E_FAIL, "Partitions are not supported by this version of COM+"); | ||
1026 | } | ||
1027 | |||
1028 | // install event classes | ||
1029 | if (pAttrs->iAttributes & aaEventClass) | ||
1030 | { | ||
1031 | hr = piCatalog->InstallEventClass(bstrAppID, bstrDllPath, bstrTlbPath, bstrPSDllPath); | ||
1032 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
1033 | CpiLogCatalogErrorInfo(); | ||
1034 | ExitOnFailure(hr, "Failed to install event classes"); | ||
1035 | } | ||
1036 | |||
1037 | // install components | ||
1038 | else | ||
1039 | { | ||
1040 | hr = piCatalog->InstallComponent(bstrAppID, bstrDllPath, bstrTlbPath, bstrPSDllPath); | ||
1041 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
1042 | CpiLogCatalogErrorInfo(); | ||
1043 | ExitOnFailure(hr, "Failed to install components"); | ||
1044 | } | ||
1045 | |||
1046 | hr = S_OK; | ||
1047 | |||
1048 | LExit: | ||
1049 | // clean up | ||
1050 | ReleaseObject(piCatalog); | ||
1051 | ReleaseObject(piCatalog2); | ||
1052 | ReleaseBSTR(bstrGlobPartID); | ||
1053 | |||
1054 | ReleaseBSTR(bstrPartID); | ||
1055 | ReleaseBSTR(bstrAppID); | ||
1056 | ReleaseBSTR(bstrDllPath); | ||
1057 | ReleaseBSTR(bstrTlbPath); | ||
1058 | ReleaseBSTR(bstrPSDllPath); | ||
1059 | |||
1060 | return hr; | ||
1061 | } | ||
1062 | |||
1063 | static HRESULT UnregisterDotNetAssembly( | ||
1064 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
1065 | ) | ||
1066 | { | ||
1067 | HRESULT hr = S_OK; | ||
1068 | |||
1069 | IDispatch* piRegHlp = NULL; | ||
1070 | |||
1071 | DISPID dispid; | ||
1072 | BSTR bstrMember = NULL; | ||
1073 | |||
1074 | VARIANTARG rgvarg[3]; | ||
1075 | DISPPARAMS dispparams; | ||
1076 | EXCEPINFO excepInfo; | ||
1077 | |||
1078 | BSTR bstrPartName = NULL; | ||
1079 | BSTR bstrAppName = NULL; | ||
1080 | BSTR bstrDllPath = NULL; | ||
1081 | |||
1082 | ::ZeroMemory(rgvarg, sizeof(rgvarg)); | ||
1083 | ::ZeroMemory(&dispparams, sizeof(dispparams)); | ||
1084 | ::ZeroMemory(&excepInfo, sizeof(excepInfo)); | ||
1085 | |||
1086 | bstrMember = ::SysAllocString(L"UninstallAssembly_2"); | ||
1087 | ExitOnNull(bstrMember, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for method name"); | ||
1088 | |||
1089 | // create BSTRs for parameters | ||
1090 | if (pAttrs->pwzPartID && *pAttrs->pwzPartID) | ||
1091 | { | ||
1092 | bstrPartName = ::SysAllocString(pAttrs->pwzPartID); | ||
1093 | ExitOnNull(bstrPartName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for partition id"); | ||
1094 | } | ||
1095 | |||
1096 | bstrAppName = ::SysAllocString(pAttrs->pwzAppID); | ||
1097 | ExitOnNull(bstrAppName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for application id"); | ||
1098 | |||
1099 | bstrDllPath = ::SysAllocString(pAttrs->pwzDllPath); | ||
1100 | ExitOnNull(bstrDllPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for dll path"); | ||
1101 | |||
1102 | // get registration helper object | ||
1103 | hr = GetRegistrationHelper(&piRegHlp); | ||
1104 | ExitOnFailure(hr, "Failed to get registration helper object"); | ||
1105 | |||
1106 | // get dispatch id of UninstallAssembly() method | ||
1107 | hr = piRegHlp->GetIDsOfNames(IID_NULL, &bstrMember, 1, LOCALE_USER_DEFAULT, &dispid); | ||
1108 | ExitOnFailure(hr, "Failed to get dispatch id of UninstallAssembly() method"); | ||
1109 | |||
1110 | // invoke UninstallAssembly() method | ||
1111 | rgvarg[0].vt = VT_BSTR; | ||
1112 | rgvarg[0].bstrVal = bstrPartName; | ||
1113 | rgvarg[1].vt = VT_BSTR; | ||
1114 | rgvarg[1].bstrVal = bstrAppName; | ||
1115 | rgvarg[2].vt = VT_BSTR; | ||
1116 | rgvarg[2].bstrVal = bstrDllPath; | ||
1117 | dispparams.rgvarg = rgvarg; | ||
1118 | dispparams.cArgs = 3; | ||
1119 | dispparams.cNamedArgs = 0; | ||
1120 | |||
1121 | hr = piRegHlp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, NULL, &excepInfo, NULL); | ||
1122 | if (DISP_E_EXCEPTION == hr) | ||
1123 | { | ||
1124 | // log exception information | ||
1125 | if (!excepInfo.pfnDeferredFillIn || (excepInfo.pfnDeferredFillIn && SUCCEEDED(excepInfo.pfnDeferredFillIn(&excepInfo)))) | ||
1126 | { | ||
1127 | WcaLog(LOGMSG_STANDARD, "ExceptionInfo: Code='%hu', Source='%S', Description='%S', HelpFile='%S', HelpContext='%u'", | ||
1128 | excepInfo.wCode, excepInfo.bstrSource, | ||
1129 | excepInfo.bstrDescription ? excepInfo.bstrDescription : L"", | ||
1130 | excepInfo.bstrHelpFile ? excepInfo.bstrHelpFile : L"", | ||
1131 | excepInfo.dwHelpContext); | ||
1132 | } | ||
1133 | } | ||
1134 | ExitOnFailure(hr, "Failed to invoke RegistrationHelper.UninstallAssembly() method"); | ||
1135 | |||
1136 | hr = S_OK; | ||
1137 | |||
1138 | LExit: | ||
1139 | // clean up | ||
1140 | ReleaseObject(piRegHlp); | ||
1141 | |||
1142 | ReleaseBSTR(bstrMember); | ||
1143 | |||
1144 | ReleaseBSTR(excepInfo.bstrSource); | ||
1145 | ReleaseBSTR(excepInfo.bstrDescription); | ||
1146 | ReleaseBSTR(excepInfo.bstrHelpFile); | ||
1147 | |||
1148 | ReleaseBSTR(bstrPartName); | ||
1149 | ReleaseBSTR(bstrAppName); | ||
1150 | ReleaseBSTR(bstrDllPath); | ||
1151 | |||
1152 | return hr; | ||
1153 | } | ||
1154 | |||
1155 | static HRESULT RemoveComponents( | ||
1156 | ICatalogCollection* piCompColl, | ||
1157 | CPI_COMPONENT* pCompList | ||
1158 | ) | ||
1159 | { | ||
1160 | HRESULT hr = S_OK; | ||
1161 | |||
1162 | for (CPI_COMPONENT* pItm = pCompList; pItm; pItm = pItm->pNext) | ||
1163 | { | ||
1164 | // remove | ||
1165 | hr = CpiRemoveCollectionObject(piCompColl, pItm->wzCLSID, NULL, FALSE); | ||
1166 | ExitOnFailure(hr, "Failed to remove component"); | ||
1167 | |||
1168 | if (S_FALSE == hr) | ||
1169 | WcaLog(LOGMSG_VERBOSE, "Component not found, nothing to delete, key: %S", pItm->wzCLSID); | ||
1170 | } | ||
1171 | |||
1172 | hr = S_OK; | ||
1173 | |||
1174 | LExit: | ||
1175 | return hr; | ||
1176 | } | ||
1177 | |||
1178 | static HRESULT ReadAssemblyAttributes( | ||
1179 | LPWSTR* ppwzData, | ||
1180 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
1181 | ) | ||
1182 | { | ||
1183 | HRESULT hr = S_OK; | ||
1184 | |||
1185 | // read attributes | ||
1186 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); | ||
1187 | ExitOnFailure(hr, "Failed to read action type"); | ||
1188 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); | ||
1189 | ExitOnFailure(hr, "Failed to read action cost"); | ||
1190 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); | ||
1191 | ExitOnFailure(hr, "Failed to read key"); | ||
1192 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAssemblyName); | ||
1193 | ExitOnFailure(hr, "Failed to read assembly name"); | ||
1194 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzDllPath); | ||
1195 | ExitOnFailure(hr, "Failed to read dll path"); | ||
1196 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzTlbPath); | ||
1197 | ExitOnFailure(hr, "Failed to read tlb path"); | ||
1198 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPSDllPath); | ||
1199 | ExitOnFailure(hr, "Failed to read proxy-stub dll path"); | ||
1200 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iAttributes); | ||
1201 | ExitOnFailure(hr, "Failed to read attributes"); | ||
1202 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAppID); | ||
1203 | ExitOnFailure(hr, "Failed to read application id"); | ||
1204 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID); | ||
1205 | ExitOnFailure(hr, "Failed to read partition id"); | ||
1206 | |||
1207 | // free existing component list | ||
1208 | if (pAttrs->pCompList) | ||
1209 | { | ||
1210 | FreeComponentList(pAttrs->pCompList); | ||
1211 | pAttrs->pCompList = NULL; | ||
1212 | } | ||
1213 | |||
1214 | // read components | ||
1215 | hr = ReadComponentList(ppwzData, &pAttrs->pCompList); | ||
1216 | ExitOnFailure(hr, "Failed to read components"); | ||
1217 | |||
1218 | hr = S_OK; | ||
1219 | |||
1220 | LExit: | ||
1221 | return hr; | ||
1222 | } | ||
1223 | |||
1224 | static void FreeAssemblyAttributes( | ||
1225 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
1226 | ) | ||
1227 | { | ||
1228 | ReleaseStr(pAttrs->pwzKey); | ||
1229 | ReleaseStr(pAttrs->pwzAssemblyName); | ||
1230 | ReleaseStr(pAttrs->pwzDllPath); | ||
1231 | ReleaseStr(pAttrs->pwzTlbPath); | ||
1232 | ReleaseStr(pAttrs->pwzPSDllPath); | ||
1233 | ReleaseStr(pAttrs->pwzAppID); | ||
1234 | ReleaseStr(pAttrs->pwzPartID); | ||
1235 | |||
1236 | if (pAttrs->pCompList) | ||
1237 | FreeComponentList(pAttrs->pCompList); | ||
1238 | } | ||
1239 | |||
1240 | static HRESULT ReadRoleAssignmentsAttributes( | ||
1241 | LPWSTR* ppwzData, | ||
1242 | CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs | ||
1243 | ) | ||
1244 | { | ||
1245 | HRESULT hr = S_OK; | ||
1246 | |||
1247 | // read attributes | ||
1248 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); | ||
1249 | ExitOnFailure(hr, "Failed to read action type"); | ||
1250 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); | ||
1251 | ExitOnFailure(hr, "Failed to read action cost"); | ||
1252 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); | ||
1253 | ExitOnFailure(hr, "Failed to read key"); | ||
1254 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iRoleCount); | ||
1255 | ExitOnFailure(hr, "Failed to read role assignments count"); | ||
1256 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAppID); | ||
1257 | ExitOnFailure(hr, "Failed to read application id"); | ||
1258 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID); | ||
1259 | ExitOnFailure(hr, "Failed to read partition id"); | ||
1260 | |||
1261 | // free existing component list | ||
1262 | if (pAttrs->pCompList) | ||
1263 | { | ||
1264 | FreeComponentList(pAttrs->pCompList); | ||
1265 | pAttrs->pCompList = NULL; | ||
1266 | } | ||
1267 | |||
1268 | // read components | ||
1269 | hr = ReadComponentList(ppwzData, &pAttrs->pCompList); | ||
1270 | ExitOnFailure(hr, "Failed to read components"); | ||
1271 | |||
1272 | hr = S_OK; | ||
1273 | |||
1274 | LExit: | ||
1275 | return hr; | ||
1276 | } | ||
1277 | |||
1278 | static void FreeRoleAssignmentsAttributes( | ||
1279 | CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs | ||
1280 | ) | ||
1281 | { | ||
1282 | ReleaseStr(pAttrs->pwzKey); | ||
1283 | ReleaseStr(pAttrs->pwzAppID); | ||
1284 | ReleaseStr(pAttrs->pwzPartID); | ||
1285 | |||
1286 | if (pAttrs->pCompList) | ||
1287 | FreeComponentList(pAttrs->pCompList); | ||
1288 | } | ||
1289 | |||
1290 | |||
1291 | static HRESULT ConfigureComponents( | ||
1292 | LPCWSTR pwzPartID, | ||
1293 | LPCWSTR pwzAppID, | ||
1294 | CPI_COMPONENT* pCompList, | ||
1295 | BOOL fCreate, | ||
1296 | BOOL fProgress | ||
1297 | ) | ||
1298 | { | ||
1299 | HRESULT hr = S_OK; | ||
1300 | |||
1301 | ICatalogCollection* piCompColl = NULL; | ||
1302 | ICatalogObject* piCompObj = NULL; | ||
1303 | |||
1304 | long lChanges = 0; | ||
1305 | |||
1306 | // get components collection | ||
1307 | hr = CpiGetComponentsCollection(pwzPartID, pwzAppID, &piCompColl); | ||
1308 | if (S_FALSE == hr) | ||
1309 | if (fCreate) | ||
1310 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
1311 | else | ||
1312 | ExitFunction1(hr = S_OK); | ||
1313 | ExitOnFailure(hr, "Failed to get components collection"); | ||
1314 | |||
1315 | // read components | ||
1316 | for (CPI_COMPONENT* pItm = pCompList; pItm; pItm = pItm->pNext) | ||
1317 | { | ||
1318 | // progress message | ||
1319 | if (fProgress) | ||
1320 | { | ||
1321 | hr = CpiActionDataMessage(1, pItm->wzCLSID); | ||
1322 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
1323 | |||
1324 | if (S_FALSE == hr) | ||
1325 | ExitFunction(); // aborted by user | ||
1326 | } | ||
1327 | |||
1328 | // find component | ||
1329 | hr = CpiFindCollectionObjectByStringKey(piCompColl, pItm->wzCLSID, &piCompObj); | ||
1330 | if (S_FALSE == hr) | ||
1331 | if (fCreate) | ||
1332 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
1333 | else | ||
1334 | continue; | ||
1335 | ExitOnFailure(hr, "Failed to find component object"); | ||
1336 | |||
1337 | // properties | ||
1338 | hr = CpiPutCollectionObjectValues(piCompObj, pItm->pPropertyList); | ||
1339 | ExitOnFailure(hr, "Failed to write properties"); | ||
1340 | |||
1341 | // read roles | ||
1342 | if (pItm->pRoleAssignmentList) | ||
1343 | { | ||
1344 | hr = ConfigureRoleAssignments(L"RolesForComponent", piCompColl, piCompObj, pItm->pRoleAssignmentList, fCreate); | ||
1345 | ExitOnFailure(hr, "Failed to read roles"); | ||
1346 | } | ||
1347 | |||
1348 | // read interfaces | ||
1349 | if (pItm->pInterfaceList) | ||
1350 | { | ||
1351 | hr = ConfigureInterfaces(piCompColl, piCompObj, pItm->pInterfaceList, fCreate); | ||
1352 | ExitOnFailure(hr, "Failed to read interfaces"); | ||
1353 | } | ||
1354 | |||
1355 | // clean up | ||
1356 | ReleaseNullObject(piCompObj); | ||
1357 | } | ||
1358 | |||
1359 | // save changes | ||
1360 | hr = piCompColl->SaveChanges(&lChanges); | ||
1361 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
1362 | CpiLogCatalogErrorInfo(); | ||
1363 | ExitOnFailure(hr, "Failed to save changes"); | ||
1364 | |||
1365 | hr = S_OK; | ||
1366 | |||
1367 | LExit: | ||
1368 | // clean up | ||
1369 | ReleaseObject(piCompColl); | ||
1370 | ReleaseObject(piCompObj); | ||
1371 | |||
1372 | return hr; | ||
1373 | } | ||
1374 | |||
1375 | static HRESULT ConfigureInterfaces( | ||
1376 | ICatalogCollection* piCompColl, | ||
1377 | ICatalogObject* piCompObj, | ||
1378 | CPI_INTERFACE* pIntfList, | ||
1379 | BOOL fCreate | ||
1380 | ) | ||
1381 | { | ||
1382 | HRESULT hr = S_OK; | ||
1383 | |||
1384 | ICatalogCollection* piIntfColl = NULL; | ||
1385 | ICatalogObject* piIntfObj = NULL; | ||
1386 | |||
1387 | long lChanges = 0; | ||
1388 | |||
1389 | // get interfaces collection | ||
1390 | hr = CpiGetInterfacesCollection(piCompColl, piCompObj, &piIntfColl); | ||
1391 | if (S_FALSE == hr) | ||
1392 | if (fCreate) | ||
1393 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
1394 | else | ||
1395 | ExitFunction1(hr = S_OK); | ||
1396 | ExitOnFailure(hr, "Failed to get interfaces collection"); | ||
1397 | |||
1398 | // read interfaces | ||
1399 | for (CPI_INTERFACE* pItm = pIntfList; pItm; pItm = pItm->pNext) | ||
1400 | { | ||
1401 | // find interface | ||
1402 | hr = CpiFindCollectionObjectByStringKey(piIntfColl, pItm->wzIID, &piIntfObj); | ||
1403 | if (S_FALSE == hr) | ||
1404 | if (fCreate) | ||
1405 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
1406 | else | ||
1407 | continue; | ||
1408 | ExitOnFailure(hr, "Failed to find interface object"); | ||
1409 | |||
1410 | // properties | ||
1411 | hr = CpiPutCollectionObjectValues(piIntfObj, pItm->pPropertyList); | ||
1412 | ExitOnFailure(hr, "Failed to write properties"); | ||
1413 | |||
1414 | // read roles | ||
1415 | if (pItm->pRoleAssignmentList) | ||
1416 | { | ||
1417 | hr = ConfigureRoleAssignments(L"RolesForInterface", piIntfColl, piIntfObj, pItm->pRoleAssignmentList, fCreate); | ||
1418 | ExitOnFailure(hr, "Failed to read roles"); | ||
1419 | } | ||
1420 | |||
1421 | // read methods | ||
1422 | if (pItm->pMethodList) | ||
1423 | { | ||
1424 | hr = ConfigureMethods(piIntfColl, piIntfObj, pItm->pMethodList, fCreate); | ||
1425 | ExitOnFailure(hr, "Failed to read methods"); | ||
1426 | } | ||
1427 | |||
1428 | // clean up | ||
1429 | ReleaseNullObject(piIntfObj); | ||
1430 | } | ||
1431 | |||
1432 | // save changes | ||
1433 | hr = piIntfColl->SaveChanges(&lChanges); | ||
1434 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
1435 | CpiLogCatalogErrorInfo(); | ||
1436 | ExitOnFailure(hr, "Failed to save changes"); | ||
1437 | |||
1438 | hr = S_OK; | ||
1439 | |||
1440 | LExit: | ||
1441 | // clean up | ||
1442 | ReleaseObject(piIntfColl); | ||
1443 | ReleaseObject(piIntfObj); | ||
1444 | |||
1445 | return hr; | ||
1446 | } | ||
1447 | |||
1448 | static HRESULT ConfigureMethods( | ||
1449 | ICatalogCollection* piIntfColl, | ||
1450 | ICatalogObject* piIntfObj, | ||
1451 | CPI_METHOD* pMethList, | ||
1452 | BOOL fCreate | ||
1453 | ) | ||
1454 | { | ||
1455 | HRESULT hr = S_OK; | ||
1456 | |||
1457 | ICatalogCollection* piMethColl = NULL; | ||
1458 | ICatalogObject* piMethObj = NULL; | ||
1459 | |||
1460 | long lChanges = 0; | ||
1461 | |||
1462 | // get methods collection | ||
1463 | hr = CpiGetMethodsCollection(piIntfColl, piIntfObj, &piMethColl); | ||
1464 | if (S_FALSE == hr) | ||
1465 | if (fCreate) | ||
1466 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
1467 | else | ||
1468 | ExitFunction1(hr = S_OK); | ||
1469 | ExitOnFailure(hr, "Failed to get methods collection"); | ||
1470 | |||
1471 | // read methods | ||
1472 | for (CPI_METHOD* pItm = pMethList; pItm; pItm = pItm->pNext) | ||
1473 | { | ||
1474 | // find method | ||
1475 | if (*pItm->wzIndex) | ||
1476 | hr = CpiFindCollectionObjectByIntegerKey(piMethColl, _wtol(pItm->wzIndex), &piMethObj); | ||
1477 | else | ||
1478 | hr = CpiFindCollectionObjectByName(piMethColl, pItm->wzName, &piMethObj); | ||
1479 | |||
1480 | if (S_FALSE == hr) | ||
1481 | if (fCreate) | ||
1482 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
1483 | else | ||
1484 | continue; | ||
1485 | ExitOnFailure(hr, "Failed to find method object"); | ||
1486 | |||
1487 | // properties | ||
1488 | hr = CpiPutCollectionObjectValues(piMethObj, pItm->pPropertyList); | ||
1489 | ExitOnFailure(hr, "Failed to write properties"); | ||
1490 | |||
1491 | // read roles | ||
1492 | if (pItm->pRoleAssignmentList) | ||
1493 | { | ||
1494 | hr = ConfigureRoleAssignments(L"RolesForMethod", piMethColl, piMethObj, pItm->pRoleAssignmentList, fCreate); | ||
1495 | ExitOnFailure(hr, "Failed to read roles"); | ||
1496 | } | ||
1497 | |||
1498 | // clean up | ||
1499 | ReleaseNullObject(piMethObj); | ||
1500 | } | ||
1501 | |||
1502 | // save changes | ||
1503 | hr = piMethColl->SaveChanges(&lChanges); | ||
1504 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
1505 | CpiLogCatalogErrorInfo(); | ||
1506 | ExitOnFailure(hr, "Failed to save changes"); | ||
1507 | |||
1508 | hr = S_OK; | ||
1509 | |||
1510 | LExit: | ||
1511 | // clean up | ||
1512 | ReleaseObject(piMethColl); | ||
1513 | ReleaseObject(piMethObj); | ||
1514 | |||
1515 | return hr; | ||
1516 | } | ||
1517 | |||
1518 | static HRESULT ConfigureRoleAssignments( | ||
1519 | LPCWSTR pwzCollName, | ||
1520 | ICatalogCollection* piCompColl, | ||
1521 | ICatalogObject* piCompObj, | ||
1522 | CPI_ROLE_ASSIGNMENT* pRoleList, | ||
1523 | BOOL fCreate | ||
1524 | ) | ||
1525 | { | ||
1526 | HRESULT hr = S_OK; | ||
1527 | |||
1528 | ICatalogCollection* piRoleColl = NULL; | ||
1529 | ICatalogObject* piRoleObj = NULL; | ||
1530 | |||
1531 | long lChanges = 0; | ||
1532 | |||
1533 | // get roles collection | ||
1534 | hr = CpiGetCatalogCollection(piCompColl, piCompObj, pwzCollName, &piRoleColl); | ||
1535 | if (S_FALSE == hr) | ||
1536 | if (fCreate) | ||
1537 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
1538 | else | ||
1539 | ExitFunction1(hr = S_OK); | ||
1540 | ExitOnFailure(hr, "Failed to get role assignments collection"); | ||
1541 | |||
1542 | // read roles | ||
1543 | for (CPI_ROLE_ASSIGNMENT* pItm = pRoleList; pItm; pItm = pItm->pNext) | ||
1544 | { | ||
1545 | if (fCreate) | ||
1546 | { | ||
1547 | // find existing role | ||
1548 | hr = CpiFindCollectionObjectByName(piRoleColl, pItm->wzRoleName, NULL); | ||
1549 | ExitOnFailure(hr, "Failed to find role, key: %S", pItm->wzKey); | ||
1550 | |||
1551 | if (S_OK == hr) | ||
1552 | continue; // role already exists | ||
1553 | |||
1554 | // add object | ||
1555 | hr = CpiAddCollectionObject(piRoleColl, &piRoleObj); | ||
1556 | ExitOnFailure(hr, "Failed to add role assignment to collection"); | ||
1557 | |||
1558 | // role name | ||
1559 | hr = CpiPutCollectionObjectValue(piRoleObj, L"Name", pItm->wzRoleName); | ||
1560 | ExitOnFailure(hr, "Failed to set role name property, key: %S", pItm->wzKey); | ||
1561 | |||
1562 | // clean up | ||
1563 | ReleaseNullObject(piRoleObj); | ||
1564 | } | ||
1565 | else | ||
1566 | { | ||
1567 | // remove role | ||
1568 | hr = CpiRemoveCollectionObject(piRoleColl, NULL, pItm->wzRoleName, FALSE); | ||
1569 | ExitOnFailure(hr, "Failed to remove role, key: %S", pItm->wzKey); | ||
1570 | } | ||
1571 | } | ||
1572 | |||
1573 | // save changes | ||
1574 | hr = piRoleColl->SaveChanges(&lChanges); | ||
1575 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
1576 | CpiLogCatalogErrorInfo(); | ||
1577 | ExitOnFailure(hr, "Failed to save changes"); | ||
1578 | |||
1579 | hr = S_OK; | ||
1580 | |||
1581 | LExit: | ||
1582 | // clean up | ||
1583 | ReleaseObject(piRoleColl); | ||
1584 | ReleaseObject(piRoleObj); | ||
1585 | |||
1586 | return hr; | ||
1587 | } | ||
1588 | |||
1589 | static HRESULT ReadComponentList( | ||
1590 | LPWSTR* ppwzData, | ||
1591 | CPI_COMPONENT** ppCompList | ||
1592 | ) | ||
1593 | { | ||
1594 | HRESULT hr = S_OK; | ||
1595 | |||
1596 | LPWSTR pwzData = NULL; | ||
1597 | |||
1598 | CPI_COMPONENT* pItm = NULL; | ||
1599 | |||
1600 | int iCnt = 0; | ||
1601 | |||
1602 | // read count | ||
1603 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
1604 | ExitOnFailure(hr, "Failed to read count"); | ||
1605 | |||
1606 | // read components | ||
1607 | for (int i = 0; i < iCnt; i++) | ||
1608 | { | ||
1609 | pItm = (CPI_COMPONENT*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_COMPONENT)); | ||
1610 | if (!pItm) | ||
1611 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
1612 | |||
1613 | // read clsid | ||
1614 | hr = WcaReadStringFromCaData(ppwzData, &pwzData); | ||
1615 | ExitOnFailure(hr, "Failed to read clsid"); | ||
1616 | StringCchCopyW(pItm->wzCLSID, countof(pItm->wzCLSID), pwzData); | ||
1617 | |||
1618 | // read properties | ||
1619 | hr = CpiReadPropertyList(ppwzData, &pItm->pPropertyList); | ||
1620 | ExitOnFailure(hr, "Failed to read properties"); | ||
1621 | |||
1622 | // read role assignments | ||
1623 | hr = ReadRoleAssignmentList(ppwzData, &pItm->pRoleAssignmentList); | ||
1624 | ExitOnFailure(hr, "Failed to read role assignments"); | ||
1625 | |||
1626 | // read interfaces | ||
1627 | hr = ReadInterfaceList(ppwzData, &pItm->pInterfaceList); | ||
1628 | ExitOnFailure(hr, "Failed to read interfaces"); | ||
1629 | |||
1630 | // add to list | ||
1631 | if (*ppCompList) | ||
1632 | pItm->pNext = *ppCompList; | ||
1633 | *ppCompList = pItm; | ||
1634 | pItm = NULL; | ||
1635 | } | ||
1636 | |||
1637 | hr = S_OK; | ||
1638 | |||
1639 | LExit: | ||
1640 | // clean up | ||
1641 | ReleaseStr(pwzData); | ||
1642 | |||
1643 | if (pItm) | ||
1644 | FreeComponentList(pItm); | ||
1645 | |||
1646 | return hr; | ||
1647 | } | ||
1648 | |||
1649 | static HRESULT ReadInterfaceList( | ||
1650 | LPWSTR* ppwzData, | ||
1651 | CPI_INTERFACE** ppIntfList | ||
1652 | ) | ||
1653 | { | ||
1654 | HRESULT hr = S_OK; | ||
1655 | |||
1656 | LPWSTR pwzData = NULL; | ||
1657 | |||
1658 | CPI_INTERFACE* pItm = NULL; | ||
1659 | |||
1660 | int iCnt = 0; | ||
1661 | |||
1662 | // read count | ||
1663 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
1664 | ExitOnFailure(hr, "Failed to read count"); | ||
1665 | |||
1666 | // read interfaces | ||
1667 | for (int i = 0; i < iCnt; i++) | ||
1668 | { | ||
1669 | pItm = (CPI_INTERFACE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_INTERFACE)); | ||
1670 | if (!pItm) | ||
1671 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
1672 | |||
1673 | // read iid | ||
1674 | hr = WcaReadStringFromCaData(ppwzData, &pwzData); | ||
1675 | ExitOnFailure(hr, "Failed to read iid"); | ||
1676 | StringCchCopyW(pItm->wzIID, countof(pItm->wzIID), pwzData); | ||
1677 | |||
1678 | // read properties | ||
1679 | hr = CpiReadPropertyList(ppwzData, &pItm->pPropertyList); | ||
1680 | ExitOnFailure(hr, "Failed to read properties"); | ||
1681 | |||
1682 | // read role assignments | ||
1683 | hr = ReadRoleAssignmentList(ppwzData, &pItm->pRoleAssignmentList); | ||
1684 | ExitOnFailure(hr, "Failed to read role assignments"); | ||
1685 | |||
1686 | // read methods | ||
1687 | hr = ReadMethodList(ppwzData, &pItm->pMethodList); | ||
1688 | ExitOnFailure(hr, "Failed to read methods"); | ||
1689 | |||
1690 | // add to list | ||
1691 | if (*ppIntfList) | ||
1692 | pItm->pNext = *ppIntfList; | ||
1693 | *ppIntfList = pItm; | ||
1694 | pItm = NULL; | ||
1695 | } | ||
1696 | |||
1697 | hr = S_OK; | ||
1698 | |||
1699 | LExit: | ||
1700 | // clean up | ||
1701 | ReleaseStr(pwzData); | ||
1702 | |||
1703 | if (pItm) | ||
1704 | FreeInterfaceList(pItm); | ||
1705 | |||
1706 | return hr; | ||
1707 | } | ||
1708 | |||
1709 | static HRESULT ReadMethodList( | ||
1710 | LPWSTR* ppwzData, | ||
1711 | CPI_METHOD** ppMethList | ||
1712 | ) | ||
1713 | { | ||
1714 | HRESULT hr = S_OK; | ||
1715 | |||
1716 | LPWSTR pwzData = NULL; | ||
1717 | |||
1718 | CPI_METHOD* pItm = NULL; | ||
1719 | |||
1720 | int iCnt = 0; | ||
1721 | |||
1722 | // read count | ||
1723 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
1724 | ExitOnFailure(hr, "Failed to read count"); | ||
1725 | |||
1726 | // read methods | ||
1727 | for (int i = 0; i < iCnt; i++) | ||
1728 | { | ||
1729 | pItm = (CPI_METHOD*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_METHOD)); | ||
1730 | if (!pItm) | ||
1731 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
1732 | |||
1733 | // read index | ||
1734 | hr = WcaReadStringFromCaData(ppwzData, &pwzData); | ||
1735 | ExitOnFailure(hr, "Failed to read index"); | ||
1736 | StringCchCopyW(pItm->wzIndex, countof(pItm->wzIndex), pwzData); | ||
1737 | |||
1738 | // read name | ||
1739 | hr = WcaReadStringFromCaData(ppwzData, &pwzData); | ||
1740 | ExitOnFailure(hr, "Failed to read name"); | ||
1741 | StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData); | ||
1742 | |||
1743 | // read properties | ||
1744 | hr = CpiReadPropertyList(ppwzData, &pItm->pPropertyList); | ||
1745 | ExitOnFailure(hr, "Failed to read properties"); | ||
1746 | |||
1747 | // read role assignments | ||
1748 | hr = ReadRoleAssignmentList(ppwzData, &pItm->pRoleAssignmentList); | ||
1749 | ExitOnFailure(hr, "Failed to read role assignments"); | ||
1750 | |||
1751 | // add to list | ||
1752 | if (*ppMethList) | ||
1753 | pItm->pNext = *ppMethList; | ||
1754 | *ppMethList = pItm; | ||
1755 | pItm = NULL; | ||
1756 | } | ||
1757 | |||
1758 | hr = S_OK; | ||
1759 | |||
1760 | LExit: | ||
1761 | // clean up | ||
1762 | ReleaseStr(pwzData); | ||
1763 | |||
1764 | if (pItm) | ||
1765 | FreeMethodList(pItm); | ||
1766 | |||
1767 | return hr; | ||
1768 | } | ||
1769 | |||
1770 | static HRESULT ReadRoleAssignmentList( | ||
1771 | LPWSTR* ppwzData, | ||
1772 | CPI_ROLE_ASSIGNMENT** ppRoleList | ||
1773 | ) | ||
1774 | { | ||
1775 | HRESULT hr = S_OK; | ||
1776 | |||
1777 | LPWSTR pwzData = NULL; | ||
1778 | |||
1779 | CPI_ROLE_ASSIGNMENT* pItm = NULL; | ||
1780 | |||
1781 | int iCnt = 0; | ||
1782 | |||
1783 | // read role count | ||
1784 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
1785 | ExitOnFailure(hr, "Failed to read role assignments count"); | ||
1786 | |||
1787 | // read roles | ||
1788 | for (int i = 0; i < iCnt; i++) | ||
1789 | { | ||
1790 | pItm = (CPI_ROLE_ASSIGNMENT*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_ROLE_ASSIGNMENT)); | ||
1791 | if (!pItm) | ||
1792 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
1793 | |||
1794 | // read key | ||
1795 | hr = WcaReadStringFromCaData(ppwzData, &pwzData); | ||
1796 | ExitOnFailure(hr, "Failed to read key"); | ||
1797 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
1798 | |||
1799 | // read role name | ||
1800 | hr = WcaReadStringFromCaData(ppwzData, &pwzData); | ||
1801 | ExitOnFailure(hr, "Failed to read role name"); | ||
1802 | StringCchCopyW(pItm->wzRoleName, countof(pItm->wzRoleName), pwzData); | ||
1803 | |||
1804 | // add to list | ||
1805 | if (*ppRoleList) | ||
1806 | pItm->pNext = *ppRoleList; | ||
1807 | *ppRoleList = pItm; | ||
1808 | pItm = NULL; | ||
1809 | } | ||
1810 | |||
1811 | hr = S_OK; | ||
1812 | |||
1813 | LExit: | ||
1814 | // clean up | ||
1815 | ReleaseStr(pwzData); | ||
1816 | |||
1817 | if (pItm) | ||
1818 | FreeRoleAssignmentList(pItm); | ||
1819 | |||
1820 | return hr; | ||
1821 | } | ||
1822 | |||
1823 | static void FreeComponentList( | ||
1824 | CPI_COMPONENT* pList | ||
1825 | ) | ||
1826 | { | ||
1827 | while (pList) | ||
1828 | { | ||
1829 | if (pList->pPropertyList) | ||
1830 | CpiFreePropertyList(pList->pPropertyList); | ||
1831 | if (pList->pRoleAssignmentList) | ||
1832 | FreeRoleAssignmentList(pList->pRoleAssignmentList); | ||
1833 | if (pList->pInterfaceList) | ||
1834 | FreeInterfaceList(pList->pInterfaceList); | ||
1835 | |||
1836 | CPI_COMPONENT* pDelete = pList; | ||
1837 | pList = pList->pNext; | ||
1838 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
1839 | } | ||
1840 | } | ||
1841 | |||
1842 | static void FreeInterfaceList( | ||
1843 | CPI_INTERFACE* pList | ||
1844 | ) | ||
1845 | { | ||
1846 | while (pList) | ||
1847 | { | ||
1848 | if (pList->pPropertyList) | ||
1849 | CpiFreePropertyList(pList->pPropertyList); | ||
1850 | if (pList->pRoleAssignmentList) | ||
1851 | FreeRoleAssignmentList(pList->pRoleAssignmentList); | ||
1852 | if (pList->pMethodList) | ||
1853 | FreeMethodList(pList->pMethodList); | ||
1854 | |||
1855 | CPI_INTERFACE* pDelete = pList; | ||
1856 | pList = pList->pNext; | ||
1857 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
1858 | } | ||
1859 | } | ||
1860 | |||
1861 | static void FreeMethodList( | ||
1862 | CPI_METHOD* pList | ||
1863 | ) | ||
1864 | { | ||
1865 | while (pList) | ||
1866 | { | ||
1867 | if (pList->pPropertyList) | ||
1868 | CpiFreePropertyList(pList->pPropertyList); | ||
1869 | if (pList->pRoleAssignmentList) | ||
1870 | FreeRoleAssignmentList(pList->pRoleAssignmentList); | ||
1871 | |||
1872 | CPI_METHOD* pDelete = pList; | ||
1873 | pList = pList->pNext; | ||
1874 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
1875 | } | ||
1876 | } | ||
1877 | |||
1878 | static void FreeRoleAssignmentList( | ||
1879 | CPI_ROLE_ASSIGNMENT* pList | ||
1880 | ) | ||
1881 | { | ||
1882 | while (pList) | ||
1883 | { | ||
1884 | CPI_ROLE_ASSIGNMENT* pDelete = pList; | ||
1885 | pList = pList->pNext; | ||
1886 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
1887 | } | ||
1888 | } | ||