win32u: Use KBDTABLES for NtUserVkKeyScanEx.
[wine.git] / dlls / sxs / cache.c
bloba924a359700b0622827964308fa9c929a2ce0c7c
1 /*
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 <stdarg.h>
23 #define COBJMACROS
24 #define INITGUID
26 #include "windef.h"
27 #include "winbase.h"
28 #include "ole2.h"
29 #include "winsxs.h"
30 #include "msxml2.h"
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};
45 struct cache
47 IAssemblyCache IAssemblyCache_iface;
48 LONG refs;
49 HANDLE lock;
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,
59 REFIID riid,
60 void **ret_iface )
62 TRACE("%p, %s, %p\n", iface, debugstr_guid(riid), ret_iface);
64 *ret_iface = NULL;
66 if (IsEqualIID(riid, &IID_IUnknown) ||
67 IsEqualIID(riid, &IID_IAssemblyCache))
69 IAssemblyCache_AddRef( iface );
70 *ret_iface = iface;
71 return S_OK;
74 return E_NOINTERFACE;
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 );
88 if (!refs)
90 TRACE("destroying %p\n", cache);
91 CloseHandle( cache->lock );
92 free( cache );
94 return refs;
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);
112 WCHAR *ret;
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];
127 unsigned int len;
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) )))
133 free( path );
134 return NULL;
136 lstrcpyW( ret, sxsdir );
137 lstrcatW( ret, path );
138 lstrcatW( ret, L"\\" );
139 free( path );
140 return ret;
143 static WCHAR *build_policy_name( const WCHAR *arch, const WCHAR *name, const WCHAR *token,
144 unsigned int *len )
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);
149 WCHAR *ret;
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];
165 unsigned int len;
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) )))
173 free( path );
174 return NULL;
176 swprintf( ret, len, fmtW, sxsdir, path, version );
177 free( path );
178 return ret;
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,
195 DWORD flags,
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;
202 WCHAR *path = NULL;
203 unsigned int len;
204 HRESULT hr;
206 TRACE("%p, 0x%08lx, %s, %p\n", iface, flags, debugstr_w(assembly_name), info);
208 if (flags || (info && info->cbAssemblyInfo != sizeof(*info)))
209 return E_INVALIDARG;
211 hr = CreateAssemblyNameObject( &name_obj, assembly_name, CANOF_PARSE_DISPLAY_NAME, 0 );
212 if (FAILED( hr ))
213 return hr;
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 );
225 if (!info)
227 IAssemblyName_Release( name_obj );
228 return S_OK;
230 cache_lock( cache );
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 );
234 else
236 hr = HRESULT_FROM_WIN32( ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE );
237 goto done;
239 if (!path)
241 hr = E_OUTOFMEMORY;
242 goto done;
244 hr = S_OK;
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)
255 info->cchBuf = len;
256 hr = HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER );
258 else lstrcpyW( info->pszCurrentAssemblyPathBuf, path );
261 done:
262 free( path );
263 IAssemblyName_Release( name_obj );
264 cache_unlock( cache );
265 return hr;
268 static HRESULT WINAPI cache_CreateAssemblyCacheItem(
269 IAssemblyCache *iface,
270 DWORD flags,
271 PVOID reserved,
272 IAssemblyCacheItem **item,
273 LPCWSTR name )
275 FIXME("%p, 0x%08lx, %p, %p, %s\n", iface, flags, reserved, item, debugstr_w(name));
276 return E_NOTIMPL;
279 static HRESULT WINAPI cache_Reserved(
280 IAssemblyCache *iface,
281 IUnknown **reserved)
283 FIXME("%p\n", reserved);
284 return E_NOTIMPL;
287 static BSTR get_attribute_value( IXMLDOMNamedNodeMap *map, const WCHAR *value_name )
289 HRESULT hr;
290 IXMLDOMNode *attr;
291 VARIANT var;
292 BSTR str;
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 );
305 return NULL;
307 TRACE("%s=%s\n", debugstr_w(value_name), debugstr_w(V_BSTR( &var )));
308 return V_BSTR( &var );
311 struct file
313 struct list entry;
314 BSTR name;
317 struct assembly
319 BSTR type;
320 BSTR name;
321 BSTR version;
322 BSTR arch;
323 BSTR token;
324 struct list files;
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 );
342 free( file );
344 free( assembly );
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;
353 IXMLDOMNode *node;
354 struct file *f;
355 BSTR str;
356 HRESULT hr;
357 LONG len;
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);
367 if (!len)
369 hr = ERROR_SXS_MANIFEST_FORMAT_ERROR;
370 goto done;
373 for (;;)
375 hr = IXMLDOMNodeList_nextNode( list, &node );
376 if (hr != S_OK || !node)
378 hr = S_OK;
379 break;
382 /* FIXME: validate node type */
384 hr = IXMLDOMNode_get_attributes( node, &attrs );
385 IXMLDOMNode_Release( node );
386 if (hr != S_OK)
387 goto done;
389 if (!(f = malloc( sizeof(*f) )))
391 IXMLDOMNamedNodeMap_Release( attrs );
392 hr = E_OUTOFMEMORY;
393 goto done;
396 f->name = get_attribute_value( attrs, nameW );
397 IXMLDOMNamedNodeMap_Release( attrs );
398 if (!f->name)
400 free( f );
401 hr = ERROR_SXS_MANIFEST_FORMAT_ERROR;
402 goto done;
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;
413 done:
414 IXMLDOMNodeList_Release( list );
415 return hr;
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;
430 BSTR str;
431 HRESULT hr;
432 LONG len;
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;
441 if (!len)
443 hr = ERROR_SXS_MANIFEST_FORMAT_ERROR;
444 goto done;
446 hr = IXMLDOMNodeList_nextNode( list, &node );
447 if (hr != S_OK) goto done;
448 if (!node)
450 hr = ERROR_SXS_MANIFEST_FORMAT_ERROR;
451 goto done;
453 if (!(a = calloc(1, sizeof(*a) )))
455 hr = E_OUTOFMEMORY;
456 goto done;
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;
474 goto done;
476 if (!wcscmp( a->type, win32W )) hr = parse_files( doc, a );
478 done:
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 );
484 return hr;
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;
493 unsigned int len;
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) )))
502 free( fullname );
503 return NULL;
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 );
514 free( fullname );
515 return ret;
518 static HRESULT install_policy( const WCHAR *manifest, struct assembly *assembly )
520 WCHAR *dst;
521 BOOL ret;
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 );
529 free( dst );
530 if (!ret)
532 HRESULT hr = HRESULT_FROM_WIN32( GetLastError() );
533 WARN("failed to copy policy manifest file 0x%08lx\n", hr);
534 return hr;
536 return S_OK;
539 static WCHAR *build_source_filename( const WCHAR *manifest, struct file *file )
541 WCHAR *src;
542 const WCHAR *p;
543 int len;
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) )))
551 return NULL;
553 memcpy( src, manifest, len * sizeof(WCHAR) );
554 lstrcpyW( src + len, file->name );
555 return src;
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;
564 unsigned int len;
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) )))
572 free( fullname );
573 return NULL;
575 lstrcpyW( ret, sxsdir );
576 lstrcatW( ret, manifestsW );
577 lstrcatW( ret, fullname );
578 lstrcatW( ret, suffixW );
580 free( fullname );
581 return ret;
584 static HRESULT load_manifest( IXMLDOMDocument *doc, const WCHAR *filename )
586 HRESULT hr;
587 VARIANT var;
588 VARIANT_BOOL b;
589 BSTR str;
591 str = SysAllocString( filename );
592 VariantInit( &var );
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;
598 if (!b)
600 WARN("failed to load manifest\n");
601 return S_FALSE;
603 return S_OK;
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 );
610 struct file *file;
611 HRESULT hr = E_OUTOFMEMORY;
612 BOOL ret;
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 );
618 free( dst );
619 if (!ret)
621 hr = HRESULT_FROM_WIN32( GetLastError() );
622 WARN("failed to copy manifest file 0x%08lx\n", hr);
623 return hr;
626 name = build_assembly_name( assembly->arch, assembly->name, assembly->token, assembly->version,
627 &len_name );
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) )))
638 free( src );
639 goto done;
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 );
650 free( src );
651 free( dst );
652 if (!ret)
654 hr = HRESULT_FROM_WIN32( GetLastError() );
655 WARN("failed to copy file 0x%08lx\n", hr);
656 goto done;
659 hr = S_OK;
661 done:
662 free( name );
663 return hr;
666 static HRESULT WINAPI cache_InstallAssembly(
667 IAssemblyCache *iface,
668 DWORD flags,
669 LPCWSTR path,
670 LPCFUSION_INSTALL_REFERENCE ref )
672 struct cache *cache = impl_from_IAssemblyCache( iface );
673 HRESULT hr, init;
674 IXMLDOMDocument *doc = NULL;
675 struct assembly *assembly = NULL;
677 TRACE("%p, 0x%08lx, %s, %p\n", iface, flags, debugstr_w(path), ref);
679 cache_lock( cache );
680 init = CoInitialize( NULL );
682 hr = CoCreateInstance( &CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void **)&doc );
683 if (hr != S_OK)
684 goto done;
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 );
693 else
694 hr = install_assembly( path, assembly );
696 done:
697 free_assembly( assembly );
698 if (doc) IXMLDOMDocument_Release( doc );
699 if (SUCCEEDED(init)) CoUninitialize();
700 cache_unlock( cache );
701 return hr;
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;
709 struct file *file;
711 name = build_assembly_name( assembly->arch, assembly->name, assembly->token, assembly->version,
712 &len_name );
713 if (!name) return E_OUTOFMEMORY;
714 if (!(dirname = malloc( (len_sxsdir + len_name + 1) * sizeof(WCHAR) )))
715 goto done;
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() );
728 free( filename );
730 RemoveDirectoryW( dirname );
731 hr = S_OK;
733 done:
734 free( dirname );
735 free( name );
736 return hr;
739 static HRESULT WINAPI cache_UninstallAssembly(
740 IAssemblyCache *iface,
741 DWORD flags,
742 LPCWSTR assembly_name,
743 LPCFUSION_INSTALL_REFERENCE ref,
744 ULONG *disp )
746 struct cache *cache = impl_from_IAssemblyCache( iface );
747 HRESULT hr, init;
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);
756 if (ref)
758 FIXME("application reference not supported\n");
759 return E_NOTIMPL;
761 cache_lock( cache );
762 init = CoInitialize( NULL );
764 hr = CreateAssemblyNameObject( &name_obj, assembly_name, CANOF_PARSE_DISPLAY_NAME, NULL );
765 if (FAILED( hr ))
766 goto done;
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)
775 hr = E_INVALIDARG;
776 goto done;
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 );
780 else
782 hr = E_INVALIDARG;
783 goto done;
786 hr = CoCreateInstance( &CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void **)&doc );
787 if (hr != S_OK)
788 goto done;
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, '\\' )))
796 *p = 0;
797 RemoveDirectoryW( path );
799 if (!wcscmp( assembly->type, win32W )) hr = uninstall_assembly( assembly );
801 done:
802 if (name_obj) IAssemblyName_Release( name_obj );
803 free( path );
804 free_assembly( assembly );
805 if (doc) IXMLDOMDocument_Release( doc );
806 if (SUCCEEDED(init)) CoUninitialize();
807 cache_unlock( cache );
808 return hr;
811 static const IAssemblyCacheVtbl cache_vtbl =
813 cache_QueryInterface,
814 cache_AddRef,
815 cache_Release,
816 cache_UninstallAssembly,
817 cache_QueryAssemblyInfo,
818 cache_CreateAssemblyCacheItem,
819 cache_Reserved,
820 cache_InstallAssembly
823 /******************************************************************
824 * CreateAssemblyCache (SXS.@)
826 HRESULT WINAPI CreateAssemblyCache( IAssemblyCache **obj, DWORD reserved )
828 struct cache *cache;
830 TRACE("%p, %lu\n", obj, reserved);
832 if (!obj)
833 return E_INVALIDARG;
835 *obj = NULL;
837 cache = malloc( sizeof(*cache) );
838 if (!cache)
839 return E_OUTOFMEMORY;
841 cache->IAssemblyCache_iface.lpVtbl = &cache_vtbl;
842 cache->refs = 1;
843 cache->lock = CreateMutexW( NULL, FALSE, cache_mutex_nameW );
844 if (!cache->lock)
846 free( cache );
847 return HRESULT_FROM_WIN32( GetLastError() );
849 *obj = &cache->IAssemblyCache_iface;
850 return S_OK;