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