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