[interp] Small fixes (#11667)
[mono-project.git] / mono / metadata / coree.c
blob6baae2851754a9be81715b6e35895cfd9d7097b8
1 /**
2 * \file
3 * mscoree.dll functions
5 * Author:
6 * Kornel Pal <http://www.kornelpal.hu/>
8 * Copyright (C) 2008 Kornel Pal
9 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12 #include <config.h>
14 #ifdef HOST_WIN32
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"
34 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
35 #include <shellapi.h>
36 #endif
38 HMODULE coree_module_handle = NULL;
40 static gboolean init_from_coree = FALSE;
42 gchar*
43 mono_get_module_file_name (HMODULE module_handle)
45 gunichar2* file_name;
46 gchar* file_name_utf8;
47 DWORD buffer_size;
48 DWORD size;
50 buffer_size = 1024;
51 file_name = g_new (gunichar2, buffer_size);
53 for (;;) {
54 size = GetModuleFileName (module_handle, file_name, buffer_size);
55 if (!size) {
56 g_free (file_name);
57 return NULL;
60 g_assert (size <= buffer_size);
61 if (size != buffer_size)
62 break;
64 buffer_size += 1024;
65 file_name = g_realloc (file_name, buffer_size * sizeof (gunichar2));
68 file_name_utf8 = g_utf16_to_utf8 (file_name, size, NULL, NULL, NULL);
69 g_free (file_name);
71 return file_name_utf8;
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)
78 MonoAssembly* assembly;
79 MonoImage* image;
80 gchar* file_name;
81 gchar* error;
83 switch (dwReason)
85 case DLL_PROCESS_ATTACH:
86 DisableThreadLibraryCalls (hInst);
88 file_name = mono_get_module_file_name (hInst);
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;
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);
112 if (!image) {
113 g_free (file_name);
114 return FALSE;
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.
122 if (image->tables [MONO_TABLE_ASSEMBLY].rows && image->image_info->cli_cli_header.ch_vtable_fixups.rva)
123 assembly = mono_assembly_open_predicate (file_name, MONO_ASMCTX_DEFAULT, NULL, NULL, NULL, NULL);
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);
136 g_free (file_name);
137 break;
140 return TRUE;
142 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
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)
148 ERROR_DECL (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;
161 file_name = mono_get_module_file_name (NULL);
162 init_from_coree = TRUE;
163 domain = mono_runtime_load (file_name, NULL);
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);
174 assembly = mono_assembly_open_predicate (file_name, MONO_ASMCTX_DEFAULT, NULL, 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);
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);
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);
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);
208 mono_runtime_run_main_checked (method, argc, argv, error);
209 mono_error_raise_exception_deprecated (error); /* OK, triggers unhandled exn handler */
210 mono_thread_manage ();
212 mono_runtime_quit ();
214 /* return does not terminate the process. */
215 ExitProcess (mono_environment_exitcode_get ());
217 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
219 /* Called by msvcrt.dll when shutting down. */
220 void STDMETHODCALLTYPE CorExitProcess(int exitCode)
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 ();
229 #endif
230 ExitProcess (exitCode);
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)
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;
248 DosHeader = (IMAGE_DOS_HEADER*)*ImageBase;
249 if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
250 return STATUS_INVALID_IMAGE_FORMAT;
252 NtHeaders32 = (IMAGE_NT_HEADERS32*)((DWORD_PTR)DosHeader + DosHeader->e_lfanew);
253 if (NtHeaders32->Signature != IMAGE_NT_SIGNATURE)
254 return STATUS_INVALID_IMAGE_FORMAT;
256 #ifdef _WIN64
257 NtHeaders64 = (IMAGE_NT_HEADERS64*)NtHeaders32;
258 if (NtHeaders64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
260 if (NtHeaders64->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
261 return STATUS_INVALID_IMAGE_FORMAT;
263 CliHeaderDir = &NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
264 if (!CliHeaderDir->VirtualAddress)
265 return STATUS_INVALID_IMAGE_FORMAT;
267 CliHeader = (MonoCLIHeader*)((DWORD_PTR)DosHeader + CliHeaderDir->VirtualAddress);
268 if (CliHeader->ch_flags & CLI_FLAGS_32BITREQUIRED)
269 return STATUS_INVALID_IMAGE_FORMAT;
271 if (CliHeader->ch_flags & CLI_FLAGS_ILONLY)
273 /* Avoid calling _CorDllMain because imports are not resolved for IL only images. */
274 if (NtHeaders64->OptionalHeader.AddressOfEntryPoint != 0)
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;
285 return STATUS_SUCCESS;
288 if (NtHeaders32->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
289 return STATUS_INVALID_IMAGE_FORMAT;
291 if (NtHeaders32->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
292 return STATUS_INVALID_IMAGE_FORMAT;
294 CliHeaderDir = &NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
295 if (!CliHeaderDir->VirtualAddress)
296 return STATUS_INVALID_IMAGE_FORMAT;
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;
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;
307 if (!VirtualProtect(DosHeader, SizeOfHeaders, PAGE_READWRITE, &OldProtect))
308 return E_UNEXPECTED;
310 memmove(NtHeaders64 + 1, IMAGE_FIRST_SECTION(NtHeaders32), sizeof(IMAGE_SECTION_HEADER) * NtHeaders32->FileHeader.NumberOfSections);
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;
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);
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;
377 if (NtHeaders32->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
378 return STATUS_INVALID_IMAGE_FORMAT;
380 CliHeaderDir = &NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
381 if (!CliHeaderDir->VirtualAddress)
382 return STATUS_INVALID_IMAGE_FORMAT;
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
395 return STATUS_SUCCESS;
397 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
399 /* Called by ntdll.dll. */
400 STDAPI_(VOID) _CorImageUnloading(PVOID ImageBase)
402 /* Nothing to do. */
405 STDAPI CorBindToRuntimeEx(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, DWORD startupFlags, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv)
407 if (ppv == NULL)
408 return E_POINTER;
410 *ppv = NULL;
411 return E_NOTIMPL;
414 STDAPI CorBindToRuntime(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv)
416 return CorBindToRuntimeEx (pwszVersion, pwszBuildFlavor, 0, rclsid, riid, ppv);
419 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
420 HMODULE WINAPI MonoLoadImage(LPCWSTR FileName)
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;
432 FileHandle = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
433 if (FileHandle == INVALID_HANDLE_VALUE)
434 return NULL;
436 FileSize = GetFileSize(FileHandle, NULL);
437 if (FileSize == INVALID_FILE_SIZE)
438 goto CloseFile;
440 MapHandle = CreateFileMapping(FileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
441 if (MapHandle == NULL)
442 goto CloseFile;
444 DosHeader = (IMAGE_DOS_HEADER*)MapViewOfFile(MapHandle, FILE_MAP_READ, 0, 0, 0);
445 if (DosHeader == NULL)
446 goto CloseMap;
448 if (FileSize < sizeof(IMAGE_DOS_HEADER) || DosHeader->e_magic != IMAGE_DOS_SIGNATURE || FileSize < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS32))
449 goto InvalidImageFormat;
451 NtHeaders32 = (IMAGE_NT_HEADERS32*)((DWORD_PTR)DosHeader + DosHeader->e_lfanew);
452 if (NtHeaders32->Signature != IMAGE_NT_SIGNATURE)
453 goto InvalidImageFormat;
455 #ifdef _WIN64
456 NtHeaders64 = (IMAGE_NT_HEADERS64*)NtHeaders32;
457 if (NtHeaders64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
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;
464 goto ValidImage;
466 #endif
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)
472 InvalidImageFormat:
473 SetLastError(STATUS_INVALID_IMAGE_FORMAT);
474 goto UnmapView;
477 #ifdef _WIN64
478 ValidImage:
479 #endif
480 UnmapViewOfFile(DosHeader);
481 CloseHandle(MapHandle);
483 ModuleHandle = LoadLibrary(FileName);
485 CloseHandle(FileHandle);
486 return ModuleHandle;
488 UnmapView:
489 UnmapViewOfFile(DosHeader);
490 CloseMap:
491 CloseHandle(MapHandle);
492 CloseFile:
493 CloseHandle(FileHandle);
494 return NULL;
496 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
498 typedef struct _EXPORT_FIXUP
500 LPCSTR Name;
501 union
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;
512 /* Has to be binary ordered. */
513 static const EXPORT_FIXUP ExportFixups[] = {
514 {"CorBindToRuntime", {(PVOID)&CorBindToRuntime}},
515 {"CorBindToRuntimeEx", {(PVOID)&CorBindToRuntimeEx}},
516 {"CorExitProcess", {(PVOID)&CorExitProcess}},
517 {"_CorDllMain", {(PVOID)&_CorDllMain}},
518 {"_CorExeMain", {(PVOID)&_CorExeMain}},
519 {"_CorImageUnloading", {(PVOID)&_CorImageUnloading}},
520 {"_CorValidateImage", {(PVOID)&_CorValidateImage}},
521 {NULL, {NULL}}
524 #define EXPORT_FIXUP_COUNT (sizeof(ExportFixups) / sizeof(EXPORT_FIXUP) - 1)
526 static HMODULE ExportFixupModuleHandle = NULL;
527 static DWORD ExportFixupRvas[EXPORT_FIXUP_COUNT];
529 /* Fixup exported functions of mscoree.dll to our implementations. */
530 STDAPI MonoFixupCorEE(HMODULE ModuleHandle)
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;
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;
560 #define ELEMENT_SIZE 13
561 #define REGION_WRITE_PROTECT PAGE_EXECUTE_READWRITE
562 #define REGION_PROTECT PAGE_EXECUTE_READ
563 #endif
564 #endif
566 if (ExportFixupModuleHandle != NULL)
567 return ModuleHandle == ExportFixupModuleHandle ? S_OK : E_FAIL;
569 DosHeader = (IMAGE_DOS_HEADER*)ModuleHandle;
570 if (DosHeader == NULL)
571 return E_POINTER;
573 if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
574 return E_INVALIDARG;
576 NtHeaders = (IMAGE_NT_HEADERS*)((DWORD_PTR)DosHeader + DosHeader->e_lfanew);
577 if (NtHeaders->Signature != IMAGE_NT_SIGNATURE)
578 return E_INVALIDARG;
580 if (NtHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
581 return E_INVALIDARG;
583 if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_EXPORT)
584 return E_FAIL;
586 ExportDataDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
587 if (!ExportDataDir->VirtualAddress)
588 return E_FAIL;
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 (;;)
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)
600 Region = VirtualAlloc(RegionBase, ELEMENT_SIZE * EXPORT_FIXUP_COUNT, MEM_COMMIT | MEM_RESERVE, REGION_WRITE_PROTECT);
601 if (Region != NULL)
602 break;
604 RegionBase = (PVOID)((DWORD_PTR)MemoryInfo.BaseAddress + (DWORD_PTR)MemoryInfo.RegionSize);
605 if (RegionBase > MaxRegionBase)
606 return E_OUTOFMEMORY;
609 #ifdef _M_IA64
610 PLabel = (PLABEL_DESCRIPTOR*)Region;
611 #else
612 Trampoline = (BYTE*)Region;
613 #endif
614 #endif
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;
623 for (i = 0; i < ExportDir->NumberOfNames; i++)
625 cmp = strcmp((LPCSTR)((DWORD_PTR)DosHeader + Names[i]), ExportFixup->Name);
626 if (cmp > 0)
627 return E_FAIL;
629 if (cmp == 0)
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
672 ExportFixupModuleHandle = ModuleHandle;
673 return S_OK;
675 ExportFixupRva++;
678 return E_FAIL;
681 /* Executable images are only mapped by the OS loader. We need to do fixups for native code support. */
682 STDAPI MonoFixupExe(HMODULE ModuleHandle)
684 IMAGE_DOS_HEADER* DosHeader;
685 IMAGE_NT_HEADERS* NtHeaders;
686 DWORD_PTR* Address;
687 DWORD OldProtect;
688 DWORD_PTR BaseDiff;
690 DosHeader = (IMAGE_DOS_HEADER*)ModuleHandle;
691 if (DosHeader == NULL)
692 return E_POINTER;
694 if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
695 return E_INVALIDARG;
697 NtHeaders = (IMAGE_NT_HEADERS*)((DWORD_PTR)DosHeader + DosHeader->e_lfanew);
698 if (NtHeaders->Signature != IMAGE_NT_SIGNATURE)
699 return E_INVALIDARG;
701 if (NtHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
702 return E_INVALIDARG;
704 if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
705 return S_OK;
707 if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
709 IMAGE_DATA_DIRECTORY* CliHeaderDir;
710 MonoCLIHeader* CliHeader;
712 CliHeaderDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
713 if (CliHeaderDir->VirtualAddress)
715 CliHeader = (MonoCLIHeader*)((DWORD_PTR)DosHeader + CliHeaderDir->VirtualAddress);
716 if (CliHeader->ch_flags & CLI_FLAGS_ILONLY)
717 return S_OK;
721 BaseDiff = (DWORD_PTR)DosHeader - NtHeaders->OptionalHeader.ImageBase;
722 if (BaseDiff != 0)
724 if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
725 return E_FAIL;
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;
734 if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_BASERELOC)
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;
744 BaseRelocDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
745 if (BaseRelocDir->VirtualAddress)
747 BaseReloc = (IMAGE_BASE_RELOCATION*)((DWORD_PTR)DosHeader + BaseRelocDir->VirtualAddress);
748 BaseRelocSize = BaseRelocDir->Size;
750 while (BaseRelocSize)
752 RelocBlockSize = BaseReloc->SizeOfBlock;
754 if (!RelocBlockSize || BaseRelocSize < RelocBlockSize)
755 return E_FAIL;
757 BaseRelocSize -= RelocBlockSize;
758 RelocBlock = (USHORT*)((DWORD_PTR)BaseReloc + sizeof(IMAGE_BASE_RELOCATION));
759 RelocBlockSize -= sizeof(IMAGE_BASE_RELOCATION);
760 RelocBlockSize /= sizeof(USHORT);
762 while (RelocBlockSize-- != 0)
764 RelocOffset = *RelocBlock & (USHORT)0x0fff;
765 RelocFixup = (DWORD_PTR*)((DWORD_PTR)DosHeader + BaseReloc->VirtualAddress + RelocOffset);
767 switch (*RelocBlock >> 12)
769 case IMAGE_REL_BASED_ABSOLUTE:
770 break;
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;
784 default:
785 return E_FAIL;
788 RelocBlock++;
790 BaseReloc = (IMAGE_BASE_RELOCATION*)RelocBlock;
796 if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_IMPORT)
798 IMAGE_DATA_DIRECTORY* ImportDir;
799 IMAGE_IMPORT_DESCRIPTOR* ImportDesc;
800 HMODULE ImportModuleHandle;
801 IMAGE_THUNK_DATA* ImportThunkData;
802 DWORD_PTR ProcAddress;
804 ImportDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
805 if (ImportDir->VirtualAddress != 0)
807 ImportDesc = (IMAGE_IMPORT_DESCRIPTOR*)((DWORD_PTR)DosHeader + ImportDir->VirtualAddress);
808 while (ImportDesc->Name && ImportDesc->OriginalFirstThunk)
810 gchar *file_utf8 = (gchar *)((DWORD_PTR)DosHeader + ImportDesc->Name);
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);
819 if (ImportModuleHandle == NULL)
820 return E_FAIL;
822 ImportThunkData = (IMAGE_THUNK_DATA*)((DWORD_PTR)DosHeader + ImportDesc->OriginalFirstThunk);
823 while (ImportThunkData->u1.Ordinal != 0)
825 if (IMAGE_SNAP_BY_ORDINAL(ImportThunkData->u1.Ordinal))
826 ProcAddress = (DWORD_PTR)GetProcAddress(ImportModuleHandle, (LPCSTR)IMAGE_ORDINAL(ImportThunkData->u1.Ordinal));
827 else
829 IMAGE_IMPORT_BY_NAME* ImportByName = (IMAGE_IMPORT_BY_NAME*)((DWORD_PTR)DosHeader + ImportThunkData->u1.AddressOfData);
830 ProcAddress = (DWORD_PTR)GetProcAddress(ImportModuleHandle, (PCSTR)ImportByName->Name);
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++;
843 ImportDesc++;
848 return S_OK;
851 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
852 void
853 mono_coree_set_act_ctx (const char* file_name)
855 typedef HANDLE (WINAPI* CREATEACTCTXW_PROC) (PCACTCTXW pActCtx);
856 typedef BOOL (WINAPI* ACTIVATEACTCTX_PROC) (HANDLE hActCtx, ULONG_PTR* lpCookie);
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;
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;
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);
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 = CREATEPROCESS_MANIFEST_RESOURCE_ID;
897 act_ctx.lpApplicationName = base_name_utf16;
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);
905 g_free (base_name_utf16);
906 g_free (dir_name_utf16);
907 g_free (full_path_utf16);
909 if (handle != INVALID_HANDLE_VALUE)
910 ActivateActCtx_proc (handle, &cookie);
912 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
914 void
915 mono_load_coree (const char* exe_file_name)
917 HMODULE module_handle;
918 gunichar2* file_name;
919 UINT required_size;
920 UINT size;
922 if (coree_module_handle)
923 return;
925 if (!init_from_coree && exe_file_name)
926 mono_coree_set_act_ctx (exe_file_name);
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));
937 module_handle = LoadLibrary (file_name);
938 g_free (file_name);
940 if (module_handle && !SUCCEEDED (MonoFixupCorEE (module_handle))) {
941 FreeLibrary (module_handle);
942 module_handle = NULL;
945 coree_module_handle = module_handle;
948 void
949 mono_fixup_exe_image (MonoImage* image)
951 if (!init_from_coree && image && image->is_module_handle)
952 MonoFixupExe ((HMODULE) image->raw_data);
955 #endif /* HOST_WIN32 */