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