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