2 * coree.c: mscoree.dll functions
5 * Kornel Pal <http://www.kornelpal.hu/>
7 * Copyright (C) 2008 Kornel Pal
8 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
17 #include <mono/io-layer/io-layer.h>
18 #include <mono/utils/mono-path.h>
20 #include "metadata-internals.h"
23 #include "domain-internals.h"
24 #include "appdomain.h"
26 #include "object-internals.h"
29 #include "environment.h"
31 #include "coree-internals.h"
33 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
37 HMODULE coree_module_handle = NULL;
39 static gboolean init_from_coree = FALSE;
42 mono_get_module_file_name (HMODULE module_handle)
45 gchar* file_name_utf8;
50 file_name = g_new (gunichar2, buffer_size);
53 size = GetModuleFileName (module_handle, file_name, buffer_size);
59 g_assert (size <= buffer_size);
60 if (size != buffer_size)
64 file_name = g_realloc (file_name, buffer_size * sizeof (gunichar2));
67 file_name_utf8 = g_utf16_to_utf8 (file_name, size, NULL, NULL, NULL);
70 return file_name_utf8;
73 /* Entry point called by LdrLoadDll of ntdll.dll after _CorValidateImage. */
74 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
75 BOOL STDMETHODCALLTYPE _CorDllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved)
77 MonoAssembly* assembly;
84 case DLL_PROCESS_ATTACH:
85 DisableThreadLibraryCalls (hInst);
87 file_name = mono_get_module_file_name (hInst);
89 if (mono_get_root_domain ()) {
90 image = mono_image_open_from_module_handle (hInst, mono_path_resolve_symlinks (file_name), TRUE, NULL);
92 init_from_coree = TRUE;
93 mono_runtime_load (file_name, NULL);
94 error = (gchar*) mono_check_corlib_version ();
102 image = mono_image_open (file_name, NULL);
104 image->has_entry_point = TRUE;
105 mono_close_exe_image ();
106 /* Decrement reference count to zero. (Image will not be closed.) */
107 mono_image_close (image);
117 * FIXME: Find a better way to call mono_image_fixup_vtable. Only
118 * loader trampolines should be used and assembly loading should
119 * probably be delayed until the first call to an exported function.
121 if (image->tables [MONO_TABLE_ASSEMBLY].rows && ((MonoCLIImageInfo*) image->image_info)->cli_cli_header.ch_vtable_fixups.rva)
122 assembly = mono_assembly_open (file_name, NULL);
126 case DLL_PROCESS_DETACH:
127 if (lpReserved != NULL)
128 /* The process is terminating. */
130 file_name = mono_get_module_file_name (hInst);
131 image = mono_image_loaded (file_name);
133 mono_image_close (image);
141 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
143 /* Called by ntdll.dll reagardless of entry point after _CorValidateImage. */
144 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
145 __int32 STDMETHODCALLTYPE _CorExeMain(void)
149 MonoAssembly* assembly;
154 gchar* corlib_version_error;
160 file_name = mono_get_module_file_name (NULL);
161 init_from_coree = TRUE;
162 domain = mono_runtime_load (file_name, NULL);
164 corlib_version_error = (gchar*) mono_check_corlib_version ();
165 if (corlib_version_error) {
166 g_free (corlib_version_error);
168 MessageBox (NULL, L"Corlib not in sync with this runtime.", NULL, MB_ICONERROR);
169 mono_runtime_quit ();
173 assembly = mono_assembly_open (file_name, NULL);
174 mono_close_exe_image ();
177 MessageBox (NULL, L"Cannot open assembly.", NULL, MB_ICONERROR);
178 mono_runtime_quit ();
182 image = assembly->image;
183 entry = mono_image_get_entry_point (image);
186 MessageBox (NULL, L"Assembly doesn't have an entry point.", NULL, MB_ICONERROR);
187 mono_runtime_quit ();
191 method = mono_get_method_checked (image, entry, NULL, NULL, &error);
192 if (method == NULL) {
194 mono_error_cleanup (&error); /* FIXME don't swallow the error */
195 MessageBox (NULL, L"The entry point method could not be loaded.", NULL, MB_ICONERROR);
196 mono_runtime_quit ();
200 argvw = CommandLineToArgvW (GetCommandLine (), &argc);
201 argv = g_new0 (gchar*, argc);
202 argv [0] = file_name;
203 for (i = 1; i < argc; ++i)
204 argv [i] = g_utf16_to_utf8 (argvw [i], -1, NULL, NULL, NULL);
207 mono_runtime_run_main_checked (method, argc, argv, &error);
208 mono_error_raise_exception (&error); /* OK, triggers unhandled exn handler */
209 mono_thread_manage ();
211 mono_runtime_quit ();
213 /* return does not terminate the process. */
214 ExitProcess (mono_environment_exitcode_get ());
216 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
218 /* Called by msvcrt.dll when shutting down. */
219 void STDMETHODCALLTYPE CorExitProcess(int exitCode)
221 /* FIXME: This is not currently supported by the runtime. */
223 if (mono_get_root_domain () && !mono_runtime_is_shutting_down ()) {
224 mono_runtime_set_shutting_down ();
225 mono_thread_suspend_all_other_threads ();
226 mono_runtime_quit ();
229 ExitProcess (exitCode);
232 /* Called by ntdll.dll before _CorDllMain and _CorExeMain. */
233 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
234 STDAPI _CorValidateImage(PVOID *ImageBase, LPCWSTR FileName)
236 IMAGE_DOS_HEADER* DosHeader;
237 IMAGE_NT_HEADERS32* NtHeaders32;
238 IMAGE_DATA_DIRECTORY* CliHeaderDir;
240 IMAGE_NT_HEADERS64* NtHeaders64;
241 MonoCLIHeader* CliHeader;
247 DosHeader = (IMAGE_DOS_HEADER*)*ImageBase;
248 if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
249 return STATUS_INVALID_IMAGE_FORMAT;
251 NtHeaders32 = (IMAGE_NT_HEADERS32*)((DWORD_PTR)DosHeader + DosHeader->e_lfanew);
252 if (NtHeaders32->Signature != IMAGE_NT_SIGNATURE)
253 return STATUS_INVALID_IMAGE_FORMAT;
256 NtHeaders64 = (IMAGE_NT_HEADERS64*)NtHeaders32;
257 if (NtHeaders64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
259 if (NtHeaders64->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
260 return STATUS_INVALID_IMAGE_FORMAT;
262 CliHeaderDir = &NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
263 if (!CliHeaderDir->VirtualAddress)
264 return STATUS_INVALID_IMAGE_FORMAT;
266 CliHeader = (MonoCLIHeader*)((DWORD_PTR)DosHeader + CliHeaderDir->VirtualAddress);
267 if (CliHeader->ch_flags & CLI_FLAGS_32BITREQUIRED)
268 return STATUS_INVALID_IMAGE_FORMAT;
270 if (CliHeader->ch_flags & CLI_FLAGS_ILONLY)
272 /* Avoid calling _CorDllMain because imports are not resolved for IL only images. */
273 if (NtHeaders64->OptionalHeader.AddressOfEntryPoint != 0)
275 Address = &NtHeaders64->OptionalHeader.AddressOfEntryPoint;
276 if (!VirtualProtect(Address, sizeof(DWORD), PAGE_READWRITE, &OldProtect))
279 if (!VirtualProtect(Address, sizeof(DWORD), OldProtect, &OldProtect))
284 return STATUS_SUCCESS;
287 if (NtHeaders32->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
288 return STATUS_INVALID_IMAGE_FORMAT;
290 if (NtHeaders32->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
291 return STATUS_INVALID_IMAGE_FORMAT;
293 CliHeaderDir = &NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
294 if (!CliHeaderDir->VirtualAddress)
295 return STATUS_INVALID_IMAGE_FORMAT;
297 CliHeader = (MonoCLIHeader*)((DWORD_PTR)DosHeader + CliHeaderDir->VirtualAddress);
298 if (!(CliHeader->ch_flags & CLI_FLAGS_ILONLY) || (CliHeader->ch_flags & CLI_FLAGS_32BITREQUIRED))
299 return STATUS_INVALID_IMAGE_FORMAT;
301 /* Fixup IMAGE_NT_HEADERS32 to IMAGE_NT_HEADERS64. */
302 SizeOfHeaders = NtHeaders32->OptionalHeader.SizeOfHeaders;
303 if (SizeOfHeaders < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS64) + (sizeof(IMAGE_SECTION_HEADER) * NtHeaders32->FileHeader.NumberOfSections))
304 return STATUS_INVALID_IMAGE_FORMAT;
306 if (!VirtualProtect(DosHeader, SizeOfHeaders, PAGE_READWRITE, &OldProtect))
309 memmove(NtHeaders64 + 1, IMAGE_FIRST_SECTION(NtHeaders32), sizeof(IMAGE_SECTION_HEADER) * NtHeaders32->FileHeader.NumberOfSections);
311 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1].Size = 0;
312 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1].VirtualAddress = 0;
313 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size;
314 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
315 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size = 0;
316 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress = 0;
317 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = 0;
318 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = 0;
319 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
320 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
321 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size = 0;
322 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress = 0;
323 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size = 0;
324 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress = 0;
325 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR].Size = 0;
326 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR].VirtualAddress = 0;
327 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_ARCHITECTURE].Size = 0;
328 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_ARCHITECTURE].VirtualAddress = 0;
329 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
330 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
331 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
332 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
333 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
334 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress;
335 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;
336 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;
337 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size;
338 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
339 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = 0;
340 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = 0;
341 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = 0;
342 NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = 0;
344 NtHeaders64->OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
345 NtHeaders64->OptionalHeader.LoaderFlags = NtHeaders32->OptionalHeader.LoaderFlags;
346 NtHeaders64->OptionalHeader.SizeOfHeapCommit = (ULONGLONG)NtHeaders32->OptionalHeader.SizeOfHeapCommit;
347 NtHeaders64->OptionalHeader.SizeOfHeapReserve = (ULONGLONG)NtHeaders32->OptionalHeader.SizeOfHeapReserve;
348 NtHeaders64->OptionalHeader.SizeOfStackCommit = (ULONGLONG)NtHeaders32->OptionalHeader.SizeOfStackCommit;
349 NtHeaders64->OptionalHeader.SizeOfStackReserve = (ULONGLONG)NtHeaders32->OptionalHeader.SizeOfStackReserve;
350 NtHeaders64->OptionalHeader.DllCharacteristics = NtHeaders32->OptionalHeader.DllCharacteristics;
351 NtHeaders64->OptionalHeader.Subsystem = NtHeaders32->OptionalHeader.Subsystem;
352 NtHeaders64->OptionalHeader.CheckSum = NtHeaders32->OptionalHeader.CheckSum;
353 NtHeaders64->OptionalHeader.SizeOfHeaders = NtHeaders32->OptionalHeader.SizeOfHeaders;
354 NtHeaders64->OptionalHeader.SizeOfImage = NtHeaders32->OptionalHeader.SizeOfImage;
355 NtHeaders64->OptionalHeader.Win32VersionValue = NtHeaders32->OptionalHeader.Win32VersionValue;
356 NtHeaders64->OptionalHeader.MinorSubsystemVersion = NtHeaders32->OptionalHeader.MinorSubsystemVersion;
357 NtHeaders64->OptionalHeader.MajorSubsystemVersion = NtHeaders32->OptionalHeader.MajorSubsystemVersion;
358 NtHeaders64->OptionalHeader.MinorImageVersion = NtHeaders32->OptionalHeader.MinorImageVersion;
359 NtHeaders64->OptionalHeader.MajorImageVersion = NtHeaders32->OptionalHeader.MajorImageVersion;
360 NtHeaders64->OptionalHeader.MinorOperatingSystemVersion = NtHeaders32->OptionalHeader.MinorOperatingSystemVersion;
361 NtHeaders64->OptionalHeader.MajorOperatingSystemVersion = NtHeaders32->OptionalHeader.MajorOperatingSystemVersion;
362 NtHeaders64->OptionalHeader.FileAlignment = NtHeaders32->OptionalHeader.FileAlignment;
363 NtHeaders64->OptionalHeader.SectionAlignment = NtHeaders32->OptionalHeader.SectionAlignment;
364 NtHeaders64->OptionalHeader.ImageBase = (ULONGLONG)NtHeaders32->OptionalHeader.ImageBase;
365 /* BaseOfCode is at the same offset. */
366 NtHeaders64->OptionalHeader.AddressOfEntryPoint = 0;
367 NtHeaders64->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC;
368 NtHeaders64->FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER64);
370 if (!VirtualProtect(DosHeader, SizeOfHeaders, OldProtect, &OldProtect))
373 if (NtHeaders32->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
374 return STATUS_INVALID_IMAGE_FORMAT;
376 if (NtHeaders32->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
377 return STATUS_INVALID_IMAGE_FORMAT;
379 CliHeaderDir = &NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
380 if (!CliHeaderDir->VirtualAddress)
381 return STATUS_INVALID_IMAGE_FORMAT;
383 Address = &NtHeaders32->OptionalHeader.AddressOfEntryPoint;
384 if (!VirtualProtect(Address, sizeof(DWORD), PAGE_READWRITE, &OldProtect))
386 if (NtHeaders32->FileHeader.Characteristics & IMAGE_FILE_DLL)
387 *Address = (DWORD)((DWORD_PTR)&_CorDllMain - (DWORD_PTR)DosHeader);
389 *Address = (DWORD)((DWORD_PTR)&_CorExeMain - (DWORD_PTR)DosHeader);
390 if (!VirtualProtect(Address, sizeof(DWORD), OldProtect, &OldProtect))
394 return STATUS_SUCCESS;
396 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
398 /* Called by ntdll.dll. */
399 STDAPI_(VOID) _CorImageUnloading(PVOID ImageBase)
404 STDAPI CorBindToRuntimeEx(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, DWORD startupFlags, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv)
413 STDAPI CorBindToRuntime(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv)
415 return CorBindToRuntimeEx (pwszVersion, pwszBuildFlavor, 0, rclsid, riid, ppv);
418 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
419 HMODULE WINAPI MonoLoadImage(LPCWSTR FileName)
424 IMAGE_DOS_HEADER* DosHeader;
425 IMAGE_NT_HEADERS32* NtHeaders32;
427 IMAGE_NT_HEADERS64* NtHeaders64;
429 HMODULE ModuleHandle;
431 FileHandle = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
432 if (FileHandle == INVALID_HANDLE_VALUE)
435 FileSize = GetFileSize(FileHandle, NULL);
436 if (FileSize == INVALID_FILE_SIZE)
439 MapHandle = CreateFileMapping(FileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
440 if (MapHandle == NULL)
443 DosHeader = (IMAGE_DOS_HEADER*)MapViewOfFile(MapHandle, FILE_MAP_READ, 0, 0, 0);
444 if (DosHeader == NULL)
447 if (FileSize < sizeof(IMAGE_DOS_HEADER) || DosHeader->e_magic != IMAGE_DOS_SIGNATURE || FileSize < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS32))
448 goto InvalidImageFormat;
450 NtHeaders32 = (IMAGE_NT_HEADERS32*)((DWORD_PTR)DosHeader + DosHeader->e_lfanew);
451 if (NtHeaders32->Signature != IMAGE_NT_SIGNATURE)
452 goto InvalidImageFormat;
455 NtHeaders64 = (IMAGE_NT_HEADERS64*)NtHeaders32;
456 if (NtHeaders64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
458 if (FileSize < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS64) ||
459 NtHeaders64->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR ||
460 !NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress)
461 goto InvalidImageFormat;
467 if (NtHeaders32->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC ||
468 NtHeaders32->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR ||
469 !NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress)
472 SetLastError(STATUS_INVALID_IMAGE_FORMAT);
479 UnmapViewOfFile(DosHeader);
480 CloseHandle(MapHandle);
482 ModuleHandle = LoadLibrary(FileName);
484 CloseHandle(FileHandle);
488 UnmapViewOfFile(DosHeader);
490 CloseHandle(MapHandle);
492 CloseHandle(FileHandle);
495 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
497 typedef struct _EXPORT_FIXUP
504 BYTE Bytes[sizeof(PVOID)];
506 PLABEL_DESCRIPTOR* PLabel;
511 /* Has to be binary ordered. */
512 static const EXPORT_FIXUP ExportFixups[] = {
513 {"CorBindToRuntime", {&CorBindToRuntime}},
514 {"CorBindToRuntimeEx", {&CorBindToRuntimeEx}},
515 {"CorExitProcess", {&CorExitProcess}},
516 {"_CorDllMain", {&_CorDllMain}},
517 {"_CorExeMain", {&_CorExeMain}},
518 {"_CorImageUnloading", {&_CorImageUnloading}},
519 {"_CorValidateImage", {&_CorValidateImage}},
523 #define EXPORT_FIXUP_COUNT (sizeof(ExportFixups) / sizeof(EXPORT_FIXUP) - 1)
525 static HMODULE ExportFixupModuleHandle = NULL;
526 static DWORD ExportFixupRvas[EXPORT_FIXUP_COUNT];
528 /* Fixup exported functions of mscoree.dll to our implementations. */
529 STDAPI MonoFixupCorEE(HMODULE ModuleHandle)
531 IMAGE_DOS_HEADER* DosHeader;
532 IMAGE_NT_HEADERS* NtHeaders;
533 IMAGE_DATA_DIRECTORY* ExportDataDir;
534 IMAGE_EXPORT_DIRECTORY* ExportDir;
538 EXPORT_FIXUP* ExportFixup;
539 DWORD* ExportFixupRva;
546 MEMORY_BASIC_INFORMATION MemoryInfo;
551 PLABEL_DESCRIPTOR* PLabel;
553 #define ELEMENT_SIZE sizeof(PLABEL_DESCRIPTOR)
554 #define REGION_WRITE_PROTECT PAGE_READWRITE
555 #define REGION_PROTECT PAGE_READ
559 #define ELEMENT_SIZE 13
560 #define REGION_WRITE_PROTECT PAGE_EXECUTE_READWRITE
561 #define REGION_PROTECT PAGE_EXECUTE_READ
565 if (ExportFixupModuleHandle != NULL)
566 return ModuleHandle == ExportFixupModuleHandle ? S_OK : E_FAIL;
568 DosHeader = (IMAGE_DOS_HEADER*)ModuleHandle;
569 if (DosHeader == NULL)
572 if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
575 NtHeaders = (IMAGE_NT_HEADERS*)((DWORD_PTR)DosHeader + DosHeader->e_lfanew);
576 if (NtHeaders->Signature != IMAGE_NT_SIGNATURE)
579 if (NtHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
582 if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_EXPORT)
585 ExportDataDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
586 if (!ExportDataDir->VirtualAddress)
590 /* Allocate memory after base address because RVAs are 32-bit unsigned integers. */
591 RegionBase = DosHeader;
592 MaxRegionBase = (PVOID)((DWORD_PTR)RegionBase + (DWORD_PTR)(0x100000000L - (ELEMENT_SIZE * (EXPORT_FIXUP_COUNT - 1))));
595 if (!VirtualQuery(RegionBase, &MemoryInfo, sizeof(MEMORY_BASIC_INFORMATION)))
597 if (MemoryInfo.State == MEM_FREE && MemoryInfo.RegionSize >= ELEMENT_SIZE * EXPORT_FIXUP_COUNT)
599 Region = VirtualAlloc(RegionBase, ELEMENT_SIZE * EXPORT_FIXUP_COUNT, MEM_COMMIT | MEM_RESERVE, REGION_WRITE_PROTECT);
603 RegionBase = (PVOID)((DWORD_PTR)MemoryInfo.BaseAddress + (DWORD_PTR)MemoryInfo.RegionSize);
604 if (RegionBase > MaxRegionBase)
605 return E_OUTOFMEMORY;
609 PLabel = (PLABEL_DESCRIPTOR*)Region;
611 Trampoline = (BYTE*)Region;
615 ExportDir = (IMAGE_EXPORT_DIRECTORY*)((DWORD_PTR)DosHeader + ExportDataDir->VirtualAddress);
616 Functions = (DWORD*)((DWORD_PTR)DosHeader + ExportDir->AddressOfFunctions);
617 Names = (DWORD*)((DWORD_PTR)DosHeader + ExportDir->AddressOfNames);
618 NameOrdinals = (WORD*)((DWORD_PTR)DosHeader + ExportDir->AddressOfNameOrdinals);
619 ExportFixup = (EXPORT_FIXUP*)&ExportFixups;
620 ExportFixupRva = (DWORD*)&ExportFixupRvas;
622 for (i = 0; i < ExportDir->NumberOfNames; i++)
624 cmp = strcmp((LPCSTR)((DWORD_PTR)DosHeader + Names[i]), ExportFixup->Name);
632 ProcRva = (DWORD)((DWORD_PTR)PLabel - (DWORD_PTR)DosHeader);
633 *(PLabel)++ = *ExportFixup->ProcAddress.PLabel;
634 #elif defined(_M_AMD64)
635 ProcRva = (DWORD)((DWORD_PTR)Trampoline - (DWORD_PTR)DosHeader);
636 /* mov r11, ExportFixup->ProcAddress */
637 *(Trampoline)++ = 0x49;
638 *(Trampoline)++ = 0xBB;
639 *(Trampoline)++ = ExportFixup->ProcAddress.Bytes[0];
640 *(Trampoline)++ = ExportFixup->ProcAddress.Bytes[1];
641 *(Trampoline)++ = ExportFixup->ProcAddress.Bytes[2];
642 *(Trampoline)++ = ExportFixup->ProcAddress.Bytes[3];
643 *(Trampoline)++ = ExportFixup->ProcAddress.Bytes[4];
644 *(Trampoline)++ = ExportFixup->ProcAddress.Bytes[5];
645 *(Trampoline)++ = ExportFixup->ProcAddress.Bytes[6];
646 *(Trampoline)++ = ExportFixup->ProcAddress.Bytes[7];
648 *(Trampoline)++ = 0x41;
649 *(Trampoline)++ = 0xFF;
650 *(Trampoline)++ = 0xE3;
652 #error Unsupported architecture.
655 ProcRva = (DWORD)(ExportFixup->ProcAddress.DWordPtr - (DWORD_PTR)DosHeader);
657 Address = &Functions[NameOrdinals[i]];
658 if (!VirtualProtect(Address, sizeof(DWORD), PAGE_READWRITE, &OldProtect))
660 *ExportFixupRva = *Address;
662 if (!VirtualProtect(Address, sizeof(DWORD), OldProtect, &OldProtect))
665 if (ExportFixup->Name == NULL) {
667 if (!VirtualProtect(Region, ELEMENT_SIZE * EXPORT_FIXUP_COUNT, REGION_PROTECT, &OldProtect))
671 ExportFixupModuleHandle = ModuleHandle;
680 /* Executable images are only mapped by the OS loader. We need to do fixups for native code support. */
681 STDAPI MonoFixupExe(HMODULE ModuleHandle)
683 IMAGE_DOS_HEADER* DosHeader;
684 IMAGE_NT_HEADERS* NtHeaders;
689 DosHeader = (IMAGE_DOS_HEADER*)ModuleHandle;
690 if (DosHeader == NULL)
693 if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
696 NtHeaders = (IMAGE_NT_HEADERS*)((DWORD_PTR)DosHeader + DosHeader->e_lfanew);
697 if (NtHeaders->Signature != IMAGE_NT_SIGNATURE)
700 if (NtHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
703 if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
706 if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
708 IMAGE_DATA_DIRECTORY* CliHeaderDir;
709 MonoCLIHeader* CliHeader;
711 CliHeaderDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
712 if (CliHeaderDir->VirtualAddress)
714 CliHeader = (MonoCLIHeader*)((DWORD_PTR)DosHeader + CliHeaderDir->VirtualAddress);
715 if (CliHeader->ch_flags & CLI_FLAGS_ILONLY)
720 BaseDiff = (DWORD_PTR)DosHeader - NtHeaders->OptionalHeader.ImageBase;
723 if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
726 Address = &NtHeaders->OptionalHeader.ImageBase;
727 if (!VirtualProtect(Address, sizeof(DWORD_PTR), PAGE_READWRITE, &OldProtect))
729 *Address = (DWORD_PTR)DosHeader;
730 if (!VirtualProtect(Address, sizeof(DWORD_PTR), OldProtect, &OldProtect))
733 if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_BASERELOC)
735 IMAGE_DATA_DIRECTORY* BaseRelocDir;
736 IMAGE_BASE_RELOCATION* BaseReloc;
739 ULONG RelocBlockSize;
741 DWORD_PTR UNALIGNED *RelocFixup;
743 BaseRelocDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
744 if (BaseRelocDir->VirtualAddress)
746 BaseReloc = (IMAGE_BASE_RELOCATION*)((DWORD_PTR)DosHeader + BaseRelocDir->VirtualAddress);
747 BaseRelocSize = BaseRelocDir->Size;
749 while (BaseRelocSize)
751 RelocBlockSize = BaseReloc->SizeOfBlock;
753 if (!RelocBlockSize || BaseRelocSize < RelocBlockSize)
756 BaseRelocSize -= RelocBlockSize;
757 RelocBlock = (USHORT*)((DWORD_PTR)BaseReloc + sizeof(IMAGE_BASE_RELOCATION));
758 RelocBlockSize -= sizeof(IMAGE_BASE_RELOCATION);
759 RelocBlockSize /= sizeof(USHORT);
761 while (RelocBlockSize-- != 0)
763 RelocOffset = *RelocBlock & (USHORT)0x0fff;
764 RelocFixup = (DWORD_PTR*)((DWORD_PTR)DosHeader + BaseReloc->VirtualAddress + RelocOffset);
766 switch (*RelocBlock >> 12)
768 case IMAGE_REL_BASED_ABSOLUTE:
772 case IMAGE_REL_BASED_DIR64:
774 case IMAGE_REL_BASED_HIGHLOW:
776 if (!VirtualProtect(RelocFixup, sizeof(DWORD_PTR), PAGE_EXECUTE_READWRITE, &OldProtect))
778 *RelocFixup += BaseDiff;
779 if (!VirtualProtect(RelocFixup, sizeof(DWORD_PTR), OldProtect, &OldProtect))
789 BaseReloc = (IMAGE_BASE_RELOCATION*)RelocBlock;
795 if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_IMPORT)
797 IMAGE_DATA_DIRECTORY* ImportDir;
798 IMAGE_IMPORT_DESCRIPTOR* ImportDesc;
799 HMODULE ImportModuleHandle;
800 IMAGE_THUNK_DATA* ImportThunkData;
801 DWORD_PTR ProcAddress;
803 ImportDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
804 if (ImportDir->VirtualAddress != 0)
806 ImportDesc = (IMAGE_IMPORT_DESCRIPTOR*)((DWORD_PTR)DosHeader + ImportDir->VirtualAddress);
807 while (ImportDesc->Name && ImportDesc->OriginalFirstThunk)
809 gchar *file_utf8 = (gchar *)((DWORD_PTR)DosHeader + ImportDesc->Name);
811 gunichar2 *file_utf16 = g_utf8_to_utf16 (file_utf8, (glong)strlen (file_utf8), NULL, NULL, NULL);
812 ImportModuleHandle = NULL;
813 if (file_utf16 != NULL) {
814 ImportModuleHandle = LoadLibraryW(file_utf16);
818 if (ImportModuleHandle == NULL)
821 ImportThunkData = (IMAGE_THUNK_DATA*)((DWORD_PTR)DosHeader + ImportDesc->OriginalFirstThunk);
822 while (ImportThunkData->u1.Ordinal != 0)
824 if (IMAGE_SNAP_BY_ORDINAL(ImportThunkData->u1.Ordinal))
825 ProcAddress = (DWORD_PTR)GetProcAddress(ImportModuleHandle, (LPCSTR)IMAGE_ORDINAL(ImportThunkData->u1.Ordinal));
828 IMAGE_IMPORT_BY_NAME* ImportByName = (IMAGE_IMPORT_BY_NAME*)((DWORD_PTR)DosHeader + ImportThunkData->u1.AddressOfData);
829 ProcAddress = (DWORD_PTR)GetProcAddress(ImportModuleHandle, ImportByName->Name);
831 if (ProcAddress == 0)
833 Address = (DWORD_PTR*)((DWORD_PTR)ImportThunkData - ImportDesc->OriginalFirstThunk + ImportDesc->FirstThunk);
834 if (!VirtualProtect(Address, sizeof(DWORD_PTR), PAGE_READWRITE, &OldProtect))
836 *Address = ProcAddress;
837 if (!VirtualProtect(Address, sizeof(DWORD_PTR), OldProtect, &OldProtect))
850 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
852 mono_coree_set_act_ctx (const char* file_name)
854 typedef HANDLE (WINAPI* CREATEACTCTXW_PROC) (PCACTCTXW pActCtx);
855 typedef BOOL (WINAPI* ACTIVATEACTCTX_PROC) (HANDLE hActCtx, ULONG_PTR* lpCookie);
857 HMODULE kernel32_handle;
858 CREATEACTCTXW_PROC CreateActCtx_proc;
859 ACTIVATEACTCTX_PROC ActivateActCtx_proc;
861 gunichar2* full_path_utf16;
863 gunichar2* dir_name_utf16;
865 gunichar2* base_name_utf16;
870 kernel32_handle = GetModuleHandle (L"kernel32.dll");
871 if (!kernel32_handle)
873 CreateActCtx_proc = (CREATEACTCTXW_PROC) GetProcAddress (kernel32_handle, "CreateActCtxW");
874 if (!CreateActCtx_proc)
876 ActivateActCtx_proc = (ACTIVATEACTCTX_PROC) GetProcAddress (kernel32_handle, "ActivateActCtx");
877 if (!ActivateActCtx_proc)
880 full_path = mono_path_canonicalize (file_name);
881 full_path_utf16 = g_utf8_to_utf16 (full_path, -1, NULL, NULL, NULL);
882 dir_name = g_path_get_dirname (full_path);
883 dir_name_utf16 = g_utf8_to_utf16 (dir_name, -1, NULL, NULL, NULL);
884 base_name = g_path_get_basename (full_path);
885 base_name_utf16 = g_utf8_to_utf16 (base_name, -1, NULL, NULL, NULL);
890 memset (&act_ctx, 0, sizeof (ACTCTX));
891 act_ctx.cbSize = sizeof (ACTCTX);
892 act_ctx.dwFlags = ACTCTX_FLAG_SET_PROCESS_DEFAULT | ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID | ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_APPLICATION_NAME_VALID;
893 act_ctx.lpSource = full_path_utf16;
894 act_ctx.lpAssemblyDirectory = dir_name_utf16;
895 act_ctx.lpResourceName = MAKEINTRESOURCE (CREATEPROCESS_MANIFEST_RESOURCE_ID);
896 act_ctx.lpApplicationName = base_name_utf16;
898 handle = CreateActCtx_proc (&act_ctx);
899 if (handle == INVALID_HANDLE_VALUE && GetLastError () == ERROR_SXS_PROCESS_DEFAULT_ALREADY_SET) {
900 act_ctx.dwFlags &= ~ACTCTX_FLAG_SET_PROCESS_DEFAULT;
901 handle = CreateActCtx_proc (&act_ctx);
904 g_free (base_name_utf16);
905 g_free (dir_name_utf16);
906 g_free (full_path_utf16);
908 if (handle != INVALID_HANDLE_VALUE)
909 ActivateActCtx_proc (handle, &cookie);
911 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
914 mono_load_coree (const char* exe_file_name)
916 HMODULE module_handle;
917 gunichar2* file_name;
921 if (coree_module_handle)
924 if (!init_from_coree && exe_file_name)
925 mono_coree_set_act_ctx (exe_file_name);
927 /* ntdll.dll loads mscoree.dll from the system32 directory. */
928 required_size = GetSystemDirectory (NULL, 0);
929 file_name = g_new (gunichar2, required_size + 12);
930 size = GetSystemDirectory (file_name, required_size);
931 g_assert (size < required_size);
932 if (file_name [size - 1] != L'\\')
933 file_name [size++] = L'\\';
934 memcpy (&file_name [size], L"mscoree.dll", 12 * sizeof (gunichar2));
936 module_handle = LoadLibrary (file_name);
939 if (module_handle && !SUCCEEDED (MonoFixupCorEE (module_handle))) {
940 FreeLibrary (module_handle);
941 module_handle = NULL;
944 coree_module_handle = module_handle;
948 mono_fixup_exe_image (MonoImage* image)
950 if (!init_from_coree && image && image->is_module_handle)
951 MonoFixupExe ((HMODULE) image->raw_data);
954 #endif /* HOST_WIN32 */