wined3d: Don't unnecessarily fallback to immediate mode for FFP draws with the PSIZE...
[wine.git] / dlls / mscoree / metahost.c
blobfb0068df1eaeb5acf5a84faa242c6e513e6fefdb
1 /*
2 * ICLRMetaHost - discovery and management of available .NET runtimes
4 * Copyright 2010 Vincent Povirk for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <assert.h>
25 #define COBJMACROS
27 #include "wine/unicode.h"
28 #include "wine/library.h"
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winreg.h"
32 #include "ole2.h"
34 #include "corerror.h"
35 #include "cor.h"
36 #include "mscoree.h"
37 #include "corhdr.h"
38 #include "cordebug.h"
39 #include "metahost.h"
40 #include "fusion.h"
41 #include "wine/list.h"
42 #include "mscoree_private.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
48 static const struct ICLRRuntimeInfoVtbl CLRRuntimeInfoVtbl;
50 #define NUM_RUNTIMES 4
52 static struct CLRRuntimeInfo runtimes[NUM_RUNTIMES] = {
53 {{&CLRRuntimeInfoVtbl}, 1, 0, 3705, 0},
54 {{&CLRRuntimeInfoVtbl}, 1, 1, 4322, 0},
55 {{&CLRRuntimeInfoVtbl}, 2, 0, 50727, 0},
56 {{&CLRRuntimeInfoVtbl}, 4, 0, 30319, 0}
59 static CRITICAL_SECTION runtime_list_cs;
60 static CRITICAL_SECTION_DEBUG runtime_list_cs_debug =
62 0, 0, &runtime_list_cs,
63 { &runtime_list_cs_debug.ProcessLocksList,
64 &runtime_list_cs_debug.ProcessLocksList },
65 0, 0, { (DWORD_PTR)(__FILE__ ": runtime_list_cs") }
67 static CRITICAL_SECTION runtime_list_cs = { &runtime_list_cs_debug, -1, 0, 0, 0, 0 };
69 static HMODULE mono_handle;
71 BOOL is_mono_started;
72 static BOOL is_mono_shutdown;
74 MonoImage* (CDECL *mono_assembly_get_image)(MonoAssembly *assembly);
75 MonoAssembly* (CDECL *mono_assembly_load_from)(MonoImage *image, const char *fname, MonoImageOpenStatus *status);
76 MonoAssembly* (CDECL *mono_assembly_open)(const char *filename, MonoImageOpenStatus *status);
77 MonoClass* (CDECL *mono_class_from_mono_type)(MonoType *type);
78 MonoClass* (CDECL *mono_class_from_name)(MonoImage *image, const char* name_space, const char *name);
79 MonoMethod* (CDECL *mono_class_get_method_from_name)(MonoClass *klass, const char *name, int param_count);
80 static void (CDECL *mono_config_parse)(const char *filename);
81 MonoAssembly* (CDECL *mono_domain_assembly_open)(MonoDomain *domain, const char *name);
82 static void (CDECL *mono_free)(void *);
83 static MonoImage* (CDECL *mono_image_open)(const char *fname, MonoImageOpenStatus *status);
84 MonoImage* (CDECL *mono_image_open_from_module_handle)(HMODULE module_handle, char* fname, UINT has_entry_point, MonoImageOpenStatus* status);
85 static void (CDECL *mono_install_assembly_preload_hook)(MonoAssemblyPreLoadFunc func, void *user_data);
86 int (CDECL *mono_jit_exec)(MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[]);
87 MonoDomain* (CDECL *mono_jit_init_version)(const char *domain_name, const char *runtime_version);
88 static int (CDECL *mono_jit_set_trace_options)(const char* options);
89 void* (CDECL *mono_marshal_get_vtfixup_ftnptr)(MonoImage *image, DWORD token, WORD type);
90 MonoDomain* (CDECL *mono_object_get_domain)(MonoObject *obj);
91 MonoObject* (CDECL *mono_object_new)(MonoDomain *domain, MonoClass *klass);
92 void* (CDECL *mono_object_unbox)(MonoObject *obj);
93 static void (CDECL *mono_profiler_install)(MonoProfiler *prof, MonoProfileFunc shutdown_callback);
94 MonoType* (CDECL *mono_reflection_type_from_name)(char *name, MonoImage *image);
95 MonoObject* (CDECL *mono_runtime_invoke)(MonoMethod *method, void *obj, void **params, MonoObject **exc);
96 void (CDECL *mono_runtime_object_init)(MonoObject *this_obj);
97 void (CDECL *mono_runtime_quit)(void);
98 static void (CDECL *mono_set_dirs)(const char *assembly_dir, const char *config_dir);
99 static void (CDECL *mono_set_verbose_level)(DWORD level);
100 MonoString* (CDECL *mono_string_new)(MonoDomain *domain, const char *str);
101 static char* (CDECL *mono_stringify_assembly_name)(MonoAssemblyName *aname);
102 MonoThread* (CDECL *mono_thread_attach)(MonoDomain *domain);
103 void (CDECL *mono_thread_manage)(void);
104 void (CDECL *mono_trace_set_assembly)(MonoAssembly *assembly);
106 static BOOL get_mono_path(LPWSTR path);
108 static BOOL find_mono_dll(LPCWSTR path, LPWSTR dll_path);
110 static MonoAssembly* mono_assembly_preload_hook_fn(MonoAssemblyName *aname, char **assemblies_path, void *user_data);
112 static void mono_shutdown_callback_fn(MonoProfiler *prof);
114 static void set_environment(LPCWSTR bin_path)
116 WCHAR path_env[MAX_PATH];
117 int len;
119 static const WCHAR pathW[] = {'P','A','T','H',0};
121 /* We have to modify PATH as Mono loads other DLLs from this directory. */
122 GetEnvironmentVariableW(pathW, path_env, sizeof(path_env)/sizeof(WCHAR));
123 len = strlenW(path_env);
124 path_env[len++] = ';';
125 strcpyW(path_env+len, bin_path);
126 SetEnvironmentVariableW(pathW, path_env);
129 static MonoImage* CDECL image_open_module_handle_dummy(HMODULE module_handle,
130 char* fname, UINT has_entry_point, MonoImageOpenStatus* status)
132 return mono_image_open(fname, status);
135 static void missing_runtime_message(void)
137 MESSAGE("wine: Install Mono for Windows to run .NET applications.\n");
140 static HRESULT load_mono(LPCWSTR mono_path)
142 static const WCHAR bin[] = {'\\','b','i','n',0};
143 static const WCHAR lib[] = {'\\','l','i','b',0};
144 static const WCHAR etc[] = {'\\','e','t','c',0};
145 WCHAR mono_dll_path[MAX_PATH+16], mono_bin_path[MAX_PATH+4];
146 WCHAR mono_lib_path[MAX_PATH+4], mono_etc_path[MAX_PATH+4];
147 char mono_lib_path_a[MAX_PATH], mono_etc_path_a[MAX_PATH];
148 int trace_size;
149 char trace_setting[256];
150 int verbose_size;
151 char verbose_setting[256];
153 if (is_mono_shutdown)
155 ERR("Cannot load Mono after it has been shut down.\n");
156 return E_FAIL;
159 if (!mono_handle)
161 strcpyW(mono_bin_path, mono_path);
162 strcatW(mono_bin_path, bin);
163 set_environment(mono_bin_path);
165 strcpyW(mono_lib_path, mono_path);
166 strcatW(mono_lib_path, lib);
167 WideCharToMultiByte(CP_UTF8, 0, mono_lib_path, -1, mono_lib_path_a, MAX_PATH, NULL, NULL);
169 strcpyW(mono_etc_path, mono_path);
170 strcatW(mono_etc_path, etc);
171 WideCharToMultiByte(CP_UTF8, 0, mono_etc_path, -1, mono_etc_path_a, MAX_PATH, NULL, NULL);
173 if (!find_mono_dll(mono_path, mono_dll_path)) goto fail;
175 mono_handle = LoadLibraryW(mono_dll_path);
177 if (!mono_handle) goto fail;
179 #define LOAD_MONO_FUNCTION(x) do { \
180 x = (void*)GetProcAddress(mono_handle, #x); \
181 if (!x) { \
182 goto fail; \
184 } while (0);
186 LOAD_MONO_FUNCTION(mono_assembly_get_image);
187 LOAD_MONO_FUNCTION(mono_assembly_load_from);
188 LOAD_MONO_FUNCTION(mono_assembly_open);
189 LOAD_MONO_FUNCTION(mono_config_parse);
190 LOAD_MONO_FUNCTION(mono_class_from_mono_type);
191 LOAD_MONO_FUNCTION(mono_class_from_name);
192 LOAD_MONO_FUNCTION(mono_class_get_method_from_name);
193 LOAD_MONO_FUNCTION(mono_domain_assembly_open);
194 LOAD_MONO_FUNCTION(mono_free);
195 LOAD_MONO_FUNCTION(mono_image_open);
196 LOAD_MONO_FUNCTION(mono_install_assembly_preload_hook);
197 LOAD_MONO_FUNCTION(mono_jit_exec);
198 LOAD_MONO_FUNCTION(mono_jit_init_version);
199 LOAD_MONO_FUNCTION(mono_jit_set_trace_options);
200 LOAD_MONO_FUNCTION(mono_marshal_get_vtfixup_ftnptr);
201 LOAD_MONO_FUNCTION(mono_object_get_domain);
202 LOAD_MONO_FUNCTION(mono_object_new);
203 LOAD_MONO_FUNCTION(mono_object_unbox);
204 LOAD_MONO_FUNCTION(mono_profiler_install);
205 LOAD_MONO_FUNCTION(mono_reflection_type_from_name);
206 LOAD_MONO_FUNCTION(mono_runtime_invoke);
207 LOAD_MONO_FUNCTION(mono_runtime_object_init);
208 LOAD_MONO_FUNCTION(mono_runtime_quit);
209 LOAD_MONO_FUNCTION(mono_set_dirs);
210 LOAD_MONO_FUNCTION(mono_set_verbose_level);
211 LOAD_MONO_FUNCTION(mono_stringify_assembly_name);
212 LOAD_MONO_FUNCTION(mono_string_new);
213 LOAD_MONO_FUNCTION(mono_thread_attach);
214 LOAD_MONO_FUNCTION(mono_thread_manage);
215 LOAD_MONO_FUNCTION(mono_trace_set_assembly);
217 #undef LOAD_MONO_FUNCTION
219 #define LOAD_OPT_MONO_FUNCTION(x, default) do { \
220 x = (void*)GetProcAddress(mono_handle, #x); \
221 if (!x) { \
222 x = default; \
224 } while (0);
226 LOAD_OPT_MONO_FUNCTION(mono_image_open_from_module_handle, image_open_module_handle_dummy);
228 #undef LOAD_OPT_MONO_FUNCTION
230 mono_profiler_install(NULL, mono_shutdown_callback_fn);
232 mono_set_dirs(mono_lib_path_a, mono_etc_path_a);
234 mono_config_parse(NULL);
236 mono_install_assembly_preload_hook(mono_assembly_preload_hook_fn, NULL);
238 trace_size = GetEnvironmentVariableA("WINE_MONO_TRACE", trace_setting, sizeof(trace_setting));
240 if (trace_size)
242 mono_jit_set_trace_options(trace_setting);
245 verbose_size = GetEnvironmentVariableA("WINE_MONO_VERBOSE", verbose_setting, sizeof(verbose_setting));
247 if (verbose_size)
249 mono_set_verbose_level(verbose_setting[0] - '0');
253 return S_OK;
255 fail:
256 ERR("Could not load Mono into this process\n");
257 FreeLibrary(mono_handle);
258 mono_handle = NULL;
259 return E_FAIL;
262 static void mono_shutdown_callback_fn(MonoProfiler *prof)
264 is_mono_shutdown = TRUE;
267 static HRESULT CLRRuntimeInfo_GetRuntimeHost(CLRRuntimeInfo *This, RuntimeHost **result)
269 HRESULT hr = S_OK;
270 WCHAR mono_path[MAX_PATH];
272 if (This->loaded_runtime)
274 *result = This->loaded_runtime;
275 return hr;
278 if (!get_mono_path(mono_path))
280 missing_runtime_message();
281 return CLR_E_SHIM_RUNTIME;
284 EnterCriticalSection(&runtime_list_cs);
286 hr = load_mono(mono_path);
288 if (SUCCEEDED(hr))
289 hr = RuntimeHost_Construct(This, &This->loaded_runtime);
291 LeaveCriticalSection(&runtime_list_cs);
293 if (SUCCEEDED(hr))
294 *result = This->loaded_runtime;
296 return hr;
299 void expect_no_runtimes(void)
301 if (mono_handle && is_mono_started && !is_mono_shutdown)
303 ERR("Process exited with a Mono runtime loaded.\n");
304 return;
308 static inline CLRRuntimeInfo *impl_from_ICLRRuntimeInfo(ICLRRuntimeInfo *iface)
310 return CONTAINING_RECORD(iface, CLRRuntimeInfo, ICLRRuntimeInfo_iface);
313 static HRESULT WINAPI CLRRuntimeInfo_QueryInterface(ICLRRuntimeInfo* iface,
314 REFIID riid,
315 void **ppvObject)
317 TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
319 if ( IsEqualGUID( riid, &IID_ICLRRuntimeInfo ) ||
320 IsEqualGUID( riid, &IID_IUnknown ) )
322 *ppvObject = iface;
324 else
326 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
327 return E_NOINTERFACE;
330 ICLRRuntimeInfo_AddRef( iface );
332 return S_OK;
335 static ULONG WINAPI CLRRuntimeInfo_AddRef(ICLRRuntimeInfo* iface)
337 return 2;
340 static ULONG WINAPI CLRRuntimeInfo_Release(ICLRRuntimeInfo* iface)
342 return 1;
345 static HRESULT WINAPI CLRRuntimeInfo_GetVersionString(ICLRRuntimeInfo* iface,
346 LPWSTR pwzBuffer, DWORD *pcchBuffer)
348 struct CLRRuntimeInfo *This = impl_from_ICLRRuntimeInfo(iface);
349 DWORD buffer_size = *pcchBuffer;
350 HRESULT hr = S_OK;
351 char version[11];
352 DWORD size;
354 TRACE("%p %p %p\n", iface, pwzBuffer, pcchBuffer);
356 size = snprintf(version, sizeof(version), "v%u.%u.%u", This->major, This->minor, This->build);
358 assert(size <= sizeof(version));
360 *pcchBuffer = MultiByteToWideChar(CP_UTF8, 0, version, -1, NULL, 0);
362 if (pwzBuffer)
364 if (buffer_size >= *pcchBuffer)
365 MultiByteToWideChar(CP_UTF8, 0, version, -1, pwzBuffer, buffer_size);
366 else
367 hr = E_NOT_SUFFICIENT_BUFFER;
370 return hr;
373 static BOOL get_install_root(LPWSTR install_dir)
375 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};
376 const WCHAR install_root[] = {'I','n','s','t','a','l','l','R','o','o','t',0};
378 DWORD len;
379 HKEY key;
381 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, dotnet_key, 0, KEY_READ, &key))
382 return FALSE;
384 len = MAX_PATH;
385 if (RegQueryValueExW(key, install_root, 0, NULL, (LPBYTE)install_dir, &len))
387 RegCloseKey(key);
388 return FALSE;
390 RegCloseKey(key);
392 return TRUE;
395 static HRESULT WINAPI CLRRuntimeInfo_GetRuntimeDirectory(ICLRRuntimeInfo* iface,
396 LPWSTR pwzBuffer, DWORD *pcchBuffer)
398 static const WCHAR slash[] = {'\\',0};
399 DWORD buffer_size = *pcchBuffer;
400 WCHAR system_dir[MAX_PATH];
401 WCHAR version[MAX_PATH];
402 DWORD version_size, size;
403 HRESULT hr = S_OK;
405 TRACE("%p %p %p\n", iface, pwzBuffer, pcchBuffer);
407 if (!get_install_root(system_dir))
409 ERR("error reading registry key for installroot\n");
410 return E_FAIL;
412 else
414 version_size = MAX_PATH;
415 ICLRRuntimeInfo_GetVersionString(iface, version, &version_size);
416 lstrcatW(system_dir, version);
417 lstrcatW(system_dir, slash);
418 size = lstrlenW(system_dir) + 1;
421 *pcchBuffer = size;
423 if (pwzBuffer)
425 if (buffer_size >= size)
426 strcpyW(pwzBuffer, system_dir);
427 else
428 hr = E_NOT_SUFFICIENT_BUFFER;
431 return hr;
434 static HRESULT WINAPI CLRRuntimeInfo_IsLoaded(ICLRRuntimeInfo* iface,
435 HANDLE hndProcess, BOOL *pbLoaded)
437 FIXME("%p %p %p\n", iface, hndProcess, pbLoaded);
439 return E_NOTIMPL;
442 static HRESULT WINAPI CLRRuntimeInfo_LoadErrorString(ICLRRuntimeInfo* iface,
443 UINT iResourceID, LPWSTR pwzBuffer, DWORD *pcchBuffer, LONG iLocaleid)
445 FIXME("%p %u %p %p %x\n", iface, iResourceID, pwzBuffer, pcchBuffer, iLocaleid);
447 return E_NOTIMPL;
450 static HRESULT WINAPI CLRRuntimeInfo_LoadLibrary(ICLRRuntimeInfo* iface,
451 LPCWSTR pwzDllName, HMODULE *phndModule)
453 WCHAR version[MAX_PATH];
454 HRESULT hr;
455 DWORD cchBuffer;
457 TRACE("%p %s %p\n", iface, debugstr_w(pwzDllName), phndModule);
459 cchBuffer = MAX_PATH;
460 hr = ICLRRuntimeInfo_GetVersionString(iface, version, &cchBuffer);
461 if (FAILED(hr)) return hr;
463 return LoadLibraryShim(pwzDllName, version, NULL, phndModule);
466 static HRESULT WINAPI CLRRuntimeInfo_GetProcAddress(ICLRRuntimeInfo* iface,
467 LPCSTR pszProcName, LPVOID *ppProc)
469 FIXME("%p %s %p\n", iface, debugstr_a(pszProcName), ppProc);
471 return E_NOTIMPL;
474 static HRESULT WINAPI CLRRuntimeInfo_GetInterface(ICLRRuntimeInfo* iface,
475 REFCLSID rclsid, REFIID riid, LPVOID *ppUnk)
477 struct CLRRuntimeInfo *This = impl_from_ICLRRuntimeInfo(iface);
478 RuntimeHost *host;
479 HRESULT hr;
481 TRACE("%p %s %s %p\n", iface, debugstr_guid(rclsid), debugstr_guid(riid), ppUnk);
483 hr = CLRRuntimeInfo_GetRuntimeHost(This, &host);
485 if (SUCCEEDED(hr))
486 hr = RuntimeHost_GetInterface(host, rclsid, riid, ppUnk);
488 return hr;
491 static HRESULT WINAPI CLRRuntimeInfo_IsLoadable(ICLRRuntimeInfo* iface,
492 BOOL *pbLoadable)
494 FIXME("%p %p\n", iface, pbLoadable);
496 return E_NOTIMPL;
499 static HRESULT WINAPI CLRRuntimeInfo_SetDefaultStartupFlags(ICLRRuntimeInfo* iface,
500 DWORD dwStartupFlags, LPCWSTR pwzHostConfigFile)
502 FIXME("%p %x %s\n", iface, dwStartupFlags, debugstr_w(pwzHostConfigFile));
504 return E_NOTIMPL;
507 static HRESULT WINAPI CLRRuntimeInfo_GetDefaultStartupFlags(ICLRRuntimeInfo* iface,
508 DWORD *pdwStartupFlags, LPWSTR pwzHostConfigFile, DWORD *pcchHostConfigFile)
510 FIXME("%p %p %p %p\n", iface, pdwStartupFlags, pwzHostConfigFile, pcchHostConfigFile);
512 return E_NOTIMPL;
515 static HRESULT WINAPI CLRRuntimeInfo_BindAsLegacyV2Runtime(ICLRRuntimeInfo* iface)
517 FIXME("%p\n", iface);
519 return E_NOTIMPL;
522 static HRESULT WINAPI CLRRuntimeInfo_IsStarted(ICLRRuntimeInfo* iface,
523 BOOL *pbStarted, DWORD *pdwStartupFlags)
525 FIXME("%p %p %p\n", iface, pbStarted, pdwStartupFlags);
527 return E_NOTIMPL;
530 static const struct ICLRRuntimeInfoVtbl CLRRuntimeInfoVtbl = {
531 CLRRuntimeInfo_QueryInterface,
532 CLRRuntimeInfo_AddRef,
533 CLRRuntimeInfo_Release,
534 CLRRuntimeInfo_GetVersionString,
535 CLRRuntimeInfo_GetRuntimeDirectory,
536 CLRRuntimeInfo_IsLoaded,
537 CLRRuntimeInfo_LoadErrorString,
538 CLRRuntimeInfo_LoadLibrary,
539 CLRRuntimeInfo_GetProcAddress,
540 CLRRuntimeInfo_GetInterface,
541 CLRRuntimeInfo_IsLoadable,
542 CLRRuntimeInfo_SetDefaultStartupFlags,
543 CLRRuntimeInfo_GetDefaultStartupFlags,
544 CLRRuntimeInfo_BindAsLegacyV2Runtime,
545 CLRRuntimeInfo_IsStarted
548 HRESULT ICLRRuntimeInfo_GetRuntimeHost(ICLRRuntimeInfo *iface, RuntimeHost **result)
550 struct CLRRuntimeInfo *This = impl_from_ICLRRuntimeInfo(iface);
552 assert(This->ICLRRuntimeInfo_iface.lpVtbl == &CLRRuntimeInfoVtbl);
554 return CLRRuntimeInfo_GetRuntimeHost(This, result);
557 #ifdef __i386__
558 static const WCHAR libmono2_arch_dll[] = {'\\','b','i','n','\\','l','i','b','m','o','n','o','-','2','.','0','-','x','8','6','.','d','l','l',0};
559 #elif defined(__x86_64__)
560 static const WCHAR libmono2_arch_dll[] = {'\\','b','i','n','\\','l','i','b','m','o','n','o','-','2','.','0','-','x','8','6','_','6','4','.','d','l','l',0};
561 #else
562 static const WCHAR libmono2_arch_dll[] = {'\\','b','i','n','\\','l','i','b','m','o','n','o','-','2','.','0','.','d','l','l',0};
563 #endif
565 static BOOL find_mono_dll(LPCWSTR path, LPWSTR dll_path)
567 static const WCHAR mono2_dll[] = {'\\','b','i','n','\\','m','o','n','o','-','2','.','0','.','d','l','l',0};
568 static const WCHAR libmono2_dll[] = {'\\','b','i','n','\\','l','i','b','m','o','n','o','-','2','.','0','.','d','l','l',0};
569 DWORD attributes=INVALID_FILE_ATTRIBUTES;
571 strcpyW(dll_path, path);
572 strcatW(dll_path, libmono2_arch_dll);
573 attributes = GetFileAttributesW(dll_path);
575 if (attributes == INVALID_FILE_ATTRIBUTES)
577 strcpyW(dll_path, path);
578 strcatW(dll_path, mono2_dll);
579 attributes = GetFileAttributesW(dll_path);
582 if (attributes == INVALID_FILE_ATTRIBUTES)
584 strcpyW(dll_path, path);
585 strcatW(dll_path, libmono2_dll);
586 attributes = GetFileAttributesW(dll_path);
589 return (attributes != INVALID_FILE_ATTRIBUTES);
592 static BOOL get_mono_path_from_registry(LPWSTR path)
594 static const WCHAR mono_key[] = {'S','o','f','t','w','a','r','e','\\','N','o','v','e','l','l','\\','M','o','n','o',0};
595 static const WCHAR defaul_clr[] = {'D','e','f','a','u','l','t','C','L','R',0};
596 static const WCHAR install_root[] = {'S','d','k','I','n','s','t','a','l','l','R','o','o','t',0};
597 static const WCHAR slash[] = {'\\',0};
599 WCHAR version[64], version_key[MAX_PATH];
600 DWORD len;
601 HKEY key;
602 WCHAR dll_path[MAX_PATH];
604 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, mono_key, 0, KEY_READ, &key))
605 return FALSE;
607 len = sizeof(version);
608 if (RegQueryValueExW(key, defaul_clr, 0, NULL, (LPBYTE)version, &len))
610 RegCloseKey(key);
611 return FALSE;
613 RegCloseKey(key);
615 lstrcpyW(version_key, mono_key);
616 lstrcatW(version_key, slash);
617 lstrcatW(version_key, version);
619 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, version_key, 0, KEY_READ, &key))
620 return FALSE;
622 len = sizeof(WCHAR) * MAX_PATH;
623 if (RegQueryValueExW(key, install_root, 0, NULL, (LPBYTE)path, &len))
625 RegCloseKey(key);
626 return FALSE;
628 RegCloseKey(key);
630 return find_mono_dll(path, dll_path);
633 static BOOL get_mono_path_from_folder(LPCWSTR folder, LPWSTR mono_path)
635 static const WCHAR mono_two_dot_zero[] = {'\\','m','o','n','o','-','2','.','0', 0};
636 WCHAR mono_dll_path[MAX_PATH];
637 BOOL found = FALSE;
639 strcpyW(mono_path, folder);
641 strcatW(mono_path, mono_two_dot_zero);
643 found = find_mono_dll(mono_path, mono_dll_path);
645 return found;
648 static BOOL get_mono_path(LPWSTR path)
650 static const WCHAR subdir_mono[] = {'\\','m','o','n','o',0};
651 static const WCHAR sibling_mono[] = {'\\','.','.','\\','m','o','n','o',0};
652 WCHAR base_path[MAX_PATH];
653 const char *unix_data_dir;
654 WCHAR *dos_data_dir;
655 BOOL build_tree = FALSE;
656 static WCHAR* (CDECL *wine_get_dos_file_name)(const char*);
658 /* First try c:\windows\mono */
659 GetWindowsDirectoryW(base_path, MAX_PATH);
660 strcatW(base_path, subdir_mono);
662 if (get_mono_path_from_folder(base_path, path))
663 return TRUE;
665 /* Next: /usr/share/wine/mono */
666 unix_data_dir = wine_get_data_dir();
668 if (!unix_data_dir)
670 unix_data_dir = wine_get_build_dir();
671 build_tree = TRUE;
674 if (unix_data_dir)
676 if (!wine_get_dos_file_name)
677 wine_get_dos_file_name = (void*)GetProcAddress(GetModuleHandleA("kernel32"), "wine_get_dos_file_name");
679 if (wine_get_dos_file_name)
681 dos_data_dir = wine_get_dos_file_name(unix_data_dir);
683 if (dos_data_dir)
685 strcpyW(base_path, dos_data_dir);
686 strcatW(base_path, build_tree ? sibling_mono : subdir_mono);
688 HeapFree(GetProcessHeap(), 0, dos_data_dir);
690 if (get_mono_path_from_folder(base_path, path))
691 return TRUE;
696 /* Last: the registry */
697 return get_mono_path_from_registry(path);
700 struct InstalledRuntimeEnum
702 IEnumUnknown IEnumUnknown_iface;
703 LONG ref;
704 ULONG pos;
707 static const struct IEnumUnknownVtbl InstalledRuntimeEnum_Vtbl;
709 static inline struct InstalledRuntimeEnum *impl_from_IEnumUnknown(IEnumUnknown *iface)
711 return CONTAINING_RECORD(iface, struct InstalledRuntimeEnum, IEnumUnknown_iface);
714 static HRESULT WINAPI InstalledRuntimeEnum_QueryInterface(IEnumUnknown* iface, REFIID riid,
715 void **ppvObject)
717 TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
719 if ( IsEqualGUID( riid, &IID_IEnumUnknown ) ||
720 IsEqualGUID( riid, &IID_IUnknown ) )
722 *ppvObject = iface;
724 else
726 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
727 return E_NOINTERFACE;
730 IEnumUnknown_AddRef( iface );
732 return S_OK;
735 static ULONG WINAPI InstalledRuntimeEnum_AddRef(IEnumUnknown* iface)
737 struct InstalledRuntimeEnum *This = impl_from_IEnumUnknown(iface);
738 ULONG ref = InterlockedIncrement(&This->ref);
740 TRACE("(%p) refcount=%u\n", iface, ref);
742 return ref;
745 static ULONG WINAPI InstalledRuntimeEnum_Release(IEnumUnknown* iface)
747 struct InstalledRuntimeEnum *This = impl_from_IEnumUnknown(iface);
748 ULONG ref = InterlockedDecrement(&This->ref);
750 TRACE("(%p) refcount=%u\n", iface, ref);
752 if (ref == 0)
754 HeapFree(GetProcessHeap(), 0, This);
757 return ref;
760 static HRESULT WINAPI InstalledRuntimeEnum_Next(IEnumUnknown *iface, ULONG celt,
761 IUnknown **rgelt, ULONG *pceltFetched)
763 struct InstalledRuntimeEnum *This = impl_from_IEnumUnknown(iface);
764 ULONG num_fetched = 0;
765 HRESULT hr=S_OK;
766 IUnknown *item;
768 TRACE("(%p,%u,%p,%p)\n", iface, celt, rgelt, pceltFetched);
770 while (num_fetched < celt)
772 if (This->pos >= NUM_RUNTIMES)
774 hr = S_FALSE;
775 break;
777 item = (IUnknown*)&runtimes[This->pos].ICLRRuntimeInfo_iface;
778 IUnknown_AddRef(item);
779 rgelt[num_fetched] = item;
780 num_fetched++;
781 This->pos++;
784 if (pceltFetched)
785 *pceltFetched = num_fetched;
787 return hr;
790 static HRESULT WINAPI InstalledRuntimeEnum_Skip(IEnumUnknown *iface, ULONG celt)
792 struct InstalledRuntimeEnum *This = impl_from_IEnumUnknown(iface);
793 ULONG num_fetched = 0;
794 HRESULT hr=S_OK;
796 TRACE("(%p,%u)\n", iface, celt);
798 while (num_fetched < celt)
800 if (This->pos >= NUM_RUNTIMES)
802 hr = S_FALSE;
803 break;
805 num_fetched++;
806 This->pos++;
809 return hr;
812 static HRESULT WINAPI InstalledRuntimeEnum_Reset(IEnumUnknown *iface)
814 struct InstalledRuntimeEnum *This = impl_from_IEnumUnknown(iface);
816 TRACE("(%p)\n", iface);
818 This->pos = 0;
820 return S_OK;
823 static HRESULT WINAPI InstalledRuntimeEnum_Clone(IEnumUnknown *iface, IEnumUnknown **ppenum)
825 struct InstalledRuntimeEnum *This = impl_from_IEnumUnknown(iface);
826 struct InstalledRuntimeEnum *new_enum;
828 TRACE("(%p)\n", iface);
830 new_enum = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_enum));
831 if (!new_enum)
832 return E_OUTOFMEMORY;
834 new_enum->IEnumUnknown_iface.lpVtbl = &InstalledRuntimeEnum_Vtbl;
835 new_enum->ref = 1;
836 new_enum->pos = This->pos;
838 *ppenum = &new_enum->IEnumUnknown_iface;
840 return S_OK;
843 static const struct IEnumUnknownVtbl InstalledRuntimeEnum_Vtbl = {
844 InstalledRuntimeEnum_QueryInterface,
845 InstalledRuntimeEnum_AddRef,
846 InstalledRuntimeEnum_Release,
847 InstalledRuntimeEnum_Next,
848 InstalledRuntimeEnum_Skip,
849 InstalledRuntimeEnum_Reset,
850 InstalledRuntimeEnum_Clone
853 struct CLRMetaHost
855 ICLRMetaHost ICLRMetaHost_iface;
857 RuntimeLoadedCallbackFnPtr callback;
860 static struct CLRMetaHost GlobalCLRMetaHost;
862 static HRESULT WINAPI CLRMetaHost_QueryInterface(ICLRMetaHost* iface,
863 REFIID riid,
864 void **ppvObject)
866 TRACE("%s %p\n", debugstr_guid(riid), ppvObject);
868 if ( IsEqualGUID( riid, &IID_ICLRMetaHost ) ||
869 IsEqualGUID( riid, &IID_IUnknown ) )
871 *ppvObject = iface;
873 else
875 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
876 return E_NOINTERFACE;
879 ICLRMetaHost_AddRef( iface );
881 return S_OK;
884 static ULONG WINAPI CLRMetaHost_AddRef(ICLRMetaHost* iface)
886 return 2;
889 static ULONG WINAPI CLRMetaHost_Release(ICLRMetaHost* iface)
891 return 1;
894 static BOOL parse_runtime_version(LPCWSTR version, DWORD *major, DWORD *minor, DWORD *build)
896 *major = 0;
897 *minor = 0;
898 *build = 0;
900 if (version[0] == 'v' || version[0] == 'V')
902 version++;
903 if (!isdigit(*version))
904 return FALSE;
906 while (isdigit(*version))
907 *major = *major * 10 + (*version++ - '0');
909 if (*version == 0)
910 return TRUE;
912 if (*version++ != '.' || !isdigit(*version))
913 return FALSE;
915 while (isdigit(*version))
916 *minor = *minor * 10 + (*version++ - '0');
918 if (*version == 0)
919 return TRUE;
921 if (*version++ != '.' || !isdigit(*version))
922 return FALSE;
924 while (isdigit(*version))
925 *build = *build * 10 + (*version++ - '0');
927 return *version == 0;
929 else
930 return FALSE;
933 static HRESULT get_runtime(LPCWSTR pwzVersion, BOOL allow_short,
934 REFIID iid, LPVOID *ppRuntime)
936 int i;
937 DWORD major, minor, build;
939 if (!pwzVersion)
940 return E_POINTER;
942 if (!parse_runtime_version(pwzVersion, &major, &minor, &build))
944 ERR("Cannot parse %s\n", debugstr_w(pwzVersion));
945 return CLR_E_SHIM_RUNTIME;
948 for (i=0; i<NUM_RUNTIMES; i++)
950 if (runtimes[i].major == major && runtimes[i].minor == minor &&
951 (runtimes[i].build == build || (allow_short && major >= 4 && build == 0)))
953 return ICLRRuntimeInfo_QueryInterface(&runtimes[i].ICLRRuntimeInfo_iface, iid,
954 ppRuntime);
958 FIXME("Unrecognized version %s\n", debugstr_w(pwzVersion));
959 return CLR_E_SHIM_RUNTIME;
962 HRESULT WINAPI CLRMetaHost_GetRuntime(ICLRMetaHost* iface,
963 LPCWSTR pwzVersion, REFIID iid, LPVOID *ppRuntime)
965 TRACE("%s %s %p\n", debugstr_w(pwzVersion), debugstr_guid(iid), ppRuntime);
967 return get_runtime(pwzVersion, FALSE, iid, ppRuntime);
970 HRESULT WINAPI CLRMetaHost_GetVersionFromFile(ICLRMetaHost* iface,
971 LPCWSTR pwzFilePath, LPWSTR pwzBuffer, DWORD *pcchBuffer)
973 ASSEMBLY *assembly;
974 HRESULT hr;
975 LPSTR version;
976 ULONG buffer_size=*pcchBuffer;
978 TRACE("%s %p %p\n", debugstr_w(pwzFilePath), pwzBuffer, pcchBuffer);
980 hr = assembly_create(&assembly, pwzFilePath);
982 if (SUCCEEDED(hr))
984 hr = assembly_get_runtime_version(assembly, &version);
986 if (SUCCEEDED(hr))
988 *pcchBuffer = MultiByteToWideChar(CP_UTF8, 0, version, -1, NULL, 0);
990 if (pwzBuffer)
992 if (buffer_size >= *pcchBuffer)
993 MultiByteToWideChar(CP_UTF8, 0, version, -1, pwzBuffer, buffer_size);
994 else
995 hr = E_NOT_SUFFICIENT_BUFFER;
999 assembly_release(assembly);
1002 return hr;
1005 static HRESULT WINAPI CLRMetaHost_EnumerateInstalledRuntimes(ICLRMetaHost* iface,
1006 IEnumUnknown **ppEnumerator)
1008 struct InstalledRuntimeEnum *new_enum;
1010 TRACE("%p\n", ppEnumerator);
1012 new_enum = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_enum));
1013 if (!new_enum)
1014 return E_OUTOFMEMORY;
1016 new_enum->IEnumUnknown_iface.lpVtbl = &InstalledRuntimeEnum_Vtbl;
1017 new_enum->ref = 1;
1018 new_enum->pos = 0;
1020 *ppEnumerator = &new_enum->IEnumUnknown_iface;
1022 return S_OK;
1025 static HRESULT WINAPI CLRMetaHost_EnumerateLoadedRuntimes(ICLRMetaHost* iface,
1026 HANDLE hndProcess, IEnumUnknown **ppEnumerator)
1028 FIXME("%p %p\n", hndProcess, ppEnumerator);
1030 return E_NOTIMPL;
1033 static HRESULT WINAPI CLRMetaHost_RequestRuntimeLoadedNotification(ICLRMetaHost* iface,
1034 RuntimeLoadedCallbackFnPtr pCallbackFunction)
1036 TRACE("%p\n", pCallbackFunction);
1038 if(!pCallbackFunction)
1039 return E_POINTER;
1041 WARN("Callback currently will not be called.\n");
1043 GlobalCLRMetaHost.callback = pCallbackFunction;
1045 return S_OK;
1048 static HRESULT WINAPI CLRMetaHost_QueryLegacyV2RuntimeBinding(ICLRMetaHost* iface,
1049 REFIID riid, LPVOID *ppUnk)
1051 FIXME("%s %p\n", debugstr_guid(riid), ppUnk);
1053 return E_NOTIMPL;
1056 HRESULT WINAPI CLRMetaHost_ExitProcess(ICLRMetaHost* iface, INT32 iExitCode)
1058 TRACE("%i\n", iExitCode);
1060 EnterCriticalSection(&runtime_list_cs);
1062 if (is_mono_started && !is_mono_shutdown)
1064 /* search for a runtime and call System.Environment.Exit() */
1065 int i;
1067 for (i=0; i<NUM_RUNTIMES; i++)
1068 if (runtimes[i].loaded_runtime)
1069 RuntimeHost_ExitProcess(runtimes[i].loaded_runtime, iExitCode);
1072 ExitProcess(iExitCode);
1075 static const struct ICLRMetaHostVtbl CLRMetaHost_vtbl =
1077 CLRMetaHost_QueryInterface,
1078 CLRMetaHost_AddRef,
1079 CLRMetaHost_Release,
1080 CLRMetaHost_GetRuntime,
1081 CLRMetaHost_GetVersionFromFile,
1082 CLRMetaHost_EnumerateInstalledRuntimes,
1083 CLRMetaHost_EnumerateLoadedRuntimes,
1084 CLRMetaHost_RequestRuntimeLoadedNotification,
1085 CLRMetaHost_QueryLegacyV2RuntimeBinding,
1086 CLRMetaHost_ExitProcess
1089 static struct CLRMetaHost GlobalCLRMetaHost = {
1090 { &CLRMetaHost_vtbl }
1093 HRESULT CLRMetaHost_CreateInstance(REFIID riid, void **ppobj)
1095 return ICLRMetaHost_QueryInterface(&GlobalCLRMetaHost.ICLRMetaHost_iface, riid, ppobj);
1098 struct CLRMetaHostPolicy
1100 ICLRMetaHostPolicy ICLRMetaHostPolicy_iface;
1103 static struct CLRMetaHostPolicy GlobalCLRMetaHostPolicy;
1105 static HRESULT WINAPI metahostpolicy_QueryInterface(ICLRMetaHostPolicy *iface, REFIID riid, void **obj)
1107 TRACE("%s %p\n", debugstr_guid(riid), obj);
1109 if ( IsEqualGUID( riid, &IID_ICLRMetaHostPolicy ) ||
1110 IsEqualGUID( riid, &IID_IUnknown ) )
1112 ICLRMetaHostPolicy_AddRef( iface );
1113 *obj = iface;
1114 return S_OK;
1117 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
1119 *obj = NULL;
1120 return E_NOINTERFACE;
1123 static ULONG WINAPI metahostpolicy_AddRef(ICLRMetaHostPolicy *iface)
1125 return 2;
1128 static ULONG WINAPI metahostpolicy_Release(ICLRMetaHostPolicy *iface)
1130 return 1;
1133 static HRESULT WINAPI metahostpolicy_GetRequestedRuntime(ICLRMetaHostPolicy *iface, METAHOST_POLICY_FLAGS dwPolicyFlags,
1134 LPCWSTR pwzBinary, IStream *pCfgStream, LPWSTR pwzVersion, DWORD *pcchVersion,
1135 LPWSTR pwzImageVersion, DWORD *pcchImageVersion, DWORD *pdwConfigFlags, REFIID riid,
1136 LPVOID *ppRuntime)
1138 ICLRRuntimeInfo *result;
1139 HRESULT hr;
1140 WCHAR filename[MAX_PATH];
1141 const WCHAR *path = NULL;
1142 int flags = 0;
1144 TRACE("%d %p %p %p %p %p %p %p %s %p\n", dwPolicyFlags, pwzBinary, pCfgStream,
1145 pwzVersion, pcchVersion, pwzImageVersion, pcchImageVersion, pdwConfigFlags,
1146 debugstr_guid(riid), ppRuntime);
1148 if (pCfgStream)
1149 FIXME("ignoring config file stream\n");
1151 if (pdwConfigFlags)
1152 FIXME("ignoring config flags\n");
1154 if(dwPolicyFlags & METAHOST_POLICY_USE_PROCESS_IMAGE_PATH)
1156 GetModuleFileNameW(0, filename, MAX_PATH);
1157 path = filename;
1159 else if(pwzBinary)
1161 path = pwzBinary;
1164 if(dwPolicyFlags & METAHOST_POLICY_APPLY_UPGRADE_POLICY)
1165 flags |= RUNTIME_INFO_UPGRADE_VERSION;
1167 hr = get_runtime_info(path, pwzImageVersion, NULL, 0, flags, FALSE, &result);
1168 if (SUCCEEDED(hr))
1170 if (pwzImageVersion)
1172 /* Ignoring errors on purpose */
1173 ICLRRuntimeInfo_GetVersionString(result, pwzImageVersion, pcchImageVersion);
1176 hr = ICLRRuntimeInfo_QueryInterface(result, riid, ppRuntime);
1178 ICLRRuntimeInfo_Release(result);
1181 TRACE("<- 0x%08x\n", hr);
1183 return hr;
1186 static const struct ICLRMetaHostPolicyVtbl CLRMetaHostPolicy_vtbl =
1188 metahostpolicy_QueryInterface,
1189 metahostpolicy_AddRef,
1190 metahostpolicy_Release,
1191 metahostpolicy_GetRequestedRuntime
1194 static struct CLRMetaHostPolicy GlobalCLRMetaHostPolicy = {
1195 { &CLRMetaHostPolicy_vtbl }
1198 HRESULT CLRMetaHostPolicy_CreateInstance(REFIID riid, void **ppobj)
1200 return ICLRMetaHostPolicy_QueryInterface(&GlobalCLRMetaHostPolicy.ICLRMetaHostPolicy_iface, riid, ppobj);
1203 HRESULT get_file_from_strongname(WCHAR* stringnameW, WCHAR* assemblies_path, int path_length)
1205 HRESULT hr=S_OK;
1206 IAssemblyCache *asmcache;
1207 ASSEMBLY_INFO info;
1208 static const WCHAR fusiondll[] = {'f','u','s','i','o','n',0};
1209 HMODULE hfusion=NULL;
1210 static HRESULT (WINAPI *pCreateAssemblyCache)(IAssemblyCache**,DWORD);
1212 if (!pCreateAssemblyCache)
1214 hr = LoadLibraryShim(fusiondll, NULL, NULL, &hfusion);
1216 if (SUCCEEDED(hr))
1218 pCreateAssemblyCache = (void*)GetProcAddress(hfusion, "CreateAssemblyCache");
1219 if (!pCreateAssemblyCache)
1220 hr = E_FAIL;
1224 if (SUCCEEDED(hr))
1225 hr = pCreateAssemblyCache(&asmcache, 0);
1227 if (SUCCEEDED(hr))
1229 info.cbAssemblyInfo = sizeof(info);
1230 info.pszCurrentAssemblyPathBuf = assemblies_path;
1231 info.cchBuf = path_length;
1232 assemblies_path[0] = 0;
1234 hr = IAssemblyCache_QueryAssemblyInfo(asmcache, 0, stringnameW, &info);
1236 IAssemblyCache_Release(asmcache);
1239 return hr;
1242 static MonoAssembly* mono_assembly_preload_hook_fn(MonoAssemblyName *aname, char **assemblies_path, void *user_data)
1244 HRESULT hr;
1245 MonoAssembly *result=NULL;
1246 char *stringname=NULL;
1247 LPWSTR stringnameW;
1248 int stringnameW_size;
1249 WCHAR path[MAX_PATH];
1250 char *pathA;
1251 MonoImageOpenStatus stat;
1253 stringname = mono_stringify_assembly_name(aname);
1255 TRACE("%s\n", debugstr_a(stringname));
1257 if (!stringname) return NULL;
1259 /* FIXME: We should search the given paths before the GAC. */
1261 stringnameW_size = MultiByteToWideChar(CP_UTF8, 0, stringname, -1, NULL, 0);
1263 stringnameW = HeapAlloc(GetProcessHeap(), 0, stringnameW_size * sizeof(WCHAR));
1264 if (stringnameW)
1266 MultiByteToWideChar(CP_UTF8, 0, stringname, -1, stringnameW, stringnameW_size);
1268 hr = get_file_from_strongname(stringnameW, path, MAX_PATH);
1270 HeapFree(GetProcessHeap(), 0, stringnameW);
1272 else
1273 hr = E_OUTOFMEMORY;
1275 if (SUCCEEDED(hr))
1277 TRACE("found: %s\n", debugstr_w(path));
1279 pathA = WtoA(path);
1281 if (pathA)
1283 result = mono_assembly_open(pathA, &stat);
1285 if (!result)
1286 ERR("Failed to load %s, status=%u\n", debugstr_w(path), stat);
1288 HeapFree(GetProcessHeap(), 0, pathA);
1292 mono_free(stringname);
1294 return result;
1297 HRESULT get_runtime_info(LPCWSTR exefile, LPCWSTR version, LPCWSTR config_file,
1298 DWORD startup_flags, DWORD runtimeinfo_flags, BOOL legacy, ICLRRuntimeInfo **result)
1300 static const WCHAR dotconfig[] = {'.','c','o','n','f','i','g',0};
1301 static const DWORD supported_startup_flags = 0;
1302 static const DWORD supported_runtime_flags = RUNTIME_INFO_UPGRADE_VERSION;
1303 int i;
1304 WCHAR local_version[MAX_PATH];
1305 ULONG local_version_size = MAX_PATH;
1306 WCHAR local_config_file[MAX_PATH];
1307 HRESULT hr;
1308 parsed_config_file parsed_config;
1310 if (startup_flags & ~supported_startup_flags)
1311 FIXME("unsupported startup flags %x\n", startup_flags & ~supported_startup_flags);
1313 if (runtimeinfo_flags & ~supported_runtime_flags)
1314 FIXME("unsupported runtimeinfo flags %x\n", runtimeinfo_flags & ~supported_runtime_flags);
1316 if (exefile && !exefile[0])
1317 exefile = NULL;
1319 if (exefile && !config_file)
1321 strcpyW(local_config_file, exefile);
1322 strcatW(local_config_file, dotconfig);
1324 config_file = local_config_file;
1327 if (config_file)
1329 BOOL found = FALSE;
1330 hr = parse_config_file(config_file, &parsed_config);
1332 if (SUCCEEDED(hr))
1334 supported_runtime *entry;
1335 LIST_FOR_EACH_ENTRY(entry, &parsed_config.supported_runtimes, supported_runtime, entry)
1337 hr = get_runtime(entry->version, TRUE, &IID_ICLRRuntimeInfo, (void**)result);
1338 if (SUCCEEDED(hr))
1340 found = TRUE;
1341 break;
1345 else
1347 WARN("failed to parse config file %s, hr=%x\n", debugstr_w(config_file), hr);
1350 free_parsed_config_file(&parsed_config);
1352 if (found)
1353 return S_OK;
1356 if (exefile && !version)
1358 hr = CLRMetaHost_GetVersionFromFile(0, exefile, local_version, &local_version_size);
1360 version = local_version;
1362 if (FAILED(hr)) return hr;
1365 if (version)
1367 hr = CLRMetaHost_GetRuntime(0, version, &IID_ICLRRuntimeInfo, (void**)result);
1368 if(SUCCEEDED(hr))
1369 return hr;
1372 if (runtimeinfo_flags & RUNTIME_INFO_UPGRADE_VERSION)
1374 DWORD major, minor, build;
1376 if (version && !parse_runtime_version(version, &major, &minor, &build))
1378 ERR("Cannot parse %s\n", debugstr_w(version));
1379 return CLR_E_SHIM_RUNTIME;
1382 if (legacy)
1383 i = 3;
1384 else
1385 i = NUM_RUNTIMES;
1387 while (i--)
1389 /* Must be greater or equal to the version passed in. */
1390 if (!version || ((runtimes[i].major >= major && runtimes[i].minor >= minor && runtimes[i].build >= build) ||
1391 (runtimes[i].major >= major && runtimes[i].minor > minor) ||
1392 (runtimes[i].major > major)))
1394 return ICLRRuntimeInfo_QueryInterface(&runtimes[i].ICLRRuntimeInfo_iface,
1395 &IID_ICLRRuntimeInfo, (void **)result);
1399 missing_runtime_message();
1401 return CLR_E_SHIM_RUNTIME;
1404 return CLR_E_SHIM_RUNTIME;