Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencache.c
Go to the documentation of this file.
00001 /* 00002 * IAssemblyCache implementation 00003 * 00004 * Copyright 2010 Hans Leidekker for CodeWeavers 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include <stdarg.h> 00022 00023 #define COBJMACROS 00024 #define INITGUID 00025 00026 #include "windef.h" 00027 #include "winbase.h" 00028 #include "ole2.h" 00029 #include "winsxs.h" 00030 #include "msxml2.h" 00031 00032 #include "wine/debug.h" 00033 #include "wine/list.h" 00034 #include "wine/unicode.h" 00035 #include "sxs_private.h" 00036 00037 WINE_DEFAULT_DEBUG_CHANNEL(sxs); 00038 00039 static const WCHAR cache_mutex_nameW[] = 00040 {'_','_','W','I','N','E','_','S','X','S','_','C','A','C','H','E','_','M','U','T','E','X','_','_',0}; 00041 00042 static const WCHAR win32W[] = {'w','i','n','3','2',0}; 00043 static const WCHAR win32_policyW[] = {'w','i','n','3','2','-','p','o','l','i','c','y',0}; 00044 static const WCHAR backslashW[] = {'\\',0}; 00045 00046 struct cache 00047 { 00048 IAssemblyCache IAssemblyCache_iface; 00049 LONG refs; 00050 HANDLE lock; 00051 }; 00052 00053 static inline struct cache *impl_from_IAssemblyCache(IAssemblyCache *iface) 00054 { 00055 return CONTAINING_RECORD(iface, struct cache, IAssemblyCache_iface); 00056 } 00057 00058 static HRESULT WINAPI cache_QueryInterface( 00059 IAssemblyCache *iface, 00060 REFIID riid, 00061 void **obj ) 00062 { 00063 struct cache *cache = impl_from_IAssemblyCache(iface); 00064 00065 TRACE("%p, %s, %p\n", cache, debugstr_guid(riid), obj); 00066 00067 *obj = NULL; 00068 00069 if (IsEqualIID(riid, &IID_IUnknown) || 00070 IsEqualIID(riid, &IID_IAssemblyCache)) 00071 { 00072 IUnknown_AddRef( iface ); 00073 *obj = cache; 00074 return S_OK; 00075 } 00076 00077 return E_NOINTERFACE; 00078 } 00079 00080 static ULONG WINAPI cache_AddRef( IAssemblyCache *iface ) 00081 { 00082 struct cache *cache = impl_from_IAssemblyCache(iface); 00083 return InterlockedIncrement( &cache->refs ); 00084 } 00085 00086 static ULONG WINAPI cache_Release( IAssemblyCache *iface ) 00087 { 00088 struct cache *cache = impl_from_IAssemblyCache(iface); 00089 ULONG refs = InterlockedDecrement( &cache->refs ); 00090 00091 if (!refs) 00092 { 00093 TRACE("destroying %p\n", cache); 00094 CloseHandle( cache->lock ); 00095 HeapFree( GetProcessHeap(), 0, cache ); 00096 } 00097 return refs; 00098 } 00099 00100 static unsigned int build_sxs_path( WCHAR *path ) 00101 { 00102 static const WCHAR winsxsW[] = {'\\','w','i','n','s','x','s','\\',0}; 00103 unsigned int len = GetWindowsDirectoryW( path, MAX_PATH ); 00104 00105 memcpy( path + len, winsxsW, sizeof(winsxsW) ); 00106 return len + sizeof(winsxsW) / sizeof(winsxsW[0]) - 1; 00107 } 00108 00109 static WCHAR *build_assembly_name( const WCHAR *arch, const WCHAR *name, const WCHAR *token, 00110 const WCHAR *version, unsigned int *len ) 00111 { 00112 static const WCHAR fmtW[] = 00113 {'%','s','_','%','s','_','%','s','_','%','s','_','n','o','n','e','_','d','e','a','d','b','e','e','f',0}; 00114 unsigned int buflen = sizeof(fmtW) / sizeof(fmtW[0]); 00115 WCHAR *ret, *p; 00116 00117 buflen += strlenW( arch ); 00118 buflen += strlenW( name ); 00119 buflen += strlenW( token ); 00120 buflen += strlenW( version ); 00121 if (!(ret = HeapAlloc( GetProcessHeap(), 0, buflen * sizeof(WCHAR) ))) return NULL; 00122 *len = sprintfW( ret, fmtW, arch, name, token, version ); 00123 for (p = ret; *p; p++) *p = tolowerW( *p ); 00124 return ret; 00125 } 00126 00127 static WCHAR *build_manifest_path( const WCHAR *arch, const WCHAR *name, const WCHAR *token, 00128 const WCHAR *version ) 00129 { 00130 static const WCHAR fmtW[] = 00131 {'%','s','m','a','n','i','f','e','s','t','s','\\','%','s','.','m','a','n','i','f','e','s','t',0}; 00132 WCHAR *path = NULL, *ret, sxsdir[MAX_PATH]; 00133 unsigned int len; 00134 00135 if (!(path = build_assembly_name( arch, name, token, version, &len ))) return NULL; 00136 len += sizeof(fmtW) / sizeof(fmtW[0]); 00137 len += build_sxs_path( sxsdir ); 00138 if (!(ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) 00139 { 00140 HeapFree( GetProcessHeap(), 0, path ); 00141 return NULL; 00142 } 00143 sprintfW( ret, fmtW, sxsdir, path ); 00144 HeapFree( GetProcessHeap(), 0, path ); 00145 return ret; 00146 } 00147 00148 static WCHAR *build_policy_name( const WCHAR *arch, const WCHAR *name, const WCHAR *token, 00149 unsigned int *len ) 00150 { 00151 static const WCHAR fmtW[] = 00152 {'%','s','_','%','s','_','%','s','_','n','o','n','e','_','d','e','a','d','b','e','e','f',0}; 00153 unsigned int buflen = sizeof(fmtW) / sizeof(fmtW[0]); 00154 WCHAR *ret, *p; 00155 00156 buflen += strlenW( arch ); 00157 buflen += strlenW( name ); 00158 buflen += strlenW( token ); 00159 if (!(ret = HeapAlloc( GetProcessHeap(), 0, buflen * sizeof(WCHAR) ))) return NULL; 00160 *len = sprintfW( ret, fmtW, arch, name, token ); 00161 for (p = ret; *p; p++) *p = tolowerW( *p ); 00162 return ret; 00163 } 00164 00165 static WCHAR *build_policy_path( const WCHAR *arch, const WCHAR *name, const WCHAR *token, 00166 const WCHAR *version ) 00167 { 00168 static const WCHAR fmtW[] = 00169 {'%','s','p','o','l','i','c','i','e','s','\\','%','s','\\','%','s','.','p','o','l','i','c','y',0}; 00170 WCHAR *path = NULL, *ret, sxsdir[MAX_PATH]; 00171 unsigned int len; 00172 00173 if (!(path = build_policy_name( arch, name, token, &len ))) return NULL; 00174 len += sizeof(fmtW) / sizeof(fmtW[0]); 00175 len += build_sxs_path( sxsdir ); 00176 len += strlenW( version ); 00177 if (!(ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) 00178 { 00179 HeapFree( GetProcessHeap(), 0, path ); 00180 return NULL; 00181 } 00182 sprintfW( ret, fmtW, sxsdir, path, version ); 00183 HeapFree( GetProcessHeap(), 0, path ); 00184 return ret; 00185 } 00186 00187 static void cache_lock( struct cache *cache ) 00188 { 00189 WaitForSingleObject( cache->lock, INFINITE ); 00190 } 00191 00192 static void cache_unlock( struct cache *cache ) 00193 { 00194 ReleaseMutex( cache->lock ); 00195 } 00196 00197 #define ASSEMBLYINFO_FLAG_INSTALLED 1 00198 00199 static HRESULT WINAPI cache_QueryAssemblyInfo( 00200 IAssemblyCache *iface, 00201 DWORD flags, 00202 LPCWSTR assembly_name, 00203 ASSEMBLY_INFO *info ) 00204 { 00205 struct cache *cache = impl_from_IAssemblyCache( iface ); 00206 IAssemblyName *name_obj; 00207 const WCHAR *arch, *name, *token, *type, *version; 00208 WCHAR *p, *path = NULL; 00209 unsigned int len; 00210 HRESULT hr; 00211 00212 TRACE("%p, 0x%08x, %s, %p\n", iface, flags, debugstr_w(assembly_name), info); 00213 00214 if (flags || (info && info->cbAssemblyInfo != sizeof(*info))) 00215 return E_INVALIDARG; 00216 00217 hr = CreateAssemblyNameObject( &name_obj, assembly_name, CANOF_PARSE_DISPLAY_NAME, 0 ); 00218 if (FAILED( hr )) 00219 return hr; 00220 00221 arch = get_name_attribute( name_obj, NAME_ATTR_ID_ARCH ); 00222 name = get_name_attribute( name_obj, NAME_ATTR_ID_NAME ); 00223 token = get_name_attribute( name_obj, NAME_ATTR_ID_TOKEN ); 00224 type = get_name_attribute( name_obj, NAME_ATTR_ID_TYPE ); 00225 version = get_name_attribute( name_obj, NAME_ATTR_ID_VERSION ); 00226 if (!arch || !name || !token || !type || !version) 00227 { 00228 IAssemblyName_Release( name_obj ); 00229 return HRESULT_FROM_WIN32( ERROR_SXS_MISSING_ASSEMBLY_IDENTITY_ATTRIBUTE ); 00230 } 00231 if (!info) 00232 { 00233 IAssemblyName_Release( name_obj ); 00234 return S_OK; 00235 } 00236 cache_lock( cache ); 00237 00238 if (!strcmpW( type, win32W )) path = build_manifest_path( arch, name, token, version ); 00239 else if (!strcmpW( type, win32_policyW )) path = build_policy_path( arch, name, token, version ); 00240 else 00241 { 00242 hr = HRESULT_FROM_WIN32( ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE ); 00243 goto done; 00244 } 00245 if (!path) 00246 { 00247 hr = E_OUTOFMEMORY; 00248 goto done; 00249 } 00250 hr = S_OK; 00251 if (GetFileAttributesW( path ) != INVALID_FILE_ATTRIBUTES) /* FIXME: better check */ 00252 { 00253 info->dwAssemblyFlags = ASSEMBLYINFO_FLAG_INSTALLED; 00254 TRACE("assembly is installed\n"); 00255 } 00256 if ((p = strrchrW( path, '\\' ))) *p = 0; 00257 len = strlenW( path ) + 1; 00258 if (info->pszCurrentAssemblyPathBuf) 00259 { 00260 if (info->cchBuf < len) 00261 { 00262 info->cchBuf = len; 00263 hr = HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ); 00264 } 00265 else strcpyW( info->pszCurrentAssemblyPathBuf, path ); 00266 } 00267 00268 done: 00269 HeapFree( GetProcessHeap(), 0, path ); 00270 IAssemblyName_Release( name_obj ); 00271 cache_unlock( cache ); 00272 return hr; 00273 } 00274 00275 static HRESULT WINAPI cache_CreateAssemblyCacheItem( 00276 IAssemblyCache *iface, 00277 DWORD flags, 00278 PVOID reserved, 00279 IAssemblyCacheItem **item, 00280 LPCWSTR name ) 00281 { 00282 FIXME("%p, 0x%08x, %p, %p, %s\n", iface, flags, reserved, item, debugstr_w(name)); 00283 return E_NOTIMPL; 00284 } 00285 00286 static HRESULT WINAPI cache_Reserved( 00287 IAssemblyCache *iface, 00288 IUnknown **reserved) 00289 { 00290 FIXME("%p\n", reserved); 00291 return E_NOTIMPL; 00292 } 00293 00294 static BSTR get_attribute_value( IXMLDOMNamedNodeMap *map, const WCHAR *value_name ) 00295 { 00296 HRESULT hr; 00297 IXMLDOMNode *attr; 00298 VARIANT var; 00299 BSTR str; 00300 00301 str = SysAllocString( value_name ); 00302 hr = IXMLDOMNamedNodeMap_getNamedItem( map, str, &attr ); 00303 SysFreeString( str ); 00304 if (hr != S_OK) return NULL; 00305 00306 hr = IXMLDOMNode_get_nodeValue( attr, &var ); 00307 IXMLDOMNode_Release( attr ); 00308 if (hr != S_OK) return NULL; 00309 if (V_VT(&var) != VT_BSTR) 00310 { 00311 VariantClear( &var ); 00312 return NULL; 00313 } 00314 TRACE("%s=%s\n", debugstr_w(value_name), debugstr_w(V_BSTR( &var ))); 00315 return V_BSTR( &var ); 00316 } 00317 00318 struct file 00319 { 00320 struct list entry; 00321 BSTR name; 00322 }; 00323 00324 struct assembly 00325 { 00326 BSTR type; 00327 BSTR name; 00328 BSTR version; 00329 BSTR arch; 00330 BSTR token; 00331 struct list files; 00332 }; 00333 00334 static void free_assembly( struct assembly *assembly ) 00335 { 00336 struct list *item, *cursor; 00337 00338 if (!assembly) return; 00339 SysFreeString( assembly->type ); 00340 SysFreeString( assembly->name ); 00341 SysFreeString( assembly->version ); 00342 SysFreeString( assembly->arch ); 00343 SysFreeString( assembly->token ); 00344 LIST_FOR_EACH_SAFE( item, cursor, &assembly->files ) 00345 { 00346 struct file *file = LIST_ENTRY( item, struct file, entry ); 00347 list_remove( &file->entry ); 00348 SysFreeString( file->name ); 00349 HeapFree( GetProcessHeap(), 0, file ); 00350 } 00351 HeapFree( GetProcessHeap(), 0, assembly ); 00352 } 00353 00354 static HRESULT parse_files( IXMLDOMDocument *doc, struct assembly *assembly ) 00355 { 00356 static const WCHAR fileW[] = {'f','i','l','e',0}; 00357 static const WCHAR nameW[] = {'n','a','m','e',0}; 00358 IXMLDOMNamedNodeMap *attrs; 00359 IXMLDOMNodeList *list; 00360 IXMLDOMNode *node; 00361 struct file *f; 00362 BSTR str; 00363 HRESULT hr; 00364 LONG len; 00365 00366 str = SysAllocString( fileW ); 00367 hr = IXMLDOMDocument_getElementsByTagName( doc, str, &list ); 00368 SysFreeString( str ); 00369 if (hr != S_OK) return hr; 00370 00371 hr = IXMLDOMNodeList_get_length( list, &len ); 00372 if (hr != S_OK) goto done; 00373 TRACE("found %d files\n", len); 00374 if (!len) 00375 { 00376 hr = ERROR_SXS_MANIFEST_FORMAT_ERROR; 00377 goto done; 00378 } 00379 00380 for (;;) 00381 { 00382 hr = IXMLDOMNodeList_nextNode( list, &node ); 00383 if (hr != S_OK || !node) 00384 { 00385 hr = S_OK; 00386 break; 00387 } 00388 00389 /* FIXME: validate node type */ 00390 00391 hr = IXMLDOMNode_get_attributes( node, &attrs ); 00392 IXMLDOMNode_Release( node ); 00393 if (hr != S_OK) 00394 goto done; 00395 00396 if (!(f = HeapAlloc( GetProcessHeap(), 0, sizeof(struct file) ))) 00397 { 00398 IXMLDOMNamedNodeMap_Release( attrs ); 00399 hr = E_OUTOFMEMORY; 00400 goto done; 00401 } 00402 00403 f->name = get_attribute_value( attrs, nameW ); 00404 IXMLDOMNamedNodeMap_Release( attrs ); 00405 if (!f->name) 00406 { 00407 HeapFree( GetProcessHeap(), 0, f ); 00408 hr = ERROR_SXS_MANIFEST_FORMAT_ERROR; 00409 goto done; 00410 } 00411 list_add_tail( &assembly->files, &f->entry ); 00412 } 00413 00414 if (list_empty( &assembly->files )) 00415 { 00416 WARN("no files found\n"); 00417 hr = ERROR_SXS_MANIFEST_FORMAT_ERROR; 00418 } 00419 00420 done: 00421 IXMLDOMNodeList_Release( list ); 00422 return hr; 00423 } 00424 00425 static HRESULT parse_assembly( IXMLDOMDocument *doc, struct assembly **assembly ) 00426 { 00427 static const WCHAR identityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0}; 00428 static const WCHAR typeW[] = {'t','y','p','e',0}; 00429 static const WCHAR nameW[] = {'n','a','m','e',0}; 00430 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0}; 00431 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}; 00432 static const WCHAR tokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0}; 00433 IXMLDOMNodeList *list = NULL; 00434 IXMLDOMNode *node = NULL; 00435 IXMLDOMNamedNodeMap *attrs = NULL; 00436 struct assembly *a = NULL; 00437 BSTR str; 00438 HRESULT hr; 00439 LONG len; 00440 00441 str = SysAllocString( identityW ); 00442 hr = IXMLDOMDocument_getElementsByTagName( doc, str, &list ); 00443 SysFreeString( str ); 00444 if (hr != S_OK) goto done; 00445 00446 hr = IXMLDOMNodeList_get_length( list, &len ); 00447 if (hr != S_OK) goto done; 00448 if (!len) 00449 { 00450 hr = ERROR_SXS_MANIFEST_FORMAT_ERROR; 00451 goto done; 00452 } 00453 hr = IXMLDOMNodeList_nextNode( list, &node ); 00454 if (hr != S_OK) goto done; 00455 if (!node) 00456 { 00457 hr = ERROR_SXS_MANIFEST_FORMAT_ERROR; 00458 goto done; 00459 } 00460 if (!(a = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct assembly) ))) 00461 { 00462 hr = E_OUTOFMEMORY; 00463 goto done; 00464 } 00465 list_init( &a->files ); 00466 00467 hr = IXMLDOMNode_get_attributes( node, &attrs ); 00468 if (hr != S_OK) goto done; 00469 00470 a->type = get_attribute_value( attrs, typeW ); 00471 a->name = get_attribute_value( attrs, nameW ); 00472 a->version = get_attribute_value( attrs, versionW ); 00473 a->arch = get_attribute_value( attrs, architectureW ); 00474 a->token = get_attribute_value( attrs, tokenW ); 00475 00476 if (!a->type || (strcmpW( a->type, win32W ) && strcmpW( a->type, win32_policyW )) || 00477 !a->name || !a->version || !a->arch || !a->token) 00478 { 00479 WARN("invalid win32 assembly\n"); 00480 hr = ERROR_SXS_MANIFEST_FORMAT_ERROR; 00481 goto done; 00482 } 00483 if (!strcmpW( a->type, win32W )) hr = parse_files( doc, a ); 00484 00485 done: 00486 if (attrs) IXMLDOMNamedNodeMap_Release( attrs ); 00487 if (node) IXMLDOMNode_Release( node ); 00488 if (list) IXMLDOMNodeList_Release( list ); 00489 if (hr == S_OK) *assembly = a; 00490 else free_assembly( a ); 00491 return hr; 00492 } 00493 00494 static WCHAR *build_policy_filename( const WCHAR *arch, const WCHAR *name, const WCHAR *token, 00495 const WCHAR *version ) 00496 { 00497 static const WCHAR policiesW[] = {'p','o','l','i','c','i','e','s','\\',0}; 00498 static const WCHAR suffixW[] = {'.','p','o','l','i','c','y',0}; 00499 WCHAR sxsdir[MAX_PATH], *ret, *fullname; 00500 unsigned int len; 00501 00502 if (!(fullname = build_policy_name( arch, name, token, &len ))) return NULL; 00503 len += build_sxs_path( sxsdir ); 00504 len += sizeof(policiesW) / sizeof(policiesW[0]) - 1; 00505 len += strlenW( version ); 00506 len += sizeof(suffixW) / sizeof(suffixW[0]) - 1; 00507 if (!(ret = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) 00508 { 00509 HeapFree( GetProcessHeap(), 0, fullname ); 00510 return NULL; 00511 } 00512 strcpyW( ret, sxsdir ); 00513 strcatW( ret, policiesW ); 00514 CreateDirectoryW( ret, NULL ); 00515 strcatW( ret, name ); 00516 CreateDirectoryW( ret, NULL ); 00517 strcatW( ret, backslashW ); 00518 strcatW( ret, version ); 00519 strcatW( ret, suffixW ); 00520 00521 HeapFree( GetProcessHeap(), 0, fullname ); 00522 return ret; 00523 } 00524 00525 static HRESULT install_policy( const WCHAR *manifest, struct assembly *assembly ) 00526 { 00527 WCHAR *dst; 00528 BOOL ret; 00529 00530 /* FIXME: handle catalog file */ 00531 00532 dst = build_policy_filename( assembly->arch, assembly->name, assembly->token, assembly->version ); 00533 if (!dst) return E_OUTOFMEMORY; 00534 00535 ret = CopyFileW( manifest, dst, FALSE ); 00536 HeapFree( GetProcessHeap(), 0, dst ); 00537 if (!ret) 00538 { 00539 HRESULT hr = HRESULT_FROM_WIN32( GetLastError() ); 00540 WARN("failed to copy policy manifest file 0x%08x\n", hr); 00541 return hr; 00542 } 00543 return S_OK; 00544 } 00545 00546 static WCHAR *build_source_filename( const WCHAR *manifest, struct file *file ) 00547 { 00548 WCHAR *src; 00549 const WCHAR *p; 00550 int len; 00551 00552 p = strrchrW( manifest, '\\' ); 00553 if (!p) p = strrchrW( manifest, '/' ); 00554 if (!p) return strdupW( manifest ); 00555 00556 len = p - manifest + 1; 00557 if (!(src = HeapAlloc( GetProcessHeap(), 0, (len + strlenW( file->name ) + 1) * sizeof(WCHAR) ))) 00558 return NULL; 00559 00560 memcpy( src, manifest, len * sizeof(WCHAR) ); 00561 strcpyW( src + len, file->name ); 00562 return src; 00563 } 00564 00565 static WCHAR *build_manifest_filename( const WCHAR *arch, const WCHAR *name, const WCHAR *token, 00566 const WCHAR *version ) 00567 { 00568 static const WCHAR manifestsW[] = {'m','a','n','i','f','e','s','t','s','\\',0}; 00569 static const WCHAR suffixW[] = {'.','m','a','n','i','f','e','s','t',0}; 00570 WCHAR sxsdir[MAX_PATH], *ret, *fullname; 00571 unsigned int len; 00572 00573 if (!(fullname = build_assembly_name( arch, name, token, version, &len ))) return NULL; 00574 len += build_sxs_path( sxsdir ); 00575 len += sizeof(manifestsW) / sizeof(manifestsW[0]) - 1; 00576 len += sizeof(suffixW) / sizeof(suffixW[0]) - 1; 00577 if (!(ret = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) 00578 { 00579 HeapFree( GetProcessHeap(), 0, fullname ); 00580 return NULL; 00581 } 00582 strcpyW( ret, sxsdir ); 00583 strcatW( ret, manifestsW ); 00584 strcatW( ret, fullname ); 00585 strcatW( ret, suffixW ); 00586 00587 HeapFree( GetProcessHeap(), 0, fullname ); 00588 return ret; 00589 } 00590 00591 static HRESULT load_manifest( IXMLDOMDocument *doc, const WCHAR *filename ) 00592 { 00593 HRESULT hr; 00594 VARIANT var; 00595 VARIANT_BOOL b; 00596 BSTR str; 00597 00598 str = SysAllocString( filename ); 00599 VariantInit( &var ); 00600 V_VT( &var ) = VT_BSTR; 00601 V_BSTR( &var ) = str; 00602 hr = IXMLDOMDocument_load( doc, var, &b ); 00603 SysFreeString( str ); 00604 if (hr != S_OK) return hr; 00605 if (!b) 00606 { 00607 WARN("failed to load manifest\n"); 00608 return S_FALSE; 00609 } 00610 return S_OK; 00611 } 00612 00613 static HRESULT install_assembly( const WCHAR *manifest, struct assembly *assembly ) 00614 { 00615 WCHAR sxsdir[MAX_PATH], *p, *name, *dst, *src; 00616 unsigned int len, len_name, len_sxsdir = build_sxs_path( sxsdir ); 00617 struct file *file; 00618 HRESULT hr = E_OUTOFMEMORY; 00619 BOOL ret; 00620 00621 dst = build_manifest_filename( assembly->arch, assembly->name, assembly->token, assembly->version ); 00622 if (!dst) return E_OUTOFMEMORY; 00623 00624 ret = CopyFileW( manifest, dst, FALSE ); 00625 HeapFree( GetProcessHeap(), 0, dst ); 00626 if (!ret) 00627 { 00628 hr = HRESULT_FROM_WIN32( GetLastError() ); 00629 WARN("failed to copy manifest file 0x%08x\n", hr); 00630 return hr; 00631 } 00632 00633 name = build_assembly_name( assembly->arch, assembly->name, assembly->token, assembly->version, 00634 &len_name ); 00635 if (!name) return E_OUTOFMEMORY; 00636 00637 /* FIXME: this should be a transaction */ 00638 LIST_FOR_EACH_ENTRY( file, &assembly->files, struct file, entry ) 00639 { 00640 if (!(src = build_source_filename( manifest, file ))) goto done; 00641 00642 len = len_sxsdir + len_name + strlenW( file->name ); 00643 if (!(dst = HeapAlloc( GetProcessHeap(), 0, (len + 2) * sizeof(WCHAR) ))) 00644 { 00645 HeapFree( GetProcessHeap(), 0, src ); 00646 goto done; 00647 } 00648 strcpyW( dst, sxsdir ); 00649 strcatW( dst, name ); 00650 CreateDirectoryW( dst, NULL ); 00651 00652 strcatW( dst, backslashW ); 00653 strcatW( dst, file->name ); 00654 for (p = dst; *p; p++) *p = tolowerW( *p ); 00655 00656 ret = CopyFileW( src, dst, FALSE ); 00657 HeapFree( GetProcessHeap(), 0, src ); 00658 HeapFree( GetProcessHeap(), 0, dst ); 00659 if (!ret) 00660 { 00661 hr = HRESULT_FROM_WIN32( GetLastError() ); 00662 WARN("failed to copy file 0x%08x\n", hr); 00663 goto done; 00664 } 00665 } 00666 hr = S_OK; 00667 00668 done: 00669 HeapFree( GetProcessHeap(), 0, name ); 00670 return hr; 00671 } 00672 00673 static HRESULT WINAPI cache_InstallAssembly( 00674 IAssemblyCache *iface, 00675 DWORD flags, 00676 LPCWSTR path, 00677 LPCFUSION_INSTALL_REFERENCE ref ) 00678 { 00679 struct cache *cache = impl_from_IAssemblyCache( iface ); 00680 HRESULT hr, init; 00681 IXMLDOMDocument *doc = NULL; 00682 struct assembly *assembly = NULL; 00683 00684 TRACE("%p, 0x%08x, %s, %p\n", iface, flags, debugstr_w(path), ref); 00685 00686 cache_lock( cache ); 00687 init = CoInitialize( NULL ); 00688 00689 hr = CoCreateInstance( &CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void **)&doc ); 00690 if (hr != S_OK) 00691 goto done; 00692 00693 if ((hr = load_manifest( doc, path )) != S_OK) goto done; 00694 if ((hr = parse_assembly( doc, &assembly )) != S_OK) goto done; 00695 00696 /* FIXME: verify name attributes */ 00697 00698 if (!strcmpW( assembly->type, win32_policyW )) 00699 hr = install_policy( path, assembly ); 00700 else 00701 hr = install_assembly( path, assembly ); 00702 00703 done: 00704 free_assembly( assembly ); 00705 if (doc) IXMLDOMDocument_Release( doc ); 00706 if (SUCCEEDED(init)) CoUninitialize(); 00707 cache_unlock( cache ); 00708 return hr; 00709 } 00710 00711 static HRESULT uninstall_assembly( struct assembly *assembly ) 00712 { 00713 WCHAR sxsdir[MAX_PATH], *name, *dirname, *filename; 00714 unsigned int len, len_name, len_sxsdir = build_sxs_path( sxsdir ); 00715 HRESULT hr = E_OUTOFMEMORY; 00716 struct file *file; 00717 00718 name = build_assembly_name( assembly->arch, assembly->name, assembly->token, assembly->version, 00719 &len_name ); 00720 if (!name) return E_OUTOFMEMORY; 00721 if (!(dirname = HeapAlloc( GetProcessHeap(), 0, (len_sxsdir + len_name + 1) * sizeof(WCHAR) ))) 00722 goto done; 00723 strcpyW( dirname, sxsdir ); 00724 strcpyW( dirname + len_sxsdir, name ); 00725 00726 LIST_FOR_EACH_ENTRY( file, &assembly->files, struct file, entry ) 00727 { 00728 len = len_sxsdir + len_name + 1 + strlenW( file->name ); 00729 if (!(filename = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) goto done; 00730 strcpyW( filename, dirname ); 00731 strcatW( filename, backslashW ); 00732 strcatW( filename, file->name ); 00733 00734 if (!DeleteFileW( filename )) WARN( "failed to delete file %u\n", GetLastError() ); 00735 HeapFree( GetProcessHeap(), 0, filename ); 00736 } 00737 RemoveDirectoryW( dirname ); 00738 hr = S_OK; 00739 00740 done: 00741 HeapFree( GetProcessHeap(), 0, dirname ); 00742 HeapFree( GetProcessHeap(), 0, name ); 00743 return hr; 00744 } 00745 00746 static HRESULT WINAPI cache_UninstallAssembly( 00747 IAssemblyCache *iface, 00748 DWORD flags, 00749 LPCWSTR assembly_name, 00750 LPCFUSION_INSTALL_REFERENCE ref, 00751 ULONG *disp ) 00752 { 00753 struct cache *cache = impl_from_IAssemblyCache( iface ); 00754 HRESULT hr, init; 00755 IXMLDOMDocument *doc = NULL; 00756 struct assembly *assembly = NULL; 00757 IAssemblyName *name_obj = NULL; 00758 const WCHAR *arch, *name, *token, *type, *version; 00759 WCHAR *p, *path = NULL; 00760 00761 TRACE("%p, 0x%08x, %s, %p, %p\n", iface, flags, debugstr_w(assembly_name), ref, disp); 00762 00763 if (ref) 00764 { 00765 FIXME("application reference not supported\n"); 00766 return E_NOTIMPL; 00767 } 00768 cache_lock( cache ); 00769 init = CoInitialize( NULL ); 00770 00771 hr = CreateAssemblyNameObject( &name_obj, assembly_name, CANOF_PARSE_DISPLAY_NAME, NULL ); 00772 if (FAILED( hr )) 00773 goto done; 00774 00775 arch = get_name_attribute( name_obj, NAME_ATTR_ID_ARCH ); 00776 name = get_name_attribute( name_obj, NAME_ATTR_ID_NAME ); 00777 token = get_name_attribute( name_obj, NAME_ATTR_ID_TOKEN ); 00778 type = get_name_attribute( name_obj, NAME_ATTR_ID_TYPE ); 00779 version = get_name_attribute( name_obj, NAME_ATTR_ID_VERSION ); 00780 if (!arch || !name || !token || !type || !version) 00781 { 00782 hr = E_INVALIDARG; 00783 goto done; 00784 } 00785 if (!strcmpW( type, win32W )) path = build_manifest_filename( arch, name, token, version ); 00786 else if (!strcmpW( type, win32_policyW )) path = build_policy_filename( arch, name, token, version ); 00787 else 00788 { 00789 hr = E_INVALIDARG; 00790 goto done; 00791 } 00792 00793 hr = CoCreateInstance( &CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void **)&doc ); 00794 if (hr != S_OK) 00795 goto done; 00796 00797 if ((hr = load_manifest( doc, path )) != S_OK) goto done; 00798 if ((hr = parse_assembly( doc, &assembly )) != S_OK) goto done; 00799 00800 if (!DeleteFileW( path )) WARN( "unable to remove manifest file %u\n", GetLastError() ); 00801 else if ((p = strrchrW( path, '\\' ))) 00802 { 00803 *p = 0; 00804 RemoveDirectoryW( path ); 00805 } 00806 if (!strcmpW( assembly->type, win32W )) hr = uninstall_assembly( assembly ); 00807 00808 done: 00809 if (name_obj) IAssemblyName_Release( name_obj ); 00810 HeapFree( GetProcessHeap(), 0, path ); 00811 free_assembly( assembly ); 00812 if (doc) IXMLDOMDocument_Release( doc ); 00813 if (SUCCEEDED(init)) CoUninitialize(); 00814 cache_unlock( cache ); 00815 return hr; 00816 } 00817 00818 static const IAssemblyCacheVtbl cache_vtbl = 00819 { 00820 cache_QueryInterface, 00821 cache_AddRef, 00822 cache_Release, 00823 cache_UninstallAssembly, 00824 cache_QueryAssemblyInfo, 00825 cache_CreateAssemblyCacheItem, 00826 cache_Reserved, 00827 cache_InstallAssembly 00828 }; 00829 00830 /****************************************************************** 00831 * CreateAssemblyCache (SXS.@) 00832 */ 00833 HRESULT WINAPI CreateAssemblyCache( IAssemblyCache **obj, DWORD reserved ) 00834 { 00835 struct cache *cache; 00836 00837 TRACE("%p, %u\n", obj, reserved); 00838 00839 if (!obj) 00840 return E_INVALIDARG; 00841 00842 *obj = NULL; 00843 00844 cache = HeapAlloc( GetProcessHeap(), 0, sizeof(struct cache) ); 00845 if (!cache) 00846 return E_OUTOFMEMORY; 00847 00848 cache->IAssemblyCache_iface.lpVtbl = &cache_vtbl; 00849 cache->refs = 1; 00850 cache->lock = CreateMutexW( NULL, FALSE, cache_mutex_nameW ); 00851 if (!cache->lock) 00852 { 00853 HeapFree( GetProcessHeap(), 0, cache ); 00854 return HRESULT_FROM_WIN32( GetLastError() ); 00855 } 00856 *obj = &cache->IAssemblyCache_iface; 00857 return S_OK; 00858 } Generated on Sat May 26 2012 04:16:05 for ReactOS by
1.7.6.1
|