From c78e2675cf9303abfaf224a6ebb92c770afeb735 Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Sun, 3 Oct 2010 13:24:01 -0500 Subject: [PATCH 04/13] mscoree: Use the new architecture to implement _CorExeMain. --- dlls/mscoree/corruntimehost.c | 207 ++++++++++++++++++++++++++ dlls/mscoree/metahost.c | 9 + dlls/mscoree/mscoree_main.c | 317 ---------------------------------------- dlls/mscoree/mscoree_private.h | 12 +-- 4 files changed, 218 insertions(+), 327 deletions(-) diff --git a/dlls/mscoree/corruntimehost.c b/dlls/mscoree/corruntimehost.c index cac9991..95f7ef3 100644 --- a/dlls/mscoree/corruntimehost.c +++ b/dlls/mscoree/corruntimehost.c @@ -24,8 +24,10 @@ #include "windef.h" #include "winbase.h" #include "winuser.h" +#include "winnls.h" #include "winreg.h" #include "ole2.h" +#include "shellapi.h" #include "cor.h" #include "mscoree.h" @@ -33,6 +35,7 @@ #include "mscoree_private.h" #include "wine/debug.h" +#include "wine/list.h" WINE_DEFAULT_DEBUG_CHANNEL( mscoree ); @@ -42,9 +45,117 @@ struct RuntimeHost const struct ICLRRuntimeHostVtbl *lpCLRHostVtbl; const CLRRuntimeInfo *version; const loaded_mono *mono; + struct list domains; + MonoDomain *default_domain; + CRITICAL_SECTION lock; LONG ref; }; +struct DomainEntry +{ + struct list entry; + 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; + char *mscorlib_path; + HRESULT res=S_OK; + + EnterCriticalSection(&This->lock); + + entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry)); + if (!entry) + { + res = E_OUTOFMEMORY; + goto end; + } + + mscorlib_path = WtoA(This->version->mscorlib_path); + if (!mscorlib_path) + { + HeapFree(GetProcessHeap(), 0, entry); + res = E_OUTOFMEMORY; + goto end; + } + + entry->domain = This->mono->mono_jit_init(mscorlib_path); + + HeapFree(GetProcessHeap(), 0, mscorlib_path); + + if (!entry->domain) + { + HeapFree(GetProcessHeap(), 0, entry); + res = E_FAIL; + goto end; + } + + list_add_tail(&This->domains, &entry->entry); + + *result = entry->domain; + +end: + LeaveCriticalSection(&This->lock); + + return res; +} + +static HRESULT RuntimeHost_GetDefaultDomain(RuntimeHost *This, MonoDomain **result) +{ + HRESULT res=S_OK; + + EnterCriticalSection(&This->lock); + + if (This->default_domain) goto end; + + res = RuntimeHost_AddDomain(This, &This->default_domain); + +end: + *result = This->default_domain; + + LeaveCriticalSection(&This->lock); + + return res; +} + +static void RuntimeHost_DeleteDomain(RuntimeHost *This, MonoDomain *domain) +{ + struct DomainEntry *entry; + + EnterCriticalSection(&This->lock); + + LIST_FOR_EACH_ENTRY(entry, &This->domains, struct DomainEntry, entry) + { + if (entry->domain == domain) + { + This->mono->mono_jit_cleanup(domain); + list_remove(&entry->entry); + if (This->default_domain == domain) + This->default_domain = NULL; + HeapFree(GetProcessHeap(), 0, entry); + break; + } + } + + LeaveCriticalSection(&This->lock); +} + static inline RuntimeHost *impl_from_ICLRRuntimeHost( ICLRRuntimeHost *iface ) { return (RuntimeHost *)((char*)iface - FIELD_OFFSET(RuntimeHost, lpCLRHostVtbl)); @@ -392,6 +503,86 @@ static const struct ICLRRuntimeHostVtbl CLRHostVtbl = CLRRuntimeHost_ExecuteInDefaultAppDomain }; +static void get_utf8_args(int *argc, char ***argv) +{ + WCHAR **argvw; + int size=0, i; + char *current_arg; + + argvw = CommandLineToArgvW(GetCommandLineW(), argc); + + for (i=0; i<*argc; i++) + { + size += sizeof(char*); + size += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, NULL, 0, NULL, NULL); + } + size += sizeof(char*); + + *argv = HeapAlloc(GetProcessHeap(), 0, size); + current_arg = (char*)(*argv + *argc + 1); + + for (i=0; i<*argc; i++) + { + (*argv)[i] = current_arg; + current_arg += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, current_arg, size, NULL, NULL); + } + + (*argv)[*argc] = NULL; + + HeapFree(GetProcessHeap(), 0, argvw); +} + +__int32 WINAPI _CorExeMain(void) +{ + int exit_code; + int argc; + char **argv; + MonoDomain *domain; + MonoAssembly *assembly; + WCHAR filename[MAX_PATH]; + char *filenameA; + ICLRRuntimeInfo *info; + RuntimeHost *host; + HRESULT hr; + + get_utf8_args(&argc, &argv); + + GetModuleFileNameW(NULL, filename, MAX_PATH); + + filenameA = WtoA(filename); + if (!filenameA) + return -1; + + hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info); + + if (SUCCEEDED(hr)) + { + hr = ICLRRuntimeInfo_GetRuntimeHost(info, &host); + + if (SUCCEEDED(hr)) + hr = RuntimeHost_GetDefaultDomain(host, &domain); + + if (SUCCEEDED(hr)) + { + assembly = host->mono->mono_domain_assembly_open(domain, filenameA); + + exit_code = host->mono->mono_jit_exec(domain, assembly, argc, argv); + + RuntimeHost_DeleteDomain(host, domain); + } + else + exit_code = -1; + + ICLRRuntimeInfo_Release(info); + } + else + exit_code = -1; + + HeapFree(GetProcessHeap(), 0, argv); + + return exit_code; +} + HRESULT RuntimeHost_Construct(const CLRRuntimeInfo *runtime_version, const loaded_mono *loaded_mono, RuntimeHost** result) { @@ -406,6 +597,10 @@ HRESULT RuntimeHost_Construct(const CLRRuntimeInfo *runtime_version, This->ref = 1; This->version = runtime_version; This->mono = loaded_mono; + list_init(&This->domains); + This->default_domain = NULL; + InitializeCriticalSection(&This->lock); + This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RuntimeHost.lock"); *result = This; @@ -433,6 +628,18 @@ HRESULT RuntimeHost_GetInterface(RuntimeHost *This, REFCLSID clsid, REFIID riid, HRESULT RuntimeHost_Destroy(RuntimeHost *This) { + struct DomainEntry *cursor, *cursor2; + + This->lock.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&This->lock); + + LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->domains, struct DomainEntry, entry) + { + This->mono->mono_jit_cleanup(cursor->domain); + list_remove(&cursor->entry); + HeapFree(GetProcessHeap(), 0, cursor); + } + HeapFree( GetProcessHeap(), 0, This ); return S_OK; } diff --git a/dlls/mscoree/metahost.c b/dlls/mscoree/metahost.c index d781afd..51897b2 100644 --- a/dlls/mscoree/metahost.c +++ b/dlls/mscoree/metahost.c @@ -436,6 +436,15 @@ const struct ICLRRuntimeInfoVtbl CLRRuntimeInfoVtbl = { CLRRuntimeInfo_IsStarted }; +HRESULT ICLRRuntimeInfo_GetRuntimeHost(ICLRRuntimeInfo *iface, RuntimeHost **result) +{ + struct CLRRuntimeInfo *This = (struct CLRRuntimeInfo*)iface; + + assert(This->ICLRRuntimeInfo_vtbl == &CLRRuntimeInfoVtbl); + + return CLRRuntimeInfo_GetRuntimeHost(This, result); +} + static BOOL find_mono_dll(LPCWSTR path, LPWSTR dll_path, int abi_version) { static const WCHAR mono_dll[] = {'\\','b','i','n','\\','m','o','n','o','.','d','l','l',0}; diff --git a/dlls/mscoree/mscoree_main.c b/dlls/mscoree/mscoree_main.c index d1f4324..0e96a47 100644 --- a/dlls/mscoree/mscoree_main.c +++ b/dlls/mscoree/mscoree_main.c @@ -44,148 +44,6 @@ WINE_DEFAULT_DEBUG_CHANNEL( mscoree ); -static BOOL find_mono_dll(LPCWSTR path, LPWSTR dll_path, int* abi_version) -{ - static const WCHAR mono_dll[] = {'\\','b','i','n','\\','m','o','n','o','.','d','l','l',0}; - static const WCHAR libmono_dll[] = {'\\','b','i','n','\\','l','i','b','m','o','n','o','.','d','l','l',0}; - DWORD attributes; - - strcpyW(dll_path, path); - strcatW(dll_path, mono_dll); - attributes = GetFileAttributesW(dll_path); - - if (attributes == INVALID_FILE_ATTRIBUTES) - { - strcpyW(dll_path, path); - strcatW(dll_path, libmono_dll); - attributes = GetFileAttributesW(dll_path); - } - - if (attributes != INVALID_FILE_ATTRIBUTES) - { - /* FIXME: Test for appropriate architecture. */ - *abi_version = 1; - return TRUE; - } - - return FALSE; -} - -static BOOL get_mono_path_from_registry(LPWSTR path) -{ - static const WCHAR mono_key[] = {'S','o','f','t','w','a','r','e','\\','N','o','v','e','l','l','\\','M','o','n','o',0}; - static const WCHAR defaul_clr[] = {'D','e','f','a','u','l','t','C','L','R',0}; - static const WCHAR install_root[] = {'S','d','k','I','n','s','t','a','l','l','R','o','o','t',0}; - static const WCHAR slash[] = {'\\',0}; - - WCHAR version[64], version_key[MAX_PATH]; - DWORD len; - HKEY key; - WCHAR dll_path[MAX_PATH]; - int abi_version; - - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, mono_key, 0, KEY_READ, &key)) - return FALSE; - - len = sizeof(version); - if (RegQueryValueExW(key, defaul_clr, 0, NULL, (LPBYTE)version, &len)) - { - RegCloseKey(key); - return FALSE; - } - RegCloseKey(key); - - lstrcpyW(version_key, mono_key); - lstrcatW(version_key, slash); - lstrcatW(version_key, version); - - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, version_key, 0, KEY_READ, &key)) - return FALSE; - - len = sizeof(WCHAR) * MAX_PATH; - if (RegQueryValueExW(key, install_root, 0, NULL, (LPBYTE)path, &len)) - { - RegCloseKey(key); - return FALSE; - } - RegCloseKey(key); - - return find_mono_dll(path, dll_path, &abi_version); -} - -static BOOL get_mono_path_from_folder(LPCWSTR folder, LPWSTR mono_path) -{ - static const WCHAR mono_one_dot_zero[] = {'\\','m','o','n','o','-','1','.','0', 0}; - WCHAR mono_dll_path[MAX_PATH]; - int abi_version; - BOOL found = FALSE; - - strcpyW(mono_path, folder); - strcatW(mono_path, mono_one_dot_zero); - - found = find_mono_dll(mono_path, mono_dll_path, &abi_version); - - if (found && abi_version != 1) - { - ERR("found wrong ABI in %s\n", debugstr_w(mono_path)); - found = FALSE; - } - - return found; -} - -static BOOL get_mono_path(LPWSTR path) -{ - static const WCHAR subdir_mono[] = {'\\','m','o','n','o',0}; - static const WCHAR sibling_mono[] = {'\\','.','.','\\','m','o','n','o',0}; - WCHAR base_path[MAX_PATH]; - const char *unix_data_dir; - WCHAR *dos_data_dir; - int build_tree=0; - static WCHAR* (CDECL *wine_get_dos_file_name)(const char*); - - /* First try c:\windows\mono */ - GetWindowsDirectoryW(base_path, MAX_PATH); - strcatW(base_path, subdir_mono); - - if (get_mono_path_from_folder(base_path, path)) - return TRUE; - - /* Next: /usr/share/wine/mono */ - unix_data_dir = wine_get_data_dir(); - - if (!unix_data_dir) - { - unix_data_dir = wine_get_build_dir(); - build_tree = 1; - } - - if (unix_data_dir) - { - if (!wine_get_dos_file_name) - wine_get_dos_file_name = (void*)GetProcAddress(GetModuleHandleA("kernel32"), "wine_get_dos_file_name"); - - if (wine_get_dos_file_name) - { - dos_data_dir = wine_get_dos_file_name(unix_data_dir); - - if (dos_data_dir) - { - strcpyW(base_path, dos_data_dir); - strcatW(base_path, build_tree ? sibling_mono : subdir_mono); - - HeapFree(GetProcessHeap(), 0, dos_data_dir); - - if (get_mono_path_from_folder(base_path, path)) - return TRUE; - } - } - } - - /* Last: the registry */ - return get_mono_path_from_registry(path); -} - 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}; @@ -208,112 +66,6 @@ static BOOL get_install_root(LPWSTR install_dir) return TRUE; } -static CRITICAL_SECTION mono_lib_cs; -static CRITICAL_SECTION_DEBUG mono_lib_cs_debug = -{ - 0, 0, &mono_lib_cs, - { &mono_lib_cs_debug.ProcessLocksList, - &mono_lib_cs_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": mono_lib_cs") } -}; -static CRITICAL_SECTION mono_lib_cs = { &mono_lib_cs_debug, -1, 0, 0, 0, 0 }; - -HMODULE mono_handle; - -void (*mono_config_parse)(const char *filename); -MonoAssembly* (*mono_domain_assembly_open) (MonoDomain *domain, const char *name); -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); - -static void set_environment(LPCWSTR bin_path) -{ - WCHAR path_env[MAX_PATH]; - int len; - - static const WCHAR pathW[] = {'P','A','T','H',0}; - - /* We have to modify PATH as Mono loads other DLLs from this directory. */ - GetEnvironmentVariableW(pathW, path_env, sizeof(path_env)/sizeof(WCHAR)); - len = strlenW(path_env); - path_env[len++] = ';'; - strcpyW(path_env+len, bin_path); - SetEnvironmentVariableW(pathW, path_env); -} - -static HMODULE load_mono(void) -{ - static const WCHAR bin[] = {'\\','b','i','n',0}; - static const WCHAR lib[] = {'\\','l','i','b',0}; - static const WCHAR etc[] = {'\\','e','t','c',0}; - HMODULE result; - WCHAR mono_path[MAX_PATH], 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]; - int abi_version; - - EnterCriticalSection(&mono_lib_cs); - - if (!mono_handle) - { - if (!get_mono_path(mono_path)) goto end; - - strcpyW(mono_bin_path, mono_path); - strcatW(mono_bin_path, bin); - set_environment(mono_bin_path); - - strcpyW(mono_lib_path, mono_path); - strcatW(mono_lib_path, lib); - WideCharToMultiByte(CP_UTF8, 0, mono_lib_path, -1, mono_lib_path_a, MAX_PATH, NULL, NULL); - - strcpyW(mono_etc_path, mono_path); - strcatW(mono_etc_path, etc); - WideCharToMultiByte(CP_UTF8, 0, mono_etc_path, -1, mono_etc_path_a, MAX_PATH, NULL, NULL); - - if (!find_mono_dll(mono_path, mono_dll_path, &abi_version)) goto end; - - if (abi_version != 1) goto end; - - mono_handle = LoadLibraryW(mono_dll_path); - - if (!mono_handle) goto end; - -#define LOAD_MONO_FUNCTION(x) do { \ - x = (void*)GetProcAddress(mono_handle, #x); \ - if (!x) { \ - mono_handle = NULL; \ - goto end; \ - } \ -} while (0); - - LOAD_MONO_FUNCTION(mono_config_parse); - LOAD_MONO_FUNCTION(mono_domain_assembly_open); - 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); - -#undef LOAD_MONO_FUNCTION - - mono_set_dirs(mono_lib_path_a, mono_etc_path_a); - - mono_config_parse(NULL); - } - -end: - result = mono_handle; - - LeaveCriticalSection(&mono_lib_cs); - - if (!result) - MESSAGE("wine: Install the Windows version of Mono to run .NET executables\n"); - - return result; -} - HRESULT WINAPI CorBindToRuntimeHost(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, LPCWSTR pwszHostConfigFile, VOID *pReserved, DWORD startupFlags, REFCLSID rclsid, @@ -373,75 +125,6 @@ BOOL WINAPI _CorDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) return TRUE; } -static void get_utf8_args(int *argc, char ***argv) -{ - WCHAR **argvw; - int size=0, i; - char *current_arg; - - argvw = CommandLineToArgvW(GetCommandLineW(), argc); - - for (i=0; i<*argc; i++) - { - size += sizeof(char*); - size += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, NULL, 0, NULL, NULL); - } - size += sizeof(char*); - - *argv = HeapAlloc(GetProcessHeap(), 0, size); - current_arg = (char*)(*argv + *argc + 1); - - for (i=0; i<*argc; i++) - { - (*argv)[i] = current_arg; - current_arg += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, current_arg, size, NULL, NULL); - } - - (*argv)[*argc] = NULL; - - HeapFree(GetProcessHeap(), 0, argvw); -} - -__int32 WINAPI _CorExeMain(void) -{ - int exit_code; - int trace_size; - char trace_setting[256]; - int argc; - char **argv; - MonoDomain *domain; - MonoAssembly *assembly; - char filename[MAX_PATH]; - - if (!load_mono()) - { - return -1; - } - - get_utf8_args(&argc, &argv); - - trace_size = GetEnvironmentVariableA("WINE_MONO_TRACE", trace_setting, sizeof(trace_setting)); - - if (trace_size) - { - mono_jit_set_trace_options(trace_setting); - } - - GetModuleFileNameA(NULL, filename, MAX_PATH); - - domain = mono_jit_init(filename); - - assembly = mono_domain_assembly_open(domain, filename); - - exit_code = mono_jit_exec(domain, assembly, argc, argv); - - mono_jit_cleanup(domain); - - HeapFree(GetProcessHeap(), 0, argv); - - return exit_code; -} - __int32 WINAPI _CorExeMain2(PBYTE ptrMemory, DWORD cntMemory, LPWSTR imageName, LPWSTR loaderName, LPWSTR cmdLine) { TRACE("(%p, %u, %s, %s, %s)\n", ptrMemory, cntMemory, debugstr_w(imageName), debugstr_w(loaderName), debugstr_w(cmdLine)); diff --git a/dlls/mscoree/mscoree_private.h b/dlls/mscoree/mscoree_private.h index 37e6f29..5062431 100644 --- a/dlls/mscoree/mscoree_private.h +++ b/dlls/mscoree/mscoree_private.h @@ -48,20 +48,12 @@ extern HRESULT get_runtime_info(LPCWSTR exefile, LPCWSTR version, LPCWSTR config extern HRESULT force_get_runtime_info(ICLRRuntimeInfo **result); +extern HRESULT ICLRRuntimeInfo_GetRuntimeHost(ICLRRuntimeInfo *iface, RuntimeHost **result); + /* Mono 2.6 embedding */ typedef struct _MonoDomain MonoDomain; typedef struct _MonoAssembly MonoAssembly; -extern HMODULE mono_handle; - -extern void (*mono_config_parse)(const char *filename); -extern MonoAssembly* (*mono_domain_assembly_open) (MonoDomain *domain, const char *name); -extern void (*mono_jit_cleanup)(MonoDomain *domain); -extern int (*mono_jit_exec)(MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[]); -extern MonoDomain* (*mono_jit_init)(const char *file); -extern int (*mono_jit_set_trace_options)(const char* options); -extern void (*mono_set_dirs)(const char *assembly_dir, const char *config_dir); - typedef struct loaded_mono { HMODULE mono_handle; -- 1.7.1