diff options
Diffstat (limited to 'src/ext/ComPlus/ca/cpasmexec.cpp')
-rw-r--r-- | src/ext/ComPlus/ca/cpasmexec.cpp | 1877 |
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 | |||
8 | typedef struct _FUSION_INSTALL_REFERENCE_ | ||
9 | { | ||
10 | DWORD cbSize; | ||
11 | DWORD dwFlags; | ||
12 | GUID guidScheme; | ||
13 | LPCWSTR szIdentifier; | ||
14 | LPCWSTR szNonCannonicalData; | ||
15 | } FUSION_INSTALL_REFERENCE; | ||
16 | |||
17 | typedef struct _FUSION_INSTALL_REFERENCE_ *LPFUSION_INSTALL_REFERENCE; | ||
18 | |||
19 | typedef const FUSION_INSTALL_REFERENCE *LPCFUSION_INSTALL_REFERENCE; | ||
20 | |||
21 | typedef struct _ASSEMBLY_INFO | ||
22 | { | ||
23 | ULONG cbAssemblyInfo; | ||
24 | DWORD dwAssemblyFlags; | ||
25 | ULARGE_INTEGER uliAssemblySizeInKB; | ||
26 | LPWSTR pszCurrentAssemblyPathBuf; | ||
27 | ULONG cchBuf; | ||
28 | } ASSEMBLY_INFO; | ||
29 | |||
30 | typedef interface IAssemblyCacheItem IAssemblyCacheItem; | ||
31 | |||
32 | MIDL_INTERFACE("e707dcde-d1cd-11d2-bab9-00c04f8eceae") | ||
33 | IAssemblyCache : public IUnknown | ||
34 | { | ||
35 | public: | ||
36 | virtual HRESULT STDMETHODCALLTYPE UninstallAssembly( | ||
37 | /* [in] */ DWORD dwFlags, | ||
38 | /* [in] */ LPCWSTR pszAssemblyName, | ||
39 | /* [in] */ LPCFUSION_INSTALL_REFERENCE pRefData, | ||
40 | /* [optional][out] */ ULONG *pulDisposition) = 0; | ||
41 | |||
42 | virtual HRESULT STDMETHODCALLTYPE QueryAssemblyInfo( | ||
43 | /* [in] */ DWORD dwFlags, | ||
44 | /* [in] */ LPCWSTR pszAssemblyName, | ||
45 | /* [out][in] */ ASSEMBLY_INFO *pAsmInfo) = 0; | ||
46 | |||
47 | virtual HRESULT STDMETHODCALLTYPE CreateAssemblyCacheItem( | ||
48 | /* [in] */ DWORD dwFlags, | ||
49 | /* [in] */ PVOID pvReserved, | ||
50 | /* [out] */ IAssemblyCacheItem **ppAsmItem, | ||
51 | /* [optional][in] */ LPCWSTR pszAssemblyName) = 0; | ||
52 | |||
53 | virtual HRESULT STDMETHODCALLTYPE CreateAssemblyScavenger( | ||
54 | /* [out] */ IUnknown **ppUnkReserved) = 0; | ||
55 | |||
56 | virtual HRESULT STDMETHODCALLTYPE InstallAssembly( | ||
57 | /* [in] */ DWORD dwFlags, | ||
58 | /* [in] */ LPCWSTR pszManifestFilePath, | ||
59 | /* [in] */ LPCFUSION_INSTALL_REFERENCE pRefData) = 0; | ||
60 | }; | ||
61 | |||
62 | typedef HRESULT (__stdcall *LoadLibraryShimFunc)(LPCWSTR szDllName, LPCWSTR szVersion, LPVOID pvReserved, HMODULE *phModDll); | ||
63 | typedef HRESULT (__stdcall *CreateAssemblyCacheFunc)(IAssemblyCache **ppAsmCache, DWORD dwReserved); | ||
64 | |||
65 | |||
66 | // RegistrationHelper related declarations | ||
67 | |||
68 | static const GUID CLSID_RegistrationHelper = | ||
69 | { 0x89a86e7b, 0xc229, 0x4008, { 0x9b, 0xaa, 0x2f, 0x5c, 0x84, 0x11, 0xd7, 0xe0 } }; | ||
70 | |||
71 | enum eInstallationFlags { | ||
72 | ifConfigureComponentsOnly = 16, | ||
73 | ifFindOrCreateTargetApplication = 4, | ||
74 | ifExpectExistingTypeLib = 1 | ||
75 | }; | ||
76 | |||
77 | |||
78 | // private structs | ||
79 | |||
80 | struct 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 | |||
88 | struct 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 | |||
99 | struct 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 | |||
110 | struct 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 | |||
121 | struct 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 | |||
136 | struct 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 | |||
150 | static HRESULT RegisterAssembly( | ||
151 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
152 | ); | ||
153 | static HRESULT UnregisterAssembly( | ||
154 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
155 | ); | ||
156 | static void InitAssemblyExec(); | ||
157 | static void UninitAssemblyExec(); | ||
158 | static HRESULT GetRegistrationHelper( | ||
159 | IDispatch** ppiRegHlp | ||
160 | ); | ||
161 | static HRESULT GetAssemblyCacheObject( | ||
162 | IAssemblyCache** ppAssemblyCache | ||
163 | ); | ||
164 | static HRESULT GetAssemblyPathFromGAC( | ||
165 | LPCWSTR pwzAssemblyName, | ||
166 | LPWSTR* ppwzAssemblyPath | ||
167 | ); | ||
168 | static HRESULT RegisterDotNetAssembly( | ||
169 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
170 | ); | ||
171 | static HRESULT RegisterNativeAssembly( | ||
172 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
173 | ); | ||
174 | static HRESULT UnregisterDotNetAssembly( | ||
175 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
176 | ); | ||
177 | static HRESULT RemoveComponents( | ||
178 | ICatalogCollection* piCompColl, | ||
179 | CPIEXEC_COMPONENT* pCompList | ||
180 | ); | ||
181 | static HRESULT ReadAssemblyAttributes( | ||
182 | LPWSTR* ppwzData, | ||
183 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
184 | ); | ||
185 | static void FreeAssemblyAttributes( | ||
186 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
187 | ); | ||
188 | static HRESULT ReadRoleAssignmentsAttributes( | ||
189 | LPWSTR* ppwzData, | ||
190 | CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs | ||
191 | ); | ||
192 | static void FreeRoleAssignmentsAttributes( | ||
193 | CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs | ||
194 | ); | ||
195 | static HRESULT ConfigureComponents( | ||
196 | LPCWSTR pwzPartID, | ||
197 | LPCWSTR pwzAppID, | ||
198 | CPIEXEC_COMPONENT* pCompList, | ||
199 | BOOL fCreate, | ||
200 | BOOL fProgress | ||
201 | ); | ||
202 | static HRESULT ConfigureInterfaces( | ||
203 | ICatalogCollection* piCompColl, | ||
204 | ICatalogObject* piCompObj, | ||
205 | CPIEXEC_INTERFACE* pIntfList, | ||
206 | BOOL fCreate | ||
207 | ); | ||
208 | static HRESULT ConfigureMethods( | ||
209 | ICatalogCollection* piIntfColl, | ||
210 | ICatalogObject* piIntfObj, | ||
211 | CPIEXEC_METHOD* pMethList, | ||
212 | BOOL fCreate | ||
213 | ); | ||
214 | static HRESULT ConfigureRoleAssignments( | ||
215 | LPCWSTR pwzCollName, | ||
216 | ICatalogCollection* piCompColl, | ||
217 | ICatalogObject* piCompObj, | ||
218 | CPIEXEC_ROLE_ASSIGNMENT* pRoleList, | ||
219 | BOOL fCreate | ||
220 | ); | ||
221 | static HRESULT ReadComponentList( | ||
222 | LPWSTR* ppwzData, | ||
223 | CPIEXEC_COMPONENT** ppCompList | ||
224 | ); | ||
225 | static HRESULT ReadInterfaceList( | ||
226 | LPWSTR* ppwzData, | ||
227 | CPIEXEC_INTERFACE** ppIntfList | ||
228 | ); | ||
229 | static HRESULT ReadMethodList( | ||
230 | LPWSTR* ppwzData, | ||
231 | CPIEXEC_METHOD** ppMethList | ||
232 | ); | ||
233 | static HRESULT ReadRoleAssignmentList( | ||
234 | LPWSTR* ppwzData, | ||
235 | CPIEXEC_ROLE_ASSIGNMENT** ppRoleList | ||
236 | ); | ||
237 | static void FreeComponentList( | ||
238 | CPIEXEC_COMPONENT* pList | ||
239 | ); | ||
240 | static void FreeInterfaceList( | ||
241 | CPIEXEC_INTERFACE* pList | ||
242 | ); | ||
243 | static void FreeMethodList( | ||
244 | CPIEXEC_METHOD* pList | ||
245 | ); | ||
246 | static void FreeRoleAssignmentList( | ||
247 | CPIEXEC_ROLE_ASSIGNMENT* pList | ||
248 | ); | ||
249 | |||
250 | |||
251 | // variables | ||
252 | |||
253 | static IDispatch* gpiRegHlp; | ||
254 | static IAssemblyCache* gpAssemblyCache; | ||
255 | static HMODULE ghMscoree; | ||
256 | static HMODULE ghFusion; | ||
257 | |||
258 | |||
259 | // function definitions | ||
260 | |||
261 | HRESULT 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 | |||
327 | LExit: | ||
328 | // clean up | ||
329 | FreeAssemblyAttributes(&attrs); | ||
330 | |||
331 | // uninitialize | ||
332 | UninitAssemblyExec(); | ||
333 | |||
334 | return hr; | ||
335 | } | ||
336 | |||
337 | HRESULT 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 | |||
399 | LExit: | ||
400 | // clean up | ||
401 | FreeAssemblyAttributes(&attrs); | ||
402 | |||
403 | // uninitialize | ||
404 | UninitAssemblyExec(); | ||
405 | |||
406 | return hr; | ||
407 | } | ||
408 | |||
409 | HRESULT 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 | |||
463 | LExit: | ||
464 | // clean up | ||
465 | FreeRoleAssignmentsAttributes(&attrs); | ||
466 | |||
467 | return hr; | ||
468 | } | ||
469 | |||
470 | HRESULT 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 | |||
524 | LExit: | ||
525 | // clean up | ||
526 | FreeRoleAssignmentsAttributes(&attrs); | ||
527 | |||
528 | return hr; | ||
529 | } | ||
530 | |||
531 | |||
532 | // helper function definitions | ||
533 | |||
534 | static 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 | |||
585 | LExit: | ||
586 | return hr; | ||
587 | } | ||
588 | |||
589 | static 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 | |||
698 | LExit: | ||
699 | // clean up | ||
700 | ReleaseObject(piColl); | ||
701 | ReleaseObject(piObj); | ||
702 | |||
703 | return hr; | ||
704 | } | ||
705 | |||
706 | static void InitAssemblyExec() | ||
707 | { | ||
708 | gpiRegHlp = NULL; | ||
709 | gpAssemblyCache = NULL; | ||
710 | ghMscoree = NULL; | ||
711 | ghFusion = NULL; | ||
712 | } | ||
713 | |||
714 | static void UninitAssemblyExec() | ||
715 | { | ||
716 | ReleaseObject(gpiRegHlp); | ||
717 | ReleaseObject(gpAssemblyCache); | ||
718 | if (ghFusion) | ||
719 | ::FreeLibrary(ghFusion); | ||
720 | if (ghMscoree) | ||
721 | ::FreeLibrary(ghMscoree); | ||
722 | } | ||
723 | |||
724 | static 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 | |||
742 | LExit: | ||
743 | return hr; | ||
744 | } | ||
745 | |||
746 | static 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 | |||
788 | LExit: | ||
789 | return hr; | ||
790 | } | ||
791 | |||
792 | static 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 | |||
827 | LExit: | ||
828 | // clean up | ||
829 | ReleaseObject(pAssemblyCache); | ||
830 | |||
831 | return hr; | ||
832 | } | ||
833 | |||
834 | static 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 | |||
931 | LExit: | ||
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 | |||
949 | static 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 | |||
1037 | LExit: | ||
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 | |||
1052 | static 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 | |||
1127 | LExit: | ||
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 | |||
1144 | static 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 | |||
1163 | LExit: | ||
1164 | return hr; | ||
1165 | } | ||
1166 | |||
1167 | static 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 | |||
1209 | LExit: | ||
1210 | return hr; | ||
1211 | } | ||
1212 | |||
1213 | static 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 | |||
1229 | static 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 | |||
1263 | LExit: | ||
1264 | return hr; | ||
1265 | } | ||
1266 | |||
1267 | static 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 | |||
1280 | static 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 | |||
1356 | LExit: | ||
1357 | // clean up | ||
1358 | ReleaseObject(piCompColl); | ||
1359 | ReleaseObject(piCompObj); | ||
1360 | |||
1361 | return hr; | ||
1362 | } | ||
1363 | |||
1364 | static 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 | |||
1429 | LExit: | ||
1430 | // clean up | ||
1431 | ReleaseObject(piIntfColl); | ||
1432 | ReleaseObject(piIntfObj); | ||
1433 | |||
1434 | return hr; | ||
1435 | } | ||
1436 | |||
1437 | static 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 | |||
1499 | LExit: | ||
1500 | // clean up | ||
1501 | ReleaseObject(piMethColl); | ||
1502 | ReleaseObject(piMethObj); | ||
1503 | |||
1504 | return hr; | ||
1505 | } | ||
1506 | |||
1507 | static 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 | |||
1570 | LExit: | ||
1571 | // clean up | ||
1572 | ReleaseObject(piRoleColl); | ||
1573 | ReleaseObject(piRoleObj); | ||
1574 | |||
1575 | return hr; | ||
1576 | } | ||
1577 | |||
1578 | static 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 | |||
1628 | LExit: | ||
1629 | // clean up | ||
1630 | ReleaseStr(pwzData); | ||
1631 | |||
1632 | if (pItm) | ||
1633 | FreeComponentList(pItm); | ||
1634 | |||
1635 | return hr; | ||
1636 | } | ||
1637 | |||
1638 | static 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 | |||
1688 | LExit: | ||
1689 | // clean up | ||
1690 | ReleaseStr(pwzData); | ||
1691 | |||
1692 | if (pItm) | ||
1693 | FreeInterfaceList(pItm); | ||
1694 | |||
1695 | return hr; | ||
1696 | } | ||
1697 | |||
1698 | static 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 | |||
1749 | LExit: | ||
1750 | // clean up | ||
1751 | ReleaseStr(pwzData); | ||
1752 | |||
1753 | if (pItm) | ||
1754 | FreeMethodList(pItm); | ||
1755 | |||
1756 | return hr; | ||
1757 | } | ||
1758 | |||
1759 | static 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 | |||
1802 | LExit: | ||
1803 | // clean up | ||
1804 | ReleaseStr(pwzData); | ||
1805 | |||
1806 | if (pItm) | ||
1807 | FreeRoleAssignmentList(pItm); | ||
1808 | |||
1809 | return hr; | ||
1810 | } | ||
1811 | |||
1812 | static 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 | |||
1831 | static 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 | |||
1850 | static 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 | |||
1867 | static 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 | } | ||