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 "assembly-internals.h"
24 #include "domain-internals.h"
25 #include "appdomain.h"
27 #include "object-internals.h"
30 #include "environment.h"
32 #include "coree-internals.h"
34 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
38 HMODULE coree_module_handle
= NULL
;
40 static gboolean init_from_coree
= FALSE
;
43 mono_get_module_file_name (HMODULE module_handle
)
46 gchar
* file_name_utf8
;
51 file_name
= g_new (gunichar2
, buffer_size
);
54 size
= GetModuleFileName (module_handle
, file_name
, buffer_size
);
60 g_assert (size
<= buffer_size
);
61 if (size
!= buffer_size
)
65 file_name
= g_realloc (file_name
, buffer_size
* sizeof (gunichar2
));
68 file_name_utf8
= g_utf16_to_utf8 (file_name
, size
, NULL
, NULL
, NULL
);
71 return file_name_utf8
;
74 /* Entry point called by LdrLoadDll of ntdll.dll after _CorValidateImage. */
75 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
76 BOOL STDMETHODCALLTYPE
_CorDllMain(HINSTANCE hInst
, DWORD dwReason
, LPVOID lpReserved
)
78 MonoAssembly
* assembly
;
85 case DLL_PROCESS_ATTACH
:
86 DisableThreadLibraryCalls (hInst
);
88 file_name
= mono_get_module_file_name (hInst
);
90 if (mono_get_root_domain ()) {
91 image
= mono_image_open_from_module_handle (hInst
, mono_path_resolve_symlinks (file_name
), TRUE
, NULL
);
93 init_from_coree
= TRUE
;
94 mono_runtime_load (file_name
, NULL
);
95 error
= (gchar
*) mono_check_corlib_version ();
103 image
= mono_image_open (file_name
, NULL
);
105 image
->has_entry_point
= TRUE
;
106 mono_close_exe_image ();
107 /* Decrement reference count to zero. (Image will not be closed.) */
108 mono_image_close (image
);
118 * FIXME: Find a better way to call mono_image_fixup_vtable. Only
119 * loader trampolines should be used and assembly loading should
120 * probably be delayed until the first call to an exported function.
122 if (image
->tables
[MONO_TABLE_ASSEMBLY
].rows
&& image
->image_info
->cli_cli_header
.ch_vtable_fixups
.rva
)
123 assembly
= mono_assembly_open_predicate (file_name
, MONO_ASMCTX_DEFAULT
, NULL
, NULL
, NULL
, NULL
);
127 case DLL_PROCESS_DETACH
:
128 if (lpReserved
!= NULL
)
129 /* The process is terminating. */
131 file_name
= mono_get_module_file_name (hInst
);
132 image
= mono_image_loaded (file_name
);
134 mono_image_close (image
);
142 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
144 /* Called by ntdll.dll reagardless of entry point after _CorValidateImage. */
145 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
146 __int32 STDMETHODCALLTYPE
_CorExeMain(void)
150 MonoAssembly
* assembly
;
155 gchar
* corlib_version_error
;
161 file_name
= mono_get_module_file_name (NULL
);
162 init_from_coree
= TRUE
;
163 domain
= mono_runtime_load (file_name
, NULL
);
165 corlib_version_error
= (gchar
*) mono_check_corlib_version ();
166 if (corlib_version_error
) {
167 g_free (corlib_version_error
);
169 MessageBox (NULL
, L
"Corlib not in sync with this runtime.", NULL
, MB_ICONERROR
);
170 mono_runtime_quit ();
174 assembly
= mono_assembly_open_predicate (file_name
, MONO_ASMCTX_DEFAULT
, NULL
, NULL
, NULL
, NULL
);
175 mono_close_exe_image ();
178 MessageBox (NULL
, L
"Cannot open assembly.", NULL
, MB_ICONERROR
);
179 mono_runtime_quit ();
183 image
= assembly
->image
;
184 entry
= mono_image_get_entry_point (image
);
187 MessageBox (NULL
, L
"Assembly doesn't have an entry point.", NULL
, MB_ICONERROR
);
188 mono_runtime_quit ();
192 method
= mono_get_method_checked (image
, entry
, NULL
, NULL
, error
);
193 if (method
== NULL
) {
195 mono_error_cleanup (error
); /* FIXME don't swallow the error */
196 MessageBox (NULL
, L
"The entry point method could not be loaded.", NULL
, MB_ICONERROR
);
197 mono_runtime_quit ();
201 argvw
= CommandLineToArgvW (GetCommandLine (), &argc
);
202 argv
= g_new0 (gchar
*, argc
);
203 argv
[0] = file_name
;
204 for (i
= 1; i
< argc
; ++i
)
205 argv
[i
] = g_utf16_to_utf8 (argvw
[i
], -1, NULL
, NULL
, NULL
);
208 mono_runtime_run_main_checked (method
, argc
, argv
, error
);
209 mono_error_raise_exception_deprecated (error
); /* OK, triggers unhandled exn handler */
210 mono_thread_manage ();
212 mono_runtime_quit ();
214 /* return does not terminate the process. */
215 ExitProcess (mono_environment_exitcode_get ());
217 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
219 /* Called by msvcrt.dll when shutting down. */
220 void STDMETHODCALLTYPE
CorExitProcess(int exitCode
)
222 /* FIXME: This is not currently supported by the runtime. */
224 if (mono_get_root_domain () && !mono_runtime_is_shutting_down ()) {
225 mono_runtime_set_shutting_down ();
226 mono_thread_suspend_all_other_threads ();
227 mono_runtime_quit ();
230 ExitProcess (exitCode
);
233 /* Called by ntdll.dll before _CorDllMain and _CorExeMain. */
234 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
235 STDAPI
_CorValidateImage(PVOID
*ImageBase
, LPCWSTR FileName
)
237 IMAGE_DOS_HEADER
* DosHeader
;
238 IMAGE_NT_HEADERS32
* NtHeaders32
;
239 IMAGE_DATA_DIRECTORY
* CliHeaderDir
;
241 IMAGE_NT_HEADERS64
* NtHeaders64
;
242 MonoCLIHeader
* CliHeader
;
248 DosHeader
= (IMAGE_DOS_HEADER
*)*ImageBase
;
249 if (DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
250 return STATUS_INVALID_IMAGE_FORMAT
;
252 NtHeaders32
= (IMAGE_NT_HEADERS32
*)((DWORD_PTR
)DosHeader
+ DosHeader
->e_lfanew
);
253 if (NtHeaders32
->Signature
!= IMAGE_NT_SIGNATURE
)
254 return STATUS_INVALID_IMAGE_FORMAT
;
257 NtHeaders64
= (IMAGE_NT_HEADERS64
*)NtHeaders32
;
258 if (NtHeaders64
->OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR64_MAGIC
)
260 if (NtHeaders64
->OptionalHeader
.NumberOfRvaAndSizes
<= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
)
261 return STATUS_INVALID_IMAGE_FORMAT
;
263 CliHeaderDir
= &NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
];
264 if (!CliHeaderDir
->VirtualAddress
)
265 return STATUS_INVALID_IMAGE_FORMAT
;
267 CliHeader
= (MonoCLIHeader
*)((DWORD_PTR
)DosHeader
+ CliHeaderDir
->VirtualAddress
);
268 if (CliHeader
->ch_flags
& CLI_FLAGS_32BITREQUIRED
)
269 return STATUS_INVALID_IMAGE_FORMAT
;
271 if (CliHeader
->ch_flags
& CLI_FLAGS_ILONLY
)
273 /* Avoid calling _CorDllMain because imports are not resolved for IL only images. */
274 if (NtHeaders64
->OptionalHeader
.AddressOfEntryPoint
!= 0)
276 Address
= &NtHeaders64
->OptionalHeader
.AddressOfEntryPoint
;
277 if (!VirtualProtect(Address
, sizeof(DWORD
), PAGE_READWRITE
, &OldProtect
))
280 if (!VirtualProtect(Address
, sizeof(DWORD
), OldProtect
, &OldProtect
))
285 return STATUS_SUCCESS
;
288 if (NtHeaders32
->OptionalHeader
.Magic
!= IMAGE_NT_OPTIONAL_HDR32_MAGIC
)
289 return STATUS_INVALID_IMAGE_FORMAT
;
291 if (NtHeaders32
->OptionalHeader
.NumberOfRvaAndSizes
<= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
)
292 return STATUS_INVALID_IMAGE_FORMAT
;
294 CliHeaderDir
= &NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
];
295 if (!CliHeaderDir
->VirtualAddress
)
296 return STATUS_INVALID_IMAGE_FORMAT
;
298 CliHeader
= (MonoCLIHeader
*)((DWORD_PTR
)DosHeader
+ CliHeaderDir
->VirtualAddress
);
299 if (!(CliHeader
->ch_flags
& CLI_FLAGS_ILONLY
) || (CliHeader
->ch_flags
& CLI_FLAGS_32BITREQUIRED
))
300 return STATUS_INVALID_IMAGE_FORMAT
;
302 /* Fixup IMAGE_NT_HEADERS32 to IMAGE_NT_HEADERS64. */
303 SizeOfHeaders
= NtHeaders32
->OptionalHeader
.SizeOfHeaders
;
304 if (SizeOfHeaders
< DosHeader
->e_lfanew
+ sizeof(IMAGE_NT_HEADERS64
) + (sizeof(IMAGE_SECTION_HEADER
) * NtHeaders32
->FileHeader
.NumberOfSections
))
305 return STATUS_INVALID_IMAGE_FORMAT
;
307 if (!VirtualProtect(DosHeader
, SizeOfHeaders
, PAGE_READWRITE
, &OldProtect
))
310 memmove(NtHeaders64
+ 1, IMAGE_FIRST_SECTION(NtHeaders32
), sizeof(IMAGE_SECTION_HEADER
) * NtHeaders32
->FileHeader
.NumberOfSections
);
312 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_NUMBEROF_DIRECTORY_ENTRIES
- 1].Size
= 0;
313 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_NUMBEROF_DIRECTORY_ENTRIES
- 1].VirtualAddress
= 0;
314 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
= NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
;
315 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
= NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
;
316 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
].Size
= 0;
317 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
].VirtualAddress
= 0;
318 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IAT
].Size
= 0;
319 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IAT
].VirtualAddress
= 0;
320 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
].Size
= 0;
321 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
].VirtualAddress
= 0;
322 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
].Size
= 0;
323 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
].VirtualAddress
= 0;
324 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_TLS
].Size
= 0;
325 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_TLS
].VirtualAddress
= 0;
326 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_GLOBALPTR
].Size
= 0;
327 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_GLOBALPTR
].VirtualAddress
= 0;
328 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_ARCHITECTURE
].Size
= 0;
329 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_ARCHITECTURE
].VirtualAddress
= 0;
330 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
331 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
332 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
333 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
334 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
= NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
;
335 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_SECURITY
].VirtualAddress
= NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_SECURITY
].VirtualAddress
;
336 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
337 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
338 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
= NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
;
339 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
= NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
340 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].Size
= 0;
341 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
= 0;
342 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
= 0;
343 NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
= 0;
345 NtHeaders64
->OptionalHeader
.NumberOfRvaAndSizes
= IMAGE_NUMBEROF_DIRECTORY_ENTRIES
;
346 NtHeaders64
->OptionalHeader
.LoaderFlags
= NtHeaders32
->OptionalHeader
.LoaderFlags
;
347 NtHeaders64
->OptionalHeader
.SizeOfHeapCommit
= (ULONGLONG
)NtHeaders32
->OptionalHeader
.SizeOfHeapCommit
;
348 NtHeaders64
->OptionalHeader
.SizeOfHeapReserve
= (ULONGLONG
)NtHeaders32
->OptionalHeader
.SizeOfHeapReserve
;
349 NtHeaders64
->OptionalHeader
.SizeOfStackCommit
= (ULONGLONG
)NtHeaders32
->OptionalHeader
.SizeOfStackCommit
;
350 NtHeaders64
->OptionalHeader
.SizeOfStackReserve
= (ULONGLONG
)NtHeaders32
->OptionalHeader
.SizeOfStackReserve
;
351 NtHeaders64
->OptionalHeader
.DllCharacteristics
= NtHeaders32
->OptionalHeader
.DllCharacteristics
;
352 NtHeaders64
->OptionalHeader
.Subsystem
= NtHeaders32
->OptionalHeader
.Subsystem
;
353 NtHeaders64
->OptionalHeader
.CheckSum
= NtHeaders32
->OptionalHeader
.CheckSum
;
354 NtHeaders64
->OptionalHeader
.SizeOfHeaders
= NtHeaders32
->OptionalHeader
.SizeOfHeaders
;
355 NtHeaders64
->OptionalHeader
.SizeOfImage
= NtHeaders32
->OptionalHeader
.SizeOfImage
;
356 NtHeaders64
->OptionalHeader
.Win32VersionValue
= NtHeaders32
->OptionalHeader
.Win32VersionValue
;
357 NtHeaders64
->OptionalHeader
.MinorSubsystemVersion
= NtHeaders32
->OptionalHeader
.MinorSubsystemVersion
;
358 NtHeaders64
->OptionalHeader
.MajorSubsystemVersion
= NtHeaders32
->OptionalHeader
.MajorSubsystemVersion
;
359 NtHeaders64
->OptionalHeader
.MinorImageVersion
= NtHeaders32
->OptionalHeader
.MinorImageVersion
;
360 NtHeaders64
->OptionalHeader
.MajorImageVersion
= NtHeaders32
->OptionalHeader
.MajorImageVersion
;
361 NtHeaders64
->OptionalHeader
.MinorOperatingSystemVersion
= NtHeaders32
->OptionalHeader
.MinorOperatingSystemVersion
;
362 NtHeaders64
->OptionalHeader
.MajorOperatingSystemVersion
= NtHeaders32
->OptionalHeader
.MajorOperatingSystemVersion
;
363 NtHeaders64
->OptionalHeader
.FileAlignment
= NtHeaders32
->OptionalHeader
.FileAlignment
;
364 NtHeaders64
->OptionalHeader
.SectionAlignment
= NtHeaders32
->OptionalHeader
.SectionAlignment
;
365 NtHeaders64
->OptionalHeader
.ImageBase
= (ULONGLONG
)NtHeaders32
->OptionalHeader
.ImageBase
;
366 /* BaseOfCode is at the same offset. */
367 NtHeaders64
->OptionalHeader
.AddressOfEntryPoint
= 0;
368 NtHeaders64
->OptionalHeader
.Magic
= IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
369 NtHeaders64
->FileHeader
.SizeOfOptionalHeader
= sizeof(IMAGE_OPTIONAL_HEADER64
);
371 if (!VirtualProtect(DosHeader
, SizeOfHeaders
, OldProtect
, &OldProtect
))
374 if (NtHeaders32
->OptionalHeader
.Magic
!= IMAGE_NT_OPTIONAL_HDR32_MAGIC
)
375 return STATUS_INVALID_IMAGE_FORMAT
;
377 if (NtHeaders32
->OptionalHeader
.NumberOfRvaAndSizes
<= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
)
378 return STATUS_INVALID_IMAGE_FORMAT
;
380 CliHeaderDir
= &NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
];
381 if (!CliHeaderDir
->VirtualAddress
)
382 return STATUS_INVALID_IMAGE_FORMAT
;
384 Address
= &NtHeaders32
->OptionalHeader
.AddressOfEntryPoint
;
385 if (!VirtualProtect(Address
, sizeof(DWORD
), PAGE_READWRITE
, &OldProtect
))
387 if (NtHeaders32
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
)
388 *Address
= (DWORD
)((DWORD_PTR
)&_CorDllMain
- (DWORD_PTR
)DosHeader
);
390 *Address
= (DWORD
)((DWORD_PTR
)&_CorExeMain
- (DWORD_PTR
)DosHeader
);
391 if (!VirtualProtect(Address
, sizeof(DWORD
), OldProtect
, &OldProtect
))
395 return STATUS_SUCCESS
;
397 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
399 /* Called by ntdll.dll. */
400 STDAPI_(VOID
) _CorImageUnloading(PVOID ImageBase
)
405 STDAPI
CorBindToRuntimeEx(LPCWSTR pwszVersion
, LPCWSTR pwszBuildFlavor
, DWORD startupFlags
, REFCLSID rclsid
, REFIID riid
, LPVOID FAR
*ppv
)
414 STDAPI
CorBindToRuntime(LPCWSTR pwszVersion
, LPCWSTR pwszBuildFlavor
, REFCLSID rclsid
, REFIID riid
, LPVOID FAR
*ppv
)
416 return CorBindToRuntimeEx (pwszVersion
, pwszBuildFlavor
, 0, rclsid
, riid
, ppv
);
419 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
420 HMODULE WINAPI
MonoLoadImage(LPCWSTR FileName
)
425 IMAGE_DOS_HEADER
* DosHeader
;
426 IMAGE_NT_HEADERS32
* NtHeaders32
;
428 IMAGE_NT_HEADERS64
* NtHeaders64
;
430 HMODULE ModuleHandle
;
432 FileHandle
= CreateFile(FileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
433 if (FileHandle
== INVALID_HANDLE_VALUE
)
436 FileSize
= GetFileSize(FileHandle
, NULL
);
437 if (FileSize
== INVALID_FILE_SIZE
)
440 MapHandle
= CreateFileMapping(FileHandle
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
441 if (MapHandle
== NULL
)
444 DosHeader
= (IMAGE_DOS_HEADER
*)MapViewOfFile(MapHandle
, FILE_MAP_READ
, 0, 0, 0);
445 if (DosHeader
== NULL
)
448 if (FileSize
< sizeof(IMAGE_DOS_HEADER
) || DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
|| FileSize
< DosHeader
->e_lfanew
+ sizeof(IMAGE_NT_HEADERS32
))
449 goto InvalidImageFormat
;
451 NtHeaders32
= (IMAGE_NT_HEADERS32
*)((DWORD_PTR
)DosHeader
+ DosHeader
->e_lfanew
);
452 if (NtHeaders32
->Signature
!= IMAGE_NT_SIGNATURE
)
453 goto InvalidImageFormat
;
456 NtHeaders64
= (IMAGE_NT_HEADERS64
*)NtHeaders32
;
457 if (NtHeaders64
->OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR64_MAGIC
)
459 if (FileSize
< DosHeader
->e_lfanew
+ sizeof(IMAGE_NT_HEADERS64
) ||
460 NtHeaders64
->OptionalHeader
.NumberOfRvaAndSizes
<= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
||
461 !NtHeaders64
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
)
462 goto InvalidImageFormat
;
468 if (NtHeaders32
->OptionalHeader
.Magic
!= IMAGE_NT_OPTIONAL_HDR32_MAGIC
||
469 NtHeaders32
->OptionalHeader
.NumberOfRvaAndSizes
<= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
||
470 !NtHeaders32
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
)
473 SetLastError(STATUS_INVALID_IMAGE_FORMAT
);
480 UnmapViewOfFile(DosHeader
);
481 CloseHandle(MapHandle
);
483 ModuleHandle
= LoadLibrary(FileName
);
485 CloseHandle(FileHandle
);
489 UnmapViewOfFile(DosHeader
);
491 CloseHandle(MapHandle
);
493 CloseHandle(FileHandle
);
496 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
498 typedef struct _EXPORT_FIXUP
505 BYTE Bytes
[sizeof(PVOID
)];
507 PLABEL_DESCRIPTOR
* PLabel
;
512 /* Has to be binary ordered. */
513 static const EXPORT_FIXUP ExportFixups
[] = {
514 {"CorBindToRuntime", {(PVOID
)&CorBindToRuntime
}},
515 {"CorBindToRuntimeEx", {(PVOID
)&CorBindToRuntimeEx
}},
516 {"CorExitProcess", {(PVOID
)&CorExitProcess
}},
517 {"_CorDllMain", {(PVOID
)&_CorDllMain
}},
518 {"_CorExeMain", {(PVOID
)&_CorExeMain
}},
519 {"_CorImageUnloading", {(PVOID
)&_CorImageUnloading
}},
520 {"_CorValidateImage", {(PVOID
)&_CorValidateImage
}},
524 #define EXPORT_FIXUP_COUNT (sizeof(ExportFixups) / sizeof(EXPORT_FIXUP) - 1)
526 static HMODULE ExportFixupModuleHandle
= NULL
;
527 static DWORD ExportFixupRvas
[EXPORT_FIXUP_COUNT
];
529 /* Fixup exported functions of mscoree.dll to our implementations. */
530 STDAPI
MonoFixupCorEE(HMODULE ModuleHandle
)
532 IMAGE_DOS_HEADER
* DosHeader
;
533 IMAGE_NT_HEADERS
* NtHeaders
;
534 IMAGE_DATA_DIRECTORY
* ExportDataDir
;
535 IMAGE_EXPORT_DIRECTORY
* ExportDir
;
539 EXPORT_FIXUP
* ExportFixup
;
540 DWORD
* ExportFixupRva
;
547 MEMORY_BASIC_INFORMATION MemoryInfo
;
552 PLABEL_DESCRIPTOR
* PLabel
;
554 #define ELEMENT_SIZE sizeof(PLABEL_DESCRIPTOR)
555 #define REGION_WRITE_PROTECT PAGE_READWRITE
556 #define REGION_PROTECT PAGE_READ
560 #define ELEMENT_SIZE 13
561 #define REGION_WRITE_PROTECT PAGE_EXECUTE_READWRITE
562 #define REGION_PROTECT PAGE_EXECUTE_READ
566 if (ExportFixupModuleHandle
!= NULL
)
567 return ModuleHandle
== ExportFixupModuleHandle
? S_OK
: E_FAIL
;
569 DosHeader
= (IMAGE_DOS_HEADER
*)ModuleHandle
;
570 if (DosHeader
== NULL
)
573 if (DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
576 NtHeaders
= (IMAGE_NT_HEADERS
*)((DWORD_PTR
)DosHeader
+ DosHeader
->e_lfanew
);
577 if (NtHeaders
->Signature
!= IMAGE_NT_SIGNATURE
)
580 if (NtHeaders
->OptionalHeader
.Magic
!= IMAGE_NT_OPTIONAL_HDR_MAGIC
)
583 if (NtHeaders
->OptionalHeader
.NumberOfRvaAndSizes
<= IMAGE_DIRECTORY_ENTRY_EXPORT
)
586 ExportDataDir
= &NtHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
];
587 if (!ExportDataDir
->VirtualAddress
)
591 /* Allocate memory after base address because RVAs are 32-bit unsigned integers. */
592 RegionBase
= DosHeader
;
593 MaxRegionBase
= (PVOID
)((DWORD_PTR
)RegionBase
+ (DWORD_PTR
)(0x100000000L
- (ELEMENT_SIZE
* (EXPORT_FIXUP_COUNT
- 1))));
596 if (!VirtualQuery(RegionBase
, &MemoryInfo
, sizeof(MEMORY_BASIC_INFORMATION
)))
598 if (MemoryInfo
.State
== MEM_FREE
&& MemoryInfo
.RegionSize
>= ELEMENT_SIZE
* EXPORT_FIXUP_COUNT
)
600 Region
= VirtualAlloc(RegionBase
, ELEMENT_SIZE
* EXPORT_FIXUP_COUNT
, MEM_COMMIT
| MEM_RESERVE
, REGION_WRITE_PROTECT
);
604 RegionBase
= (PVOID
)((DWORD_PTR
)MemoryInfo
.BaseAddress
+ (DWORD_PTR
)MemoryInfo
.RegionSize
);
605 if (RegionBase
> MaxRegionBase
)
606 return E_OUTOFMEMORY
;
610 PLabel
= (PLABEL_DESCRIPTOR
*)Region
;
612 Trampoline
= (BYTE
*)Region
;
616 ExportDir
= (IMAGE_EXPORT_DIRECTORY
*)((DWORD_PTR
)DosHeader
+ ExportDataDir
->VirtualAddress
);
617 Functions
= (DWORD
*)((DWORD_PTR
)DosHeader
+ ExportDir
->AddressOfFunctions
);
618 Names
= (DWORD
*)((DWORD_PTR
)DosHeader
+ ExportDir
->AddressOfNames
);
619 NameOrdinals
= (WORD
*)((DWORD_PTR
)DosHeader
+ ExportDir
->AddressOfNameOrdinals
);
620 ExportFixup
= (EXPORT_FIXUP
*)&ExportFixups
;
621 ExportFixupRva
= (DWORD
*)&ExportFixupRvas
;
623 for (i
= 0; i
< ExportDir
->NumberOfNames
; i
++)
625 cmp
= strcmp((LPCSTR
)((DWORD_PTR
)DosHeader
+ Names
[i
]), ExportFixup
->Name
);
633 ProcRva
= (DWORD
)((DWORD_PTR
)PLabel
- (DWORD_PTR
)DosHeader
);
634 *(PLabel
)++ = *ExportFixup
->ProcAddress
.PLabel
;
635 #elif defined(_M_AMD64)
636 ProcRva
= (DWORD
)((DWORD_PTR
)Trampoline
- (DWORD_PTR
)DosHeader
);
637 /* mov r11, ExportFixup->ProcAddress */
638 *(Trampoline
)++ = 0x49;
639 *(Trampoline
)++ = 0xBB;
640 *(Trampoline
)++ = ExportFixup
->ProcAddress
.Bytes
[0];
641 *(Trampoline
)++ = ExportFixup
->ProcAddress
.Bytes
[1];
642 *(Trampoline
)++ = ExportFixup
->ProcAddress
.Bytes
[2];
643 *(Trampoline
)++ = ExportFixup
->ProcAddress
.Bytes
[3];
644 *(Trampoline
)++ = ExportFixup
->ProcAddress
.Bytes
[4];
645 *(Trampoline
)++ = ExportFixup
->ProcAddress
.Bytes
[5];
646 *(Trampoline
)++ = ExportFixup
->ProcAddress
.Bytes
[6];
647 *(Trampoline
)++ = ExportFixup
->ProcAddress
.Bytes
[7];
649 *(Trampoline
)++ = 0x41;
650 *(Trampoline
)++ = 0xFF;
651 *(Trampoline
)++ = 0xE3;
653 #error Unsupported architecture.
656 ProcRva
= (DWORD
)(ExportFixup
->ProcAddress
.DWordPtr
- (DWORD_PTR
)DosHeader
);
658 Address
= &Functions
[NameOrdinals
[i
]];
659 if (!VirtualProtect(Address
, sizeof(DWORD
), PAGE_READWRITE
, &OldProtect
))
661 *ExportFixupRva
= *Address
;
663 if (!VirtualProtect(Address
, sizeof(DWORD
), OldProtect
, &OldProtect
))
666 if (ExportFixup
->Name
== NULL
) {
668 if (!VirtualProtect(Region
, ELEMENT_SIZE
* EXPORT_FIXUP_COUNT
, REGION_PROTECT
, &OldProtect
))
672 ExportFixupModuleHandle
= ModuleHandle
;
681 /* Executable images are only mapped by the OS loader. We need to do fixups for native code support. */
682 STDAPI
MonoFixupExe(HMODULE ModuleHandle
)
684 IMAGE_DOS_HEADER
* DosHeader
;
685 IMAGE_NT_HEADERS
* NtHeaders
;
690 DosHeader
= (IMAGE_DOS_HEADER
*)ModuleHandle
;
691 if (DosHeader
== NULL
)
694 if (DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
697 NtHeaders
= (IMAGE_NT_HEADERS
*)((DWORD_PTR
)DosHeader
+ DosHeader
->e_lfanew
);
698 if (NtHeaders
->Signature
!= IMAGE_NT_SIGNATURE
)
701 if (NtHeaders
->OptionalHeader
.Magic
!= IMAGE_NT_OPTIONAL_HDR_MAGIC
)
704 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
)
707 if (NtHeaders
->OptionalHeader
.NumberOfRvaAndSizes
> IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
)
709 IMAGE_DATA_DIRECTORY
* CliHeaderDir
;
710 MonoCLIHeader
* CliHeader
;
712 CliHeaderDir
= &NtHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
];
713 if (CliHeaderDir
->VirtualAddress
)
715 CliHeader
= (MonoCLIHeader
*)((DWORD_PTR
)DosHeader
+ CliHeaderDir
->VirtualAddress
);
716 if (CliHeader
->ch_flags
& CLI_FLAGS_ILONLY
)
721 BaseDiff
= (DWORD_PTR
)DosHeader
- NtHeaders
->OptionalHeader
.ImageBase
;
724 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
727 Address
= &NtHeaders
->OptionalHeader
.ImageBase
;
728 if (!VirtualProtect(Address
, sizeof(DWORD_PTR
), PAGE_READWRITE
, &OldProtect
))
730 *Address
= (DWORD_PTR
)DosHeader
;
731 if (!VirtualProtect(Address
, sizeof(DWORD_PTR
), OldProtect
, &OldProtect
))
734 if (NtHeaders
->OptionalHeader
.NumberOfRvaAndSizes
> IMAGE_DIRECTORY_ENTRY_BASERELOC
)
736 IMAGE_DATA_DIRECTORY
* BaseRelocDir
;
737 IMAGE_BASE_RELOCATION
* BaseReloc
;
740 ULONG RelocBlockSize
;
742 DWORD_PTR UNALIGNED
*RelocFixup
;
744 BaseRelocDir
= &NtHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
745 if (BaseRelocDir
->VirtualAddress
)
747 BaseReloc
= (IMAGE_BASE_RELOCATION
*)((DWORD_PTR
)DosHeader
+ BaseRelocDir
->VirtualAddress
);
748 BaseRelocSize
= BaseRelocDir
->Size
;
750 while (BaseRelocSize
)
752 RelocBlockSize
= BaseReloc
->SizeOfBlock
;
754 if (!RelocBlockSize
|| BaseRelocSize
< RelocBlockSize
)
757 BaseRelocSize
-= RelocBlockSize
;
758 RelocBlock
= (USHORT
*)((DWORD_PTR
)BaseReloc
+ sizeof(IMAGE_BASE_RELOCATION
));
759 RelocBlockSize
-= sizeof(IMAGE_BASE_RELOCATION
);
760 RelocBlockSize
/= sizeof(USHORT
);
762 while (RelocBlockSize
-- != 0)
764 RelocOffset
= *RelocBlock
& (USHORT
)0x0fff;
765 RelocFixup
= (DWORD_PTR
*)((DWORD_PTR
)DosHeader
+ BaseReloc
->VirtualAddress
+ RelocOffset
);
767 switch (*RelocBlock
>> 12)
769 case IMAGE_REL_BASED_ABSOLUTE
:
773 case IMAGE_REL_BASED_DIR64
:
775 case IMAGE_REL_BASED_HIGHLOW
:
777 if (!VirtualProtect(RelocFixup
, sizeof(DWORD_PTR
), PAGE_EXECUTE_READWRITE
, &OldProtect
))
779 *RelocFixup
+= BaseDiff
;
780 if (!VirtualProtect(RelocFixup
, sizeof(DWORD_PTR
), OldProtect
, &OldProtect
))
790 BaseReloc
= (IMAGE_BASE_RELOCATION
*)RelocBlock
;
796 if (NtHeaders
->OptionalHeader
.NumberOfRvaAndSizes
> IMAGE_DIRECTORY_ENTRY_IMPORT
)
798 IMAGE_DATA_DIRECTORY
* ImportDir
;
799 IMAGE_IMPORT_DESCRIPTOR
* ImportDesc
;
800 HMODULE ImportModuleHandle
;
801 IMAGE_THUNK_DATA
* ImportThunkData
;
802 DWORD_PTR ProcAddress
;
804 ImportDir
= &NtHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
];
805 if (ImportDir
->VirtualAddress
!= 0)
807 ImportDesc
= (IMAGE_IMPORT_DESCRIPTOR
*)((DWORD_PTR
)DosHeader
+ ImportDir
->VirtualAddress
);
808 while (ImportDesc
->Name
&& ImportDesc
->OriginalFirstThunk
)
810 gchar
*file_utf8
= (gchar
*)((DWORD_PTR
)DosHeader
+ ImportDesc
->Name
);
812 gunichar2
*file_utf16
= g_utf8_to_utf16 (file_utf8
, (glong
)strlen (file_utf8
), NULL
, NULL
, NULL
);
813 ImportModuleHandle
= NULL
;
814 if (file_utf16
!= NULL
) {
815 ImportModuleHandle
= LoadLibraryW(file_utf16
);
819 if (ImportModuleHandle
== NULL
)
822 ImportThunkData
= (IMAGE_THUNK_DATA
*)((DWORD_PTR
)DosHeader
+ ImportDesc
->OriginalFirstThunk
);
823 while (ImportThunkData
->u1
.Ordinal
!= 0)
825 if (IMAGE_SNAP_BY_ORDINAL(ImportThunkData
->u1
.Ordinal
))
826 ProcAddress
= (DWORD_PTR
)GetProcAddress(ImportModuleHandle
, (LPCSTR
)IMAGE_ORDINAL(ImportThunkData
->u1
.Ordinal
));
829 IMAGE_IMPORT_BY_NAME
* ImportByName
= (IMAGE_IMPORT_BY_NAME
*)((DWORD_PTR
)DosHeader
+ ImportThunkData
->u1
.AddressOfData
);
830 ProcAddress
= (DWORD_PTR
)GetProcAddress(ImportModuleHandle
, (PCSTR
)ImportByName
->Name
);
832 if (ProcAddress
== 0)
834 Address
= (DWORD_PTR
*)((DWORD_PTR
)ImportThunkData
- ImportDesc
->OriginalFirstThunk
+ ImportDesc
->FirstThunk
);
835 if (!VirtualProtect(Address
, sizeof(DWORD_PTR
), PAGE_READWRITE
, &OldProtect
))
837 *Address
= ProcAddress
;
838 if (!VirtualProtect(Address
, sizeof(DWORD_PTR
), OldProtect
, &OldProtect
))
851 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
853 mono_coree_set_act_ctx (const char* file_name
)
855 typedef HANDLE (WINAPI
* CREATEACTCTXW_PROC
) (PCACTCTXW pActCtx
);
856 typedef BOOL (WINAPI
* ACTIVATEACTCTX_PROC
) (HANDLE hActCtx
, ULONG_PTR
* lpCookie
);
858 HMODULE kernel32_handle
;
859 CREATEACTCTXW_PROC CreateActCtx_proc
;
860 ACTIVATEACTCTX_PROC ActivateActCtx_proc
;
862 gunichar2
* full_path_utf16
;
864 gunichar2
* dir_name_utf16
;
866 gunichar2
* base_name_utf16
;
871 kernel32_handle
= GetModuleHandle (L
"kernel32.dll");
872 if (!kernel32_handle
)
874 CreateActCtx_proc
= (CREATEACTCTXW_PROC
) GetProcAddress (kernel32_handle
, "CreateActCtxW");
875 if (!CreateActCtx_proc
)
877 ActivateActCtx_proc
= (ACTIVATEACTCTX_PROC
) GetProcAddress (kernel32_handle
, "ActivateActCtx");
878 if (!ActivateActCtx_proc
)
881 full_path
= mono_path_canonicalize (file_name
);
882 full_path_utf16
= g_utf8_to_utf16 (full_path
, -1, NULL
, NULL
, NULL
);
883 dir_name
= g_path_get_dirname (full_path
);
884 dir_name_utf16
= g_utf8_to_utf16 (dir_name
, -1, NULL
, NULL
, NULL
);
885 base_name
= g_path_get_basename (full_path
);
886 base_name_utf16
= g_utf8_to_utf16 (base_name
, -1, NULL
, NULL
, NULL
);
891 memset (&act_ctx
, 0, sizeof (ACTCTX
));
892 act_ctx
.cbSize
= sizeof (ACTCTX
);
893 act_ctx
.dwFlags
= ACTCTX_FLAG_SET_PROCESS_DEFAULT
| ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
| ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_APPLICATION_NAME_VALID
;
894 act_ctx
.lpSource
= full_path_utf16
;
895 act_ctx
.lpAssemblyDirectory
= dir_name_utf16
;
896 act_ctx
.lpResourceName
= CREATEPROCESS_MANIFEST_RESOURCE_ID
;
897 act_ctx
.lpApplicationName
= base_name_utf16
;
899 handle
= CreateActCtx_proc (&act_ctx
);
900 if (handle
== INVALID_HANDLE_VALUE
&& GetLastError () == ERROR_SXS_PROCESS_DEFAULT_ALREADY_SET
) {
901 act_ctx
.dwFlags
&= ~ACTCTX_FLAG_SET_PROCESS_DEFAULT
;
902 handle
= CreateActCtx_proc (&act_ctx
);
905 g_free (base_name_utf16
);
906 g_free (dir_name_utf16
);
907 g_free (full_path_utf16
);
909 if (handle
!= INVALID_HANDLE_VALUE
)
910 ActivateActCtx_proc (handle
, &cookie
);
912 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
915 mono_load_coree (const char* exe_file_name
)
917 HMODULE module_handle
;
918 gunichar2
* file_name
;
922 if (coree_module_handle
)
925 if (!init_from_coree
&& exe_file_name
)
926 mono_coree_set_act_ctx (exe_file_name
);
928 /* ntdll.dll loads mscoree.dll from the system32 directory. */
929 required_size
= GetSystemDirectory (NULL
, 0);
930 file_name
= g_new (gunichar2
, required_size
+ 12);
931 size
= GetSystemDirectory (file_name
, required_size
);
932 g_assert (size
< required_size
);
933 if (file_name
[size
- 1] != L
'\\')
934 file_name
[size
++] = L
'\\';
935 memcpy (&file_name
[size
], L
"mscoree.dll", 12 * sizeof (gunichar2
));
937 module_handle
= LoadLibrary (file_name
);
940 if (module_handle
&& !SUCCEEDED (MonoFixupCorEE (module_handle
))) {
941 FreeLibrary (module_handle
);
942 module_handle
= NULL
;
945 coree_module_handle
= module_handle
;
949 mono_fixup_exe_image (MonoImage
* image
)
951 if (!init_from_coree
&& image
&& image
->is_module_handle
)
952 MonoFixupExe ((HMODULE
) image
->raw_data
);
955 #endif /* HOST_WIN32 */