Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmetahost.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
1.7.6.1
|