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