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