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