From 4b8a228e431dabb3dbae597a23837a7024adbbc5 Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Tue, 5 Oct 2010 15:50:01 -0500 Subject: [PATCH 1/3] mscoree: Search the Global Assembly Cache for required assemblies. --- dlls/mscoree/corruntimehost.c | 15 ----- dlls/mscoree/metahost.c | 112 ++++++++++++++++++++++++++++++++++++++++ dlls/mscoree/mscoree_main.c | 16 ++++++ dlls/mscoree/mscoree_private.h | 19 ++++++- 4 files changed, 146 insertions(+), 16 deletions(-) diff --git a/dlls/mscoree/corruntimehost.c b/dlls/mscoree/corruntimehost.c index 8145948..c22dd22 100644 --- a/dlls/mscoree/corruntimehost.c +++ b/dlls/mscoree/corruntimehost.c @@ -57,21 +57,6 @@ struct DomainEntry MonoDomain *domain; }; -static char *WtoA(LPCWSTR wstr) -{ - int length; - char *result; - - length = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL); - - result = HeapAlloc(GetProcessHeap(), 0, length); - - if (result) - WideCharToMultiByte(CP_UTF8, 0, wstr, -1, result, length, NULL, NULL); - - return result; -} - static HRESULT RuntimeHost_AddDomain(RuntimeHost *This, MonoDomain **result) { struct DomainEntry *entry; diff --git a/dlls/mscoree/metahost.c b/dlls/mscoree/metahost.c index 3f572f7..1333f79 100644 --- a/dlls/mscoree/metahost.c +++ b/dlls/mscoree/metahost.c @@ -33,6 +33,7 @@ #include "corerror.h" #include "mscoree.h" +#include "fusion.h" #include "metahost.h" #include "wine/list.h" #include "mscoree_private.h" @@ -73,6 +74,8 @@ static loaded_mono loaded_monos[NUM_ABI_VERSIONS]; static BOOL find_mono_dll(LPCWSTR path, LPWSTR dll_path, int abi_version); +static MonoAssembly* mono_assembly_search_hook_fn(MonoAssemblyName *aname, char **assemblies_path, void *user_data); + static void set_environment(LPCWSTR bin_path) { WCHAR path_env[MAX_PATH]; @@ -93,6 +96,7 @@ static HRESULT load_mono(CLRRuntimeInfo *This, loaded_mono **result) static const WCHAR bin[] = {'\\','b','i','n',0}; static const WCHAR lib[] = {'\\','l','i','b',0}; static const WCHAR etc[] = {'\\','e','t','c',0}; + static const WCHAR glibdll[] = {'l','i','b','g','l','i','b','-','2','.','0','-','0','.','d','l','l',0}; WCHAR mono_dll_path[MAX_PATH+16], mono_bin_path[MAX_PATH+4]; WCHAR mono_lib_path[MAX_PATH+4], mono_etc_path[MAX_PATH+4]; char mono_lib_path_a[MAX_PATH], mono_etc_path_a[MAX_PATH]; @@ -134,13 +138,30 @@ static HRESULT load_mono(CLRRuntimeInfo *This, loaded_mono **result) } \ } while (0); + LOAD_MONO_FUNCTION(mono_assembly_open); LOAD_MONO_FUNCTION(mono_config_parse); LOAD_MONO_FUNCTION(mono_domain_assembly_open); + LOAD_MONO_FUNCTION(mono_install_assembly_preload_hook); LOAD_MONO_FUNCTION(mono_jit_cleanup); LOAD_MONO_FUNCTION(mono_jit_exec); LOAD_MONO_FUNCTION(mono_jit_init); LOAD_MONO_FUNCTION(mono_jit_set_trace_options); LOAD_MONO_FUNCTION(mono_set_dirs); + LOAD_MONO_FUNCTION(mono_stringify_assembly_name); + + /* GLib imports obsoleted by the 2.0 ABI */ + if (This->mono_abi_version == 1) + { + (*result)->glib_handle = LoadLibraryW(glibdll); + if (!(*result)->glib_handle) goto fail; + + (*result)->mono_free = (void*)GetProcAddress((*result)->glib_handle, "g_free"); + if (!(*result)->mono_free) goto fail; + } + else + { + LOAD_MONO_FUNCTION(mono_free); + } #undef LOAD_MONO_FUNCTION @@ -148,6 +169,8 @@ static HRESULT load_mono(CLRRuntimeInfo *This, loaded_mono **result) (*result)->mono_config_parse(NULL); + (*result)->mono_install_assembly_preload_hook(mono_assembly_search_hook_fn, *result); + trace_size = GetEnvironmentVariableA("WINE_MONO_TRACE", trace_setting, sizeof(trace_setting)); if (trace_size) @@ -161,7 +184,9 @@ static HRESULT load_mono(CLRRuntimeInfo *This, loaded_mono **result) fail: ERR("Could not load Mono into this process\n"); FreeLibrary((*result)->mono_handle); + FreeLibrary((*result)->glib_handle); (*result)->mono_handle = NULL; + (*result)->glib_handle = NULL; return E_FAIL; } @@ -1039,6 +1064,93 @@ extern HRESULT CLRMetaHost_CreateInstance(REFIID riid, void **ppobj) return ICLRMetaHost_QueryInterface((ICLRMetaHost*)&GlobalCLRMetaHost, riid, ppobj); } +static MonoAssembly* mono_assembly_search_hook_fn(MonoAssemblyName *aname, char **assemblies_path, void *user_data) +{ + loaded_mono *mono = user_data; + HRESULT hr=S_OK; + MonoAssembly *result=NULL; + char *stringname=NULL; + LPWSTR stringnameW; + int stringnameW_size; + IAssemblyCache *asmcache; + ASSEMBLY_INFO info; + WCHAR path[MAX_PATH]; + char *pathA; + MonoImageOpenStatus stat; + static WCHAR fusiondll[] = {'f','u','s','i','o','n',0}; + HMODULE hfusion=NULL; + static HRESULT WINAPI (*pCreateAssemblyCache)(IAssemblyCache**,DWORD); + + stringname = mono->mono_stringify_assembly_name(aname); + + TRACE("%s\n", debugstr_a(stringname)); + + if (!stringname) return NULL; + + /* FIXME: We should search the given paths before the GAC. */ + + if (!pCreateAssemblyCache) + { + hr = LoadLibraryShim(fusiondll, NULL, NULL, &hfusion); + + if (SUCCEEDED(hr)) + { + pCreateAssemblyCache = (void*)GetProcAddress(hfusion, "CreateAssemblyCache"); + if (!pCreateAssemblyCache) + hr = E_FAIL; + } + } + + if (SUCCEEDED(hr)) + hr = pCreateAssemblyCache(&asmcache, 0); + + if (SUCCEEDED(hr)) + { + stringnameW_size = MultiByteToWideChar(CP_UTF8, 0, stringname, -1, NULL, 0); + + stringnameW = HeapAlloc(GetProcessHeap(), 0, stringnameW_size * sizeof(WCHAR)); + if (stringnameW) + MultiByteToWideChar(CP_UTF8, 0, stringname, -1, stringnameW, stringnameW_size); + else + hr = E_OUTOFMEMORY; + + if (SUCCEEDED(hr)) + { + info.cbAssemblyInfo = sizeof(info); + info.pszCurrentAssemblyPathBuf = path; + info.cchBuf = MAX_PATH; + path[0] = 0; + + hr = IAssemblyCache_QueryAssemblyInfo(asmcache, 0, stringnameW, &info); + } + + HeapFree(GetProcessHeap(), 0, stringnameW); + + IAssemblyCache_Release(asmcache); + } + + if (SUCCEEDED(hr)) + { + TRACE("found: %s\n", debugstr_w(path)); + + pathA = WtoA(path); + + if (pathA) + { + result = mono->mono_assembly_open(pathA, &stat); + + if (!result) + ERR("Failed to load %s, status=%u\n", debugstr_w(path), stat); + + HeapFree(GetProcessHeap(), 0, pathA); + } + } + + mono->mono_free(stringname); + + return result; +} + HRESULT get_runtime_info(LPCWSTR exefile, LPCWSTR version, LPCWSTR config_file, DWORD startup_flags, DWORD runtimeinfo_flags, BOOL legacy, ICLRRuntimeInfo **result) { diff --git a/dlls/mscoree/mscoree_main.c b/dlls/mscoree/mscoree_main.c index c913e6e..0e373ed 100644 --- a/dlls/mscoree/mscoree_main.c +++ b/dlls/mscoree/mscoree_main.c @@ -40,6 +40,7 @@ #include "cor.h" #include "corerror.h" #include "mscoree.h" +#include "fusion.h" #include "metahost.h" #include "wine/list.h" #include "mscoree_private.h" @@ -50,6 +51,21 @@ WINE_DEFAULT_DEBUG_CHANNEL( mscoree ); LONG dll_refs = 0; +char *WtoA(LPCWSTR wstr) +{ + int length; + char *result; + + length = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL); + + result = HeapAlloc(GetProcessHeap(), 0, length); + + if (result) + WideCharToMultiByte(CP_UTF8, 0, wstr, -1, result, length, NULL, NULL); + + return result; +} + static BOOL get_install_root(LPWSTR install_dir) { const WCHAR dotnet_key[] = {'S','O','F','T','W','A','R','E','\\','M','i','c','r','o','s','o','f','t','\\','.','N','E','T','F','r','a','m','e','w','o','r','k','\\',0}; diff --git a/dlls/mscoree/mscoree_private.h b/dlls/mscoree/mscoree_private.h index 46c49c6..2609b9e 100644 --- a/dlls/mscoree/mscoree_private.h +++ b/dlls/mscoree/mscoree_private.h @@ -24,6 +24,8 @@ extern LONG dll_refs; static inline void MSCOREE_LockModule(void) { InterlockedIncrement(&dll_refs); } static inline void MSCOREE_UnlockModule(void) { InterlockedDecrement(&dll_refs); } +extern char *WtoA(LPCWSTR wstr); + extern HRESULT CLRMetaHost_CreateInstance(REFIID riid, void **ppobj); typedef struct tagASSEMBLY ASSEMBLY; @@ -71,21 +73,36 @@ extern HRESULT parse_config_file(LPCWSTR filename, parsed_config_file *result); extern void free_parsed_config_file(parsed_config_file *file); -/* Mono 2.6 embedding */ +/* Mono embedding */ typedef struct _MonoDomain MonoDomain; typedef struct _MonoAssembly MonoAssembly; +typedef struct _MonoAssemblyName MonoAssemblyName; + +typedef enum { + MONO_IMAGE_OK, + MONO_IMAGE_ERROR_ERRNO, + MONO_IMAGE_MISSING_ASSEMBLYREF, + MONO_IMAGE_IMAGE_INVALID +} MonoImageOpenStatus; + +typedef MonoAssembly* (*MonoAssemblyPreLoadFunc)(MonoAssemblyName *aname, char **assemblies_path, void *user_data); typedef struct loaded_mono { HMODULE mono_handle; + HMODULE glib_handle; + MonoAssembly* (*mono_assembly_open)(const char *filename, MonoImageOpenStatus *status); void (*mono_config_parse)(const char *filename); MonoAssembly* (*mono_domain_assembly_open) (MonoDomain *domain, const char *name); + void (*mono_free)(void *); + void (*mono_install_assembly_preload_hook)(MonoAssemblyPreLoadFunc func, void *user_data); void (*mono_jit_cleanup)(MonoDomain *domain); int (*mono_jit_exec)(MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[]); MonoDomain* (*mono_jit_init)(const char *file); int (*mono_jit_set_trace_options)(const char* options); void (*mono_set_dirs)(const char *assembly_dir, const char *config_dir); + char* (*mono_stringify_assembly_name)(MonoAssemblyName *aname); } loaded_mono; /* loaded runtime interfaces */ -- 1.7.1