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