aboutsummaryrefslogtreecommitdiff
path: root/src/ca/cpasmexec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ca/cpasmexec.cpp')
-rw-r--r--src/ca/cpasmexec.cpp1888
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
8typedef 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
17typedef struct _FUSION_INSTALL_REFERENCE_ *LPFUSION_INSTALL_REFERENCE;
18
19typedef const FUSION_INSTALL_REFERENCE *LPCFUSION_INSTALL_REFERENCE;
20
21typedef struct _ASSEMBLY_INFO
22{
23 ULONG cbAssemblyInfo;
24 DWORD dwAssemblyFlags;
25 ULARGE_INTEGER uliAssemblySizeInKB;
26 LPWSTR pszCurrentAssemblyPathBuf;
27 ULONG cchBuf;
28} ASSEMBLY_INFO;
29
30typedef interface IAssemblyCacheItem IAssemblyCacheItem;
31
32MIDL_INTERFACE("e707dcde-d1cd-11d2-bab9-00c04f8eceae")
33IAssemblyCache : public IUnknown
34{
35public:
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
62typedef HRESULT (__stdcall *LoadLibraryShimFunc)(LPCWSTR szDllName, LPCWSTR szVersion, LPVOID pvReserved, HMODULE *phModDll);
63typedef HRESULT (__stdcall *CreateAssemblyCacheFunc)(IAssemblyCache **ppAsmCache, DWORD dwReserved);
64
65
66// RegistrationHelper related declarations
67
68static const GUID CLSID_RegistrationHelper =
69 { 0x89a86e7b, 0xc229, 0x4008, { 0x9b, 0xaa, 0x2f, 0x5c, 0x84, 0x11, 0xd7, 0xe0 } };
70
71enum eInstallationFlags {
72 ifConfigureComponentsOnly = 16,
73 ifFindOrCreateTargetApplication = 4,
74 ifExpectExistingTypeLib = 1
75};
76
77
78// private constants
79
80enum 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
91struct 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
99struct 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
110struct 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
121struct 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
132struct 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
147struct 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
161static HRESULT RegisterAssembly(
162 CPI_ASSEMBLY_ATTRIBUTES* pAttrs
163 );
164static HRESULT UnregisterAssembly(
165 CPI_ASSEMBLY_ATTRIBUTES* pAttrs
166 );
167static void InitAssemblyExec();
168static void UninitAssemblyExec();
169static HRESULT GetRegistrationHelper(
170 IDispatch** ppiRegHlp
171 );
172static HRESULT GetAssemblyCacheObject(
173 IAssemblyCache** ppAssemblyCache
174 );
175static HRESULT GetAssemblyPathFromGAC(
176 LPCWSTR pwzAssemblyName,
177 LPWSTR* ppwzAssemblyPath
178 );
179static HRESULT RegisterDotNetAssembly(
180 CPI_ASSEMBLY_ATTRIBUTES* pAttrs
181 );
182static HRESULT RegisterNativeAssembly(
183 CPI_ASSEMBLY_ATTRIBUTES* pAttrs
184 );
185static HRESULT UnregisterDotNetAssembly(
186 CPI_ASSEMBLY_ATTRIBUTES* pAttrs
187 );
188static HRESULT RemoveComponents(
189 ICatalogCollection* piCompColl,
190 CPI_COMPONENT* pCompList
191 );
192static HRESULT ReadAssemblyAttributes(
193 LPWSTR* ppwzData,
194 CPI_ASSEMBLY_ATTRIBUTES* pAttrs
195 );
196static void FreeAssemblyAttributes(
197 CPI_ASSEMBLY_ATTRIBUTES* pAttrs
198 );
199static HRESULT ReadRoleAssignmentsAttributes(
200 LPWSTR* ppwzData,
201 CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs
202 );
203static void FreeRoleAssignmentsAttributes(
204 CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs
205 );
206static HRESULT ConfigureComponents(
207 LPCWSTR pwzPartID,
208 LPCWSTR pwzAppID,
209 CPI_COMPONENT* pCompList,
210 BOOL fCreate,
211 BOOL fProgress
212 );
213static HRESULT ConfigureInterfaces(
214 ICatalogCollection* piCompColl,
215 ICatalogObject* piCompObj,
216 CPI_INTERFACE* pIntfList,
217 BOOL fCreate
218 );
219static HRESULT ConfigureMethods(
220 ICatalogCollection* piIntfColl,
221 ICatalogObject* piIntfObj,
222 CPI_METHOD* pMethList,
223 BOOL fCreate
224 );
225static HRESULT ConfigureRoleAssignments(
226 LPCWSTR pwzCollName,
227 ICatalogCollection* piCompColl,
228 ICatalogObject* piCompObj,
229 CPI_ROLE_ASSIGNMENT* pRoleList,
230 BOOL fCreate
231 );
232static HRESULT ReadComponentList(
233 LPWSTR* ppwzData,
234 CPI_COMPONENT** ppCompList
235 );
236static HRESULT ReadInterfaceList(
237 LPWSTR* ppwzData,
238 CPI_INTERFACE** ppIntfList
239 );
240static HRESULT ReadMethodList(
241 LPWSTR* ppwzData,
242 CPI_METHOD** ppMethList
243 );
244static HRESULT ReadRoleAssignmentList(
245 LPWSTR* ppwzData,
246 CPI_ROLE_ASSIGNMENT** ppRoleList
247 );
248static void FreeComponentList(
249 CPI_COMPONENT* pList
250 );
251static void FreeInterfaceList(
252 CPI_INTERFACE* pList
253 );
254static void FreeMethodList(
255 CPI_METHOD* pList
256 );
257static void FreeRoleAssignmentList(
258 CPI_ROLE_ASSIGNMENT* pList
259 );
260
261
262// variables
263
264static IDispatch* gpiRegHlp;
265static IAssemblyCache* gpAssemblyCache;
266static HMODULE ghMscoree;
267static HMODULE ghFusion;
268
269
270// function definitions
271
272HRESULT 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
338LExit:
339 // clean up
340 FreeAssemblyAttributes(&attrs);
341
342 // uninitialize
343 UninitAssemblyExec();
344
345 return hr;
346}
347
348HRESULT 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
410LExit:
411 // clean up
412 FreeAssemblyAttributes(&attrs);
413
414 // uninitialize
415 UninitAssemblyExec();
416
417 return hr;
418}
419
420HRESULT 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
474LExit:
475 // clean up
476 FreeRoleAssignmentsAttributes(&attrs);
477
478 return hr;
479}
480
481HRESULT 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
535LExit:
536 // clean up
537 FreeRoleAssignmentsAttributes(&attrs);
538
539 return hr;
540}
541
542
543// helper function definitions
544
545static 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
596LExit:
597 return hr;
598}
599
600static 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
709LExit:
710 // clean up
711 ReleaseObject(piColl);
712 ReleaseObject(piObj);
713
714 return hr;
715}
716
717static void InitAssemblyExec()
718{
719 gpiRegHlp = NULL;
720 gpAssemblyCache = NULL;
721 ghMscoree = NULL;
722 ghFusion = NULL;
723}
724
725static void UninitAssemblyExec()
726{
727 ReleaseObject(gpiRegHlp);
728 ReleaseObject(gpAssemblyCache);
729 if (ghFusion)
730 ::FreeLibrary(ghFusion);
731 if (ghMscoree)
732 ::FreeLibrary(ghMscoree);
733}
734
735static 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
753LExit:
754 return hr;
755}
756
757static 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
799LExit:
800 return hr;
801}
802
803static 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
838LExit:
839 // clean up
840 ReleaseObject(pAssemblyCache);
841
842 return hr;
843}
844
845static 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
942LExit:
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
960static 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
1048LExit:
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
1063static 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
1138LExit:
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
1155static 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
1174LExit:
1175 return hr;
1176}
1177
1178static 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
1220LExit:
1221 return hr;
1222}
1223
1224static 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
1240static 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
1274LExit:
1275 return hr;
1276}
1277
1278static 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
1291static 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
1367LExit:
1368 // clean up
1369 ReleaseObject(piCompColl);
1370 ReleaseObject(piCompObj);
1371
1372 return hr;
1373}
1374
1375static 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
1440LExit:
1441 // clean up
1442 ReleaseObject(piIntfColl);
1443 ReleaseObject(piIntfObj);
1444
1445 return hr;
1446}
1447
1448static 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
1510LExit:
1511 // clean up
1512 ReleaseObject(piMethColl);
1513 ReleaseObject(piMethObj);
1514
1515 return hr;
1516}
1517
1518static 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
1581LExit:
1582 // clean up
1583 ReleaseObject(piRoleColl);
1584 ReleaseObject(piRoleObj);
1585
1586 return hr;
1587}
1588
1589static 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
1639LExit:
1640 // clean up
1641 ReleaseStr(pwzData);
1642
1643 if (pItm)
1644 FreeComponentList(pItm);
1645
1646 return hr;
1647}
1648
1649static 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
1699LExit:
1700 // clean up
1701 ReleaseStr(pwzData);
1702
1703 if (pItm)
1704 FreeInterfaceList(pItm);
1705
1706 return hr;
1707}
1708
1709static 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
1760LExit:
1761 // clean up
1762 ReleaseStr(pwzData);
1763
1764 if (pItm)
1765 FreeMethodList(pItm);
1766
1767 return hr;
1768}
1769
1770static 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
1813LExit:
1814 // clean up
1815 ReleaseStr(pwzData);
1816
1817 if (pItm)
1818 FreeRoleAssignmentList(pItm);
1819
1820 return hr;
1821}
1822
1823static 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
1842static 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
1861static 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
1878static 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}