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

asmcache.c
Go to the documentation of this file.
00001 /*
00002  * IAssemblyCache implementation
00003  *
00004  * Copyright 2008 James Hawkins
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 #include <stdio.h>
00023 
00024 #define COBJMACROS
00025 
00026 #include "windef.h"
00027 #include "winbase.h"
00028 #include "winuser.h"
00029 #include "winver.h"
00030 #include "wincrypt.h"
00031 #include "winreg.h"
00032 #include "shlwapi.h"
00033 #include "dbghelp.h"
00034 #include "ole2.h"
00035 #include "fusion.h"
00036 #include "corerror.h"
00037 
00038 #include "fusionpriv.h"
00039 #include "wine/debug.h"
00040 #include "wine/unicode.h"
00041 
00042 WINE_DEFAULT_DEBUG_CHANNEL(fusion);
00043 
00044 static const WCHAR cache_mutex_nameW[] =
00045     {'_','_','W','I','N','E','_','F','U','S','I','O','N','_','C','A','C','H','E','_','M','U','T','E','X','_','_',0};
00046 
00047 static BOOL create_full_path(LPCWSTR path)
00048 {
00049     LPWSTR new_path;
00050     BOOL ret = TRUE;
00051     int len;
00052 
00053     new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * sizeof(WCHAR));
00054     if (!new_path)
00055         return FALSE;
00056 
00057     strcpyW(new_path, path);
00058 
00059     while ((len = strlenW(new_path)) && new_path[len - 1] == '\\')
00060         new_path[len - 1] = 0;
00061 
00062     while (!CreateDirectoryW(new_path, NULL))
00063     {
00064         LPWSTR slash;
00065         DWORD last_error = GetLastError();
00066 
00067         if(last_error == ERROR_ALREADY_EXISTS)
00068             break;
00069 
00070         if(last_error != ERROR_PATH_NOT_FOUND)
00071         {
00072             ret = FALSE;
00073             break;
00074         }
00075 
00076         if(!(slash = strrchrW(new_path, '\\')))
00077         {
00078             ret = FALSE;
00079             break;
00080         }
00081 
00082         len = slash - new_path;
00083         new_path[len] = 0;
00084         if(!create_full_path(new_path))
00085         {
00086             ret = FALSE;
00087             break;
00088         }
00089 
00090         new_path[len] = '\\';
00091     }
00092 
00093     HeapFree(GetProcessHeap(), 0, new_path);
00094     return ret;
00095 }
00096 
00097 static BOOL get_assembly_directory(LPWSTR dir, DWORD size, BYTE architecture)
00098 {
00099     static const WCHAR gac[] = {'\\','a','s','s','e','m','b','l','y','\\','G','A','C',0};
00100 
00101     static const WCHAR msil[] = {'_','M','S','I','L',0};
00102     static const WCHAR x86[] = {'_','3','2',0};
00103     static const WCHAR amd64[] = {'_','6','4',0};
00104 
00105     GetWindowsDirectoryW(dir, size);
00106     strcatW(dir, gac);
00107 
00108     switch (architecture)
00109     {
00110         case peMSIL:
00111             strcatW(dir, msil);
00112             break;
00113 
00114         case peI386:
00115             strcatW(dir, x86);
00116             break;
00117 
00118         case peAMD64:
00119             strcatW(dir, amd64);
00120             break;
00121     }
00122 
00123     return TRUE;
00124 }
00125 
00126 /* IAssemblyCache */
00127 
00128 typedef struct {
00129     IAssemblyCache IAssemblyCache_iface;
00130 
00131     LONG ref;
00132     HANDLE lock;
00133 } IAssemblyCacheImpl;
00134 
00135 static inline IAssemblyCacheImpl *impl_from_IAssemblyCache(IAssemblyCache *iface)
00136 {
00137     return CONTAINING_RECORD(iface, IAssemblyCacheImpl, IAssemblyCache_iface);
00138 }
00139 
00140 static HRESULT WINAPI IAssemblyCacheImpl_QueryInterface(IAssemblyCache *iface,
00141                                                         REFIID riid, LPVOID *ppobj)
00142 {
00143     IAssemblyCacheImpl *This = impl_from_IAssemblyCache(iface);
00144 
00145     TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj);
00146 
00147     *ppobj = NULL;
00148 
00149     if (IsEqualIID(riid, &IID_IUnknown) ||
00150         IsEqualIID(riid, &IID_IAssemblyCache))
00151     {
00152         IUnknown_AddRef(iface);
00153         *ppobj = This;
00154         return S_OK;
00155     }
00156 
00157     WARN("(%p, %s, %p): not found\n", This, debugstr_guid(riid), ppobj);
00158     return E_NOINTERFACE;
00159 }
00160 
00161 static ULONG WINAPI IAssemblyCacheImpl_AddRef(IAssemblyCache *iface)
00162 {
00163     IAssemblyCacheImpl *This = impl_from_IAssemblyCache(iface);
00164     ULONG refCount = InterlockedIncrement(&This->ref);
00165 
00166     TRACE("(%p)->(ref before = %u)\n", This, refCount - 1);
00167 
00168     return refCount;
00169 }
00170 
00171 static ULONG WINAPI IAssemblyCacheImpl_Release(IAssemblyCache *iface)
00172 {
00173     IAssemblyCacheImpl *cache = impl_from_IAssemblyCache(iface);
00174     ULONG refCount = InterlockedDecrement( &cache->ref );
00175 
00176     TRACE("(%p)->(ref before = %u)\n", cache, refCount + 1);
00177 
00178     if (!refCount)
00179     {
00180         CloseHandle( cache->lock );
00181         HeapFree( GetProcessHeap(), 0, cache );
00182     }
00183     return refCount;
00184 }
00185 
00186 static void cache_lock( IAssemblyCacheImpl *cache )
00187 {
00188     WaitForSingleObject( cache->lock, INFINITE );
00189 }
00190 
00191 static void cache_unlock( IAssemblyCacheImpl *cache )
00192 {
00193     ReleaseMutex( cache->lock );
00194 }
00195 
00196 static HRESULT WINAPI IAssemblyCacheImpl_UninstallAssembly(IAssemblyCache *iface,
00197                                                            DWORD dwFlags,
00198                                                            LPCWSTR pszAssemblyName,
00199                                                            LPCFUSION_INSTALL_REFERENCE pRefData,
00200                                                            ULONG *pulDisposition)
00201 {
00202     HRESULT hr;
00203     IAssemblyCacheImpl *cache = impl_from_IAssemblyCache(iface);
00204     IAssemblyName *asmname, *next = NULL;
00205     IAssemblyEnum *asmenum = NULL;
00206     WCHAR *p, *path = NULL;
00207     ULONG disp;
00208     DWORD len;
00209 
00210     TRACE("(%p, 0%08x, %s, %p, %p)\n", iface, dwFlags,
00211           debugstr_w(pszAssemblyName), pRefData, pulDisposition);
00212 
00213     if (pRefData)
00214     {
00215         FIXME("application reference not supported\n");
00216         return E_NOTIMPL;
00217     }
00218     hr = CreateAssemblyNameObject( &asmname, pszAssemblyName, CANOF_PARSE_DISPLAY_NAME, NULL );
00219     if (FAILED( hr ))
00220         return hr;
00221 
00222     cache_lock( cache );
00223 
00224     hr = CreateAssemblyEnum( &asmenum, NULL, asmname, ASM_CACHE_GAC, NULL );
00225     if (FAILED( hr ))
00226         goto done;
00227 
00228     hr = IAssemblyEnum_GetNextAssembly( asmenum, NULL, &next, 0 );
00229     if (hr == S_FALSE)
00230     {
00231         if (pulDisposition)
00232             *pulDisposition = IASSEMBLYCACHE_UNINSTALL_DISPOSITION_ALREADY_UNINSTALLED;
00233         goto done;
00234     }
00235     hr = IAssemblyName_GetPath( next, NULL, &len );
00236     if (hr != HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ))
00237         goto done;
00238 
00239     if (!(path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
00240     {
00241         hr = E_OUTOFMEMORY;
00242         goto done;
00243     }
00244     hr = IAssemblyName_GetPath( next, path, &len );
00245     if (FAILED( hr ))
00246         goto done;
00247 
00248     if (DeleteFileW( path ))
00249     {
00250         if ((p = strrchrW( path, '\\' )))
00251         {
00252             *p = 0;
00253             RemoveDirectoryW( path );
00254             if ((p = strrchrW( path, '\\' )))
00255             {
00256                 *p = 0;
00257                 RemoveDirectoryW( path );
00258             }
00259         }
00260         disp = IASSEMBLYCACHE_UNINSTALL_DISPOSITION_UNINSTALLED;
00261         hr = S_OK;
00262     }
00263     else
00264     {
00265         disp = IASSEMBLYCACHE_UNINSTALL_DISPOSITION_ALREADY_UNINSTALLED;
00266         hr = S_FALSE;
00267     }
00268     if (pulDisposition) *pulDisposition = disp;
00269 
00270 done:
00271     IAssemblyName_Release( asmname );
00272     if (next) IAssemblyName_Release( next );
00273     if (asmenum) IAssemblyEnum_Release( asmenum );
00274     HeapFree( GetProcessHeap(), 0, path );
00275     cache_unlock( cache );
00276     return hr;
00277 }
00278 
00279 static HRESULT WINAPI IAssemblyCacheImpl_QueryAssemblyInfo(IAssemblyCache *iface,
00280                                                            DWORD dwFlags,
00281                                                            LPCWSTR pszAssemblyName,
00282                                                            ASSEMBLY_INFO *pAsmInfo)
00283 {
00284     IAssemblyCacheImpl *cache = impl_from_IAssemblyCache(iface);
00285     IAssemblyName *asmname, *next = NULL;
00286     IAssemblyEnum *asmenum = NULL;
00287     HRESULT hr;
00288 
00289     TRACE("(%p, %d, %s, %p)\n", iface, dwFlags,
00290           debugstr_w(pszAssemblyName), pAsmInfo);
00291 
00292     if (pAsmInfo)
00293     {
00294         if (pAsmInfo->cbAssemblyInfo == 0)
00295             pAsmInfo->cbAssemblyInfo = sizeof(ASSEMBLY_INFO);
00296         else if (pAsmInfo->cbAssemblyInfo != sizeof(ASSEMBLY_INFO))
00297             return E_INVALIDARG;
00298     }
00299 
00300     hr = CreateAssemblyNameObject(&asmname, pszAssemblyName,
00301                                   CANOF_PARSE_DISPLAY_NAME, NULL);
00302     if (FAILED(hr))
00303         return hr;
00304 
00305     cache_lock( cache );
00306 
00307     hr = CreateAssemblyEnum(&asmenum, NULL, asmname, ASM_CACHE_GAC, NULL);
00308     if (FAILED(hr))
00309         goto done;
00310 
00311     hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0);
00312     if (hr == S_FALSE)
00313     {
00314         hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
00315         goto done;
00316     }
00317 
00318     if (!pAsmInfo)
00319         goto done;
00320 
00321     hr = IAssemblyName_GetPath(next, pAsmInfo->pszCurrentAssemblyPathBuf, &pAsmInfo->cchBuf);
00322 
00323     pAsmInfo->dwAssemblyFlags = ASSEMBLYINFO_FLAG_INSTALLED;
00324 
00325 done:
00326     IAssemblyName_Release(asmname);
00327     if (next) IAssemblyName_Release(next);
00328     if (asmenum) IAssemblyEnum_Release(asmenum);
00329     cache_unlock( cache );
00330     return hr;
00331 }
00332 
00333 static HRESULT WINAPI IAssemblyCacheImpl_CreateAssemblyCacheItem(IAssemblyCache *iface,
00334                                                                  DWORD dwFlags,
00335                                                                  PVOID pvReserved,
00336                                                                  IAssemblyCacheItem **ppAsmItem,
00337                                                                  LPCWSTR pszAssemblyName)
00338 {
00339     FIXME("(%p, %d, %p, %p, %s) stub!\n", iface, dwFlags, pvReserved,
00340           ppAsmItem, debugstr_w(pszAssemblyName));
00341 
00342     return E_NOTIMPL;
00343 }
00344 
00345 static HRESULT WINAPI IAssemblyCacheImpl_CreateAssemblyScavenger(IAssemblyCache *iface,
00346                                                                  IUnknown **ppUnkReserved)
00347 {
00348     FIXME("(%p, %p) stub!\n", iface, ppUnkReserved);
00349     return E_NOTIMPL;
00350 }
00351 
00352 static HRESULT WINAPI IAssemblyCacheImpl_InstallAssembly(IAssemblyCache *iface,
00353                                                          DWORD dwFlags,
00354                                                          LPCWSTR pszManifestFilePath,
00355                                                          LPCFUSION_INSTALL_REFERENCE pRefData)
00356 {
00357     static const WCHAR format[] = {'%','s','\\','%','s','\\','%','s','_','_','%','s','\\',0};
00358     static const WCHAR ext_exe[] = {'.','e','x','e',0};
00359     static const WCHAR ext_dll[] = {'.','d','l','l',0};
00360     IAssemblyCacheImpl *cache = impl_from_IAssemblyCache(iface);
00361     ASSEMBLY *assembly;
00362     LPWSTR filename;
00363     LPWSTR name = NULL;
00364     LPWSTR token = NULL;
00365     LPWSTR version = NULL;
00366     LPWSTR asmpath = NULL;
00367     WCHAR path[MAX_PATH];
00368     WCHAR asmdir[MAX_PATH];
00369     LPWSTR ext;
00370     HRESULT hr;
00371 
00372     TRACE("(%p, %d, %s, %p)\n", iface, dwFlags,
00373           debugstr_w(pszManifestFilePath), pRefData);
00374 
00375     if (!pszManifestFilePath || !*pszManifestFilePath)
00376         return E_INVALIDARG;
00377 
00378     if (!(ext = strrchrW(pszManifestFilePath, '.')))
00379         return HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
00380 
00381     if (lstrcmpiW(ext, ext_exe) && lstrcmpiW(ext, ext_dll))
00382         return HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
00383 
00384     if (GetFileAttributesW(pszManifestFilePath) == INVALID_FILE_ATTRIBUTES)
00385         return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
00386 
00387     hr = assembly_create(&assembly, pszManifestFilePath);
00388     if (FAILED(hr))
00389     {
00390         hr = COR_E_ASSEMBLYEXPECTED;
00391         goto done;
00392     }
00393 
00394     hr = assembly_get_name(assembly, &name);
00395     if (FAILED(hr))
00396         goto done;
00397 
00398     hr = assembly_get_pubkey_token(assembly, &token);
00399     if (FAILED(hr))
00400         goto done;
00401 
00402     hr = assembly_get_version(assembly, &version);
00403     if (FAILED(hr))
00404         goto done;
00405 
00406     cache_lock( cache );
00407 
00408     get_assembly_directory(asmdir, MAX_PATH, assembly_get_architecture(assembly));
00409 
00410     sprintfW(path, format, asmdir, name, version, token);
00411 
00412     create_full_path(path);
00413 
00414     hr = assembly_get_path(assembly, &asmpath);
00415     if (FAILED(hr))
00416         goto done;
00417 
00418     filename = PathFindFileNameW(asmpath);
00419 
00420     strcatW(path, filename);
00421     if (!CopyFileW(asmpath, path, FALSE))
00422         hr = HRESULT_FROM_WIN32(GetLastError());
00423 
00424 done:
00425     HeapFree(GetProcessHeap(), 0, name);
00426     HeapFree(GetProcessHeap(), 0, token);
00427     HeapFree(GetProcessHeap(), 0, version);
00428     HeapFree(GetProcessHeap(), 0, asmpath);
00429     assembly_release(assembly);
00430     cache_unlock( cache );
00431     return hr;
00432 }
00433 
00434 static const IAssemblyCacheVtbl AssemblyCacheVtbl = {
00435     IAssemblyCacheImpl_QueryInterface,
00436     IAssemblyCacheImpl_AddRef,
00437     IAssemblyCacheImpl_Release,
00438     IAssemblyCacheImpl_UninstallAssembly,
00439     IAssemblyCacheImpl_QueryAssemblyInfo,
00440     IAssemblyCacheImpl_CreateAssemblyCacheItem,
00441     IAssemblyCacheImpl_CreateAssemblyScavenger,
00442     IAssemblyCacheImpl_InstallAssembly
00443 };
00444 
00445 /******************************************************************
00446  *  CreateAssemblyCache   (FUSION.@)
00447  */
00448 HRESULT WINAPI CreateAssemblyCache(IAssemblyCache **ppAsmCache, DWORD dwReserved)
00449 {
00450     IAssemblyCacheImpl *cache;
00451 
00452     TRACE("(%p, %d)\n", ppAsmCache, dwReserved);
00453 
00454     if (!ppAsmCache)
00455         return E_INVALIDARG;
00456 
00457     *ppAsmCache = NULL;
00458 
00459     cache = HeapAlloc(GetProcessHeap(), 0, sizeof(IAssemblyCacheImpl));
00460     if (!cache)
00461         return E_OUTOFMEMORY;
00462 
00463     cache->IAssemblyCache_iface.lpVtbl = &AssemblyCacheVtbl;
00464     cache->ref = 1;
00465     cache->lock = CreateMutexW( NULL, FALSE, cache_mutex_nameW );
00466     if (!cache->lock)
00467     {
00468         HeapFree( GetProcessHeap(), 0, cache );
00469         return HRESULT_FROM_WIN32( GetLastError() );
00470     }
00471     *ppAsmCache = &cache->IAssemblyCache_iface;
00472     return S_OK;
00473 }
00474 
00475 /* IAssemblyCacheItem */
00476 
00477 typedef struct {
00478     IAssemblyCacheItem IAssemblyCacheItem_iface;
00479 
00480     LONG ref;
00481 } IAssemblyCacheItemImpl;
00482 
00483 static inline IAssemblyCacheItemImpl *impl_from_IAssemblyCacheItem(IAssemblyCacheItem *iface)
00484 {
00485     return CONTAINING_RECORD(iface, IAssemblyCacheItemImpl, IAssemblyCacheItem_iface);
00486 }
00487 
00488 static HRESULT WINAPI IAssemblyCacheItemImpl_QueryInterface(IAssemblyCacheItem *iface,
00489                                                             REFIID riid, LPVOID *ppobj)
00490 {
00491     IAssemblyCacheItemImpl *This = impl_from_IAssemblyCacheItem(iface);
00492 
00493     TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj);
00494 
00495     *ppobj = NULL;
00496 
00497     if (IsEqualIID(riid, &IID_IUnknown) ||
00498         IsEqualIID(riid, &IID_IAssemblyCacheItem))
00499     {
00500         IUnknown_AddRef(iface);
00501         *ppobj = This;
00502         return S_OK;
00503     }
00504 
00505     WARN("(%p, %s, %p): not found\n", This, debugstr_guid(riid), ppobj);
00506     return E_NOINTERFACE;
00507 }
00508 
00509 static ULONG WINAPI IAssemblyCacheItemImpl_AddRef(IAssemblyCacheItem *iface)
00510 {
00511     IAssemblyCacheItemImpl *This = impl_from_IAssemblyCacheItem(iface);
00512     ULONG refCount = InterlockedIncrement(&This->ref);
00513 
00514     TRACE("(%p)->(ref before = %u)\n", This, refCount - 1);
00515 
00516     return refCount;
00517 }
00518 
00519 static ULONG WINAPI IAssemblyCacheItemImpl_Release(IAssemblyCacheItem *iface)
00520 {
00521     IAssemblyCacheItemImpl *This = impl_from_IAssemblyCacheItem(iface);
00522     ULONG refCount = InterlockedDecrement(&This->ref);
00523 
00524     TRACE("(%p)->(ref before = %u)\n", This, refCount + 1);
00525 
00526     if (!refCount)
00527         HeapFree(GetProcessHeap(), 0, This);
00528 
00529     return refCount;
00530 }
00531 
00532 static HRESULT WINAPI IAssemblyCacheItemImpl_CreateStream(IAssemblyCacheItem *iface,
00533                                                         DWORD dwFlags,
00534                                                         LPCWSTR pszStreamName,
00535                                                         DWORD dwFormat,
00536                                                         DWORD dwFormatFlags,
00537                                                         IStream **ppIStream,
00538                                                         ULARGE_INTEGER *puliMaxSize)
00539 {
00540     FIXME("(%p, %d, %s, %d, %d, %p, %p) stub!\n", iface, dwFlags,
00541           debugstr_w(pszStreamName), dwFormat, dwFormatFlags, ppIStream, puliMaxSize);
00542 
00543     return E_NOTIMPL;
00544 }
00545 
00546 static HRESULT WINAPI IAssemblyCacheItemImpl_Commit(IAssemblyCacheItem *iface,
00547                                                   DWORD dwFlags,
00548                                                   ULONG *pulDisposition)
00549 {
00550     FIXME("(%p, %d, %p) stub!\n", iface, dwFlags, pulDisposition);
00551     return E_NOTIMPL;
00552 }
00553 
00554 static HRESULT WINAPI IAssemblyCacheItemImpl_AbortItem(IAssemblyCacheItem *iface)
00555 {
00556     FIXME("(%p) stub!\n", iface);
00557     return E_NOTIMPL;
00558 }
00559 
00560 static const IAssemblyCacheItemVtbl AssemblyCacheItemVtbl = {
00561     IAssemblyCacheItemImpl_QueryInterface,
00562     IAssemblyCacheItemImpl_AddRef,
00563     IAssemblyCacheItemImpl_Release,
00564     IAssemblyCacheItemImpl_CreateStream,
00565     IAssemblyCacheItemImpl_Commit,
00566     IAssemblyCacheItemImpl_AbortItem
00567 };

Generated on Sun May 27 2012 04:23:33 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.