3 * mscoree.dll functions
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.
18 #include <mono/utils/mono-path.h>
19 #include "utils/w32api.h"
21 #include "metadata-internals.h"
23 #include "image-internals.h"
24 #include "assembly-internals.h"
25 #include "domain-internals.h"
26 #include "appdomain.h"
28 #include "object-internals.h"
31 #include "environment.h"
33 #include "coree-internals.h"
35 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
39 HMODULE coree_module_handle
= NULL
;
41 static gboolean init_from_coree
= FALSE
;
44 mono_get_module_file_name (HMODULE module_handle
)
47 gchar
* file_name_utf8
;
52 file_name
= g_new (gunichar2
, buffer_size
);
55 size
= GetModuleFileName (module_handle
, file_name
, buffer_size
);
61 g_assert (size
<= buffer_size
);
62 if (size
!= buffer_size
)
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
);
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
;
83 MonoAssemblyLoadContext
*alc
= mono_domain_default_alc (mono_get_root_domain ());
87 case DLL_PROCESS_ATTACH
:
88 DisableThreadLibraryCalls (hInst
);
90 file_name
= mono_get_module_file_name (hInst
);
92 if (mono_get_root_domain ()) {
93 image
= mono_image_open_from_module_handle (alc
, hInst
, mono_path_resolve_symlinks (file_name
), TRUE
, NULL
);
95 init_from_coree
= TRUE
;
96 mono_runtime_load (file_name
, NULL
);
97 error
= (gchar
*) mono_check_corlib_version ();
101 mono_runtime_quit_internal ();
105 image
= mono_image_open (file_name
, NULL
);
107 image
->storage
->has_entry_point
= TRUE
;
108 mono_close_exe_image ();
109 /* Decrement reference count to zero. (Image will not be closed.) */
110 mono_image_close (image
);
120 * FIXME: Find a better way to call mono_image_fixup_vtable. Only
121 * loader trampolines should be used and assembly loading should
122 * probably be delayed until the first call to an exported function.
124 if (image
->tables
[MONO_TABLE_ASSEMBLY
].rows
&& image
->image_info
->cli_cli_header
.ch_vtable_fixups
.rva
) {
125 MonoAssemblyOpenRequest req
;
126 mono_assembly_request_prepare_open (&req
, MONO_ASMCTX_DEFAULT
, alc
);
127 assembly
= mono_assembly_request_open (file_name
, &req
, NULL
);
132 case DLL_PROCESS_DETACH
:
133 if (lpReserved
!= NULL
)
134 /* The process is terminating. */
136 file_name
= mono_get_module_file_name (hInst
);
137 image
= mono_image_loaded_internal (alc
, file_name
, FALSE
);
139 mono_image_close (image
);
147 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
149 /* Called by ntdll.dll reagardless of entry point after _CorValidateImage. */
150 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
151 __int32 STDMETHODCALLTYPE
_CorExeMain(void)
155 MonoAssembly
* assembly
;
160 gchar
* corlib_version_error
;
166 file_name
= mono_get_module_file_name (NULL
);
167 init_from_coree
= TRUE
;
168 domain
= mono_runtime_load (file_name
, NULL
);
170 corlib_version_error
= (gchar
*) mono_check_corlib_version ();
171 if (corlib_version_error
) {
172 g_free (corlib_version_error
);
174 MessageBox (NULL
, L
"Corlib not in sync with this runtime.", NULL
, MB_ICONERROR
);
175 mono_runtime_quit_internal ();
179 MonoAssemblyOpenRequest req
;
180 mono_assembly_request_prepare_open (&req
, MONO_ASMCTX_DEFAULT
, mono_domain_default_alc (mono_get_root_domain ()));
181 assembly
= mono_assembly_request_open (file_name
, &req
, NULL
);
182 mono_close_exe_image ();
185 MessageBox (NULL
, L
"Cannot open assembly.", NULL
, MB_ICONERROR
);
186 mono_runtime_quit_internal ();
190 image
= assembly
->image
;
191 entry
= mono_image_get_entry_point (image
);
194 MessageBox (NULL
, L
"Assembly doesn't have an entry point.", NULL
, MB_ICONERROR
);
195 mono_runtime_quit_internal ();
199 method
= mono_get_method_checked (image
, entry
, NULL
, NULL
, error
);
200 if (method
== NULL
) {
202 mono_error_cleanup (error
); /* FIXME don't swallow the error */
203 MessageBox (NULL
, L
"The entry point method could not be loaded.", NULL
, MB_ICONERROR
);
204 mono_runtime_quit_internal ();
208 argvw
= CommandLineToArgvW (GetCommandLine (), &argc
);
209 argv
= g_new0 (gchar
*, argc
);
210 argv
[0] = file_name
;
211 for (i
= 1; i
< argc
; ++i
)
212 argv
[i
] = g_utf16_to_utf8 (argvw
[i
], -1, NULL
, NULL
, NULL
);
215 mono_runtime_run_main_checked (method
, argc
, argv
, error
);
216 mono_error_raise_exception_deprecated (error
); /* OK, triggers unhandled exn handler */
217 mono_thread_manage_internal ();
219 mono_runtime_quit_internal ();
221 /* return does not terminate the process. */
222 ExitProcess (mono_environment_exitcode_get ());
224 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
226 /* Called by msvcrt.dll when shutting down. */
227 void STDMETHODCALLTYPE
CorExitProcess(int exitCode
)
229 /* FIXME: This is not currently supported by the runtime. */
231 if (mono_get_root_domain () && !mono_runtime_is_shutting_down ()) {
232 mono_runtime_set_shutting_down ();
233 mono_thread_suspend_all_other_threads ();
234 mono_runtime_quit_internal ();
237 ExitProcess (exitCode
);
240 /* Called by ntdll.dll before _CorDllMain and _CorExeMain. */
241 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
242 STDAPI
_CorValidateImage(PVOID
*ImageBase
, LPCWSTR FileName
)
244 IMAGE_DOS_HEADER
* DosHeader
;
245 IMAGE_NT_HEADERS32
* NtHeaders32
;
246 IMAGE_DATA_DIRECTORY
* CliHeaderDir
;
248 IMAGE_NT_HEADERS64
* NtHeaders64
;
249 MonoCLIHeader
* CliHeader
;
255 DosHeader
= (IMAGE_DOS_HEADER
*)*ImageBase
;
256 if (DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
257 return STATUS_INVALID_IMAGE_FORMAT
;
259 NtHeaders32
= (IMAGE_NT_HEADERS32
*)((DWORD_PTR
)DosHeader
+ DosHeader
->e_lfanew
);
260 if (NtHeaders32
->Signature
!= IMAGE_NT_SIGNATURE
)
261 return STATUS_INVALID_IMAGE_FORMAT
;
264 NtHeaders64
= (IMAGE_NT_HEADERS64
*)NtHeaders32
;
265 if (NtHeaders64
->OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR64_MAGIC
)
267 if (NtHeaders64
->OptionalHeader
.NumberOfRvaAndSizes
<= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
)
268 return STATUS_INVALID_IMAGE_FORMAT
;
270 CliHeaderDir
= &NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
];
271 if (!CliHeaderDir
->VirtualAddress
)
272 return STATUS_INVALID_IMAGE_FORMAT
;
274 CliHeader
= (MonoCLIHeader
*)((DWORD_PTR
)DosHeader
+ CliHeaderDir
->VirtualAddress
);
275 if (CliHeader
->ch_flags
& CLI_FLAGS_32BITREQUIRED
)
276 return STATUS_INVALID_IMAGE_FORMAT
;
278 if (CliHeader
->ch_flags
& CLI_FLAGS_ILONLY
)
280 /* Avoid calling _CorDllMain because imports are not resolved for IL only images. */
281 if (NtHeaders64
->OptionalHeader
.AddressOfEntryPoint
!= 0)
283 Address
= &NtHeaders64
->OptionalHeader
.AddressOfEntryPoint
;
284 if (!VirtualProtect(Address
, sizeof(DWORD
), PAGE_READWRITE
, &OldProtect
))
287 if (!VirtualProtect(Address
, sizeof(DWORD
), OldProtect
, &OldProtect
))
292 return STATUS_SUCCESS
;
295 if (NtHeaders32
->OptionalHeader
.Magic
!= IMAGE_NT_OPTIONAL_HDR32_MAGIC
)
296 return STATUS_INVALID_IMAGE_FORMAT
;
298 if (NtHeaders32
->OptionalHeader
.NumberOfRvaAndSizes
<= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
)
299 return STATUS_INVALID_IMAGE_FORMAT
;
301 CliHeaderDir
= &NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
];
302 if (!CliHeaderDir
->VirtualAddress
)
303 return STATUS_INVALID_IMAGE_FORMAT
;
305 CliHeader
= (MonoCLIHeader
*)((DWORD_PTR
)DosHeader
+ CliHeaderDir
->VirtualAddress
);
306 if (!(CliHeader
->ch_flags
& CLI_FLAGS_ILONLY
) || (CliHeader
->ch_flags
& CLI_FLAGS_32BITREQUIRED
))
307 return STATUS_INVALID_IMAGE_FORMAT
;
309 /* Fixup IMAGE_NT_HEADERS32 to IMAGE_NT_HEADERS64. */
310 SizeOfHeaders
= NtHeaders32
->OptionalHeader
.SizeOfHeaders
;
311 if (SizeOfHeaders
< DosHeader
->e_lfanew
+ sizeof(IMAGE_NT_HEADERS64
) + (sizeof(IMAGE_SECTION_HEADER
) * NtHeaders32
->FileHeader
.NumberOfSections
))
312 return STATUS_INVALID_IMAGE_FORMAT
;
314 if (!VirtualProtect(DosHeader
, SizeOfHeaders
, PAGE_READWRITE
, &OldProtect
))
317 memmove(NtHeaders64
+ 1, IMAGE_FIRST_SECTION(NtHeaders32
), sizeof(IMAGE_SECTION_HEADER
) * NtHeaders32
->FileHeader
.NumberOfSections
);
319 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_NUMBEROF_DIRECTORY_ENTRIES
- 1].Size
= 0;
320 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_NUMBEROF_DIRECTORY_ENTRIES
- 1].VirtualAddress
= 0;
321 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
= NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
;
322 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
= NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
;
323 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
].Size
= 0;
324 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
].VirtualAddress
= 0;
325 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IAT
].Size
= 0;
326 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IAT
].VirtualAddress
= 0;
327 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
].Size
= 0;
328 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
].VirtualAddress
= 0;
329 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
].Size
= 0;
330 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
].VirtualAddress
= 0;
331 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_TLS
].Size
= 0;
332 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_TLS
].VirtualAddress
= 0;
333 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_GLOBALPTR
].Size
= 0;
334 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_GLOBALPTR
].VirtualAddress
= 0;
335 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_ARCHITECTURE
].Size
= 0;
336 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_ARCHITECTURE
].VirtualAddress
= 0;
337 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
338 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
339 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
340 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
341 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
= NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
;
342 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_SECURITY
].VirtualAddress
= NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_SECURITY
].VirtualAddress
;
343 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
344 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
345 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
= NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
;
346 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
= NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
347 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].Size
= 0;
348 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
= 0;
349 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
= 0;
350 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
= 0;
352 NtHeaders64
->OptionalHeader
.NumberOfRvaAndSizes
= IMAGE_NUMBEROF_DIRECTORY_ENTRIES
;
353 NtHeaders64
->OptionalHeader
.LoaderFlags
= NtHeaders32
->OptionalHeader
.LoaderFlags
;
354 NtHeaders64
->OptionalHeader
.SizeOfHeapCommit
= (ULONGLONG
)NtHeaders32
->OptionalHeader
.SizeOfHeapCommit
;
355 NtHeaders64
->OptionalHeader
.SizeOfHeapReserve
= (ULONGLONG
)NtHeaders32
->OptionalHeader
.SizeOfHeapReserve
;
356 NtHeaders64
->OptionalHeader
.SizeOfStackCommit
= (ULONGLONG
)NtHeaders32
->OptionalHeader
.SizeOfStackCommit
;
357 NtHeaders64
->OptionalHeader
.SizeOfStackReserve
= (ULONGLONG
)NtHeaders32
->OptionalHeader
.SizeOfStackReserve
;
358 NtHeaders64
->OptionalHeader
.DllCharacteristics
= NtHeaders32
->OptionalHeader
.DllCharacteristics
;
359 NtHeaders64
->OptionalHeader
.Subsystem
= NtHeaders32
->OptionalHeader
.Subsystem
;
360 NtHeaders64
->OptionalHeader
.CheckSum
= NtHeaders32
->OptionalHeader
.CheckSum
;
361 NtHeaders64
->OptionalHeader
.SizeOfHeaders
= NtHeaders32
->OptionalHeader
.SizeOfHeaders
;
362 NtHeaders64
->OptionalHeader
.SizeOfImage
= NtHeaders32
->OptionalHeader
.SizeOfImage
;
363 NtHeaders64
->OptionalHeader
.Win32VersionValue
= NtHeaders32
->OptionalHeader
.Win32VersionValue
;
364 NtHeaders64
->OptionalHeader
.MinorSubsystemVersion
= NtHeaders32
->OptionalHeader
.MinorSubsystemVersion
;
365 NtHeaders64
->OptionalHeader
.MajorSubsystemVersion
= NtHeaders32
->OptionalHeader
.MajorSubsystemVersion
;
366 NtHeaders64
->OptionalHeader
.MinorImageVersion
= NtHeaders32
->OptionalHeader
.MinorImageVersion
;
367 NtHeaders64
->OptionalHeader
.MajorImageVersion
= NtHeaders32
->OptionalHeader
.MajorImageVersion
;
368 NtHeaders64
->OptionalHeader
.MinorOperatingSystemVersion
= NtHeaders32
->OptionalHeader
.MinorOperatingSystemVersion
;
369 NtHeaders64
->OptionalHeader
.MajorOperatingSystemVersion
= NtHeaders32
->OptionalHeader
.MajorOperatingSystemVersion
;
370 NtHeaders64
->OptionalHeader
.FileAlignment
= NtHeaders32
->OptionalHeader
.FileAlignment
;
371 NtHeaders64
->OptionalHeader
.SectionAlignment
= NtHeaders32
->OptionalHeader
.SectionAlignment
;
372 NtHeaders64
->OptionalHeader
.ImageBase
= (ULONGLONG
)NtHeaders32
->OptionalHeader
.ImageBase
;
373 /* BaseOfCode is at the same offset. */
374 NtHeaders64
->OptionalHeader
.AddressOfEntryPoint
= 0;
375 NtHeaders64
->OptionalHeader
.Magic
= IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
376 NtHeaders64
->FileHeader
.SizeOfOptionalHeader
= sizeof(IMAGE_OPTIONAL_HEADER64
);
378 if (!VirtualProtect(DosHeader
, SizeOfHeaders
, OldProtect
, &OldProtect
))
381 if (NtHeaders32
->OptionalHeader
.Magic
!= IMAGE_NT_OPTIONAL_HDR32_MAGIC
)
382 return STATUS_INVALID_IMAGE_FORMAT
;
384 if (NtHeaders32
->OptionalHeader
.NumberOfRvaAndSizes
<= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
)
385 return STATUS_INVALID_IMAGE_FORMAT
;
387 CliHeaderDir
= &NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
];
388 if (!CliHeaderDir
->VirtualAddress
)
389 return STATUS_INVALID_IMAGE_FORMAT
;
391 Address
= &NtHeaders32
->OptionalHeader
.AddressOfEntryPoint
;
392 if (!VirtualProtect(Address
, sizeof(DWORD
), PAGE_READWRITE
, &OldProtect
))
394 if (NtHeaders32
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
)
395 *Address
= (DWORD
)((DWORD_PTR
)&_CorDllMain
- (DWORD_PTR
)DosHeader
);
397 *Address
= (DWORD
)((DWORD_PTR
)&_CorExeMain
- (DWORD_PTR
)DosHeader
);
398 if (!VirtualProtect(Address
, sizeof(DWORD
), OldProtect
, &OldProtect
))
402 return STATUS_SUCCESS
;
404 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
406 /* Called by ntdll.dll. */
407 STDAPI_(VOID
) _CorImageUnloading(PVOID ImageBase
)
412 STDAPI
CorBindToRuntimeEx(LPCWSTR pwszVersion
, LPCWSTR pwszBuildFlavor
, DWORD startupFlags
, REFCLSID rclsid
, REFIID riid
, LPVOID FAR
*ppv
)
421 STDAPI
CorBindToRuntime(LPCWSTR pwszVersion
, LPCWSTR pwszBuildFlavor
, REFCLSID rclsid
, REFIID riid
, LPVOID FAR
*ppv
)
423 return CorBindToRuntimeEx (pwszVersion
, pwszBuildFlavor
, 0, rclsid
, riid
, ppv
);
426 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
427 HMODULE WINAPI
MonoLoadImage(LPCWSTR FileName
)
432 IMAGE_DOS_HEADER
* DosHeader
;
433 IMAGE_NT_HEADERS32
* NtHeaders32
;
435 IMAGE_NT_HEADERS64
* NtHeaders64
;
437 HMODULE ModuleHandle
;
439 FileHandle
= CreateFile(FileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
440 if (FileHandle
== INVALID_HANDLE_VALUE
)
443 FileSize
= GetFileSize(FileHandle
, NULL
);
444 if (FileSize
== INVALID_FILE_SIZE
)
447 MapHandle
= CreateFileMapping(FileHandle
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
448 if (MapHandle
== NULL
)
451 DosHeader
= (IMAGE_DOS_HEADER
*)MapViewOfFile(MapHandle
, FILE_MAP_READ
, 0, 0, 0);
452 if (DosHeader
== NULL
)
455 if (FileSize
< sizeof(IMAGE_DOS_HEADER
) || DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
|| FileSize
< DosHeader
->e_lfanew
+ sizeof(IMAGE_NT_HEADERS32
))
456 goto InvalidImageFormat
;
458 NtHeaders32
= (IMAGE_NT_HEADERS32
*)((DWORD_PTR
)DosHeader
+ DosHeader
->e_lfanew
);
459 if (NtHeaders32
->Signature
!= IMAGE_NT_SIGNATURE
)
460 goto InvalidImageFormat
;
463 NtHeaders64
= (IMAGE_NT_HEADERS64
*)NtHeaders32
;
464 if (NtHeaders64
->OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR64_MAGIC
)
466 if (FileSize
< DosHeader
->e_lfanew
+ sizeof(IMAGE_NT_HEADERS64
) ||
467 NtHeaders64
->OptionalHeader
.NumberOfRvaAndSizes
<= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
||
468 !NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
)
469 goto InvalidImageFormat
;
475 if (NtHeaders32
->OptionalHeader
.Magic
!= IMAGE_NT_OPTIONAL_HDR32_MAGIC
||
476 NtHeaders32
->OptionalHeader
.NumberOfRvaAndSizes
<= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
||
477 !NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
)
480 SetLastError(STATUS_INVALID_IMAGE_FORMAT
);
487 UnmapViewOfFile(DosHeader
);
488 CloseHandle(MapHandle
);
490 ModuleHandle
= LoadLibrary(FileName
);
492 CloseHandle(FileHandle
);
496 UnmapViewOfFile(DosHeader
);
498 CloseHandle(MapHandle
);
500 CloseHandle(FileHandle
);
503 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
505 typedef struct _EXPORT_FIXUP
512 BYTE Bytes
[sizeof(PVOID
)];
514 PLABEL_DESCRIPTOR
* PLabel
;
519 /* Has to be binary ordered. */
520 static const EXPORT_FIXUP ExportFixups
[] = {
521 {"CorBindToRuntime", {(PVOID
)&CorBindToRuntime
}},
522 {"CorBindToRuntimeEx", {(PVOID
)&CorBindToRuntimeEx
}},
523 {"CorExitProcess", {(PVOID
)&CorExitProcess
}},
524 {"_CorDllMain", {(PVOID
)&_CorDllMain
}},
525 {"_CorExeMain", {(PVOID
)&_CorExeMain
}},
526 {"_CorImageUnloading", {(PVOID
)&_CorImageUnloading
}},
527 {"_CorValidateImage", {(PVOID
)&_CorValidateImage
}},
531 #define EXPORT_FIXUP_COUNT (sizeof(ExportFixups) / sizeof(EXPORT_FIXUP) - 1)
533 static HMODULE ExportFixupModuleHandle
= NULL
;
534 static DWORD ExportFixupRvas
[EXPORT_FIXUP_COUNT
];
536 /* Fixup exported functions of mscoree.dll to our implementations. */
537 STDAPI
MonoFixupCorEE(HMODULE ModuleHandle
)
539 IMAGE_DOS_HEADER
* DosHeader
;
540 IMAGE_NT_HEADERS
* NtHeaders
;
541 IMAGE_DATA_DIRECTORY
* ExportDataDir
;
542 IMAGE_EXPORT_DIRECTORY
* ExportDir
;
546 EXPORT_FIXUP
* ExportFixup
;
547 DWORD
* ExportFixupRva
;
554 MEMORY_BASIC_INFORMATION MemoryInfo
;
559 PLABEL_DESCRIPTOR
* PLabel
;
561 #define ELEMENT_SIZE sizeof(PLABEL_DESCRIPTOR)
562 #define REGION_WRITE_PROTECT PAGE_READWRITE
563 #define REGION_PROTECT PAGE_READ
567 #define ELEMENT_SIZE 13
568 #define REGION_WRITE_PROTECT PAGE_EXECUTE_READWRITE
569 #define REGION_PROTECT PAGE_EXECUTE_READ
573 if (ExportFixupModuleHandle
!= NULL
)
574 return ModuleHandle
== ExportFixupModuleHandle
? S_OK
: E_FAIL
;
576 DosHeader
= (IMAGE_DOS_HEADER
*)ModuleHandle
;
577 if (DosHeader
== NULL
)
580 if (DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
583 NtHeaders
= (IMAGE_NT_HEADERS
*)((DWORD_PTR
)DosHeader
+ DosHeader
->e_lfanew
);
584 if (NtHeaders
->Signature
!= IMAGE_NT_SIGNATURE
)
587 if (NtHeaders
->OptionalHeader
.Magic
!= IMAGE_NT_OPTIONAL_HDR_MAGIC
)
590 if (NtHeaders
->OptionalHeader
.NumberOfRvaAndSizes
<= IMAGE_DIRECTORY_ENTRY_EXPORT
)
593 ExportDataDir
= &NtHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
];
594 if (!ExportDataDir
->VirtualAddress
)
598 /* Allocate memory after base address because RVAs are 32-bit unsigned integers. */
599 RegionBase
= DosHeader
;
600 MaxRegionBase
= (PVOID
)((DWORD_PTR
)RegionBase
+ (DWORD_PTR
)(0x100000000L
- (ELEMENT_SIZE
* (EXPORT_FIXUP_COUNT
- 1))));
603 if (!VirtualQuery(RegionBase
, &MemoryInfo
, sizeof(MEMORY_BASIC_INFORMATION
)))
605 if (MemoryInfo
.State
== MEM_FREE
&& MemoryInfo
.RegionSize
>= ELEMENT_SIZE
* EXPORT_FIXUP_COUNT
)
607 Region
= VirtualAlloc(RegionBase
, ELEMENT_SIZE
* EXPORT_FIXUP_COUNT
, MEM_COMMIT
| MEM_RESERVE
, REGION_WRITE_PROTECT
);
611 RegionBase
= (PVOID
)((DWORD_PTR
)MemoryInfo
.BaseAddress
+ (DWORD_PTR
)MemoryInfo
.RegionSize
);
612 if (RegionBase
> MaxRegionBase
)
613 return E_OUTOFMEMORY
;
617 PLabel
= (PLABEL_DESCRIPTOR
*)Region
;
619 Trampoline
= (BYTE
*)Region
;
623 ExportDir
= (IMAGE_EXPORT_DIRECTORY
*)((DWORD_PTR
)DosHeader
+ ExportDataDir
->VirtualAddress
);
624 Functions
= (DWORD
*)((DWORD_PTR
)DosHeader
+ ExportDir
->AddressOfFunctions
);
625 Names
= (DWORD
*)((DWORD_PTR
)DosHeader
+ ExportDir
->AddressOfNames
);
626 NameOrdinals
= (WORD
*)((DWORD_PTR
)DosHeader
+ ExportDir
->AddressOfNameOrdinals
);
627 ExportFixup
= (EXPORT_FIXUP
*)&ExportFixups
;
628 ExportFixupRva
= (DWORD
*)&ExportFixupRvas
;
630 for (i
= 0; i
< ExportDir
->NumberOfNames
; i
++)
632 cmp
= strcmp((LPCSTR
)((DWORD_PTR
)DosHeader
+ Names
[i
]), ExportFixup
->Name
);
640 ProcRva
= (DWORD
)((DWORD_PTR
)PLabel
- (DWORD_PTR
)DosHeader
);
641 *(PLabel
)++ = *ExportFixup
->ProcAddress
.PLabel
;
642 #elif defined(_M_AMD64)
643 ProcRva
= (DWORD
)((DWORD_PTR
)Trampoline
- (DWORD_PTR
)DosHeader
);
644 /* mov r11, ExportFixup->ProcAddress */
645 *(Trampoline
)++ = 0x49;
646 *(Trampoline
)++ = 0xBB;
647 *(Trampoline
)++ = ExportFixup
->ProcAddress
.Bytes
[0];
648 *(Trampoline
)++ = ExportFixup
->ProcAddress
.Bytes
[1];
649 *(Trampoline
)++ = ExportFixup
->ProcAddress
.Bytes
[2];
650 *(Trampoline
)++ = ExportFixup
->ProcAddress
.Bytes
[3];
651 *(Trampoline
)++ = ExportFixup
->ProcAddress
.Bytes
[4];
652 *(Trampoline
)++ = ExportFixup
->ProcAddress
.Bytes
[5];
653 *(Trampoline
)++ = ExportFixup
->ProcAddress
.Bytes
[6];
654 *(Trampoline
)++ = ExportFixup
->ProcAddress
.Bytes
[7];
656 *(Trampoline
)++ = 0x41;
657 *(Trampoline
)++ = 0xFF;
658 *(Trampoline
)++ = 0xE3;
660 #error Unsupported architecture.
663 ProcRva
= (DWORD
)(ExportFixup
->ProcAddress
.DWordPtr
- (DWORD_PTR
)DosHeader
);
665 Address
= &Functions
[NameOrdinals
[i
]];
666 if (!VirtualProtect(Address
, sizeof(DWORD
), PAGE_READWRITE
, &OldProtect
))
668 *ExportFixupRva
= *Address
;
670 if (!VirtualProtect(Address
, sizeof(DWORD
), OldProtect
, &OldProtect
))
673 if (ExportFixup
->Name
== NULL
) {
675 if (!VirtualProtect(Region
, ELEMENT_SIZE
* EXPORT_FIXUP_COUNT
, REGION_PROTECT
, &OldProtect
))
679 ExportFixupModuleHandle
= ModuleHandle
;
688 /* Executable images are only mapped by the OS loader. We need to do fixups for native code support. */
689 STDAPI
MonoFixupExe(HMODULE ModuleHandle
)
691 IMAGE_DOS_HEADER
* DosHeader
;
692 IMAGE_NT_HEADERS
* NtHeaders
;
697 DosHeader
= (IMAGE_DOS_HEADER
*)ModuleHandle
;
698 if (DosHeader
== NULL
)
701 if (DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
704 NtHeaders
= (IMAGE_NT_HEADERS
*)((DWORD_PTR
)DosHeader
+ DosHeader
->e_lfanew
);
705 if (NtHeaders
->Signature
!= IMAGE_NT_SIGNATURE
)
708 if (NtHeaders
->OptionalHeader
.Magic
!= IMAGE_NT_OPTIONAL_HDR_MAGIC
)
711 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
)
714 if (NtHeaders
->OptionalHeader
.NumberOfRvaAndSizes
> IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
)
716 IMAGE_DATA_DIRECTORY
* CliHeaderDir
;
717 MonoCLIHeader
* CliHeader
;
719 CliHeaderDir
= &NtHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
];
720 if (CliHeaderDir
->VirtualAddress
)
722 CliHeader
= (MonoCLIHeader
*)((DWORD_PTR
)DosHeader
+ CliHeaderDir
->VirtualAddress
);
723 if (CliHeader
->ch_flags
& CLI_FLAGS_ILONLY
)
728 BaseDiff
= (DWORD_PTR
)DosHeader
- NtHeaders
->OptionalHeader
.ImageBase
;
731 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
734 Address
= &NtHeaders
->OptionalHeader
.ImageBase
;
735 if (!VirtualProtect(Address
, sizeof(DWORD_PTR
), PAGE_READWRITE
, &OldProtect
))
737 *Address
= (DWORD_PTR
)DosHeader
;
738 if (!VirtualProtect(Address
, sizeof(DWORD_PTR
), OldProtect
, &OldProtect
))
741 if (NtHeaders
->OptionalHeader
.NumberOfRvaAndSizes
> IMAGE_DIRECTORY_ENTRY_BASERELOC
)
743 IMAGE_DATA_DIRECTORY
* BaseRelocDir
;
744 IMAGE_BASE_RELOCATION
* BaseReloc
;
747 ULONG RelocBlockSize
;
749 DWORD_PTR UNALIGNED
*RelocFixup
;
751 BaseRelocDir
= &NtHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
752 if (BaseRelocDir
->VirtualAddress
)
754 BaseReloc
= (IMAGE_BASE_RELOCATION
*)((DWORD_PTR
)DosHeader
+ BaseRelocDir
->VirtualAddress
);
755 BaseRelocSize
= BaseRelocDir
->Size
;
757 while (BaseRelocSize
)
759 RelocBlockSize
= BaseReloc
->SizeOfBlock
;
761 if (!RelocBlockSize
|| BaseRelocSize
< RelocBlockSize
)
764 BaseRelocSize
-= RelocBlockSize
;
765 RelocBlock
= (USHORT
*)((DWORD_PTR
)BaseReloc
+ sizeof(IMAGE_BASE_RELOCATION
));
766 RelocBlockSize
-= sizeof(IMAGE_BASE_RELOCATION
);
767 RelocBlockSize
/= sizeof(USHORT
);
769 while (RelocBlockSize
-- != 0)
771 RelocOffset
= *RelocBlock
& (USHORT
)0x0fff;
772 RelocFixup
= (DWORD_PTR
*)((DWORD_PTR
)DosHeader
+ BaseReloc
->VirtualAddress
+ RelocOffset
);
774 switch (*RelocBlock
>> 12)
776 case IMAGE_REL_BASED_ABSOLUTE
:
780 case IMAGE_REL_BASED_DIR64
:
782 case IMAGE_REL_BASED_HIGHLOW
:
784 if (!VirtualProtect(RelocFixup
, sizeof(DWORD_PTR
), PAGE_EXECUTE_READWRITE
, &OldProtect
))
786 *RelocFixup
+= BaseDiff
;
787 if (!VirtualProtect(RelocFixup
, sizeof(DWORD_PTR
), OldProtect
, &OldProtect
))
797 BaseReloc
= (IMAGE_BASE_RELOCATION
*)RelocBlock
;
803 if (NtHeaders
->OptionalHeader
.NumberOfRvaAndSizes
> IMAGE_DIRECTORY_ENTRY_IMPORT
)
805 IMAGE_DATA_DIRECTORY
* ImportDir
;
806 IMAGE_IMPORT_DESCRIPTOR
* ImportDesc
;
807 HMODULE ImportModuleHandle
;
808 IMAGE_THUNK_DATA
* ImportThunkData
;
809 DWORD_PTR ProcAddress
;
811 ImportDir
= &NtHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
];
812 if (ImportDir
->VirtualAddress
!= 0)
814 ImportDesc
= (IMAGE_IMPORT_DESCRIPTOR
*)((DWORD_PTR
)DosHeader
+ ImportDir
->VirtualAddress
);
815 while (ImportDesc
->Name
&& ImportDesc
->OriginalFirstThunk
)
817 gchar
*file_utf8
= (gchar
*)((DWORD_PTR
)DosHeader
+ ImportDesc
->Name
);
819 gunichar2
*file_utf16
= g_utf8_to_utf16 (file_utf8
, (glong
)strlen (file_utf8
), NULL
, NULL
, NULL
);
820 ImportModuleHandle
= NULL
;
821 if (file_utf16
!= NULL
) {
822 ImportModuleHandle
= LoadLibraryW(file_utf16
);
826 if (ImportModuleHandle
== NULL
)
829 ImportThunkData
= (IMAGE_THUNK_DATA
*)((DWORD_PTR
)DosHeader
+ ImportDesc
->OriginalFirstThunk
);
830 while (ImportThunkData
->u1
.Ordinal
!= 0)
832 if (IMAGE_SNAP_BY_ORDINAL(ImportThunkData
->u1
.Ordinal
))
833 ProcAddress
= (DWORD_PTR
)GetProcAddress(ImportModuleHandle
, (LPCSTR
)IMAGE_ORDINAL(ImportThunkData
->u1
.Ordinal
));
836 IMAGE_IMPORT_BY_NAME
* ImportByName
= (IMAGE_IMPORT_BY_NAME
*)((DWORD_PTR
)DosHeader
+ ImportThunkData
->u1
.AddressOfData
);
837 ProcAddress
= (DWORD_PTR
)GetProcAddress(ImportModuleHandle
, (PCSTR
)ImportByName
->Name
);
839 if (ProcAddress
== 0)
841 Address
= (DWORD_PTR
*)((DWORD_PTR
)ImportThunkData
- ImportDesc
->OriginalFirstThunk
+ ImportDesc
->FirstThunk
);
842 if (!VirtualProtect(Address
, sizeof(DWORD_PTR
), PAGE_READWRITE
, &OldProtect
))
844 *Address
= ProcAddress
;
845 if (!VirtualProtect(Address
, sizeof(DWORD_PTR
), OldProtect
, &OldProtect
))
858 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
860 mono_coree_set_act_ctx (const char* file_name
)
862 typedef HANDLE (WINAPI
* CREATEACTCTXW_PROC
) (PCACTCTXW pActCtx
);
863 typedef BOOL (WINAPI
* ACTIVATEACTCTX_PROC
) (HANDLE hActCtx
, ULONG_PTR
* lpCookie
);
865 HMODULE kernel32_handle
;
866 CREATEACTCTXW_PROC CreateActCtx_proc
;
867 ACTIVATEACTCTX_PROC ActivateActCtx_proc
;
869 gunichar2
* full_path_utf16
;
871 gunichar2
* dir_name_utf16
;
873 gunichar2
* base_name_utf16
;
878 kernel32_handle
= GetModuleHandle (L
"kernel32.dll");
879 if (!kernel32_handle
)
881 CreateActCtx_proc
= (CREATEACTCTXW_PROC
) GetProcAddress (kernel32_handle
, "CreateActCtxW");
882 if (!CreateActCtx_proc
)
884 ActivateActCtx_proc
= (ACTIVATEACTCTX_PROC
) GetProcAddress (kernel32_handle
, "ActivateActCtx");
885 if (!ActivateActCtx_proc
)
888 full_path
= mono_path_canonicalize (file_name
);
889 full_path_utf16
= g_utf8_to_utf16 (full_path
, -1, NULL
, NULL
, NULL
);
890 dir_name
= g_path_get_dirname (full_path
);
891 dir_name_utf16
= g_utf8_to_utf16 (dir_name
, -1, NULL
, NULL
, NULL
);
892 base_name
= g_path_get_basename (full_path
);
893 base_name_utf16
= g_utf8_to_utf16 (base_name
, -1, NULL
, NULL
, NULL
);
898 memset (&act_ctx
, 0, sizeof (ACTCTX
));
899 act_ctx
.cbSize
= sizeof (ACTCTX
);
900 act_ctx
.dwFlags
= ACTCTX_FLAG_SET_PROCESS_DEFAULT
| ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
| ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_APPLICATION_NAME_VALID
;
901 act_ctx
.lpSource
= full_path_utf16
;
902 act_ctx
.lpAssemblyDirectory
= dir_name_utf16
;
903 act_ctx
.lpResourceName
= CREATEPROCESS_MANIFEST_RESOURCE_ID
;
904 act_ctx
.lpApplicationName
= base_name_utf16
;
906 handle
= CreateActCtx_proc (&act_ctx
);
907 if (handle
== INVALID_HANDLE_VALUE
&& GetLastError () == ERROR_SXS_PROCESS_DEFAULT_ALREADY_SET
) {
908 act_ctx
.dwFlags
&= ~ACTCTX_FLAG_SET_PROCESS_DEFAULT
;
909 handle
= CreateActCtx_proc (&act_ctx
);
912 g_free (base_name_utf16
);
913 g_free (dir_name_utf16
);
914 g_free (full_path_utf16
);
916 if (handle
!= INVALID_HANDLE_VALUE
)
917 ActivateActCtx_proc (handle
, &cookie
);
919 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
922 mono_load_coree (const char* exe_file_name
)
924 HMODULE module_handle
;
925 gunichar2
* file_name
;
929 if (coree_module_handle
)
932 // No GC safe transition because this is called early in driver.c
933 if (!init_from_coree
&& exe_file_name
)
934 mono_coree_set_act_ctx (exe_file_name
);
936 /* ntdll.dll loads mscoree.dll from the system32 directory. */
937 required_size
= GetSystemDirectory (NULL
, 0);
938 file_name
= g_new (gunichar2
, required_size
+ 12);
939 size
= GetSystemDirectory (file_name
, required_size
);
940 g_assert (size
< required_size
);
941 if (file_name
[size
- 1] != L
'\\')
942 file_name
[size
++] = L
'\\';
943 memcpy (&file_name
[size
], L
"mscoree.dll", 12 * sizeof (gunichar2
));
945 module_handle
= LoadLibrary (file_name
);
948 if (module_handle
&& !SUCCEEDED (MonoFixupCorEE (module_handle
))) {
949 FreeLibrary (module_handle
);
950 module_handle
= NULL
;
953 coree_module_handle
= module_handle
;
957 mono_fixup_exe_image (MonoImage
* image
)
959 if (!init_from_coree
&& image
&& m_image_is_module_handle (image
))
960 MonoFixupExe ((HMODULE
) image
->raw_data
);
965 #include <mono/utils/mono-compiler.h>
967 MONO_EMPTY_SOURCE_FILE (coree
);
969 #endif /* HOST_WIN32 */