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