Vincent Povirk : mscoree: Search the Global Assembly Cache for required assemblies.

Alexandre Julliard julliard at winehq.org
Fri Nov 12 11:22:44 CST 2010


Module: wine
Branch: master
Commit: d2d743efbb84cf1972bcc90d558a4a029b3466dd
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d2d743efbb84cf1972bcc90d558a4a029b3466dd

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Tue Oct  5 15:50:01 2010 -0500

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 */




More information about the wine-cvs mailing list