2 * Implementation of mscoree.dll
3 * Microsoft Component Object Runtime Execution Engine
5 * Copyright 2006 Paul Chitescu
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/unicode.h"
37 #include "mscoree_private.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL( mscoree
);
43 static BOOL
get_mono_path(LPWSTR path
)
45 static const WCHAR mono_key
[] = {'S','o','f','t','w','a','r','e','\\','N','o','v','e','l','l','\\','M','o','n','o',0};
46 static const WCHAR defaul_clr
[] = {'D','e','f','a','u','l','t','C','L','R',0};
47 static const WCHAR install_root
[] = {'S','d','k','I','n','s','t','a','l','l','R','o','o','t',0};
48 static const WCHAR slash
[] = {'\\',0};
50 WCHAR version
[64], version_key
[MAX_PATH
];
54 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, mono_key
, 0, KEY_READ
, &key
))
57 len
= sizeof(version
);
58 if (RegQueryValueExW(key
, defaul_clr
, 0, NULL
, (LPBYTE
)version
, &len
))
65 lstrcpyW(version_key
, mono_key
);
66 lstrcatW(version_key
, slash
);
67 lstrcatW(version_key
, version
);
69 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, version_key
, 0, KEY_READ
, &key
))
72 len
= sizeof(WCHAR
) * MAX_PATH
;
73 if (RegQueryValueExW(key
, install_root
, 0, NULL
, (LPBYTE
)path
, &len
))
83 static BOOL
get_install_root(LPWSTR install_dir
)
85 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};
86 const WCHAR install_root
[] = {'I','n','s','t','a','l','l','R','o','o','t',0};
91 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, dotnet_key
, 0, KEY_READ
, &key
))
95 if (RegQueryValueExW(key
, install_root
, 0, NULL
, (LPBYTE
)install_dir
, &len
))
105 static CRITICAL_SECTION mono_lib_cs
;
106 static CRITICAL_SECTION_DEBUG mono_lib_cs_debug
=
109 { &mono_lib_cs_debug
.ProcessLocksList
,
110 &mono_lib_cs_debug
.ProcessLocksList
},
111 0, 0, { (DWORD_PTR
)(__FILE__
": mono_lib_cs") }
113 static CRITICAL_SECTION mono_lib_cs
= { &mono_lib_cs_debug
, -1, 0, 0, 0, 0 };
117 void (*mono_config_parse
)(const char *filename
);
118 MonoAssembly
* (*mono_domain_assembly_open
) (MonoDomain
*domain
, const char *name
);
119 void (*mono_jit_cleanup
)(MonoDomain
*domain
);
120 int (*mono_jit_exec
)(MonoDomain
*domain
, MonoAssembly
*assembly
, int argc
, char *argv
[]);
121 MonoDomain
* (*mono_jit_init
)(const char *file
);
122 int (*mono_jit_set_trace_options
)(const char* options
);
123 void (*mono_set_dirs
)(const char *assembly_dir
, const char *config_dir
);
125 static void set_environment(LPCWSTR bin_path
)
127 WCHAR path_env
[MAX_PATH
];
130 static const WCHAR pathW
[] = {'P','A','T','H',0};
132 /* We have to modify PATH as Mono loads other DLLs from this directory. */
133 GetEnvironmentVariableW(pathW
, path_env
, sizeof(path_env
)/sizeof(WCHAR
));
134 len
= strlenW(path_env
);
135 path_env
[len
++] = ';';
136 strcpyW(path_env
+len
, bin_path
);
137 SetEnvironmentVariableW(pathW
, path_env
);
140 static HMODULE
load_mono(void)
142 static const WCHAR mono_dll
[] = {'\\','b','i','n','\\','m','o','n','o','.','d','l','l',0};
143 static const WCHAR libmono_dll
[] = {'\\','b','i','n','\\','l','i','b','m','o','n','o','.','d','l','l',0};
144 static const WCHAR bin
[] = {'\\','b','i','n',0};
145 static const WCHAR lib
[] = {'\\','l','i','b',0};
146 static const WCHAR etc
[] = {'\\','e','t','c',0};
148 WCHAR mono_path
[MAX_PATH
], mono_dll_path
[MAX_PATH
+16], mono_bin_path
[MAX_PATH
+4];
149 WCHAR mono_lib_path
[MAX_PATH
+4], mono_etc_path
[MAX_PATH
+4];
150 char mono_lib_path_a
[MAX_PATH
], mono_etc_path_a
[MAX_PATH
];
152 EnterCriticalSection(&mono_lib_cs
);
156 if (!get_mono_path(mono_path
)) goto end
;
158 strcpyW(mono_bin_path
, mono_path
);
159 strcatW(mono_bin_path
, bin
);
160 set_environment(mono_bin_path
);
162 strcpyW(mono_lib_path
, mono_path
);
163 strcatW(mono_lib_path
, lib
);
164 WideCharToMultiByte(CP_UTF8
, 0, mono_lib_path
, -1, mono_lib_path_a
, MAX_PATH
, NULL
, NULL
);
166 strcpyW(mono_etc_path
, mono_path
);
167 strcatW(mono_etc_path
, etc
);
168 WideCharToMultiByte(CP_UTF8
, 0, mono_etc_path
, -1, mono_etc_path_a
, MAX_PATH
, NULL
, NULL
);
170 strcpyW(mono_dll_path
, mono_path
);
171 strcatW(mono_dll_path
, mono_dll
);
172 mono_handle
= LoadLibraryW(mono_dll_path
);
176 strcpyW(mono_dll_path
, mono_path
);
177 strcatW(mono_dll_path
, libmono_dll
);
178 mono_handle
= LoadLibraryW(mono_dll_path
);
181 if (!mono_handle
) goto end
;
183 #define LOAD_MONO_FUNCTION(x) do { \
184 x = (void*)GetProcAddress(mono_handle, #x); \
186 mono_handle = NULL; \
191 LOAD_MONO_FUNCTION(mono_config_parse
);
192 LOAD_MONO_FUNCTION(mono_domain_assembly_open
);
193 LOAD_MONO_FUNCTION(mono_jit_cleanup
);
194 LOAD_MONO_FUNCTION(mono_jit_exec
);
195 LOAD_MONO_FUNCTION(mono_jit_init
);
196 LOAD_MONO_FUNCTION(mono_jit_set_trace_options
);
197 LOAD_MONO_FUNCTION(mono_set_dirs
);
199 #undef LOAD_MONO_FUNCTION
201 mono_set_dirs(mono_lib_path_a
, mono_etc_path_a
);
203 mono_config_parse(NULL
);
207 result
= mono_handle
;
209 LeaveCriticalSection(&mono_lib_cs
);
212 MESSAGE("wine: Install the Windows version of Mono to run .NET executables\n");
217 HRESULT WINAPI
CorBindToRuntimeHost(LPCWSTR pwszVersion
, LPCWSTR pwszBuildFlavor
,
218 LPCWSTR pwszHostConfigFile
, VOID
*pReserved
,
219 DWORD startupFlags
, REFCLSID rclsid
,
220 REFIID riid
, LPVOID
*ppv
)
222 FIXME("(%s, %s, %s, %p, %d, %s, %s, %p): semi-stub!\n", debugstr_w(pwszVersion
),
223 debugstr_w(pwszBuildFlavor
), debugstr_w(pwszHostConfigFile
), pReserved
,
224 startupFlags
, debugstr_guid(rclsid
), debugstr_guid(riid
), ppv
);
226 if (!get_mono_path(NULL
))
228 MESSAGE("wine: Install the Windows version of Mono to run .NET executables\n");
235 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
237 TRACE("(%p, %d, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
241 case DLL_WINE_PREATTACH
:
242 return FALSE
; /* prefer native version */
243 case DLL_PROCESS_ATTACH
:
244 DisableThreadLibraryCalls(hinstDLL
);
246 case DLL_PROCESS_DETACH
:
252 BOOL WINAPI
_CorDllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
254 FIXME("(%p, %d, %p): stub\n", hinstDLL
, fdwReason
, lpvReserved
);
258 case DLL_PROCESS_ATTACH
:
259 DisableThreadLibraryCalls(hinstDLL
);
261 case DLL_PROCESS_DETACH
:
267 static void get_utf8_args(int *argc
, char ***argv
)
273 argvw
= CommandLineToArgvW(GetCommandLineW(), argc
);
275 for (i
=0; i
<*argc
; i
++)
277 size
+= sizeof(char*);
278 size
+= WideCharToMultiByte(CP_UTF8
, 0, argvw
[i
], -1, NULL
, 0, NULL
, NULL
);
280 size
+= sizeof(char*);
282 *argv
= HeapAlloc(GetProcessHeap(), 0, size
);
283 current_arg
= (char*)(*argv
+ *argc
+ 1);
285 for (i
=0; i
<*argc
; i
++)
287 (*argv
)[i
] = current_arg
;
288 current_arg
+= WideCharToMultiByte(CP_UTF8
, 0, argvw
[i
], -1, current_arg
, size
, NULL
, NULL
);
291 (*argv
)[*argc
] = NULL
;
293 HeapFree(GetProcessHeap(), 0, argvw
);
296 __int32 WINAPI
_CorExeMain(void)
300 char trace_setting
[256];
304 MonoAssembly
*assembly
;
305 char filename
[MAX_PATH
];
312 get_utf8_args(&argc
, &argv
);
314 trace_size
= GetEnvironmentVariableA("WINE_MONO_TRACE", trace_setting
, sizeof(trace_setting
));
318 mono_jit_set_trace_options(trace_setting
);
321 GetModuleFileNameA(NULL
, filename
, MAX_PATH
);
323 domain
= mono_jit_init(filename
);
325 assembly
= mono_domain_assembly_open(domain
, filename
);
327 exit_code
= mono_jit_exec(domain
, assembly
, argc
, argv
);
329 mono_jit_cleanup(domain
);
331 HeapFree(GetProcessHeap(), 0, argv
);
336 __int32 WINAPI
_CorExeMain2(PBYTE ptrMemory
, DWORD cntMemory
, LPWSTR imageName
, LPWSTR loaderName
, LPWSTR cmdLine
)
338 TRACE("(%p, %u, %s, %s, %s)\n", ptrMemory
, cntMemory
, debugstr_w(imageName
), debugstr_w(loaderName
), debugstr_w(cmdLine
));
339 FIXME("Directly running .NET applications not supported.\n");
343 void WINAPI
CorExitProcess(int exitCode
)
345 FIXME("(%x) stub\n", exitCode
);
346 ExitProcess(exitCode
);
349 VOID WINAPI
_CorImageUnloading(PVOID imageBase
)
351 TRACE("(%p): stub\n", imageBase
);
354 HRESULT WINAPI
_CorValidateImage(PVOID
* imageBase
, LPCWSTR imageName
)
356 TRACE("(%p, %s): stub\n", imageBase
, debugstr_w(imageName
));
360 HRESULT WINAPI
GetCORSystemDirectory(LPWSTR pbuffer
, DWORD cchBuffer
, DWORD
*dwLength
)
362 static const WCHAR slash
[] = {'\\',0};
363 WCHAR system_dir
[MAX_PATH
];
364 WCHAR version
[MAX_PATH
];
366 FIXME("(%p, %d, %p): semi-stub!\n", pbuffer
, cchBuffer
, dwLength
);
372 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
374 if (!get_install_root(system_dir
))
376 ERR("error reading registry key for installroot, returning empty path\n");
381 GetCORVersion(version
, MAX_PATH
, dwLength
);
382 lstrcatW(system_dir
, version
);
383 lstrcatW(system_dir
, slash
);
384 *dwLength
= lstrlenW(system_dir
) + 1;
386 if (cchBuffer
< *dwLength
)
387 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
389 lstrcpyW(pbuffer
, system_dir
);
395 HRESULT WINAPI
GetCORVersion(LPWSTR pbuffer
, DWORD cchBuffer
, DWORD
*dwLength
)
397 static const WCHAR version
[] = {'v','2','.','0','.','5','0','7','2','7',0};
399 FIXME("(%p, %d, %p): semi-stub!\n", pbuffer
, cchBuffer
, dwLength
);
401 if (!dwLength
|| !pbuffer
)
404 *dwLength
= lstrlenW(version
) + 1;
406 if (cchBuffer
< *dwLength
)
407 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
409 lstrcpyW(pbuffer
, version
);
414 HRESULT WINAPI
GetRequestedRuntimeInfo(LPCWSTR pExe
, LPCWSTR pwszVersion
, LPCWSTR pConfigurationFile
,
415 DWORD startupFlags
, DWORD runtimeInfoFlags
, LPWSTR pDirectory
, DWORD dwDirectory
, DWORD
*dwDirectoryLength
,
416 LPWSTR pVersion
, DWORD cchBuffer
, DWORD
*dwlength
)
419 DWORD ver_len
, dir_len
;
420 WCHAR dirW
[MAX_PATH
], verW
[MAX_PATH
];
422 FIXME("(%s, %s, %s, 0x%08x, 0x%08x, %p, 0x%08x, %p, %p, 0x%08x, %p) semi-stub\n", debugstr_w(pExe
),
423 debugstr_w(pwszVersion
), debugstr_w(pConfigurationFile
), startupFlags
, runtimeInfoFlags
, pDirectory
,
424 dwDirectory
, dwDirectoryLength
, pVersion
, cchBuffer
, dwlength
);
426 if (!pwszVersion
&& !(runtimeInfoFlags
& RUNTIME_INFO_UPGRADE_VERSION
))
427 return CLR_E_SHIM_RUNTIME
;
429 ret
= GetCORSystemDirectory(dirW
, dwDirectory
, &dir_len
);
433 if (dwDirectoryLength
)
434 *dwDirectoryLength
= dir_len
;
436 lstrcpyW(pDirectory
, dirW
);
438 ret
= GetCORVersion(verW
, cchBuffer
, &ver_len
);
445 lstrcpyW(pVersion
, verW
);
451 HRESULT WINAPI
LoadLibraryShim( LPCWSTR szDllName
, LPCWSTR szVersion
, LPVOID pvReserved
, HMODULE
* phModDll
)
453 FIXME("(%p %s, %p, %p, %p): semi-stub\n", szDllName
, debugstr_w(szDllName
), szVersion
, pvReserved
, phModDll
);
455 if (phModDll
) *phModDll
= LoadLibraryW(szDllName
);
459 HRESULT WINAPI
LockClrVersion(FLockClrVersionCallback hostCallback
, FLockClrVersionCallback
*pBeginHostSetup
, FLockClrVersionCallback
*pEndHostSetup
)
461 FIXME("(%p %p %p): stub\n", hostCallback
, pBeginHostSetup
, pEndHostSetup
);
465 HRESULT WINAPI
CoInitializeCor(DWORD fFlags
)
467 FIXME("(0x%08x): stub\n", fFlags
);
471 HRESULT WINAPI
GetAssemblyMDImport(LPCWSTR szFileName
, REFIID riid
, IUnknown
**ppIUnk
)
473 FIXME("(%p %s, %s, %p): stub\n", szFileName
, debugstr_w(szFileName
), debugstr_guid(riid
), *ppIUnk
);
474 return ERROR_CALL_NOT_IMPLEMENTED
;
477 HRESULT WINAPI
GetVersionFromProcess(HANDLE hProcess
, LPWSTR pVersion
, DWORD cchBuffer
, DWORD
*dwLength
)
479 FIXME("(%p, %p, %d, %p): stub\n", hProcess
, pVersion
, cchBuffer
, dwLength
);
483 HRESULT WINAPI
LoadStringRCEx(LCID culture
, UINT resId
, LPWSTR pBuffer
, int iBufLen
, int bQuiet
, int* pBufLen
)
486 if ((iBufLen
<= 0) || !pBuffer
)
490 FIXME("(%d, %x, %p, %d, %d, %p): semi-stub\n", culture
, resId
, pBuffer
, iBufLen
, bQuiet
, pBufLen
);
496 *pBufLen
= lstrlenW(pBuffer
);
500 HRESULT WINAPI
LoadStringRC(UINT resId
, LPWSTR pBuffer
, int iBufLen
, int bQuiet
)
502 return LoadStringRCEx(-1, resId
, pBuffer
, iBufLen
, bQuiet
, NULL
);
505 HRESULT WINAPI
CorBindToRuntimeEx(LPWSTR szVersion
, LPWSTR szBuildFlavor
, DWORD nflags
, REFCLSID rslsid
,
506 REFIID riid
, LPVOID
*ppv
)
508 FIXME("%s %s %d %s %s %p\n", debugstr_w(szVersion
), debugstr_w(szBuildFlavor
), nflags
, debugstr_guid( rslsid
),
509 debugstr_guid( riid
), ppv
);
511 if(IsEqualGUID( riid
, &IID_ICorRuntimeHost
))
513 *ppv
= create_corruntimehost();
520 HRESULT WINAPI
CorBindToCurrentRuntime(LPCWSTR filename
, REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
522 FIXME("(%s, %s, %s, %p): stub\n", debugstr_w(filename
), debugstr_guid(rclsid
), debugstr_guid(riid
), ppv
);
526 STDAPI
ClrCreateManagedInstance(LPCWSTR pTypeName
, REFIID riid
, void **ppObject
)
528 FIXME("(%s,%s,%p)\n", debugstr_w(pTypeName
), debugstr_guid(riid
), ppObject
);
532 BOOL WINAPI
StrongNameSignatureVerification(LPCWSTR filename
, DWORD inFlags
, DWORD
* pOutFlags
)
534 FIXME("(%s, 0x%X, %p): stub\n", debugstr_w(filename
), inFlags
, pOutFlags
);
538 BOOL WINAPI
StrongNameSignatureVerificationEx(LPCWSTR filename
, BOOL forceVerification
, BOOL
* pVerified
)
540 FIXME("(%s, %u, %p): stub\n", debugstr_w(filename
), forceVerification
, pVerified
);
544 HRESULT WINAPI
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
* ppv
)
546 FIXME("(%s, %s, %p): stub\n", debugstr_guid(rclsid
), debugstr_guid(riid
), ppv
);
553 HRESULT WINAPI
DllRegisterServer(void)
559 HRESULT WINAPI
DllUnregisterServer(void)
565 HRESULT WINAPI
DllCanUnloadNow(VOID
)
570 INT WINAPI
ND_RU1( const void *ptr
, INT offset
)
572 return *((const BYTE
*)ptr
+ offset
);
575 INT WINAPI
ND_RI2( const void *ptr
, INT offset
)
577 return *(const SHORT
*)((const BYTE
*)ptr
+ offset
);
580 INT WINAPI
ND_RI4( const void *ptr
, INT offset
)
582 return *(const INT
*)((const BYTE
*)ptr
+ offset
);
585 INT64 WINAPI
ND_RI8( const void *ptr
, INT offset
)
587 return *(const INT64
*)((const BYTE
*)ptr
+ offset
);
590 void WINAPI
ND_WU1( void *ptr
, INT offset
, BYTE val
)
592 *((BYTE
*)ptr
+ offset
) = val
;
595 void WINAPI
ND_WI2( void *ptr
, INT offset
, SHORT val
)
597 *(SHORT
*)((BYTE
*)ptr
+ offset
) = val
;
600 void WINAPI
ND_WI4( void *ptr
, INT offset
, INT val
)
602 *(INT
*)((BYTE
*)ptr
+ offset
) = val
;
605 void WINAPI
ND_WI8( void *ptr
, INT offset
, INT64 val
)
607 *(INT64
*)((BYTE
*)ptr
+ offset
) = val
;
610 void WINAPI
ND_CopyObjDst( const void *src
, void *dst
, INT offset
, INT size
)
612 memcpy( (BYTE
*)dst
+ offset
, src
, size
);
615 void WINAPI
ND_CopyObjSrc( const void *src
, INT offset
, void *dst
, INT size
)
617 memcpy( dst
, (const BYTE
*)src
+ offset
, size
);