2003-03-19 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mono / metadata / appdomain.c
1 /*
2  * appdomain.c: AppDomain functions
3  *
4  * Authors:
5  *      Dietmar Maurer (dietmar@ximian.com)
6  *      Patrik Torstensson
7  *      Gonzalo Paniagua Javier (gonzalo@ximian.com)
8  *
9  * (c) 2001-2003 Ximian, Inc. (http://www.ximian.com)
10  */
11
12 #include <config.h>
13 #include <glib.h>
14 #include <string.h>
15
16 #include <mono/os/gc_wrapper.h>
17
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/tabledefs.h>
25 #include <mono/metadata/gc-internal.h>
26
27 HANDLE mono_delegate_semaphore = NULL;
28 CRITICAL_SECTION mono_delegate_section;
29
30 static MonoAssembly *
31 mono_domain_assembly_preload (MonoAssemblyName *aname,
32                               gchar **assemblies_path,
33                               gpointer user_data);
34
35 static void
36 mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data);
37
38 static MonoMethod *
39 look_for_method_by_name (MonoClass *klass, const gchar *name);
40
41 /*
42  * mono_runtime_init:
43  * @domain: domain returned by mono_init ()
44  *
45  * Initialize the core AppDomain: this function will run also some
46  * IL initialization code, so it needs the execution engine to be fully 
47  * operational.
48  *
49  * AppDomain.SetupInformation is set up in mono_runtime_exec_main, where
50  * we know the entry_assembly.
51  *
52  */
53 void
54 mono_runtime_init (MonoDomain *domain, MonoThreadStartCB start_cb,
55                    MonoThreadAttachCB attach_cb)
56 {
57         MonoAppDomainSetup *setup;
58         MonoAppDomain *ad;
59         MonoClass *class;
60         
61         mono_install_assembly_preload_hook (mono_domain_assembly_preload, NULL);
62         mono_install_assembly_load_hook (mono_domain_fire_assembly_load, NULL);
63         mono_install_lookup_dynamic_token (mono_reflection_lookup_dynamic_token);
64
65         class = mono_class_from_name (mono_defaults.corlib, "System", "AppDomainSetup");
66         setup = (MonoAppDomainSetup *) mono_object_new (domain, class);
67
68         class = mono_class_from_name (mono_defaults.corlib, "System", "AppDomain");
69         ad = (MonoAppDomain *) mono_object_new (domain, class);
70         ad->data = domain;
71         domain->domain = ad;
72         domain->setup = setup;
73
74         mono_delegate_semaphore = CreateSemaphore (NULL, 0, 0x7fffffff, NULL);
75         g_assert (mono_delegate_semaphore != INVALID_HANDLE_VALUE);
76         InitializeCriticalSection (&mono_delegate_section);
77
78         mono_context_init (domain);
79         mono_context_set (domain->default_context);
80
81         mono_thread_init (start_cb, attach_cb);
82         
83         /* GC init has to happen after thread init */
84         mono_gc_init ();
85
86         mono_network_init ();
87
88         return;
89 }
90
91 void
92 mono_context_init (MonoDomain *domain)
93 {
94         MonoClass *class;
95         MonoAppContext *context;
96
97         class = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Contexts", "Context");
98         context = (MonoAppContext *) mono_object_new (domain, class);
99         context->domain_id = domain->domain_id;
100         context->context_id = 0;
101         domain->default_context = context;
102 }
103
104 /* This must not be called while there are still running threads executing
105  * managed code.
106  */
107 void
108 mono_runtime_cleanup (MonoDomain *domain)
109 {
110         /* Not really needed, but do it anyway */
111         mono_gc_cleanup ();
112         
113         mono_network_cleanup ();
114 }
115
116 gboolean
117 mono_domain_has_type_resolve (MonoDomain *domain)
118 {
119         static MonoClassField *field = NULL;
120         MonoObject *o;
121
122         if (field == NULL) {
123                 MonoClass *klass = mono_defaults.appdomain_class;
124                 int i;
125
126                 for (i = 0; i < klass->field.count; ++i)
127                         if (strcmp (klass->fields [i].name, "TypeResolve") == 0)
128                                 field = &klass->fields [i];
129                 g_assert (field);
130         }
131
132         mono_field_get_value ((MonoObject*)(domain->domain), field, &o);
133         return o != NULL;
134 }
135
136 MonoReflectionAssembly *
137 mono_domain_try_type_resolve (MonoDomain *domain, char *name, MonoObject *tb)
138 {
139         MonoClass *klass;
140         void *params [1];
141         static MonoMethod *method = NULL;
142
143         g_assert (domain != NULL && ((name != NULL) || (tb != NULL)));
144
145         if (method == NULL) {
146                 klass = domain->domain->mbr.obj.vtable->klass;
147                 g_assert (klass);
148
149                 method = look_for_method_by_name (klass, "DoTypeResolve");
150                 if (method == NULL) {
151                         g_warning ("Method AppDomain.DoTypeResolve not found.\n");
152                         return NULL;
153                 }
154         }
155
156         if (name)
157                 *params = (MonoObject*)mono_string_new (mono_domain_get (), name);
158         else
159                 *params = tb;
160         return (MonoReflectionAssembly *) mono_runtime_invoke (method, domain->domain, params, NULL);
161 }
162
163 void
164 ves_icall_System_AppDomainSetup_InitAppDomainSetup (MonoAppDomainSetup *setup)
165 {
166         MonoDomain* domain = mono_domain_get ();
167         MonoAssembly *assembly;
168         gchar *str;
169         gchar *config_suffix;
170         
171         MONO_ARCH_SAVE_REGS;
172
173         assembly = domain->entry_assembly;
174         g_assert (assembly);
175
176         setup->application_base = mono_string_new (domain, assembly->basedir);
177
178         config_suffix = g_strconcat (assembly->aname.name, ".exe.config", NULL);
179         str = g_build_filename (assembly->basedir, config_suffix, NULL);
180         g_free (config_suffix);
181         setup->configuration_file = mono_string_new (domain, str);
182         g_free (str);
183 }
184
185 MonoObject *
186 ves_icall_System_AppDomain_GetData (MonoAppDomain *ad, MonoString *name)
187 {
188         MonoDomain *add = ad->data;
189         MonoObject *o;
190         char *str;
191
192         MONO_ARCH_SAVE_REGS;
193
194         g_assert (ad != NULL);
195         g_assert (name != NULL);
196
197         str = mono_string_to_utf8 (name);
198
199         mono_domain_lock (add);
200
201         if (!strcmp (str, "APPBASE"))
202                 o = (MonoObject *)add->setup->application_base;
203         else if (!strcmp (str, "APP_CONFIG_FILE"))
204                 o = (MonoObject *)add->setup->configuration_file;
205         else if (!strcmp (str, "DYNAMIC_BASE"))
206                 o = (MonoObject *)add->setup->dynamic_base;
207         else if (!strcmp (str, "APP_NAME"))
208                 o = (MonoObject *)add->setup->application_name;
209         else if (!strcmp (str, "CACHE_BASE"))
210                 o = (MonoObject *)add->setup->cache_path;
211         else if (!strcmp (str, "PRIVATE_BINPATH"))
212                 o = (MonoObject *)add->setup->private_bin_path;
213         else if (!strcmp (str, "BINPATH_PROBE_ONLY"))
214                 o = (MonoObject *)add->setup->private_bin_path_probe;
215         else if (!strcmp (str, "SHADOW_COPY_DIRS"))
216                 o = (MonoObject *)add->setup->shadow_copy_directories;
217         else if (!strcmp (str, "FORCE_CACHE_INSTALL"))
218                 o = (MonoObject *)add->setup->shadow_copy_files;
219         else 
220                 o = mono_g_hash_table_lookup (add->env, name);
221
222         mono_domain_unlock (add);
223         g_free (str);
224
225         if (!o)
226                 return NULL;
227
228         return o;
229 }
230
231 void
232 ves_icall_System_AppDomain_SetData (MonoAppDomain *ad, MonoString *name, MonoObject *data)
233 {
234         MonoDomain *add = ad->data;
235
236         MONO_ARCH_SAVE_REGS;
237
238         g_assert (ad != NULL);
239         g_assert (name != NULL);
240
241         mono_domain_lock (add);
242
243         mono_g_hash_table_insert (add->env, name, data);
244
245         mono_domain_unlock (add);
246 }
247
248 MonoAppDomainSetup *
249 ves_icall_System_AppDomain_getSetup (MonoAppDomain *ad)
250 {
251         MONO_ARCH_SAVE_REGS;
252
253         g_assert (ad != NULL);
254         g_assert (ad->data != NULL);
255
256         return ad->data->setup;
257 }
258
259 MonoString *
260 ves_icall_System_AppDomain_getFriendlyName (MonoAppDomain *ad)
261 {
262         MONO_ARCH_SAVE_REGS;
263
264         g_assert (ad != NULL);
265         g_assert (ad->data != NULL);
266
267         return mono_string_new (ad->data, ad->data->friendly_name);
268 }
269
270 MonoAppDomain *
271 ves_icall_System_AppDomain_getCurDomain ()
272 {
273         MonoDomain *add = mono_domain_get ();
274
275         MONO_ARCH_SAVE_REGS;
276
277         return add->domain;
278 }
279
280 MonoAppDomain *
281 ves_icall_System_AppDomain_createDomain (MonoString *friendly_name, MonoAppDomainSetup *setup)
282 {
283         /*MonoDomain *domain = mono_domain_get (); */
284         MonoClass *adclass;
285         MonoAppDomain *ad;
286         MonoDomain *data;
287         
288         MONO_ARCH_SAVE_REGS;
289
290         adclass = mono_class_from_name (mono_defaults.corlib, "System", "AppDomain");
291
292         /* FIXME: pin all those objects */
293         data = mono_domain_create();
294
295         ad = (MonoAppDomain *) mono_object_new (data, adclass);
296         ad->data = data;
297         data->domain = ad;
298         data->setup = setup;
299         data->friendly_name = mono_string_to_utf8 (friendly_name);
300
301         mono_context_init (data);
302
303         /* FIXME: what to do next ? */
304
305         return ad;
306 }
307
308 typedef struct {
309         MonoArray *res;
310         MonoDomain *domain;
311         int idx;
312 } add_assembly_helper_t;
313
314 static void
315 add_assembly (gpointer key, gpointer value, gpointer user_data)
316 {
317         add_assembly_helper_t *ah = (add_assembly_helper_t *) user_data;
318
319         mono_array_set (ah->res, gpointer, ah->idx++, mono_assembly_get_object (ah->domain, value));
320 }
321
322 MonoArray *
323 ves_icall_System_AppDomain_GetAssemblies (MonoAppDomain *ad)
324 {
325         MonoDomain *domain = ad->data; 
326         static MonoClass *System_Reflection_Assembly;
327         MonoArray *res;
328         add_assembly_helper_t ah;
329         
330         MONO_ARCH_SAVE_REGS;
331
332         if (!System_Reflection_Assembly)
333                 System_Reflection_Assembly = mono_class_from_name (
334                         mono_defaults.corlib, "System.Reflection", "Assembly");
335
336         res = mono_array_new (domain, System_Reflection_Assembly, g_hash_table_size (domain->assemblies));
337
338         ah.domain = domain;
339         ah.res = res;
340         ah.idx = 0;
341         mono_domain_lock (domain);
342         g_hash_table_foreach (domain->assemblies, add_assembly, &ah);
343         mono_domain_unlock (domain);
344
345         return res;
346 }
347
348 /*
349  * Used to find methods in AppDomain class.
350  * It only works if there are no multiple signatures for any given method name
351  */
352 static MonoMethod *
353 look_for_method_by_name (MonoClass *klass, const gchar *name)
354 {
355         gint i;
356         MonoMethod *method;
357
358         for (i = 0; i < klass->method.count; i++) {
359                 method = klass->methods [i];
360                 if (!strcmp (method->name, name))
361                         return method;
362         }
363
364         return NULL;
365 }
366
367 static MonoReflectionAssembly *
368 try_assembly_resolve (MonoDomain *domain, MonoString *fname)
369 {
370         MonoClass *klass;
371         MonoMethod *method;
372         void *params [1];
373
374         g_assert (domain != NULL && fname != NULL);
375
376         klass = domain->domain->mbr.obj.vtable->klass;
377         g_assert (klass);
378         
379         method = look_for_method_by_name (klass, "DoAssemblyResolve");
380         if (method == NULL) {
381                 g_warning ("Method AppDomain.DoAssemblyResolve not found.\n");
382                 return NULL;
383         }
384
385         *params = fname;
386         return (MonoReflectionAssembly *) mono_runtime_invoke (method, domain->domain, params, NULL);
387 }
388
389 static void
390 add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass)
391 {
392         gint i;
393
394         if (g_hash_table_lookup (domain->assemblies, ass->aname.name))
395                 return; /* This is ok while no lazy loading of assemblies */
396
397         mono_domain_lock (domain);
398         g_hash_table_insert (domain->assemblies, (gpointer) ass->aname.name, ass);
399         mono_domain_unlock (domain);
400
401         for (i = 0; ass->image->references [i] != NULL; i++)
402                 add_assemblies_to_domain (domain, ass->image->references [i]);
403 }
404
405 static void
406 mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data)
407 {
408         MonoDomain *domain = mono_domain_get ();
409         MonoReflectionAssembly *ref_assembly;
410         MonoClass *klass;
411         MonoMethod *method;
412         void *params [1];
413
414         klass = domain->domain->mbr.obj.vtable->klass;
415
416         
417         method = look_for_method_by_name (klass, "DoAssemblyLoad");
418         if (method == NULL) {
419                 g_warning ("Method AppDomain.DoAssemblyLoad not found.\n");
420                 return;
421         }
422
423         add_assemblies_to_domain (domain, assembly);
424
425         ref_assembly = mono_assembly_get_object (domain, assembly);
426         g_assert (ref_assembly);
427
428         *params = ref_assembly;
429         mono_runtime_invoke (method, domain->domain, params, NULL);
430 }
431
432 static void
433 set_domain_search_path (MonoDomain *domain)
434 {
435         MonoAppDomainSetup *setup;
436         gchar **tmp;
437         gchar *utf8;
438         gint i;
439         gint npaths = 0;
440         gchar **pvt_split = NULL;
441         GError *error = NULL;
442
443         if (domain->search_path != NULL)
444                 return;
445
446         setup = domain->setup;
447         if (setup->application_base)
448                 npaths++;
449
450         if (setup->private_bin_path) {
451                 utf8 = mono_string_to_utf8 (setup->private_bin_path);
452                 pvt_split = g_strsplit (utf8, G_SEARCHPATH_SEPARATOR_S, 1000);
453                 g_free (utf8);
454                 for (tmp = pvt_split; *tmp; tmp++, npaths++);
455         }
456
457         if (!npaths) {
458                 if (pvt_split)
459                         g_strfreev (pvt_split);
460                 /*
461                  * Don't do this because the first time is called, the domain
462                  * setup is not finished.
463                  *
464                  * domain->search_path = g_malloc (sizeof (char *));
465                  * domain->search_path [0] = NULL;
466                 */
467                 return;
468         }
469
470         domain->search_path = tmp = g_malloc ((npaths + 1) * sizeof (gchar *));
471         tmp [npaths] = NULL;
472         if (setup->application_base) {
473                 *tmp = mono_string_to_utf8 (setup->application_base);
474                 /* FIXME: is this needed? */
475                 if (strncmp (*tmp, "file://", 7) == 0) {
476                         gchar *file = *tmp;
477                         *tmp = g_filename_from_uri (*tmp, NULL, &error);
478                         if (error != NULL) {
479                                 g_error_free (error);
480                                 *tmp = file;
481                         } else {
482                                 g_free (file);
483                         }
484                 }
485                 
486         } else {
487                 *tmp = g_strdup ("");
488         }
489
490         for (i = 1; pvt_split && i < npaths; i++) {
491                 if (*tmp [0] == '\0' || g_path_is_absolute (pvt_split [i - 1])) {
492                         tmp [i] = g_strdup (pvt_split [i - 1]);
493                         continue;
494                 }
495
496                 tmp [i] = g_build_filename (tmp [0], pvt_split [i - 1], NULL);
497         }
498         
499         if (setup->private_bin_path_probe != NULL && setup->application_base) {
500                 g_free (tmp [0]);
501                 tmp [0] = g_strdup ("");
502         }
503                 
504
505         g_strfreev (pvt_split);
506 }
507
508 static MonoAssembly *
509 real_load (gchar **search_path, gchar *filename)
510 {
511         MonoAssembly *result;
512         gchar **path;
513         gchar *fullpath;
514
515         for (path = search_path; *path; path++) {
516                 if (**path == '\0')
517                         continue; /* Ignore empty ApplicationBase */
518                 fullpath = g_build_filename (*path, filename, NULL);
519                 result = mono_assembly_open (fullpath, NULL);
520                 g_free (fullpath);
521                 if (result)
522                         return result;
523         }
524
525         return NULL;
526 }
527
528 /*
529  * Try loading the assembly from ApplicationBase and PrivateBinPath 
530  * and then from assemblies_path if any.
531  */
532 static MonoAssembly *
533 mono_domain_assembly_preload (MonoAssemblyName *aname,
534                               gchar **assemblies_path,
535                               gpointer user_data)
536 {
537         MonoDomain *domain = mono_domain_get ();
538         MonoAssembly *result;
539         gchar *dll, *exe;
540
541         set_domain_search_path (domain);
542
543         dll = g_strconcat (aname->name, ".dll", NULL);
544         exe = g_strdup (dll);
545         strcpy (exe + strlen (exe) - 4, ".exe");
546
547         if (domain->search_path && domain->search_path [0] != NULL) {
548                 /* TODO: should also search in name/name.dll and name/name.exe from appbase */
549                 result = real_load (domain->search_path, dll);
550                 if (result) {
551                         g_free (dll);
552                         g_free (exe);
553                         return result;
554                 }
555
556                 result = real_load (domain->search_path, exe);
557                 if (result) {
558                         g_free (dll);
559                         g_free (exe);
560                         return result;
561                 }
562         }
563
564         if (assemblies_path && assemblies_path [0] != NULL) {
565                 result = real_load (assemblies_path, dll);
566                 if (result) {
567                         g_free (dll);
568                         g_free (exe);
569                         return result;
570                 }
571
572                 result = real_load (assemblies_path, exe);
573                 if (result) {
574                         g_free (dll);
575                         g_free (exe);
576                         return result;
577                 }
578         }
579         
580         g_free (dll);
581         g_free (exe);
582         return NULL;
583 }
584
585 MonoReflectionAssembly *
586 ves_icall_System_Reflection_Assembly_LoadFrom (MonoString *fname)
587 {
588         MonoDomain *domain = mono_domain_get ();
589         char *name, *filename;
590         MonoImageOpenStatus status = MONO_IMAGE_OK;
591         MonoAssembly *ass;
592
593         MONO_ARCH_SAVE_REGS;
594
595         if (fname == NULL) {
596                 MonoException *exc = mono_get_exception_argument_null ("assemblyFile");
597                 mono_raise_exception (exc);
598         }
599                 
600         name = filename = mono_string_to_utf8 (fname);
601
602         ass = mono_assembly_open (filename, &status);
603         
604         g_free (name);
605
606         if (!ass){
607                 MonoException *exc = mono_get_exception_file_not_found (fname);
608                 mono_raise_exception (exc);
609         }
610
611         return mono_assembly_get_object (domain, ass);
612 }
613
614 static void
615 free_assembly_name (MonoAssemblyName *aname)
616 {
617         if (aname == NULL)
618                 return;
619
620         g_free ((void *) aname->name);
621         g_free ((void *) aname->culture);
622         g_free ((void *) aname->hash_value);
623 }
624
625 static gboolean
626 get_info_from_assembly_name (MonoReflectionAssemblyName *assRef, MonoAssemblyName *aname)
627 {
628         gchar *name;
629         gchar *value;
630         gchar **parts;
631         gchar **tmp;
632         gint major, minor, build, revision;
633
634         memset (aname, 0, sizeof (MonoAssemblyName));
635
636         name = mono_string_to_utf8 (assRef->name);
637         parts = tmp = g_strsplit (name, ",", 4);
638         g_free (name);
639         if (!tmp || !*tmp) {
640                 g_strfreev (tmp);
641                 return FALSE;
642         }
643
644         value = g_strstrip (*tmp);
645         /* g_print ("Assembly name: %s\n", value); */
646         aname->name = g_strdup (value);
647         tmp++;
648         if (!*tmp) {
649                 g_strfreev (parts);
650                 return TRUE;
651         }
652
653         value = g_strstrip (*tmp);
654         if (strncmp (value, "Version=", 8)) {
655                 g_strfreev (parts);
656                 return FALSE;
657         }
658         
659         if (sscanf (value + 8, "%u.%u.%u.%u", &major, &minor, &build, &revision) != 4) {
660                 g_strfreev (parts);
661                 return FALSE;
662         }
663
664         /* g_print ("Version: %u.%u.%u.%u\n", major, minor, build, revision); */
665         aname->major = major;
666         aname->minor = minor;
667         aname->build = build;
668         aname->revision = revision;
669         tmp++;
670
671         if (!*tmp) {
672                 g_strfreev (parts);
673                 return FALSE;
674         }
675
676         value = g_strstrip (*tmp);
677         if (strncmp (value, "Culture=", 8)) {
678                 g_strfreev (parts);
679                 return FALSE;
680         }
681
682         /* g_print ("Culture: %s\n", aname->culture); */
683         aname->culture = g_strstrip (g_strdup (value + 8));
684         tmp++;
685
686         if (!*tmp) {
687                 g_strfreev (parts);
688                 return FALSE;
689         }
690
691         value = g_strstrip (*tmp);
692         if (strncmp (value, "PublicKeyToken=", 15)) {
693                 g_strfreev (parts);
694                 return FALSE;
695         }
696
697         value += 15;
698         if (*value && strcmp (value, "null")) {
699                 gint i, len;
700                 gchar h, l;
701                 gchar *result;
702                 
703                 value = g_strstrip (g_strdup (value));
704                 len = strlen (value);
705                 if (len % 2) {
706                         g_free (value);
707                         g_strfreev (parts);
708                         return FALSE;
709                 }
710                 
711                 aname->hash_len = len / 2;
712                 aname->hash_value = g_malloc0 (aname->hash_len);
713                 result = (gchar *) aname->hash_value;
714                 
715                 for (i = 0; i < len; i++) {
716                         if (i % 2) {
717                                 l = g_ascii_xdigit_value (value [i]);
718                                 if (l == -1) {
719                                         g_free (value);
720                                         g_strfreev (parts);
721                                         return FALSE;
722                                 }
723                                 result [i / 2] = (h * 16) + l;
724                         } else {
725                                 h = g_ascii_xdigit_value (value [i]);
726                                 if (h == -1) {
727                                         g_free (value);
728                                         g_strfreev (parts);
729                                         return FALSE;
730                                 }
731                         }
732                 }
733                 g_free (value);
734
735                 /*
736                 g_print ("PublicKeyToken: ");
737                 for (i = 0; i < aname->hash_len; i++) {
738                         g_print ("%x", 0x00FF & aname->hash_value [i]); 
739                 }
740                 g_print ("\n");
741                 */
742         }
743
744         g_strfreev (parts);
745         return TRUE;
746 }
747
748 MonoReflectionAssembly *
749 ves_icall_System_AppDomain_LoadAssembly (MonoAppDomain *ad,  MonoReflectionAssemblyName *assRef, MonoObject *evidence)
750 {
751         MonoDomain *domain = ad->data; 
752         MonoImageOpenStatus status = MONO_IMAGE_OK;
753         MonoAssembly *ass;
754         MonoAssemblyName aname;
755         MonoReflectionAssembly *refass = NULL;
756
757         MONO_ARCH_SAVE_REGS;
758
759         memset (&aname, 0, sizeof (aname));
760
761         /* FIXME : examine evidence? */
762
763         g_assert (assRef != NULL);
764         g_assert (assRef->name != NULL);
765
766         if (!get_info_from_assembly_name (assRef, &aname)) {
767                 MonoException *exc;
768
769                 free_assembly_name (&aname);
770                 /* This is a parse error... */
771                 exc = mono_get_exception_file_not_found (assRef->name);
772                 mono_raise_exception (exc);
773         }
774
775         ass = mono_assembly_load (&aname, NULL, &status);
776         free_assembly_name (&aname);
777
778         if (!ass && (refass = try_assembly_resolve (domain, assRef->name)) == NULL){
779                 /* FIXME: it doesn't make much sense since we really don't have a filename ... */
780                 MonoException *exc = mono_get_exception_file_not_found (assRef->name);
781                 mono_raise_exception (exc);
782         }
783
784         if (refass != NULL)
785                 return refass;
786
787         return mono_assembly_get_object (domain, ass);
788 }
789
790 void
791 ves_icall_System_AppDomain_InternalUnload (gint32 domain_id)
792 {
793         MonoDomain * domain = mono_domain_get_by_id (domain_id);
794
795         MONO_ARCH_SAVE_REGS;
796
797         if (NULL == domain) {
798                 MonoException *exc = mono_get_exception_execution_engine ("Failed to unload domain, domain id not found");
799                 mono_raise_exception (exc);
800         }
801         
802
803         mono_domain_unload (domain, FALSE);
804 }
805
806 gint32
807 ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomain *ad, MonoString *file, 
808                                             MonoObject *evidence, MonoArray *args)
809 {
810         MonoAssembly *assembly;
811         MonoImage *image;
812         MonoMethod *method;
813         char *filename;
814         gint32 res;
815
816         MONO_ARCH_SAVE_REGS;
817
818         filename = mono_string_to_utf8 (file);
819         assembly = mono_assembly_open (filename, NULL);
820         g_free (filename);
821
822         if (!assembly) {
823                 mono_raise_exception ((MonoException *)mono_exception_from_name (
824                         mono_defaults.corlib, "System.IO", "FileNotFoundException"));
825         }
826
827         image = assembly->image;
828
829         method = mono_get_method (image, mono_image_get_entry_point (image), NULL);
830
831         if (!method)
832                 g_error ("No entry point method found in %s", image->name);
833
834         if (!args)
835                 args = (MonoArray *) mono_array_new (ad->data, mono_defaults.string_class, 0);
836
837         res = mono_runtime_exec_main (method, (MonoArray *)args, NULL);
838
839         return res;
840 }
841
842 gint32 
843 ves_icall_System_AppDomain_GetIDFromDomain (MonoAppDomain * ad) 
844 {
845         MONO_ARCH_SAVE_REGS;
846
847         return ad->data->domain_id;
848 }
849
850 MonoAppDomain * 
851 ves_icall_System_AppDomain_InternalSetDomain (MonoAppDomain *ad)
852 {
853         MonoDomain *old_domain = mono_domain_get();
854
855         MONO_ARCH_SAVE_REGS;
856
857         mono_domain_set(ad->data);
858
859         return old_domain->domain;
860 }
861
862 MonoAppDomain * 
863 ves_icall_System_AppDomain_InternalSetDomainByID (gint32 domainid)
864 {
865         MonoDomain *current_domain = mono_domain_get ();
866         MonoDomain *domain = mono_domain_get_by_id (domainid);
867
868         MONO_ARCH_SAVE_REGS;
869
870         mono_domain_set (domain);
871         
872         return current_domain->domain;
873 }
874
875 MonoAppContext * 
876 ves_icall_System_AppDomain_InternalGetContext ()
877 {
878         MONO_ARCH_SAVE_REGS;
879
880         return mono_context_get ();
881 }
882
883 MonoAppContext * 
884 ves_icall_System_AppDomain_InternalGetDefaultContext ()
885 {
886         MONO_ARCH_SAVE_REGS;
887
888         return mono_domain_get ()->default_context;
889 }
890
891 MonoAppContext * 
892 ves_icall_System_AppDomain_InternalSetContext (MonoAppContext *mc)
893 {
894         MonoAppContext *old_context = mono_context_get ();
895
896         MONO_ARCH_SAVE_REGS;
897
898         mono_context_set (mc);
899         
900         return old_context;
901 }