2 * IAssemblyCache implementation
4 * Copyright 2010 Hans Leidekker for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "wine/debug.h"
33 #include "wine/list.h"
34 #include "sxs_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(sxs
);
38 static const WCHAR cache_mutex_nameW
[] =
39 {'_','_','W','I','N','E','_','S','X','S','_','C','A','C','H','E','_','M','U','T','E','X','_','_',0};
41 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
42 static const WCHAR win32_policyW
[] = {'w','i','n','3','2','-','p','o','l','i','c','y',0};
43 static const WCHAR backslashW
[] = {'\\',0};
47 IAssemblyCache IAssemblyCache_iface
;
52 static inline struct cache
*impl_from_IAssemblyCache(IAssemblyCache
*iface
)
54 return CONTAINING_RECORD(iface
, struct cache
, IAssemblyCache_iface
);
57 static HRESULT WINAPI
cache_QueryInterface(
58 IAssemblyCache
*iface
,
62 TRACE("%p, %s, %p\n", iface
, debugstr_guid(riid
), ret_iface
);
66 if (IsEqualIID(riid
, &IID_IUnknown
) ||
67 IsEqualIID(riid
, &IID_IAssemblyCache
))
69 IAssemblyCache_AddRef( iface
);
77 static ULONG WINAPI
cache_AddRef( IAssemblyCache
*iface
)
79 struct cache
*cache
= impl_from_IAssemblyCache(iface
);
80 return InterlockedIncrement( &cache
->refs
);
83 static ULONG WINAPI
cache_Release( IAssemblyCache
*iface
)
85 struct cache
*cache
= impl_from_IAssemblyCache(iface
);
86 ULONG refs
= InterlockedDecrement( &cache
->refs
);
90 TRACE("destroying %p\n", cache
);
91 CloseHandle( cache
->lock
);
97 static unsigned int build_sxs_path( WCHAR
*path
)
99 static const WCHAR winsxsW
[] = {'\\','w','i','n','s','x','s','\\',0};
100 unsigned int len
= GetWindowsDirectoryW( path
, MAX_PATH
);
102 memcpy( path
+ len
, winsxsW
, sizeof(winsxsW
) );
103 return len
+ ARRAY_SIZE(winsxsW
) - 1;
106 static WCHAR
*build_assembly_name( const WCHAR
*arch
, const WCHAR
*name
, const WCHAR
*token
,
107 const WCHAR
*version
, unsigned int *len
)
109 static const WCHAR fmtW
[] =
110 {'%','s','_','%','s','_','%','s','_','%','s','_','n','o','n','e','_','d','e','a','d','b','e','e','f',0};
111 unsigned int buflen
= ARRAY_SIZE(fmtW
);
114 buflen
+= lstrlenW( arch
);
115 buflen
+= lstrlenW( name
);
116 buflen
+= lstrlenW( token
);
117 buflen
+= lstrlenW( version
);
118 if (!(ret
= malloc( buflen
* sizeof(WCHAR
) ))) return NULL
;
119 *len
= swprintf( ret
, buflen
, fmtW
, arch
, name
, token
, version
);
120 return wcslwr( ret
);
123 static WCHAR
*build_dll_path( const WCHAR
*arch
, const WCHAR
*name
, const WCHAR
*token
,
124 const WCHAR
*version
)
126 WCHAR
*path
= NULL
, *ret
, sxsdir
[MAX_PATH
];
129 if (!(path
= build_assembly_name( arch
, name
, token
, version
, &len
))) return NULL
;
130 len
+= build_sxs_path( sxsdir
) + 2;
131 if (!(ret
= malloc( len
* sizeof(WCHAR
) )))
136 lstrcpyW( ret
, sxsdir
);
137 lstrcatW( ret
, path
);
138 lstrcatW( ret
, L
"\\" );
143 static WCHAR
*build_policy_name( const WCHAR
*arch
, const WCHAR
*name
, const WCHAR
*token
,
146 static const WCHAR fmtW
[] =
147 {'%','s','_','%','s','_','%','s','_','n','o','n','e','_','d','e','a','d','b','e','e','f',0};
148 unsigned int buflen
= ARRAY_SIZE(fmtW
);
151 buflen
+= lstrlenW( arch
);
152 buflen
+= lstrlenW( name
);
153 buflen
+= lstrlenW( token
);
154 if (!(ret
= malloc( buflen
* sizeof(WCHAR
) ))) return NULL
;
155 *len
= swprintf( ret
, buflen
, fmtW
, arch
, name
, token
);
156 return wcslwr( ret
);
159 static WCHAR
*build_policy_path( const WCHAR
*arch
, const WCHAR
*name
, const WCHAR
*token
,
160 const WCHAR
*version
)
162 static const WCHAR fmtW
[] =
163 {'%','s','p','o','l','i','c','i','e','s','\\','%','s','\\','%','s','.','p','o','l','i','c','y',0};
164 WCHAR
*path
= NULL
, *ret
, sxsdir
[MAX_PATH
];
167 if (!(path
= build_policy_name( arch
, name
, token
, &len
))) return NULL
;
168 len
+= ARRAY_SIZE(fmtW
);
169 len
+= build_sxs_path( sxsdir
);
170 len
+= lstrlenW( version
);
171 if (!(ret
= malloc( len
* sizeof(WCHAR
) )))
176 swprintf( ret
, len
, fmtW
, sxsdir
, path
, version
);
181 static void cache_lock( struct cache
*cache
)
183 WaitForSingleObject( cache
->lock
, INFINITE
);
186 static void cache_unlock( struct cache
*cache
)
188 ReleaseMutex( cache
->lock
);
191 #define ASSEMBLYINFO_FLAG_INSTALLED 1
193 static HRESULT WINAPI
cache_QueryAssemblyInfo(
194 IAssemblyCache
*iface
,
196 LPCWSTR assembly_name
,
197 ASSEMBLY_INFO
*info
)
199 struct cache
*cache
= impl_from_IAssemblyCache( iface
);
200 IAssemblyName
*name_obj
;
201 const WCHAR
*arch
, *name
, *token
, *type
, *version
;
206 TRACE("%p, 0x%08lx, %s, %p\n", iface
, flags
, debugstr_w(assembly_name
), info
);
208 if (flags
|| (info
&& info
->cbAssemblyInfo
!= sizeof(*info
)))
211 hr
= CreateAssemblyNameObject( &name_obj
, assembly_name
, CANOF_PARSE_DISPLAY_NAME
, 0 );
215 arch
= get_name_attribute( name_obj
, NAME_ATTR_ID_ARCH
);
216 name
= get_name_attribute( name_obj
, NAME_ATTR_ID_NAME
);
217 token
= get_name_attribute( name_obj
, NAME_ATTR_ID_TOKEN
);
218 type
= get_name_attribute( name_obj
, NAME_ATTR_ID_TYPE
);
219 version
= get_name_attribute( name_obj
, NAME_ATTR_ID_VERSION
);
220 if (!arch
|| !name
|| !token
|| !type
|| !version
)
222 IAssemblyName_Release( name_obj
);
223 return HRESULT_FROM_WIN32( ERROR_SXS_MISSING_ASSEMBLY_IDENTITY_ATTRIBUTE
);
227 IAssemblyName_Release( name_obj
);
232 if (!wcscmp( type
, win32W
)) path
= build_dll_path( arch
, name
, token
, version
);
233 else if (!wcscmp( type
, win32_policyW
)) path
= build_policy_path( arch
, name
, token
, version
);
236 hr
= HRESULT_FROM_WIN32( ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE
);
245 if (GetFileAttributesW( path
) != INVALID_FILE_ATTRIBUTES
) /* FIXME: better check */
247 info
->dwAssemblyFlags
= ASSEMBLYINFO_FLAG_INSTALLED
;
248 TRACE("assembly is installed\n");
250 len
= lstrlenW( path
) + 1;
251 if (info
->pszCurrentAssemblyPathBuf
)
253 if (info
->cchBuf
< len
)
256 hr
= HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER
);
258 else lstrcpyW( info
->pszCurrentAssemblyPathBuf
, path
);
263 IAssemblyName_Release( name_obj
);
264 cache_unlock( cache
);
268 static HRESULT WINAPI
cache_CreateAssemblyCacheItem(
269 IAssemblyCache
*iface
,
272 IAssemblyCacheItem
**item
,
275 FIXME("%p, 0x%08lx, %p, %p, %s\n", iface
, flags
, reserved
, item
, debugstr_w(name
));
279 static HRESULT WINAPI
cache_Reserved(
280 IAssemblyCache
*iface
,
283 FIXME("%p\n", reserved
);
287 static BSTR
get_attribute_value( IXMLDOMNamedNodeMap
*map
, const WCHAR
*value_name
)
294 str
= SysAllocString( value_name
);
295 hr
= IXMLDOMNamedNodeMap_getNamedItem( map
, str
, &attr
);
296 SysFreeString( str
);
297 if (hr
!= S_OK
) return NULL
;
299 hr
= IXMLDOMNode_get_nodeValue( attr
, &var
);
300 IXMLDOMNode_Release( attr
);
301 if (hr
!= S_OK
) return NULL
;
302 if (V_VT(&var
) != VT_BSTR
)
304 VariantClear( &var
);
307 TRACE("%s=%s\n", debugstr_w(value_name
), debugstr_w(V_BSTR( &var
)));
308 return V_BSTR( &var
);
327 static void free_assembly( struct assembly
*assembly
)
329 struct list
*item
, *cursor
;
331 if (!assembly
) return;
332 SysFreeString( assembly
->type
);
333 SysFreeString( assembly
->name
);
334 SysFreeString( assembly
->version
);
335 SysFreeString( assembly
->arch
);
336 SysFreeString( assembly
->token
);
337 LIST_FOR_EACH_SAFE( item
, cursor
, &assembly
->files
)
339 struct file
*file
= LIST_ENTRY( item
, struct file
, entry
);
340 list_remove( &file
->entry
);
341 SysFreeString( file
->name
);
347 static HRESULT
parse_files( IXMLDOMDocument
*doc
, struct assembly
*assembly
)
349 static const WCHAR fileW
[] = {'f','i','l','e',0};
350 static const WCHAR nameW
[] = {'n','a','m','e',0};
351 IXMLDOMNamedNodeMap
*attrs
;
352 IXMLDOMNodeList
*list
;
359 str
= SysAllocString( fileW
);
360 hr
= IXMLDOMDocument_getElementsByTagName( doc
, str
, &list
);
361 SysFreeString( str
);
362 if (hr
!= S_OK
) return hr
;
364 hr
= IXMLDOMNodeList_get_length( list
, &len
);
365 if (hr
!= S_OK
) goto done
;
366 TRACE("found %ld files\n", len
);
369 hr
= ERROR_SXS_MANIFEST_FORMAT_ERROR
;
375 hr
= IXMLDOMNodeList_nextNode( list
, &node
);
376 if (hr
!= S_OK
|| !node
)
382 /* FIXME: validate node type */
384 hr
= IXMLDOMNode_get_attributes( node
, &attrs
);
385 IXMLDOMNode_Release( node
);
389 if (!(f
= malloc( sizeof(*f
) )))
391 IXMLDOMNamedNodeMap_Release( attrs
);
396 f
->name
= get_attribute_value( attrs
, nameW
);
397 IXMLDOMNamedNodeMap_Release( attrs
);
401 hr
= ERROR_SXS_MANIFEST_FORMAT_ERROR
;
404 list_add_tail( &assembly
->files
, &f
->entry
);
407 if (list_empty( &assembly
->files
))
409 WARN("no files found\n");
410 hr
= ERROR_SXS_MANIFEST_FORMAT_ERROR
;
414 IXMLDOMNodeList_Release( list
);
418 static HRESULT
parse_assembly( IXMLDOMDocument
*doc
, struct assembly
**assembly
)
420 static const WCHAR identityW
[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
421 static const WCHAR typeW
[] = {'t','y','p','e',0};
422 static const WCHAR nameW
[] = {'n','a','m','e',0};
423 static const WCHAR versionW
[] = {'v','e','r','s','i','o','n',0};
424 static const WCHAR architectureW
[] = {'p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e',0};
425 static const WCHAR tokenW
[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
426 IXMLDOMNodeList
*list
= NULL
;
427 IXMLDOMNode
*node
= NULL
;
428 IXMLDOMNamedNodeMap
*attrs
= NULL
;
429 struct assembly
*a
= NULL
;
434 str
= SysAllocString( identityW
);
435 hr
= IXMLDOMDocument_getElementsByTagName( doc
, str
, &list
);
436 SysFreeString( str
);
437 if (hr
!= S_OK
) goto done
;
439 hr
= IXMLDOMNodeList_get_length( list
, &len
);
440 if (hr
!= S_OK
) goto done
;
443 hr
= ERROR_SXS_MANIFEST_FORMAT_ERROR
;
446 hr
= IXMLDOMNodeList_nextNode( list
, &node
);
447 if (hr
!= S_OK
) goto done
;
450 hr
= ERROR_SXS_MANIFEST_FORMAT_ERROR
;
453 if (!(a
= calloc(1, sizeof(*a
) )))
458 list_init( &a
->files
);
460 hr
= IXMLDOMNode_get_attributes( node
, &attrs
);
461 if (hr
!= S_OK
) goto done
;
463 a
->type
= get_attribute_value( attrs
, typeW
);
464 a
->name
= get_attribute_value( attrs
, nameW
);
465 a
->version
= get_attribute_value( attrs
, versionW
);
466 a
->arch
= get_attribute_value( attrs
, architectureW
);
467 a
->token
= get_attribute_value( attrs
, tokenW
);
469 if (!a
->type
|| (wcscmp( a
->type
, win32W
) && wcscmp( a
->type
, win32_policyW
)) ||
470 !a
->name
|| !a
->version
|| !a
->arch
|| !a
->token
)
472 WARN("invalid win32 assembly\n");
473 hr
= ERROR_SXS_MANIFEST_FORMAT_ERROR
;
476 if (!wcscmp( a
->type
, win32W
)) hr
= parse_files( doc
, a
);
479 if (attrs
) IXMLDOMNamedNodeMap_Release( attrs
);
480 if (node
) IXMLDOMNode_Release( node
);
481 if (list
) IXMLDOMNodeList_Release( list
);
482 if (hr
== S_OK
) *assembly
= a
;
483 else free_assembly( a
);
487 static WCHAR
*build_policy_filename( const WCHAR
*arch
, const WCHAR
*name
, const WCHAR
*token
,
488 const WCHAR
*version
)
490 static const WCHAR policiesW
[] = {'p','o','l','i','c','i','e','s','\\',0};
491 static const WCHAR suffixW
[] = {'.','p','o','l','i','c','y',0};
492 WCHAR sxsdir
[MAX_PATH
], *ret
, *fullname
;
495 if (!(fullname
= build_policy_name( arch
, name
, token
, &len
))) return NULL
;
496 len
+= build_sxs_path( sxsdir
);
497 len
+= ARRAY_SIZE(policiesW
) - 1;
498 len
+= lstrlenW( version
);
499 len
+= ARRAY_SIZE(suffixW
) - 1;
500 if (!(ret
= malloc( (len
+ 1) * sizeof(WCHAR
) )))
505 lstrcpyW( ret
, sxsdir
);
506 lstrcatW( ret
, policiesW
);
507 CreateDirectoryW( ret
, NULL
);
508 lstrcatW( ret
, name
);
509 CreateDirectoryW( ret
, NULL
);
510 lstrcatW( ret
, backslashW
);
511 lstrcatW( ret
, version
);
512 lstrcatW( ret
, suffixW
);
518 static HRESULT
install_policy( const WCHAR
*manifest
, struct assembly
*assembly
)
523 /* FIXME: handle catalog file */
525 dst
= build_policy_filename( assembly
->arch
, assembly
->name
, assembly
->token
, assembly
->version
);
526 if (!dst
) return E_OUTOFMEMORY
;
528 ret
= CopyFileW( manifest
, dst
, FALSE
);
532 HRESULT hr
= HRESULT_FROM_WIN32( GetLastError() );
533 WARN("failed to copy policy manifest file 0x%08lx\n", hr
);
539 static WCHAR
*build_source_filename( const WCHAR
*manifest
, struct file
*file
)
545 p
= wcsrchr( manifest
, '\\' );
546 if (!p
) p
= wcsrchr( manifest
, '/' );
547 if (!p
) return wcsdup( manifest
);
549 len
= p
- manifest
+ 1;
550 if (!(src
= malloc( (len
+ lstrlenW( file
->name
) + 1) * sizeof(WCHAR
) )))
553 memcpy( src
, manifest
, len
* sizeof(WCHAR
) );
554 lstrcpyW( src
+ len
, file
->name
);
558 static WCHAR
*build_manifest_filename( const WCHAR
*arch
, const WCHAR
*name
, const WCHAR
*token
,
559 const WCHAR
*version
)
561 static const WCHAR manifestsW
[] = {'m','a','n','i','f','e','s','t','s','\\',0};
562 static const WCHAR suffixW
[] = {'.','m','a','n','i','f','e','s','t',0};
563 WCHAR sxsdir
[MAX_PATH
], *ret
, *fullname
;
566 if (!(fullname
= build_assembly_name( arch
, name
, token
, version
, &len
))) return NULL
;
567 len
+= build_sxs_path( sxsdir
);
568 len
+= ARRAY_SIZE(manifestsW
) - 1;
569 len
+= ARRAY_SIZE(suffixW
) - 1;
570 if (!(ret
= malloc( (len
+ 1) * sizeof(WCHAR
) )))
575 lstrcpyW( ret
, sxsdir
);
576 lstrcatW( ret
, manifestsW
);
577 lstrcatW( ret
, fullname
);
578 lstrcatW( ret
, suffixW
);
584 static HRESULT
load_manifest( IXMLDOMDocument
*doc
, const WCHAR
*filename
)
591 str
= SysAllocString( filename
);
593 V_VT( &var
) = VT_BSTR
;
594 V_BSTR( &var
) = str
;
595 hr
= IXMLDOMDocument_load( doc
, var
, &b
);
596 SysFreeString( str
);
597 if (hr
!= S_OK
) return hr
;
600 WARN("failed to load manifest\n");
606 static HRESULT
install_assembly( const WCHAR
*manifest
, struct assembly
*assembly
)
608 WCHAR sxsdir
[MAX_PATH
], *p
, *name
, *dst
, *src
;
609 unsigned int len
, len_name
, len_sxsdir
= build_sxs_path( sxsdir
);
611 HRESULT hr
= E_OUTOFMEMORY
;
614 dst
= build_manifest_filename( assembly
->arch
, assembly
->name
, assembly
->token
, assembly
->version
);
615 if (!dst
) return E_OUTOFMEMORY
;
617 ret
= CopyFileW( manifest
, dst
, FALSE
);
621 hr
= HRESULT_FROM_WIN32( GetLastError() );
622 WARN("failed to copy manifest file 0x%08lx\n", hr
);
626 name
= build_assembly_name( assembly
->arch
, assembly
->name
, assembly
->token
, assembly
->version
,
628 if (!name
) return E_OUTOFMEMORY
;
630 /* FIXME: this should be a transaction */
631 LIST_FOR_EACH_ENTRY( file
, &assembly
->files
, struct file
, entry
)
633 if (!(src
= build_source_filename( manifest
, file
))) goto done
;
635 len
= len_sxsdir
+ len_name
+ lstrlenW( file
->name
);
636 if (!(dst
= malloc( (len
+ 2) * sizeof(WCHAR
) )))
641 lstrcpyW( dst
, sxsdir
);
642 lstrcatW( dst
, name
);
643 CreateDirectoryW( dst
, NULL
);
645 lstrcatW( dst
, backslashW
);
646 lstrcatW( dst
, file
->name
);
647 for (p
= dst
; *p
; p
++) *p
= towlower( *p
);
649 ret
= CopyFileW( src
, dst
, FALSE
);
654 hr
= HRESULT_FROM_WIN32( GetLastError() );
655 WARN("failed to copy file 0x%08lx\n", hr
);
666 static HRESULT WINAPI
cache_InstallAssembly(
667 IAssemblyCache
*iface
,
670 LPCFUSION_INSTALL_REFERENCE ref
)
672 struct cache
*cache
= impl_from_IAssemblyCache( iface
);
674 IXMLDOMDocument
*doc
= NULL
;
675 struct assembly
*assembly
= NULL
;
677 TRACE("%p, 0x%08lx, %s, %p\n", iface
, flags
, debugstr_w(path
), ref
);
680 init
= CoInitialize( NULL
);
682 hr
= CoCreateInstance( &CLSID_DOMDocument
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IXMLDOMDocument
, (void **)&doc
);
686 if ((hr
= load_manifest( doc
, path
)) != S_OK
) goto done
;
687 if ((hr
= parse_assembly( doc
, &assembly
)) != S_OK
) goto done
;
689 /* FIXME: verify name attributes */
691 if (!wcscmp( assembly
->type
, win32_policyW
))
692 hr
= install_policy( path
, assembly
);
694 hr
= install_assembly( path
, assembly
);
697 free_assembly( assembly
);
698 if (doc
) IXMLDOMDocument_Release( doc
);
699 if (SUCCEEDED(init
)) CoUninitialize();
700 cache_unlock( cache
);
704 static HRESULT
uninstall_assembly( struct assembly
*assembly
)
706 WCHAR sxsdir
[MAX_PATH
], *name
, *dirname
, *filename
;
707 unsigned int len
, len_name
, len_sxsdir
= build_sxs_path( sxsdir
);
708 HRESULT hr
= E_OUTOFMEMORY
;
711 name
= build_assembly_name( assembly
->arch
, assembly
->name
, assembly
->token
, assembly
->version
,
713 if (!name
) return E_OUTOFMEMORY
;
714 if (!(dirname
= malloc( (len_sxsdir
+ len_name
+ 1) * sizeof(WCHAR
) )))
716 lstrcpyW( dirname
, sxsdir
);
717 lstrcpyW( dirname
+ len_sxsdir
, name
);
719 LIST_FOR_EACH_ENTRY( file
, &assembly
->files
, struct file
, entry
)
721 len
= len_sxsdir
+ len_name
+ 1 + lstrlenW( file
->name
);
722 if (!(filename
= malloc( (len
+ 1) * sizeof(WCHAR
) ))) goto done
;
723 lstrcpyW( filename
, dirname
);
724 lstrcatW( filename
, backslashW
);
725 lstrcatW( filename
, file
->name
);
727 if (!DeleteFileW( filename
)) WARN( "failed to delete file %lu\n", GetLastError() );
730 RemoveDirectoryW( dirname
);
739 static HRESULT WINAPI
cache_UninstallAssembly(
740 IAssemblyCache
*iface
,
742 LPCWSTR assembly_name
,
743 LPCFUSION_INSTALL_REFERENCE ref
,
746 struct cache
*cache
= impl_from_IAssemblyCache( iface
);
748 IXMLDOMDocument
*doc
= NULL
;
749 struct assembly
*assembly
= NULL
;
750 IAssemblyName
*name_obj
= NULL
;
751 const WCHAR
*arch
, *name
, *token
, *type
, *version
;
752 WCHAR
*p
, *path
= NULL
;
754 TRACE("%p, 0x%08lx, %s, %p, %p\n", iface
, flags
, debugstr_w(assembly_name
), ref
, disp
);
758 FIXME("application reference not supported\n");
762 init
= CoInitialize( NULL
);
764 hr
= CreateAssemblyNameObject( &name_obj
, assembly_name
, CANOF_PARSE_DISPLAY_NAME
, NULL
);
768 arch
= get_name_attribute( name_obj
, NAME_ATTR_ID_ARCH
);
769 name
= get_name_attribute( name_obj
, NAME_ATTR_ID_NAME
);
770 token
= get_name_attribute( name_obj
, NAME_ATTR_ID_TOKEN
);
771 type
= get_name_attribute( name_obj
, NAME_ATTR_ID_TYPE
);
772 version
= get_name_attribute( name_obj
, NAME_ATTR_ID_VERSION
);
773 if (!arch
|| !name
|| !token
|| !type
|| !version
)
778 if (!wcscmp( type
, win32W
)) path
= build_manifest_filename( arch
, name
, token
, version
);
779 else if (!wcscmp( type
, win32_policyW
)) path
= build_policy_filename( arch
, name
, token
, version
);
786 hr
= CoCreateInstance( &CLSID_DOMDocument
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IXMLDOMDocument
, (void **)&doc
);
790 if ((hr
= load_manifest( doc
, path
)) != S_OK
) goto done
;
791 if ((hr
= parse_assembly( doc
, &assembly
)) != S_OK
) goto done
;
793 if (!DeleteFileW( path
)) WARN( "unable to remove manifest file %lu\n", GetLastError() );
794 else if ((p
= wcsrchr( path
, '\\' )))
797 RemoveDirectoryW( path
);
799 if (!wcscmp( assembly
->type
, win32W
)) hr
= uninstall_assembly( assembly
);
802 if (name_obj
) IAssemblyName_Release( name_obj
);
804 free_assembly( assembly
);
805 if (doc
) IXMLDOMDocument_Release( doc
);
806 if (SUCCEEDED(init
)) CoUninitialize();
807 cache_unlock( cache
);
811 static const IAssemblyCacheVtbl cache_vtbl
=
813 cache_QueryInterface
,
816 cache_UninstallAssembly
,
817 cache_QueryAssemblyInfo
,
818 cache_CreateAssemblyCacheItem
,
820 cache_InstallAssembly
823 /******************************************************************
824 * CreateAssemblyCache (SXS.@)
826 HRESULT WINAPI
CreateAssemblyCache( IAssemblyCache
**obj
, DWORD reserved
)
830 TRACE("%p, %lu\n", obj
, reserved
);
837 cache
= malloc( sizeof(*cache
) );
839 return E_OUTOFMEMORY
;
841 cache
->IAssemblyCache_iface
.lpVtbl
= &cache_vtbl
;
843 cache
->lock
= CreateMutexW( NULL
, FALSE
, cache_mutex_nameW
);
847 return HRESULT_FROM_WIN32( GetLastError() );
849 *obj
= &cache
->IAssemblyCache_iface
;