ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

metahost.c
Go to the documentation of this file.
00001 /*
00002  * ICLRMetaHost - discovery and management of available .NET runtimes
00003  *
00004  * Copyright 2010 Vincent Povirk for CodeWeavers
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 <stdio.h>
00022 #include <stdarg.h>
00023 #include <assert.h>
00024 
00025 #define COBJMACROS
00026 
00027 #include "wine/unicode.h"
00028 #include "wine/library.h"
00029 #include "windef.h"
00030 #include "winbase.h"
00031 #include "winreg.h"
00032 #include "ole2.h"
00033 
00034 #include "corerror.h"
00035 #include "cor.h"
00036 #include "mscoree.h"
00037 #include "corhdr.h"
00038 #include "cordebug.h"
00039 #include "metahost.h"
00040 #include "fusion.h"
00041 #include "wine/list.h"
00042 #include "mscoree_private.h"
00043 
00044 #include "wine/debug.h"
00045 
00046 WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
00047 
00048 static const WCHAR net_11_subdir[] = {'1','.','0',0};
00049 static const WCHAR net_20_subdir[] = {'2','.','0',0};
00050 static const WCHAR net_40_subdir[] = {'4','.','0',0};
00051 
00052 static const struct ICLRRuntimeInfoVtbl CLRRuntimeInfoVtbl;
00053 
00054 #define NUM_RUNTIMES 3
00055 
00056 static struct CLRRuntimeInfo runtimes[NUM_RUNTIMES] = {
00057     {{&CLRRuntimeInfoVtbl}, net_11_subdir, 1, 1, 4322, 0},
00058     {{&CLRRuntimeInfoVtbl}, net_20_subdir, 2, 0, 50727, 0},
00059     {{&CLRRuntimeInfoVtbl}, net_40_subdir, 4, 0, 30319, 0}
00060 };
00061 
00062 static int runtimes_initialized;
00063 
00064 static CRITICAL_SECTION runtime_list_cs;
00065 static CRITICAL_SECTION_DEBUG runtime_list_cs_debug =
00066 {
00067     0, 0, &runtime_list_cs,
00068     { &runtime_list_cs_debug.ProcessLocksList,
00069       &runtime_list_cs_debug.ProcessLocksList },
00070       0, 0, { (DWORD_PTR)(__FILE__ ": runtime_list_cs") }
00071 };
00072 static CRITICAL_SECTION runtime_list_cs = { &runtime_list_cs_debug, -1, 0, 0, 0, 0 };
00073 
00074 #define NUM_ABI_VERSIONS 2
00075 
00076 static loaded_mono loaded_monos[NUM_ABI_VERSIONS];
00077 
00078 static BOOL find_mono_dll(LPCWSTR path, LPWSTR dll_path, int abi_version);
00079 
00080 static MonoAssembly* mono_assembly_search_hook_fn(MonoAssemblyName *aname, char **assemblies_path, void *user_data);
00081 
00082 static void mono_shutdown_callback_fn(MonoProfiler *prof);
00083 
00084 static void set_environment(LPCWSTR bin_path)
00085 {
00086     WCHAR path_env[MAX_PATH];
00087     int len;
00088 
00089     static const WCHAR pathW[] = {'P','A','T','H',0};
00090 
00091     /* We have to modify PATH as Mono loads other DLLs from this directory. */
00092     GetEnvironmentVariableW(pathW, path_env, sizeof(path_env)/sizeof(WCHAR));
00093     len = strlenW(path_env);
00094     path_env[len++] = ';';
00095     strcpyW(path_env+len, bin_path);
00096     SetEnvironmentVariableW(pathW, path_env);
00097 }
00098 
00099 static void CDECL do_nothing(void)
00100 {
00101 }
00102 
00103 static void missing_runtime_message(const CLRRuntimeInfo *This)
00104 {
00105     if (This->major == 1)
00106         MESSAGE("wine: Install Mono 2.6 for Windows to run .NET 1.1 applications.\n");
00107     else if (This->major == 2)
00108         MESSAGE("wine: Install Mono for Windows to run .NET 2.0 applications.\n");
00109     else if (This->major == 4)
00110         MESSAGE("wine: Install Mono 2.8 or greater for Windows to run .NET 4.0 applications.\n");
00111 }
00112 
00113 static HRESULT load_mono(CLRRuntimeInfo *This, loaded_mono **result)
00114 {
00115     static const WCHAR bin[] = {'\\','b','i','n',0};
00116     static const WCHAR lib[] = {'\\','l','i','b',0};
00117     static const WCHAR etc[] = {'\\','e','t','c',0};
00118     static const WCHAR glibdll[] = {'l','i','b','g','l','i','b','-','2','.','0','-','0','.','d','l','l',0};
00119     WCHAR mono_dll_path[MAX_PATH+16], mono_bin_path[MAX_PATH+4];
00120     WCHAR mono_lib_path[MAX_PATH+4], mono_etc_path[MAX_PATH+4];
00121     char mono_lib_path_a[MAX_PATH], mono_etc_path_a[MAX_PATH];
00122     int trace_size;
00123     char trace_setting[256];
00124 
00125     if (This->mono_abi_version <= 0 || This->mono_abi_version > NUM_ABI_VERSIONS)
00126     {
00127         missing_runtime_message(This);
00128         return E_FAIL;
00129     }
00130 
00131     *result = &loaded_monos[This->mono_abi_version-1];
00132 
00133     if ((*result)->is_shutdown)
00134     {
00135         ERR("Cannot load Mono after it has been shut down.\n");
00136         *result = NULL;
00137         return E_FAIL;
00138     }
00139 
00140     if (!(*result)->mono_handle)
00141     {
00142         strcpyW(mono_bin_path, This->mono_path);
00143         strcatW(mono_bin_path, bin);
00144         set_environment(mono_bin_path);
00145 
00146         strcpyW(mono_lib_path, This->mono_path);
00147         strcatW(mono_lib_path, lib);
00148         WideCharToMultiByte(CP_UTF8, 0, mono_lib_path, -1, mono_lib_path_a, MAX_PATH, NULL, NULL);
00149 
00150         strcpyW(mono_etc_path, This->mono_path);
00151         strcatW(mono_etc_path, etc);
00152         WideCharToMultiByte(CP_UTF8, 0, mono_etc_path, -1, mono_etc_path_a, MAX_PATH, NULL, NULL);
00153 
00154         if (!find_mono_dll(This->mono_path, mono_dll_path, This->mono_abi_version)) goto fail;
00155 
00156         (*result)->mono_handle = LoadLibraryW(mono_dll_path);
00157 
00158         if (!(*result)->mono_handle) goto fail;
00159 
00160 #define LOAD_MONO_FUNCTION(x) do { \
00161     (*result)->x = (void*)GetProcAddress((*result)->mono_handle, #x); \
00162     if (!(*result)->x) { \
00163         goto fail; \
00164     } \
00165 } while (0);
00166 
00167         LOAD_MONO_FUNCTION(mono_assembly_get_image);
00168         LOAD_MONO_FUNCTION(mono_assembly_open);
00169         LOAD_MONO_FUNCTION(mono_config_parse);
00170         LOAD_MONO_FUNCTION(mono_class_from_mono_type);
00171         LOAD_MONO_FUNCTION(mono_class_from_name);
00172         LOAD_MONO_FUNCTION(mono_class_get_method_from_name);
00173         LOAD_MONO_FUNCTION(mono_domain_assembly_open);
00174         LOAD_MONO_FUNCTION(mono_install_assembly_preload_hook);
00175         LOAD_MONO_FUNCTION(mono_jit_exec);
00176         LOAD_MONO_FUNCTION(mono_jit_init);
00177         LOAD_MONO_FUNCTION(mono_jit_set_trace_options);
00178         LOAD_MONO_FUNCTION(mono_object_get_domain);
00179         LOAD_MONO_FUNCTION(mono_object_new);
00180         LOAD_MONO_FUNCTION(mono_object_unbox);
00181         LOAD_MONO_FUNCTION(mono_profiler_install);
00182         LOAD_MONO_FUNCTION(mono_reflection_type_from_name);
00183         LOAD_MONO_FUNCTION(mono_runtime_invoke);
00184         LOAD_MONO_FUNCTION(mono_runtime_object_init);
00185         LOAD_MONO_FUNCTION(mono_runtime_quit);
00186         LOAD_MONO_FUNCTION(mono_set_dirs);
00187         LOAD_MONO_FUNCTION(mono_stringify_assembly_name);
00188         LOAD_MONO_FUNCTION(mono_string_new);
00189 
00190         /* GLib imports obsoleted by the 2.0 ABI */
00191         if (This->mono_abi_version == 1)
00192         {
00193             (*result)->glib_handle = LoadLibraryW(glibdll);
00194             if (!(*result)->glib_handle) goto fail;
00195 
00196             (*result)->mono_free = (void*)GetProcAddress((*result)->glib_handle, "g_free");
00197             if (!(*result)->mono_free) goto fail;
00198         }
00199         else
00200         {
00201             LOAD_MONO_FUNCTION(mono_free);
00202         }
00203 
00204 #undef LOAD_MONO_FUNCTION
00205 
00206 #define LOAD_OPT_VOID_MONO_FUNCTION(x) do { \
00207     (*result)->x = (void*)GetProcAddress((*result)->mono_handle, #x); \
00208     if (!(*result)->x) { \
00209         (*result)->x = do_nothing; \
00210     } \
00211 } while (0);
00212 
00213         LOAD_OPT_VOID_MONO_FUNCTION(mono_runtime_set_shutting_down);
00214         LOAD_OPT_VOID_MONO_FUNCTION(mono_thread_pool_cleanup);
00215         LOAD_OPT_VOID_MONO_FUNCTION(mono_thread_suspend_all_other_threads);
00216         LOAD_OPT_VOID_MONO_FUNCTION(mono_threads_set_shutting_down);
00217 
00218 #undef LOAD_OPT_VOID_MONO_FUNCTION
00219 
00220         (*result)->mono_profiler_install((MonoProfiler*)*result, mono_shutdown_callback_fn);
00221 
00222         (*result)->mono_set_dirs(mono_lib_path_a, mono_etc_path_a);
00223 
00224         (*result)->mono_config_parse(NULL);
00225 
00226         (*result)->mono_install_assembly_preload_hook(mono_assembly_search_hook_fn, *result);
00227 
00228         trace_size = GetEnvironmentVariableA("WINE_MONO_TRACE", trace_setting, sizeof(trace_setting));
00229 
00230         if (trace_size)
00231         {
00232             (*result)->mono_jit_set_trace_options(trace_setting);
00233         }
00234     }
00235 
00236     return S_OK;
00237 
00238 fail:
00239     ERR("Could not load Mono into this process\n");
00240     FreeLibrary((*result)->mono_handle);
00241     FreeLibrary((*result)->glib_handle);
00242     (*result)->mono_handle = NULL;
00243     (*result)->glib_handle = NULL;
00244     return E_FAIL;
00245 }
00246 
00247 static void mono_shutdown_callback_fn(MonoProfiler *prof)
00248 {
00249     loaded_mono *mono = (loaded_mono*)prof;
00250 
00251     mono->is_shutdown = TRUE;
00252 }
00253 
00254 static HRESULT CLRRuntimeInfo_GetRuntimeHost(CLRRuntimeInfo *This, RuntimeHost **result)
00255 {
00256     HRESULT hr = S_OK;
00257     loaded_mono *ploaded_mono;
00258 
00259     if (This->loaded_runtime)
00260     {
00261         *result = This->loaded_runtime;
00262         return hr;
00263     }
00264 
00265     EnterCriticalSection(&runtime_list_cs);
00266 
00267     hr = load_mono(This, &ploaded_mono);
00268 
00269     if (SUCCEEDED(hr))
00270         hr = RuntimeHost_Construct(This, ploaded_mono, &This->loaded_runtime);
00271 
00272     LeaveCriticalSection(&runtime_list_cs);
00273 
00274     if (SUCCEEDED(hr))
00275         *result = This->loaded_runtime;
00276 
00277     return hr;
00278 }
00279 
00280 void unload_all_runtimes(void)
00281 {
00282     int i;
00283 
00284     for (i=0; i<NUM_ABI_VERSIONS; i++)
00285     {
00286         loaded_mono *mono = &loaded_monos[i];
00287         if (mono->mono_handle && mono->is_started && !mono->is_shutdown)
00288         {
00289             /* Copied from Mono's ves_icall_System_Environment_Exit */
00290         mono->mono_threads_set_shutting_down();
00291         mono->mono_runtime_set_shutting_down();
00292         mono->mono_thread_pool_cleanup();
00293         mono->mono_thread_suspend_all_other_threads();
00294         mono->mono_runtime_quit();
00295         }
00296     }
00297 
00298     for (i=0; i<NUM_RUNTIMES; i++)
00299         if (runtimes[i].loaded_runtime)
00300             RuntimeHost_Destroy(runtimes[i].loaded_runtime);
00301 }
00302 
00303 void expect_no_runtimes(void)
00304 {
00305     int i;
00306 
00307     for (i=0; i<NUM_ABI_VERSIONS; i++)
00308     {
00309         loaded_mono *mono = &loaded_monos[i];
00310         if (mono->mono_handle && mono->is_started && !mono->is_shutdown)
00311         {
00312             ERR("Process exited with a Mono runtime loaded.\n");
00313             return;
00314         }
00315     }
00316 }
00317 
00318 static inline CLRRuntimeInfo *impl_from_ICLRRuntimeInfo(ICLRRuntimeInfo *iface)
00319 {
00320     return CONTAINING_RECORD(iface, CLRRuntimeInfo, ICLRRuntimeInfo_iface);
00321 }
00322 
00323 static HRESULT WINAPI CLRRuntimeInfo_QueryInterface(ICLRRuntimeInfo* iface,
00324         REFIID riid,
00325         void **ppvObject)
00326 {
00327     TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
00328 
00329     if ( IsEqualGUID( riid, &IID_ICLRRuntimeInfo ) ||
00330          IsEqualGUID( riid, &IID_IUnknown ) )
00331     {
00332         *ppvObject = iface;
00333     }
00334     else
00335     {
00336         FIXME("Unsupported interface %s\n", debugstr_guid(riid));
00337         return E_NOINTERFACE;
00338     }
00339 
00340     ICLRRuntimeInfo_AddRef( iface );
00341 
00342     return S_OK;
00343 }
00344 
00345 static ULONG WINAPI CLRRuntimeInfo_AddRef(ICLRRuntimeInfo* iface)
00346 {
00347     return 2;
00348 }
00349 
00350 static ULONG WINAPI CLRRuntimeInfo_Release(ICLRRuntimeInfo* iface)
00351 {
00352     return 1;
00353 }
00354 
00355 static HRESULT WINAPI CLRRuntimeInfo_GetVersionString(ICLRRuntimeInfo* iface,
00356     LPWSTR pwzBuffer, DWORD *pcchBuffer)
00357 {
00358     struct CLRRuntimeInfo *This = impl_from_ICLRRuntimeInfo(iface);
00359     DWORD buffer_size = *pcchBuffer;
00360     HRESULT hr = S_OK;
00361     char version[11];
00362     DWORD size;
00363 
00364     TRACE("%p %p %p\n", iface, pwzBuffer, pcchBuffer);
00365 
00366     size = snprintf(version, sizeof(version), "v%u.%u.%u", This->major, This->minor, This->build);
00367 
00368     assert(size <= sizeof(version));
00369 
00370     *pcchBuffer = MultiByteToWideChar(CP_UTF8, 0, version, -1, NULL, 0);
00371 
00372     if (pwzBuffer)
00373     {
00374         if (buffer_size >= *pcchBuffer)
00375             MultiByteToWideChar(CP_UTF8, 0, version, -1, pwzBuffer, buffer_size);
00376         else
00377             hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
00378     }
00379 
00380     return hr;
00381 }
00382 
00383 static BOOL get_install_root(LPWSTR install_dir)
00384 {
00385     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};
00386     const WCHAR install_root[] = {'I','n','s','t','a','l','l','R','o','o','t',0};
00387 
00388     DWORD len;
00389     HKEY key;
00390 
00391     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, dotnet_key, 0, KEY_READ, &key))
00392         return FALSE;
00393 
00394     len = MAX_PATH;
00395     if (RegQueryValueExW(key, install_root, 0, NULL, (LPBYTE)install_dir, &len))
00396     {
00397         RegCloseKey(key);
00398         return FALSE;
00399     }
00400     RegCloseKey(key);
00401 
00402     return TRUE;
00403 }
00404 
00405 static HRESULT WINAPI CLRRuntimeInfo_GetRuntimeDirectory(ICLRRuntimeInfo* iface,
00406     LPWSTR pwzBuffer, DWORD *pcchBuffer)
00407 {
00408     static const WCHAR slash[] = {'\\',0};
00409     DWORD buffer_size = *pcchBuffer;
00410     WCHAR system_dir[MAX_PATH];
00411     WCHAR version[MAX_PATH];
00412     DWORD version_size, size;
00413     HRESULT hr = S_OK;
00414 
00415     TRACE("%p %p %p\n", iface, pwzBuffer, pcchBuffer);
00416 
00417     if (!get_install_root(system_dir))
00418     {
00419         ERR("error reading registry key for installroot\n");
00420         return E_FAIL;
00421     }
00422     else
00423     {
00424         version_size = MAX_PATH;
00425         ICLRRuntimeInfo_GetVersionString(iface, version, &version_size);
00426         lstrcatW(system_dir, version);
00427         lstrcatW(system_dir, slash);
00428         size = lstrlenW(system_dir) + 1;
00429     }
00430 
00431     *pcchBuffer = size;
00432 
00433     if (pwzBuffer)
00434     {
00435         if (buffer_size >= size)
00436             strcpyW(pwzBuffer, system_dir);
00437         else
00438             hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
00439     }
00440 
00441     return hr;
00442 }
00443 
00444 static HRESULT WINAPI CLRRuntimeInfo_IsLoaded(ICLRRuntimeInfo* iface,
00445     HANDLE hndProcess, BOOL *pbLoaded)
00446 {
00447     FIXME("%p %p %p\n", iface, hndProcess, pbLoaded);
00448 
00449     return E_NOTIMPL;
00450 }
00451 
00452 static HRESULT WINAPI CLRRuntimeInfo_LoadErrorString(ICLRRuntimeInfo* iface,
00453     UINT iResourceID, LPWSTR pwzBuffer, DWORD *pcchBuffer, LONG iLocaleid)
00454 {
00455     FIXME("%p %u %p %p %x\n", iface, iResourceID, pwzBuffer, pcchBuffer, iLocaleid);
00456 
00457     return E_NOTIMPL;
00458 }
00459 
00460 static HRESULT WINAPI CLRRuntimeInfo_LoadLibrary(ICLRRuntimeInfo* iface,
00461     LPCWSTR pwzDllName, HMODULE *phndModule)
00462 {
00463     WCHAR version[MAX_PATH];
00464     HRESULT hr;
00465     DWORD cchBuffer;
00466 
00467     TRACE("%p %s %p\n", iface, debugstr_w(pwzDllName), phndModule);
00468 
00469     cchBuffer = MAX_PATH;
00470     hr = ICLRRuntimeInfo_GetVersionString(iface, version, &cchBuffer);
00471     if (FAILED(hr)) return hr;
00472 
00473     return LoadLibraryShim(pwzDllName, version, NULL, phndModule);
00474 }
00475 
00476 static HRESULT WINAPI CLRRuntimeInfo_GetProcAddress(ICLRRuntimeInfo* iface,
00477     LPCSTR pszProcName, LPVOID *ppProc)
00478 {
00479     FIXME("%p %s %p\n", iface, debugstr_a(pszProcName), ppProc);
00480 
00481     return E_NOTIMPL;
00482 }
00483 
00484 static HRESULT WINAPI CLRRuntimeInfo_GetInterface(ICLRRuntimeInfo* iface,
00485     REFCLSID rclsid, REFIID riid, LPVOID *ppUnk)
00486 {
00487     struct CLRRuntimeInfo *This = impl_from_ICLRRuntimeInfo(iface);
00488     RuntimeHost *host;
00489     HRESULT hr;
00490 
00491     TRACE("%p %s %s %p\n", iface, debugstr_guid(rclsid), debugstr_guid(riid), ppUnk);
00492 
00493     hr = CLRRuntimeInfo_GetRuntimeHost(This, &host);
00494 
00495     if (SUCCEEDED(hr))
00496         hr = RuntimeHost_GetInterface(host, rclsid, riid, ppUnk);
00497 
00498     return hr;
00499 }
00500 
00501 static HRESULT WINAPI CLRRuntimeInfo_IsLoadable(ICLRRuntimeInfo* iface,
00502     BOOL *pbLoadable)
00503 {
00504     FIXME("%p %p\n", iface, pbLoadable);
00505 
00506     return E_NOTIMPL;
00507 }
00508 
00509 static HRESULT WINAPI CLRRuntimeInfo_SetDefaultStartupFlags(ICLRRuntimeInfo* iface,
00510     DWORD dwStartupFlags, LPCWSTR pwzHostConfigFile)
00511 {
00512     FIXME("%p %x %s\n", iface, dwStartupFlags, debugstr_w(pwzHostConfigFile));
00513 
00514     return E_NOTIMPL;
00515 }
00516 
00517 static HRESULT WINAPI CLRRuntimeInfo_GetDefaultStartupFlags(ICLRRuntimeInfo* iface,
00518     DWORD *pdwStartupFlags, LPWSTR pwzHostConfigFile, DWORD *pcchHostConfigFile)
00519 {
00520     FIXME("%p %p %p %p\n", iface, pdwStartupFlags, pwzHostConfigFile, pcchHostConfigFile);
00521 
00522     return E_NOTIMPL;
00523 }
00524 
00525 static HRESULT WINAPI CLRRuntimeInfo_BindAsLegacyV2Runtime(ICLRRuntimeInfo* iface)
00526 {
00527     FIXME("%p\n", iface);
00528 
00529     return E_NOTIMPL;
00530 }
00531 
00532 static HRESULT WINAPI CLRRuntimeInfo_IsStarted(ICLRRuntimeInfo* iface,
00533     BOOL *pbStarted, DWORD *pdwStartupFlags)
00534 {
00535     FIXME("%p %p %p\n", iface, pbStarted, pdwStartupFlags);
00536 
00537     return E_NOTIMPL;
00538 }
00539 
00540 static const struct ICLRRuntimeInfoVtbl CLRRuntimeInfoVtbl = {
00541     CLRRuntimeInfo_QueryInterface,
00542     CLRRuntimeInfo_AddRef,
00543     CLRRuntimeInfo_Release,
00544     CLRRuntimeInfo_GetVersionString,
00545     CLRRuntimeInfo_GetRuntimeDirectory,
00546     CLRRuntimeInfo_IsLoaded,
00547     CLRRuntimeInfo_LoadErrorString,
00548     CLRRuntimeInfo_LoadLibrary,
00549     CLRRuntimeInfo_GetProcAddress,
00550     CLRRuntimeInfo_GetInterface,
00551     CLRRuntimeInfo_IsLoadable,
00552     CLRRuntimeInfo_SetDefaultStartupFlags,
00553     CLRRuntimeInfo_GetDefaultStartupFlags,
00554     CLRRuntimeInfo_BindAsLegacyV2Runtime,
00555     CLRRuntimeInfo_IsStarted
00556 };
00557 
00558 HRESULT ICLRRuntimeInfo_GetRuntimeHost(ICLRRuntimeInfo *iface, RuntimeHost **result)
00559 {
00560     struct CLRRuntimeInfo *This = impl_from_ICLRRuntimeInfo(iface);
00561 
00562     assert(This->ICLRRuntimeInfo_iface.lpVtbl == &CLRRuntimeInfoVtbl);
00563 
00564     return CLRRuntimeInfo_GetRuntimeHost(This, result);
00565 }
00566 
00567 static BOOL find_mono_dll(LPCWSTR path, LPWSTR dll_path, int abi_version)
00568 {
00569     static const WCHAR mono_dll[] = {'\\','b','i','n','\\','m','o','n','o','.','d','l','l',0};
00570     static const WCHAR libmono_dll[] = {'\\','b','i','n','\\','l','i','b','m','o','n','o','.','d','l','l',0};
00571     static const WCHAR mono2_dll[] = {'\\','b','i','n','\\','m','o','n','o','-','2','.','0','.','d','l','l',0};
00572     static const WCHAR libmono2_dll[] = {'\\','b','i','n','\\','l','i','b','m','o','n','o','-','2','.','0','.','d','l','l',0};
00573     DWORD attributes=INVALID_FILE_ATTRIBUTES;
00574 
00575     if (abi_version == 1)
00576     {
00577         strcpyW(dll_path, path);
00578         strcatW(dll_path, mono_dll);
00579         attributes = GetFileAttributesW(dll_path);
00580 
00581         if (attributes == INVALID_FILE_ATTRIBUTES)
00582         {
00583             strcpyW(dll_path, path);
00584             strcatW(dll_path, libmono_dll);
00585             attributes = GetFileAttributesW(dll_path);
00586         }
00587     }
00588     else if (abi_version == 2)
00589     {
00590         strcpyW(dll_path, path);
00591         strcatW(dll_path, mono2_dll);
00592         attributes = GetFileAttributesW(dll_path);
00593 
00594         if (attributes == INVALID_FILE_ATTRIBUTES)
00595         {
00596             strcpyW(dll_path, path);
00597             strcatW(dll_path, libmono2_dll);
00598             attributes = GetFileAttributesW(dll_path);
00599         }
00600     }
00601 
00602     return (attributes != INVALID_FILE_ATTRIBUTES);
00603 }
00604 
00605 static BOOL get_mono_path_from_registry(LPWSTR path, int abi_version)
00606 {
00607     static const WCHAR mono_key[] = {'S','o','f','t','w','a','r','e','\\','N','o','v','e','l','l','\\','M','o','n','o',0};
00608     static const WCHAR defaul_clr[] = {'D','e','f','a','u','l','t','C','L','R',0};
00609     static const WCHAR install_root[] = {'S','d','k','I','n','s','t','a','l','l','R','o','o','t',0};
00610     static const WCHAR slash[] = {'\\',0};
00611 
00612     WCHAR version[64], version_key[MAX_PATH];
00613     DWORD len;
00614     HKEY key;
00615     WCHAR dll_path[MAX_PATH];
00616 
00617     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, mono_key, 0, KEY_READ, &key))
00618         return FALSE;
00619 
00620     len = sizeof(version);
00621     if (RegQueryValueExW(key, defaul_clr, 0, NULL, (LPBYTE)version, &len))
00622     {
00623         RegCloseKey(key);
00624         return FALSE;
00625     }
00626     RegCloseKey(key);
00627 
00628     lstrcpyW(version_key, mono_key);
00629     lstrcatW(version_key, slash);
00630     lstrcatW(version_key, version);
00631 
00632     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, version_key, 0, KEY_READ, &key))
00633         return FALSE;
00634 
00635     len = sizeof(WCHAR) * MAX_PATH;
00636     if (RegQueryValueExW(key, install_root, 0, NULL, (LPBYTE)path, &len))
00637     {
00638         RegCloseKey(key);
00639         return FALSE;
00640     }
00641     RegCloseKey(key);
00642 
00643     return find_mono_dll(path, dll_path, abi_version);
00644 }
00645 
00646 static BOOL get_mono_path_from_folder(LPCWSTR folder, LPWSTR mono_path, int abi_version)
00647 {
00648     static const WCHAR mono_one_dot_zero[] = {'\\','m','o','n','o','-','1','.','0', 0};
00649     static const WCHAR mono_two_dot_zero[] = {'\\','m','o','n','o','-','2','.','0', 0};
00650     WCHAR mono_dll_path[MAX_PATH];
00651     BOOL found = FALSE;
00652 
00653     strcpyW(mono_path, folder);
00654 
00655     if (abi_version == 1)
00656         strcatW(mono_path, mono_one_dot_zero);
00657     else if (abi_version == 2)
00658         strcatW(mono_path, mono_two_dot_zero);
00659 
00660     found = find_mono_dll(mono_path, mono_dll_path, abi_version);
00661 
00662     return found;
00663 }
00664 
00665 static BOOL get_mono_path(LPWSTR path, int abi_version)
00666 {
00667     static const WCHAR subdir_mono[] = {'\\','m','o','n','o',0};
00668     static const WCHAR sibling_mono[] = {'\\','.','.','\\','m','o','n','o',0};
00669     WCHAR base_path[MAX_PATH];
00670     const char *unix_data_dir;
00671     WCHAR *dos_data_dir;
00672     int build_tree=0;
00673     static WCHAR* (CDECL *wine_get_dos_file_name)(const char*);
00674 
00675     /* First try c:\windows\mono */
00676     GetWindowsDirectoryW(base_path, MAX_PATH);
00677     strcatW(base_path, subdir_mono);
00678 
00679     if (get_mono_path_from_folder(base_path, path, abi_version))
00680         return TRUE;
00681 
00682     /* Next: /usr/share/wine/mono */
00683     unix_data_dir = wine_get_data_dir();
00684 
00685     if (!unix_data_dir)
00686     {
00687         unix_data_dir = wine_get_build_dir();
00688         build_tree = 1;
00689     }
00690 
00691     if (unix_data_dir)
00692     {
00693         if (!wine_get_dos_file_name)
00694             wine_get_dos_file_name = (void*)GetProcAddress(GetModuleHandleA("kernel32"), "wine_get_dos_file_name");
00695 
00696         if (wine_get_dos_file_name)
00697         {
00698             dos_data_dir = wine_get_dos_file_name(unix_data_dir);
00699 
00700             if (dos_data_dir)
00701             {
00702                 strcpyW(base_path, dos_data_dir);
00703                 strcatW(base_path, build_tree ? sibling_mono : subdir_mono);
00704 
00705                 HeapFree(GetProcessHeap(), 0, dos_data_dir);
00706 
00707                 if (get_mono_path_from_folder(base_path, path, abi_version))
00708                     return TRUE;
00709             }
00710         }
00711     }
00712 
00713     /* Last: the registry */
00714     return get_mono_path_from_registry(path, abi_version);
00715 }
00716 
00717 static void find_runtimes(void)
00718 {
00719     int abi_version, i;
00720     static const WCHAR libmono[] = {'\\','l','i','b','\\','m','o','n','o','\\',0};
00721     static const WCHAR mscorlib[] = {'\\','m','s','c','o','r','l','i','b','.','d','l','l',0};
00722     WCHAR mono_path[MAX_PATH], lib_path[MAX_PATH];
00723     BOOL any_runtimes_found = FALSE;
00724 
00725     if (runtimes_initialized) return;
00726 
00727     EnterCriticalSection(&runtime_list_cs);
00728 
00729     if (runtimes_initialized) goto end;
00730 
00731     for (abi_version=NUM_ABI_VERSIONS; abi_version>0; abi_version--)
00732     {
00733         if (!get_mono_path(mono_path, abi_version))
00734             continue;
00735 
00736         for (i=0; i<NUM_RUNTIMES; i++)
00737         {
00738             if (runtimes[i].mono_abi_version == 0)
00739             {
00740                 strcpyW(lib_path, mono_path);
00741                 strcatW(lib_path, libmono);
00742                 strcatW(lib_path, runtimes[i].mono_libdir);
00743                 strcatW(lib_path, mscorlib);
00744 
00745                 if (GetFileAttributesW(lib_path) != INVALID_FILE_ATTRIBUTES)
00746                 {
00747                     runtimes[i].mono_abi_version = abi_version;
00748 
00749                     strcpyW(runtimes[i].mono_path, mono_path);
00750                     strcpyW(runtimes[i].mscorlib_path, lib_path);
00751 
00752                     any_runtimes_found = TRUE;
00753                 }
00754             }
00755         }
00756     }
00757 
00758     if (!any_runtimes_found)
00759     {
00760         /* Report all runtimes are available if Mono isn't installed.
00761          * FIXME: Remove this when Mono is properly packaged. */
00762         for (i=0; i<NUM_RUNTIMES; i++)
00763             runtimes[i].mono_abi_version = -1;
00764     }
00765 
00766     runtimes_initialized = 1;
00767 
00768 end:
00769     LeaveCriticalSection(&runtime_list_cs);
00770 }
00771 
00772 struct InstalledRuntimeEnum
00773 {
00774     IEnumUnknown IEnumUnknown_iface;
00775     LONG ref;
00776     ULONG pos;
00777 };
00778 
00779 static const struct IEnumUnknownVtbl InstalledRuntimeEnum_Vtbl;
00780 
00781 static inline struct InstalledRuntimeEnum *impl_from_IEnumUnknown(IEnumUnknown *iface)
00782 {
00783     return CONTAINING_RECORD(iface, struct InstalledRuntimeEnum, IEnumUnknown_iface);
00784 }
00785 
00786 static HRESULT WINAPI InstalledRuntimeEnum_QueryInterface(IEnumUnknown* iface, REFIID riid,
00787         void **ppvObject)
00788 {
00789     TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
00790 
00791     if ( IsEqualGUID( riid, &IID_IEnumUnknown ) ||
00792          IsEqualGUID( riid, &IID_IUnknown ) )
00793     {
00794         *ppvObject = iface;
00795     }
00796     else
00797     {
00798         FIXME("Unsupported interface %s\n", debugstr_guid(riid));
00799         return E_NOINTERFACE;
00800     }
00801 
00802     IEnumUnknown_AddRef( iface );
00803 
00804     return S_OK;
00805 }
00806 
00807 static ULONG WINAPI InstalledRuntimeEnum_AddRef(IEnumUnknown* iface)
00808 {
00809     struct InstalledRuntimeEnum *This = impl_from_IEnumUnknown(iface);
00810     ULONG ref = InterlockedIncrement(&This->ref);
00811 
00812     TRACE("(%p) refcount=%u\n", iface, ref);
00813 
00814     return ref;
00815 }
00816 
00817 static ULONG WINAPI InstalledRuntimeEnum_Release(IEnumUnknown* iface)
00818 {
00819     struct InstalledRuntimeEnum *This = impl_from_IEnumUnknown(iface);
00820     ULONG ref = InterlockedDecrement(&This->ref);
00821 
00822     TRACE("(%p) refcount=%u\n", iface, ref);
00823 
00824     if (ref == 0)
00825     {
00826         HeapFree(GetProcessHeap(), 0, This);
00827     }
00828 
00829     return ref;
00830 }
00831 
00832 static HRESULT WINAPI InstalledRuntimeEnum_Next(IEnumUnknown *iface, ULONG celt,
00833     IUnknown **rgelt, ULONG *pceltFetched)
00834 {
00835     struct InstalledRuntimeEnum *This = impl_from_IEnumUnknown(iface);
00836     int num_fetched = 0;
00837     HRESULT hr=S_OK;
00838     IUnknown *item;
00839 
00840     TRACE("(%p,%u,%p,%p)\n", iface, celt, rgelt, pceltFetched);
00841 
00842     while (num_fetched < celt)
00843     {
00844         if (This->pos >= NUM_RUNTIMES)
00845         {
00846             hr = S_FALSE;
00847             break;
00848         }
00849         if (runtimes[This->pos].mono_abi_version)
00850         {
00851             item = (IUnknown*)&runtimes[This->pos].ICLRRuntimeInfo_iface;
00852             IUnknown_AddRef(item);
00853             rgelt[num_fetched] = item;
00854             num_fetched++;
00855         }
00856         This->pos++;
00857     }
00858 
00859     if (pceltFetched)
00860         *pceltFetched = num_fetched;
00861 
00862     return hr;
00863 }
00864 
00865 static HRESULT WINAPI InstalledRuntimeEnum_Skip(IEnumUnknown *iface, ULONG celt)
00866 {
00867     struct InstalledRuntimeEnum *This = impl_from_IEnumUnknown(iface);
00868     int num_fetched = 0;
00869     HRESULT hr=S_OK;
00870 
00871     TRACE("(%p,%u)\n", iface, celt);
00872 
00873     while (num_fetched < celt)
00874     {
00875         if (This->pos >= NUM_RUNTIMES)
00876         {
00877             hr = S_FALSE;
00878             break;
00879         }
00880         if (runtimes[This->pos].mono_abi_version)
00881         {
00882             num_fetched++;
00883         }
00884         This->pos++;
00885     }
00886 
00887     return hr;
00888 }
00889 
00890 static HRESULT WINAPI InstalledRuntimeEnum_Reset(IEnumUnknown *iface)
00891 {
00892     struct InstalledRuntimeEnum *This = impl_from_IEnumUnknown(iface);
00893 
00894     TRACE("(%p)\n", iface);
00895 
00896     This->pos = 0;
00897 
00898     return S_OK;
00899 }
00900 
00901 static HRESULT WINAPI InstalledRuntimeEnum_Clone(IEnumUnknown *iface, IEnumUnknown **ppenum)
00902 {
00903     struct InstalledRuntimeEnum *This = impl_from_IEnumUnknown(iface);
00904     struct InstalledRuntimeEnum *new_enum;
00905 
00906     TRACE("(%p)\n", iface);
00907 
00908     new_enum = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_enum));
00909     if (!new_enum)
00910         return E_OUTOFMEMORY;
00911 
00912     new_enum->IEnumUnknown_iface.lpVtbl = &InstalledRuntimeEnum_Vtbl;
00913     new_enum->ref = 1;
00914     new_enum->pos = This->pos;
00915 
00916     *ppenum = &new_enum->IEnumUnknown_iface;
00917 
00918     return S_OK;
00919 }
00920 
00921 static const struct IEnumUnknownVtbl InstalledRuntimeEnum_Vtbl = {
00922     InstalledRuntimeEnum_QueryInterface,
00923     InstalledRuntimeEnum_AddRef,
00924     InstalledRuntimeEnum_Release,
00925     InstalledRuntimeEnum_Next,
00926     InstalledRuntimeEnum_Skip,
00927     InstalledRuntimeEnum_Reset,
00928     InstalledRuntimeEnum_Clone
00929 };
00930 
00931 struct CLRMetaHost
00932 {
00933     ICLRMetaHost ICLRMetaHost_iface;
00934 };
00935 
00936 static struct CLRMetaHost GlobalCLRMetaHost;
00937 
00938 static HRESULT WINAPI CLRMetaHost_QueryInterface(ICLRMetaHost* iface,
00939         REFIID riid,
00940         void **ppvObject)
00941 {
00942     TRACE("%s %p\n", debugstr_guid(riid), ppvObject);
00943 
00944     if ( IsEqualGUID( riid, &IID_ICLRMetaHost ) ||
00945          IsEqualGUID( riid, &IID_IUnknown ) )
00946     {
00947         *ppvObject = iface;
00948     }
00949     else
00950     {
00951         FIXME("Unsupported interface %s\n", debugstr_guid(riid));
00952         return E_NOINTERFACE;
00953     }
00954 
00955     ICLRMetaHost_AddRef( iface );
00956 
00957     return S_OK;
00958 }
00959 
00960 static ULONG WINAPI CLRMetaHost_AddRef(ICLRMetaHost* iface)
00961 {
00962     return 2;
00963 }
00964 
00965 static ULONG WINAPI CLRMetaHost_Release(ICLRMetaHost* iface)
00966 {
00967     return 1;
00968 }
00969 
00970 static BOOL parse_runtime_version(LPCWSTR version, DWORD *major, DWORD *minor, DWORD *build)
00971 {
00972     *major = 0;
00973     *minor = 0;
00974     *build = 0;
00975 
00976     if (version[0] == 'v')
00977     {
00978         version++;
00979         if (!isdigit(*version))
00980             return FALSE;
00981 
00982         while (isdigit(*version))
00983             *major = *major * 10 + (*version++ - '0');
00984 
00985         if (*version == 0)
00986             return TRUE;
00987 
00988         if (*version++ != '.' || !isdigit(*version))
00989             return FALSE;
00990 
00991         while (isdigit(*version))
00992             *minor = *minor * 10 + (*version++ - '0');
00993 
00994         if (*version == 0)
00995             return TRUE;
00996 
00997         if (*version++ != '.' || !isdigit(*version))
00998             return FALSE;
00999 
01000         while (isdigit(*version))
01001             *build = *build * 10 + (*version++ - '0');
01002 
01003         return *version == 0;
01004     }
01005     else
01006         return FALSE;
01007 }
01008 
01009 HRESULT WINAPI CLRMetaHost_GetRuntime(ICLRMetaHost* iface,
01010     LPCWSTR pwzVersion, REFIID iid, LPVOID *ppRuntime)
01011 {
01012     int i;
01013     DWORD major, minor, build;
01014 
01015     TRACE("%s %s %p\n", debugstr_w(pwzVersion), debugstr_guid(iid), ppRuntime);
01016 
01017     if (!pwzVersion)
01018         return E_POINTER;
01019 
01020     if (!parse_runtime_version(pwzVersion, &major, &minor, &build))
01021     {
01022         ERR("Cannot parse %s\n", debugstr_w(pwzVersion));
01023         return CLR_E_SHIM_RUNTIME;
01024     }
01025 
01026     find_runtimes();
01027 
01028     for (i=0; i<NUM_RUNTIMES; i++)
01029     {
01030         if (runtimes[i].major == major && runtimes[i].minor == minor &&
01031             runtimes[i].build == build)
01032         {
01033             if (runtimes[i].mono_abi_version)
01034                 return ICLRRuntimeInfo_QueryInterface(&runtimes[i].ICLRRuntimeInfo_iface, iid,
01035                         ppRuntime);
01036             else
01037             {
01038                 missing_runtime_message(&runtimes[i]);
01039                 return CLR_E_SHIM_RUNTIME;
01040             }
01041         }
01042     }
01043 
01044     FIXME("Unrecognized version %s\n", debugstr_w(pwzVersion));
01045     return CLR_E_SHIM_RUNTIME;
01046 }
01047 
01048 HRESULT WINAPI CLRMetaHost_GetVersionFromFile(ICLRMetaHost* iface,
01049     LPCWSTR pwzFilePath, LPWSTR pwzBuffer, DWORD *pcchBuffer)
01050 {
01051     ASSEMBLY *assembly;
01052     HRESULT hr;
01053     LPSTR version;
01054     ULONG buffer_size=*pcchBuffer;
01055 
01056     TRACE("%s %p %p\n", debugstr_w(pwzFilePath), pwzBuffer, pcchBuffer);
01057 
01058     hr = assembly_create(&assembly, pwzFilePath);
01059 
01060     if (SUCCEEDED(hr))
01061     {
01062         hr = assembly_get_runtime_version(assembly, &version);
01063 
01064         if (SUCCEEDED(hr))
01065         {
01066             *pcchBuffer = MultiByteToWideChar(CP_UTF8, 0, version, -1, NULL, 0);
01067 
01068             if (pwzBuffer)
01069             {
01070                 if (buffer_size >= *pcchBuffer)
01071                     MultiByteToWideChar(CP_UTF8, 0, version, -1, pwzBuffer, buffer_size);
01072                 else
01073                     hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
01074             }
01075         }
01076 
01077         assembly_release(assembly);
01078     }
01079 
01080     return hr;
01081 }
01082 
01083 static HRESULT WINAPI CLRMetaHost_EnumerateInstalledRuntimes(ICLRMetaHost* iface,
01084     IEnumUnknown **ppEnumerator)
01085 {
01086     struct InstalledRuntimeEnum *new_enum;
01087 
01088     TRACE("%p\n", ppEnumerator);
01089 
01090     find_runtimes();
01091 
01092     new_enum = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_enum));
01093     if (!new_enum)
01094         return E_OUTOFMEMORY;
01095 
01096     new_enum->IEnumUnknown_iface.lpVtbl = &InstalledRuntimeEnum_Vtbl;
01097     new_enum->ref = 1;
01098     new_enum->pos = 0;
01099 
01100     *ppEnumerator = &new_enum->IEnumUnknown_iface;
01101 
01102     return S_OK;
01103 }
01104 
01105 static HRESULT WINAPI CLRMetaHost_EnumerateLoadedRuntimes(ICLRMetaHost* iface,
01106     HANDLE hndProcess, IEnumUnknown **ppEnumerator)
01107 {
01108     FIXME("%p %p\n", hndProcess, ppEnumerator);
01109 
01110     return E_NOTIMPL;
01111 }
01112 
01113 static HRESULT WINAPI CLRMetaHost_RequestRuntimeLoadedNotification(ICLRMetaHost* iface,
01114     RuntimeLoadedCallbackFnPtr pCallbackFunction)
01115 {
01116     FIXME("%p\n", pCallbackFunction);
01117 
01118     return E_NOTIMPL;
01119 }
01120 
01121 static HRESULT WINAPI CLRMetaHost_QueryLegacyV2RuntimeBinding(ICLRMetaHost* iface,
01122     REFIID riid, LPVOID *ppUnk)
01123 {
01124     FIXME("%s %p\n", debugstr_guid(riid), ppUnk);
01125 
01126     return E_NOTIMPL;
01127 }
01128 
01129 static HRESULT WINAPI CLRMetaHost_ExitProcess(ICLRMetaHost* iface, INT32 iExitCode)
01130 {
01131     FIXME("%i: stub\n", iExitCode);
01132 
01133     ExitProcess(iExitCode);
01134 }
01135 
01136 static const struct ICLRMetaHostVtbl CLRMetaHost_vtbl =
01137 {
01138     CLRMetaHost_QueryInterface,
01139     CLRMetaHost_AddRef,
01140     CLRMetaHost_Release,
01141     CLRMetaHost_GetRuntime,
01142     CLRMetaHost_GetVersionFromFile,
01143     CLRMetaHost_EnumerateInstalledRuntimes,
01144     CLRMetaHost_EnumerateLoadedRuntimes,
01145     CLRMetaHost_RequestRuntimeLoadedNotification,
01146     CLRMetaHost_QueryLegacyV2RuntimeBinding,
01147     CLRMetaHost_ExitProcess
01148 };
01149 
01150 static struct CLRMetaHost GlobalCLRMetaHost = {
01151     { &CLRMetaHost_vtbl }
01152 };
01153 
01154 HRESULT CLRMetaHost_CreateInstance(REFIID riid, void **ppobj)
01155 {
01156     return ICLRMetaHost_QueryInterface(&GlobalCLRMetaHost.ICLRMetaHost_iface, riid, ppobj);
01157 }
01158 
01159 static MonoAssembly* mono_assembly_search_hook_fn(MonoAssemblyName *aname, char **assemblies_path, void *user_data)
01160 {
01161     loaded_mono *mono = user_data;
01162     HRESULT hr=S_OK;
01163     MonoAssembly *result=NULL;
01164     char *stringname=NULL;
01165     LPWSTR stringnameW;
01166     int stringnameW_size;
01167     IAssemblyCache *asmcache;
01168     ASSEMBLY_INFO info;
01169     WCHAR path[MAX_PATH];
01170     char *pathA;
01171     MonoImageOpenStatus stat;
01172     static WCHAR fusiondll[] = {'f','u','s','i','o','n',0};
01173     HMODULE hfusion=NULL;
01174     static HRESULT (WINAPI *pCreateAssemblyCache)(IAssemblyCache**,DWORD);
01175 
01176     stringname = mono->mono_stringify_assembly_name(aname);
01177 
01178     TRACE("%s\n", debugstr_a(stringname));
01179 
01180     if (!stringname) return NULL;
01181 
01182     /* FIXME: We should search the given paths before the GAC. */
01183 
01184     if (!pCreateAssemblyCache)
01185     {
01186         hr = LoadLibraryShim(fusiondll, NULL, NULL, &hfusion);
01187 
01188         if (SUCCEEDED(hr))
01189         {
01190             pCreateAssemblyCache = (void*)GetProcAddress(hfusion, "CreateAssemblyCache");
01191             if (!pCreateAssemblyCache)
01192                 hr = E_FAIL;
01193         }
01194     }
01195 
01196     if (SUCCEEDED(hr))
01197         hr = pCreateAssemblyCache(&asmcache, 0);
01198 
01199     if (SUCCEEDED(hr))
01200     {
01201         stringnameW_size = MultiByteToWideChar(CP_UTF8, 0, stringname, -1, NULL, 0);
01202 
01203         stringnameW = HeapAlloc(GetProcessHeap(), 0, stringnameW_size * sizeof(WCHAR));
01204         if (stringnameW)
01205             MultiByteToWideChar(CP_UTF8, 0, stringname, -1, stringnameW, stringnameW_size);
01206         else
01207             hr = E_OUTOFMEMORY;
01208 
01209         if (SUCCEEDED(hr))
01210         {
01211             info.cbAssemblyInfo = sizeof(info);
01212             info.pszCurrentAssemblyPathBuf = path;
01213             info.cchBuf = MAX_PATH;
01214             path[0] = 0;
01215 
01216             hr = IAssemblyCache_QueryAssemblyInfo(asmcache, 0, stringnameW, &info);
01217         }
01218 
01219         HeapFree(GetProcessHeap(), 0, stringnameW);
01220 
01221         IAssemblyCache_Release(asmcache);
01222     }
01223 
01224     if (SUCCEEDED(hr))
01225     {
01226         TRACE("found: %s\n", debugstr_w(path));
01227 
01228         pathA = WtoA(path);
01229 
01230         if (pathA)
01231         {
01232             result = mono->mono_assembly_open(pathA, &stat);
01233 
01234             if (!result)
01235                 ERR("Failed to load %s, status=%u\n", debugstr_w(path), stat);
01236 
01237             HeapFree(GetProcessHeap(), 0, pathA);
01238         }
01239     }
01240 
01241     mono->mono_free(stringname);
01242 
01243     return result;
01244 }
01245 
01246 HRESULT get_runtime_info(LPCWSTR exefile, LPCWSTR version, LPCWSTR config_file,
01247     DWORD startup_flags, DWORD runtimeinfo_flags, BOOL legacy, ICLRRuntimeInfo **result)
01248 {
01249     static const WCHAR dotconfig[] = {'.','c','o','n','f','i','g',0};
01250     static const DWORD supported_startup_flags = 0;
01251     static const DWORD supported_runtime_flags = RUNTIME_INFO_UPGRADE_VERSION;
01252     int i;
01253     WCHAR local_version[MAX_PATH];
01254     ULONG local_version_size = MAX_PATH;
01255     WCHAR local_config_file[MAX_PATH];
01256     HRESULT hr;
01257     parsed_config_file parsed_config;
01258 
01259     if (startup_flags & ~supported_startup_flags)
01260         FIXME("unsupported startup flags %x\n", startup_flags & ~supported_startup_flags);
01261 
01262     if (runtimeinfo_flags & ~supported_runtime_flags)
01263         FIXME("unsupported runtimeinfo flags %x\n", runtimeinfo_flags & ~supported_runtime_flags);
01264 
01265     if (exefile && !config_file)
01266     {
01267         strcpyW(local_config_file, exefile);
01268         strcatW(local_config_file, dotconfig);
01269 
01270         config_file = local_config_file;
01271     }
01272 
01273     if (config_file)
01274     {
01275         int found=0;
01276         hr = parse_config_file(config_file, &parsed_config);
01277 
01278         if (SUCCEEDED(hr))
01279         {
01280             supported_runtime *entry;
01281             LIST_FOR_EACH_ENTRY(entry, &parsed_config.supported_runtimes, supported_runtime, entry)
01282             {
01283                 hr = CLRMetaHost_GetRuntime(0, entry->version, &IID_ICLRRuntimeInfo, (void**)result);
01284                 if (SUCCEEDED(hr))
01285                 {
01286                     found = 1;
01287                     break;
01288                 }
01289             }
01290         }
01291         else
01292         {
01293             WARN("failed to parse config file %s, hr=%x\n", debugstr_w(config_file), hr);
01294         }
01295 
01296         free_parsed_config_file(&parsed_config);
01297 
01298         if (found)
01299             return S_OK;
01300     }
01301 
01302     if (exefile && !version)
01303     {
01304         hr = CLRMetaHost_GetVersionFromFile(0, exefile, local_version, &local_version_size);
01305 
01306         version = local_version;
01307 
01308         if (FAILED(hr)) return hr;
01309     }
01310 
01311     if (version)
01312     {
01313         return CLRMetaHost_GetRuntime(0, version, &IID_ICLRRuntimeInfo, (void**)result);
01314     }
01315 
01316     if (runtimeinfo_flags & RUNTIME_INFO_UPGRADE_VERSION)
01317     {
01318         find_runtimes();
01319 
01320         if (legacy)
01321             i = 2;
01322         else
01323             i = NUM_RUNTIMES;
01324 
01325         while (i--)
01326         {
01327             if (runtimes[i].mono_abi_version)
01328                 return ICLRRuntimeInfo_QueryInterface(&runtimes[i].ICLRRuntimeInfo_iface,
01329                         &IID_ICLRRuntimeInfo, (void **)result);
01330         }
01331 
01332         if (legacy)
01333             missing_runtime_message(&runtimes[1]);
01334         else
01335             missing_runtime_message(&runtimes[NUM_RUNTIMES-1]);
01336 
01337         return CLR_E_SHIM_RUNTIME;
01338     }
01339 
01340     return CLR_E_SHIM_RUNTIME;
01341 }

Generated on Sun May 27 2012 04:24:48 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.