2 * appdomain.c: AppDomain functions
5 * Dietmar Maurer (dietmar@ximian.com)
7 * (C) 2001 Ximian, Inc.
18 #include <mono/metadata/object.h>
19 #include <mono/metadata/appdomain.h>
20 #include <mono/metadata/assembly.h>
21 #include <mono/metadata/exception.h>
22 #include <mono/metadata/threads.h>
23 #include <mono/metadata/socket-io.h>
24 #include <mono/metadata/cil-coff.h>
26 HANDLE mono_delegate_semaphore = NULL;
27 CRITICAL_SECTION mono_delegate_section;
28 int mono_runtime_shutdown = 0;
32 * @domain: domain returned by mono_init ()
34 * Initialize the core AppDomain: this function will run also some
35 * IL initialization code, so it needs the execution engine to be fully
39 mono_runtime_init (MonoDomain *domain, MonoThreadStartCB start_cb)
41 MonoAppDomainSetup *setup;
45 class = mono_class_from_name (mono_defaults.corlib, "System", "AppDomainSetup");
46 setup = (MonoAppDomainSetup *) mono_object_new (domain, class);
47 ves_icall_System_AppDomainSetup_InitAppDomainSetup (setup);
49 class = mono_class_from_name (mono_defaults.corlib, "System", "AppDomain");
50 ad = (MonoAppDomain *) mono_object_new (domain, class);
53 domain->setup = setup;
55 mono_delegate_semaphore = CreateSemaphore (NULL, 0, 0x7fffffff, NULL);
56 g_assert (mono_delegate_semaphore != INVALID_HANDLE_VALUE);
57 InitializeCriticalSection (&mono_delegate_section);
59 mono_thread_init (domain, start_cb);
67 mono_runtime_cleanup (MonoDomain *domain)
69 mono_runtime_shutdown = 1;
71 /* signal all waiters in order to stop all workers (max. 0xffff) */
72 ReleaseSemaphore (mono_delegate_semaphore, 0xffff, NULL);
74 mono_thread_cleanup ();
76 /* Do this after the thread cleanup, because subthreads might
77 * still be doing socket calls.
79 mono_network_cleanup ();
83 ves_icall_System_AppDomainSetup_InitAppDomainSetup (MonoAppDomainSetup *setup)
85 /* FIXME: implement me */
89 * mono_domain_transfer_object:
90 * @src: the source domain
91 * @dst: the destination domain
92 * @obj: the object to transfer
94 * This function is used to transfer objects between domains. This is done by
95 * marshalling or serialisation.
98 mono_domain_transfer_object (MonoDomain *src, MonoDomain *dst, MonoObject *obj)
106 g_assert (obj->vtable->domain == src);
108 /* fixme: transfer an object from one domain into another */
110 klass = obj->vtable->klass;
112 if (MONO_CLASS_IS_ARRAY (klass)) {
113 MonoArray *ao = (MonoArray *)obj;
114 int esize, ecount, i;
117 esize = mono_array_element_size (klass);
118 if (ao->bounds == NULL) {
119 ecount = mono_array_length (ao);
120 res = (MonoObject *)mono_array_new_full (dst, klass, &ecount, NULL);
123 sizes = alloca (klass->rank * sizeof(guint32) * 2);
125 for (i = 0; i < klass->rank; ++i) {
126 sizes [i] = ao->bounds [i].length;
127 ecount *= ao->bounds [i].length;
128 sizes [i + klass->rank] = ao->bounds [i].lower_bound;
130 res = (MonoObject *)mono_array_new_full (dst, klass, sizes, sizes + klass->rank);
132 if (klass->element_class->valuetype) {
133 memcpy (res, (char *)ao + sizeof(MonoArray), esize * ecount);
135 g_assert (esize == sizeof (gpointer));
136 for (i = 0; i < ecount; i++) {
137 int offset = sizeof (MonoArray) + esize * i;
138 gpointer *src_ea = (gpointer *)((char *)ao + offset);
139 gpointer *dst_ea = (gpointer *)((char *)res + offset);
141 *dst_ea = mono_domain_transfer_object (src, dst, *src_ea);
144 } else if (klass == mono_defaults.string_class) {
145 MonoString *str = (MonoString *)obj;
146 res = (MonoObject *)mono_string_new_utf16 (dst,
147 (const guint16 *)mono_string_chars (str), str->length);
149 /* FIXME: we need generic marshalling code here */
150 g_assert_not_reached ();
157 ves_icall_System_AppDomain_GetData (MonoAppDomain *ad, MonoString *name)
159 MonoDomain *add = ad->data;
160 MonoDomain *cur = mono_domain_get ();
164 g_assert (ad != NULL);
165 g_assert (name != NULL);
167 str = mono_string_to_utf8 (name);
169 mono_domain_lock (add);
170 if (!strcmp (str, "APPBASE"))
171 o = (MonoObject *)add->setup->application_base;
172 else if (!strcmp (str, "APP_CONFIG_FILE"))
173 o = (MonoObject *)add->setup->configuration_file;
174 else if (!strcmp (str, "DYNAMIC_BASE"))
175 o = (MonoObject *)add->setup->dynamic_base;
176 else if (!strcmp (str, "APP_NAME"))
177 o = (MonoObject *)add->setup->application_name;
178 else if (!strcmp (str, "CACHE_BASE"))
179 o = (MonoObject *)add->setup->cache_path;
180 else if (!strcmp (str, "PRIVATE_BINPATH"))
181 o = (MonoObject *)add->setup->private_bin_path;
182 else if (!strcmp (str, "BINPATH_PROBE_ONLY"))
183 o = (MonoObject *)add->setup->private_bin_path_probe;
184 else if (!strcmp (str, "SHADOW_COPY_DIRS"))
185 o = (MonoObject *)add->setup->shadow_copy_directories;
186 else if (!strcmp (str, "FORCE_CACHE_INSTALL"))
187 o = (MonoObject *)add->setup->shadow_copy_files;
189 o = g_hash_table_lookup (add->env, str);
191 mono_domain_unlock (add);
197 return mono_domain_transfer_object (add, cur, o);
201 ves_icall_System_AppDomain_SetData (MonoAppDomain *ad, MonoString *name, MonoObject *data)
203 MonoDomain *add = ad->data;
204 MonoDomain *cur = mono_domain_get ();
208 g_assert (ad != NULL);
209 g_assert (name != NULL);
211 o = mono_domain_transfer_object (cur, add, data);
213 /* fixme: need a hash func for MonoString */
214 str = mono_string_to_utf8 (name);
215 mono_domain_lock (add);
216 g_hash_table_insert (add->env, str, o);
217 mono_domain_unlock (add);
222 ves_icall_System_AppDomain_getSetup (MonoAppDomain *ad)
224 g_assert (ad != NULL);
225 g_assert (ad->data != NULL);
227 return ad->data->setup;
231 ves_icall_System_AppDomain_getFriendlyName (MonoAppDomain *ad)
233 g_assert (ad != NULL);
234 g_assert (ad->data != NULL);
236 return mono_string_new (ad->data, ad->data->friendly_name);
240 ves_icall_System_AppDomain_getCurDomain ()
242 MonoDomain *add = mono_domain_get ();
247 ves_icall_System_AppDomain_createDomain (MonoString *friendly_name, MonoAppDomainSetup *setup)
249 MonoDomain *domain = mono_domain_get ();
254 adclass = mono_class_from_name (mono_defaults.corlib, "System", "AppDomain");
256 /* FIXME: pin all those objects */
257 ad = (MonoAppDomain *) mono_object_new (domain, adclass);
258 ad->data = data = mono_domain_create ();
261 data->friendly_name = mono_string_to_utf8 (friendly_name);
263 /* FIXME: what to do next ? */
272 } add_assembly_helper_t;
275 add_assembly (gpointer key, gpointer value, gpointer user_data)
277 add_assembly_helper_t *ah = (add_assembly_helper_t *) user_data;
279 mono_array_set (ah->res, gpointer, ah->idx++, mono_assembly_get_object (ah->domain, value));
283 ves_icall_System_AppDomain_GetAssemblies (MonoAppDomain *ad)
285 MonoDomain *domain = ad->data;
286 static MonoClass *System_Reflection_Assembly;
288 add_assembly_helper_t ah;
290 if (!System_Reflection_Assembly)
291 System_Reflection_Assembly = mono_class_from_name (
292 mono_defaults.corlib, "System.Reflection", "Assembly");
294 res = mono_array_new (domain, System_Reflection_Assembly, g_hash_table_size (domain->assemblies));
299 mono_domain_lock (domain);
300 g_hash_table_foreach (domain->assemblies, add_assembly, &ah);
301 mono_domain_unlock (domain);
306 MonoReflectionAssembly *
307 ves_icall_System_Reflection_Assembly_LoadFrom (MonoString *fname)
309 MonoDomain *domain = mono_domain_get ();
310 char *name, *filename;
311 MonoImageOpenStatus status = MONO_IMAGE_OK;
314 name = filename = mono_string_to_utf8 (fname);
316 /* FIXME: move uri handling to mono_assembly_open */
317 if (strncmp (filename, "file://", 7) == 0)
320 ass = mono_assembly_open (filename, &status);
325 MonoException *exc = mono_get_exception_file_not_found (fname);
326 mono_raise_exception (exc);
329 return mono_assembly_get_object (domain, ass);
333 MonoReflectionAssembly *
334 ves_icall_System_AppDomain_LoadAssembly (MonoAppDomain *ad, MonoReflectionAssemblyName *assRef, MonoObject *evidence)
336 MonoDomain *domain = ad->data;
338 MonoImageOpenStatus status = MONO_IMAGE_OK;
340 MonoAssemblyName aname;
342 memset (&aname, 0, sizeof (aname));
344 /* FIXME : examine evidence? */
346 g_assert (assRef != NULL);
347 g_assert (assRef->name != NULL);
349 /* FIXME : examine version, culture info */
351 aname.name = name = mono_string_to_utf8 (assRef->name);
353 ass = mono_assembly_load (&aname, NULL, &status);
358 /* FIXME: it doesn't make much sense since we really don't have a filename ... */
359 MonoException *exc = mono_get_exception_file_not_found (assRef->name);
360 mono_raise_exception (exc);
363 return mono_assembly_get_object (domain, ass);
367 ves_icall_System_AppDomain_Unload (MonoAppDomain *ad)
369 mono_domain_unload (ad->data, FALSE);
373 ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomain *ad, MonoString *file,
374 MonoObject *evidence, MonoArray *args)
376 MonoDomain *cdom = mono_domain_get ();
377 MonoAssembly *assembly;
379 MonoCLIImageInfo *iinfo;
385 mono_domain_set (ad->data);
387 filename = mono_string_to_utf8 (file);
388 assembly = mono_assembly_open (filename, NULL);
392 mono_raise_exception ((MonoException *)mono_exception_from_name (
393 mono_defaults.corlib, "System.IO", "FileNotFoundException"));
396 image = assembly->image;
397 iinfo = image->image_info;
398 method = mono_get_method (image, iinfo->cli_cli_header.ch_entry_point, NULL);
401 g_error ("No entry point method found in %s", image->name);
403 margs = mono_domain_transfer_object (cdom, ad->data, (MonoObject *)args);
404 res = mono_runtime_exec_main (method, (MonoArray *)margs, NULL);
406 mono_domain_set (cdom);