Implemeneted imprecise.
[mono-project.git] / mono / metadata / coree.c
blob9f09564703da382d177e55cecd161c78a792c5ca
1 /**
2 * \file
3 * mscoree.dll functions
5 * Author:
6 * Kornel Pal <http://www.kornelpal.hu/>
8 * Copyright (C) 2008 Kornel Pal
9 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12 #include <config.h>
14 #ifdef HOST_WIN32
16 #include <glib.h>
17 #include <string.h>
18 #include <mono/utils/mono-path.h>
19 #include "utils/w32api.h"
20 #include "cil-coff.h"
21 #include "metadata-internals.h"
22 #include "image.h"
23 #include "image-internals.h"
24 #include "assembly-internals.h"
25 #include "domain-internals.h"
26 #include "appdomain.h"
27 #include "object.h"
28 #include "object-internals.h"
29 #include "loader.h"
30 #include "threads.h"
31 #include "environment.h"
32 #include "coree.h"
33 #include "coree-internals.h"
35 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
36 #include <shellapi.h>
37 #endif
39 HMODULE coree_module_handle = NULL;
41 static gboolean init_from_coree = FALSE;
43 gchar*
44 mono_get_module_file_name (HMODULE module_handle)
46 gunichar2* file_name;
47 gchar* file_name_utf8;
48 DWORD buffer_size;
49 DWORD size;
51 buffer_size = 1024;
52 file_name = g_new (gunichar2, buffer_size);
54 for (;;) {
55 size = GetModuleFileName (module_handle, file_name, buffer_size);
56 if (!size) {
57 g_free (file_name);
58 return NULL;
61 g_assert (size <= buffer_size);
62 if (size != buffer_size)
63 break;
65 buffer_size += 1024;
66 file_name = g_realloc (file_name, buffer_size * sizeof (gunichar2));
69 file_name_utf8 = g_utf16_to_utf8 (file_name, size, NULL, NULL, NULL);
70 g_free (file_name);
72 return file_name_utf8;
75 /* Entry point called by LdrLoadDll of ntdll.dll after _CorValidateImage. */
76 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
77 BOOL STDMETHODCALLTYPE _CorDllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved)
79 MonoAssembly* assembly;
80 MonoImage* image;
81 gchar* file_name;
82 gchar* error;
83 MonoAssemblyLoadContext *alc = mono_domain_default_alc (mono_get_root_domain ());
85 switch (dwReason)
87 case DLL_PROCESS_ATTACH:
88 DisableThreadLibraryCalls (hInst);
90 file_name = mono_get_module_file_name (hInst);
92 if (mono_get_root_domain ()) {
93 image = mono_image_open_from_module_handle (alc, hInst, mono_path_resolve_symlinks (file_name), TRUE, NULL);
94 } else {
95 init_from_coree = TRUE;
96 mono_runtime_load (file_name, NULL);
97 error = (gchar*) mono_check_corlib_version ();
98 if (error) {
99 g_free (error);
100 g_free (file_name);
101 mono_runtime_quit ();
102 return FALSE;
105 image = mono_image_open (file_name, NULL);
106 if (image) {
107 image->storage->has_entry_point = TRUE;
108 mono_close_exe_image ();
109 /* Decrement reference count to zero. (Image will not be closed.) */
110 mono_image_close (image);
114 if (!image) {
115 g_free (file_name);
116 return FALSE;
120 * FIXME: Find a better way to call mono_image_fixup_vtable. Only
121 * loader trampolines should be used and assembly loading should
122 * probably be delayed until the first call to an exported function.
124 if (image->tables [MONO_TABLE_ASSEMBLY].rows && image->image_info->cli_cli_header.ch_vtable_fixups.rva) {
125 MonoAssemblyOpenRequest req;
126 mono_assembly_request_prepare_open (&req, MONO_ASMCTX_DEFAULT, alc);
127 assembly = mono_assembly_request_open (file_name, &req, NULL);
130 g_free (file_name);
131 break;
132 case DLL_PROCESS_DETACH:
133 if (lpReserved != NULL)
134 /* The process is terminating. */
135 return TRUE;
136 file_name = mono_get_module_file_name (hInst);
137 image = mono_image_loaded_internal (alc, file_name, FALSE);
138 if (image)
139 mono_image_close (image);
141 g_free (file_name);
142 break;
145 return TRUE;
147 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
149 /* Called by ntdll.dll reagardless of entry point after _CorValidateImage. */
150 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
151 __int32 STDMETHODCALLTYPE _CorExeMain(void)
153 ERROR_DECL (error);
154 MonoDomain* domain;
155 MonoAssembly* assembly;
156 MonoImage* image;
157 MonoMethod* method;
158 guint32 entry;
159 gchar* file_name;
160 gchar* corlib_version_error;
161 int argc;
162 gunichar2** argvw;
163 gchar** argv;
164 int i;
166 file_name = mono_get_module_file_name (NULL);
167 init_from_coree = TRUE;
168 domain = mono_runtime_load (file_name, NULL);
170 corlib_version_error = (gchar*) mono_check_corlib_version ();
171 if (corlib_version_error) {
172 g_free (corlib_version_error);
173 g_free (file_name);
174 MessageBox (NULL, L"Corlib not in sync with this runtime.", NULL, MB_ICONERROR);
175 mono_runtime_quit ();
176 ExitProcess (1);
179 MonoAssemblyOpenRequest req;
180 mono_assembly_request_prepare_open (&req, MONO_ASMCTX_DEFAULT, mono_domain_default_alc (mono_get_root_domain ()));
181 assembly = mono_assembly_request_open (file_name, &req, NULL);
182 mono_close_exe_image ();
183 if (!assembly) {
184 g_free (file_name);
185 MessageBox (NULL, L"Cannot open assembly.", NULL, MB_ICONERROR);
186 mono_runtime_quit ();
187 ExitProcess (1);
190 image = assembly->image;
191 entry = mono_image_get_entry_point (image);
192 if (!entry) {
193 g_free (file_name);
194 MessageBox (NULL, L"Assembly doesn't have an entry point.", NULL, MB_ICONERROR);
195 mono_runtime_quit ();
196 ExitProcess (1);
199 method = mono_get_method_checked (image, entry, NULL, NULL, error);
200 if (method == NULL) {
201 g_free (file_name);
202 mono_error_cleanup (error); /* FIXME don't swallow the error */
203 MessageBox (NULL, L"The entry point method could not be loaded.", NULL, MB_ICONERROR);
204 mono_runtime_quit ();
205 ExitProcess (1);
208 argvw = CommandLineToArgvW (GetCommandLine (), &argc);
209 argv = g_new0 (gchar*, argc);
210 argv [0] = file_name;
211 for (i = 1; i < argc; ++i)
212 argv [i] = g_utf16_to_utf8 (argvw [i], -1, NULL, NULL, NULL);
213 LocalFree (argvw);
215 mono_runtime_run_main_checked (method, argc, argv, error);
216 mono_error_raise_exception_deprecated (error); /* OK, triggers unhandled exn handler */
217 mono_thread_manage ();
219 mono_runtime_quit ();
221 /* return does not terminate the process. */
222 ExitProcess (mono_environment_exitcode_get ());
224 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
226 /* Called by msvcrt.dll when shutting down. */
227 void STDMETHODCALLTYPE CorExitProcess(int exitCode)
229 /* FIXME: This is not currently supported by the runtime. */
230 #if 0
231 if (mono_get_root_domain () && !mono_runtime_is_shutting_down ()) {
232 mono_runtime_set_shutting_down ();
233 mono_thread_suspend_all_other_threads ();
234 mono_runtime_quit ();
236 #endif
237 ExitProcess (exitCode);
240 /* Called by ntdll.dll before _CorDllMain and _CorExeMain. */
241 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
242 STDAPI _CorValidateImage(PVOID *ImageBase, LPCWSTR FileName)
244 IMAGE_DOS_HEADER* DosHeader;
245 IMAGE_NT_HEADERS32* NtHeaders32;
246 IMAGE_DATA_DIRECTORY* CliHeaderDir;
247 #ifdef _WIN64
248 IMAGE_NT_HEADERS64* NtHeaders64;
249 MonoCLIHeader* CliHeader;
250 DWORD SizeOfHeaders;
251 #endif
252 DWORD* Address;
253 DWORD OldProtect;
255 DosHeader = (IMAGE_DOS_HEADER*)*ImageBase;
256 if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
257 return STATUS_INVALID_IMAGE_FORMAT;
259 NtHeaders32 = (IMAGE_NT_HEADERS32*)((DWORD_PTR)DosHeader + DosHeader->e_lfanew);
260 if (NtHeaders32->Signature != IMAGE_NT_SIGNATURE)
261 return STATUS_INVALID_IMAGE_FORMAT;
263 #ifdef _WIN64
264 NtHeaders64 = (IMAGE_NT_HEADERS64*)NtHeaders32;
265 if (NtHeaders64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
267 if (NtHeaders64->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
268 return STATUS_INVALID_IMAGE_FORMAT;
270 CliHeaderDir = &NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
271 if (!CliHeaderDir->VirtualAddress)
272 return STATUS_INVALID_IMAGE_FORMAT;
274 CliHeader = (MonoCLIHeader*)((DWORD_PTR)DosHeader + CliHeaderDir->VirtualAddress);
275 if (CliHeader->ch_flags & CLI_FLAGS_32BITREQUIRED)
276 return STATUS_INVALID_IMAGE_FORMAT;
278 if (CliHeader->ch_flags & CLI_FLAGS_ILONLY)
280 /* Avoid calling _CorDllMain because imports are not resolved for IL only images. */
281 if (NtHeaders64->OptionalHeader.AddressOfEntryPoint != 0)
283 Address = &NtHeaders64->OptionalHeader.AddressOfEntryPoint;
284 if (!VirtualProtect(Address, sizeof(DWORD), PAGE_READWRITE, &OldProtect))
285 return E_UNEXPECTED;
286 *Address = (DWORD)0;
287 if (!VirtualProtect(Address, sizeof(DWORD), OldProtect, &OldProtect))
288 return E_UNEXPECTED;
292 return STATUS_SUCCESS;
295 if (NtHeaders32->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
296 return STATUS_INVALID_IMAGE_FORMAT;
298 if (NtHeaders32->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
299 return STATUS_INVALID_IMAGE_FORMAT;
301 CliHeaderDir = &NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
302 if (!CliHeaderDir->VirtualAddress)
303 return STATUS_INVALID_IMAGE_FORMAT;
305 CliHeader = (MonoCLIHeader*)((DWORD_PTR)DosHeader + CliHeaderDir->VirtualAddress);
306 if (!(CliHeader->ch_flags & CLI_FLAGS_ILONLY) || (CliHeader->ch_flags & CLI_FLAGS_32BITREQUIRED))
307 return STATUS_INVALID_IMAGE_FORMAT;
309 /* Fixup IMAGE_NT_HEADERS32 to IMAGE_NT_HEADERS64. */
310 SizeOfHeaders = NtHeaders32->OptionalHeader.SizeOfHeaders;
311 if (SizeOfHeaders < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS64) + (sizeof(IMAGE_SECTION_HEADER) * NtHeaders32->FileHeader.NumberOfSections))
312 return STATUS_INVALID_IMAGE_FORMAT;
314 if (!VirtualProtect(DosHeader, SizeOfHeaders, PAGE_READWRITE, &OldProtect))
315 return E_UNEXPECTED;
317 memmove(NtHeaders64 + 1, IMAGE_FIRST_SECTION(NtHeaders32), sizeof(IMAGE_SECTION_HEADER) * NtHeaders32->FileHeader.NumberOfSections);
319 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1].Size = 0;
320 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1].VirtualAddress = 0;
321 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size;
322 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
323 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size = 0;
324 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress = 0;
325 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = 0;
326 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = 0;
327 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
328 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
329 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size = 0;
330 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress = 0;
331 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size = 0;
332 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress = 0;
333 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR].Size = 0;
334 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR].VirtualAddress = 0;
335 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_ARCHITECTURE].Size = 0;
336 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_ARCHITECTURE].VirtualAddress = 0;
337 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
338 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
339 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
340 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
341 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
342 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress;
343 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;
344 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;
345 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size;
346 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
347 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = 0;
348 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = 0;
349 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = 0;
350 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = 0;
352 NtHeaders64->OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
353 NtHeaders64->OptionalHeader.LoaderFlags = NtHeaders32->OptionalHeader.LoaderFlags;
354 NtHeaders64->OptionalHeader.SizeOfHeapCommit = (ULONGLONG)NtHeaders32->OptionalHeader.SizeOfHeapCommit;
355 NtHeaders64->OptionalHeader.SizeOfHeapReserve = (ULONGLONG)NtHeaders32->OptionalHeader.SizeOfHeapReserve;
356 NtHeaders64->OptionalHeader.SizeOfStackCommit = (ULONGLONG)NtHeaders32->OptionalHeader.SizeOfStackCommit;
357 NtHeaders64->OptionalHeader.SizeOfStackReserve = (ULONGLONG)NtHeaders32->OptionalHeader.SizeOfStackReserve;
358 NtHeaders64->OptionalHeader.DllCharacteristics = NtHeaders32->OptionalHeader.DllCharacteristics;
359 NtHeaders64->OptionalHeader.Subsystem = NtHeaders32->OptionalHeader.Subsystem;
360 NtHeaders64->OptionalHeader.CheckSum = NtHeaders32->OptionalHeader.CheckSum;
361 NtHeaders64->OptionalHeader.SizeOfHeaders = NtHeaders32->OptionalHeader.SizeOfHeaders;
362 NtHeaders64->OptionalHeader.SizeOfImage = NtHeaders32->OptionalHeader.SizeOfImage;
363 NtHeaders64->OptionalHeader.Win32VersionValue = NtHeaders32->OptionalHeader.Win32VersionValue;
364 NtHeaders64->OptionalHeader.MinorSubsystemVersion = NtHeaders32->OptionalHeader.MinorSubsystemVersion;
365 NtHeaders64->OptionalHeader.MajorSubsystemVersion = NtHeaders32->OptionalHeader.MajorSubsystemVersion;
366 NtHeaders64->OptionalHeader.MinorImageVersion = NtHeaders32->OptionalHeader.MinorImageVersion;
367 NtHeaders64->OptionalHeader.MajorImageVersion = NtHeaders32->OptionalHeader.MajorImageVersion;
368 NtHeaders64->OptionalHeader.MinorOperatingSystemVersion = NtHeaders32->OptionalHeader.MinorOperatingSystemVersion;
369 NtHeaders64->OptionalHeader.MajorOperatingSystemVersion = NtHeaders32->OptionalHeader.MajorOperatingSystemVersion;
370 NtHeaders64->OptionalHeader.FileAlignment = NtHeaders32->OptionalHeader.FileAlignment;
371 NtHeaders64->OptionalHeader.SectionAlignment = NtHeaders32->OptionalHeader.SectionAlignment;
372 NtHeaders64->OptionalHeader.ImageBase = (ULONGLONG)NtHeaders32->OptionalHeader.ImageBase;
373 /* BaseOfCode is at the same offset. */
374 NtHeaders64->OptionalHeader.AddressOfEntryPoint = 0;
375 NtHeaders64->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC;
376 NtHeaders64->FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER64);
378 if (!VirtualProtect(DosHeader, SizeOfHeaders, OldProtect, &OldProtect))
379 return E_UNEXPECTED;
380 #else
381 if (NtHeaders32->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
382 return STATUS_INVALID_IMAGE_FORMAT;
384 if (NtHeaders32->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
385 return STATUS_INVALID_IMAGE_FORMAT;
387 CliHeaderDir = &NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
388 if (!CliHeaderDir->VirtualAddress)
389 return STATUS_INVALID_IMAGE_FORMAT;
391 Address = &NtHeaders32->OptionalHeader.AddressOfEntryPoint;
392 if (!VirtualProtect(Address, sizeof(DWORD), PAGE_READWRITE, &OldProtect))
393 return E_UNEXPECTED;
394 if (NtHeaders32->FileHeader.Characteristics & IMAGE_FILE_DLL)
395 *Address = (DWORD)((DWORD_PTR)&_CorDllMain - (DWORD_PTR)DosHeader);
396 else
397 *Address = (DWORD)((DWORD_PTR)&_CorExeMain - (DWORD_PTR)DosHeader);
398 if (!VirtualProtect(Address, sizeof(DWORD), OldProtect, &OldProtect))
399 return E_UNEXPECTED;
400 #endif
402 return STATUS_SUCCESS;
404 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
406 /* Called by ntdll.dll. */
407 STDAPI_(VOID) _CorImageUnloading(PVOID ImageBase)
409 /* Nothing to do. */
412 STDAPI CorBindToRuntimeEx(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, DWORD startupFlags, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv)
414 if (ppv == NULL)
415 return E_POINTER;
417 *ppv = NULL;
418 return E_NOTIMPL;
421 STDAPI CorBindToRuntime(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv)
423 return CorBindToRuntimeEx (pwszVersion, pwszBuildFlavor, 0, rclsid, riid, ppv);
426 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
427 HMODULE WINAPI MonoLoadImage(LPCWSTR FileName)
429 HANDLE FileHandle;
430 DWORD FileSize;
431 HANDLE MapHandle;
432 IMAGE_DOS_HEADER* DosHeader;
433 IMAGE_NT_HEADERS32* NtHeaders32;
434 #ifdef _WIN64
435 IMAGE_NT_HEADERS64* NtHeaders64;
436 #endif
437 HMODULE ModuleHandle;
439 FileHandle = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
440 if (FileHandle == INVALID_HANDLE_VALUE)
441 return NULL;
443 FileSize = GetFileSize(FileHandle, NULL);
444 if (FileSize == INVALID_FILE_SIZE)
445 goto CloseFile;
447 MapHandle = CreateFileMapping(FileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
448 if (MapHandle == NULL)
449 goto CloseFile;
451 DosHeader = (IMAGE_DOS_HEADER*)MapViewOfFile(MapHandle, FILE_MAP_READ, 0, 0, 0);
452 if (DosHeader == NULL)
453 goto CloseMap;
455 if (FileSize < sizeof(IMAGE_DOS_HEADER) || DosHeader->e_magic != IMAGE_DOS_SIGNATURE || FileSize < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS32))
456 goto InvalidImageFormat;
458 NtHeaders32 = (IMAGE_NT_HEADERS32*)((DWORD_PTR)DosHeader + DosHeader->e_lfanew);
459 if (NtHeaders32->Signature != IMAGE_NT_SIGNATURE)
460 goto InvalidImageFormat;
462 #ifdef _WIN64
463 NtHeaders64 = (IMAGE_NT_HEADERS64*)NtHeaders32;
464 if (NtHeaders64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
466 if (FileSize < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS64) ||
467 NtHeaders64->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR ||
468 !NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress)
469 goto InvalidImageFormat;
471 goto ValidImage;
473 #endif
475 if (NtHeaders32->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC ||
476 NtHeaders32->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR ||
477 !NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress)
479 InvalidImageFormat:
480 SetLastError(STATUS_INVALID_IMAGE_FORMAT);
481 goto UnmapView;
484 #ifdef _WIN64
485 ValidImage:
486 #endif
487 UnmapViewOfFile(DosHeader);
488 CloseHandle(MapHandle);
490 ModuleHandle = LoadLibrary(FileName);
492 CloseHandle(FileHandle);
493 return ModuleHandle;
495 UnmapView:
496 UnmapViewOfFile(DosHeader);
497 CloseMap:
498 CloseHandle(MapHandle);
499 CloseFile:
500 CloseHandle(FileHandle);
501 return NULL;
503 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
505 typedef struct _EXPORT_FIXUP
507 LPCSTR Name;
508 union
510 PVOID Pointer;
511 DWORD_PTR DWordPtr;
512 BYTE Bytes[sizeof(PVOID)];
513 #ifdef _M_IA64
514 PLABEL_DESCRIPTOR* PLabel;
515 #endif
516 } ProcAddress;
517 } EXPORT_FIXUP;
519 /* Has to be binary ordered. */
520 static const EXPORT_FIXUP ExportFixups[] = {
521 {"CorBindToRuntime", {(PVOID)&CorBindToRuntime}},
522 {"CorBindToRuntimeEx", {(PVOID)&CorBindToRuntimeEx}},
523 {"CorExitProcess", {(PVOID)&CorExitProcess}},
524 {"_CorDllMain", {(PVOID)&_CorDllMain}},
525 {"_CorExeMain", {(PVOID)&_CorExeMain}},
526 {"_CorImageUnloading", {(PVOID)&_CorImageUnloading}},
527 {"_CorValidateImage", {(PVOID)&_CorValidateImage}},
528 {NULL, {NULL}}
531 #define EXPORT_FIXUP_COUNT (sizeof(ExportFixups) / sizeof(EXPORT_FIXUP) - 1)
533 static HMODULE ExportFixupModuleHandle = NULL;
534 static DWORD ExportFixupRvas[EXPORT_FIXUP_COUNT];
536 /* Fixup exported functions of mscoree.dll to our implementations. */
537 STDAPI MonoFixupCorEE(HMODULE ModuleHandle)
539 IMAGE_DOS_HEADER* DosHeader;
540 IMAGE_NT_HEADERS* NtHeaders;
541 IMAGE_DATA_DIRECTORY* ExportDataDir;
542 IMAGE_EXPORT_DIRECTORY* ExportDir;
543 DWORD* Functions;
544 DWORD* Names;
545 WORD* NameOrdinals;
546 EXPORT_FIXUP* ExportFixup;
547 DWORD* ExportFixupRva;
548 DWORD* Address;
549 DWORD OldProtect;
550 DWORD ProcRva;
551 DWORD i;
552 int cmp;
553 #ifdef _WIN64
554 MEMORY_BASIC_INFORMATION MemoryInfo;
555 PVOID Region;
556 PVOID RegionBase;
557 PVOID MaxRegionBase;
558 #ifdef _M_IA64
559 PLABEL_DESCRIPTOR* PLabel;
561 #define ELEMENT_SIZE sizeof(PLABEL_DESCRIPTOR)
562 #define REGION_WRITE_PROTECT PAGE_READWRITE
563 #define REGION_PROTECT PAGE_READ
564 #else
565 BYTE* Trampoline;
567 #define ELEMENT_SIZE 13
568 #define REGION_WRITE_PROTECT PAGE_EXECUTE_READWRITE
569 #define REGION_PROTECT PAGE_EXECUTE_READ
570 #endif
571 #endif
573 if (ExportFixupModuleHandle != NULL)
574 return ModuleHandle == ExportFixupModuleHandle ? S_OK : E_FAIL;
576 DosHeader = (IMAGE_DOS_HEADER*)ModuleHandle;
577 if (DosHeader == NULL)
578 return E_POINTER;
580 if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
581 return E_INVALIDARG;
583 NtHeaders = (IMAGE_NT_HEADERS*)((DWORD_PTR)DosHeader + DosHeader->e_lfanew);
584 if (NtHeaders->Signature != IMAGE_NT_SIGNATURE)
585 return E_INVALIDARG;
587 if (NtHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
588 return E_INVALIDARG;
590 if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_EXPORT)
591 return E_FAIL;
593 ExportDataDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
594 if (!ExportDataDir->VirtualAddress)
595 return E_FAIL;
597 #ifdef _WIN64
598 /* Allocate memory after base address because RVAs are 32-bit unsigned integers. */
599 RegionBase = DosHeader;
600 MaxRegionBase = (PVOID)((DWORD_PTR)RegionBase + (DWORD_PTR)(0x100000000L - (ELEMENT_SIZE * (EXPORT_FIXUP_COUNT - 1))));
601 for (;;)
603 if (!VirtualQuery(RegionBase, &MemoryInfo, sizeof(MEMORY_BASIC_INFORMATION)))
604 return E_UNEXPECTED;
605 if (MemoryInfo.State == MEM_FREE && MemoryInfo.RegionSize >= ELEMENT_SIZE * EXPORT_FIXUP_COUNT)
607 Region = VirtualAlloc(RegionBase, ELEMENT_SIZE * EXPORT_FIXUP_COUNT, MEM_COMMIT | MEM_RESERVE, REGION_WRITE_PROTECT);
608 if (Region != NULL)
609 break;
611 RegionBase = (PVOID)((DWORD_PTR)MemoryInfo.BaseAddress + (DWORD_PTR)MemoryInfo.RegionSize);
612 if (RegionBase > MaxRegionBase)
613 return E_OUTOFMEMORY;
616 #ifdef _M_IA64
617 PLabel = (PLABEL_DESCRIPTOR*)Region;
618 #else
619 Trampoline = (BYTE*)Region;
620 #endif
621 #endif
623 ExportDir = (IMAGE_EXPORT_DIRECTORY*)((DWORD_PTR)DosHeader + ExportDataDir->VirtualAddress);
624 Functions = (DWORD*)((DWORD_PTR)DosHeader + ExportDir->AddressOfFunctions);
625 Names = (DWORD*)((DWORD_PTR)DosHeader + ExportDir->AddressOfNames);
626 NameOrdinals = (WORD*)((DWORD_PTR)DosHeader + ExportDir->AddressOfNameOrdinals);
627 ExportFixup = (EXPORT_FIXUP*)&ExportFixups;
628 ExportFixupRva = (DWORD*)&ExportFixupRvas;
630 for (i = 0; i < ExportDir->NumberOfNames; i++)
632 cmp = strcmp((LPCSTR)((DWORD_PTR)DosHeader + Names[i]), ExportFixup->Name);
633 if (cmp > 0)
634 return E_FAIL;
636 if (cmp == 0)
638 #ifdef _WIN64
639 #if defined(_M_IA64)
640 ProcRva = (DWORD)((DWORD_PTR)PLabel - (DWORD_PTR)DosHeader);
641 *(PLabel)++ = *ExportFixup->ProcAddress.PLabel;
642 #elif defined(_M_AMD64)
643 ProcRva = (DWORD)((DWORD_PTR)Trampoline - (DWORD_PTR)DosHeader);
644 /* mov r11, ExportFixup->ProcAddress */
645 *(Trampoline)++ = 0x49;
646 *(Trampoline)++ = 0xBB;
647 *(Trampoline)++ = ExportFixup->ProcAddress.Bytes[0];
648 *(Trampoline)++ = ExportFixup->ProcAddress.Bytes[1];
649 *(Trampoline)++ = ExportFixup->ProcAddress.Bytes[2];
650 *(Trampoline)++ = ExportFixup->ProcAddress.Bytes[3];
651 *(Trampoline)++ = ExportFixup->ProcAddress.Bytes[4];
652 *(Trampoline)++ = ExportFixup->ProcAddress.Bytes[5];
653 *(Trampoline)++ = ExportFixup->ProcAddress.Bytes[6];
654 *(Trampoline)++ = ExportFixup->ProcAddress.Bytes[7];
655 /* jmp r11 */
656 *(Trampoline)++ = 0x41;
657 *(Trampoline)++ = 0xFF;
658 *(Trampoline)++ = 0xE3;
659 #else
660 #error Unsupported architecture.
661 #endif
662 #else
663 ProcRva = (DWORD)(ExportFixup->ProcAddress.DWordPtr - (DWORD_PTR)DosHeader);
664 #endif
665 Address = &Functions[NameOrdinals[i]];
666 if (!VirtualProtect(Address, sizeof(DWORD), PAGE_READWRITE, &OldProtect))
667 return E_UNEXPECTED;
668 *ExportFixupRva = *Address;
669 *Address = ProcRva;
670 if (!VirtualProtect(Address, sizeof(DWORD), OldProtect, &OldProtect))
671 return E_UNEXPECTED;
672 ExportFixup++;
673 if (ExportFixup->Name == NULL) {
674 #ifdef _WIN64
675 if (!VirtualProtect(Region, ELEMENT_SIZE * EXPORT_FIXUP_COUNT, REGION_PROTECT, &OldProtect))
676 return E_UNEXPECTED;
677 #endif
679 ExportFixupModuleHandle = ModuleHandle;
680 return S_OK;
682 ExportFixupRva++;
685 return E_FAIL;
688 /* Executable images are only mapped by the OS loader. We need to do fixups for native code support. */
689 STDAPI MonoFixupExe(HMODULE ModuleHandle)
691 IMAGE_DOS_HEADER* DosHeader;
692 IMAGE_NT_HEADERS* NtHeaders;
693 DWORD_PTR* Address;
694 DWORD OldProtect;
695 DWORD_PTR BaseDiff;
697 DosHeader = (IMAGE_DOS_HEADER*)ModuleHandle;
698 if (DosHeader == NULL)
699 return E_POINTER;
701 if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
702 return E_INVALIDARG;
704 NtHeaders = (IMAGE_NT_HEADERS*)((DWORD_PTR)DosHeader + DosHeader->e_lfanew);
705 if (NtHeaders->Signature != IMAGE_NT_SIGNATURE)
706 return E_INVALIDARG;
708 if (NtHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
709 return E_INVALIDARG;
711 if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
712 return S_OK;
714 if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
716 IMAGE_DATA_DIRECTORY* CliHeaderDir;
717 MonoCLIHeader* CliHeader;
719 CliHeaderDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
720 if (CliHeaderDir->VirtualAddress)
722 CliHeader = (MonoCLIHeader*)((DWORD_PTR)DosHeader + CliHeaderDir->VirtualAddress);
723 if (CliHeader->ch_flags & CLI_FLAGS_ILONLY)
724 return S_OK;
728 BaseDiff = (DWORD_PTR)DosHeader - NtHeaders->OptionalHeader.ImageBase;
729 if (BaseDiff != 0)
731 if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
732 return E_FAIL;
734 Address = &NtHeaders->OptionalHeader.ImageBase;
735 if (!VirtualProtect(Address, sizeof(DWORD_PTR), PAGE_READWRITE, &OldProtect))
736 return E_UNEXPECTED;
737 *Address = (DWORD_PTR)DosHeader;
738 if (!VirtualProtect(Address, sizeof(DWORD_PTR), OldProtect, &OldProtect))
739 return E_UNEXPECTED;
741 if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_BASERELOC)
743 IMAGE_DATA_DIRECTORY* BaseRelocDir;
744 IMAGE_BASE_RELOCATION* BaseReloc;
745 USHORT* RelocBlock;
746 ULONG BaseRelocSize;
747 ULONG RelocBlockSize;
748 USHORT RelocOffset;
749 DWORD_PTR UNALIGNED *RelocFixup;
751 BaseRelocDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
752 if (BaseRelocDir->VirtualAddress)
754 BaseReloc = (IMAGE_BASE_RELOCATION*)((DWORD_PTR)DosHeader + BaseRelocDir->VirtualAddress);
755 BaseRelocSize = BaseRelocDir->Size;
757 while (BaseRelocSize)
759 RelocBlockSize = BaseReloc->SizeOfBlock;
761 if (!RelocBlockSize || BaseRelocSize < RelocBlockSize)
762 return E_FAIL;
764 BaseRelocSize -= RelocBlockSize;
765 RelocBlock = (USHORT*)((DWORD_PTR)BaseReloc + sizeof(IMAGE_BASE_RELOCATION));
766 RelocBlockSize -= sizeof(IMAGE_BASE_RELOCATION);
767 RelocBlockSize /= sizeof(USHORT);
769 while (RelocBlockSize-- != 0)
771 RelocOffset = *RelocBlock & (USHORT)0x0fff;
772 RelocFixup = (DWORD_PTR*)((DWORD_PTR)DosHeader + BaseReloc->VirtualAddress + RelocOffset);
774 switch (*RelocBlock >> 12)
776 case IMAGE_REL_BASED_ABSOLUTE:
777 break;
779 #ifdef _WIN64
780 case IMAGE_REL_BASED_DIR64:
781 #else
782 case IMAGE_REL_BASED_HIGHLOW:
783 #endif
784 if (!VirtualProtect(RelocFixup, sizeof(DWORD_PTR), PAGE_EXECUTE_READWRITE, &OldProtect))
785 return E_UNEXPECTED;
786 *RelocFixup += BaseDiff;
787 if (!VirtualProtect(RelocFixup, sizeof(DWORD_PTR), OldProtect, &OldProtect))
788 return E_UNEXPECTED;
789 break;
791 default:
792 return E_FAIL;
795 RelocBlock++;
797 BaseReloc = (IMAGE_BASE_RELOCATION*)RelocBlock;
803 if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_IMPORT)
805 IMAGE_DATA_DIRECTORY* ImportDir;
806 IMAGE_IMPORT_DESCRIPTOR* ImportDesc;
807 HMODULE ImportModuleHandle;
808 IMAGE_THUNK_DATA* ImportThunkData;
809 DWORD_PTR ProcAddress;
811 ImportDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
812 if (ImportDir->VirtualAddress != 0)
814 ImportDesc = (IMAGE_IMPORT_DESCRIPTOR*)((DWORD_PTR)DosHeader + ImportDir->VirtualAddress);
815 while (ImportDesc->Name && ImportDesc->OriginalFirstThunk)
817 gchar *file_utf8 = (gchar *)((DWORD_PTR)DosHeader + ImportDesc->Name);
819 gunichar2 *file_utf16 = g_utf8_to_utf16 (file_utf8, (glong)strlen (file_utf8), NULL, NULL, NULL);
820 ImportModuleHandle = NULL;
821 if (file_utf16 != NULL) {
822 ImportModuleHandle = LoadLibraryW(file_utf16);
823 g_free (file_utf16);
826 if (ImportModuleHandle == NULL)
827 return E_FAIL;
829 ImportThunkData = (IMAGE_THUNK_DATA*)((DWORD_PTR)DosHeader + ImportDesc->OriginalFirstThunk);
830 while (ImportThunkData->u1.Ordinal != 0)
832 if (IMAGE_SNAP_BY_ORDINAL(ImportThunkData->u1.Ordinal))
833 ProcAddress = (DWORD_PTR)GetProcAddress(ImportModuleHandle, (LPCSTR)IMAGE_ORDINAL(ImportThunkData->u1.Ordinal));
834 else
836 IMAGE_IMPORT_BY_NAME* ImportByName = (IMAGE_IMPORT_BY_NAME*)((DWORD_PTR)DosHeader + ImportThunkData->u1.AddressOfData);
837 ProcAddress = (DWORD_PTR)GetProcAddress(ImportModuleHandle, (PCSTR)ImportByName->Name);
839 if (ProcAddress == 0)
840 return E_FAIL;
841 Address = (DWORD_PTR*)((DWORD_PTR)ImportThunkData - ImportDesc->OriginalFirstThunk + ImportDesc->FirstThunk);
842 if (!VirtualProtect(Address, sizeof(DWORD_PTR), PAGE_READWRITE, &OldProtect))
843 return E_UNEXPECTED;
844 *Address = ProcAddress;
845 if (!VirtualProtect(Address, sizeof(DWORD_PTR), OldProtect, &OldProtect))
846 return E_UNEXPECTED;
847 ImportThunkData++;
850 ImportDesc++;
855 return S_OK;
858 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
859 void
860 mono_coree_set_act_ctx (const char* file_name)
862 typedef HANDLE (WINAPI* CREATEACTCTXW_PROC) (PCACTCTXW pActCtx);
863 typedef BOOL (WINAPI* ACTIVATEACTCTX_PROC) (HANDLE hActCtx, ULONG_PTR* lpCookie);
865 HMODULE kernel32_handle;
866 CREATEACTCTXW_PROC CreateActCtx_proc;
867 ACTIVATEACTCTX_PROC ActivateActCtx_proc;
868 gchar* full_path;
869 gunichar2* full_path_utf16;
870 gchar* dir_name;
871 gunichar2* dir_name_utf16;
872 gchar* base_name;
873 gunichar2* base_name_utf16;
874 ACTCTX act_ctx;
875 HANDLE handle;
876 ULONG_PTR cookie;
878 kernel32_handle = GetModuleHandle (L"kernel32.dll");
879 if (!kernel32_handle)
880 return;
881 CreateActCtx_proc = (CREATEACTCTXW_PROC) GetProcAddress (kernel32_handle, "CreateActCtxW");
882 if (!CreateActCtx_proc)
883 return;
884 ActivateActCtx_proc = (ACTIVATEACTCTX_PROC) GetProcAddress (kernel32_handle, "ActivateActCtx");
885 if (!ActivateActCtx_proc)
886 return;
888 full_path = mono_path_canonicalize (file_name);
889 full_path_utf16 = g_utf8_to_utf16 (full_path, -1, NULL, NULL, NULL);
890 dir_name = g_path_get_dirname (full_path);
891 dir_name_utf16 = g_utf8_to_utf16 (dir_name, -1, NULL, NULL, NULL);
892 base_name = g_path_get_basename (full_path);
893 base_name_utf16 = g_utf8_to_utf16 (base_name, -1, NULL, NULL, NULL);
894 g_free (base_name);
895 g_free (dir_name);
896 g_free (full_path);
898 memset (&act_ctx, 0, sizeof (ACTCTX));
899 act_ctx.cbSize = sizeof (ACTCTX);
900 act_ctx.dwFlags = ACTCTX_FLAG_SET_PROCESS_DEFAULT | ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID | ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_APPLICATION_NAME_VALID;
901 act_ctx.lpSource = full_path_utf16;
902 act_ctx.lpAssemblyDirectory = dir_name_utf16;
903 act_ctx.lpResourceName = CREATEPROCESS_MANIFEST_RESOURCE_ID;
904 act_ctx.lpApplicationName = base_name_utf16;
906 handle = CreateActCtx_proc (&act_ctx);
907 if (handle == INVALID_HANDLE_VALUE && GetLastError () == ERROR_SXS_PROCESS_DEFAULT_ALREADY_SET) {
908 act_ctx.dwFlags &= ~ACTCTX_FLAG_SET_PROCESS_DEFAULT;
909 handle = CreateActCtx_proc (&act_ctx);
912 g_free (base_name_utf16);
913 g_free (dir_name_utf16);
914 g_free (full_path_utf16);
916 if (handle != INVALID_HANDLE_VALUE)
917 ActivateActCtx_proc (handle, &cookie);
919 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
921 void
922 mono_load_coree (const char* exe_file_name)
924 HMODULE module_handle;
925 gunichar2* file_name;
926 UINT required_size;
927 UINT size;
929 if (coree_module_handle)
930 return;
932 // No GC safe transition because this is called early in driver.c
933 if (!init_from_coree && exe_file_name)
934 mono_coree_set_act_ctx (exe_file_name);
936 /* ntdll.dll loads mscoree.dll from the system32 directory. */
937 required_size = GetSystemDirectory (NULL, 0);
938 file_name = g_new (gunichar2, required_size + 12);
939 size = GetSystemDirectory (file_name, required_size);
940 g_assert (size < required_size);
941 if (file_name [size - 1] != L'\\')
942 file_name [size++] = L'\\';
943 memcpy (&file_name [size], L"mscoree.dll", 12 * sizeof (gunichar2));
945 module_handle = LoadLibrary (file_name);
946 g_free (file_name);
948 if (module_handle && !SUCCEEDED (MonoFixupCorEE (module_handle))) {
949 FreeLibrary (module_handle);
950 module_handle = NULL;
953 coree_module_handle = module_handle;
956 void
957 mono_fixup_exe_image (MonoImage* image)
959 if (!init_from_coree && image && m_image_is_module_handle (image))
960 MonoFixupExe ((HMODULE) image->raw_data);
963 #endif /* HOST_WIN32 */