1 /**
2  * \file
3  * mscoree.dll functions
4  *
5  * Author:
6  *   Kornel Pal <http://www.kornelpal.hu/>
7  *
8  * Copyright (C) 2008 Kornel Pal
9  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
10  */
11 
12 #include <config.h>
13 
14 #ifdef HOST_WIN32
15 
16 #include <glib.h>
17 #include <string.h>
18 #include <mono/utils/mono-path.h>
19 #include "utils/w32api.h"
20 #include "cil-coff.h"
21 #include "metadata-internals.h"
22 #include "image.h"
23 #include "assembly-internals.h"
24 #include "domain-internals.h"
25 #include "appdomain.h"
26 #include "object.h"
27 #include "object-internals.h"
28 #include "loader.h"
29 #include "threads.h"
30 #include "environment.h"
31 #include "coree.h"
32 #include "coree-internals.h"
33 
34 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
35 #include <shellapi.h>
36 #endif
37 
38 HMODULE coree_module_handle = NULL;
39 
40 static gboolean init_from_coree = FALSE;
41 
42 gchar*
mono_get_module_file_name(HMODULE module_handle)43 mono_get_module_file_name (HMODULE module_handle)
44 {
45 	gunichar2* file_name;
46 	gchar* file_name_utf8;
47 	DWORD buffer_size;
48 	DWORD size;
49 
50 	buffer_size = 1024;
51 	file_name = g_new (gunichar2, buffer_size);
52 
53 	for (;;) {
54 		size = GetModuleFileName (module_handle, file_name, buffer_size);
55 		if (!size) {
56 			g_free (file_name);
57 			return NULL;
58 		}
59 
60 		g_assert (size <= buffer_size);
61 		if (size != buffer_size)
62 			break;
63 
64 		buffer_size += 1024;
65 		file_name = g_realloc (file_name, buffer_size * sizeof (gunichar2));
66 	}
67 
68 	file_name_utf8 = g_utf16_to_utf8 (file_name, size, NULL, NULL, NULL);
69 	g_free (file_name);
70 
71 	return file_name_utf8;
72 }
73 
74 /* Entry point called by LdrLoadDll of ntdll.dll after _CorValidateImage. */
75 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
_CorDllMain(HINSTANCE hInst,DWORD dwReason,LPVOID lpReserved)76 BOOL STDMETHODCALLTYPE _CorDllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved)
77 {
78 	MonoAssembly* assembly;
79 	MonoImage* image;
80 	gchar* file_name;
81 	gchar* error;
82 
83 	switch (dwReason)
84 	{
85 	case DLL_PROCESS_ATTACH:
86 		DisableThreadLibraryCalls (hInst);
87 
88 		file_name = mono_get_module_file_name (hInst);
89 
90 		if (mono_get_root_domain ()) {
91 			image = mono_image_open_from_module_handle (hInst, mono_path_resolve_symlinks (file_name), TRUE, NULL);
92 		} else {
93 			init_from_coree = TRUE;
94 			mono_runtime_load (file_name, NULL);
95 			error = (gchar*) mono_check_corlib_version ();
96 			if (error) {
97 				g_free (error);
98 				g_free (file_name);
99 				mono_runtime_quit ();
100 				return FALSE;
101 			}
102 
103 			image = mono_image_open (file_name, NULL);
104 			if (image) {
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);
109 			}
110 		}
111 
112 		if (!image) {
113 			g_free (file_name);
114 			return FALSE;
115 		}
116 
117 		/*
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.
121 		 */
122 		if (image->tables [MONO_TABLE_ASSEMBLY].rows && ((MonoCLIImageInfo*) image->image_info)->cli_cli_header.ch_vtable_fixups.rva)
123 			assembly = mono_assembly_open_predicate (file_name, FALSE, FALSE, NULL, NULL, NULL);
124 
125 		g_free (file_name);
126 		break;
127 	case DLL_PROCESS_DETACH:
128 		if (lpReserved != NULL)
129 			/* The process is terminating. */
130 			return TRUE;
131 		file_name = mono_get_module_file_name (hInst);
132 		image = mono_image_loaded (file_name);
133 		if (image)
134 			mono_image_close (image);
135 
136 		g_free (file_name);
137 		break;
138 	}
139 
140 	return TRUE;
141 }
142 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
143 
144 /* Called by ntdll.dll reagardless of entry point after _CorValidateImage. */
145 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
_CorExeMain(void)146 __int32 STDMETHODCALLTYPE _CorExeMain(void)
147 {
148 	MonoError error;
149 	MonoDomain* domain;
150 	MonoAssembly* assembly;
151 	MonoImage* image;
152 	MonoMethod* method;
153 	guint32 entry;
154 	gchar* file_name;
155 	gchar* corlib_version_error;
156 	int argc;
157 	gunichar2** argvw;
158 	gchar** argv;
159 	int i;
160 
161 	file_name = mono_get_module_file_name (NULL);
162 	init_from_coree = TRUE;
163 	domain = mono_runtime_load (file_name, NULL);
164 
165 	corlib_version_error = (gchar*) mono_check_corlib_version ();
166 	if (corlib_version_error) {
167 		g_free (corlib_version_error);
168 		g_free (file_name);
169 		MessageBox (NULL, L"Corlib not in sync with this runtime.", NULL, MB_ICONERROR);
170 		mono_runtime_quit ();
171 		ExitProcess (1);
172 	}
173 
174 	assembly = mono_assembly_open_predicate (file_name, FALSE, FALSE, NULL, NULL, NULL);
175 	mono_close_exe_image ();
176 	if (!assembly) {
177 		g_free (file_name);
178 		MessageBox (NULL, L"Cannot open assembly.", NULL, MB_ICONERROR);
179 		mono_runtime_quit ();
180 		ExitProcess (1);
181 	}
182 
183 	image = assembly->image;
184 	entry = mono_image_get_entry_point (image);
185 	if (!entry) {
186 		g_free (file_name);
187 		MessageBox (NULL, L"Assembly doesn't have an entry point.", NULL, MB_ICONERROR);
188 		mono_runtime_quit ();
189 		ExitProcess (1);
190 	}
191 
192 	method = mono_get_method_checked (image, entry, NULL, NULL, &error);
193 	if (method == NULL) {
194 		g_free (file_name);
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 ();
198 		ExitProcess (1);
199 	}
200 
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);
206 	LocalFree (argvw);
207 
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 ();
211 
212 	mono_runtime_quit ();
213 
214 	/* return does not terminate the process. */
215 	ExitProcess (mono_environment_exitcode_get ());
216 }
217 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
218 
219 /* Called by msvcrt.dll when shutting down. */
CorExitProcess(int exitCode)220 void STDMETHODCALLTYPE CorExitProcess(int exitCode)
221 {
222 	/* FIXME: This is not currently supported by the runtime. */
223 #if 0
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 ();
228 	}
229 #endif
230 	ExitProcess (exitCode);
231 }
232 
233 /* Called by ntdll.dll before _CorDllMain and _CorExeMain. */
234 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
_CorValidateImage(PVOID * ImageBase,LPCWSTR FileName)235 STDAPI _CorValidateImage(PVOID *ImageBase, LPCWSTR FileName)
236 {
237 	IMAGE_DOS_HEADER* DosHeader;
238 	IMAGE_NT_HEADERS32* NtHeaders32;
239 	IMAGE_DATA_DIRECTORY* CliHeaderDir;
240 #ifdef _WIN64
241 	IMAGE_NT_HEADERS64* NtHeaders64;
242 	MonoCLIHeader* CliHeader;
243 	DWORD SizeOfHeaders;
244 #endif
245 	DWORD* Address;
246 	DWORD OldProtect;
247 
248 	DosHeader = (IMAGE_DOS_HEADER*)*ImageBase;
249 	if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
250 		return STATUS_INVALID_IMAGE_FORMAT;
251 
252 	NtHeaders32 = (IMAGE_NT_HEADERS32*)((DWORD_PTR)DosHeader + DosHeader->e_lfanew);
253 	if (NtHeaders32->Signature != IMAGE_NT_SIGNATURE)
254 		return STATUS_INVALID_IMAGE_FORMAT;
255 
256 #ifdef _WIN64
257 	NtHeaders64 = (IMAGE_NT_HEADERS64*)NtHeaders32;
258 	if (NtHeaders64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
259 	{
260 		if (NtHeaders64->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
261 			return STATUS_INVALID_IMAGE_FORMAT;
262 
263 		CliHeaderDir = &NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
264 		if (!CliHeaderDir->VirtualAddress)
265 			return STATUS_INVALID_IMAGE_FORMAT;
266 
267 		CliHeader = (MonoCLIHeader*)((DWORD_PTR)DosHeader + CliHeaderDir->VirtualAddress);
268 		if (CliHeader->ch_flags & CLI_FLAGS_32BITREQUIRED)
269 			return STATUS_INVALID_IMAGE_FORMAT;
270 
271 		if (CliHeader->ch_flags & CLI_FLAGS_ILONLY)
272 		{
273 			/* Avoid calling _CorDllMain because imports are not resolved for IL only images. */
274 			if (NtHeaders64->OptionalHeader.AddressOfEntryPoint != 0)
275 			{
276 				Address = &NtHeaders64->OptionalHeader.AddressOfEntryPoint;
277 				if (!VirtualProtect(Address, sizeof(DWORD), PAGE_READWRITE, &OldProtect))
278 					return E_UNEXPECTED;
279 				*Address = (DWORD)0;
280 				if (!VirtualProtect(Address, sizeof(DWORD), OldProtect, &OldProtect))
281 					return E_UNEXPECTED;
282 			}
283 		}
284 
285 		return STATUS_SUCCESS;
286 	}
287 
288 	if (NtHeaders32->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
289 		return STATUS_INVALID_IMAGE_FORMAT;
290 
291 	if (NtHeaders32->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
292 		return STATUS_INVALID_IMAGE_FORMAT;
293 
294 	CliHeaderDir = &NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
295 	if (!CliHeaderDir->VirtualAddress)
296 		return STATUS_INVALID_IMAGE_FORMAT;
297 
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;
301 
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;
306 
307 	if (!VirtualProtect(DosHeader, SizeOfHeaders, PAGE_READWRITE, &OldProtect))
308 		return E_UNEXPECTED;
309 
310 	memmove(NtHeaders64 + 1, IMAGE_FIRST_SECTION(NtHeaders32), sizeof(IMAGE_SECTION_HEADER) * NtHeaders32->FileHeader.NumberOfSections);
311 
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;
344 
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);
370 
371 	if (!VirtualProtect(DosHeader, SizeOfHeaders, OldProtect, &OldProtect))
372 		return E_UNEXPECTED;
373 #else
374 	if (NtHeaders32->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
375 		return STATUS_INVALID_IMAGE_FORMAT;
376 
377 	if (NtHeaders32->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
378 		return STATUS_INVALID_IMAGE_FORMAT;
379 
380 	CliHeaderDir = &NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
381 	if (!CliHeaderDir->VirtualAddress)
382 		return STATUS_INVALID_IMAGE_FORMAT;
383 
384 	Address = &NtHeaders32->OptionalHeader.AddressOfEntryPoint;
385 	if (!VirtualProtect(Address, sizeof(DWORD), PAGE_READWRITE, &OldProtect))
386 		return E_UNEXPECTED;
387 	if (NtHeaders32->FileHeader.Characteristics & IMAGE_FILE_DLL)
388 		*Address = (DWORD)((DWORD_PTR)&_CorDllMain - (DWORD_PTR)DosHeader);
389 	else
390 		*Address = (DWORD)((DWORD_PTR)&_CorExeMain - (DWORD_PTR)DosHeader);
391 	if (!VirtualProtect(Address, sizeof(DWORD), OldProtect, &OldProtect))
392 		return E_UNEXPECTED;
393 #endif
394 
395 	return STATUS_SUCCESS;
396 }
397 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
398 
399 /* Called by ntdll.dll. */
_CorImageUnloading(PVOID ImageBase)400 STDAPI_(VOID) _CorImageUnloading(PVOID ImageBase)
401 {
402 	/* Nothing to do. */
403 }
404 
CorBindToRuntimeEx(LPCWSTR pwszVersion,LPCWSTR pwszBuildFlavor,DWORD startupFlags,REFCLSID rclsid,REFIID riid,LPVOID FAR * ppv)405 STDAPI CorBindToRuntimeEx(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, DWORD startupFlags, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv)
406 {
407 	if (ppv == NULL)
408 		return E_POINTER;
409 
410 	*ppv = NULL;
411 	return E_NOTIMPL;
412 }
413 
CorBindToRuntime(LPCWSTR pwszVersion,LPCWSTR pwszBuildFlavor,REFCLSID rclsid,REFIID riid,LPVOID FAR * ppv)414 STDAPI CorBindToRuntime(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv)
415 {
416 	return CorBindToRuntimeEx (pwszVersion, pwszBuildFlavor, 0, rclsid, riid, ppv);
417 }
418 
419 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
MonoLoadImage(LPCWSTR FileName)420 HMODULE WINAPI MonoLoadImage(LPCWSTR FileName)
421 {
422 	HANDLE FileHandle;
423 	DWORD FileSize;
424 	HANDLE MapHandle;
425 	IMAGE_DOS_HEADER* DosHeader;
426 	IMAGE_NT_HEADERS32* NtHeaders32;
427 #ifdef _WIN64
428 	IMAGE_NT_HEADERS64* NtHeaders64;
429 #endif
430 	HMODULE ModuleHandle;
431 
432 	FileHandle = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
433 	if (FileHandle == INVALID_HANDLE_VALUE)
434 		return NULL;
435 
436 	FileSize = GetFileSize(FileHandle, NULL);
437 	if (FileSize == INVALID_FILE_SIZE)
438 		goto CloseFile;
439 
440 	MapHandle = CreateFileMapping(FileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
441 	if (MapHandle == NULL)
442 		goto CloseFile;
443 
444 	DosHeader = (IMAGE_DOS_HEADER*)MapViewOfFile(MapHandle, FILE_MAP_READ, 0, 0, 0);
445 	if (DosHeader == NULL)
446 		goto CloseMap;
447 
448 	if (FileSize < sizeof(IMAGE_DOS_HEADER) || DosHeader->e_magic != IMAGE_DOS_SIGNATURE || FileSize < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS32))
449 		goto InvalidImageFormat;
450 
451 	NtHeaders32 = (IMAGE_NT_HEADERS32*)((DWORD_PTR)DosHeader + DosHeader->e_lfanew);
452 	if (NtHeaders32->Signature != IMAGE_NT_SIGNATURE)
453 		goto InvalidImageFormat;
454 
455 #ifdef _WIN64
456 	NtHeaders64 = (IMAGE_NT_HEADERS64*)NtHeaders32;
457 	if (NtHeaders64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
458 	{
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;
463 
464 		goto ValidImage;
465 	}
466 #endif
467 
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)
471 	{
472 InvalidImageFormat:
473 		SetLastError(STATUS_INVALID_IMAGE_FORMAT);
474 		goto UnmapView;
475 	}
476 
477 #ifdef _WIN64
478 ValidImage:
479 #endif
480 	UnmapViewOfFile(DosHeader);
481 	CloseHandle(MapHandle);
482 
483 	ModuleHandle = LoadLibrary(FileName);
484 
485 	CloseHandle(FileHandle);
486 	return ModuleHandle;
487 
488 UnmapView:
489 	UnmapViewOfFile(DosHeader);
490 CloseMap:
491 	CloseHandle(MapHandle);
492 CloseFile:
493 	CloseHandle(FileHandle);
494 	return NULL;
495 }
496 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
497 
498 typedef struct _EXPORT_FIXUP
499 {
500 	LPCSTR Name;
501 	union
502 	{
503 		PVOID Pointer;
504 		DWORD_PTR DWordPtr;
505 		BYTE Bytes[sizeof(PVOID)];
506 #ifdef _M_IA64
507 		PLABEL_DESCRIPTOR* PLabel;
508 #endif
509 	} ProcAddress;
510 } EXPORT_FIXUP;
511 
512 /* Has to be binary ordered. */
513 static const EXPORT_FIXUP ExportFixups[] = {
514 	{"CorBindToRuntime", {&CorBindToRuntime}},
515 	{"CorBindToRuntimeEx", {&CorBindToRuntimeEx}},
516 	{"CorExitProcess", {&CorExitProcess}},
517 	{"_CorDllMain", {&_CorDllMain}},
518 	{"_CorExeMain", {&_CorExeMain}},
519 	{"_CorImageUnloading", {&_CorImageUnloading}},
520 	{"_CorValidateImage", {&_CorValidateImage}},
521 	{NULL, {NULL}}
522 };
523 
524 #define EXPORT_FIXUP_COUNT (sizeof(ExportFixups) / sizeof(EXPORT_FIXUP) - 1)
525 
526 static HMODULE ExportFixupModuleHandle = NULL;
527 static DWORD ExportFixupRvas[EXPORT_FIXUP_COUNT];
528 
529 /* Fixup exported functions of mscoree.dll to our implementations. */
MonoFixupCorEE(HMODULE ModuleHandle)530 STDAPI MonoFixupCorEE(HMODULE ModuleHandle)
531 {
532 	IMAGE_DOS_HEADER* DosHeader;
533 	IMAGE_NT_HEADERS* NtHeaders;
534 	IMAGE_DATA_DIRECTORY* ExportDataDir;
535 	IMAGE_EXPORT_DIRECTORY* ExportDir;
536 	DWORD* Functions;
537 	DWORD* Names;
538 	WORD* NameOrdinals;
539 	EXPORT_FIXUP* ExportFixup;
540 	DWORD* ExportFixupRva;
541 	DWORD* Address;
542 	DWORD OldProtect;
543 	DWORD ProcRva;
544 	DWORD i;
545 	int cmp;
546 #ifdef _WIN64
547 	MEMORY_BASIC_INFORMATION MemoryInfo;
548 	PVOID Region;
549 	PVOID RegionBase;
550 	PVOID MaxRegionBase;
551 #ifdef _M_IA64
552 	PLABEL_DESCRIPTOR* PLabel;
553 
554 #define ELEMENT_SIZE sizeof(PLABEL_DESCRIPTOR)
555 #define REGION_WRITE_PROTECT PAGE_READWRITE
556 #define REGION_PROTECT PAGE_READ
557 #else
558 	BYTE* Trampoline;
559 
560 #define ELEMENT_SIZE 13
561 #define REGION_WRITE_PROTECT PAGE_EXECUTE_READWRITE
562 #define REGION_PROTECT PAGE_EXECUTE_READ
563 #endif
564 #endif
565 
566 	if (ExportFixupModuleHandle != NULL)
567 		return ModuleHandle == ExportFixupModuleHandle ? S_OK : E_FAIL;
568 
569 	DosHeader = (IMAGE_DOS_HEADER*)ModuleHandle;
570 	if (DosHeader == NULL)
571 		return E_POINTER;
572 
573 	if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
574 		return E_INVALIDARG;
575 
576 	NtHeaders = (IMAGE_NT_HEADERS*)((DWORD_PTR)DosHeader + DosHeader->e_lfanew);
577 	if (NtHeaders->Signature != IMAGE_NT_SIGNATURE)
578 		return E_INVALIDARG;
579 
580 	if (NtHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
581 		return E_INVALIDARG;
582 
583 	if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_EXPORT)
584 		return E_FAIL;
585 
586 	ExportDataDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
587 	if (!ExportDataDir->VirtualAddress)
588 		return E_FAIL;
589 
590 #ifdef _WIN64
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))));
594 	for (;;)
595 	{
596 		if (!VirtualQuery(RegionBase, &MemoryInfo, sizeof(MEMORY_BASIC_INFORMATION)))
597 			return E_UNEXPECTED;
598 		if (MemoryInfo.State == MEM_FREE && MemoryInfo.RegionSize >= ELEMENT_SIZE * EXPORT_FIXUP_COUNT)
599 		{
600 			Region = VirtualAlloc(RegionBase, ELEMENT_SIZE * EXPORT_FIXUP_COUNT, MEM_COMMIT | MEM_RESERVE, REGION_WRITE_PROTECT);
601 			if (Region != NULL)
602 				break;
603 		}
604 		RegionBase = (PVOID)((DWORD_PTR)MemoryInfo.BaseAddress + (DWORD_PTR)MemoryInfo.RegionSize);
605 		if (RegionBase > MaxRegionBase)
606 			return E_OUTOFMEMORY;
607 	}
608 
609 #ifdef _M_IA64
610 	PLabel = (PLABEL_DESCRIPTOR*)Region;
611 #else
612 	Trampoline = (BYTE*)Region;
613 #endif
614 #endif
615 
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;
622 
623 	for (i = 0; i < ExportDir->NumberOfNames; i++)
624 	{
625 		cmp = strcmp((LPCSTR)((DWORD_PTR)DosHeader + Names[i]), ExportFixup->Name);
626 		if (cmp > 0)
627 			return E_FAIL;
628 
629 		if (cmp == 0)
630 		{
631 #ifdef _WIN64
632 #if defined(_M_IA64)
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];
648 			/* jmp r11 */
649 			*(Trampoline)++ = 0x41;
650 			*(Trampoline)++ = 0xFF;
651 			*(Trampoline)++ = 0xE3;
652 #else
653 #error Unsupported architecture.
654 #endif
655 #else
656 			ProcRva = (DWORD)(ExportFixup->ProcAddress.DWordPtr - (DWORD_PTR)DosHeader);
657 #endif
658 			Address = &Functions[NameOrdinals[i]];
659 			if (!VirtualProtect(Address, sizeof(DWORD), PAGE_READWRITE, &OldProtect))
660 				return E_UNEXPECTED;
661 			*ExportFixupRva = *Address;
662 			*Address = ProcRva;
663 			if (!VirtualProtect(Address, sizeof(DWORD), OldProtect, &OldProtect))
664 				return E_UNEXPECTED;
665 			ExportFixup++;
666 			if (ExportFixup->Name == NULL) {
667 #ifdef _WIN64
668 				if (!VirtualProtect(Region, ELEMENT_SIZE * EXPORT_FIXUP_COUNT, REGION_PROTECT, &OldProtect))
669 					return E_UNEXPECTED;
670 #endif
671 
672 				ExportFixupModuleHandle = ModuleHandle;
673 				return S_OK;
674 			}
675 			ExportFixupRva++;
676 		}
677 	}
678 	return E_FAIL;
679 }
680 
681 /* Executable images are only mapped by the OS loader. We need to do fixups for native code support. */
MonoFixupExe(HMODULE ModuleHandle)682 STDAPI MonoFixupExe(HMODULE ModuleHandle)
683 {
684 	IMAGE_DOS_HEADER* DosHeader;
685 	IMAGE_NT_HEADERS* NtHeaders;
686 	DWORD_PTR* Address;
687 	DWORD OldProtect;
688 	DWORD_PTR BaseDiff;
689 
690 	DosHeader = (IMAGE_DOS_HEADER*)ModuleHandle;
691 	if (DosHeader == NULL)
692 		return E_POINTER;
693 
694 	if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
695 		return E_INVALIDARG;
696 
697 	NtHeaders = (IMAGE_NT_HEADERS*)((DWORD_PTR)DosHeader + DosHeader->e_lfanew);
698 	if (NtHeaders->Signature != IMAGE_NT_SIGNATURE)
699 		return E_INVALIDARG;
700 
701 	if (NtHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
702 		return E_INVALIDARG;
703 
704 	if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
705 		return S_OK;
706 
707 	if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
708 	{
709 		IMAGE_DATA_DIRECTORY* CliHeaderDir;
710 		MonoCLIHeader* CliHeader;
711 
712 		CliHeaderDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
713 		if (CliHeaderDir->VirtualAddress)
714 		{
715 			CliHeader = (MonoCLIHeader*)((DWORD_PTR)DosHeader + CliHeaderDir->VirtualAddress);
716 			if (CliHeader->ch_flags & CLI_FLAGS_ILONLY)
717 				return S_OK;
718 		}
719 	}
720 
721 	BaseDiff = (DWORD_PTR)DosHeader - NtHeaders->OptionalHeader.ImageBase;
722 	if (BaseDiff != 0)
723 	{
724 		if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
725 			return E_FAIL;
726 
727 		Address = &NtHeaders->OptionalHeader.ImageBase;
728 		if (!VirtualProtect(Address, sizeof(DWORD_PTR), PAGE_READWRITE, &OldProtect))
729 			return E_UNEXPECTED;
730 		*Address = (DWORD_PTR)DosHeader;
731 		if (!VirtualProtect(Address, sizeof(DWORD_PTR), OldProtect, &OldProtect))
732 			return E_UNEXPECTED;
733 
734 		if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_BASERELOC)
735 		{
736 			IMAGE_DATA_DIRECTORY* BaseRelocDir;
737 			IMAGE_BASE_RELOCATION* BaseReloc;
738 			USHORT* RelocBlock;
739 			ULONG BaseRelocSize;
740 			ULONG RelocBlockSize;
741 			USHORT RelocOffset;
742 			DWORD_PTR UNALIGNED *RelocFixup;
743 
744 			BaseRelocDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
745 			if (BaseRelocDir->VirtualAddress)
746 			{
747 				BaseReloc = (IMAGE_BASE_RELOCATION*)((DWORD_PTR)DosHeader + BaseRelocDir->VirtualAddress);
748 				BaseRelocSize = BaseRelocDir->Size;
749 
750 				while (BaseRelocSize)
751 				{
752 					RelocBlockSize = BaseReloc->SizeOfBlock;
753 
754 					if (!RelocBlockSize || BaseRelocSize < RelocBlockSize)
755 						return E_FAIL;
756 
757 					BaseRelocSize -= RelocBlockSize;
758 					RelocBlock = (USHORT*)((DWORD_PTR)BaseReloc + sizeof(IMAGE_BASE_RELOCATION));
759 					RelocBlockSize -= sizeof(IMAGE_BASE_RELOCATION);
760 					RelocBlockSize /= sizeof(USHORT);
761 
762 					while (RelocBlockSize-- != 0)
763 					{
764 						RelocOffset = *RelocBlock & (USHORT)0x0fff;
765 						RelocFixup = (DWORD_PTR*)((DWORD_PTR)DosHeader + BaseReloc->VirtualAddress + RelocOffset);
766 
767 						switch (*RelocBlock >> 12)
768 						{
769 							case IMAGE_REL_BASED_ABSOLUTE:
770 								break;
771 
772 #ifdef _WIN64
773 							case IMAGE_REL_BASED_DIR64:
774 #else
775 							case IMAGE_REL_BASED_HIGHLOW:
776 #endif
777 								if (!VirtualProtect(RelocFixup, sizeof(DWORD_PTR), PAGE_EXECUTE_READWRITE, &OldProtect))
778 									return E_UNEXPECTED;
779 								*RelocFixup += BaseDiff;
780 								if (!VirtualProtect(RelocFixup, sizeof(DWORD_PTR), OldProtect, &OldProtect))
781 									return E_UNEXPECTED;
782 								break;
783 
784 							default:
785 								return E_FAIL;
786 						}
787 
788 						RelocBlock++;
789 					}
790 					BaseReloc = (IMAGE_BASE_RELOCATION*)RelocBlock;
791 				}
792 			}
793 		}
794 	}
795 
796 	if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_IMPORT)
797 	{
798 		IMAGE_DATA_DIRECTORY* ImportDir;
799 		IMAGE_IMPORT_DESCRIPTOR* ImportDesc;
800 		HMODULE ImportModuleHandle;
801 		IMAGE_THUNK_DATA* ImportThunkData;
802 		DWORD_PTR ProcAddress;
803 
804 		ImportDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
805 		if (ImportDir->VirtualAddress != 0)
806 		{
807 			ImportDesc = (IMAGE_IMPORT_DESCRIPTOR*)((DWORD_PTR)DosHeader + ImportDir->VirtualAddress);
808 			while (ImportDesc->Name && ImportDesc->OriginalFirstThunk)
809 			{
810 				gchar *file_utf8 = (gchar *)((DWORD_PTR)DosHeader + ImportDesc->Name);
811 
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);
816 					g_free (file_utf16);
817 				}
818 
819 				if (ImportModuleHandle == NULL)
820 					return E_FAIL;
821 
822 				ImportThunkData = (IMAGE_THUNK_DATA*)((DWORD_PTR)DosHeader + ImportDesc->OriginalFirstThunk);
823 				while (ImportThunkData->u1.Ordinal != 0)
824 				{
825 					if (IMAGE_SNAP_BY_ORDINAL(ImportThunkData->u1.Ordinal))
826 						ProcAddress = (DWORD_PTR)GetProcAddress(ImportModuleHandle, (LPCSTR)IMAGE_ORDINAL(ImportThunkData->u1.Ordinal));
827 					else
828 					{
829 						IMAGE_IMPORT_BY_NAME* ImportByName = (IMAGE_IMPORT_BY_NAME*)((DWORD_PTR)DosHeader + ImportThunkData->u1.AddressOfData);
830 						ProcAddress = (DWORD_PTR)GetProcAddress(ImportModuleHandle, ImportByName->Name);
831 					}
832 					if (ProcAddress == 0)
833 						return E_FAIL;
834 					Address = (DWORD_PTR*)((DWORD_PTR)ImportThunkData - ImportDesc->OriginalFirstThunk + ImportDesc->FirstThunk);
835 					if (!VirtualProtect(Address, sizeof(DWORD_PTR), PAGE_READWRITE, &OldProtect))
836 						return E_UNEXPECTED;
837 					*Address = ProcAddress;
838 					if (!VirtualProtect(Address, sizeof(DWORD_PTR), OldProtect, &OldProtect))
839 						return E_UNEXPECTED;
840 					ImportThunkData++;
841 				}
842 
843 				ImportDesc++;
844 			}
845 		}
846 	}
847 
848 	return S_OK;
849 }
850 
851 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
852 void
mono_coree_set_act_ctx(const char * file_name)853 mono_coree_set_act_ctx (const char* file_name)
854 {
855 	typedef HANDLE (WINAPI* CREATEACTCTXW_PROC) (PCACTCTXW pActCtx);
856 	typedef BOOL (WINAPI* ACTIVATEACTCTX_PROC) (HANDLE hActCtx, ULONG_PTR* lpCookie);
857 
858 	HMODULE kernel32_handle;
859 	CREATEACTCTXW_PROC CreateActCtx_proc;
860 	ACTIVATEACTCTX_PROC ActivateActCtx_proc;
861 	gchar* full_path;
862 	gunichar2* full_path_utf16;
863 	gchar* dir_name;
864 	gunichar2* dir_name_utf16;
865 	gchar* base_name;
866 	gunichar2* base_name_utf16;
867 	ACTCTX act_ctx;
868 	HANDLE handle;
869 	ULONG_PTR cookie;
870 
871 	kernel32_handle = GetModuleHandle (L"kernel32.dll");
872 	if (!kernel32_handle)
873 		return;
874 	CreateActCtx_proc = (CREATEACTCTXW_PROC) GetProcAddress (kernel32_handle, "CreateActCtxW");
875 	if (!CreateActCtx_proc)
876 		return;
877 	ActivateActCtx_proc = (ACTIVATEACTCTX_PROC) GetProcAddress (kernel32_handle, "ActivateActCtx");
878 	if (!ActivateActCtx_proc)
879 		return;
880 
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);
887 	g_free (base_name);
888 	g_free (dir_name);
889 	g_free (full_path);
890 
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 = MAKEINTRESOURCE (CREATEPROCESS_MANIFEST_RESOURCE_ID);
897 	act_ctx.lpApplicationName = base_name_utf16;
898 
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);
903 	}
904 
905 	g_free (base_name_utf16);
906 	g_free (dir_name_utf16);
907 	g_free (full_path_utf16);
908 
909 	if (handle != INVALID_HANDLE_VALUE)
910 		ActivateActCtx_proc (handle, &cookie);
911 }
912 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
913 
914 void
mono_load_coree(const char * exe_file_name)915 mono_load_coree (const char* exe_file_name)
916 {
917 	HMODULE module_handle;
918 	gunichar2* file_name;
919 	UINT required_size;
920 	UINT size;
921 
922 	if (coree_module_handle)
923 		return;
924 
925 	if (!init_from_coree && exe_file_name)
926 		mono_coree_set_act_ctx (exe_file_name);
927 
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));
936 
937 	module_handle = LoadLibrary (file_name);
938 	g_free (file_name);
939 
940 	if (module_handle && !SUCCEEDED (MonoFixupCorEE (module_handle))) {
941 		FreeLibrary (module_handle);
942 		module_handle = NULL;
943 	}
944 
945 	coree_module_handle = module_handle;
946 }
947 
948 void
mono_fixup_exe_image(MonoImage * image)949 mono_fixup_exe_image (MonoImage* image)
950 {
951 	if (!init_from_coree && image && image->is_module_handle)
952 		MonoFixupExe ((HMODULE) image->raw_data);
953 }
954 
955 #endif /* HOST_WIN32 */
956