2 #include <mono/utils/mono-compiler.h>
7 #include "mini-runtime.h"
8 #include <mono/metadata/assembly.h>
9 #include <mono/metadata/assembly-internals.h>
10 #include <mono/metadata/environment.h>
11 #include <mono/metadata/loader-internals.h>
12 #include <mono/utils/mono-logger-internals.h>
14 #ifndef STDAPICALLTYPE
15 #define STDAPICALLTYPE
18 #if defined(_MSC_VER) && defined(HOST_WIN32) && defined(HOST_X86)
19 // Ensure that the exported symbols are not decorated and that only one set is exported
20 #pragma comment(linker, "/export:coreclr_initialize=_coreclr_initialize@28")
21 #pragma comment(linker, "/export:coreclr_execute_assembly=_coreclr_execute_assembly@24")
22 #pragma comment(linker, "/export:coreclr_shutdown_2=_coreclr_shutdown_2@12")
23 #pragma comment(linker, "/export:coreclr_create_delegate=_coreclr_create_delegate@24")
25 #define MONO_API MONO_EXTERN_C
28 MONO_API
int STDAPICALLTYPE
coreclr_initialize (const char* exePath
, const char* appDomainFriendlyName
,
29 int propertyCount
, const char** propertyKeys
, const char** propertyValues
,
30 void** hostHandle
, unsigned int* domainId
);
32 MONO_API
int STDAPICALLTYPE
coreclr_execute_assembly (void* hostHandle
, unsigned int domainId
,
33 int argc
, const char** argv
,
34 const char* managedAssemblyPath
, unsigned int* exitCode
);
36 MONO_API
int STDAPICALLTYPE
coreclr_shutdown_2 (void* hostHandle
, unsigned int domainId
, int* latchedExitCode
);
38 MONO_API
int STDAPICALLTYPE
coreclr_create_delegate (void* hostHandle
, unsigned int domainId
,
39 const char* entryPointAssemblyName
, const char* entryPointTypeName
, const char* entryPointMethodName
,
44 char **basenames
; /* Foo.dll */
45 char **assembly_filepaths
; /* /blah/blah/blah/Foo.dll */
46 } MonoCoreTrustedPlatformAssemblies
;
51 } MonoCoreNativeLibPaths
;
53 static MonoCoreTrustedPlatformAssemblies
*trusted_platform_assemblies
;
54 static MonoCoreNativeLibPaths
*native_lib_paths
;
57 mono_core_trusted_platform_assemblies_free (MonoCoreTrustedPlatformAssemblies
*a
)
61 g_strfreev (a
->basenames
);
62 g_strfreev (a
->assembly_filepaths
);
67 mono_core_native_lib_paths_free (MonoCoreNativeLibPaths
*dl
)
71 g_strfreev (dl
->dirs
);
76 parse_trusted_platform_assemblies (const char *assemblies_paths
)
79 // https://docs.microsoft.com/en-us/dotnet/core/tutorials/netcore-hosting#step-3---prepare-runtime-properties
80 // this is ';' separated on Windows and ':' separated elsewhere.
81 char **parts
= g_strsplit (assemblies_paths
, G_SEARCHPATH_SEPARATOR_S
, 0);
83 for (char **p
= parts
; *p
!= NULL
&& **p
!= '\0'; p
++) {
85 const char *part
= *p
;
86 // can't use logger, it's not initialized yet.
87 printf ("\t\tassembly %d = <%s>\n", asm_count
, part
);
91 MonoCoreTrustedPlatformAssemblies
*a
= g_new0 (MonoCoreTrustedPlatformAssemblies
, 1);
92 a
->assembly_count
= asm_count
;
93 a
->assembly_filepaths
= parts
;
94 a
->basenames
= g_new0 (char*, asm_count
+ 1);
95 for (int i
= 0; i
< asm_count
; ++i
) {
96 a
->basenames
[i
] = g_path_get_basename (a
->assembly_filepaths
[i
]);
98 a
->basenames
[asm_count
] = NULL
;
100 trusted_platform_assemblies
= a
;
105 parse_native_dll_search_directories (const char *native_dlls_dirs
)
107 char **parts
= g_strsplit (native_dlls_dirs
, G_SEARCHPATH_SEPARATOR_S
, 0);
109 for (char **p
= parts
; *p
!= NULL
&& **p
!= '\0'; p
++) {
111 const char *part
= *p
;
112 // can't use logger, it's not initialized yet.
113 printf ("\t\tnative search dir %d = <%s>\n", dir_count
, part
);
117 MonoCoreNativeLibPaths
*dl
= g_new0 (MonoCoreNativeLibPaths
, 1);
119 dl
->dir_count
= dir_count
;
121 native_lib_paths
= dl
;
126 mono_core_preload_hook (MonoAssemblyLoadContext
*alc
, MonoAssemblyName
*aname
, char **assemblies_path
, gboolean refonly
, gpointer user_data
, MonoError
*error
)
128 MonoAssembly
*result
= NULL
;
129 MonoCoreTrustedPlatformAssemblies
*a
= (MonoCoreTrustedPlatformAssemblies
*)user_data
;
130 /* TODO: check that CoreCLR wants the strong name semantics here */
131 MonoAssemblyCandidatePredicate predicate
= &mono_assembly_candidate_predicate_sn_same_name
;
132 void* predicate_ud
= aname
;
135 g_assert (aname
->name
);
136 /* alc might be a user ALC - we get here from alc.LoadFromAssemblyName(), but we should load TPA assemblies into the default alc */
137 MonoAssemblyLoadContext
*default_alc
= mono_domain_default_alc (mono_alc_domain (alc
));
139 char *basename
= g_strconcat (aname
->name
, ".dll", (const char*)NULL
); /* TODO: make sure CoreCLR never needs to load .exe files */
141 for (int i
= 0; i
< a
->assembly_count
; ++i
) {
142 if (!strcmp (basename
, a
->basenames
[i
])) {
143 MonoAssemblyOpenRequest req
;
144 mono_assembly_request_prepare_open (&req
, refonly
? MONO_ASMCTX_REFONLY
: MONO_ASMCTX_DEFAULT
, default_alc
);
145 req
.request
.predicate
= predicate
;
146 req
.request
.predicate_ud
= predicate_ud
;
148 const char *fullpath
= a
->assembly_filepaths
[i
];
150 gboolean found
= g_file_test (fullpath
, G_FILE_TEST_IS_REGULAR
);
153 MonoImageOpenStatus status
;
154 result
= mono_assembly_request_open (fullpath
, &req
, &status
);
155 /* TODO: do something with the status at the end? */
165 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_ASSEMBLY
, "netcore preload hook: did not find '%s'.", aname
->name
);
167 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_ASSEMBLY
, "netcore preload hook: loading '%s' from '%s'.", aname
->name
, result
->image
->name
);
173 install_assembly_loader_hooks (void)
175 mono_install_assembly_preload_hook_v2 (mono_core_preload_hook
, (void*)trusted_platform_assemblies
, FALSE
);
179 parse_properties (int propertyCount
, const char** propertyKeys
, const char** propertyValues
)
181 // The a partial list of relevant properties is
182 // https://docs.microsoft.com/en-us/dotnet/core/tutorials/netcore-hosting#step-3---prepare-runtime-properties
183 // TODO: We should also pick up at least APP_PATHS and APP_NI_PATHS
184 // and PLATFORM_RESOURCE_ROOTS for satellite assemblies in culture-specific subdirectories
186 for (int i
= 0; i
< propertyCount
; ++i
) {
187 if (!strcmp (propertyKeys
[i
], "TRUSTED_PLATFORM_ASSEMBLIES")) {
188 parse_trusted_platform_assemblies (propertyValues
[i
]);
189 } else if (!strcmp (propertyKeys
[i
], "NATIVE_DLL_SEARCH_DIRECTORIES")) {
190 parse_native_dll_search_directories (propertyValues
[i
]);
191 } else if (!strcmp (propertyKeys
[i
], "System.Globalization.Invariant")) {
192 // TODO: Ideally we should propagate this through AppContext options
193 g_setenv ("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", propertyValues
[i
], TRUE
);
196 // can't use mono logger, it's not initialized yet.
197 printf ("\t Unprocessed property %03d '%s': <%s>\n", i
, propertyKeys
[i
], propertyValues
[i
]);
205 // Initialize the CoreCLR. Creates and starts CoreCLR host and creates an app domain
208 // exePath - Absolute path of the executable that invoked the ExecuteAssembly
209 // appDomainFriendlyName - Friendly name of the app domain that will be created to execute the assembly
210 // propertyCount - Number of properties (elements of the following two arguments)
211 // propertyKeys - Keys of properties of the app domain
212 // propertyValues - Values of properties of the app domain
213 // hostHandle - Output parameter, handle of the created host
214 // domainId - Output parameter, id of the created app domain
217 // HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
219 int STDAPICALLTYPE
coreclr_initialize (const char* exePath
, const char* appDomainFriendlyName
,
220 int propertyCount
, const char** propertyKeys
, const char** propertyValues
,
221 void** hostHandle
, unsigned int* domainId
)
223 mono_runtime_register_appctx_properties (propertyCount
, propertyKeys
, propertyValues
);
225 // TODO: TRUSTED_PLATFORM_ASSEMBLIES is the property key for managed assemblies mapping
226 if (!parse_properties (propertyCount
, propertyKeys
, propertyValues
))
227 return 0x80004005; /* E_FAIL */
229 install_assembly_loader_hooks ();
230 if (native_lib_paths
!= NULL
)
231 mono_set_pinvoke_search_directories (native_lib_paths
->dir_count
, native_lib_paths
->dirs
);
234 * Don't use Mono's legacy assembly name matching behavior - respect
235 * the requested version and culture.
237 mono_loader_set_strict_assembly_name_check (TRUE
);
244 // Execute a managed assembly with given arguments
247 // hostHandle - Handle of the host
248 // domainId - Id of the domain
249 // argc - Number of arguments passed to the executed assembly
250 // argv - Array of arguments passed to the executed assembly
251 // managedAssemblyPath - Path of the managed assembly to execute (or NULL if using a custom entrypoint).
252 // exitCode - Exit code returned by the executed assembly
255 // HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
257 int STDAPICALLTYPE
coreclr_execute_assembly (void* hostHandle
, unsigned int domainId
,
258 int argc
, const char** argv
,
259 const char* managedAssemblyPath
, unsigned int* exitCode
)
261 if (exitCode
== NULL
)
267 // Make room for program name and executable assembly
269 int mono_argc
= argc
+ 2;
271 char **mono_argv
= (char **) malloc (sizeof (char *) * (mono_argc
+ 1 /* null terminated */));
272 const char **ptr
= (const char **) mono_argv
;
276 // executable assembly
277 *ptr
++ = (char*) managedAssemblyPath
;
280 for (int i
= 0; i
< argc
; ++i
)
285 mono_parse_env_options (&mono_argc
, &mono_argv
);
287 // TODO: Should be return code of Main only (mono_jit_exec result)
288 *exitCode
= mono_main (mono_argc
, mono_argv
);
294 // Shutdown CoreCLR. It unloads the app domain and stops the CoreCLR host.
297 // hostHandle - Handle of the host
298 // domainId - Id of the domain
299 // latchedExitCode - Latched exit code after domain unloaded
302 // HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
304 int STDAPICALLTYPE
coreclr_shutdown_2 (void* hostHandle
, unsigned int domainId
, int* latchedExitCode
)
306 mono_set_pinvoke_search_directories (0, NULL
);
307 MonoCoreNativeLibPaths
*dl
= native_lib_paths
;
308 native_lib_paths
= NULL
;
309 mono_core_native_lib_paths_free (dl
);
311 MonoCoreTrustedPlatformAssemblies
*a
= trusted_platform_assemblies
;
312 trusted_platform_assemblies
= NULL
;
313 mono_core_trusted_platform_assemblies_free (a
);
315 *latchedExitCode
= mono_environment_exitcode_get ();
321 // Create a native callable delegate for a managed method.
324 // hostHandle - Handle of the host
325 // domainId - Id of the domain
326 // entryPointAssemblyName - Name of the assembly which holds the custom entry point
327 // entryPointTypeName - Name of the type which holds the custom entry point
328 // entryPointMethodName - Name of the method which is the custom entry point
329 // delegate - Output parameter, the function stores a pointer to the delegate at the specified address
332 // HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
334 int STDAPICALLTYPE
coreclr_create_delegate (void* hostHandle
, unsigned int domainId
,
335 const char* entryPointAssemblyName
, const char* entryPointTypeName
, const char* entryPointMethodName
,
338 g_error ("Not implemented");
343 MONO_EMPTY_SOURCE_FILE (main_core
);
344 #endif // ENABLE_NETCORE