ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

cache.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.