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
21 #include "sxs_private.h"
26 #include <wine/list.h>
28 static const WCHAR cache_mutex_nameW
[] =
29 {'_','_','W','I','N','E','_','S','X','S','_','C','A','C','H','E','_','M','U','T','E','X','_','_',0};
31 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
32 static const WCHAR win32_policyW
[] = {'w','i','n','3','2','-','p','o','l','i','c','y',0};
33 static const WCHAR backslashW
[] = {'\\',0};
37 IAssemblyCache IAssemblyCache_iface
;
42 static inline struct cache
*impl_from_IAssemblyCache(IAssemblyCache
*iface
)
44 return CONTAINING_RECORD(iface
, struct cache
, IAssemblyCache_iface
);
47 static HRESULT WINAPI
cache_QueryInterface(
48 IAssemblyCache
*iface
,
52 struct cache
*cache
= impl_from_IAssemblyCache(iface
);
54 TRACE("%p, %s, %p\n", cache
, debugstr_guid(riid
), obj
);
58 if (IsEqualIID(riid
, &IID_IUnknown
) ||
59 IsEqualIID(riid
, &IID_IAssemblyCache
))
61 IAssemblyCache_AddRef( iface
);
69 static ULONG WINAPI
cache_AddRef( IAssemblyCache
*iface
)
71 struct cache
*cache
= impl_from_IAssemblyCache(iface
);
72 return InterlockedIncrement( &cache
->refs
);
75 static ULONG WINAPI
cache_Release( IAssemblyCache
*iface
)
77 struct cache
*cache
= impl_from_IAssemblyCache(iface
);
78 ULONG refs
= InterlockedDecrement( &cache
->refs
);
82 TRACE("destroying %p\n", cache
);
83 CloseHandle( cache
->lock
);
84 HeapFree( GetProcessHeap(), 0, cache
);
89 static unsigned int build_sxs_path( WCHAR
*path
)
91 static const WCHAR winsxsW
[] = {'\\','w','i','n','s','x','s','\\',0};
92 unsigned int len
= GetWindowsDirectoryW( path
, MAX_PATH
);
94 memcpy( path
+ len
, winsxsW
, sizeof(winsxsW
) );
95 return len
+ sizeof(winsxsW
) / sizeof(winsxsW
[0]) - 1;
98 static WCHAR
*build_assembly_name( const WCHAR
*arch
, const WCHAR
*name
, const WCHAR
*token
,
99 const WCHAR
*version
, unsigned int *len
)
101 static const WCHAR fmtW
[] =
102 {'%','s','_','%','s','_','%','s','_','%','s','_','n','o','n','e','_','d','e','a','d','b','e','e','f',0};
103 unsigned int buflen
= sizeof(fmtW
) / sizeof(fmtW
[0]);
106 buflen
+= strlenW( arch
);
107 buflen
+= strlenW( name
);
108 buflen
+= strlenW( token
);
109 buflen
+= strlenW( version
);
110 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, buflen
* sizeof(WCHAR
) ))) return NULL
;
111 *len
= sprintfW( ret
, fmtW
, arch
, name
, token
, version
);
112 for (p
= ret
; *p
; p
++) *p
= tolowerW( *p
);
116 static WCHAR
*build_manifest_path( const WCHAR
*arch
, const WCHAR
*name
, const WCHAR
*token
,
117 const WCHAR
*version
)
119 static const WCHAR fmtW
[] =
120 {'%','s','m','a','n','i','f','e','s','t','s','\\','%','s','.','m','a','n','i','f','e','s','t',0};
121 WCHAR
*path
= NULL
, *ret
, sxsdir
[MAX_PATH
];
124 if (!(path
= build_assembly_name( arch
, name
, token
, version
, &len
))) return NULL
;
125 len
+= sizeof(fmtW
) / sizeof(fmtW
[0]);
126 len
+= build_sxs_path( sxsdir
);
127 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
129 HeapFree( GetProcessHeap(), 0, path
);
132 sprintfW( ret
, fmtW
, sxsdir
, path
);
133 HeapFree( GetProcessHeap(), 0, path
);
137 static WCHAR
*build_policy_name( const WCHAR
*arch
, const WCHAR
*name
, const WCHAR
*token
,
140 static const WCHAR fmtW
[] =
141 {'%','s','_','%','s','_','%','s','_','n','o','n','e','_','d','e','a','d','b','e','e','f',0};
142 unsigned int buflen
= sizeof(fmtW
) / sizeof(fmtW
[0]);
145 buflen
+= strlenW( arch
);
146 buflen
+= strlenW( name
);
147 buflen
+= strlenW( token
);
148 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, buflen
* sizeof(WCHAR
) ))) return NULL
;
149 *len
= sprintfW( ret
, fmtW
, arch
, name
, token
);
150 for (p
= ret
; *p
; p
++) *p
= tolowerW( *p
);
154 static WCHAR
*build_policy_path( const WCHAR
*arch
, const WCHAR
*name
, const WCHAR
*token
,
155 const WCHAR
*version
)
157 static const WCHAR fmtW
[] =
158 {'%','s','p','o','l','i','c','i','e','s','\\','%','s','\\','%','s','.','p','o','l','i','c','y',0};
159 WCHAR
*path
= NULL
, *ret
, sxsdir
[MAX_PATH
];
162 if (!(path
= build_policy_name( arch
, name
, token
, &len
))) return NULL
;
163 len
+= sizeof(fmtW
) / sizeof(fmtW
[0]);
164 len
+= build_sxs_path( sxsdir
);
165 len
+= strlenW( version
);
166 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
168 HeapFree( GetProcessHeap(), 0, path
);
171 sprintfW( ret
, fmtW
, sxsdir
, path
, version
);
172 HeapFree( GetProcessHeap(), 0, path
);
176 static void cache_lock( struct cache
*cache
)
178 WaitForSingleObject( cache
->lock
, INFINITE
);
181 static void cache_unlock( struct cache
*cache
)
183 ReleaseMutex( cache
->lock
);
186 #define ASSEMBLYINFO_FLAG_INSTALLED 1
188 static HRESULT WINAPI
cache_QueryAssemblyInfo(
189 IAssemblyCache
*iface
,
191 LPCWSTR assembly_name
,
192 ASSEMBLY_INFO
*info
)
194 struct cache
*cache
= impl_from_IAssemblyCache( iface
);
195 IAssemblyName
*name_obj
;
196 const WCHAR
*arch
, *name
, *token
, *type
, *version
;
197 WCHAR
*p
, *path
= NULL
;
201 TRACE("%p, 0x%08x, %s, %p\n", iface
, flags
, debugstr_w(assembly_name
), info
);
203 if (flags
|| (info
&& info
->cbAssemblyInfo
!= sizeof(*info
)))
206 hr
= CreateAssemblyNameObject( &name_obj
, assembly_name
, CANOF_PARSE_DISPLAY_NAME
, 0 );
210 arch
= get_name_attribute( name_obj
, NAME_ATTR_ID_ARCH
);
211 name
= get_name_attribute( name_obj
, NAME_ATTR_ID_NAME
);
212 token
= get_name_attribute( name_obj
, NAME_ATTR_ID_TOKEN
);
213 type
= get_name_attribute( name_obj
, NAME_ATTR_ID_TYPE
);
214 version
= get_name_attribute( name_obj
, NAME_ATTR_ID_VERSION
);
215 if (!arch
|| !name
|| !token
|| !type
|| !version
)
217 IAssemblyName_Release( name_obj
);
218 return HRESULT_FROM_WIN32( ERROR_SXS_MISSING_ASSEMBLY_IDENTITY_ATTRIBUTE
);
222 IAssemblyName_Release( name_obj
);
227 if (!strcmpW( type
, win32W
)) path
= build_manifest_path( arch
, name
, token
, version
);
228 else if (!strcmpW( type
, win32_policyW
)) path
= build_policy_path( arch
, name
, token
, version
);
231 hr
= HRESULT_FROM_WIN32( ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE
);
240 if (GetFileAttributesW( path
) != INVALID_FILE_ATTRIBUTES
) /* FIXME: better check */
242 info
->dwAssemblyFlags
= ASSEMBLYINFO_FLAG_INSTALLED
;
243 TRACE("assembly is installed\n");
245 if ((p
= strrchrW( path
, '\\' ))) *p
= 0;
246 len
= strlenW( path
) + 1;
247 if (info
->pszCurrentAssemblyPathBuf
)
249 if (info
->cchBuf
< len
)
252 hr
= HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER
);
254 else strcpyW( info
->pszCurrentAssemblyPathBuf
, path
);
258 HeapFree( GetProcessHeap(), 0, path
);
259 IAssemblyName_Release( name_obj
);
260 cache_unlock( cache
);
264 static HRESULT WINAPI
cache_CreateAssemblyCacheItem(
265 IAssemblyCache
*iface
,
268 IAssemblyCacheItem
**item
,
271 FIXME("%p, 0x%08x, %p, %p, %s\n", iface
, flags
, reserved
, item
, debugstr_w(name
));
275 static HRESULT WINAPI
cache_Reserved(
276 IAssemblyCache
*iface
,
279 FIXME("%p\n", reserved
);
283 static BSTR
get_attribute_value( IXMLDOMNamedNodeMap
*map
, const WCHAR
*value_name
)
290 str
= SysAllocString( value_name
);
291 hr
= IXMLDOMNamedNodeMap_getNamedItem( map
, str
, &attr
);
292 SysFreeString( str
);
293 if (hr
!= S_OK
) return NULL
;
295 hr
= IXMLDOMNode_get_nodeValue( attr
, &var
);
296 IXMLDOMNode_Release( attr
);
297 if (hr
!= S_OK
) return NULL
;
298 if (V_VT(&var
) != VT_BSTR
)
300 VariantClear( &var
);
303 TRACE("%s=%s\n", debugstr_w(value_name
), debugstr_w(V_BSTR( &var
)));
304 return V_BSTR( &var
);
323 static void free_assembly( struct assembly
*assembly
)
325 struct list
*item
, *cursor
;
327 if (!assembly
) return;
328 SysFreeString( assembly
->type
);
329 SysFreeString( assembly
->name
);
330 SysFreeString( assembly
->version
);
331 SysFreeString( assembly
->arch
);
332 SysFreeString( assembly
->token
);
333 LIST_FOR_EACH_SAFE( item
, cursor
, &assembly
->files
)
335 struct file
*file
= LIST_ENTRY( item
, struct file
, entry
);
336 list_remove( &file
->entry
);
337 SysFreeString( file
->name
);
338 HeapFree( GetProcessHeap(), 0, file
);
340 HeapFree( GetProcessHeap(), 0, assembly
);
343 static HRESULT
parse_files( IXMLDOMDocument
*doc
, struct assembly
*assembly
)
345 static const WCHAR fileW
[] = {'f','i','l','e',0};
346 static const WCHAR nameW
[] = {'n','a','m','e',0};
347 IXMLDOMNamedNodeMap
*attrs
;
348 IXMLDOMNodeList
*list
;
355 str
= SysAllocString( fileW
);
356 hr
= IXMLDOMDocument_getElementsByTagName( doc
, str
, &list
);
357 SysFreeString( str
);
358 if (hr
!= S_OK
) return hr
;
360 hr
= IXMLDOMNodeList_get_length( list
, &len
);
361 if (hr
!= S_OK
) goto done
;
362 TRACE("found %d files\n", len
);
365 hr
= ERROR_SXS_MANIFEST_FORMAT_ERROR
;
371 hr
= IXMLDOMNodeList_nextNode( list
, &node
);
372 if (hr
!= S_OK
|| !node
)
378 /* FIXME: validate node type */
380 hr
= IXMLDOMNode_get_attributes( node
, &attrs
);
381 IXMLDOMNode_Release( node
);
385 if (!(f
= HeapAlloc( GetProcessHeap(), 0, sizeof(struct file
) )))
387 IXMLDOMNamedNodeMap_Release( attrs
);
392 f
->name
= get_attribute_value( attrs
, nameW
);
393 IXMLDOMNamedNodeMap_Release( attrs
);
396 HeapFree( GetProcessHeap(), 0, f
);
397 hr
= ERROR_SXS_MANIFEST_FORMAT_ERROR
;
400 list_add_tail( &assembly
->files
, &f
->entry
);
403 if (list_empty( &assembly
->files
))
405 WARN("no files found\n");
406 hr
= ERROR_SXS_MANIFEST_FORMAT_ERROR
;
410 IXMLDOMNodeList_Release( list
);
414 static HRESULT
parse_assembly( IXMLDOMDocument
*doc
, struct assembly
**assembly
)
416 static const WCHAR identityW
[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
417 static const WCHAR typeW
[] = {'t','y','p','e',0};
418 static const WCHAR nameW
[] = {'n','a','m','e',0};
419 static const WCHAR versionW
[] = {'v','e','r','s','i','o','n',0};
420 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};
421 static const WCHAR tokenW
[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
422 IXMLDOMNodeList
*list
= NULL
;
423 IXMLDOMNode
*node
= NULL
;
424 IXMLDOMNamedNodeMap
*attrs
= NULL
;
425 struct assembly
*a
= NULL
;
430 str
= SysAllocString( identityW
);
431 hr
= IXMLDOMDocument_getElementsByTagName( doc
, str
, &list
);
432 SysFreeString( str
);
433 if (hr
!= S_OK
) goto done
;
435 hr
= IXMLDOMNodeList_get_length( list
, &len
);
436 if (hr
!= S_OK
) goto done
;
439 hr
= ERROR_SXS_MANIFEST_FORMAT_ERROR
;
442 hr
= IXMLDOMNodeList_nextNode( list
, &node
);
443 if (hr
!= S_OK
) goto done
;
446 hr
= ERROR_SXS_MANIFEST_FORMAT_ERROR
;
449 if (!(a
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct assembly
) )))
454 list_init( &a
->files
);
456 hr
= IXMLDOMNode_get_attributes( node
, &attrs
);
457 if (hr
!= S_OK
) goto done
;
459 a
->type
= get_attribute_value( attrs
, typeW
);
460 a
->name
= get_attribute_value( attrs
, nameW
);
461 a
->version
= get_attribute_value( attrs
, versionW
);
462 a
->arch
= get_attribute_value( attrs
, architectureW
);
463 a
->token
= get_attribute_value( attrs
, tokenW
);
465 if (!a
->type
|| (strcmpW( a
->type
, win32W
) && strcmpW( a
->type
, win32_policyW
)) ||
466 !a
->name
|| !a
->version
|| !a
->arch
|| !a
->token
)
468 WARN("invalid win32 assembly\n");
469 hr
= ERROR_SXS_MANIFEST_FORMAT_ERROR
;
472 if (!strcmpW( a
->type
, win32W
)) hr
= parse_files( doc
, a
);
475 if (attrs
) IXMLDOMNamedNodeMap_Release( attrs
);
476 if (node
) IXMLDOMNode_Release( node
);
477 if (list
) IXMLDOMNodeList_Release( list
);
478 if (hr
== S_OK
) *assembly
= a
;
479 else free_assembly( a
);
483 static WCHAR
*build_policy_filename( const WCHAR
*arch
, const WCHAR
*name
, const WCHAR
*token
,
484 const WCHAR
*version
)
486 static const WCHAR policiesW
[] = {'p','o','l','i','c','i','e','s','\\',0};
487 static const WCHAR suffixW
[] = {'.','p','o','l','i','c','y',0};
488 WCHAR sxsdir
[MAX_PATH
], *ret
, *fullname
;
491 if (!(fullname
= build_policy_name( arch
, name
, token
, &len
))) return NULL
;
492 len
+= build_sxs_path( sxsdir
);
493 len
+= sizeof(policiesW
) / sizeof(policiesW
[0]) - 1;
494 len
+= strlenW( version
);
495 len
+= sizeof(suffixW
) / sizeof(suffixW
[0]) - 1;
496 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
) )))
498 HeapFree( GetProcessHeap(), 0, fullname
);
501 strcpyW( ret
, sxsdir
);
502 strcatW( ret
, policiesW
);
503 CreateDirectoryW( ret
, NULL
);
504 strcatW( ret
, name
);
505 CreateDirectoryW( ret
, NULL
);
506 strcatW( ret
, backslashW
);
507 strcatW( ret
, version
);
508 strcatW( ret
, suffixW
);
510 HeapFree( GetProcessHeap(), 0, fullname
);
514 static HRESULT
install_policy( const WCHAR
*manifest
, struct assembly
*assembly
)
519 /* FIXME: handle catalog file */
521 dst
= build_policy_filename( assembly
->arch
, assembly
->name
, assembly
->token
, assembly
->version
);
522 if (!dst
) return E_OUTOFMEMORY
;
524 ret
= CopyFileW( manifest
, dst
, FALSE
);
525 HeapFree( GetProcessHeap(), 0, dst
);
528 HRESULT hr
= HRESULT_FROM_WIN32( GetLastError() );
529 WARN("failed to copy policy manifest file 0x%08x\n", hr
);
535 static WCHAR
*build_source_filename( const WCHAR
*manifest
, struct file
*file
)
541 p
= strrchrW( manifest
, '\\' );
542 if (!p
) p
= strrchrW( manifest
, '/' );
543 if (!p
) return strdupW( manifest
);
545 len
= p
- manifest
+ 1;
546 if (!(src
= HeapAlloc( GetProcessHeap(), 0, (len
+ strlenW( file
->name
) + 1) * sizeof(WCHAR
) )))
549 memcpy( src
, manifest
, len
* sizeof(WCHAR
) );
550 strcpyW( src
+ len
, file
->name
);
554 static WCHAR
*build_manifest_filename( const WCHAR
*arch
, const WCHAR
*name
, const WCHAR
*token
,
555 const WCHAR
*version
)
557 static const WCHAR manifestsW
[] = {'m','a','n','i','f','e','s','t','s','\\',0};
558 static const WCHAR suffixW
[] = {'.','m','a','n','i','f','e','s','t',0};
559 WCHAR sxsdir
[MAX_PATH
], *ret
, *fullname
;
562 if (!(fullname
= build_assembly_name( arch
, name
, token
, version
, &len
))) return NULL
;
563 len
+= build_sxs_path( sxsdir
);
564 len
+= sizeof(manifestsW
) / sizeof(manifestsW
[0]) - 1;
565 len
+= sizeof(suffixW
) / sizeof(suffixW
[0]) - 1;
566 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
) )))
568 HeapFree( GetProcessHeap(), 0, fullname
);
571 strcpyW( ret
, sxsdir
);
572 strcatW( ret
, manifestsW
);
573 strcatW( ret
, fullname
);
574 strcatW( ret
, suffixW
);
576 HeapFree( GetProcessHeap(), 0, fullname
);
580 static HRESULT
load_manifest( IXMLDOMDocument
*doc
, const WCHAR
*filename
)
587 str
= SysAllocString( filename
);
589 V_VT( &var
) = VT_BSTR
;
590 V_BSTR( &var
) = str
;
591 hr
= IXMLDOMDocument_load( doc
, var
, &b
);
592 SysFreeString( str
);
593 if (hr
!= S_OK
) return hr
;
596 WARN("failed to load manifest\n");
602 static HRESULT
install_assembly( const WCHAR
*manifest
, struct assembly
*assembly
)
604 WCHAR sxsdir
[MAX_PATH
], *p
, *name
, *dst
, *src
;
605 unsigned int len
, len_name
, len_sxsdir
= build_sxs_path( sxsdir
);
607 HRESULT hr
= E_OUTOFMEMORY
;
610 dst
= build_manifest_filename( assembly
->arch
, assembly
->name
, assembly
->token
, assembly
->version
);
611 if (!dst
) return E_OUTOFMEMORY
;
613 ret
= CopyFileW( manifest
, dst
, FALSE
);
614 HeapFree( GetProcessHeap(), 0, dst
);
617 hr
= HRESULT_FROM_WIN32( GetLastError() );
618 WARN("failed to copy manifest file 0x%08x\n", hr
);
622 name
= build_assembly_name( assembly
->arch
, assembly
->name
, assembly
->token
, assembly
->version
,
624 if (!name
) return E_OUTOFMEMORY
;
626 /* FIXME: this should be a transaction */
627 LIST_FOR_EACH_ENTRY( file
, &assembly
->files
, struct file
, entry
)
629 if (!(src
= build_source_filename( manifest
, file
))) goto done
;
631 len
= len_sxsdir
+ len_name
+ strlenW( file
->name
);
632 if (!(dst
= HeapAlloc( GetProcessHeap(), 0, (len
+ 2) * sizeof(WCHAR
) )))
634 HeapFree( GetProcessHeap(), 0, src
);
637 strcpyW( dst
, sxsdir
);
638 strcatW( dst
, name
);
639 CreateDirectoryW( dst
, NULL
);
641 strcatW( dst
, backslashW
);
642 strcatW( dst
, file
->name
);
643 for (p
= dst
; *p
; p
++) *p
= tolowerW( *p
);
645 ret
= CopyFileW( src
, dst
, FALSE
);
646 HeapFree( GetProcessHeap(), 0, src
);
647 HeapFree( GetProcessHeap(), 0, dst
);
650 hr
= HRESULT_FROM_WIN32( GetLastError() );
651 WARN("failed to copy file 0x%08x\n", hr
);
658 HeapFree( GetProcessHeap(), 0, name
);
662 static HRESULT WINAPI
cache_InstallAssembly(
663 IAssemblyCache
*iface
,
666 LPCFUSION_INSTALL_REFERENCE ref
)
668 struct cache
*cache
= impl_from_IAssemblyCache( iface
);
670 IXMLDOMDocument
*doc
= NULL
;
671 struct assembly
*assembly
= NULL
;
673 TRACE("%p, 0x%08x, %s, %p\n", iface
, flags
, debugstr_w(path
), ref
);
676 init
= CoInitialize( NULL
);
678 hr
= CoCreateInstance( &CLSID_DOMDocument
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IXMLDOMDocument
, (void **)&doc
);
682 if ((hr
= load_manifest( doc
, path
)) != S_OK
) goto done
;
683 if ((hr
= parse_assembly( doc
, &assembly
)) != S_OK
) goto done
;
685 /* FIXME: verify name attributes */
687 if (!strcmpW( assembly
->type
, win32_policyW
))
688 hr
= install_policy( path
, assembly
);
690 hr
= install_assembly( path
, assembly
);
693 free_assembly( assembly
);
694 if (doc
) IXMLDOMDocument_Release( doc
);
695 if (SUCCEEDED(init
)) CoUninitialize();
696 cache_unlock( cache
);
700 static HRESULT
uninstall_assembly( struct assembly
*assembly
)
702 WCHAR sxsdir
[MAX_PATH
], *name
, *dirname
, *filename
;
703 unsigned int len
, len_name
, len_sxsdir
= build_sxs_path( sxsdir
);
704 HRESULT hr
= E_OUTOFMEMORY
;
707 name
= build_assembly_name( assembly
->arch
, assembly
->name
, assembly
->token
, assembly
->version
,
709 if (!name
) return E_OUTOFMEMORY
;
710 if (!(dirname
= HeapAlloc( GetProcessHeap(), 0, (len_sxsdir
+ len_name
+ 1) * sizeof(WCHAR
) )))
712 strcpyW( dirname
, sxsdir
);
713 strcpyW( dirname
+ len_sxsdir
, name
);
715 LIST_FOR_EACH_ENTRY( file
, &assembly
->files
, struct file
, entry
)
717 len
= len_sxsdir
+ len_name
+ 1 + strlenW( file
->name
);
718 if (!(filename
= HeapAlloc( GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
) ))) goto done
;
719 strcpyW( filename
, dirname
);
720 strcatW( filename
, backslashW
);
721 strcatW( filename
, file
->name
);
723 if (!DeleteFileW( filename
)) WARN( "failed to delete file %u\n", GetLastError() );
724 HeapFree( GetProcessHeap(), 0, filename
);
726 RemoveDirectoryW( dirname
);
730 HeapFree( GetProcessHeap(), 0, dirname
);
731 HeapFree( GetProcessHeap(), 0, name
);
735 static HRESULT WINAPI
cache_UninstallAssembly(
736 IAssemblyCache
*iface
,
738 LPCWSTR assembly_name
,
739 LPCFUSION_INSTALL_REFERENCE ref
,
742 struct cache
*cache
= impl_from_IAssemblyCache( iface
);
744 IXMLDOMDocument
*doc
= NULL
;
745 struct assembly
*assembly
= NULL
;
746 IAssemblyName
*name_obj
= NULL
;
747 const WCHAR
*arch
, *name
, *token
, *type
, *version
;
748 WCHAR
*p
, *path
= NULL
;
750 TRACE("%p, 0x%08x, %s, %p, %p\n", iface
, flags
, debugstr_w(assembly_name
), ref
, disp
);
754 FIXME("application reference not supported\n");
758 init
= CoInitialize( NULL
);
760 hr
= CreateAssemblyNameObject( &name_obj
, assembly_name
, CANOF_PARSE_DISPLAY_NAME
, NULL
);
764 arch
= get_name_attribute( name_obj
, NAME_ATTR_ID_ARCH
);
765 name
= get_name_attribute( name_obj
, NAME_ATTR_ID_NAME
);
766 token
= get_name_attribute( name_obj
, NAME_ATTR_ID_TOKEN
);
767 type
= get_name_attribute( name_obj
, NAME_ATTR_ID_TYPE
);
768 version
= get_name_attribute( name_obj
, NAME_ATTR_ID_VERSION
);
769 if (!arch
|| !name
|| !token
|| !type
|| !version
)
774 if (!strcmpW( type
, win32W
)) path
= build_manifest_filename( arch
, name
, token
, version
);
775 else if (!strcmpW( type
, win32_policyW
)) path
= build_policy_filename( arch
, name
, token
, version
);
782 hr
= CoCreateInstance( &CLSID_DOMDocument
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IXMLDOMDocument
, (void **)&doc
);
786 if ((hr
= load_manifest( doc
, path
)) != S_OK
) goto done
;
787 if ((hr
= parse_assembly( doc
, &assembly
)) != S_OK
) goto done
;
789 if (!DeleteFileW( path
)) WARN( "unable to remove manifest file %u\n", GetLastError() );
790 else if ((p
= strrchrW( path
, '\\' )))
793 RemoveDirectoryW( path
);
795 if (!strcmpW( assembly
->type
, win32W
)) hr
= uninstall_assembly( assembly
);
798 if (name_obj
) IAssemblyName_Release( name_obj
);
799 HeapFree( GetProcessHeap(), 0, path
);
800 free_assembly( assembly
);
801 if (doc
) IXMLDOMDocument_Release( doc
);
802 if (SUCCEEDED(init
)) CoUninitialize();
803 cache_unlock( cache
);
807 static const IAssemblyCacheVtbl cache_vtbl
=
809 cache_QueryInterface
,
812 cache_UninstallAssembly
,
813 cache_QueryAssemblyInfo
,
814 cache_CreateAssemblyCacheItem
,
816 cache_InstallAssembly
819 /******************************************************************
820 * CreateAssemblyCache (SXS.@)
822 HRESULT WINAPI
CreateAssemblyCache( IAssemblyCache
**obj
, DWORD reserved
)
826 TRACE("%p, %u\n", obj
, reserved
);
833 cache
= HeapAlloc( GetProcessHeap(), 0, sizeof(struct cache
) );
835 return E_OUTOFMEMORY
;
837 cache
->IAssemblyCache_iface
.lpVtbl
= &cache_vtbl
;
839 cache
->lock
= CreateMutexW( NULL
, FALSE
, cache_mutex_nameW
);
842 HeapFree( GetProcessHeap(), 0, cache
);
843 return HRESULT_FROM_WIN32( GetLastError() );
845 *obj
= &cache
->IAssemblyCache_iface
;