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