Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenasmcache.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
1.7.6.1
|