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