diff --git a/dlls/fusion/asmcache.c b/dlls/fusion/asmcache.c index d0b45c7626..e6a2a653de 100644 --- a/dlls/fusion/asmcache.c +++ b/dlls/fusion/asmcache.c @@ -41,6 +41,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(fusion); +static const WCHAR cache_mutex_nameW[] = + {'_','_','W','I','N','E','_','F','U','S','I','O','N','_','C','A','C','H','E','_','M','U','T','E','X','_','_',0}; + static BOOL create_full_path(LPCWSTR path) { LPWSTR new_path; @@ -126,6 +129,7 @@ typedef struct { IAssemblyCache IAssemblyCache_iface; LONG ref; + HANDLE lock; } IAssemblyCacheImpl; static inline IAssemblyCacheImpl *impl_from_IAssemblyCache(IAssemblyCache *iface) @@ -166,17 +170,29 @@ static ULONG WINAPI IAssemblyCacheImpl_AddRef(IAssemblyCache *iface) static ULONG WINAPI IAssemblyCacheImpl_Release(IAssemblyCache *iface) { - IAssemblyCacheImpl *This = impl_from_IAssemblyCache(iface); - ULONG refCount = InterlockedDecrement(&This->ref); + IAssemblyCacheImpl *cache = impl_from_IAssemblyCache(iface); + ULONG refCount = InterlockedDecrement( &cache->ref ); - TRACE("(%p)->(ref before = %u)\n", This, refCount + 1); + TRACE("(%p)->(ref before = %u)\n", cache, refCount + 1); if (!refCount) - HeapFree(GetProcessHeap(), 0, This); - + { + CloseHandle( cache->lock ); + HeapFree( GetProcessHeap(), 0, cache ); + } return refCount; } +static void cache_lock( IAssemblyCacheImpl *cache ) +{ + WaitForSingleObject( cache->lock, INFINITE ); +} + +static void cache_unlock( IAssemblyCacheImpl *cache ) +{ + ReleaseMutex( cache->lock ); +} + static HRESULT WINAPI IAssemblyCacheImpl_UninstallAssembly(IAssemblyCache *iface, DWORD dwFlags, LPCWSTR pszAssemblyName, @@ -184,6 +200,7 @@ static HRESULT WINAPI IAssemblyCacheImpl_UninstallAssembly(IAssemblyCache *iface ULONG *pulDisposition) { HRESULT hr; + IAssemblyCacheImpl *cache = impl_from_IAssemblyCache(iface); IAssemblyName *asmname, *next = NULL; IAssemblyEnum *asmenum = NULL; WCHAR *p, *path = NULL; @@ -202,6 +219,8 @@ static HRESULT WINAPI IAssemblyCacheImpl_UninstallAssembly(IAssemblyCache *iface if (FAILED( hr )) return hr; + cache_lock( cache ); + hr = CreateAssemblyEnum( &asmenum, NULL, asmname, ASM_CACHE_GAC, NULL ); if (FAILED( hr )) goto done; @@ -253,6 +272,7 @@ done: if (next) IAssemblyName_Release( next ); if (asmenum) IAssemblyEnum_Release( asmenum ); HeapFree( GetProcessHeap(), 0, path ); + cache_unlock( cache ); return hr; } @@ -261,6 +281,7 @@ static HRESULT WINAPI IAssemblyCacheImpl_QueryAssemblyInfo(IAssemblyCache *iface LPCWSTR pszAssemblyName, ASSEMBLY_INFO *pAsmInfo) { + IAssemblyCacheImpl *cache = impl_from_IAssemblyCache(iface); IAssemblyName *asmname, *next = NULL; IAssemblyEnum *asmenum = NULL; HRESULT hr; @@ -281,6 +302,8 @@ static HRESULT WINAPI IAssemblyCacheImpl_QueryAssemblyInfo(IAssemblyCache *iface if (FAILED(hr)) return hr; + cache_lock( cache ); + hr = CreateAssemblyEnum(&asmenum, NULL, asmname, ASM_CACHE_GAC, NULL); if (FAILED(hr)) goto done; @@ -303,7 +326,7 @@ done: IAssemblyName_Release(asmname); if (next) IAssemblyName_Release(next); if (asmenum) IAssemblyEnum_Release(asmenum); - + cache_unlock( cache ); return hr; } @@ -331,9 +354,10 @@ static HRESULT WINAPI IAssemblyCacheImpl_InstallAssembly(IAssemblyCache *iface, LPCWSTR pszManifestFilePath, LPCFUSION_INSTALL_REFERENCE pRefData) { - static const WCHAR format[] = - {'%','s','\\','%','s','\\','%','s','_','_','%','s','\\',0}; - + static const WCHAR format[] = {'%','s','\\','%','s','\\','%','s','_','_','%','s','\\',0}; + static const WCHAR ext_exe[] = {'.','e','x','e',0}; + static const WCHAR ext_dll[] = {'.','d','l','l',0}; + IAssemblyCacheImpl *cache = impl_from_IAssemblyCache(iface); ASSEMBLY *assembly; LPWSTR filename; LPWSTR name = NULL; @@ -345,9 +369,6 @@ static HRESULT WINAPI IAssemblyCacheImpl_InstallAssembly(IAssemblyCache *iface, LPWSTR ext; HRESULT hr; - static const WCHAR ext_exe[] = {'.','e','x','e',0}; - static const WCHAR ext_dll[] = {'.','d','l','l',0}; - TRACE("(%p, %d, %s, %p)\n", iface, dwFlags, debugstr_w(pszManifestFilePath), pRefData); @@ -382,6 +403,8 @@ static HRESULT WINAPI IAssemblyCacheImpl_InstallAssembly(IAssemblyCache *iface, if (FAILED(hr)) goto done; + cache_lock( cache ); + get_assembly_directory(asmdir, MAX_PATH, assembly_get_architecture(assembly)); sprintfW(path, format, asmdir, name, version, token); @@ -404,6 +427,7 @@ done: HeapFree(GetProcessHeap(), 0, version); HeapFree(GetProcessHeap(), 0, asmpath); assembly_release(assembly); + cache_unlock( cache ); return hr; } @@ -438,9 +462,13 @@ HRESULT WINAPI CreateAssemblyCache(IAssemblyCache **ppAsmCache, DWORD dwReserved cache->IAssemblyCache_iface.lpVtbl = &AssemblyCacheVtbl; cache->ref = 1; - + cache->lock = CreateMutexW( NULL, FALSE, cache_mutex_nameW ); + if (!cache->lock) + { + HeapFree( GetProcessHeap(), 0, cache ); + return HRESULT_FROM_WIN32( GetLastError() ); + } *ppAsmCache = &cache->IAssemblyCache_iface; - return S_OK; }