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
;
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
);
94 init_from_coree
= TRUE
;
95 mono_runtime_load (file_name
, NULL
);
96 error
= (gchar
*) mono_check_corlib_version ();
100 mono_runtime_quit ();
104 image
= mono_image_open (file_name
, NULL
);
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
);
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
);
131 case DLL_PROCESS_DETACH
:
132 if (lpReserved
!= NULL
)
133 /* The process is terminating. */
135 file_name
= mono_get_module_file_name (hInst
);
136 image
= mono_image_loaded_internal (file_name
, FALSE
);
138 mono_image_close (image
);
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)
154 MonoAssembly
* assembly
;
159 gchar
* corlib_version_error
;
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
);
173 MessageBox (NULL
, L
"Corlib not in sync with this runtime.", NULL
, MB_ICONERROR
);
174 mono_runtime_quit ();
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 ();
184 MessageBox (NULL
, L
"Cannot open assembly.", NULL
, MB_ICONERROR
);
185 mono_runtime_quit ();
189 image
= assembly
->image
;
190 entry
= mono_image_get_entry_point (image
);
193 MessageBox (NULL
, L
"Assembly doesn't have an entry point.", NULL
, MB_ICONERROR
);
194 mono_runtime_quit ();
198 method
= mono_get_method_checked (image
, entry
, NULL
, NULL
, error
);
199 if (method
== NULL
) {
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 ();
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
);
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. */
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 ();
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
;
247 IMAGE_NT_HEADERS64
* NtHeaders64
;
248 MonoCLIHeader
* CliHeader
;
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
;
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
))
286 if (!VirtualProtect(Address
, sizeof(DWORD
), OldProtect
, &OldProtect
))
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
))
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
))
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
))
393 if (NtHeaders32
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
)
394 *Address
= (DWORD
)((DWORD_PTR
)&_CorDllMain
- (DWORD_PTR
)DosHeader
);
396 *Address
= (DWORD
)((DWORD_PTR
)&_CorExeMain
- (DWORD_PTR
)DosHeader
);
397 if (!VirtualProtect(Address
, sizeof(DWORD
), OldProtect
, &OldProtect
))
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
)
411 STDAPI
CorBindToRuntimeEx(LPCWSTR pwszVersion
, LPCWSTR pwszBuildFlavor
, DWORD startupFlags
, REFCLSID rclsid
, REFIID riid
, LPVOID FAR
*ppv
)
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
)
431 IMAGE_DOS_HEADER
* DosHeader
;
432 IMAGE_NT_HEADERS32
* NtHeaders32
;
434 IMAGE_NT_HEADERS64
* NtHeaders64
;
436 HMODULE ModuleHandle
;
438 FileHandle
= CreateFile(FileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
439 if (FileHandle
== INVALID_HANDLE_VALUE
)
442 FileSize
= GetFileSize(FileHandle
, NULL
);
443 if (FileSize
== INVALID_FILE_SIZE
)
446 MapHandle
= CreateFileMapping(FileHandle
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
447 if (MapHandle
== NULL
)
450 DosHeader
= (IMAGE_DOS_HEADER
*)MapViewOfFile(MapHandle
, FILE_MAP_READ
, 0, 0, 0);
451 if (DosHeader
== NULL
)
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
;
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
;
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
)
479 SetLastError(STATUS_INVALID_IMAGE_FORMAT
);
486 UnmapViewOfFile(DosHeader
);
487 CloseHandle(MapHandle
);
489 ModuleHandle
= LoadLibrary(FileName
);
491 CloseHandle(FileHandle
);
495 UnmapViewOfFile(DosHeader
);
497 CloseHandle(MapHandle
);
499 CloseHandle(FileHandle
);
502 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
504 typedef struct _EXPORT_FIXUP
511 BYTE Bytes
[sizeof(PVOID
)];
513 PLABEL_DESCRIPTOR
* PLabel
;
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
}},
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
;
545 EXPORT_FIXUP
* ExportFixup
;
546 DWORD
* ExportFixupRva
;
553 MEMORY_BASIC_INFORMATION MemoryInfo
;
558 PLABEL_DESCRIPTOR
* PLabel
;
560 #define ELEMENT_SIZE sizeof(PLABEL_DESCRIPTOR)
561 #define REGION_WRITE_PROTECT PAGE_READWRITE
562 #define REGION_PROTECT PAGE_READ
566 #define ELEMENT_SIZE 13
567 #define REGION_WRITE_PROTECT PAGE_EXECUTE_READWRITE
568 #define REGION_PROTECT PAGE_EXECUTE_READ
572 if (ExportFixupModuleHandle
!= NULL
)
573 return ModuleHandle
== ExportFixupModuleHandle
? S_OK
: E_FAIL
;
575 DosHeader
= (IMAGE_DOS_HEADER
*)ModuleHandle
;
576 if (DosHeader
== NULL
)
579 if (DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
582 NtHeaders
= (IMAGE_NT_HEADERS
*)((DWORD_PTR
)DosHeader
+ DosHeader
->e_lfanew
);
583 if (NtHeaders
->Signature
!= IMAGE_NT_SIGNATURE
)
586 if (NtHeaders
->OptionalHeader
.Magic
!= IMAGE_NT_OPTIONAL_HDR_MAGIC
)
589 if (NtHeaders
->OptionalHeader
.NumberOfRvaAndSizes
<= IMAGE_DIRECTORY_ENTRY_EXPORT
)
592 ExportDataDir
= &NtHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
];
593 if (!ExportDataDir
->VirtualAddress
)
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))));
602 if (!VirtualQuery(RegionBase
, &MemoryInfo
, sizeof(MEMORY_BASIC_INFORMATION
)))
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
);
610 RegionBase
= (PVOID
)((DWORD_PTR
)MemoryInfo
.BaseAddress
+ (DWORD_PTR
)MemoryInfo
.RegionSize
);
611 if (RegionBase
> MaxRegionBase
)
612 return E_OUTOFMEMORY
;
616 PLabel
= (PLABEL_DESCRIPTOR
*)Region
;
618 Trampoline
= (BYTE
*)Region
;
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
);
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];
655 *(Trampoline
)++ = 0x41;
656 *(Trampoline
)++ = 0xFF;
657 *(Trampoline
)++ = 0xE3;
659 #error Unsupported architecture.
662 ProcRva
= (DWORD
)(ExportFixup
->ProcAddress
.DWordPtr
- (DWORD_PTR
)DosHeader
);
664 Address
= &Functions
[NameOrdinals
[i
]];
665 if (!VirtualProtect(Address
, sizeof(DWORD
), PAGE_READWRITE
, &OldProtect
))
667 *ExportFixupRva
= *Address
;
669 if (!VirtualProtect(Address
, sizeof(DWORD
), OldProtect
, &OldProtect
))
672 if (ExportFixup
->Name
== NULL
) {
674 if (!VirtualProtect(Region
, ELEMENT_SIZE
* EXPORT_FIXUP_COUNT
, REGION_PROTECT
, &OldProtect
))
678 ExportFixupModuleHandle
= ModuleHandle
;
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
;
696 DosHeader
= (IMAGE_DOS_HEADER
*)ModuleHandle
;
697 if (DosHeader
== NULL
)
700 if (DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
703 NtHeaders
= (IMAGE_NT_HEADERS
*)((DWORD_PTR
)DosHeader
+ DosHeader
->e_lfanew
);
704 if (NtHeaders
->Signature
!= IMAGE_NT_SIGNATURE
)
707 if (NtHeaders
->OptionalHeader
.Magic
!= IMAGE_NT_OPTIONAL_HDR_MAGIC
)
710 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
)
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
)
727 BaseDiff
= (DWORD_PTR
)DosHeader
- NtHeaders
->OptionalHeader
.ImageBase
;
730 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
733 Address
= &NtHeaders
->OptionalHeader
.ImageBase
;
734 if (!VirtualProtect(Address
, sizeof(DWORD_PTR
), PAGE_READWRITE
, &OldProtect
))
736 *Address
= (DWORD_PTR
)DosHeader
;
737 if (!VirtualProtect(Address
, sizeof(DWORD_PTR
), OldProtect
, &OldProtect
))
740 if (NtHeaders
->OptionalHeader
.NumberOfRvaAndSizes
> IMAGE_DIRECTORY_ENTRY_BASERELOC
)
742 IMAGE_DATA_DIRECTORY
* BaseRelocDir
;
743 IMAGE_BASE_RELOCATION
* BaseReloc
;
746 ULONG RelocBlockSize
;
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
)
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
:
779 case IMAGE_REL_BASED_DIR64
:
781 case IMAGE_REL_BASED_HIGHLOW
:
783 if (!VirtualProtect(RelocFixup
, sizeof(DWORD_PTR
), PAGE_EXECUTE_READWRITE
, &OldProtect
))
785 *RelocFixup
+= BaseDiff
;
786 if (!VirtualProtect(RelocFixup
, sizeof(DWORD_PTR
), OldProtect
, &OldProtect
))
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
);
825 if (ImportModuleHandle
== NULL
)
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
));
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)
840 Address
= (DWORD_PTR
*)((DWORD_PTR
)ImportThunkData
- ImportDesc
->OriginalFirstThunk
+ ImportDesc
->FirstThunk
);
841 if (!VirtualProtect(Address
, sizeof(DWORD_PTR
), PAGE_READWRITE
, &OldProtect
))
843 *Address
= ProcAddress
;
844 if (!VirtualProtect(Address
, sizeof(DWORD_PTR
), OldProtect
, &OldProtect
))
857 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
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
;
868 gunichar2
* full_path_utf16
;
870 gunichar2
* dir_name_utf16
;
872 gunichar2
* base_name_utf16
;
877 kernel32_handle
= GetModuleHandle (L
"kernel32.dll");
878 if (!kernel32_handle
)
880 CreateActCtx_proc
= (CREATEACTCTXW_PROC
) GetProcAddress (kernel32_handle
, "CreateActCtxW");
881 if (!CreateActCtx_proc
)
883 ActivateActCtx_proc
= (ACTIVATEACTCTX_PROC
) GetProcAddress (kernel32_handle
, "ActivateActCtx");
884 if (!ActivateActCtx_proc
)
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
);
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) */
921 mono_load_coree (const char* exe_file_name
)
923 HMODULE module_handle
;
924 gunichar2
* file_name
;
928 if (coree_module_handle
)
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
);
946 if (module_handle
&& !SUCCEEDED (MonoFixupCorEE (module_handle
))) {
947 FreeLibrary (module_handle
);
948 module_handle
= NULL
;
951 coree_module_handle
= module_handle
;
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 */