719e19ffbf3915122636657a8b141560bc7fa2d7
[mono.git] / mono / metadata / icall.c
1 /*
2  * icall.c:
3  *
4  * Authors:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *   Paolo Molaro (lupus@ximian.com)
7  *       Patrik Torstensson (patrik.torstensson@labs2.com)
8  *
9  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11  */
12
13 #include <config.h>
14 #include <glib.h>
15 #include <stdarg.h>
16 #include <string.h>
17 #include <ctype.h>
18 #ifdef HAVE_ALLOCA_H
19 #include <alloca.h>
20 #endif
21 #ifdef HAVE_SYS_TIME_H
22 #include <sys/time.h>
23 #endif
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #if defined (HOST_WIN32)
28 #include <stdlib.h>
29 #endif
30
31 #include "mono/utils/mono-membar.h"
32 #include <mono/metadata/object.h>
33 #include <mono/metadata/threads.h>
34 #include <mono/metadata/threads-types.h>
35 #include <mono/metadata/threadpool.h>
36 #include <mono/metadata/monitor.h>
37 #include <mono/metadata/reflection.h>
38 #include <mono/metadata/assembly.h>
39 #include <mono/metadata/tabledefs.h>
40 #include <mono/metadata/exception.h>
41 #include <mono/metadata/file-io.h>
42 #include <mono/metadata/console-io.h>
43 #include <mono/metadata/socket-io.h>
44 #include <mono/metadata/mono-endian.h>
45 #include <mono/metadata/tokentype.h>
46 #include <mono/metadata/domain-internals.h>
47 #include <mono/metadata/metadata-internals.h>
48 #include <mono/metadata/class-internals.h>
49 #include <mono/metadata/marshal.h>
50 #include <mono/metadata/gc-internal.h>
51 #include <mono/metadata/mono-gc.h>
52 #include <mono/metadata/rand.h>
53 #include <mono/metadata/sysmath.h>
54 #include <mono/metadata/string-icalls.h>
55 #include <mono/metadata/debug-helpers.h>
56 #include <mono/metadata/process.h>
57 #include <mono/metadata/environment.h>
58 #include <mono/metadata/profiler-private.h>
59 #include <mono/metadata/locales.h>
60 #include <mono/metadata/filewatcher.h>
61 #include <mono/metadata/char-conversions.h>
62 #include <mono/metadata/security.h>
63 #include <mono/metadata/mono-config.h>
64 #include <mono/metadata/cil-coff.h>
65 #include <mono/metadata/number-formatter.h>
66 #include <mono/metadata/security-manager.h>
67 #include <mono/metadata/security-core-clr.h>
68 #include <mono/metadata/mono-perfcounters.h>
69 #include <mono/metadata/mono-debug.h>
70 #include <mono/metadata/mono-ptr-array.h>
71 #include <mono/metadata/verify-internals.h>
72 #include <mono/io-layer/io-layer.h>
73 #include <mono/utils/strtod.h>
74 #include <mono/utils/monobitset.h>
75 #include <mono/utils/mono-time.h>
76 #include <mono/utils/mono-proclib.h>
77 #include <mono/utils/mono-string.h>
78 #include <mono/utils/mono-error-internals.h>
79 #include <mono/utils/mono-mmap.h>
80
81 #if defined (HOST_WIN32)
82 #include <windows.h>
83 #include <shlobj.h>
84 #endif
85 #include "decimal.h"
86
87 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
88
89 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
90
91 static MonoArray*
92 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
93
94 static inline MonoBoolean
95 is_generic_parameter (MonoType *type)
96 {
97         return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
98 }
99
100 static void
101 mono_class_init_or_throw (MonoClass *klass)
102 {
103         if (!mono_class_init (klass))
104                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
105 }
106
107 /*
108  * We expect a pointer to a char, not a string
109  */
110 static gboolean
111 mono_double_ParseImpl (char *ptr, double *result)
112 {
113         gchar *endptr = NULL;
114         *result = 0.0;
115
116         MONO_ARCH_SAVE_REGS;
117
118 #ifdef __arm__
119         if (*ptr)
120                 *result = strtod (ptr, &endptr);
121 #else
122         if (*ptr){
123                 /* mono_strtod () is not thread-safe */
124                 EnterCriticalSection (&mono_strtod_mutex);
125                 *result = mono_strtod (ptr, &endptr);
126                 LeaveCriticalSection (&mono_strtod_mutex);
127         }
128 #endif
129
130         if (!*ptr || (endptr && *endptr))
131                 return FALSE;
132         
133         return TRUE;
134 }
135
136 static MonoObject *
137 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
138 {
139         MonoClass *ac;
140         MonoArray *ao;
141         gint32 esize;
142         gpointer *ea;
143
144         MONO_ARCH_SAVE_REGS;
145
146         ao = (MonoArray *)this;
147         ac = (MonoClass *)ao->obj.vtable->klass;
148
149         esize = mono_array_element_size (ac);
150         ea = (gpointer*)((char*)ao->vector + (pos * esize));
151
152         if (ac->element_class->valuetype)
153                 return mono_value_box (this->vtable->domain, ac->element_class, ea);
154         else
155                 return *ea;
156 }
157
158 static MonoObject *
159 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
160 {
161         MonoClass *ac, *ic;
162         MonoArray *ao, *io;
163         gint32 i, pos, *ind;
164
165         MONO_ARCH_SAVE_REGS;
166
167         MONO_CHECK_ARG_NULL (idxs);
168
169         io = (MonoArray *)idxs;
170         ic = (MonoClass *)io->obj.vtable->klass;
171         
172         ao = (MonoArray *)this;
173         ac = (MonoClass *)ao->obj.vtable->klass;
174
175         g_assert (ic->rank == 1);
176         if (io->bounds != NULL || io->max_length !=  ac->rank)
177                 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
178
179         ind = (gint32 *)io->vector;
180
181         if (ao->bounds == NULL) {
182                 if (*ind < 0 || *ind >= ao->max_length)
183                         mono_raise_exception (mono_get_exception_index_out_of_range ());
184
185                 return ves_icall_System_Array_GetValueImpl (this, *ind);
186         }
187         
188         for (i = 0; i < ac->rank; i++)
189                 if ((ind [i] < ao->bounds [i].lower_bound) ||
190                     (ind [i] >=  (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
191                         mono_raise_exception (mono_get_exception_index_out_of_range ());
192
193         pos = ind [0] - ao->bounds [0].lower_bound;
194         for (i = 1; i < ac->rank; i++)
195                 pos = pos*ao->bounds [i].length + ind [i] - 
196                         ao->bounds [i].lower_bound;
197
198         return ves_icall_System_Array_GetValueImpl (this, pos);
199 }
200
201 static void
202 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
203 {
204         MonoClass *ac, *vc, *ec;
205         gint32 esize, vsize;
206         gpointer *ea, *va;
207         int et, vt;
208
209         guint64 u64 = 0;
210         gint64 i64 = 0;
211         gdouble r64 = 0;
212
213         MONO_ARCH_SAVE_REGS;
214
215         if (value)
216                 vc = value->vtable->klass;
217         else
218                 vc = NULL;
219
220         ac = this->obj.vtable->klass;
221         ec = ac->element_class;
222
223         esize = mono_array_element_size (ac);
224         ea = (gpointer*)((char*)this->vector + (pos * esize));
225         va = (gpointer*)((char*)value + sizeof (MonoObject));
226
227         if (mono_class_is_nullable (ec)) {
228                 mono_nullable_init ((guint8*)ea, value, ec);
229                 return;
230         }
231
232         if (!value) {
233                 memset (ea, 0,  esize);
234                 return;
235         }
236
237 #define NO_WIDENING_CONVERSION G_STMT_START{\
238         mono_raise_exception (mono_get_exception_argument ( \
239                 "value", "not a widening conversion")); \
240 }G_STMT_END
241
242 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
243         if (esize < vsize + (extra)) \
244                 mono_raise_exception (mono_get_exception_argument ( \
245                         "value", "not a widening conversion")); \
246 }G_STMT_END
247
248 #define INVALID_CAST G_STMT_START{\
249         mono_raise_exception (mono_get_exception_invalid_cast ()); \
250 }G_STMT_END
251
252         /* Check element (destination) type. */
253         switch (ec->byval_arg.type) {
254         case MONO_TYPE_STRING:
255                 switch (vc->byval_arg.type) {
256                 case MONO_TYPE_STRING:
257                         break;
258                 default:
259                         INVALID_CAST;
260                 }
261                 break;
262         case MONO_TYPE_BOOLEAN:
263                 switch (vc->byval_arg.type) {
264                 case MONO_TYPE_BOOLEAN:
265                         break;
266                 case MONO_TYPE_CHAR:
267                 case MONO_TYPE_U1:
268                 case MONO_TYPE_U2:
269                 case MONO_TYPE_U4:
270                 case MONO_TYPE_U8:
271                 case MONO_TYPE_I1:
272                 case MONO_TYPE_I2:
273                 case MONO_TYPE_I4:
274                 case MONO_TYPE_I8:
275                 case MONO_TYPE_R4:
276                 case MONO_TYPE_R8:
277                         NO_WIDENING_CONVERSION;
278                 default:
279                         INVALID_CAST;
280                 }
281                 break;
282         }
283
284         if (!ec->valuetype) {
285                 if (!mono_object_isinst (value, ec))
286                         INVALID_CAST;
287                 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
288                 return;
289         }
290
291         if (mono_object_isinst (value, ec)) {
292                 if (ec->has_references)
293                         mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
294                 else
295                         memcpy (ea, (char *)value + sizeof (MonoObject), esize);
296                 return;
297         }
298
299         if (!vc->valuetype)
300                 INVALID_CAST;
301
302         vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
303
304         et = ec->byval_arg.type;
305         if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
306                 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
307
308         vt = vc->byval_arg.type;
309         if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
310                 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
311
312 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
313         switch (vt) { \
314         case MONO_TYPE_U1: \
315         case MONO_TYPE_U2: \
316         case MONO_TYPE_U4: \
317         case MONO_TYPE_U8: \
318         case MONO_TYPE_CHAR: \
319                 CHECK_WIDENING_CONVERSION(0); \
320                 *(etype *) ea = (etype) u64; \
321                 return; \
322         /* You can't assign a signed value to an unsigned array. */ \
323         case MONO_TYPE_I1: \
324         case MONO_TYPE_I2: \
325         case MONO_TYPE_I4: \
326         case MONO_TYPE_I8: \
327         /* You can't assign a floating point number to an integer array. */ \
328         case MONO_TYPE_R4: \
329         case MONO_TYPE_R8: \
330                 NO_WIDENING_CONVERSION; \
331         } \
332 }G_STMT_END
333
334 #define ASSIGN_SIGNED(etype) G_STMT_START{\
335         switch (vt) { \
336         case MONO_TYPE_I1: \
337         case MONO_TYPE_I2: \
338         case MONO_TYPE_I4: \
339         case MONO_TYPE_I8: \
340                 CHECK_WIDENING_CONVERSION(0); \
341                 *(etype *) ea = (etype) i64; \
342                 return; \
343         /* You can assign an unsigned value to a signed array if the array's */ \
344         /* element size is larger than the value size. */ \
345         case MONO_TYPE_U1: \
346         case MONO_TYPE_U2: \
347         case MONO_TYPE_U4: \
348         case MONO_TYPE_U8: \
349         case MONO_TYPE_CHAR: \
350                 CHECK_WIDENING_CONVERSION(1); \
351                 *(etype *) ea = (etype) u64; \
352                 return; \
353         /* You can't assign a floating point number to an integer array. */ \
354         case MONO_TYPE_R4: \
355         case MONO_TYPE_R8: \
356                 NO_WIDENING_CONVERSION; \
357         } \
358 }G_STMT_END
359
360 #define ASSIGN_REAL(etype) G_STMT_START{\
361         switch (vt) { \
362         case MONO_TYPE_R4: \
363         case MONO_TYPE_R8: \
364                 CHECK_WIDENING_CONVERSION(0); \
365                 *(etype *) ea = (etype) r64; \
366                 return; \
367         /* All integer values fit into a floating point array, so we don't */ \
368         /* need to CHECK_WIDENING_CONVERSION here. */ \
369         case MONO_TYPE_I1: \
370         case MONO_TYPE_I2: \
371         case MONO_TYPE_I4: \
372         case MONO_TYPE_I8: \
373                 *(etype *) ea = (etype) i64; \
374                 return; \
375         case MONO_TYPE_U1: \
376         case MONO_TYPE_U2: \
377         case MONO_TYPE_U4: \
378         case MONO_TYPE_U8: \
379         case MONO_TYPE_CHAR: \
380                 *(etype *) ea = (etype) u64; \
381                 return; \
382         } \
383 }G_STMT_END
384
385         switch (vt) {
386         case MONO_TYPE_U1:
387                 u64 = *(guint8 *) va;
388                 break;
389         case MONO_TYPE_U2:
390                 u64 = *(guint16 *) va;
391                 break;
392         case MONO_TYPE_U4:
393                 u64 = *(guint32 *) va;
394                 break;
395         case MONO_TYPE_U8:
396                 u64 = *(guint64 *) va;
397                 break;
398         case MONO_TYPE_I1:
399                 i64 = *(gint8 *) va;
400                 break;
401         case MONO_TYPE_I2:
402                 i64 = *(gint16 *) va;
403                 break;
404         case MONO_TYPE_I4:
405                 i64 = *(gint32 *) va;
406                 break;
407         case MONO_TYPE_I8:
408                 i64 = *(gint64 *) va;
409                 break;
410         case MONO_TYPE_R4:
411                 r64 = *(gfloat *) va;
412                 break;
413         case MONO_TYPE_R8:
414                 r64 = *(gdouble *) va;
415                 break;
416         case MONO_TYPE_CHAR:
417                 u64 = *(guint16 *) va;
418                 break;
419         case MONO_TYPE_BOOLEAN:
420                 /* Boolean is only compatible with itself. */
421                 switch (et) {
422                 case MONO_TYPE_CHAR:
423                 case MONO_TYPE_U1:
424                 case MONO_TYPE_U2:
425                 case MONO_TYPE_U4:
426                 case MONO_TYPE_U8:
427                 case MONO_TYPE_I1:
428                 case MONO_TYPE_I2:
429                 case MONO_TYPE_I4:
430                 case MONO_TYPE_I8:
431                 case MONO_TYPE_R4:
432                 case MONO_TYPE_R8:
433                         NO_WIDENING_CONVERSION;
434                 default:
435                         INVALID_CAST;
436                 }
437                 break;
438         }
439
440         /* If we can't do a direct copy, let's try a widening conversion. */
441         switch (et) {
442         case MONO_TYPE_CHAR:
443                 ASSIGN_UNSIGNED (guint16);
444         case MONO_TYPE_U1:
445                 ASSIGN_UNSIGNED (guint8);
446         case MONO_TYPE_U2:
447                 ASSIGN_UNSIGNED (guint16);
448         case MONO_TYPE_U4:
449                 ASSIGN_UNSIGNED (guint32);
450         case MONO_TYPE_U8:
451                 ASSIGN_UNSIGNED (guint64);
452         case MONO_TYPE_I1:
453                 ASSIGN_SIGNED (gint8);
454         case MONO_TYPE_I2:
455                 ASSIGN_SIGNED (gint16);
456         case MONO_TYPE_I4:
457                 ASSIGN_SIGNED (gint32);
458         case MONO_TYPE_I8:
459                 ASSIGN_SIGNED (gint64);
460         case MONO_TYPE_R4:
461                 ASSIGN_REAL (gfloat);
462         case MONO_TYPE_R8:
463                 ASSIGN_REAL (gdouble);
464         }
465
466         INVALID_CAST;
467         /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
468         return;
469
470 #undef INVALID_CAST
471 #undef NO_WIDENING_CONVERSION
472 #undef CHECK_WIDENING_CONVERSION
473 #undef ASSIGN_UNSIGNED
474 #undef ASSIGN_SIGNED
475 #undef ASSIGN_REAL
476 }
477
478 static void 
479 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
480                                  MonoArray *idxs)
481 {
482         MonoClass *ac, *ic;
483         gint32 i, pos, *ind;
484
485         MONO_ARCH_SAVE_REGS;
486
487         MONO_CHECK_ARG_NULL (idxs);
488
489         ic = idxs->obj.vtable->klass;
490         ac = this->obj.vtable->klass;
491
492         g_assert (ic->rank == 1);
493         if (idxs->bounds != NULL || idxs->max_length != ac->rank)
494                 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
495
496         ind = (gint32 *)idxs->vector;
497
498         if (this->bounds == NULL) {
499                 if (*ind < 0 || *ind >= this->max_length)
500                         mono_raise_exception (mono_get_exception_index_out_of_range ());
501
502                 ves_icall_System_Array_SetValueImpl (this, value, *ind);
503                 return;
504         }
505         
506         for (i = 0; i < ac->rank; i++)
507                 if ((ind [i] < this->bounds [i].lower_bound) ||
508                     (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
509                         mono_raise_exception (mono_get_exception_index_out_of_range ());
510
511         pos = ind [0] - this->bounds [0].lower_bound;
512         for (i = 1; i < ac->rank; i++)
513                 pos = pos * this->bounds [i].length + ind [i] - 
514                         this->bounds [i].lower_bound;
515
516         ves_icall_System_Array_SetValueImpl (this, value, pos);
517 }
518
519 static MonoArray *
520 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
521 {
522         MonoClass *aklass, *klass;
523         MonoArray *array;
524         uintptr_t *sizes, i;
525         gboolean bounded = FALSE;
526
527         MONO_ARCH_SAVE_REGS;
528
529         MONO_CHECK_ARG_NULL (type);
530         MONO_CHECK_ARG_NULL (lengths);
531
532         MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
533         if (bounds)
534                 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
535
536         for (i = 0; i < mono_array_length (lengths); i++)
537                 if (mono_array_get (lengths, gint32, i) < 0)
538                         mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
539
540         klass = mono_class_from_mono_type (type->type);
541         mono_class_init_or_throw (klass);
542
543         if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
544                 /* vectors are not the same as one dimensional arrays with no-zero bounds */
545                 bounded = TRUE;
546         else
547                 bounded = FALSE;
548
549         aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
550
551         sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
552         for (i = 0; i < aklass->rank; ++i) {
553                 sizes [i] = mono_array_get (lengths, guint32, i);
554                 if (bounds)
555                         sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
556                 else
557                         sizes [i + aklass->rank] = 0;
558         }
559
560         array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
561
562         return array;
563 }
564
565 static MonoArray *
566 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
567 {
568         MonoClass *aklass, *klass;
569         MonoArray *array;
570         uintptr_t *sizes, i;
571         gboolean bounded = FALSE;
572
573         MONO_ARCH_SAVE_REGS;
574
575         MONO_CHECK_ARG_NULL (type);
576         MONO_CHECK_ARG_NULL (lengths);
577
578         MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
579         if (bounds)
580                 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
581
582         for (i = 0; i < mono_array_length (lengths); i++) 
583                 if ((mono_array_get (lengths, gint64, i) < 0) ||
584                     (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
585                         mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
586
587         klass = mono_class_from_mono_type (type->type);
588         mono_class_init_or_throw (klass);
589
590         if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
591                 /* vectors are not the same as one dimensional arrays with no-zero bounds */
592                 bounded = TRUE;
593         else
594                 bounded = FALSE;
595
596         aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
597
598         sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
599         for (i = 0; i < aklass->rank; ++i) {
600                 sizes [i] = mono_array_get (lengths, guint64, i);
601                 if (bounds)
602                         sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
603                 else
604                         sizes [i + aklass->rank] = 0;
605         }
606
607         array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
608
609         return array;
610 }
611
612 static gint32 
613 ves_icall_System_Array_GetRank (MonoObject *this)
614 {
615         MONO_ARCH_SAVE_REGS;
616
617         return this->vtable->klass->rank;
618 }
619
620 static gint32
621 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
622 {
623         gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
624         uintptr_t length;
625
626         MONO_ARCH_SAVE_REGS;
627
628         if ((dimension < 0) || (dimension >= rank))
629                 mono_raise_exception (mono_get_exception_index_out_of_range ());
630         
631         if (this->bounds == NULL)
632                 length = this->max_length;
633         else
634                 length = this->bounds [dimension].length;
635
636 #ifdef MONO_BIG_ARRAYS
637         if (length > G_MAXINT32)
638                 mono_raise_exception (mono_get_exception_overflow ());
639 #endif
640         return length;
641 }
642
643 static gint64
644 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
645 {
646         gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
647
648         MONO_ARCH_SAVE_REGS;
649
650         if ((dimension < 0) || (dimension >= rank))
651                 mono_raise_exception (mono_get_exception_index_out_of_range ());
652         
653         if (this->bounds == NULL)
654                 return this->max_length;
655         
656         return this->bounds [dimension].length;
657 }
658
659 static gint32
660 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
661 {
662         gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
663
664         MONO_ARCH_SAVE_REGS;
665
666         if ((dimension < 0) || (dimension >= rank))
667                 mono_raise_exception (mono_get_exception_index_out_of_range ());
668         
669         if (this->bounds == NULL)
670                 return 0;
671         
672         return this->bounds [dimension].lower_bound;
673 }
674
675 static void
676 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
677 {
678         int sz = mono_array_element_size (mono_object_class (arr));
679         memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
680 }
681
682 static gboolean
683 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
684 {
685         int element_size;
686         void * dest_addr;
687         void * source_addr;
688         MonoClass *src_class;
689         MonoClass *dest_class;
690
691         MONO_ARCH_SAVE_REGS;
692
693         if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
694                 return FALSE;
695
696         if (source->bounds || dest->bounds)
697                 return FALSE;
698
699         /* there's no integer overflow since mono_array_length returns an unsigned integer */
700         if ((dest_idx + length > mono_array_length (dest)) ||
701                 (source_idx + length > mono_array_length (source)))
702                 return FALSE;
703
704         src_class = source->obj.vtable->klass->element_class;
705         dest_class = dest->obj.vtable->klass->element_class;
706
707         /*
708          * Handle common cases.
709          */
710
711         /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
712         if (src_class == mono_defaults.object_class && dest_class->valuetype) {
713                 // FIXME: This is racy
714                 return FALSE;
715                 /*
716                   int i;
717                 int has_refs = dest_class->has_references;
718                 for (i = source_idx; i < source_idx + length; ++i) {
719                         MonoObject *elem = mono_array_get (source, MonoObject*, i);
720                         if (elem && !mono_object_isinst (elem, dest_class))
721                                 return FALSE;
722                 }
723
724                 element_size = mono_array_element_size (dest->obj.vtable->klass);
725                 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
726                 for (i = 0; i < length; ++i) {
727                         MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
728                         void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
729                         if (!elem)
730                                 continue;
731                         if (has_refs)
732                                 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
733                         else
734                                 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
735                 }
736                 return TRUE;
737                 */
738         }
739
740         /* Check if we're copying a char[] <==> (u)short[] */
741         if (src_class != dest_class) {
742                 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
743                         return FALSE;
744
745                 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
746                         ;
747                 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
748                 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE)) {
749                         // FIXME: This is racy
750                         return FALSE;
751                         /*
752                           int i;
753                         for (i = source_idx; i < source_idx + length; ++i) {
754                                 MonoObject *elem = mono_array_get (source, MonoObject*, i);
755                                 if (elem && !mono_object_isinst (elem, dest_class))
756                                         return FALSE;
757                         }
758                         */
759                 } else
760                         return FALSE;
761         }
762
763         if (dest_class->valuetype) {
764                 element_size = mono_array_element_size (source->obj.vtable->klass);
765                 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
766                 if (dest_class->has_references) {
767                         mono_value_copy_array (dest, dest_idx, source_addr, length);
768                 } else {
769                         dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
770                         memmove (dest_addr, source_addr, element_size * length);
771                 }
772         } else {
773                 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
774         }
775
776         return TRUE;
777 }
778
779 static void
780 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
781 {
782         MonoClass *ac;
783         MonoArray *ao;
784         gint32 esize;
785         gpointer *ea;
786
787         MONO_ARCH_SAVE_REGS;
788
789         ao = (MonoArray *)this;
790         ac = (MonoClass *)ao->obj.vtable->klass;
791
792         esize = mono_array_element_size (ac);
793         ea = (gpointer*)((char*)ao->vector + (pos * esize));
794
795         memcpy (value, ea, esize);
796 }
797
798 static void
799 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
800 {
801         MonoClass *ac, *ec;
802         MonoArray *ao;
803         gint32 esize;
804         gpointer *ea;
805
806         MONO_ARCH_SAVE_REGS;
807
808         ao = (MonoArray *)this;
809         ac = (MonoClass *)ao->obj.vtable->klass;
810         ec = ac->element_class;
811
812         esize = mono_array_element_size (ac);
813         ea = (gpointer*)((char*)ao->vector + (pos * esize));
814
815         if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
816                 g_assert (esize == sizeof (gpointer));
817                 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
818         } else {
819                 g_assert (ec->inited);
820                 g_assert (esize == mono_class_value_size (ec, NULL));
821                 if (ec->has_references)
822                         mono_gc_wbarrier_value_copy (ea, value, 1, ec);
823                 else
824                         memcpy (ea, value, esize);
825         }
826 }
827
828 static void
829 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
830 {
831         MonoClass *klass = array->obj.vtable->klass;
832         guint32 size = mono_array_element_size (klass);
833         MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
834         int align;
835         const char *field_data;
836
837         if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
838                 MonoException *exc = mono_get_exception_argument("array",
839                         "Cannot initialize array of non-primitive type.");
840                 mono_raise_exception (exc);
841         }
842
843         if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
844                 MonoException *exc = mono_get_exception_argument("field_handle",
845                         "Field doesn't have an RVA");
846                 mono_raise_exception (exc);
847         }
848
849         size *= array->max_length;
850         field_data = mono_field_get_data (field_handle);
851
852         if (size > mono_type_size (field_handle->type, &align)) {
853                 MonoException *exc = mono_get_exception_argument("field_handle",
854                         "Field not large enough to fill array");
855                 mono_raise_exception (exc);
856         }
857
858 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
859 #define SWAP(n) {\
860         guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
861         guint ## n *src = (guint ## n *) field_data; \
862         guint ## n *end = (guint ## n *)((char*)src + size); \
863 \
864         for (; src < end; data++, src++) { \
865                 *data = read ## n (src); \
866         } \
867 }
868
869         /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
870
871         switch (type->type) {
872         case MONO_TYPE_CHAR:
873         case MONO_TYPE_I2:
874         case MONO_TYPE_U2:
875                 SWAP (16);
876                 break;
877         case MONO_TYPE_I4:
878         case MONO_TYPE_U4:
879         case MONO_TYPE_R4:
880                 SWAP (32);
881                 break;
882         case MONO_TYPE_I8:
883         case MONO_TYPE_U8:
884         case MONO_TYPE_R8:
885                 SWAP (64);
886                 break;
887         default:
888                 memcpy (mono_array_addr (array, char, 0), field_data, size);
889                 break;
890         }
891 #else
892         memcpy (mono_array_addr (array, char, 0), field_data, size);
893 #ifdef ARM_FPU_FPA
894         if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
895                 gint i;
896                 double tmp;
897                 double *data = (double*)mono_array_addr (array, double, 0);
898
899                 for (i = 0; i < size; i++, data++) {
900                         readr8 (data, &tmp);
901                         *data = tmp;
902                 }
903         }
904 #endif
905 #endif
906 }
907
908 static gint
909 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
910 {
911         MONO_ARCH_SAVE_REGS;
912
913         return offsetof (MonoString, chars);
914 }
915
916 static MonoObject *
917 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
918 {
919         MONO_ARCH_SAVE_REGS;
920
921         if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
922                 return obj;
923         else
924                 return mono_object_clone (obj);
925 }
926
927 static void
928 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
929 {
930         MonoClass *klass;
931         MonoVTable *vtable;
932
933         MONO_CHECK_ARG_NULL (handle);
934
935         klass = mono_class_from_mono_type (handle);
936         MONO_CHECK_ARG (handle, klass);
937
938         vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
939
940         /* This will call the type constructor */
941         mono_runtime_class_init (vtable);
942 }
943
944 static void
945 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
946 {
947         MONO_ARCH_SAVE_REGS;
948
949         mono_image_check_for_module_cctor (image);
950         if (image->has_module_cctor) {
951                 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
952                 /*It's fine to raise the exception here*/
953                 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
954         }
955 }
956
957 static MonoBoolean
958 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
959 {
960         guint8 *stack_addr;
961         guint8 *current;
962         size_t stack_size;
963         /* later make this configurable and per-arch */
964         int min_size = 4096 * 4 * sizeof (void*);
965         mono_thread_get_stack_bounds (&stack_addr, &stack_size);
966         /* if we have no info we are optimistic and assume there is enough room */
967         if (!stack_addr)
968                 return TRUE;
969         current = (guint8 *)&stack_addr;
970         if (current > stack_addr) {
971                 if ((current - stack_addr) < min_size)
972                         return FALSE;
973         } else {
974                 if (current - (stack_addr - stack_size) < min_size)
975                         return FALSE;
976         }
977         return TRUE;
978 }
979
980 static MonoObject *
981 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
982 {
983         MONO_ARCH_SAVE_REGS;
984
985         return mono_object_clone (this);
986 }
987
988 static gint32
989 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
990 {
991         MonoClass *klass;
992         MonoObject **values = NULL;
993         MonoObject *o;
994         int count = 0;
995         gint32 result = 0;
996         MonoClassField* field;
997         gpointer iter;
998
999         MONO_ARCH_SAVE_REGS;
1000
1001         klass = mono_object_class (this);
1002
1003         if (mono_class_num_fields (klass) == 0)
1004                 return mono_object_hash (this);
1005
1006         /*
1007          * Compute the starting value of the hashcode for fields of primitive
1008          * types, and return the remaining fields in an array to the managed side.
1009          * This way, we can avoid costly reflection operations in managed code.
1010          */
1011         iter = NULL;
1012         while ((field = mono_class_get_fields (klass, &iter))) {
1013                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1014                         continue;
1015                 if (mono_field_is_deleted (field))
1016                         continue;
1017                 /* FIXME: Add more types */
1018                 switch (field->type->type) {
1019                 case MONO_TYPE_I4:
1020                         result ^= *(gint32*)((guint8*)this + field->offset);
1021                         break;
1022                 case MONO_TYPE_STRING: {
1023                         MonoString *s;
1024                         s = *(MonoString**)((guint8*)this + field->offset);
1025                         if (s != NULL)
1026                                 result ^= mono_string_hash (s);
1027                         break;
1028                 }
1029                 default:
1030                         if (!values)
1031                                 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1032                         o = mono_field_get_value_object (mono_object_domain (this), field, this);
1033                         values [count++] = o;
1034                 }
1035         }
1036
1037         if (values) {
1038                 int i;
1039                 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1040                 for (i = 0; i < count; ++i)
1041                         mono_array_setref (*fields, i, values [i]);
1042         } else {
1043                 *fields = NULL;
1044         }
1045         return result;
1046 }
1047
1048 static MonoBoolean
1049 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1050 {
1051         MonoClass *klass;
1052         MonoObject **values = NULL;
1053         MonoObject *o;
1054         MonoClassField* field;
1055         gpointer iter;
1056         int count = 0;
1057
1058         MONO_ARCH_SAVE_REGS;
1059
1060         MONO_CHECK_ARG_NULL (that);
1061
1062         if (this->vtable != that->vtable)
1063                 return FALSE;
1064
1065         klass = mono_object_class (this);
1066
1067         if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1068                 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1069
1070         /*
1071          * Do the comparison for fields of primitive type and return a result if
1072          * possible. Otherwise, return the remaining fields in an array to the 
1073          * managed side. This way, we can avoid costly reflection operations in 
1074          * managed code.
1075          */
1076         *fields = NULL;
1077         iter = NULL;
1078         while ((field = mono_class_get_fields (klass, &iter))) {
1079                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1080                         continue;
1081                 if (mono_field_is_deleted (field))
1082                         continue;
1083                 /* FIXME: Add more types */
1084                 switch (field->type->type) {
1085                 case MONO_TYPE_U1:
1086                 case MONO_TYPE_I1:
1087                 case MONO_TYPE_BOOLEAN:
1088                         if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1089                                 return FALSE;
1090                         break;
1091                 case MONO_TYPE_U2:
1092                 case MONO_TYPE_I2:
1093                 case MONO_TYPE_CHAR:
1094                         if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1095                                 return FALSE;
1096                         break;
1097                 case MONO_TYPE_U4:
1098                 case MONO_TYPE_I4:
1099                         if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1100                                 return FALSE;
1101                         break;
1102                 case MONO_TYPE_U8:
1103                 case MONO_TYPE_I8:
1104                         if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1105                                 return FALSE;
1106                         break;
1107                 case MONO_TYPE_R4:
1108                         if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1109                                 return FALSE;
1110                         break;
1111                 case MONO_TYPE_R8:
1112                         if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1113                                 return FALSE;
1114                         break;
1115
1116
1117                 case MONO_TYPE_STRING: {
1118                         MonoString *s1, *s2;
1119                         guint32 s1len, s2len;
1120                         s1 = *(MonoString**)((guint8*)this + field->offset);
1121                         s2 = *(MonoString**)((guint8*)that + field->offset);
1122                         if (s1 == s2)
1123                                 break;
1124                         if ((s1 == NULL) || (s2 == NULL))
1125                                 return FALSE;
1126                         s1len = mono_string_length (s1);
1127                         s2len = mono_string_length (s2);
1128                         if (s1len != s2len)
1129                                 return FALSE;
1130
1131                         if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1132                                 return FALSE;
1133                         break;
1134                 }
1135                 default:
1136                         if (!values)
1137                                 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1138                         o = mono_field_get_value_object (mono_object_domain (this), field, this);
1139                         values [count++] = o;
1140                         o = mono_field_get_value_object (mono_object_domain (this), field, that);
1141                         values [count++] = o;
1142                 }
1143
1144                 if (klass->enumtype)
1145                         /* enums only have one non-static field */
1146                         break;
1147         }
1148
1149         if (values) {
1150                 int i;
1151                 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1152                 for (i = 0; i < count; ++i)
1153                         mono_array_setref (*fields, i, values [i]);
1154                 return FALSE;
1155         } else {
1156                 return TRUE;
1157         }
1158 }
1159
1160 static MonoReflectionType *
1161 ves_icall_System_Object_GetType (MonoObject *obj)
1162 {
1163         MONO_ARCH_SAVE_REGS;
1164
1165         if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1166                 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1167         else
1168                 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1169 }
1170
1171 static void
1172 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1173 {
1174         MONO_ARCH_SAVE_REGS;
1175
1176         mtype->type = &obj->vtable->klass->byval_arg;
1177         g_assert (mtype->type->type);
1178 }
1179
1180 static gint32
1181 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1182 {
1183         MONO_ARCH_SAVE_REGS;
1184         
1185         MONO_CHECK_ARG_NULL (obj);
1186         
1187         return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1188 }
1189
1190 static gint32
1191 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1192                                         MonoReflectionMethod *method,
1193                                         MonoArray *opt_param_types)
1194 {
1195         MONO_ARCH_SAVE_REGS;
1196
1197         MONO_CHECK_ARG_NULL (method);
1198         
1199         return mono_image_create_method_token (
1200                 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1201 }
1202
1203 static void
1204 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1205 {
1206         MONO_ARCH_SAVE_REGS;
1207
1208         mono_image_create_pefile (mb, file);
1209 }
1210
1211 static void
1212 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1213 {
1214         MONO_ARCH_SAVE_REGS;
1215
1216         mono_image_build_metadata (mb);
1217 }
1218
1219 static void
1220 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1221 {
1222         MONO_ARCH_SAVE_REGS;
1223
1224         mono_image_register_token (mb->dynamic_image, token, obj);
1225 }
1226
1227 static gboolean
1228 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1229 {
1230         MonoMethod **dest = data;
1231
1232         /* skip unmanaged frames */
1233         if (!managed)
1234                 return FALSE;
1235
1236         if (m == *dest) {
1237                 *dest = NULL;
1238                 return FALSE;
1239         }
1240         if (!(*dest)) {
1241                 *dest = m;
1242                 return TRUE;
1243         }
1244         return FALSE;
1245 }
1246
1247 static gboolean
1248 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1249 {
1250         MonoMethod **dest = data;
1251
1252         /* skip unmanaged frames */
1253         if (!managed)
1254                 return FALSE;
1255
1256         if (!(*dest)) {
1257                 if (!strcmp (m->klass->name_space, "System.Reflection"))
1258                         return FALSE;
1259                 *dest = m;
1260                 return TRUE;
1261         }
1262         return FALSE;
1263 }
1264
1265 static gboolean
1266 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1267 {
1268         MonoMethod **dest = data;
1269
1270         /* skip unmanaged frames */
1271         if (!managed)
1272                 return FALSE;
1273
1274         if (m->wrapper_type != MONO_WRAPPER_NONE)
1275                 return FALSE;
1276
1277         if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1278                 return FALSE;
1279
1280         if (m == *dest) {
1281                 *dest = NULL;
1282                 return FALSE;
1283         }
1284         if (!(*dest)) {
1285                 *dest = m;
1286                 return TRUE;
1287         }
1288         return FALSE;
1289 }
1290
1291 static MonoReflectionType *
1292 type_from_name (const char *str, MonoBoolean ignoreCase)
1293 {
1294         MonoType *type = NULL;
1295         MonoAssembly *assembly = NULL;
1296         MonoTypeNameParse info;
1297         char *temp_str = g_strdup (str);
1298         gboolean type_resolve = FALSE;
1299
1300         MONO_ARCH_SAVE_REGS;
1301
1302         /* mono_reflection_parse_type() mangles the string */
1303         if (!mono_reflection_parse_type (temp_str, &info)) {
1304                 mono_reflection_free_type_info (&info);
1305                 g_free (temp_str);
1306                 return NULL;
1307         }
1308
1309         if (info.assembly.name) {
1310                 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1311         } else {
1312                 MonoMethod *m = mono_method_get_last_managed ();
1313                 MonoMethod *dest = m;
1314
1315                 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1316                 if (!dest)
1317                         dest = m;
1318
1319                 /*
1320                  * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1321                  *        causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1322                  *        to crash.  This only seems to happen in some strange remoting
1323                  *        scenarios and I was unable to figure out what's happening there.
1324                  *        Dec 10, 2005 - Martin.
1325                  */
1326
1327                 if (dest) {
1328                         assembly = dest->klass->image->assembly;
1329                         type_resolve = TRUE;
1330                 } else {
1331                         g_warning (G_STRLOC);
1332                 }
1333         }
1334
1335         if (assembly) {
1336                 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1337                 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1338         }
1339
1340         if (!info.assembly.name && !type) /* try mscorlib */
1341                 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1342
1343         if (assembly && !type && type_resolve) {
1344                 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1345                 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1346         }
1347
1348         mono_reflection_free_type_info (&info);
1349         g_free (temp_str);
1350
1351         if (!type) 
1352                 return NULL;
1353
1354         return mono_type_get_object (mono_domain_get (), type);
1355 }
1356
1357 #ifdef UNUSED
1358 MonoReflectionType *
1359 mono_type_get (const char *str)
1360 {
1361         char *copy = g_strdup (str);
1362         MonoReflectionType *type = type_from_name (copy, FALSE);
1363
1364         g_free (copy);
1365         return type;
1366 }
1367 #endif
1368
1369 static MonoReflectionType*
1370 ves_icall_type_from_name (MonoString *name,
1371                           MonoBoolean throwOnError,
1372                           MonoBoolean ignoreCase)
1373 {
1374         char *str = mono_string_to_utf8 (name);
1375         MonoReflectionType *type;
1376
1377         type = type_from_name (str, ignoreCase);
1378         g_free (str);
1379         if (type == NULL){
1380                 MonoException *e = NULL;
1381                 
1382                 if (throwOnError)
1383                         e = mono_get_exception_type_load (name, NULL);
1384
1385                 mono_loader_clear_error ();
1386                 if (e != NULL)
1387                         mono_raise_exception (e);
1388         }
1389         
1390         return type;
1391 }
1392
1393
1394 static MonoReflectionType*
1395 ves_icall_type_from_handle (MonoType *handle)
1396 {
1397         MonoDomain *domain = mono_domain_get (); 
1398
1399         MONO_ARCH_SAVE_REGS;
1400
1401         return mono_type_get_object (domain, handle);
1402 }
1403
1404 static MonoBoolean
1405 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1406 {
1407         MONO_ARCH_SAVE_REGS;
1408
1409         if (c && type->type && c->type)
1410                 return mono_metadata_type_equal (type->type, c->type);
1411         else
1412                 return (type == c) ? TRUE : FALSE;
1413 }
1414
1415 /* System.TypeCode */
1416 typedef enum {
1417         TYPECODE_EMPTY,
1418         TYPECODE_OBJECT,
1419         TYPECODE_DBNULL,
1420         TYPECODE_BOOLEAN,
1421         TYPECODE_CHAR,
1422         TYPECODE_SBYTE,
1423         TYPECODE_BYTE,
1424         TYPECODE_INT16,
1425         TYPECODE_UINT16,
1426         TYPECODE_INT32,
1427         TYPECODE_UINT32,
1428         TYPECODE_INT64,
1429         TYPECODE_UINT64,
1430         TYPECODE_SINGLE,
1431         TYPECODE_DOUBLE,
1432         TYPECODE_DECIMAL,
1433         TYPECODE_DATETIME,
1434         TYPECODE_STRING = 18
1435 } TypeCode;
1436
1437 static guint32
1438 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1439 {
1440         int t = type->type->type;
1441
1442         MONO_ARCH_SAVE_REGS;
1443
1444         if (type->type->byref)
1445                 return TYPECODE_OBJECT;
1446
1447 handle_enum:
1448         switch (t) {
1449         case MONO_TYPE_VOID:
1450                 return TYPECODE_OBJECT;
1451         case MONO_TYPE_BOOLEAN:
1452                 return TYPECODE_BOOLEAN;
1453         case MONO_TYPE_U1:
1454                 return TYPECODE_BYTE;
1455         case MONO_TYPE_I1:
1456                 return TYPECODE_SBYTE;
1457         case MONO_TYPE_U2:
1458                 return TYPECODE_UINT16;
1459         case MONO_TYPE_I2:
1460                 return TYPECODE_INT16;
1461         case MONO_TYPE_CHAR:
1462                 return TYPECODE_CHAR;
1463         case MONO_TYPE_PTR:
1464         case MONO_TYPE_U:
1465         case MONO_TYPE_I:
1466                 return TYPECODE_OBJECT;
1467         case MONO_TYPE_U4:
1468                 return TYPECODE_UINT32;
1469         case MONO_TYPE_I4:
1470                 return TYPECODE_INT32;
1471         case MONO_TYPE_U8:
1472                 return TYPECODE_UINT64;
1473         case MONO_TYPE_I8:
1474                 return TYPECODE_INT64;
1475         case MONO_TYPE_R4:
1476                 return TYPECODE_SINGLE;
1477         case MONO_TYPE_R8:
1478                 return TYPECODE_DOUBLE;
1479         case MONO_TYPE_VALUETYPE: {
1480                 MonoClass *klass = type->type->data.klass;
1481                 
1482                 if (klass->enumtype) {
1483                         t = mono_class_enum_basetype (klass)->type;
1484                         goto handle_enum;
1485                 } else if (mono_is_corlib_image (klass->image)) {
1486                         if (strcmp (klass->name_space, "System") == 0) {
1487                                 if (strcmp (klass->name, "Decimal") == 0)
1488                                         return TYPECODE_DECIMAL;
1489                                 else if (strcmp (klass->name, "DateTime") == 0)
1490                                         return TYPECODE_DATETIME;
1491                         }
1492                 }
1493                 return TYPECODE_OBJECT;
1494         }
1495         case MONO_TYPE_STRING:
1496                 return TYPECODE_STRING;
1497         case MONO_TYPE_SZARRAY:
1498         case MONO_TYPE_ARRAY:
1499         case MONO_TYPE_OBJECT:
1500         case MONO_TYPE_VAR:
1501         case MONO_TYPE_MVAR:
1502         case MONO_TYPE_TYPEDBYREF:
1503                 return TYPECODE_OBJECT;
1504         case MONO_TYPE_CLASS:
1505                 {
1506                         MonoClass *klass =  type->type->data.klass;
1507                         if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1508                                 if (strcmp (klass->name, "DBNull") == 0)
1509                                         return TYPECODE_DBNULL;
1510                         }
1511                 }
1512                 return TYPECODE_OBJECT;
1513         case MONO_TYPE_GENERICINST:
1514                 return TYPECODE_OBJECT;
1515         default:
1516                 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1517         }
1518         return 0;
1519 }
1520
1521 static guint32
1522 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1523 {
1524         MonoDomain *domain; 
1525         MonoClass *klass;
1526         MonoClass *klassc;
1527
1528         MONO_ARCH_SAVE_REGS;
1529
1530         g_assert (type != NULL);
1531         
1532         domain = ((MonoObject *)type)->vtable->domain;
1533
1534         if (!c) /* FIXME: dont know what do do here */
1535                 return 0;
1536
1537         klass = mono_class_from_mono_type (type->type);
1538         klassc = mono_class_from_mono_type (c->type);
1539
1540         /* Interface check requires a more complex setup so we
1541          * only do for them. Otherwise we simply avoid mono_class_init.
1542          */
1543         if (check_interfaces) {
1544                 mono_class_init_or_throw (klass);
1545                 mono_class_init_or_throw (klassc);
1546         } else if (!klass->supertypes || !klassc->supertypes) {
1547                 mono_loader_lock ();
1548                 mono_class_setup_supertypes (klass);
1549                 mono_class_setup_supertypes (klassc);
1550                 mono_loader_unlock ();
1551         }
1552
1553         if (type->type->byref)
1554                 return klassc == mono_defaults.object_class;
1555
1556         return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1557 }
1558
1559 static gboolean
1560 mono_type_is_primitive (MonoType *type)
1561 {
1562         return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1563                         type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1564 }
1565
1566 static MonoType*
1567 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1568 {
1569         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1570                 return mono_class_enum_basetype (type->data.klass);
1571         if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1572                 return mono_class_enum_basetype (type->data.generic_class->container_class);
1573         return type;
1574 }
1575
1576 static guint32
1577 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1578 {
1579         MonoDomain *domain; 
1580         MonoClass *klass;
1581         MonoClass *klassc;
1582
1583         MONO_ARCH_SAVE_REGS;
1584
1585         g_assert (type != NULL);
1586         
1587         domain = ((MonoObject *)type)->vtable->domain;
1588
1589         klass = mono_class_from_mono_type (type->type);
1590         klassc = mono_class_from_mono_type (c->type);
1591
1592         mono_class_init_or_throw (klass);
1593         mono_class_init_or_throw (klassc);
1594
1595         if (type->type->byref ^ c->type->byref)
1596                 return FALSE;
1597
1598         if (type->type->byref) {
1599                 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1600                 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1601
1602                 klass = mono_class_from_mono_type (t);
1603                 klassc = mono_class_from_mono_type (ot);
1604
1605                 if (mono_type_is_primitive (t)) {
1606                         return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1607                 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1608                         return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1609                 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1610                         return t->type == ot->type;
1611                 } else {
1612                          if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1613                                  return FALSE;
1614
1615                          if (klass->valuetype)
1616                                 return klass == klassc;
1617                         return klass->valuetype == klassc->valuetype;
1618                 }
1619         }
1620         return mono_class_is_assignable_from (klass, klassc);
1621 }
1622
1623 static guint32
1624 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1625 {
1626         MonoClass *klass = mono_class_from_mono_type (type->type);
1627         mono_class_init_or_throw (klass);
1628         return mono_object_isinst (obj, klass) != NULL;
1629 }
1630
1631 static guint32
1632 ves_icall_get_attributes (MonoReflectionType *type)
1633 {
1634         MonoClass *klass = mono_class_from_mono_type (type->type);
1635         return klass->flags;
1636 }
1637
1638 static MonoReflectionMarshal*
1639 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1640 {
1641         MonoClass *klass = field->field->parent;
1642         MonoMarshalType *info;
1643         int i;
1644
1645         if (klass->generic_container ||
1646             (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1647                 return NULL;
1648
1649         info = mono_marshal_load_type_info (klass);
1650
1651         for (i = 0; i < info->num_fields; ++i) {
1652                 if (info->fields [i].field == field->field) {
1653                         if (!info->fields [i].mspec)
1654                                 return NULL;
1655                         else
1656                                 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1657                 }
1658         }
1659
1660         return NULL;
1661 }
1662
1663 static MonoReflectionField*
1664 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1665 {
1666         gboolean found = FALSE;
1667         MonoClass *klass;
1668         MonoClass *k;
1669
1670         g_assert (handle);
1671
1672         if (!type) {
1673                 klass = handle->parent;
1674         } else {
1675                 klass = mono_class_from_mono_type (type);
1676
1677                 /* Check that the field belongs to the class */
1678                 for (k = klass; k; k = k->parent) {
1679                         if (k == handle->parent) {
1680                                 found = TRUE;
1681                                 break;
1682                         }
1683                 }
1684
1685                 if (!found)
1686                         /* The managed code will throw the exception */
1687                         return NULL;
1688         }
1689
1690         return mono_field_get_object (mono_domain_get (), klass, handle);
1691 }
1692
1693 static MonoArray*
1694 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1695 {
1696         MonoError error;
1697         MonoType *type = mono_field_get_type_checked (field->field, &error);
1698         if (!mono_error_ok (&error))
1699                 mono_error_raise_exception (&error);
1700
1701         return type_array_from_modifiers (field->field->parent->image, type, optional);
1702 }
1703
1704 static int
1705 vell_icall_get_method_attributes (MonoMethod *method)
1706 {
1707         return method->flags;
1708 }
1709
1710 static void
1711 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1712 {
1713         MonoError error;
1714         MonoDomain *domain = mono_domain_get ();
1715         MonoMethodSignature* sig;
1716         MONO_ARCH_SAVE_REGS;
1717
1718         sig = mono_method_signature_checked (method, &error);
1719         if (!mono_error_ok (&error))
1720                 mono_error_raise_exception (&error);
1721
1722
1723         MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1724         MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1725         info->attrs = method->flags;
1726         info->implattrs = method->iflags;
1727         if (sig->call_convention == MONO_CALL_DEFAULT)
1728                 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1729         else {
1730                 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1731                         info->callconv = 2;
1732                 else
1733                         info->callconv = 1;
1734         }
1735         info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6); 
1736 }
1737
1738 static MonoArray*
1739 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1740 {
1741         MonoDomain *domain = mono_domain_get (); 
1742
1743         return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1744 }
1745
1746 static MonoReflectionMarshal*
1747 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1748 {
1749         MonoDomain *domain = mono_domain_get (); 
1750         MonoReflectionMarshal* res = NULL;
1751         MonoMarshalSpec **mspecs;
1752         int i;
1753
1754         mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1755         mono_method_get_marshal_info (method, mspecs);
1756
1757         if (mspecs [0])
1758                 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1759                 
1760         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1761                 if (mspecs [i])
1762                         mono_metadata_free_marshal_spec (mspecs [i]);
1763         g_free (mspecs);
1764
1765         return res;
1766 }
1767
1768 static gint32
1769 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1770 {
1771         MonoClass *parent = field->field->parent;
1772         if (!parent->size_inited)
1773                 mono_class_init (parent);
1774
1775         return field->field->offset - sizeof (MonoObject);
1776 }
1777
1778 static MonoReflectionType*
1779 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1780 {
1781         MonoClass *parent;
1782         MONO_ARCH_SAVE_REGS;
1783
1784         parent = declaring? field->field->parent: field->klass;
1785
1786         return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1787 }
1788
1789 static MonoObject *
1790 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1791 {       
1792         MonoClass *fklass = field->klass;
1793         MonoClassField *cf = field->field;
1794         MonoDomain *domain = mono_object_domain (field);
1795
1796         if (fklass->image->assembly->ref_only)
1797                 mono_raise_exception (mono_get_exception_invalid_operation (
1798                                         "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1799
1800         if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1801                 mono_security_core_clr_ensure_reflection_access_field (cf);
1802
1803         return mono_field_get_value_object (domain, cf, obj);
1804 }
1805
1806 static void
1807 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1808 {
1809         MonoError error;
1810         MonoClassField *cf = field->field;
1811         MonoType *type;
1812         gchar *v;
1813
1814         MONO_ARCH_SAVE_REGS;
1815
1816         if (field->klass->image->assembly->ref_only)
1817                 mono_raise_exception (mono_get_exception_invalid_operation (
1818                                         "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1819
1820         if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1821                 mono_security_core_clr_ensure_reflection_access_field (cf);
1822
1823         type = mono_field_get_type_checked (cf, &error);
1824         if (!mono_error_ok (&error))
1825                 mono_error_raise_exception (&error);
1826
1827         v = (gchar *) value;
1828         if (!type->byref) {
1829                 switch (type->type) {
1830                 case MONO_TYPE_U1:
1831                 case MONO_TYPE_I1:
1832                 case MONO_TYPE_BOOLEAN:
1833                 case MONO_TYPE_U2:
1834                 case MONO_TYPE_I2:
1835                 case MONO_TYPE_CHAR:
1836                 case MONO_TYPE_U:
1837                 case MONO_TYPE_I:
1838                 case MONO_TYPE_U4:
1839                 case MONO_TYPE_I4:
1840                 case MONO_TYPE_R4:
1841                 case MONO_TYPE_U8:
1842                 case MONO_TYPE_I8:
1843                 case MONO_TYPE_R8:
1844                 case MONO_TYPE_VALUETYPE:
1845                 case MONO_TYPE_PTR:
1846                         if (v != NULL)
1847                                 v += sizeof (MonoObject);
1848                         break;
1849                 case MONO_TYPE_STRING:
1850                 case MONO_TYPE_OBJECT:
1851                 case MONO_TYPE_CLASS:
1852                 case MONO_TYPE_ARRAY:
1853                 case MONO_TYPE_SZARRAY:
1854                         /* Do nothing */
1855                         break;
1856                 case MONO_TYPE_GENERICINST: {
1857                         MonoGenericClass *gclass = type->data.generic_class;
1858                         g_assert (!gclass->context.class_inst->is_open);
1859
1860                         if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1861                                 MonoClass *nklass = mono_class_from_mono_type (type);
1862                                 MonoObject *nullable;
1863
1864                                 /* 
1865                                  * Convert the boxed vtype into a Nullable structure.
1866                                  * This is complicated by the fact that Nullables have
1867                                  * a variable structure.
1868                                  */
1869                                 nullable = mono_object_new (mono_domain_get (), nklass);
1870
1871                                 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1872
1873                                 v = mono_object_unbox (nullable);
1874                         }
1875                         else 
1876                                 if (gclass->container_class->valuetype && (v != NULL))
1877                                         v += sizeof (MonoObject);
1878                         break;
1879                 }
1880                 default:
1881                         g_error ("type 0x%x not handled in "
1882                                  "ves_icall_FieldInfo_SetValueInternal", type->type);
1883                         return;
1884                 }
1885         }
1886
1887         if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1888                 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1889                 if (!vtable->initialized)
1890                         mono_runtime_class_init (vtable);
1891                 mono_field_static_set_value (vtable, cf, v);
1892         } else {
1893                 mono_field_set_value (obj, cf, v);
1894         }
1895 }
1896
1897 static MonoObject *
1898 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1899 {       
1900         MonoObject *o = NULL;
1901         MonoClassField *field = this->field;
1902         MonoClass *klass;
1903         MonoDomain *domain = mono_object_domain (this); 
1904         gchar *v;
1905         MonoTypeEnum def_type;
1906         const char *def_value;
1907
1908         MONO_ARCH_SAVE_REGS;
1909         
1910         mono_class_init (field->parent);
1911
1912         if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1913                 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1914
1915         if (field->parent->image->dynamic) {
1916                 /* FIXME: */
1917                 g_assert_not_reached ();
1918         }
1919
1920         def_value = mono_class_get_field_default_value (field, &def_type);
1921
1922         /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1923         switch (def_type) {
1924         case MONO_TYPE_U1:
1925         case MONO_TYPE_I1:
1926         case MONO_TYPE_BOOLEAN:
1927         case MONO_TYPE_U2:
1928         case MONO_TYPE_I2:
1929         case MONO_TYPE_CHAR:
1930         case MONO_TYPE_U:
1931         case MONO_TYPE_I:
1932         case MONO_TYPE_U4:
1933         case MONO_TYPE_I4:
1934         case MONO_TYPE_R4:
1935         case MONO_TYPE_U8:
1936         case MONO_TYPE_I8:
1937         case MONO_TYPE_R8: {
1938                 MonoType *t;
1939
1940                 /* boxed value type */
1941                 t = g_new0 (MonoType, 1);
1942                 t->type = def_type;
1943                 klass = mono_class_from_mono_type (t);
1944                 g_free (t);
1945                 o = mono_object_new (domain, klass);
1946                 v = ((gchar *) o) + sizeof (MonoObject);
1947                 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1948                 break;
1949         }
1950         case MONO_TYPE_STRING:
1951         case MONO_TYPE_CLASS:
1952                 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1953                 break;
1954         default:
1955                 g_assert_not_reached ();
1956         }
1957
1958         return o;
1959 }
1960
1961 static MonoReflectionType*
1962 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1963 {
1964         MonoError error;
1965         MonoClassField *field = ref_field->field;
1966         MonoType *type = mono_field_get_type_checked (field, &error);
1967         if (!mono_error_ok (&error))
1968                 mono_error_raise_exception (&error);
1969         return mono_type_get_object (mono_object_domain (ref_field), type);
1970 }
1971
1972 static MonoReflectionType*
1973 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1974 {
1975         MonoMethod *method = rmethod->method.method;
1976
1977         return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1978 }
1979
1980 /* From MonoProperty.cs */
1981 typedef enum {
1982         PInfo_Attributes = 1,
1983         PInfo_GetMethod  = 1 << 1,
1984         PInfo_SetMethod  = 1 << 2,
1985         PInfo_ReflectedType = 1 << 3,
1986         PInfo_DeclaringType = 1 << 4,
1987         PInfo_Name = 1 << 5
1988 } PInfo;
1989
1990 static void
1991 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1992 {
1993         MonoDomain *domain = mono_object_domain (property); 
1994
1995         MONO_ARCH_SAVE_REGS;
1996
1997         if ((req_info & PInfo_ReflectedType) != 0)
1998                 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1999         if ((req_info & PInfo_DeclaringType) != 0)
2000                 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
2001
2002         if ((req_info & PInfo_Name) != 0)
2003                 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2004
2005         if ((req_info & PInfo_Attributes) != 0)
2006                 info->attrs = property->property->attrs;
2007
2008         if ((req_info & PInfo_GetMethod) != 0)
2009                 MONO_STRUCT_SETREF (info, get, property->property->get ?
2010                                                         mono_method_get_object (domain, property->property->get, property->klass): NULL);
2011         
2012         if ((req_info & PInfo_SetMethod) != 0)
2013                 MONO_STRUCT_SETREF (info, set, property->property->set ?
2014                                                         mono_method_get_object (domain, property->property->set, property->klass): NULL);
2015         /* 
2016          * There may be other methods defined for properties, though, it seems they are not exposed 
2017          * in the reflection API 
2018          */
2019 }
2020
2021 static void
2022 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2023 {
2024         MonoDomain *domain = mono_object_domain (event); 
2025
2026         MONO_ARCH_SAVE_REGS;
2027
2028         MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2029         MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2030
2031         MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2032         info->attrs = event->event->attrs;
2033         MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2034         MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2035         MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2036
2037 #ifndef MONO_SMALL_CONFIG
2038         if (event->event->other) {
2039                 int i, n = 0;
2040                 while (event->event->other [n])
2041                         n++;
2042                 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2043
2044                 for (i = 0; i < n; i++)
2045                         mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2046         }               
2047 #endif
2048 }
2049
2050 static void
2051 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2052 {
2053         int i;
2054         MonoClass *ic;
2055
2056         mono_class_setup_interfaces (klass, error);
2057         if (!mono_error_ok (error))
2058                 return;
2059
2060         for (i = 0; i < klass->interface_count; i++) {
2061                 ic = klass->interfaces [i];
2062                 g_hash_table_insert (ifaces, ic, ic);
2063
2064                 collect_interfaces (ic, ifaces, error);
2065                 if (!mono_error_ok (error))
2066                         return;
2067         }
2068 }
2069
2070 typedef struct {
2071         MonoArray *iface_array;
2072         MonoGenericContext *context;
2073         MonoError *error;
2074         MonoDomain *domain;
2075         int next_idx;
2076 } FillIfaceArrayData;
2077
2078 static void
2079 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2080 {
2081         FillIfaceArrayData *data = user_data;
2082         MonoClass *ic = key;
2083         MonoType *ret = &ic->byval_arg, *inflated = NULL;
2084
2085         if (!mono_error_ok (data->error))
2086                 return;
2087
2088         if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2089                 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2090                 if (!mono_error_ok (data->error))
2091                         return;
2092         }
2093
2094         mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2095
2096         if (inflated)
2097                 mono_metadata_free_type (inflated);
2098 }
2099
2100 static MonoArray*
2101 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2102 {
2103         MonoError error;
2104         MonoClass *class = mono_class_from_mono_type (type->type);
2105         MonoClass *parent;
2106         FillIfaceArrayData data = { 0 };
2107         int len;
2108
2109         GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2110
2111         if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2112                 data.context = mono_class_get_context (class);
2113                 class = class->generic_class->container_class;
2114         }
2115
2116         for (parent = class; parent; parent = parent->parent) {
2117                 mono_class_setup_interfaces (parent, &error);
2118                 if (!mono_error_ok (&error))
2119                         goto fail;
2120                 collect_interfaces (parent, iface_hash, &error);
2121                 if (!mono_error_ok (&error))
2122                         goto fail;
2123         }
2124
2125         data.error = &error;
2126         data.domain = mono_object_domain (type);
2127
2128         len = g_hash_table_size (iface_hash);
2129         if (len == 0) {
2130                 g_hash_table_destroy (iface_hash);
2131                 if (!data.domain->empty_types)
2132                         data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2133                 return data.domain->empty_types;
2134         }
2135
2136         data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2137         g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2138         if (!mono_error_ok (&error))
2139                 goto fail;
2140
2141         g_hash_table_destroy (iface_hash);
2142         return data.iface_array;
2143
2144 fail:
2145         g_hash_table_destroy (iface_hash);
2146         mono_error_raise_exception (&error);
2147         return NULL;
2148 }
2149
2150 static void
2151 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2152 {
2153         gboolean variance_used;
2154         MonoClass *class = mono_class_from_mono_type (type->type);
2155         MonoClass *iclass = mono_class_from_mono_type (iface->type);
2156         MonoReflectionMethod *member;
2157         MonoMethod* method;
2158         gpointer iter;
2159         int i = 0, len, ioffset;
2160         MonoDomain *domain;
2161
2162         MONO_ARCH_SAVE_REGS;
2163         mono_class_init_or_throw (class);
2164         mono_class_init_or_throw (iclass);
2165
2166         mono_class_setup_vtable (class);
2167
2168         ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2169         if (ioffset == -1)
2170                 return;
2171
2172         len = mono_class_num_methods (iclass);
2173         domain = mono_object_domain (type);
2174         mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2175         mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2176         iter = NULL;
2177         while ((method = mono_class_get_methods (iclass, &iter))) {
2178                 member = mono_method_get_object (domain, method, iclass);
2179                 mono_array_setref (*methods, i, member);
2180                 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2181                 mono_array_setref (*targets, i, member);
2182                 
2183                 i ++;
2184         }
2185 }
2186
2187 static void
2188 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2189 {
2190         MonoClass *klass = mono_class_from_mono_type (type->type);
2191         mono_class_init_or_throw (klass);
2192
2193         if (klass->image->dynamic) {
2194                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2195                 *packing = tb->packing_size;
2196                 *size = tb->class_size;
2197         } else {
2198                 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2199         }
2200 }
2201
2202 static MonoReflectionType*
2203 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2204 {
2205         MonoClass *class;
2206
2207         MONO_ARCH_SAVE_REGS;
2208
2209         if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2210                 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2211
2212         class = mono_class_from_mono_type (type->type);
2213         mono_class_init_or_throw (class);
2214
2215         // GetElementType should only return a type for:
2216         // Array Pointer PassedByRef
2217         if (type->type->byref)
2218                 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2219         else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2220                 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2221         else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2222                 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2223         else
2224                 return NULL;
2225 }
2226
2227 static MonoReflectionType*
2228 ves_icall_get_type_parent (MonoReflectionType *type)
2229 {
2230         MonoClass *class = mono_class_from_mono_type (type->type);
2231         return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2232 }
2233
2234 static MonoBoolean
2235 ves_icall_type_ispointer (MonoReflectionType *type)
2236 {
2237         MONO_ARCH_SAVE_REGS;
2238
2239         return type->type->type == MONO_TYPE_PTR;
2240 }
2241
2242 static MonoBoolean
2243 ves_icall_type_isprimitive (MonoReflectionType *type)
2244 {
2245         MONO_ARCH_SAVE_REGS;
2246
2247         return (!type->type->byref && (((type->type->type >= MONO_TYPE_BOOLEAN) && (type->type->type <= MONO_TYPE_R8)) || (type->type->type == MONO_TYPE_I) || (type->type->type == MONO_TYPE_U)));
2248 }
2249
2250 static MonoBoolean
2251 ves_icall_type_isbyref (MonoReflectionType *type)
2252 {
2253         MONO_ARCH_SAVE_REGS;
2254
2255         return type->type->byref;
2256 }
2257
2258 static MonoBoolean
2259 ves_icall_type_iscomobject (MonoReflectionType *type)
2260 {
2261         MonoClass *klass = mono_class_from_mono_type (type->type);
2262         mono_class_init_or_throw (klass);
2263
2264         return (klass && klass->is_com_object);
2265 }
2266
2267 static MonoReflectionModule*
2268 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2269 {
2270         MonoClass *class = mono_class_from_mono_type (type->type);
2271         return mono_module_get_object (mono_object_domain (type), class->image);
2272 }
2273
2274 static MonoReflectionAssembly*
2275 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2276 {
2277         MonoDomain *domain = mono_domain_get (); 
2278         MonoClass *class = mono_class_from_mono_type (type->type);
2279         return mono_assembly_get_object (domain, class->image->assembly);
2280 }
2281
2282 static MonoReflectionType*
2283 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2284 {
2285         MonoDomain *domain = mono_domain_get ();
2286         MonoClass *class;
2287
2288         MONO_ARCH_SAVE_REGS;
2289
2290         if (type->type->byref)
2291                 return NULL;
2292         if (type->type->type == MONO_TYPE_VAR)
2293                 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2294         else if (type->type->type == MONO_TYPE_MVAR)
2295                 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2296         else
2297                 class = mono_class_from_mono_type (type->type)->nested_in;
2298
2299         return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2300 }
2301
2302 static MonoString*
2303 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2304 {
2305         MonoDomain *domain = mono_domain_get (); 
2306         MonoClass *class = mono_class_from_mono_type (type->type);
2307
2308         if (type->type->byref) {
2309                 char *n = g_strdup_printf ("%s&", class->name);
2310                 MonoString *res = mono_string_new (domain, n);
2311
2312                 g_free (n);
2313
2314                 return res;
2315         } else {
2316                 return mono_string_new (domain, class->name);
2317         }
2318 }
2319
2320 static MonoString*
2321 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2322 {
2323         MonoDomain *domain = mono_domain_get (); 
2324         MonoClass *class = mono_class_from_mono_type (type->type);
2325
2326         while (class->nested_in)
2327                 class = class->nested_in;
2328
2329         if (class->name_space [0] == '\0')
2330                 return NULL;
2331         else
2332                 return mono_string_new (domain, class->name_space);
2333 }
2334
2335 static gint32
2336 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2337 {
2338         MonoClass *class;
2339
2340         if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2341                 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2342
2343         class = mono_class_from_mono_type (type->type);
2344
2345         return class->rank;
2346 }
2347
2348 static MonoArray*
2349 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2350 {
2351         MonoArray *res;
2352         MonoClass *klass, *pklass;
2353         MonoDomain *domain = mono_object_domain (type);
2354         MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2355         int i;
2356         MONO_ARCH_SAVE_REGS;
2357
2358         klass = mono_class_from_mono_type (type->type);
2359
2360         if (klass->generic_container) {
2361                 MonoGenericContainer *container = klass->generic_container;
2362                 res = mono_array_new_specific (array_vtable, container->type_argc);
2363                 for (i = 0; i < container->type_argc; ++i) {
2364                         pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2365                         mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2366                 }
2367         } else if (klass->generic_class) {
2368                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2369                 res = mono_array_new_specific (array_vtable, inst->type_argc);
2370                 for (i = 0; i < inst->type_argc; ++i)
2371                         mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2372         } else {
2373                 res = mono_array_new_specific (array_vtable, 0);
2374         }
2375         return res;
2376 }
2377
2378 static gboolean
2379 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2380 {
2381         MonoClass *klass;
2382         MONO_ARCH_SAVE_REGS;
2383
2384         if (!IS_MONOTYPE (type))
2385                 return FALSE;
2386
2387         if (type->type->byref)
2388                 return FALSE;
2389
2390         klass = mono_class_from_mono_type (type->type);
2391         return klass->generic_container != NULL;
2392 }
2393
2394 static MonoReflectionType*
2395 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2396 {
2397         MonoClass *klass;
2398         MONO_ARCH_SAVE_REGS;
2399
2400         if (type->type->byref)
2401                 return NULL;
2402
2403         klass = mono_class_from_mono_type (type->type);
2404
2405         if (klass->generic_container) {
2406                 return type; /* check this one */
2407         }
2408         if (klass->generic_class) {
2409                 MonoClass *generic_class = klass->generic_class->container_class;
2410                 gpointer tb;
2411
2412                 tb = mono_class_get_ref_info (generic_class);
2413
2414                 if (generic_class->wastypebuilder && tb)
2415                         return tb;
2416                 else
2417                         return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2418         }
2419         return NULL;
2420 }
2421
2422 static MonoReflectionType*
2423 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2424 {
2425         MonoClass *class;
2426         MonoType *geninst, **types;
2427         int i, count;
2428
2429         g_assert (IS_MONOTYPE (type));
2430         mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2431
2432         count = mono_array_length (type_array);
2433         types = g_new0 (MonoType *, count);
2434
2435         for (i = 0; i < count; i++) {
2436                 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2437                 types [i] = t->type;
2438         }
2439
2440         geninst = mono_reflection_bind_generic_parameters (type, count, types);
2441         g_free (types);
2442         if (!geninst)
2443                 return NULL;
2444
2445         class = mono_class_from_mono_type (geninst);
2446
2447         /*we might inflate to the GTD*/
2448         if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2449                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2450
2451         return mono_type_get_object (mono_object_domain (type), geninst);
2452 }
2453
2454 static gboolean
2455 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2456 {
2457         MonoClass *klass;
2458         MONO_ARCH_SAVE_REGS;
2459
2460         if (type->type->byref)
2461                 return FALSE;
2462
2463         klass = mono_class_from_mono_type (type->type);
2464
2465         return klass->generic_class != NULL;
2466 }
2467
2468 static gboolean
2469 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2470 {
2471         MonoClass *klass;
2472         MONO_ARCH_SAVE_REGS;
2473
2474         if (!IS_MONOTYPE (type))
2475                 return FALSE;
2476
2477         if (type->type->byref)
2478                 return FALSE;
2479
2480         klass = mono_class_from_mono_type (type->type);
2481         return klass->generic_class != NULL || klass->generic_container != NULL;
2482 }
2483
2484 static gint32
2485 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2486 {
2487         MONO_ARCH_SAVE_REGS;
2488
2489         if (!IS_MONOTYPE (type))
2490                 return -1;
2491
2492         if (is_generic_parameter (type->type))
2493                 return mono_type_get_generic_param_num (type->type);
2494         return -1;
2495 }
2496
2497 static GenericParameterAttributes
2498 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2499 {
2500         MONO_ARCH_SAVE_REGS;
2501
2502         g_assert (IS_MONOTYPE (type));
2503         g_assert (is_generic_parameter (type->type));
2504         return mono_generic_param_info (type->type->data.generic_param)->flags;
2505 }
2506
2507 static MonoArray *
2508 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2509 {
2510         MonoGenericParamInfo *param_info;
2511         MonoDomain *domain;
2512         MonoClass **ptr;
2513         MonoArray *res;
2514         int i, count;
2515
2516         MONO_ARCH_SAVE_REGS;
2517
2518         g_assert (IS_MONOTYPE (type));
2519
2520         domain = mono_object_domain (type);
2521         param_info = mono_generic_param_info (type->type->data.generic_param);
2522         for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2523                 ;
2524
2525         res = mono_array_new (domain, mono_defaults.monotype_class, count);
2526         for (i = 0; i < count; i++)
2527                 mono_array_setref (res, i, mono_type_get_object (domain, &param_info->constraints [i]->byval_arg));
2528
2529
2530         return res;
2531 }
2532
2533 static MonoBoolean
2534 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2535 {
2536         MONO_ARCH_SAVE_REGS;
2537         return is_generic_parameter (type->type);
2538 }
2539
2540 static MonoBoolean
2541 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2542 {
2543         MONO_ARCH_SAVE_REGS;
2544         return is_generic_parameter (tb->type.type);
2545 }
2546
2547 static void
2548 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2549                                                                            MonoReflectionType *t)
2550 {
2551         enumtype->type = t->type;
2552 }
2553
2554 static MonoReflectionMethod*
2555 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type, 
2556                                                    MonoReflectionMethod* generic)
2557 {
2558         MonoDomain *domain; 
2559         MonoClass *klass;
2560         MonoMethod *method;
2561         gpointer iter;
2562                 
2563         MONO_ARCH_SAVE_REGS;
2564
2565         domain = ((MonoObject *)type)->vtable->domain;
2566
2567         klass = mono_class_from_mono_type (type->type);
2568         mono_class_init_or_throw (klass);
2569
2570         iter = NULL;
2571         while ((method = mono_class_get_methods (klass, &iter))) {
2572                 if (method->token == generic->method->token)
2573                         return mono_method_get_object (domain, method, klass);
2574         }
2575
2576         return NULL;
2577 }
2578
2579
2580
2581 static MonoReflectionMethod *
2582 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2583 {
2584         MonoMethod *method;
2585         MonoType *type = ref_type->type;
2586
2587         MONO_ARCH_SAVE_REGS;
2588
2589         if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2590                 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2591         if (type->type == MONO_TYPE_VAR)
2592                 return NULL;
2593
2594         method = mono_type_get_generic_param_owner (type)->owner.method;
2595         g_assert (method);
2596         return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2597 }
2598
2599 static MonoReflectionDllImportAttribute*
2600 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2601 {
2602         static MonoClass *DllImportAttributeClass = NULL;
2603         MonoDomain *domain = mono_domain_get ();
2604         MonoReflectionDllImportAttribute *attr;
2605         MonoImage *image = method->klass->image;
2606         MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2607         MonoTableInfo *tables = image->tables;
2608         MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2609         MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2610         guint32 im_cols [MONO_IMPLMAP_SIZE];
2611         guint32 scope_token;
2612         const char *import = NULL;
2613         const char *scope = NULL;
2614         guint32 flags;
2615
2616         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2617                 return NULL;
2618
2619         if (!DllImportAttributeClass) {
2620                 DllImportAttributeClass = 
2621                         mono_class_from_name (mono_defaults.corlib,
2622                                                                   "System.Runtime.InteropServices", "DllImportAttribute");
2623                 g_assert (DllImportAttributeClass);
2624         }
2625                                                                                                                 
2626         if (method->klass->image->dynamic) {
2627                 MonoReflectionMethodAux *method_aux = 
2628                         g_hash_table_lookup (
2629                                                                           ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2630                 if (method_aux) {
2631                         import = method_aux->dllentry;
2632                         scope = method_aux->dll;
2633                 }
2634
2635                 if (!import || !scope) {
2636                         mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2637                         return NULL;
2638                 }
2639         }
2640         else {
2641                 if (piinfo->implmap_idx) {
2642                         mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2643                         
2644                         piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2645                         import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2646                         scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2647                         scope = mono_metadata_string_heap (image, scope_token);
2648                 }
2649         }
2650         flags = piinfo->piflags;
2651         
2652         attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2653
2654         MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2655         MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2656         attr->call_conv = (flags & 0x700) >> 8;
2657         attr->charset = ((flags & 0x6) >> 1) + 1;
2658         if (attr->charset == 1)
2659                 attr->charset = 2;
2660         attr->exact_spelling = (flags & 0x1) != 0;
2661         attr->set_last_error = (flags & 0x40) != 0;
2662         attr->best_fit_mapping = (flags & 0x30) == 0x10;
2663         attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2664         attr->preserve_sig = FALSE;
2665
2666         return attr;
2667 }
2668
2669 static MonoReflectionMethod *
2670 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2671 {
2672         MonoMethodInflated *imethod;
2673         MonoMethod *result;
2674
2675         MONO_ARCH_SAVE_REGS;
2676
2677         if (method->method->is_generic)
2678                 return method;
2679
2680         if (!method->method->is_inflated)
2681                 return NULL;
2682
2683         imethod = (MonoMethodInflated *) method->method;
2684
2685         result = imethod->declaring;
2686         /* Not a generic method.  */
2687         if (!result->is_generic)
2688                 return NULL;
2689
2690         if (method->method->klass->image->dynamic) {
2691                 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2692                 MonoReflectionMethod *res;
2693
2694                 /*
2695                  * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2696                  * the dynamic case as well ?
2697                  */
2698                 mono_loader_lock ();
2699                 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2700                 mono_loader_unlock ();
2701
2702                 if (res)
2703                         return res;
2704         }
2705
2706         if (imethod->context.class_inst) {
2707                 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2708                 /*Generic methods gets the context of the GTD.*/
2709                 if (mono_class_get_context (klass))
2710                         result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2711         }
2712
2713         return mono_method_get_object (mono_object_domain (method), result, NULL);
2714 }
2715
2716 static gboolean
2717 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2718 {
2719         MONO_ARCH_SAVE_REGS;
2720
2721         return mono_method_signature (method->method)->generic_param_count != 0;
2722 }
2723
2724 static gboolean
2725 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2726 {
2727         MONO_ARCH_SAVE_REGS;
2728
2729         return method->method->is_generic;
2730 }
2731
2732 static MonoArray*
2733 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2734 {
2735         MonoArray *res;
2736         MonoDomain *domain;
2737         int count, i;
2738         MONO_ARCH_SAVE_REGS;
2739
2740         domain = mono_object_domain (method);
2741
2742         if (method->method->is_inflated) {
2743                 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2744
2745                 if (inst) {
2746                         count = inst->type_argc;
2747                         res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2748
2749                         for (i = 0; i < count; i++)
2750                                 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2751
2752                         return res;
2753                 }
2754         }
2755
2756         count = mono_method_signature (method->method)->generic_param_count;
2757         res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2758
2759         for (i = 0; i < count; i++) {
2760                 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2761                 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2762                 MonoClass *pklass = mono_class_from_generic_parameter (
2763                         param, method->method->klass->image, TRUE);
2764                 mono_array_setref (res, i,
2765                                 mono_type_get_object (domain, &pklass->byval_arg));
2766         }
2767
2768         return res;
2769 }
2770
2771 static MonoObject *
2772 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc) 
2773 {
2774         /* 
2775          * Invoke from reflection is supposed to always be a virtual call (the API
2776          * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2777          * greater flexibility.
2778          */
2779         MonoMethod *m = method->method;
2780         int pcount;
2781         void *obj = this;
2782
2783         MONO_ARCH_SAVE_REGS;
2784
2785         *exc = NULL;
2786
2787         if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2788                 mono_security_core_clr_ensure_reflection_access_method (m);
2789
2790         if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2791                 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2792                         mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2793                         return NULL;
2794                 }
2795
2796                 if (this) {
2797                         if (!mono_object_isinst (this, m->klass)) {
2798                                 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2799                                 return NULL;
2800                         }
2801                         m = mono_object_get_virtual_method (this, m);
2802                         /* must pass the pointer to the value for valuetype methods */
2803                         if (m->klass->valuetype)
2804                                 obj = mono_object_unbox (this);
2805                 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2806                         mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2807                         return NULL;
2808                 }
2809         }
2810
2811         pcount = params? mono_array_length (params): 0;
2812         if (pcount != mono_method_signature (m)->param_count) {
2813                 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2814                 return NULL;
2815         }
2816
2817         if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2818                 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class."));
2819                 return NULL;
2820         }
2821
2822         if (m->klass->image->assembly->ref_only) {
2823                 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
2824                 return NULL;
2825         }
2826         
2827         if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2828                 int i;
2829                 uintptr_t *lengths;
2830                 intptr_t *lower_bounds;
2831                 pcount = mono_array_length (params);
2832                 lengths = alloca (sizeof (uintptr_t) * pcount);
2833                 /* Note: the synthetized array .ctors have int32 as argument type */
2834                 for (i = 0; i < pcount; ++i)
2835                         lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2836
2837                 if (m->klass->rank == pcount) {
2838                         /* Only lengths provided. */
2839                         lower_bounds = NULL;
2840                 } else {
2841                         g_assert (pcount == (m->klass->rank * 2));
2842                         /* lower bounds are first. */
2843                         lower_bounds = (intptr_t*)lengths;
2844                         lengths += m->klass->rank;
2845                 }
2846
2847                 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2848         }
2849         return mono_runtime_invoke_array (m, obj, params, NULL);
2850 }
2851
2852 static MonoObject *
2853 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs) 
2854 {
2855         MonoDomain *domain = mono_object_domain (method); 
2856         MonoMethod *m = method->method;
2857         MonoMethodSignature *sig = mono_method_signature (m);
2858         MonoArray *out_args;
2859         MonoObject *result;
2860         int i, j, outarg_count = 0;
2861
2862         MONO_ARCH_SAVE_REGS;
2863
2864         if (m->klass == mono_defaults.object_class) {
2865
2866                 if (!strcmp (m->name, "FieldGetter")) {
2867                         MonoClass *k = this->vtable->klass;
2868                         MonoString *name;
2869                         char *str;
2870                         
2871                         /* If this is a proxy, then it must be a CBO */
2872                         if (k == mono_defaults.transparent_proxy_class) {
2873                                 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2874                                 this = tp->rp->unwrapped_server;
2875                                 g_assert (this);
2876                                 k = this->vtable->klass;
2877                         }
2878                         
2879                         name = mono_array_get (params, MonoString *, 1);
2880                         str = mono_string_to_utf8 (name);
2881                 
2882                         do {
2883                                 MonoClassField* field = mono_class_get_field_from_name (k, str);
2884                                 if (field) {
2885                                         MonoClass *field_klass =  mono_class_from_mono_type (field->type);
2886                                         if (field_klass->valuetype)
2887                                                 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2888                                         else 
2889                                                 result = *((gpointer *)((char *)this + field->offset));
2890                                 
2891                                         out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2892                                         mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2893                                         mono_array_setref (out_args, 0, result);
2894                                         g_free (str);
2895                                         return NULL;
2896                                 }
2897                                 k = k->parent;
2898                         } while (k);
2899
2900                         g_free (str);
2901                         g_assert_not_reached ();
2902
2903                 } else if (!strcmp (m->name, "FieldSetter")) {
2904                         MonoClass *k = this->vtable->klass;
2905                         MonoString *name;
2906                         guint32 size;
2907                         gint32 align;
2908                         char *str;
2909                         
2910                         /* If this is a proxy, then it must be a CBO */
2911                         if (k == mono_defaults.transparent_proxy_class) {
2912                                 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2913                                 this = tp->rp->unwrapped_server;
2914                                 g_assert (this);
2915                                 k = this->vtable->klass;
2916                         }
2917                         
2918                         name = mono_array_get (params, MonoString *, 1);
2919                         str = mono_string_to_utf8 (name);
2920                 
2921                         do {
2922                                 MonoClassField* field = mono_class_get_field_from_name (k, str);
2923                                 if (field) {
2924                                         MonoClass *field_klass =  mono_class_from_mono_type (field->type);
2925                                         MonoObject *val = mono_array_get (params, gpointer, 2);
2926
2927                                         if (field_klass->valuetype) {
2928                                                 size = mono_type_size (field->type, &align);
2929                                                 g_assert (size == mono_class_value_size (field_klass, NULL));
2930                                                 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2931                                         } else {
2932                                                 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2933                                         }
2934                                 
2935                                         out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2936                                         mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2937
2938                                         g_free (str);
2939                                         return NULL;
2940                                 }
2941                                 
2942                                 k = k->parent;
2943                         } while (k);
2944
2945                         g_free (str);
2946                         g_assert_not_reached ();
2947
2948                 }
2949         }
2950
2951         for (i = 0; i < mono_array_length (params); i++) {
2952                 if (sig->params [i]->byref) 
2953                         outarg_count++;
2954         }
2955
2956         out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2957         
2958         /* handle constructors only for objects already allocated */
2959         if (!strcmp (method->method->name, ".ctor"))
2960                 g_assert (this);
2961
2962         /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2963         g_assert (!method->method->klass->valuetype);
2964         result = mono_runtime_invoke_array (method->method, this, params, NULL);
2965
2966         for (i = 0, j = 0; i < mono_array_length (params); i++) {
2967                 if (sig->params [i]->byref) {
2968                         gpointer arg;
2969                         arg = mono_array_get (params, gpointer, i);
2970                         mono_array_setref (out_args, j, arg);
2971                         j++;
2972                 }
2973         }
2974
2975         mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2976
2977         return result;
2978 }
2979
2980 static guint64
2981 read_enum_value (char *mem, int type)
2982 {
2983         switch (type) {
2984         case MONO_TYPE_U1:
2985                 return *(guint8*)mem;
2986         case MONO_TYPE_I1:
2987                 return *(gint8*)mem;
2988         case MONO_TYPE_U2:
2989                 return *(guint16*)mem;
2990         case MONO_TYPE_I2:
2991                 return *(gint16*)mem;
2992         case MONO_TYPE_U4:
2993                 return *(guint32*)mem;
2994         case MONO_TYPE_I4:
2995                 return *(gint32*)mem;
2996         case MONO_TYPE_U8:
2997                 return *(guint64*)mem;
2998         case MONO_TYPE_I8:
2999                 return *(gint64*)mem;
3000         default:
3001                 g_assert_not_reached ();
3002         }
3003         return 0;
3004 }
3005
3006 static void
3007 write_enum_value (char *mem, int type, guint64 value)
3008 {
3009         switch (type) {
3010         case MONO_TYPE_U1:
3011         case MONO_TYPE_I1: {
3012                 guint8 *p = (guint8*)mem;
3013                 *p = value;
3014                 break;
3015         }
3016         case MONO_TYPE_U2:
3017         case MONO_TYPE_I2: {
3018                 guint16 *p = (void*)mem;
3019                 *p = value;
3020                 break;
3021         }
3022         case MONO_TYPE_U4:
3023         case MONO_TYPE_I4: {
3024                 guint32 *p = (void*)mem;
3025                 *p = value;
3026                 break;
3027         }
3028         case MONO_TYPE_U8:
3029         case MONO_TYPE_I8: {
3030                 guint64 *p = (void*)mem;
3031                 *p = value;
3032                 break;
3033         }
3034         default:
3035                 g_assert_not_reached ();
3036         }
3037         return;
3038 }
3039
3040 static MonoObject *
3041 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3042 {
3043         MonoDomain *domain; 
3044         MonoClass *enumc, *objc;
3045         MonoObject *res;
3046         MonoType *etype;
3047         guint64 val;
3048         
3049         MONO_ARCH_SAVE_REGS;
3050
3051         MONO_CHECK_ARG_NULL (enumType);
3052         MONO_CHECK_ARG_NULL (value);
3053
3054         domain = mono_object_domain (enumType); 
3055         enumc = mono_class_from_mono_type (enumType->type);
3056
3057         mono_class_init_or_throw (enumc);
3058
3059         objc = value->vtable->klass;
3060
3061         if (!enumc->enumtype)
3062                 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3063         if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3064                 mono_raise_exception (mono_get_exception_argument ("value", "The value passed in must be an enum base or an underlying type for an enum, such as an Int32."));
3065
3066         etype = mono_class_enum_basetype (enumc);
3067         if (!etype)
3068                 /* MS throws this for typebuilders */
3069                 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3070
3071         res = mono_object_new (domain, enumc);
3072         val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3073         write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3074
3075         return res;
3076 }
3077
3078 static MonoObject *
3079 ves_icall_System_Enum_get_value (MonoObject *this)
3080 {
3081         MonoObject *res;
3082         MonoClass *enumc;
3083         gpointer dst;
3084         gpointer src;
3085         int size;
3086
3087         MONO_ARCH_SAVE_REGS;
3088
3089         if (!this)
3090                 return NULL;
3091
3092         g_assert (this->vtable->klass->enumtype);
3093         
3094         enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3095         res = mono_object_new (mono_object_domain (this), enumc);
3096         dst = (char *)res + sizeof (MonoObject);
3097         src = (char *)this + sizeof (MonoObject);
3098         size = mono_class_value_size (enumc, NULL);
3099
3100         memcpy (dst, src, size);
3101
3102         return res;
3103 }
3104
3105 static MonoReflectionType *
3106 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3107 {
3108         MonoType *etype;
3109         MonoClass *klass;
3110
3111         MONO_ARCH_SAVE_REGS;
3112
3113         klass = mono_class_from_mono_type (type->type);
3114         mono_class_init_or_throw (klass);
3115
3116         etype = mono_class_enum_basetype (klass);
3117         if (!etype)
3118                 /* MS throws this for typebuilders */
3119                 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3120
3121         return mono_type_get_object (mono_object_domain (type), etype);
3122 }
3123
3124 static int
3125 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3126 {
3127         gpointer tdata = (char *)this + sizeof (MonoObject);
3128         gpointer odata = (char *)other + sizeof (MonoObject);
3129         MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3130         g_assert (basetype);
3131
3132 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3133                 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3134                 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3135                 if (me == other) \
3136                         return 0; \
3137                 return me > other ? 1 : -1; \
3138         } while (0)
3139
3140 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3141                 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3142                 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3143                 if (me == other) \
3144                         return 0; \
3145                 return me - other; \
3146         } while (0)
3147
3148         switch (basetype->type) {
3149                 case MONO_TYPE_U1:
3150                         COMPARE_ENUM_VALUES (guint8);
3151                 case MONO_TYPE_I1:
3152                         COMPARE_ENUM_VALUES (gint8);
3153                 case MONO_TYPE_CHAR:
3154                 case MONO_TYPE_U2:
3155                         COMPARE_ENUM_VALUES_RANGE (guint16);
3156                 case MONO_TYPE_I2:
3157                         COMPARE_ENUM_VALUES (gint16);
3158                 case MONO_TYPE_U4:
3159                         COMPARE_ENUM_VALUES (guint32);
3160                 case MONO_TYPE_I4:
3161                         COMPARE_ENUM_VALUES (gint32);
3162                 case MONO_TYPE_U8:
3163                         COMPARE_ENUM_VALUES (guint64);
3164                 case MONO_TYPE_I8:
3165                         COMPARE_ENUM_VALUES (gint64);
3166                 default:
3167                         g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3168         }
3169 #undef COMPARE_ENUM_VALUES_RANGE
3170 #undef COMPARE_ENUM_VALUES
3171         return 0;
3172 }
3173
3174 static int
3175 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3176 {
3177         gpointer data = (char *)this + sizeof (MonoObject);
3178         MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3179         g_assert (basetype);
3180
3181         switch (basetype->type) {
3182                 case MONO_TYPE_I1:      
3183                         return *((gint8*)data);
3184                 case MONO_TYPE_U1:
3185                         return *((guint8*)data);
3186                 case MONO_TYPE_CHAR:
3187                 case MONO_TYPE_U2:
3188                         return *((guint16*)data);
3189                 
3190                 case MONO_TYPE_I2:
3191                         return *((gint16*)data);
3192                 case MONO_TYPE_U4:
3193                         return *((guint32*)data);
3194                 case MONO_TYPE_I4:
3195                         return *((gint32*)data);
3196                 case MONO_TYPE_U8:
3197                 case MONO_TYPE_I8: {
3198                         gint64 value = *((gint64*)data);
3199                         return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3200                 }
3201                 default:
3202                         g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3203         }
3204         return 0;
3205 }
3206
3207 static void
3208 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3209 {
3210         MonoDomain *domain = mono_object_domain (type); 
3211         MonoClass *enumc = mono_class_from_mono_type (type->type);
3212         guint j = 0, nvalues, crow;
3213         gpointer iter;
3214         MonoClassField *field;
3215
3216         MONO_ARCH_SAVE_REGS;
3217
3218         mono_class_init_or_throw (enumc);
3219
3220         MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3221         nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3222         MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3223         MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3224
3225         crow = -1;
3226         iter = NULL;
3227         while ((field = mono_class_get_fields (enumc, &iter))) {
3228                 const char *p;
3229                 int len;
3230                 MonoTypeEnum def_type;
3231                 
3232                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3233                         continue;
3234                 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3235                         continue;
3236                 if (mono_field_is_deleted (field))
3237                         continue;
3238                 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3239
3240                 p = mono_class_get_field_default_value (field, &def_type);
3241                 len = mono_metadata_decode_blob_size (p, &p);
3242                 switch (mono_class_enum_basetype (enumc)->type) {
3243                 case MONO_TYPE_U1:
3244                 case MONO_TYPE_I1:
3245                         mono_array_set (info->values, gchar, j, *p);
3246                         break;
3247                 case MONO_TYPE_CHAR:
3248                 case MONO_TYPE_U2:
3249                 case MONO_TYPE_I2:
3250                         mono_array_set (info->values, gint16, j, read16 (p));
3251                         break;
3252                 case MONO_TYPE_U4:
3253                 case MONO_TYPE_I4:
3254                         mono_array_set (info->values, gint32, j, read32 (p));
3255                         break;
3256                 case MONO_TYPE_U8:
3257                 case MONO_TYPE_I8:
3258                         mono_array_set (info->values, gint64, j, read64 (p));
3259                         break;
3260                 default:
3261                         g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3262                 }
3263                 ++j;
3264         }
3265 }
3266
3267 enum {
3268         BFLAGS_IgnoreCase = 1,
3269         BFLAGS_DeclaredOnly = 2,
3270         BFLAGS_Instance = 4,
3271         BFLAGS_Static = 8,
3272         BFLAGS_Public = 0x10,
3273         BFLAGS_NonPublic = 0x20,
3274         BFLAGS_FlattenHierarchy = 0x40,
3275         BFLAGS_InvokeMethod = 0x100,
3276         BFLAGS_CreateInstance = 0x200,
3277         BFLAGS_GetField = 0x400,
3278         BFLAGS_SetField = 0x800,
3279         BFLAGS_GetProperty = 0x1000,
3280         BFLAGS_SetProperty = 0x2000,
3281         BFLAGS_ExactBinding = 0x10000,
3282         BFLAGS_SuppressChangeType = 0x20000,
3283         BFLAGS_OptionalParamBinding = 0x40000
3284 };
3285
3286 static MonoReflectionField *
3287 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3288 {
3289         MonoDomain *domain; 
3290         MonoClass *startklass, *klass;
3291         int match;
3292         MonoClassField *field;
3293         gpointer iter;
3294         char *utf8_name;
3295         int (*compare_func) (const char *s1, const char *s2) = NULL;
3296         domain = ((MonoObject *)type)->vtable->domain;
3297         klass = startklass = mono_class_from_mono_type (type->type);
3298
3299         if (!name)
3300                 mono_raise_exception (mono_get_exception_argument_null ("name"));
3301         if (type->type->byref)
3302                 return NULL;
3303
3304         compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3305
3306 handle_parent:
3307         if (klass->exception_type != MONO_EXCEPTION_NONE)
3308                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3309
3310         iter = NULL;
3311         while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3312                 guint32 flags = mono_field_get_flags (field);
3313                 match = 0;
3314
3315                 if (mono_field_is_deleted_with_flags (field, flags))
3316                         continue;
3317                 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3318                         if (bflags & BFLAGS_Public)
3319                                 match++;
3320                 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3321                         if (bflags & BFLAGS_NonPublic) {
3322                                 match++;
3323                         }
3324                 }
3325                 if (!match)
3326                         continue;
3327                 match = 0;
3328                 if (flags & FIELD_ATTRIBUTE_STATIC) {
3329                         if (bflags & BFLAGS_Static)
3330                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3331                                         match++;
3332                 } else {
3333                         if (bflags & BFLAGS_Instance)
3334                                 match++;
3335                 }
3336
3337                 if (!match)
3338                         continue;
3339                 
3340                 utf8_name = mono_string_to_utf8 (name);
3341
3342                 if (compare_func (mono_field_get_name (field), utf8_name)) {
3343                         g_free (utf8_name);
3344                         continue;
3345                 }
3346                 g_free (utf8_name);
3347                 
3348                 return mono_field_get_object (domain, klass, field);
3349         }
3350         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3351                 goto handle_parent;
3352
3353         return NULL;
3354 }
3355
3356 static MonoArray*
3357 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3358 {
3359         MonoDomain *domain; 
3360         MonoClass *startklass, *klass, *refklass;
3361         MonoArray *res;
3362         MonoObject *member;
3363         int i, match;
3364         gpointer iter;
3365         MonoClassField *field;
3366         MonoPtrArray tmp_array;
3367
3368         MONO_ARCH_SAVE_REGS;
3369
3370         domain = ((MonoObject *)type)->vtable->domain;
3371         if (type->type->byref)
3372                 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3373         klass = startklass = mono_class_from_mono_type (type->type);
3374         refklass = mono_class_from_mono_type (reftype->type);
3375
3376         mono_ptr_array_init (tmp_array, 2);
3377         
3378 handle_parent:  
3379         if (klass->exception_type != MONO_EXCEPTION_NONE) {
3380                 mono_ptr_array_destroy (tmp_array);
3381                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3382         }
3383
3384         iter = NULL;
3385         while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3386                 guint32 flags = mono_field_get_flags (field);
3387                 match = 0;
3388                 if (mono_field_is_deleted_with_flags (field, flags))
3389                         continue;
3390                 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3391                         if (bflags & BFLAGS_Public)
3392                                 match++;
3393                 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3394                         if (bflags & BFLAGS_NonPublic) {
3395                                 match++;
3396                         }
3397                 }
3398                 if (!match)
3399                         continue;
3400                 match = 0;
3401                 if (flags & FIELD_ATTRIBUTE_STATIC) {
3402                         if (bflags & BFLAGS_Static)
3403                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3404                                         match++;
3405                 } else {
3406                         if (bflags & BFLAGS_Instance)
3407                                 match++;
3408                 }
3409
3410                 if (!match)
3411                         continue;
3412                 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3413                 mono_ptr_array_append (tmp_array, member);
3414         }
3415         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3416                 goto handle_parent;
3417
3418         res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3419
3420         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3421                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3422
3423         mono_ptr_array_destroy (tmp_array);
3424
3425         return res;
3426 }
3427
3428 static gboolean
3429 method_nonpublic (MonoMethod* method, gboolean start_klass)
3430 {
3431         switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3432                 case METHOD_ATTRIBUTE_ASSEM:
3433                         return (start_klass || mono_defaults.generic_ilist_class);
3434                 case METHOD_ATTRIBUTE_PRIVATE:
3435                         return start_klass;
3436                 case METHOD_ATTRIBUTE_PUBLIC:
3437                         return FALSE;
3438                 default:
3439                         return TRUE;
3440         }
3441 }
3442
3443 static MonoArray*
3444 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3445 {
3446         static MonoClass *MethodInfo_array;
3447         MonoDomain *domain; 
3448         MonoClass *startklass, *klass, *refklass;
3449         MonoArray *res;
3450         MonoMethod *method;
3451         gpointer iter;
3452         MonoObject *member;
3453         int i, len, match, nslots;
3454         /*FIXME, use MonoBitSet*/
3455         guint32 method_slots_default [8];
3456         guint32 *method_slots = NULL;
3457         gchar *mname = NULL;
3458         int (*compare_func) (const char *s1, const char *s2) = NULL;
3459         MonoVTable *array_vtable;
3460         MonoException *ex;
3461         MonoPtrArray tmp_array;
3462
3463         mono_ptr_array_init (tmp_array, 4);
3464
3465         if (!MethodInfo_array) {
3466                 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3467                 mono_memory_barrier ();
3468                 MethodInfo_array = klass;
3469         }
3470
3471         domain = ((MonoObject *)type)->vtable->domain;
3472         array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3473         if (type->type->byref)
3474                 return mono_array_new_specific (array_vtable, 0);
3475         klass = startklass = mono_class_from_mono_type (type->type);
3476         refklass = mono_class_from_mono_type (reftype->type);
3477
3478         len = 0;
3479         if (name != NULL) {
3480                 mname = mono_string_to_utf8 (name);
3481                 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3482         }
3483
3484         /* An optimization for calls made from Delegate:CreateDelegate () */
3485         if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3486                 method = mono_get_delegate_invoke (klass);
3487                 if (mono_loader_get_last_error ())
3488                         goto loader_error;
3489
3490                 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3491
3492                 res = mono_array_new_specific (array_vtable, 1);
3493                 mono_array_setref (res, 0, member);
3494                 g_free (mname);
3495                 return res;
3496         }
3497
3498         mono_class_setup_vtable (klass);
3499         if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3500                 goto loader_error;
3501
3502         if (is_generic_parameter (type->type))
3503                 nslots = mono_class_get_vtable_size (klass->parent);
3504         else
3505                 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3506         if (nslots >= sizeof (method_slots_default) * 8) {
3507                 method_slots = g_new0 (guint32, nslots / 32 + 1);
3508         } else {
3509                 method_slots = method_slots_default;
3510                 memset (method_slots, 0, sizeof (method_slots_default));
3511         }
3512 handle_parent:
3513         mono_class_setup_vtable (klass);
3514         if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3515                 goto loader_error;              
3516
3517         iter = NULL;
3518         while ((method = mono_class_get_methods (klass, &iter))) {
3519                 match = 0;
3520                 if (method->slot != -1) {
3521                         g_assert (method->slot < nslots);
3522                         if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3523                                 continue;
3524                         if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3525                                 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3526                 }
3527
3528                 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3529                         continue;
3530                 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3531                         if (bflags & BFLAGS_Public)
3532                                 match++;
3533                 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3534                                 match++;
3535                 }
3536                 if (!match)
3537                         continue;
3538                 match = 0;
3539                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3540                         if (bflags & BFLAGS_Static)
3541                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3542                                         match++;
3543                 } else {
3544                         if (bflags & BFLAGS_Instance)
3545                                 match++;
3546                 }
3547
3548                 if (!match)
3549                         continue;
3550
3551                 if (name != NULL) {
3552                         if (compare_func (mname, method->name))
3553                                 continue;
3554                 }
3555                 
3556                 match = 0;
3557                 
3558                 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3559                 
3560                 mono_ptr_array_append (tmp_array, member);
3561         }
3562         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3563                 goto handle_parent;
3564
3565         g_free (mname);
3566         if (method_slots != method_slots_default)
3567                 g_free (method_slots);
3568
3569         res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3570
3571         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3572                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3573
3574         mono_ptr_array_destroy (tmp_array);
3575         return res;
3576
3577 loader_error:
3578         g_free (mname);
3579         if (method_slots != method_slots_default)
3580                 g_free (method_slots);
3581         mono_ptr_array_destroy (tmp_array);
3582         if (klass->exception_type != MONO_EXCEPTION_NONE) {
3583                 ex = mono_class_get_exception_for_failure (klass);
3584         } else {
3585                 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3586                 mono_loader_clear_error ();
3587         }
3588         mono_raise_exception (ex);
3589         return NULL;
3590 }
3591
3592 static MonoArray*
3593 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3594 {
3595         MonoDomain *domain; 
3596         static MonoClass *System_Reflection_ConstructorInfo;
3597         MonoClass *startklass, *klass, *refklass;
3598         MonoArray *res;
3599         MonoMethod *method;
3600         MonoObject *member;
3601         int i, match;
3602         gpointer iter = NULL;
3603         MonoPtrArray tmp_array;
3604         
3605         MONO_ARCH_SAVE_REGS;
3606
3607         mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3608
3609         domain = ((MonoObject *)type)->vtable->domain;
3610         if (type->type->byref)
3611                 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3612         klass = startklass = mono_class_from_mono_type (type->type);
3613         refklass = mono_class_from_mono_type (reftype->type);
3614
3615         if (!System_Reflection_ConstructorInfo)
3616                 System_Reflection_ConstructorInfo = mono_class_from_name (
3617                         mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3618
3619         iter = NULL;
3620         while ((method = mono_class_get_methods (klass, &iter))) {
3621                 match = 0;
3622                 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3623                         continue;
3624                 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3625                         if (bflags & BFLAGS_Public)
3626                                 match++;
3627                 } else {
3628                         if (bflags & BFLAGS_NonPublic)
3629                                 match++;
3630                 }
3631                 if (!match)
3632                         continue;
3633                 match = 0;
3634                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3635                         if (bflags & BFLAGS_Static)
3636                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3637                                         match++;
3638                 } else {
3639                         if (bflags & BFLAGS_Instance)
3640                                 match++;
3641                 }
3642
3643                 if (!match)
3644                         continue;
3645                 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3646
3647                 mono_ptr_array_append (tmp_array, member);
3648         }
3649
3650         res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3651
3652         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3653                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3654
3655         mono_ptr_array_destroy (tmp_array);
3656
3657         return res;
3658 }
3659
3660 static guint
3661 property_hash (gconstpointer data)
3662 {
3663         MonoProperty *prop = (MonoProperty*)data;
3664
3665         return g_str_hash (prop->name);
3666 }
3667
3668 static gboolean
3669 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3670 {
3671         // Properties are hide-by-name-and-signature
3672         if (!g_str_equal (prop1->name, prop2->name))
3673                 return FALSE;
3674
3675         if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3676                 return FALSE;
3677         if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3678                 return FALSE;
3679         return TRUE;
3680 }
3681
3682 static gboolean
3683 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3684 {
3685         if (!accessor)
3686                 return FALSE;
3687
3688         return method_nonpublic (accessor, start_klass);
3689 }
3690
3691 static MonoArray*
3692 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3693 {
3694         MonoException *ex;
3695         MonoDomain *domain; 
3696         static MonoClass *System_Reflection_PropertyInfo;
3697         MonoClass *startklass, *klass;
3698         MonoArray *res;
3699         MonoMethod *method;
3700         MonoProperty *prop;
3701         int i, match;
3702         guint32 flags;
3703         gchar *propname = NULL;
3704         int (*compare_func) (const char *s1, const char *s2) = NULL;
3705         gpointer iter;
3706         GHashTable *properties = NULL;
3707         MonoPtrArray tmp_array;
3708
3709         MONO_ARCH_SAVE_REGS;
3710
3711         mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3712
3713         if (!System_Reflection_PropertyInfo)
3714                 System_Reflection_PropertyInfo = mono_class_from_name (
3715                         mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3716
3717         domain = ((MonoObject *)type)->vtable->domain;
3718         if (type->type->byref)
3719                 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3720         klass = startklass = mono_class_from_mono_type (type->type);
3721
3722         if (name != NULL) {
3723                 propname = mono_string_to_utf8 (name);
3724                 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3725         }
3726
3727         properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3728 handle_parent:
3729         mono_class_setup_vtable (klass);
3730         if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3731                 goto loader_error;
3732
3733         iter = NULL;
3734         while ((prop = mono_class_get_properties (klass, &iter))) {
3735                 match = 0;
3736                 method = prop->get;
3737                 if (!method)
3738                         method = prop->set;
3739                 if (method)
3740                         flags = method->flags;
3741                 else
3742                         flags = 0;
3743                 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3744                         (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3745                         if (bflags & BFLAGS_Public)
3746                                 match++;
3747                 } else if (bflags & BFLAGS_NonPublic) {
3748                         if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3749                                 property_accessor_nonpublic(prop->set, startklass == klass)) {
3750                                 match++;
3751                         }
3752                 }
3753                 if (!match)
3754                         continue;
3755                 match = 0;
3756                 if (flags & METHOD_ATTRIBUTE_STATIC) {
3757                         if (bflags & BFLAGS_Static)
3758                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3759                                         match++;
3760                 } else {
3761                         if (bflags & BFLAGS_Instance)
3762                                 match++;
3763                 }
3764
3765                 if (!match)
3766                         continue;
3767                 match = 0;
3768
3769                 if (name != NULL) {
3770                         if (compare_func (propname, prop->name))
3771                                 continue;
3772                 }
3773                 
3774                 if (g_hash_table_lookup (properties, prop))
3775                         continue;
3776
3777                 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3778                 
3779                 g_hash_table_insert (properties, prop, prop);
3780         }
3781         if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3782                 goto handle_parent;
3783
3784         g_hash_table_destroy (properties);
3785         g_free (propname);
3786
3787         res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3788         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3789                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3790
3791         mono_ptr_array_destroy (tmp_array);
3792
3793         return res;
3794
3795 loader_error:
3796         if (properties)
3797                 g_hash_table_destroy (properties);
3798         if (name)
3799                 g_free (propname);
3800         mono_ptr_array_destroy (tmp_array);
3801
3802         if (klass->exception_type != MONO_EXCEPTION_NONE) {
3803                 ex = mono_class_get_exception_for_failure (klass);
3804         } else {
3805                 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3806                 mono_loader_clear_error ();
3807         }
3808         mono_raise_exception (ex);
3809         return NULL;
3810 }
3811
3812 static MonoReflectionEvent *
3813 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3814 {
3815         MonoDomain *domain;
3816         MonoClass *klass, *startklass;
3817         gpointer iter;
3818         MonoEvent *event;
3819         MonoMethod *method;
3820         gchar *event_name;
3821         int (*compare_func) (const char *s1, const char *s2);
3822
3823         MONO_ARCH_SAVE_REGS;
3824
3825         event_name = mono_string_to_utf8 (name);
3826         if (type->type->byref)
3827                 return NULL;
3828         klass = startklass = mono_class_from_mono_type (type->type);
3829         domain = mono_object_domain (type);
3830
3831         mono_class_init_or_throw (klass);
3832
3833         compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3834 handle_parent:  
3835         if (klass->exception_type != MONO_EXCEPTION_NONE)
3836                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3837
3838         iter = NULL;
3839         while ((event = mono_class_get_events (klass, &iter))) {
3840                 if (compare_func (event->name, event_name))
3841                         continue;
3842
3843                 method = event->add;
3844                 if (!method)
3845                         method = event->remove;
3846                 if (!method)
3847                         method = event->raise;
3848                 if (method) {
3849                         if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3850                                 if (!(bflags & BFLAGS_Public))
3851                                         continue;
3852                         } else {
3853                                 if (!(bflags & BFLAGS_NonPublic))
3854                                         continue;
3855                                 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3856                                         continue;
3857                         }
3858
3859                         if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3860                                 if (!(bflags & BFLAGS_Static))
3861                                         continue;
3862                                 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3863                                         continue;
3864                         } else {
3865                                 if (!(bflags & BFLAGS_Instance))
3866                                         continue;
3867                         }
3868                 } else 
3869                         if (!(bflags & BFLAGS_NonPublic))
3870                                 continue;
3871                 
3872                 g_free (event_name);
3873                 return mono_event_get_object (domain, startklass, event);
3874         }
3875
3876         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3877                 goto handle_parent;
3878
3879         g_free (event_name);
3880         return NULL;
3881 }
3882
3883 static MonoArray*
3884 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3885 {
3886         MonoException *ex;
3887         MonoDomain *domain; 
3888         static MonoClass *System_Reflection_EventInfo;
3889         MonoClass *startklass, *klass;
3890         MonoArray *res;
3891         MonoMethod *method;
3892         MonoEvent *event;
3893         int i, match;
3894         gpointer iter;
3895         
3896         MonoPtrArray tmp_array;
3897
3898         MONO_ARCH_SAVE_REGS;
3899
3900         mono_ptr_array_init (tmp_array, 4);
3901
3902         if (!System_Reflection_EventInfo)
3903                 System_Reflection_EventInfo = mono_class_from_name (
3904                         mono_defaults.corlib, "System.Reflection", "EventInfo");
3905
3906         domain = mono_object_domain (type);
3907         if (type->type->byref)
3908                 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3909         klass = startklass = mono_class_from_mono_type (type->type);
3910
3911 handle_parent:
3912         mono_class_setup_vtable (klass);
3913         if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3914                 goto loader_error;
3915
3916         iter = NULL;
3917         while ((event = mono_class_get_events (klass, &iter))) {
3918                 match = 0;
3919                 method = event->add;
3920                 if (!method)
3921                         method = event->remove;
3922                 if (!method)
3923                         method = event->raise;
3924                 if (method) {
3925                         if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3926                                 if (bflags & BFLAGS_Public)
3927                                         match++;
3928                         } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3929                                 if (bflags & BFLAGS_NonPublic)
3930                                         match++;
3931                         }
3932                 }
3933                 else
3934                         if (bflags & BFLAGS_NonPublic)
3935                                 match ++;
3936                 if (!match)
3937                         continue;
3938                 match = 0;
3939                 if (method) {
3940                         if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3941                                 if (bflags & BFLAGS_Static)
3942                                         if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3943                                                 match++;
3944                         } else {
3945                                 if (bflags & BFLAGS_Instance)
3946                                         match++;
3947                         }
3948                 }
3949                 else
3950                         if (bflags & BFLAGS_Instance)
3951                                 match ++;
3952                 if (!match)
3953                         continue;
3954                 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3955         }
3956         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3957                 goto handle_parent;
3958
3959         res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3960
3961         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3962                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3963
3964         mono_ptr_array_destroy (tmp_array);
3965
3966         return res;
3967
3968 loader_error:
3969         mono_ptr_array_destroy (tmp_array);
3970         if (klass->exception_type != MONO_EXCEPTION_NONE) {
3971                 ex = mono_class_get_exception_for_failure (klass);
3972         } else {
3973                 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3974                 mono_loader_clear_error ();
3975         }
3976         mono_raise_exception (ex);
3977         return NULL;
3978 }
3979
3980 static MonoReflectionType *
3981 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3982 {
3983         MonoDomain *domain; 
3984         MonoClass *klass;
3985         MonoClass *nested;
3986         char *str;
3987         gpointer iter;
3988         
3989         MONO_ARCH_SAVE_REGS;
3990
3991         if (name == NULL)
3992                 mono_raise_exception (mono_get_exception_argument_null ("name"));
3993         
3994         domain = ((MonoObject *)type)->vtable->domain;
3995         if (type->type->byref)
3996                 return NULL;
3997         klass = mono_class_from_mono_type (type->type);
3998
3999         str = mono_string_to_utf8 (name);
4000
4001  handle_parent:
4002         if (klass->exception_type != MONO_EXCEPTION_NONE)
4003                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4004
4005         /*
4006          * If a nested type is generic, return its generic type definition.
4007          * Note that this means that the return value is essentially a
4008          * nested type of the generic type definition of @klass.
4009          *
4010          * A note in MSDN claims that a generic type definition can have
4011          * nested types that aren't generic.  In any case, the container of that
4012          * nested type would be the generic type definition.
4013          */
4014         if (klass->generic_class)
4015                 klass = klass->generic_class->container_class;
4016
4017         iter = NULL;
4018         while ((nested = mono_class_get_nested_types (klass, &iter))) {
4019                 int match = 0;
4020                 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4021                         if (bflags & BFLAGS_Public)
4022                                 match++;
4023                 } else {
4024                         if (bflags & BFLAGS_NonPublic)
4025                                 match++;
4026                 }
4027                 if (!match)
4028                         continue;
4029                 if (strcmp (nested->name, str) == 0){
4030                         g_free (str);
4031                         return mono_type_get_object (domain, &nested->byval_arg);
4032                 }
4033         }
4034         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4035                 goto handle_parent;
4036         g_free (str);
4037         return NULL;
4038 }
4039
4040 static MonoArray*
4041 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4042 {
4043         MonoDomain *domain; 
4044         MonoClass *klass;
4045         MonoArray *res;
4046         MonoObject *member;
4047         int i, match;
4048         MonoClass *nested;
4049         gpointer iter;
4050         MonoPtrArray tmp_array;
4051
4052         MONO_ARCH_SAVE_REGS;
4053
4054         domain = ((MonoObject *)type)->vtable->domain;
4055         if (type->type->byref)
4056                 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4057         klass = mono_class_from_mono_type (type->type);
4058
4059         /*
4060          * If a nested type is generic, return its generic type definition.
4061          * Note that this means that the return value is essentially the set
4062          * of nested types of the generic type definition of @klass.
4063          *
4064          * A note in MSDN claims that a generic type definition can have
4065          * nested types that aren't generic.  In any case, the container of that
4066          * nested type would be the generic type definition.
4067          */
4068         if (klass->generic_class)
4069                 klass = klass->generic_class->container_class;
4070
4071         mono_ptr_array_init (tmp_array, 1);
4072         iter = NULL;
4073         while ((nested = mono_class_get_nested_types (klass, &iter))) {
4074                 match = 0;
4075                 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4076                         if (bflags & BFLAGS_Public)
4077                                 match++;
4078                 } else {
4079                         if (bflags & BFLAGS_NonPublic)
4080                                 match++;
4081                 }
4082                 if (!match)
4083                         continue;
4084                 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4085                 mono_ptr_array_append (tmp_array, member);
4086         }
4087
4088         res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4089
4090         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4091                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4092
4093         mono_ptr_array_destroy (tmp_array);
4094
4095         return res;
4096 }
4097
4098 static MonoReflectionType*
4099 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4100 {
4101         gchar *str;
4102         MonoType *type = NULL;
4103         MonoTypeNameParse info;
4104         gboolean type_resolve;
4105
4106         MONO_ARCH_SAVE_REGS;
4107
4108         /* On MS.NET, this does not fire a TypeResolve event */
4109         type_resolve = TRUE;
4110         str = mono_string_to_utf8 (name);
4111         /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4112         if (!mono_reflection_parse_type (str, &info)) {
4113                 g_free (str);
4114                 mono_reflection_free_type_info (&info);
4115                 if (throwOnError) /* uhm: this is a parse error, though... */
4116                         mono_raise_exception (mono_get_exception_type_load (name, NULL));
4117                 /*g_print ("failed parse\n");*/
4118                 return NULL;
4119         }
4120
4121         if (info.assembly.name) {
4122                 g_free (str);
4123                 mono_reflection_free_type_info (&info);
4124                 if (throwOnError) {
4125                         /* 1.0 and 2.0 throw different exceptions */
4126                         if (mono_defaults.generic_ilist_class)
4127                                 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4128                         else
4129                                 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4130                 }
4131                 return NULL;
4132         }
4133
4134         if (module != NULL) {
4135                 if (module->image)
4136                         type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4137                 else
4138                         type = NULL;
4139         }
4140         else
4141                 if (assembly->assembly->dynamic) {
4142                         /* Enumerate all modules */
4143                         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4144                         int i;
4145
4146                         type = NULL;
4147                         if (abuilder->modules) {
4148                                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4149                                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4150                                         type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4151                                         if (type)
4152                                                 break;
4153                                 }
4154                         }
4155
4156                         if (!type && abuilder->loaded_modules) {
4157                                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4158                                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4159                                         type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4160                                         if (type)
4161                                                 break;
4162                                 }
4163                         }
4164                 }
4165                 else
4166                         type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4167         g_free (str);
4168         mono_reflection_free_type_info (&info);
4169         if (!type) {
4170                 MonoException *e = NULL;
4171                 
4172                 if (throwOnError)
4173                         e = mono_get_exception_type_load (name, NULL);
4174
4175                 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4176                         e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4177
4178                 mono_loader_clear_error ();
4179
4180                 if (e != NULL)
4181                         mono_raise_exception (e);
4182
4183                 return NULL;
4184         } else if (mono_loader_get_last_error ()) {
4185                 if (throwOnError)
4186                         mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4187                 mono_loader_clear_error ();
4188         }
4189
4190         if (type->type == MONO_TYPE_CLASS) {
4191                 MonoClass *klass = mono_type_get_class (type);
4192
4193                 if (mono_is_security_manager_active () && !klass->exception_type)
4194                         /* Some security problems are detected during generic vtable construction */
4195                         mono_class_setup_vtable (klass);
4196                 /* need to report exceptions ? */
4197                 if (throwOnError && klass->exception_type) {
4198                         /* report SecurityException (or others) that occured when loading the assembly */
4199                         MonoException *exc = mono_class_get_exception_for_failure (klass);
4200                         mono_loader_clear_error ();
4201                         mono_raise_exception (exc);
4202                 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4203                         return NULL;
4204                 }
4205         }
4206
4207         /* g_print ("got it\n"); */
4208         return mono_type_get_object (mono_object_domain (assembly), type);
4209 }
4210
4211 static gboolean
4212 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4213 {
4214         gchar *content;
4215         gchar *shadow_ini_file;
4216         gsize len;
4217
4218         /* Check for shadow-copied assembly */
4219         if (mono_is_shadow_copy_enabled (domain, dirname)) {
4220                 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4221                 content = NULL;
4222                 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4223                         !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4224                         if (content) {
4225                                 g_free (content);
4226                                 content = NULL;
4227                         }
4228                 }
4229                 g_free (shadow_ini_file);
4230                 if (content != NULL) {
4231                         if (*filename)
4232                                 g_free (*filename);
4233                         *filename = content;
4234                         return TRUE;
4235                 }
4236         }
4237         return FALSE;
4238 }
4239
4240 static MonoString *
4241 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4242 {
4243         MonoDomain *domain = mono_object_domain (assembly); 
4244         MonoAssembly *mass = assembly->assembly;
4245         MonoString *res = NULL;
4246         gchar *uri;
4247         gchar *absolute;
4248         gchar *dirname;
4249         
4250         MONO_ARCH_SAVE_REGS;
4251
4252         if (g_path_is_absolute (mass->image->name)) {
4253                 absolute = g_strdup (mass->image->name);
4254                 dirname = g_path_get_dirname (absolute);
4255         } else {
4256                 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4257                 dirname = g_strdup (mass->basedir);
4258         }
4259
4260         replace_shadow_path (domain, dirname, &absolute);
4261         g_free (dirname);
4262 #if HOST_WIN32
4263         {
4264                 gint i;
4265                 for (i = strlen (absolute) - 1; i >= 0; i--)
4266                         if (absolute [i] == '\\')
4267                                 absolute [i] = '/';
4268         }
4269 #endif
4270         if (escaped) {
4271                 uri = g_filename_to_uri (absolute, NULL, NULL);
4272         } else {
4273                 const char *prepend = "file://";
4274 #if HOST_WIN32
4275                 if (*absolute == '/' && *(absolute + 1) == '/') {
4276                         prepend = "file:";
4277                 } else {
4278                         prepend = "file:///";
4279                 }
4280 #endif
4281                 uri = g_strconcat (prepend, absolute, NULL);
4282         }
4283
4284         if (uri) {
4285                 res = mono_string_new (domain, uri);
4286                 g_free (uri);
4287         }
4288         g_free (absolute);
4289         return res;
4290 }
4291
4292 static MonoBoolean
4293 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4294 {
4295         MonoAssembly *mass = assembly->assembly;
4296
4297         MONO_ARCH_SAVE_REGS;
4298
4299         return mass->in_gac;
4300 }
4301
4302 static MonoReflectionAssembly*
4303 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4304 {
4305         gchar *name;
4306         MonoAssembly *res;
4307         MonoImageOpenStatus status;
4308         
4309         MONO_ARCH_SAVE_REGS;
4310
4311         name = mono_string_to_utf8 (mname);
4312         res = mono_assembly_load_with_partial_name (name, &status);
4313
4314         g_free (name);
4315
4316         if (res == NULL)
4317                 return NULL;
4318         return mono_assembly_get_object (mono_domain_get (), res);
4319 }
4320
4321 static MonoString *
4322 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4323 {
4324         MonoDomain *domain = mono_object_domain (assembly); 
4325         MonoString *res;
4326
4327         MONO_ARCH_SAVE_REGS;
4328
4329         res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4330
4331         return res;
4332 }
4333
4334 static MonoBoolean
4335 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4336 {
4337         MONO_ARCH_SAVE_REGS;
4338
4339         return assembly->assembly->ref_only;
4340 }
4341
4342 static MonoString *
4343 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4344 {
4345         MonoDomain *domain = mono_object_domain (assembly); 
4346
4347         MONO_ARCH_SAVE_REGS;
4348
4349         return mono_string_new (domain, assembly->assembly->image->version);
4350 }
4351
4352 static MonoReflectionMethod*
4353 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly) 
4354 {
4355         guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4356
4357         MONO_ARCH_SAVE_REGS;
4358
4359         if (!token)
4360                 return NULL;
4361         return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4362 }
4363
4364 static MonoReflectionModule*
4365 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly) 
4366 {
4367         return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4368 }
4369
4370 static MonoArray*
4371 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly) 
4372 {
4373         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4374         MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4375         int i;
4376         const char *val;
4377
4378         MONO_ARCH_SAVE_REGS;
4379
4380         for (i = 0; i < table->rows; ++i) {
4381                 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4382                 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4383         }
4384         return result;
4385 }
4386
4387 static MonoObject*
4388 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4389 {
4390         static MonoClass *System_Version = NULL;
4391         static MonoMethod *create_version = NULL;
4392         MonoObject *result;
4393         gpointer args [4];
4394         
4395         if (!System_Version) {
4396                 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4397                 g_assert (System_Version);
4398         }
4399
4400         if (!create_version) {
4401                 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4402                 create_version = mono_method_desc_search_in_class (desc, System_Version);
4403                 g_assert (create_version);
4404                 mono_method_desc_free (desc);
4405         }
4406
4407         args [0] = &major;
4408         args [1] = &minor;
4409         args [2] = &build;
4410         args [3] = &revision;
4411         result = mono_object_new (domain, System_Version);
4412         mono_runtime_invoke (create_version, result, args, NULL);
4413
4414         return result;
4415 }
4416
4417 static MonoArray*
4418 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly) 
4419 {
4420         static MonoClass *System_Reflection_AssemblyName;
4421         MonoArray *result;
4422         MonoDomain *domain = mono_object_domain (assembly);
4423         int i, count = 0;
4424         static MonoMethod *create_culture = NULL;
4425         MonoImage *image = assembly->assembly->image;
4426         MonoTableInfo *t;
4427
4428         MONO_ARCH_SAVE_REGS;
4429
4430         if (!System_Reflection_AssemblyName)
4431                 System_Reflection_AssemblyName = mono_class_from_name (
4432                         mono_defaults.corlib, "System.Reflection", "AssemblyName");
4433
4434         t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4435         count = t->rows;
4436
4437         result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4438
4439         if (count > 0 && !create_culture) {
4440                 MonoMethodDesc *desc = mono_method_desc_new (
4441                         "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4442                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4443                 g_assert (create_culture);
4444                 mono_method_desc_free (desc);
4445         }
4446
4447         for (i = 0; i < count; i++) {
4448                 MonoReflectionAssemblyName *aname;
4449                 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4450
4451                 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4452
4453                 aname = (MonoReflectionAssemblyName *) mono_object_new (
4454                         domain, System_Reflection_AssemblyName);
4455
4456                 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4457
4458                 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4459                 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4460                 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4461                 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4462                 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4463                 aname->versioncompat = 1; /* SameMachine (default) */
4464                 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4465                 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4466
4467                 if (create_culture) {
4468                         gpointer args [2];
4469                         MonoBoolean assembly_ref = 1;
4470                         args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4471                         args [1] = &assembly_ref;
4472                         MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4473                 }
4474                 
4475                 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4476                         const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4477                         guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4478
4479                         if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4480                                 /* public key token isn't copied - the class library will 
4481                                 automatically generate it from the public key if required */
4482                                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4483                                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4484                         } else {
4485                                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4486                                 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4487                         }
4488                 } else {
4489                         MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4490                 }
4491                 
4492                 /* note: this function doesn't return the codebase on purpose (i.e. it can
4493                          be used under partial trust as path information isn't present). */
4494
4495                 mono_array_setref (result, i, aname);
4496         }
4497         return result;
4498 }
4499
4500 typedef struct {
4501         MonoArray *res;
4502         int idx;
4503 } NameSpaceInfo;
4504
4505 static void
4506 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4507 {
4508         MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4509
4510         mono_array_setref (info->res, info->idx, name);
4511         info->idx++;
4512 }
4513
4514 static MonoArray*
4515 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly) 
4516 {
4517         MonoImage *img = assembly->assembly->image;
4518         MonoArray *res;
4519         NameSpaceInfo info;
4520         int len;
4521
4522         MONO_ARCH_SAVE_REGS;
4523
4524         mono_image_lock (img);
4525         mono_image_init_name_cache (img);
4526
4527 RETRY_LEN:
4528         len = g_hash_table_size (img->name_cache);
4529         mono_image_unlock (img);
4530
4531         /*we can't create objects holding the image lock */
4532         res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4533
4534         mono_image_lock (img);
4535         /*len might have changed, create a new array*/
4536         if (len != g_hash_table_size (img->name_cache))
4537                 goto RETRY_LEN;
4538
4539         info.res = res;
4540         info.idx = 0;
4541         g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4542         mono_image_unlock (img);
4543
4544         return res;
4545 }
4546
4547 /* move this in some file in mono/util/ */
4548 static char *
4549 g_concat_dir_and_file (const char *dir, const char *file)
4550 {
4551         g_return_val_if_fail (dir != NULL, NULL);
4552         g_return_val_if_fail (file != NULL, NULL);
4553
4554         /*
4555          * If the directory name doesn't have a / on the end, we need
4556          * to add one so we get a proper path to the file
4557          */
4558         if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4559                 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4560         else
4561                 return g_strconcat (dir, file, NULL);
4562 }
4563
4564 static void *
4565 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module) 
4566 {
4567         char *n = mono_string_to_utf8 (name);
4568         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4569         guint32 i;
4570         guint32 cols [MONO_MANIFEST_SIZE];
4571         guint32 impl, file_idx;
4572         const char *val;
4573         MonoImage *module;
4574
4575         MONO_ARCH_SAVE_REGS;
4576
4577         for (i = 0; i < table->rows; ++i) {
4578                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4579                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4580                 if (strcmp (val, n) == 0)
4581                         break;
4582         }
4583         g_free (n);
4584         if (i == table->rows)
4585                 return NULL;
4586         /* FIXME */
4587         impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4588         if (impl) {
4589                 /*
4590                  * this code should only be called after obtaining the 
4591                  * ResourceInfo and handling the other cases.
4592                  */
4593                 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4594                 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4595
4596                 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4597                 if (!module)
4598                         return NULL;
4599         }
4600         else
4601                 module = assembly->assembly->image;
4602
4603         mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4604
4605         return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4606 }
4607
4608 static gboolean
4609 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4610 {
4611         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4612         int i;
4613         guint32 cols [MONO_MANIFEST_SIZE];
4614         guint32 file_cols [MONO_FILE_SIZE];
4615         const char *val;
4616         char *n;
4617
4618         MONO_ARCH_SAVE_REGS;
4619
4620         n = mono_string_to_utf8 (name);
4621         for (i = 0; i < table->rows; ++i) {
4622                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4623                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4624                 if (strcmp (val, n) == 0)
4625                         break;
4626         }
4627         g_free (n);
4628         if (i == table->rows)
4629                 return FALSE;
4630
4631         if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4632                 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4633         }
4634         else {
4635                 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4636                 case MONO_IMPLEMENTATION_FILE:
4637                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4638                         table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4639                         mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4640                         val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4641                         MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4642                         if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4643                                 info->location = 0;
4644                         else
4645                                 info->location = RESOURCE_LOCATION_EMBEDDED;
4646                         break;
4647
4648                 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4649                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4650                         mono_assembly_load_reference (assembly->assembly->image, i - 1);
4651                         if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4652                                 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4653                                 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4654                                 g_free (msg);
4655                                 mono_raise_exception (ex);
4656                         }
4657                         MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4658
4659                         /* Obtain info recursively */
4660                         ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4661                         info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4662                         break;
4663
4664                 case MONO_IMPLEMENTATION_EXP_TYPE:
4665                         g_assert_not_reached ();
4666                         break;
4667                 }
4668         }
4669
4670         return TRUE;
4671 }
4672
4673 static MonoObject*
4674 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules) 
4675 {
4676         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4677         MonoArray *result = NULL;
4678         int i, count;
4679         const char *val;
4680         char *n;
4681
4682         MONO_ARCH_SAVE_REGS;
4683
4684         /* check hash if needed */
4685         if (name) {
4686                 n = mono_string_to_utf8 (name);
4687                 for (i = 0; i < table->rows; ++i) {
4688                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4689                         if (strcmp (val, n) == 0) {
4690                                 MonoString *fn;
4691                                 g_free (n);
4692                                 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4693                                 fn = mono_string_new (mono_object_domain (assembly), n);
4694                                 g_free (n);
4695                                 return (MonoObject*)fn;
4696                         }
4697                 }
4698                 g_free (n);
4699                 return NULL;
4700         }
4701
4702         count = 0;
4703         for (i = 0; i < table->rows; ++i) {
4704                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4705                         count ++;
4706         }
4707
4708         result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4709
4710         count = 0;
4711         for (i = 0; i < table->rows; ++i) {
4712                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4713                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4714                         n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4715                         mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4716                         g_free (n);
4717                         count ++;
4718                 }
4719         }
4720         return (MonoObject*)result;
4721 }
4722
4723 static MonoArray*
4724 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4725 {
4726         MonoDomain *domain = mono_domain_get();
4727         MonoArray *res;
4728         MonoClass *klass;
4729         int i, j, file_count = 0;
4730         MonoImage **modules;
4731         guint32 module_count, real_module_count;
4732         MonoTableInfo *table;
4733         guint32 cols [MONO_FILE_SIZE];
4734         MonoImage *image = assembly->assembly->image;
4735
4736         g_assert (image != NULL);
4737         g_assert (!assembly->assembly->dynamic);
4738
4739         table = &image->tables [MONO_TABLE_FILE];
4740         file_count = table->rows;
4741
4742         modules = image->modules;
4743         module_count = image->module_count;
4744
4745         real_module_count = 0;
4746         for (i = 0; i < module_count; ++i)
4747                 if (modules [i])
4748                         real_module_count ++;
4749
4750         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4751         res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4752
4753         mono_array_setref (res, 0, mono_module_get_object (domain, image));
4754         j = 1;
4755         for (i = 0; i < module_count; ++i)
4756                 if (modules [i]) {
4757                         mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4758                         ++j;
4759                 }
4760
4761         for (i = 0; i < file_count; ++i, ++j) {
4762                 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4763                 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4764                         mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4765                 else {
4766                         MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4767                         if (!m) {
4768                                 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4769                                 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4770                         }
4771                         mono_array_setref (res, j, mono_module_get_object (domain, m));
4772                 }
4773         }
4774
4775         return res;
4776 }
4777
4778 static MonoReflectionMethod*
4779 ves_icall_GetCurrentMethod (void) 
4780 {
4781         MonoMethod *m = mono_method_get_last_managed ();
4782
4783         while (m->is_inflated)
4784                 m = ((MonoMethodInflated*)m)->declaring;
4785
4786         return mono_method_get_object (mono_domain_get (), m, NULL);
4787 }
4788
4789
4790 static MonoMethod*
4791 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4792 {
4793         int offset = -1, i;
4794         if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4795                 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4796                 //method is inflated, we should inflate it on the other class
4797                 MonoGenericContext ctx;
4798                 ctx.method_inst = inflated->context.method_inst;
4799                 ctx.class_inst = inflated->context.class_inst;
4800                 if (klass->generic_class)
4801                         ctx.class_inst = klass->generic_class->context.class_inst;
4802                 else if (klass->generic_container)
4803                         ctx.class_inst = klass->generic_container->context.class_inst;
4804                 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4805         }
4806
4807         mono_class_setup_methods (method->klass);
4808         if (method->klass->exception_type)
4809                 return NULL;
4810         for (i = 0; i < method->klass->method.count; ++i) {
4811                 if (method->klass->methods [i] == method) {
4812                         offset = i;
4813                         break;
4814                 }       
4815         }
4816         mono_class_setup_methods (klass);
4817         if (klass->exception_type)
4818                 return NULL;
4819         g_assert (offset >= 0 && offset < klass->method.count);
4820         return klass->methods [offset];
4821 }
4822
4823 static MonoReflectionMethod*
4824 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4825 {
4826         MonoClass *klass;
4827         if (type) {
4828                 klass = mono_class_from_mono_type (type);
4829                 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass)) 
4830                         return NULL;
4831                 if (method->klass != klass) {
4832                         method = mono_method_get_equivalent_method (method, klass);
4833                         if (!method)
4834                                 return NULL;
4835                 }
4836         } else
4837                 klass = method->klass;
4838         return mono_method_get_object (mono_domain_get (), method, klass);
4839 }
4840
4841 static MonoReflectionMethod*
4842 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4843 {
4844         return mono_method_get_object (mono_domain_get (), method, NULL);
4845 }
4846
4847 static MonoReflectionMethodBody*
4848 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4849 {
4850         return mono_method_body_get_object (mono_domain_get (), method);
4851 }
4852
4853 static MonoReflectionAssembly*
4854 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4855 {
4856         MonoMethod *dest = NULL;
4857
4858         MONO_ARCH_SAVE_REGS;
4859
4860         mono_stack_walk_no_il (get_executing, &dest);
4861         return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4862 }
4863
4864
4865 static MonoReflectionAssembly*
4866 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4867 {
4868         MonoDomain* domain = mono_domain_get ();
4869
4870         MONO_ARCH_SAVE_REGS;
4871
4872         if (!domain->entry_assembly)
4873                 return NULL;
4874
4875         return mono_assembly_get_object (domain, domain->entry_assembly);
4876 }
4877
4878 static MonoReflectionAssembly*
4879 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4880 {
4881         MonoMethod *m;
4882         MonoMethod *dest;
4883
4884         MONO_ARCH_SAVE_REGS;
4885
4886         dest = NULL;
4887         mono_stack_walk_no_il (get_executing, &dest);
4888         m = dest;
4889         mono_stack_walk_no_il (get_caller, &dest);
4890         if (!dest)
4891                 dest = m;
4892         return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4893 }
4894
4895 static MonoString *
4896 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4897                                        gboolean assembly_qualified)
4898 {
4899         MonoDomain *domain = mono_object_domain (object); 
4900         MonoTypeNameFormat format;
4901         MonoString *res;
4902         gchar *name;
4903
4904         if (full_name)
4905                 format = assembly_qualified ?
4906                         MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4907                         MONO_TYPE_NAME_FORMAT_FULL_NAME;
4908         else
4909                 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4910  
4911         name = mono_type_get_name_full (object->type, format);
4912         if (!name)
4913                 return NULL;
4914
4915         if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4916                 g_free (name);
4917                 return NULL;
4918         }
4919
4920         res = mono_string_new (domain, name);
4921         g_free (name);
4922
4923         return res;
4924 }
4925
4926 static int
4927 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4928 {
4929         MonoClass *klass = mono_class_from_mono_type (this->type);
4930         mono_class_init_or_throw (klass);
4931         return mono_security_core_clr_class_level (klass);
4932 }
4933
4934 static void
4935 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4936 {
4937         static MonoMethod *create_culture = NULL;
4938         gpointer args [2];
4939         guint32 pkey_len;
4940         const char *pkey_ptr;
4941         gchar *codebase;
4942         MonoBoolean assembly_ref = 0;
4943
4944         MONO_ARCH_SAVE_REGS;
4945
4946         MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4947         aname->major = name->major;
4948         aname->minor = name->minor;
4949         aname->build = name->build;
4950         aname->flags = name->flags;
4951         aname->revision = name->revision;
4952         aname->hashalg = name->hash_alg;
4953         aname->versioncompat = 1; /* SameMachine (default) */
4954         aname->processor_architecture = name->arch;
4955
4956         if (by_default_version)
4957                 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4958
4959         codebase = NULL;
4960         if (absolute != NULL && *absolute != '\0') {
4961                 const gchar *prepend = "file://";
4962                 gchar *result;
4963
4964                 codebase = g_strdup (absolute);
4965
4966 #if HOST_WIN32
4967                 {
4968                         gint i;
4969                         for (i = strlen (codebase) - 1; i >= 0; i--)
4970                                 if (codebase [i] == '\\')
4971                                         codebase [i] = '/';
4972
4973                         if (*codebase == '/' && *(codebase + 1) == '/') {
4974                                 prepend = "file:";
4975                         } else {
4976                                 prepend = "file:///";
4977                         }
4978                 }
4979 #endif
4980                 result = g_strconcat (prepend, codebase, NULL);
4981                 g_free (codebase);
4982                 codebase = result;
4983         }
4984
4985         if (codebase) {
4986                 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4987                 g_free (codebase);
4988         }
4989
4990         if (!create_culture) {
4991                 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4992                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4993                 g_assert (create_culture);
4994                 mono_method_desc_free (desc);
4995         }
4996
4997         if (name->culture) {
4998                 args [0] = mono_string_new (domain, name->culture);
4999                 args [1] = &assembly_ref;
5000                 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5001         }
5002
5003         if (name->public_key) {
5004                 pkey_ptr = (char*)name->public_key;
5005                 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5006
5007                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5008                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5009                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5010         } else if (default_publickey) {
5011                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5012                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5013         }
5014
5015         /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5016         if (name->public_key_token [0]) {
5017                 int i, j;
5018                 char *p;
5019
5020                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5021                 p = mono_array_addr (aname->keyToken, char, 0);
5022
5023                 for (i = 0, j = 0; i < 8; i++) {
5024                         *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5025                         *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5026                         p++;
5027                 }
5028         } else if (default_token) {
5029                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5030         }
5031 }
5032
5033 static MonoString *
5034 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5035 {
5036         MonoDomain *domain = mono_object_domain (assembly); 
5037         MonoAssembly *mass = assembly->assembly;
5038         MonoString *res;
5039         gchar *name;
5040
5041         name = mono_stringify_assembly_name (&mass->aname);
5042         res = mono_string_new (domain, name);
5043         g_free (name);
5044
5045         return res;
5046 }
5047
5048 static void
5049 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5050 {
5051         gchar *absolute;
5052         MonoAssembly *mass = assembly->assembly;
5053
5054         MONO_ARCH_SAVE_REGS;
5055
5056         if (g_path_is_absolute (mass->image->name)) {
5057                 fill_reflection_assembly_name (mono_object_domain (assembly),
5058                         aname, &mass->aname, mass->image->name, TRUE,
5059                         TRUE, TRUE);
5060                 return;
5061         }
5062         absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5063
5064         fill_reflection_assembly_name (mono_object_domain (assembly),
5065                 aname, &mass->aname, absolute, TRUE, TRUE,
5066                 TRUE);
5067
5068         g_free (absolute);
5069 }
5070
5071 static void
5072 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5073 {
5074         char *filename;
5075         MonoImageOpenStatus status = MONO_IMAGE_OK;
5076         gboolean res;
5077         MonoImage *image;
5078         MonoAssemblyName name;
5079         char *dirname
5080
5081         MONO_ARCH_SAVE_REGS;
5082
5083         filename = mono_string_to_utf8 (fname);
5084
5085         dirname = g_path_get_dirname (filename);
5086         replace_shadow_path (mono_domain_get (), dirname, &filename);
5087         g_free (dirname);
5088
5089         image = mono_image_open (filename, &status);
5090
5091         if (!image){
5092                 MonoException *exc;
5093
5094                 g_free (filename);
5095                 if (status == MONO_IMAGE_IMAGE_INVALID)
5096                         exc = mono_get_exception_bad_image_format2 (NULL, fname);
5097                 else
5098                         exc = mono_get_exception_file_not_found2 (NULL, fname);
5099                 mono_raise_exception (exc);
5100         }
5101
5102         res = mono_assembly_fill_assembly_name (image, &name);
5103         if (!res) {
5104                 mono_image_close (image);
5105                 g_free (filename);
5106                 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5107         }
5108
5109         fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5110                 TRUE, FALSE, TRUE);
5111
5112         g_free (filename);
5113         mono_image_close (image);
5114 }
5115
5116 static MonoBoolean
5117 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5118         char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5119 {
5120         MonoBoolean result = FALSE;
5121         MonoDeclSecurityEntry entry;
5122
5123         /* SecurityAction.RequestMinimum */
5124         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5125                 *minimum = entry.blob;
5126                 *minLength = entry.size;
5127                 result = TRUE;
5128         }
5129         /* SecurityAction.RequestOptional */
5130         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5131                 *optional = entry.blob;
5132                 *optLength = entry.size;
5133                 result = TRUE;
5134         }
5135         /* SecurityAction.RequestRefuse */
5136         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5137                 *refused = entry.blob;
5138                 *refLength = entry.size;
5139                 result = TRUE;
5140         }
5141
5142         return result;  
5143 }
5144
5145 static MonoArray*
5146 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5147 {
5148         MonoArray *res;
5149         MonoClass *klass;
5150         MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5151         int i, count;
5152         guint32 attrs, visibility;
5153
5154         /* we start the count from 1 because we skip the special type <Module> */
5155         if (exportedOnly) {
5156                 count = 0;
5157                 for (i = 1; i < tdef->rows; ++i) {
5158                         attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5159                         visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5160                         if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5161                                 count++;
5162                 }
5163         } else {
5164                 count = tdef->rows - 1;
5165         }
5166         res = mono_array_new (domain, mono_defaults.monotype_class, count);
5167         *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5168         count = 0;
5169         for (i = 1; i < tdef->rows; ++i) {
5170                 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5171                 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5172                 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5173                         klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5174                         if (klass) {
5175                                 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5176                         } else {
5177                                 MonoLoaderError *error;
5178                                 MonoException *ex;
5179                                 
5180                                 error = mono_loader_get_last_error ();
5181                                 g_assert (error != NULL);
5182         
5183                                 ex = mono_loader_error_prepare_exception (error);
5184                                 mono_array_setref (*exceptions, count, ex);
5185                         }
5186                         if (mono_loader_get_last_error ())
5187                                 mono_loader_clear_error ();
5188                         count++;
5189                 }
5190         }
5191         
5192         return res;
5193 }
5194
5195 static MonoArray*
5196 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5197 {
5198         MonoArray *res = NULL;
5199         MonoArray *exceptions = NULL;
5200         MonoImage *image = NULL;
5201         MonoTableInfo *table = NULL;
5202         MonoDomain *domain;
5203         GList *list = NULL;
5204         int i, len, ex_count;
5205
5206         MONO_ARCH_SAVE_REGS;
5207
5208         domain = mono_object_domain (assembly);
5209
5210         g_assert (!assembly->assembly->dynamic);
5211         image = assembly->assembly->image;
5212         table = &image->tables [MONO_TABLE_FILE];
5213         res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5214
5215         /* Append data from all modules in the assembly */
5216         for (i = 0; i < table->rows; ++i) {
5217                 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5218                         MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5219                         if (loaded_image) {
5220                                 MonoArray *ex2;
5221                                 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5222                                 /* Append the new types to the end of the array */
5223                                 if (mono_array_length (res2) > 0) {
5224                                         guint32 len1, len2;
5225                                         MonoArray *res3, *ex3;
5226
5227                                         len1 = mono_array_length (res);
5228                                         len2 = mono_array_length (res2);
5229
5230                                         res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5231                                         mono_array_memcpy_refs (res3, 0, res, 0, len1);
5232                                         mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5233                                         res = res3;
5234
5235                                         ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5236                                         mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5237                                         mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5238                                         exceptions = ex3;
5239                                 }
5240                         }
5241                 }
5242         }
5243
5244         /* the ReflectionTypeLoadException must have all the types (Types property), 
5245          * NULL replacing types which throws an exception. The LoaderException must
5246          * contain all exceptions for NULL items.
5247          */
5248
5249         len = mono_array_length (res);
5250
5251         ex_count = 0;
5252         for (i = 0; i < len; i++) {
5253                 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5254                 MonoClass *klass;
5255
5256                 if (t) {
5257                         klass = mono_type_get_class (t->type);
5258                         if ((klass != NULL) && klass->exception_type) {
5259                                 /* keep the class in the list */
5260                                 list = g_list_append (list, klass);
5261                                 /* and replace Type with NULL */
5262                                 mono_array_setref (res, i, NULL);
5263                         }
5264                 } else {
5265                         ex_count ++;
5266                 }
5267         }
5268
5269         if (list || ex_count) {
5270                 GList *tmp = NULL;
5271                 MonoException *exc = NULL;
5272                 MonoArray *exl = NULL;
5273                 int j, length = g_list_length (list) + ex_count;
5274
5275                 mono_loader_clear_error ();
5276
5277                 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5278                 /* Types for which mono_class_get () succeeded */
5279                 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5280                         MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5281                         mono_array_setref (exl, i, exc);
5282                 }
5283                 /* Types for which it don't */
5284                 for (j = 0; j < mono_array_length (exceptions); ++j) {
5285                         MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5286                         if (exc) {
5287                                 g_assert (i < length);
5288                                 mono_array_setref (exl, i, exc);
5289                                 i ++;
5290                         }
5291                 }
5292                 g_list_free (list);
5293                 list = NULL;
5294
5295                 exc = mono_get_exception_reflection_type_load (res, exl);
5296                 mono_loader_clear_error ();
5297                 mono_raise_exception (exc);
5298         }
5299                 
5300         return res;
5301 }
5302
5303 static gboolean
5304 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5305 {
5306         MonoAssemblyName aname;
5307         MonoDomain *domain = mono_object_domain (name);
5308         char *val;
5309         gboolean is_version_defined;
5310         gboolean is_token_defined;
5311
5312         aname.public_key = NULL;
5313         val = mono_string_to_utf8 (assname);
5314         if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5315                 g_free ((guint8*) aname.public_key);
5316                 g_free (val);
5317                 return FALSE;
5318         }
5319         
5320         fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5321                 FALSE, is_token_defined);
5322
5323         mono_assembly_name_free (&aname);
5324         g_free ((guint8*) aname.public_key);
5325         g_free (val);
5326
5327         return TRUE;
5328 }
5329
5330 static MonoReflectionType*
5331 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5332 {
5333         MonoDomain *domain = mono_object_domain (module); 
5334         MonoClass *klass;
5335
5336         MONO_ARCH_SAVE_REGS;
5337
5338         g_assert (module->image);
5339
5340         if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5341                 /* These images do not have a global type */
5342                 return NULL;
5343
5344         klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5345         return mono_type_get_object (domain, &klass->byval_arg);
5346 }
5347
5348 static void
5349 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5350 {
5351         /*if (module->image)
5352                 mono_image_close (module->image);*/
5353 }
5354
5355 static MonoString*
5356 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5357 {
5358         MonoDomain *domain = mono_object_domain (module); 
5359
5360         MONO_ARCH_SAVE_REGS;
5361
5362         g_assert (module->image);
5363         return mono_string_new (domain, module->image->guid);
5364 }
5365
5366 static gpointer
5367 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5368 {
5369 #ifdef HOST_WIN32
5370         if (module->image && module->image->is_module_handle)
5371                 return module->image->raw_data;
5372 #endif
5373
5374         return (gpointer) (-1);
5375 }
5376
5377 static void
5378 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5379 {
5380         if (image->dynamic) {
5381                 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5382                 *pe_kind = dyn->pe_kind;
5383                 *machine = dyn->machine;
5384         }
5385         else {
5386                 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5387                 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5388         }
5389 }
5390
5391 static gint32
5392 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5393 {
5394         return (image->md_version_major << 16) | (image->md_version_minor);
5395 }
5396
5397 static MonoArray*
5398 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5399 {
5400         MonoArray *exceptions;
5401         int i;
5402
5403         MONO_ARCH_SAVE_REGS;
5404
5405         if (!module->image)
5406                 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5407         else {
5408                 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5409                 for (i = 0; i < mono_array_length (exceptions); ++i) {
5410                         MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5411                         if (ex)
5412                                 mono_raise_exception (ex);
5413                 }
5414                 return res;
5415         }
5416 }
5417
5418 static gboolean
5419 mono_memberref_is_method (MonoImage *image, guint32 token)
5420 {
5421         if (!image->dynamic) {
5422                 guint32 cols [MONO_MEMBERREF_SIZE];
5423                 const char *sig;
5424                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5425                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5426                 mono_metadata_decode_blob_size (sig, &sig);
5427                 return (*sig != 0x6);
5428         } else {
5429                 MonoClass *handle_class;
5430
5431                 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5432                         return FALSE;
5433
5434                 return mono_defaults.methodhandle_class == handle_class;
5435         }
5436 }
5437
5438 static void
5439 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5440 {
5441         if (type_args)
5442                 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5443                                                                       mono_array_addr (type_args, MonoType*, 0));
5444         else
5445                 context->class_inst = NULL;
5446         if (method_args)
5447                 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5448                                                                        mono_array_addr (method_args, MonoType*, 0));
5449         else
5450                 context->method_inst = NULL;
5451 }
5452
5453 static MonoType*
5454 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5455 {
5456         MonoClass *klass;
5457         int table = mono_metadata_token_table (token);
5458         int index = mono_metadata_token_index (token);
5459         MonoGenericContext context;
5460
5461         *error = ResolveTokenError_Other;
5462
5463         /* Validate token */
5464         if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) && 
5465                 (table != MONO_TABLE_TYPESPEC)) {
5466                 *error = ResolveTokenError_BadTable;
5467                 return NULL;
5468         }
5469
5470         if (image->dynamic) {
5471                 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5472                         klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5473                         return klass ? &klass->byval_arg : NULL;
5474                 }
5475
5476                 init_generic_context_from_args (&context, type_args, method_args);
5477                 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5478                 return klass ? &klass->byval_arg : NULL;
5479         }
5480
5481         if ((index <= 0) || (index > image->tables [table].rows)) {
5482                 *error = ResolveTokenError_OutOfRange;
5483                 return NULL;
5484         }
5485
5486         init_generic_context_from_args (&context, type_args, method_args);
5487         klass = mono_class_get_full (image, token, &context);
5488
5489         if (mono_loader_get_last_error ())
5490                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5491
5492         if (klass)
5493                 return &klass->byval_arg;
5494         else
5495                 return NULL;
5496 }
5497
5498 static MonoMethod*
5499 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5500 {
5501         int table = mono_metadata_token_table (token);
5502         int index = mono_metadata_token_index (token);
5503         MonoGenericContext context;
5504         MonoMethod *method;
5505
5506         *error = ResolveTokenError_Other;
5507
5508         /* Validate token */
5509         if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) && 
5510                 (table != MONO_TABLE_MEMBERREF)) {
5511                 *error = ResolveTokenError_BadTable;
5512                 return NULL;
5513         }
5514
5515         if (image->dynamic) {
5516                 if (table == MONO_TABLE_METHOD)
5517                         return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5518
5519                 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5520                         *error = ResolveTokenError_BadTable;
5521                         return NULL;
5522                 }
5523
5524                 init_generic_context_from_args (&context, type_args, method_args);
5525                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5526         }
5527
5528         if ((index <= 0) || (index > image->tables [table].rows)) {
5529                 *error = ResolveTokenError_OutOfRange;
5530                 return NULL;
5531         }
5532         if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5533                 *error = ResolveTokenError_BadTable;
5534                 return NULL;
5535         }
5536
5537         init_generic_context_from_args (&context, type_args, method_args);
5538         method = mono_get_method_full (image, token, NULL, &context);
5539
5540         if (mono_loader_get_last_error ())
5541                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5542
5543         return method;
5544 }
5545
5546 static MonoString*
5547 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5548 {
5549         int index = mono_metadata_token_index (token);
5550
5551         *error = ResolveTokenError_Other;
5552
5553         /* Validate token */
5554         if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5555                 *error = ResolveTokenError_BadTable;
5556                 return NULL;
5557         }
5558
5559         if (image->dynamic)
5560                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5561
5562         if ((index <= 0) || (index >= image->heap_us.size)) {
5563                 *error = ResolveTokenError_OutOfRange;
5564                 return NULL;
5565         }
5566
5567         /* FIXME: What to do if the index points into the middle of a string ? */
5568
5569         return mono_ldstr (mono_domain_get (), image, index);
5570 }
5571
5572 static MonoClassField*
5573 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5574 {
5575         MonoClass *klass;
5576         int table = mono_metadata_token_table (token);
5577         int index = mono_metadata_token_index (token);
5578         MonoGenericContext context;
5579         MonoClassField *field;
5580
5581         *error = ResolveTokenError_Other;
5582
5583         /* Validate token */
5584         if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5585                 *error = ResolveTokenError_BadTable;
5586                 return NULL;
5587         }
5588
5589         if (image->dynamic) {
5590                 if (table == MONO_TABLE_FIELD)
5591                         return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5592
5593                 if (mono_memberref_is_method (image, token)) {
5594                         *error = ResolveTokenError_BadTable;
5595                         return NULL;
5596                 }
5597
5598                 init_generic_context_from_args (&context, type_args, method_args);
5599                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5600         }
5601
5602         if ((index <= 0) || (index > image->tables [table].rows)) {
5603                 *error = ResolveTokenError_OutOfRange;
5604                 return NULL;
5605         }
5606         if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5607                 *error = ResolveTokenError_BadTable;
5608                 return NULL;
5609         }
5610
5611         init_generic_context_from_args (&context, type_args, method_args);
5612         field = mono_field_from_token (image, token, &klass, &context);
5613
5614         if (mono_loader_get_last_error ())
5615                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5616         
5617         return field;
5618 }
5619
5620
5621 static MonoObject*
5622 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5623 {
5624         int table = mono_metadata_token_table (token);
5625
5626         *error = ResolveTokenError_Other;
5627
5628         switch (table) {
5629         case MONO_TABLE_TYPEDEF:
5630         case MONO_TABLE_TYPEREF:
5631         case MONO_TABLE_TYPESPEC: {
5632                 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5633                 if (t)
5634                         return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5635                 else
5636                         return NULL;
5637         }
5638         case MONO_TABLE_METHOD:
5639         case MONO_TABLE_METHODSPEC: {
5640                 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5641                 if (m)
5642                         return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5643                 else
5644                         return NULL;
5645         }               
5646         case MONO_TABLE_FIELD: {
5647                 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5648                 if (f)
5649                         return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5650                 else
5651                         return NULL;
5652         }
5653         case MONO_TABLE_MEMBERREF:
5654                 if (mono_memberref_is_method (image, token)) {
5655                         MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5656                         if (m)
5657                                 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5658                         else
5659                                 return NULL;
5660                 }
5661                 else {
5662                         MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5663                         if (f)
5664                                 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5665                         else
5666                                 return NULL;
5667                 }
5668                 break;
5669
5670         default:
5671                 *error = ResolveTokenError_BadTable;
5672         }
5673
5674         return NULL;
5675 }
5676
5677 static MonoArray*
5678 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5679 {
5680         int table = mono_metadata_token_table (token);
5681         int idx = mono_metadata_token_index (token);
5682         MonoTableInfo *tables = image->tables;
5683         guint32 sig, len;
5684         const char *ptr;
5685         MonoArray *res;
5686
5687         *error = ResolveTokenError_OutOfRange;
5688
5689         /* FIXME: Support other tables ? */
5690         if (table != MONO_TABLE_STANDALONESIG)
5691                 return NULL;
5692
5693         if (image->dynamic)
5694                 return NULL;
5695
5696         if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5697                 return NULL;
5698
5699         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5700
5701         ptr = mono_metadata_blob_heap (image, sig);
5702         len = mono_metadata_decode_blob_size (ptr, &ptr);
5703
5704         res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5705         memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5706         return res;
5707 }
5708
5709 static MonoReflectionType*
5710 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5711 {
5712         MonoClass *klass;
5713         int isbyref = 0, rank;
5714         char *str = mono_string_to_utf8 (smodifiers);
5715         char *p;
5716
5717         MONO_ARCH_SAVE_REGS;
5718
5719         klass = mono_class_from_mono_type (tb->type.type);
5720         p = str;
5721         /* logic taken from mono_reflection_parse_type(): keep in sync */
5722         while (*p) {
5723                 switch (*p) {
5724                 case '&':
5725                         if (isbyref) { /* only one level allowed by the spec */
5726                                 g_free (str);
5727                                 return NULL;
5728                         }
5729                         isbyref = 1;
5730                         p++;
5731                         g_free (str);
5732                         return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5733                         break;
5734                 case '*':
5735                         klass = mono_ptr_class_get (&klass->byval_arg);
5736                         mono_class_init (klass);
5737                         p++;
5738                         break;
5739                 case '[':
5740                         rank = 1;
5741                         p++;
5742                         while (*p) {
5743                                 if (*p == ']')
5744                                         break;
5745                                 if (*p == ',')
5746                                         rank++;
5747                                 else if (*p != '*') { /* '*' means unknown lower bound */
5748                                         g_free (str);
5749                                         return NULL;
5750                                 }
5751                                 ++p;
5752                         }
5753                         if (*p != ']') {
5754                                 g_free (str);
5755                                 return NULL;
5756                         }
5757                         p++;
5758                         klass = mono_array_class_get (klass, rank);
5759                         mono_class_init (klass);
5760                         break;
5761                 default:
5762                         break;
5763                 }
5764         }
5765         g_free (str);
5766         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5767 }
5768
5769 static MonoBoolean
5770 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5771 {
5772         MonoType *type;
5773         MonoBoolean res;
5774
5775         MONO_ARCH_SAVE_REGS;
5776
5777         type = t->type;
5778         res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5779
5780         return res;
5781 }
5782
5783 static void
5784 check_for_invalid_type (MonoClass *klass)
5785 {
5786         char *name;
5787         MonoString *str;
5788         if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5789                 return;
5790
5791         name = mono_type_get_full_name (klass);
5792         str =  mono_string_new (mono_domain_get (), name);
5793         g_free (name);
5794         mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5795
5796 }
5797 static MonoReflectionType *
5798 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5799 {
5800         MonoClass *klass, *aklass;
5801
5802         MONO_ARCH_SAVE_REGS;
5803
5804         klass = mono_class_from_mono_type (type->type);
5805         check_for_invalid_type (klass);
5806
5807         if (rank == 0) //single dimentional array
5808                 aklass = mono_array_class_get (klass, 1);
5809         else
5810                 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5811
5812         return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5813 }
5814
5815 static MonoReflectionType *
5816 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5817 {
5818         MonoClass *klass;
5819
5820         MONO_ARCH_SAVE_REGS;
5821
5822         klass = mono_class_from_mono_type (type->type);
5823         mono_class_init_or_throw (klass);
5824         check_for_invalid_type (klass);
5825
5826         return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5827 }
5828
5829 static MonoReflectionType *
5830 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5831 {
5832         MonoClass *klass, *pklass;
5833
5834         klass = mono_class_from_mono_type (type->type);
5835         mono_class_init_or_throw (klass);
5836         check_for_invalid_type (klass);
5837
5838         pklass = mono_ptr_class_get (type->type);
5839
5840         return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5841 }
5842
5843 static MonoObject *
5844 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5845                                                    MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5846 {
5847         MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5848         MonoObject *delegate;
5849         gpointer func;
5850         MonoMethod *method = info->method;
5851
5852         MONO_ARCH_SAVE_REGS;
5853
5854         mono_class_init_or_throw (delegate_class);
5855
5856         mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5857
5858         if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5859                 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5860                         return NULL;
5861         }
5862
5863         delegate = mono_object_new (mono_object_domain (type), delegate_class);
5864
5865         if (method->dynamic) {
5866                 /* Creating a trampoline would leak memory */
5867                 func = mono_compile_method (method);
5868         } else {
5869                 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5870                         method = mono_object_get_virtual_method (target, method);
5871                 func = mono_create_ftnptr (mono_domain_get (),
5872                         mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5873         }
5874
5875         mono_delegate_ctor_with_method (delegate, target, func, method);
5876
5877         return delegate;
5878 }
5879
5880 static void
5881 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5882 {
5883         /* Reset the invoke impl to the default one */
5884         this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5885 }
5886
5887 /*
5888  * Magic number to convert a time which is relative to
5889  * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5890  */
5891 #define EPOCH_ADJUST    ((guint64)62135596800LL)
5892
5893 /*
5894  * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5895  */
5896 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5897
5898 #ifdef HOST_WIN32
5899 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5900 static void
5901 convert_to_absolute_date(SYSTEMTIME *date)
5902 {
5903 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5904         static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5905         static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5906         /* from the calendar FAQ */
5907         int a = (14 - date->wMonth) / 12;
5908         int y = date->wYear - a;
5909         int m = date->wMonth + 12 * a - 2;
5910         int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5911
5912         /* d is now the day of the week for the first of the month (0 == Sunday) */
5913
5914         int day_of_week = date->wDayOfWeek;
5915
5916         /* set day_in_month to the first day in the month which falls on day_of_week */    
5917         int day_in_month = 1 + (day_of_week - d);
5918         if (day_in_month <= 0)
5919                 day_in_month += 7;
5920
5921         /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5922         date->wDay = day_in_month + (date->wDay - 1) * 7;
5923         if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5924                 date->wDay -= 7;
5925 }
5926 #endif
5927
5928 #ifndef HOST_WIN32
5929 /*
5930  * Return's the offset from GMT of a local time.
5931  * 
5932  *  tm is a local time
5933  *  t  is the same local time as seconds.
5934  */
5935 static int 
5936 gmt_offset(struct tm *tm, time_t t)
5937 {
5938 #if defined (HAVE_TM_GMTOFF)
5939         return tm->tm_gmtoff;
5940 #else
5941         struct tm g;
5942         time_t t2;
5943         g = *gmtime(&t);
5944         g.tm_isdst = tm->tm_isdst;
5945         t2 = mktime(&g);
5946         return (int)difftime(t, t2);
5947 #endif
5948 }
5949 #endif
5950 /*
5951  * This is heavily based on zdump.c from glibc 2.2.
5952  *
5953  *  * data[0]:  start of daylight saving time (in DateTime ticks).
5954  *  * data[1]:  end of daylight saving time (in DateTime ticks).
5955  *  * data[2]:  utcoffset (in TimeSpan ticks).
5956  *  * data[3]:  additional offset when daylight saving (in TimeSpan ticks).
5957  *  * name[0]:  name of this timezone when not daylight saving.
5958  *  * name[1]:  name of this timezone when daylight saving.
5959  *
5960  *  FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5961  *         the class library allows years between 1 and 9999.
5962  *
5963  *  Returns true on success and zero on failure.
5964  */
5965 static guint32
5966 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5967 {
5968 #ifndef HOST_WIN32
5969         MonoDomain *domain = mono_domain_get ();
5970         struct tm start, tt;
5971         time_t t;
5972
5973         long int gmtoff;
5974         int is_daylight = 0, day;
5975         char tzone [64];
5976
5977         MONO_ARCH_SAVE_REGS;
5978
5979         MONO_CHECK_ARG_NULL (data);
5980         MONO_CHECK_ARG_NULL (names);
5981
5982         mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5983         mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5984
5985         /* 
5986          * no info is better than crashing: we'll need our own tz data
5987          * to make this work properly, anyway. The range is probably
5988          * reduced to 1970 .. 2037 because that is what mktime is
5989          * guaranteed to support (we get into an infinite loop
5990          * otherwise).
5991          */
5992
5993         memset (&start, 0, sizeof (start));
5994
5995         start.tm_mday = 1;
5996         start.tm_year = year-1900;
5997
5998         t = mktime (&start);
5999
6000         if ((year < 1970) || (year > 2037) || (t == -1)) {
6001                 t = time (NULL);
6002                 tt = *localtime (&t);
6003                 strftime (tzone, sizeof (tzone), "%Z", &tt);
6004                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6005                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6006                 return 1;
6007         }
6008
6009         gmtoff = gmt_offset (&start, t);
6010
6011         /* For each day of the year, calculate the tm_gmtoff. */
6012         for (day = 0; day < 365; day++) {
6013
6014                 t += 3600*24;
6015                 tt = *localtime (&t);
6016
6017                 /* Daylight saving starts or ends here. */
6018                 if (gmt_offset (&tt, t) != gmtoff) {
6019                         struct tm tt1;
6020                         time_t t1;
6021
6022                         /* Try to find the exact hour when daylight saving starts/ends. */
6023                         t1 = t;
6024                         do {
6025                                 t1 -= 3600;
6026                                 tt1 = *localtime (&t1);
6027                         } while (gmt_offset (&tt1, t1) != gmtoff);
6028
6029                         /* Try to find the exact minute when daylight saving starts/ends. */
6030                         do {
6031                                 t1 += 60;
6032                                 tt1 = *localtime (&t1);
6033                         } while (gmt_offset (&tt1, t1) == gmtoff);
6034                         t1+=gmtoff;
6035                         strftime (tzone, sizeof (tzone), "%Z", &tt);
6036                         
6037                         /* Write data, if we're already in daylight saving, we're done. */
6038                         if (is_daylight) {
6039                                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6040                                 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6041                                 return 1;
6042                         } else {
6043                                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6044                                 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6045                                 is_daylight = 1;
6046                         }
6047
6048                         /* This is only set once when we enter daylight saving. */
6049                         mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6050                         mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6051
6052                         gmtoff = gmt_offset (&tt, t);
6053                 }
6054         }
6055
6056         if (!is_daylight) {
6057                 strftime (tzone, sizeof (tzone), "%Z", &tt);
6058                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6059                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6060                 mono_array_set ((*data), gint64, 0, 0);
6061                 mono_array_set ((*data), gint64, 1, 0);
6062                 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6063                 mono_array_set ((*data), gint64, 3, 0);
6064         }
6065
6066         return 1;
6067 #else
6068         MonoDomain *domain = mono_domain_get ();
6069         TIME_ZONE_INFORMATION tz_info;
6070         FILETIME ft;
6071         int i;
6072         int err, tz_id;
6073
6074         tz_id = GetTimeZoneInformation (&tz_info);
6075         if (tz_id == TIME_ZONE_ID_INVALID)
6076                 return 0;
6077
6078         MONO_CHECK_ARG_NULL (data);
6079         MONO_CHECK_ARG_NULL (names);
6080
6081         mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6082         mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6083
6084         for (i = 0; i < 32; ++i)
6085                 if (!tz_info.DaylightName [i])
6086                         break;
6087         mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6088         for (i = 0; i < 32; ++i)
6089                 if (!tz_info.StandardName [i])
6090                         break;
6091         mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6092
6093         if ((year <= 1601) || (year > 30827)) {
6094                 /*
6095                  * According to MSDN, the MS time functions can't handle dates outside
6096                  * this interval.
6097                  */
6098                 return 1;
6099         }
6100
6101         /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6102         if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6103                 tz_info.StandardDate.wYear = year;
6104                 convert_to_absolute_date(&tz_info.StandardDate);
6105                 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6106                 //g_assert(err);
6107                 if (err == 0)
6108                         return 0;
6109                 
6110                 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6111                 tz_info.DaylightDate.wYear = year;
6112                 convert_to_absolute_date(&tz_info.DaylightDate);
6113                 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6114                 //g_assert(err);
6115                 if (err == 0)
6116                         return 0;
6117                 
6118                 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6119         }
6120         mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6121         mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6122
6123         return 1;
6124 #endif
6125 }
6126
6127 static gpointer
6128 ves_icall_System_Object_obj_address (MonoObject *this) 
6129 {
6130         MONO_ARCH_SAVE_REGS;
6131
6132         return this;
6133 }
6134
6135 /* System.Buffer */
6136
6137 static inline gint32 
6138 mono_array_get_byte_length (MonoArray *array)
6139 {
6140         MonoClass *klass;
6141         int length;
6142         int i;
6143
6144         klass = array->obj.vtable->klass;
6145
6146         if (array->bounds == NULL)
6147                 length = array->max_length;
6148         else {
6149                 length = 1;
6150                 for (i = 0; i < klass->rank; ++ i)
6151                         length *= array->bounds [i].length;
6152         }
6153
6154         switch (klass->element_class->byval_arg.type) {
6155         case MONO_TYPE_I1:
6156         case MONO_TYPE_U1:
6157         case MONO_TYPE_BOOLEAN:
6158                 return length;
6159         case MONO_TYPE_I2:
6160         case MONO_TYPE_U2:
6161         case MONO_TYPE_CHAR:
6162                 return length << 1;
6163         case MONO_TYPE_I4:
6164         case MONO_TYPE_U4:
6165         case MONO_TYPE_R4:
6166                 return length << 2;
6167         case MONO_TYPE_I:
6168         case MONO_TYPE_U:
6169                 return length * sizeof (gpointer);
6170         case MONO_TYPE_I8:
6171         case MONO_TYPE_U8:
6172         case MONO_TYPE_R8:
6173                 return length << 3;
6174         default:
6175                 return -1;
6176         }
6177 }
6178
6179 static gint32 
6180 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array) 
6181 {
6182         MONO_ARCH_SAVE_REGS;
6183
6184         return mono_array_get_byte_length (array);
6185 }
6186
6187 static gint8 
6188 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx) 
6189 {
6190         MONO_ARCH_SAVE_REGS;
6191
6192         return mono_array_get (array, gint8, idx);
6193 }
6194
6195 static void 
6196 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value) 
6197 {
6198         MONO_ARCH_SAVE_REGS;
6199
6200         mono_array_set (array, gint8, idx, value);
6201 }
6202
6203 static MonoBoolean
6204 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count) 
6205 {
6206         guint8 *src_buf, *dest_buf;
6207
6208         MONO_ARCH_SAVE_REGS;
6209
6210         /* watch out for integer overflow */
6211         if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6212                 return FALSE;
6213
6214         src_buf = (guint8 *)src->vector + src_offset;
6215         dest_buf = (guint8 *)dest->vector + dest_offset;
6216
6217         if (src != dest)
6218                 memcpy (dest_buf, src_buf, count);
6219         else
6220                 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6221
6222         return TRUE;
6223 }
6224
6225 static MonoObject *
6226 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6227 {
6228         MonoDomain *domain = mono_object_domain (this); 
6229         MonoObject *res;
6230         MonoRealProxy *rp = ((MonoRealProxy *)this);
6231         MonoTransparentProxy *tp;
6232         MonoType *type;
6233         MonoClass *klass;
6234
6235         MONO_ARCH_SAVE_REGS;
6236
6237         res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6238         tp = (MonoTransparentProxy*) res;
6239         
6240         MONO_OBJECT_SETREF (tp, rp, rp);
6241         type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6242         klass = mono_class_from_mono_type (type);
6243
6244         tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6245         tp->remote_class = mono_remote_class (domain, class_name, klass);
6246
6247         res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6248         return res;
6249 }
6250
6251 static MonoReflectionType *
6252 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6253 {
6254         return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6255 }
6256
6257 /* System.Environment */
6258
6259 MonoString*
6260 ves_icall_System_Environment_get_UserName (void)
6261 {
6262         MONO_ARCH_SAVE_REGS;
6263
6264         /* using glib is more portable */
6265         return mono_string_new (mono_domain_get (), g_get_user_name ());
6266 }
6267
6268
6269 static MonoString *
6270 ves_icall_System_Environment_get_MachineName (void)
6271 {
6272 #if defined (HOST_WIN32)
6273         gunichar2 *buf;
6274         guint32 len;
6275         MonoString *result;
6276
6277         len = MAX_COMPUTERNAME_LENGTH + 1;
6278         buf = g_new (gunichar2, len);
6279
6280         result = NULL;
6281         if (GetComputerName (buf, (PDWORD) &len))
6282                 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6283
6284         g_free (buf);
6285         return result;
6286 #elif !defined(DISABLE_SOCKETS)
6287         gchar buf [256];
6288         MonoString *result;
6289
6290         if (gethostname (buf, sizeof (buf)) == 0)
6291                 result = mono_string_new (mono_domain_get (), buf);
6292         else
6293                 result = NULL;
6294         
6295         return result;
6296 #else
6297         return mono_string_new (mono_domain_get (), "mono");
6298 #endif
6299 }
6300
6301 static int
6302 ves_icall_System_Environment_get_Platform (void)
6303 {
6304 #if defined (TARGET_WIN32)
6305         /* Win32NT */
6306         return 2;
6307 #elif defined(__MACH__)
6308         /* OSX */
6309         //
6310         // Notice that the value is hidden from user code, and only exposed
6311         // to mscorlib.   This is due to Mono's Unix/MacOS code predating the
6312         // define and making assumptions based on Unix/128/4 values before there
6313         // was a MacOS define.    Lots of code would assume that not-Unix meant
6314         // Windows, but in this case, it would be OSX. 
6315         //
6316         return 6;
6317 #else
6318         /* Unix */
6319         return 4;
6320 #endif
6321 }
6322
6323 static MonoString *
6324 ves_icall_System_Environment_get_NewLine (void)
6325 {
6326         MONO_ARCH_SAVE_REGS;
6327
6328 #if defined (HOST_WIN32)
6329         return mono_string_new (mono_domain_get (), "\r\n");
6330 #else
6331         return mono_string_new (mono_domain_get (), "\n");
6332 #endif
6333 }
6334
6335 static MonoString *
6336 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6337 {
6338         const gchar *value;
6339         gchar *utf8_name;
6340
6341         MONO_ARCH_SAVE_REGS;
6342
6343         if (name == NULL)
6344                 return NULL;
6345
6346         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6347         value = g_getenv (utf8_name);
6348
6349         g_free (utf8_name);
6350
6351         if (value == 0)
6352                 return NULL;
6353         
6354         return mono_string_new (mono_domain_get (), value);
6355 }
6356
6357 /*
6358  * There is no standard way to get at environ.
6359  */
6360 #ifndef _MSC_VER
6361 #ifndef __MINGW32_VERSION
6362 #if defined(__APPLE__) && !defined (__arm__)
6363 /* Apple defines this in crt_externs.h but doesn't provide that header for 
6364  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
6365  * in fact exist on all implementations (so far) 
6366  */
6367 gchar ***_NSGetEnviron(void);
6368 #define environ (*_NSGetEnviron())
6369 #else
6370 extern
6371 char **environ;
6372 #endif
6373 #endif
6374 #endif
6375
6376 static MonoArray *
6377 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6378 {
6379 #ifdef HOST_WIN32
6380         MonoArray *names;
6381         MonoDomain *domain;
6382         MonoString *str;
6383         WCHAR* env_strings;
6384         WCHAR* env_string;
6385         WCHAR* equal_str;
6386         int n = 0;
6387
6388         env_strings = GetEnvironmentStrings();
6389
6390         if (env_strings) {
6391                 env_string = env_strings;
6392                 while (*env_string != '\0') {
6393                 /* weird case that MS seems to skip */
6394                         if (*env_string != '=')
6395                                 n++;
6396                         while (*env_string != '\0')
6397                                 env_string++;
6398                         env_string++;
6399                 }
6400         }
6401
6402         domain = mono_domain_get ();
6403         names = mono_array_new (domain, mono_defaults.string_class, n);
6404
6405         if (env_strings) {
6406                 n = 0;
6407                 env_string = env_strings;
6408                 while (*env_string != '\0') {
6409                         /* weird case that MS seems to skip */
6410                         if (*env_string != '=') {
6411                                 equal_str = wcschr(env_string, '=');
6412                                 g_assert(equal_str);
6413                                 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6414                                 mono_array_setref (names, n, str);
6415                                 n++;
6416                         }
6417                         while (*env_string != '\0')
6418                                 env_string++;
6419                         env_string++;
6420                 }
6421
6422                 FreeEnvironmentStrings (env_strings);
6423         }
6424
6425         return names;
6426
6427 #else
6428         MonoArray *names;
6429         MonoDomain *domain;
6430         MonoString *str;
6431         gchar **e, **parts;
6432         int n;
6433
6434         MONO_ARCH_SAVE_REGS;
6435
6436         n = 0;
6437         for (e = environ; *e != 0; ++ e)
6438                 ++ n;
6439
6440         domain = mono_domain_get ();
6441         names = mono_array_new (domain, mono_defaults.string_class, n);
6442
6443         n = 0;
6444         for (e = environ; *e != 0; ++ e) {
6445                 parts = g_strsplit (*e, "=", 2);
6446                 if (*parts != 0) {
6447                         str = mono_string_new (domain, *parts);
6448                         mono_array_setref (names, n, str);
6449                 }
6450
6451                 g_strfreev (parts);
6452
6453                 ++ n;
6454         }
6455
6456         return names;
6457 #endif
6458 }
6459
6460 /*
6461  * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6462  */
6463 #if !GLIB_CHECK_VERSION(2,4,0)
6464 #define g_setenv(a,b,c)   setenv(a,b,c)
6465 #define g_unsetenv(a) unsetenv(a)
6466 #endif
6467
6468 static void
6469 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6470 {
6471         MonoError error;
6472 #ifdef HOST_WIN32
6473
6474         gunichar2 *utf16_name, *utf16_value;
6475 #else
6476         gchar *utf8_name, *utf8_value;
6477 #endif
6478
6479         MONO_ARCH_SAVE_REGS;
6480         
6481 #ifdef HOST_WIN32
6482         utf16_name = mono_string_to_utf16 (name);
6483         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6484                 SetEnvironmentVariable (utf16_name, NULL);
6485                 g_free (utf16_name);
6486                 return;
6487         }
6488
6489         utf16_value = mono_string_to_utf16 (value);
6490
6491         SetEnvironmentVariable (utf16_name, utf16_value);
6492
6493         g_free (utf16_name);
6494         g_free (utf16_value);
6495 #else
6496         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6497
6498         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6499                 g_unsetenv (utf8_name);
6500                 g_free (utf8_name);
6501                 return;
6502         }
6503
6504         utf8_value = mono_string_to_utf8_checked (value, &error);
6505         if (!mono_error_ok (&error)) {
6506                 g_free (utf8_name);
6507                 mono_error_raise_exception (&error);
6508         }
6509         g_setenv (utf8_name, utf8_value, TRUE);
6510
6511         g_free (utf8_name);
6512         g_free (utf8_value);
6513 #endif
6514 }
6515
6516 static void
6517 ves_icall_System_Environment_Exit (int result)
6518 {
6519         MONO_ARCH_SAVE_REGS;
6520
6521         mono_threads_set_shutting_down ();
6522
6523         mono_runtime_set_shutting_down ();
6524
6525         /* This will kill the tp threads which cannot be suspended */
6526         mono_thread_pool_cleanup ();
6527
6528         /* Suspend all managed threads since the runtime is going away */
6529         mono_thread_suspend_all_other_threads ();
6530
6531         mono_runtime_quit ();
6532
6533         /* we may need to do some cleanup here... */
6534         exit (result);
6535 }
6536
6537 static MonoString*
6538 ves_icall_System_Environment_GetGacPath (void)
6539 {
6540         return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6541 }
6542
6543 static MonoString*
6544 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6545 {
6546 #if defined (HOST_WIN32)
6547         #ifndef CSIDL_FLAG_CREATE
6548                 #define CSIDL_FLAG_CREATE       0x8000
6549         #endif
6550
6551         WCHAR path [MAX_PATH];
6552         /* Create directory if no existing */
6553         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6554                 int len = 0;
6555                 while (path [len])
6556                         ++ len;
6557                 return mono_string_new_utf16 (mono_domain_get (), path, len);
6558         }
6559 #else
6560         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6561 #endif
6562         return mono_string_new (mono_domain_get (), "");
6563 }
6564
6565 static MonoArray *
6566 ves_icall_System_Environment_GetLogicalDrives (void)
6567 {
6568         gunichar2 buf [256], *ptr, *dname;
6569         gunichar2 *u16;
6570         guint initial_size = 127, size = 128;
6571         gint ndrives;
6572         MonoArray *result;
6573         MonoString *drivestr;
6574         MonoDomain *domain = mono_domain_get ();
6575         gint len;
6576
6577         MONO_ARCH_SAVE_REGS;
6578
6579         buf [0] = '\0';
6580         ptr = buf;
6581
6582         while (size > initial_size) {
6583                 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6584                 if (size > initial_size) {
6585                         if (ptr != buf)
6586                                 g_free (ptr);
6587                         ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6588                         initial_size = size;
6589                         size++;
6590                 }
6591         }
6592
6593         /* Count strings */
6594         dname = ptr;
6595         ndrives = 0;
6596         do {
6597                 while (*dname++);
6598                 ndrives++;
6599         } while (*dname);
6600
6601         dname = ptr;
6602         result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6603         ndrives = 0;
6604         do {
6605                 len = 0;
6606                 u16 = dname;
6607                 while (*u16) { u16++; len ++; }
6608                 drivestr = mono_string_new_utf16 (domain, dname, len);
6609                 mono_array_setref (result, ndrives++, drivestr);
6610                 while (*dname++);
6611         } while (*dname);
6612
6613         if (ptr != buf)
6614                 g_free (ptr);
6615
6616         return result;
6617 }
6618
6619 static MonoString *
6620 ves_icall_System_Environment_InternalGetHome (void)
6621 {
6622         MONO_ARCH_SAVE_REGS;
6623
6624         return mono_string_new (mono_domain_get (), g_get_home_dir ());
6625 }
6626
6627 static const char *encodings [] = {
6628         (char *) 1,
6629                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6630                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6631                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6632         (char *) 2,
6633                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6634                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6635                 "x_unicode_2_0_utf_7",
6636         (char *) 3,
6637                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6638                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6639         (char *) 4,
6640                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6641                 "iso_10646_ucs2",
6642         (char *) 5,
6643                 "unicodefffe", "utf_16be",
6644         (char *) 6,
6645                 "iso_8859_1",
6646         (char *) 0
6647 };
6648
6649 /*
6650  * Returns the internal codepage, if the value of "int_code_page" is
6651  * 1 at entry, and we can not compute a suitable code page number,
6652  * returns the code page as a string
6653  */
6654 static MonoString*
6655 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page) 
6656 {
6657         const char *cset;
6658         const char *p;
6659         char *c;
6660         char *codepage = NULL;
6661         int code;
6662         int want_name = *int_code_page;
6663         int i;
6664         
6665         *int_code_page = -1;
6666         MONO_ARCH_SAVE_REGS;
6667
6668         g_get_charset (&cset);
6669         c = codepage = strdup (cset);
6670         for (c = codepage; *c; c++){
6671                 if (isascii (*c) && isalpha (*c))
6672                         *c = tolower (*c);
6673                 if (*c == '-')
6674                         *c = '_';
6675         }
6676         /* g_print ("charset: %s\n", cset); */
6677         
6678         /* handle some common aliases */
6679         p = encodings [0];
6680         code = 0;
6681         for (i = 0; p != 0; ){
6682                 if ((gssize) p < 7){
6683                         code = (gssize) p;
6684                         p = encodings [++i];
6685                         continue;
6686                 }
6687                 if (strcmp (p, codepage) == 0){
6688                         *int_code_page = code;
6689                         break;
6690                 }
6691                 p = encodings [++i];
6692         }
6693         
6694         if (strstr (codepage, "utf_8") != NULL)
6695                 *int_code_page |= 0x10000000;
6696         free (codepage);
6697         
6698         if (want_name && *int_code_page == -1)
6699                 return mono_string_new (mono_domain_get (), cset);
6700         else
6701                 return NULL;
6702 }
6703
6704 static MonoBoolean
6705 ves_icall_System_Environment_get_HasShutdownStarted (void)
6706 {
6707         if (mono_runtime_is_shutting_down ())
6708                 return TRUE;
6709
6710         if (mono_domain_is_unloading (mono_domain_get ()))
6711                 return TRUE;
6712
6713         return FALSE;
6714 }
6715
6716 static void
6717 ves_icall_System_Environment_BroadcastSettingChange (void)
6718 {
6719 #ifdef HOST_WIN32
6720         SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6721 #endif
6722 }
6723
6724 static void
6725 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this, 
6726                                          MonoReflectionMethod *method,
6727                                          MonoArray *out_args)
6728 {
6729         MONO_ARCH_SAVE_REGS;
6730
6731         mono_message_init (mono_object_domain (this), this, method, out_args);
6732 }
6733
6734 static MonoBoolean
6735 ves_icall_IsTransparentProxy (MonoObject *proxy)
6736 {
6737         MONO_ARCH_SAVE_REGS;
6738
6739         if (!proxy)
6740                 return 0;
6741
6742         if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6743                 return 1;
6744
6745         return 0;
6746 }
6747
6748 static MonoReflectionMethod *
6749 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6750         MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6751 {
6752         MonoClass *klass;
6753         MonoMethod *method;
6754         MonoMethod **vtable;
6755         MonoMethod *res = NULL;
6756
6757         MONO_CHECK_ARG_NULL (rtype);
6758         MONO_CHECK_ARG_NULL (rmethod);
6759
6760         method = rmethod->method;
6761         klass = mono_class_from_mono_type (rtype->type);
6762         mono_class_init_or_throw (klass);
6763
6764         if (MONO_CLASS_IS_INTERFACE (klass))
6765                 return NULL;
6766
6767         if (method->flags & METHOD_ATTRIBUTE_STATIC)
6768                 return NULL;
6769
6770         if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6771                 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6772                         return rmethod;
6773                 else
6774                         return NULL;
6775         }
6776
6777         mono_class_setup_vtable (klass);
6778         vtable = klass->vtable;
6779
6780         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6781                 gboolean variance_used = FALSE;
6782                 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6783                 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6784                 if (offs >= 0)
6785                         res = vtable [offs + method->slot];
6786         } else {
6787                 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6788                         return NULL;
6789
6790                 if (method->slot != -1)
6791                         res = vtable [method->slot];
6792         }
6793
6794         if (!res)
6795                 return NULL;
6796
6797         return mono_method_get_object (mono_domain_get (), res, NULL);
6798 }
6799
6800 static void
6801 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6802 {
6803         MonoClass *klass;
6804         MonoVTable* vtable;
6805
6806         MONO_ARCH_SAVE_REGS;
6807
6808         klass = mono_class_from_mono_type (type->type);
6809         vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6810
6811         if (enable) vtable->remote = 1;
6812         else vtable->remote = 0;
6813 }
6814
6815 static MonoObject *
6816 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6817 {
6818         MonoClass *klass;
6819         MonoDomain *domain;
6820         
6821         MONO_ARCH_SAVE_REGS;
6822
6823         domain = mono_object_domain (type);
6824         klass = mono_class_from_mono_type (type->type);
6825         mono_class_init_or_throw (klass);
6826
6827         if (klass->rank >= 1) {
6828                 g_assert (klass->rank == 1);
6829                 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6830         } else {
6831                 /* Bypass remoting object creation check */
6832                 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6833         }
6834 }
6835
6836 static MonoString *
6837 ves_icall_System_IO_get_temp_path (void)
6838 {
6839         MONO_ARCH_SAVE_REGS;
6840
6841         return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6842 }
6843
6844 #ifndef PLATFORM_NO_DRIVEINFO
6845 static MonoBoolean
6846 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6847                                                 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6848                                                 gint32 *error)
6849 {
6850         gboolean result;
6851         ULARGE_INTEGER wapi_free_bytes_avail;
6852         ULARGE_INTEGER wapi_total_number_of_bytes;
6853         ULARGE_INTEGER wapi_total_number_of_free_bytes;
6854
6855         MONO_ARCH_SAVE_REGS;
6856
6857         *error = ERROR_SUCCESS;
6858         result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6859                                      &wapi_total_number_of_free_bytes);
6860
6861         if (result) {
6862                 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6863                 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6864                 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6865         } else {
6866                 *free_bytes_avail = 0;
6867                 *total_number_of_bytes = 0;
6868                 *total_number_of_free_bytes = 0;
6869                 *error = GetLastError ();
6870         }
6871
6872         return result;
6873 }
6874
6875 static guint32
6876 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6877 {
6878         MONO_ARCH_SAVE_REGS;
6879
6880         return GetDriveType (mono_string_chars (root_path_name));
6881 }
6882 #endif
6883
6884 static gpointer
6885 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6886 {
6887         MONO_ARCH_SAVE_REGS;
6888
6889         return mono_compile_method (method);
6890 }
6891
6892 static MonoString *
6893 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6894 {
6895         MonoString *mcpath;
6896         gchar *path;
6897
6898         MONO_ARCH_SAVE_REGS;
6899
6900         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6901
6902 #if defined (HOST_WIN32)
6903         /* Avoid mixing '/' and '\\' */
6904         {
6905                 gint i;
6906                 for (i = strlen (path) - 1; i >= 0; i--)
6907                         if (path [i] == '/')
6908                                 path [i] = '\\';
6909         }
6910 #endif
6911         mcpath = mono_string_new (mono_domain_get (), path);
6912         g_free (path);
6913
6914         return mcpath;
6915 }
6916
6917 static MonoString *
6918 get_bundled_app_config (void)
6919 {
6920         const gchar *app_config;
6921         MonoDomain *domain;
6922         MonoString *file;
6923         gchar *config_file;
6924         gsize len;
6925         gchar *module;
6926
6927         MONO_ARCH_SAVE_REGS;
6928
6929         domain = mono_domain_get ();
6930         file = domain->setup->configuration_file;
6931         if (!file)
6932                 return NULL;
6933
6934         // Retrieve config file and remove the extension
6935         config_file = mono_string_to_utf8 (file);
6936         len = strlen (config_file) - strlen (".config");
6937         module = g_malloc0 (len + 1);
6938         memcpy (module, config_file, len);
6939         // Get the config file from the module name
6940         app_config = mono_config_string_for_assembly_file (module);
6941         // Clean-up
6942         g_free (module);
6943         g_free (config_file);
6944
6945         if (!app_config)
6946                 return NULL;
6947
6948         return mono_string_new (mono_domain_get (), app_config);
6949 }
6950
6951 static MonoString *
6952 get_bundled_machine_config (void)
6953 {
6954         const gchar *machine_config;
6955
6956         MONO_ARCH_SAVE_REGS;
6957
6958         machine_config = mono_get_machine_config ();
6959
6960         if (!machine_config)
6961                 return NULL;
6962
6963         return mono_string_new (mono_domain_get (), machine_config);
6964 }
6965
6966 static MonoString *
6967 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6968 {
6969         MonoString *ipath;
6970         gchar *path;
6971
6972         MONO_ARCH_SAVE_REGS;
6973
6974         path = g_path_get_dirname (mono_get_config_dir ());
6975
6976 #if defined (HOST_WIN32)
6977         /* Avoid mixing '/' and '\\' */
6978         {
6979                 gint i;
6980                 for (i = strlen (path) - 1; i >= 0; i--)
6981                         if (path [i] == '/')
6982                                 path [i] = '\\';
6983         }
6984 #endif
6985         ipath = mono_string_new (mono_domain_get (), path);
6986         g_free (path);
6987
6988         return ipath;
6989 }
6990
6991 static gboolean
6992 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6993 {
6994         MonoPEResourceDataEntry *entry;
6995         MonoImage *image;
6996
6997         MONO_ARCH_SAVE_REGS;
6998
6999         if (!assembly || !result || !size)
7000                 return FALSE;
7001
7002         *result = NULL;
7003         *size = 0;
7004         image = assembly->assembly->image;
7005         entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7006         if (!entry)
7007                 return FALSE;
7008
7009         *result = mono_image_rva_map (image, entry->rde_data_offset);
7010         if (!(*result)) {
7011                 g_free (entry);
7012                 return FALSE;
7013         }
7014         *size = entry->rde_size;
7015         g_free (entry);
7016         return TRUE;
7017 }
7018
7019 static MonoBoolean
7020 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7021 {
7022         return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
7023 }
7024
7025 static void
7026 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7027 {
7028 #if defined (HOST_WIN32)
7029         OutputDebugString (mono_string_chars (message));
7030 #else
7031         g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7032 #endif
7033 }
7034
7035 /* Only used for value types */
7036 static MonoObject *
7037 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7038 {
7039         MonoClass *klass;
7040         MonoDomain *domain;
7041         
7042         MONO_ARCH_SAVE_REGS;
7043
7044         domain = mono_object_domain (type);
7045         klass = mono_class_from_mono_type (type->type);
7046         mono_class_init_or_throw (klass);
7047
7048         if (mono_class_is_nullable (klass))
7049                 /* No arguments -> null */
7050                 return NULL;
7051
7052         return mono_object_new (domain, klass);
7053 }
7054
7055 static MonoReflectionMethod *
7056 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7057 {
7058         MonoClass *klass, *parent;
7059         MonoMethod *method = m->method;
7060         MonoMethod *result = NULL;
7061
7062         MONO_ARCH_SAVE_REGS;
7063
7064         if (method->klass == NULL)
7065                 return m;
7066
7067         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7068             MONO_CLASS_IS_INTERFACE (method->klass) ||
7069             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7070                 return m;
7071
7072         klass = method->klass;
7073         if (klass->generic_class)
7074                 klass = klass->generic_class->container_class;
7075
7076         if (definition) {
7077                 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7078                 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7079                         mono_class_setup_vtable (parent);
7080                         if (parent->vtable_size <= method->slot)
7081                                 break;
7082                         klass = parent;
7083                 }
7084         } else {
7085                 klass = klass->parent;
7086                 if (!klass)
7087                         return m;
7088         }
7089
7090         if (klass == method->klass)
7091                 return m;
7092
7093         /*This is possible if definition == FALSE.
7094          * Do it here to be really sure we don't read invalid memory.
7095          */
7096         if (method->slot >= klass->vtable_size)
7097                 return m;
7098
7099         mono_class_setup_vtable (klass);
7100
7101         result = klass->vtable [method->slot];
7102         if (result == NULL) {
7103                 /* It is an abstract method */
7104                 gpointer iter = NULL;
7105                 while ((result = mono_class_get_methods (klass, &iter)))
7106                         if (result->slot == method->slot)
7107                                 break;
7108         }
7109
7110         if (result == NULL)
7111                 return m;
7112
7113         return mono_method_get_object (mono_domain_get (), result, NULL);
7114 }
7115
7116 static MonoString*
7117 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7118 {
7119         MonoMethod *method = m->method;
7120
7121         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7122         return m->name;
7123 }
7124
7125 static void
7126 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7127 {
7128         MONO_ARCH_SAVE_REGS;
7129
7130         iter->sig = *(MonoMethodSignature**)argsp;
7131         
7132         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7133         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7134
7135         iter->next_arg = 0;
7136         /* FIXME: it's not documented what start is exactly... */
7137         if (start) {
7138                 iter->args = start;
7139         } else {
7140                 iter->args = argsp + sizeof (gpointer);
7141         }
7142         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7143
7144         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7145 }
7146
7147 static MonoTypedRef
7148 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7149 {
7150         guint32 i, arg_size;
7151         gint32 align;
7152         MonoTypedRef res;
7153         MONO_ARCH_SAVE_REGS;
7154
7155         i = iter->sig->sentinelpos + iter->next_arg;
7156
7157         g_assert (i < iter->sig->param_count);
7158
7159         res.type = iter->sig->params [i];
7160         res.klass = mono_class_from_mono_type (res.type);
7161         res.value = iter->args;
7162         arg_size = mono_type_stack_size (res.type, &align);
7163 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7164         if (arg_size <= sizeof (gpointer)) {
7165                 int dummy;
7166                 int padding = arg_size - mono_type_size (res.type, &dummy);
7167                 res.value = (guint8*)res.value + padding;
7168         }
7169 #endif
7170         iter->args = (char*)iter->args + arg_size;
7171         iter->next_arg++;
7172
7173         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7174
7175         return res;
7176 }
7177
7178 static MonoTypedRef
7179 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7180 {
7181         guint32 i, arg_size;
7182         gint32 align;
7183         MonoTypedRef res;
7184         MONO_ARCH_SAVE_REGS;
7185
7186         i = iter->sig->sentinelpos + iter->next_arg;
7187
7188         g_assert (i < iter->sig->param_count);
7189
7190         while (i < iter->sig->param_count) {
7191                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7192                         continue;
7193                 res.type = iter->sig->params [i];
7194                 res.klass = mono_class_from_mono_type (res.type);
7195                 /* FIXME: endianess issue... */
7196                 res.value = iter->args;
7197                 arg_size = mono_type_stack_size (res.type, &align);
7198                 iter->args = (char*)iter->args + arg_size;
7199                 iter->next_arg++;
7200                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7201                 return res;
7202         }
7203         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7204
7205         res.type = NULL;
7206         res.value = NULL;
7207         res.klass = NULL;
7208         return res;
7209 }
7210
7211 static MonoType*
7212 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7213 {
7214         gint i;
7215         MONO_ARCH_SAVE_REGS;
7216         
7217         i = iter->sig->sentinelpos + iter->next_arg;
7218
7219         g_assert (i < iter->sig->param_count);
7220
7221         return iter->sig->params [i];
7222 }
7223
7224 static MonoObject*
7225 mono_TypedReference_ToObject (MonoTypedRef tref)
7226 {
7227         MONO_ARCH_SAVE_REGS;
7228
7229         if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7230                 MonoObject** objp = tref.value;
7231                 return *objp;
7232         }
7233
7234         return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7235 }
7236
7237 static MonoObject*
7238 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7239 {
7240         MONO_ARCH_SAVE_REGS;
7241
7242         if (MONO_TYPE_IS_REFERENCE (type)) {
7243                 MonoObject** objp = value;
7244                 return *objp;
7245         }
7246
7247         return mono_value_box (mono_domain_get (), klass, value);
7248 }
7249
7250 static void
7251 prelink_method (MonoMethod *method)
7252 {
7253         const char *exc_class, *exc_arg;
7254         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7255                 return;
7256         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7257         if (exc_class) {
7258                 mono_raise_exception( 
7259                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7260         }
7261         /* create the wrapper, too? */
7262 }
7263
7264 static void
7265 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7266 {
7267         MONO_ARCH_SAVE_REGS;
7268         prelink_method (method->method);
7269 }
7270
7271 static void
7272 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7273 {
7274         MonoClass *klass = mono_class_from_mono_type (type->type);
7275         MonoMethod* m;
7276         gpointer iter = NULL;
7277         MONO_ARCH_SAVE_REGS;
7278
7279         mono_class_init_or_throw (klass);
7280
7281         while ((m = mono_class_get_methods (klass, &iter)))
7282                 prelink_method (m);
7283 }
7284
7285 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7286 static void
7287 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7288                                             gint32 const **exponents,
7289                                             gunichar2 const **digitLowerTable,
7290                                             gunichar2 const **digitUpperTable,
7291                                             gint64 const **tenPowersList,
7292                                             gint32 const **decHexDigits)
7293 {
7294         *mantissas = Formatter_MantissaBitsTable;
7295         *exponents = Formatter_TensExponentTable;
7296         *digitLowerTable = Formatter_DigitLowerTable;
7297         *digitUpperTable = Formatter_DigitUpperTable;
7298         *tenPowersList = Formatter_TenPowersList;
7299         *decHexDigits = Formatter_DecHexDigits;
7300 }
7301
7302 /* These parameters are "readonly" in corlib/System/Char.cs */
7303 static void
7304 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7305                                             guint8 const **numeric_data,
7306                                             gdouble const **numeric_data_values,
7307                                             guint16 const **to_lower_data_low,
7308                                             guint16 const **to_lower_data_high,
7309                                             guint16 const **to_upper_data_low,
7310                                             guint16 const **to_upper_data_high)
7311 {
7312         *category_data = CategoryData;
7313         *numeric_data = NumericData;
7314         *numeric_data_values = NumericDataValues;
7315         *to_lower_data_low = ToLowerDataLow;
7316         *to_lower_data_high = ToLowerDataHigh;
7317         *to_upper_data_low = ToUpperDataLow;
7318         *to_upper_data_high = ToUpperDataHigh;
7319 }
7320
7321 static gint32
7322 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7323 {
7324         return method->method->token;
7325 }
7326
7327 /*
7328  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7329  * and avoid useless allocations.
7330  */
7331 static MonoArray*
7332 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7333 {
7334         MonoArray *res;
7335         int i, count = 0;
7336         for (i = 0; i < type->num_mods; ++i) {
7337                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7338                         count++;
7339         }
7340         if (!count)
7341                 return NULL;
7342         res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7343         count = 0;
7344         for (i = 0; i < type->num_mods; ++i) {
7345                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7346                         MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7347                         mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7348                         count++;
7349                 }
7350         }
7351         return res;
7352 }
7353
7354 static MonoArray*
7355 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7356 {
7357         MonoType *type = param->ClassImpl->type;
7358         MonoClass *member_class = mono_object_class (param->MemberImpl);
7359         MonoMethod *method = NULL;
7360         MonoImage *image;
7361         int pos;
7362         MonoMethodSignature *sig;
7363
7364         if (mono_class_is_reflection_method_or_constructor (member_class)) {
7365                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7366                 method = rmethod->method;
7367         } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7368                 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7369                 if (!(method = prop->property->get))
7370                         method = prop->property->set;
7371                 g_assert (method);      
7372         } else {
7373                 char *type_name = mono_type_get_full_name (member_class);
7374                 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7375                 MonoException *ex = mono_get_exception_not_supported  (msg);
7376                 g_free (type_name);
7377                 g_free (msg);
7378                 mono_raise_exception (ex);
7379         }
7380
7381         image = method->klass->image;
7382         pos = param->PositionImpl;
7383         sig = mono_method_signature (method);
7384         if (pos == -1)
7385                 type = sig->ret;
7386         else
7387                 type = sig->params [pos];
7388
7389         return type_array_from_modifiers (image, type, optional);
7390 }
7391
7392 static MonoType*
7393 get_property_type (MonoProperty *prop)
7394 {
7395         MonoMethodSignature *sig;
7396         if (prop->get) {
7397                 sig = mono_method_signature (prop->get);
7398                 return sig->ret;
7399         } else if (prop->set) {
7400                 sig = mono_method_signature (prop->set);
7401                 return sig->params [sig->param_count - 1];
7402         }
7403         return NULL;
7404 }
7405
7406 static MonoArray*
7407 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7408 {
7409         MonoType *type = get_property_type (property->property);
7410         MonoImage *image = property->klass->image;
7411
7412         if (!type)
7413                 return NULL;
7414         return type_array_from_modifiers (image, type, optional);
7415 }
7416
7417 /*
7418  *Construct a MonoType suited to be used to decode a constant blob object.
7419  *
7420  * @type is the target type which will be constructed
7421  * @blob_type is the blob type, for example, that comes from the constant table
7422  * @real_type is the expected constructed type.
7423  */
7424 static void
7425 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7426 {
7427         type->type = blob_type;
7428         type->data.klass = NULL;
7429         if (blob_type == MONO_TYPE_CLASS)
7430                 type->data.klass = mono_defaults.object_class;
7431         else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7432                 /* For enums, we need to use the base type */
7433                 type->type = MONO_TYPE_VALUETYPE;
7434                 type->data.klass = mono_class_from_mono_type (real_type);
7435         } else
7436                 type->data.klass = mono_class_from_mono_type (real_type);
7437 }
7438
7439 static MonoObject*
7440 property_info_get_default_value (MonoReflectionProperty *property)
7441 {
7442         MonoType blob_type;
7443         MonoProperty *prop = property->property;
7444         MonoType *type = get_property_type (prop);
7445         MonoDomain *domain = mono_object_domain (property); 
7446         MonoTypeEnum def_type;
7447         const char *def_value;
7448         MonoObject *o;
7449
7450         mono_class_init (prop->parent);
7451
7452         if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7453                 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7454
7455         def_value = mono_class_get_property_default_value (prop, &def_type);
7456
7457         mono_type_from_blob_type (&blob_type, def_type, type);
7458         o = mono_get_object_from_blob (domain, &blob_type, def_value);
7459
7460         return o;
7461 }
7462
7463 static MonoBoolean
7464 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7465 {
7466         MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7467         MonoCustomAttrInfo *cinfo;
7468         gboolean found;
7469
7470         mono_class_init_or_throw (attr_class);
7471
7472         cinfo = mono_reflection_get_custom_attrs_info (obj);
7473         if (!cinfo)
7474                 return FALSE;
7475         found = mono_custom_attrs_has_attr (cinfo, attr_class);
7476         if (!cinfo->cached)
7477                 mono_custom_attrs_free (cinfo);
7478         return found;
7479 }
7480
7481 static MonoArray*
7482 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7483 {
7484         MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7485         MonoArray *res;
7486         MonoError error;
7487
7488         if (attr_class)
7489                 mono_class_init_or_throw (attr_class);
7490
7491         res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7492         if (!mono_error_ok (&error))
7493                 mono_error_raise_exception (&error);
7494         if (mono_loader_get_last_error ()) {
7495                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7496                 g_assert_not_reached ();
7497                 /* Not reached */
7498                 return NULL;
7499         } else {
7500                 return res;
7501         }
7502 }
7503
7504 static MonoString*
7505 ves_icall_Mono_Runtime_GetDisplayName (void)
7506 {
7507         char *info;
7508         MonoString *display_name;
7509
7510         info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7511         display_name = mono_string_new (mono_domain_get (), info);
7512         g_free (info);
7513         return display_name;
7514 }
7515
7516 static MonoString*
7517 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7518 {
7519         MonoString *message;
7520         guint32 ret;
7521         gunichar2 buf[256];
7522         
7523         ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7524                              FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7525                              buf, 255, NULL);
7526         if (ret == 0) {
7527                 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7528         } else {
7529                 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7530         }
7531         
7532         return message;
7533 }
7534
7535 const static guchar
7536 dbase64 [] = {
7537         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7538         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7539         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7540         52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7541         128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7542         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7543         128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7544         41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7545 };
7546
7547 static MonoArray *
7548 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7549 {
7550         gint ignored;
7551         gint i;
7552         gunichar2 c;
7553         gunichar2 last, prev_last, prev2_last;
7554         gint olength;
7555         MonoArray *result;
7556         guchar *res_ptr;
7557         gint a [4], b [4];
7558         MonoException *exc;
7559
7560         ignored = 0;
7561         last = prev_last = 0, prev2_last = 0;
7562         for (i = 0; i < ilength; i++) {
7563                 c = start [i];
7564                 if (c >= sizeof (dbase64)) {
7565                         exc = mono_exception_from_name_msg (mono_get_corlib (),
7566                                 "System", "FormatException",
7567                                 "Invalid character found.");
7568                         mono_raise_exception (exc);
7569                 } else if (isspace (c)) {
7570                         ignored++;
7571                 } else {
7572                         prev2_last = prev_last;
7573                         prev_last = last;
7574                         last = c;
7575                 }
7576         }
7577
7578         olength = ilength - ignored;
7579
7580         if (allowWhitespaceOnly && olength == 0) {
7581                 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7582         }
7583
7584         if ((olength & 3) != 0 || olength <= 0) {
7585                 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7586                                         "FormatException", "Invalid length.");
7587                 mono_raise_exception (exc);
7588         }
7589
7590         if (prev2_last == '=') {
7591                 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7592                 mono_raise_exception (exc);
7593         }
7594
7595         olength = (olength * 3) / 4;
7596         if (last == '=')
7597                 olength--;
7598
7599         if (prev_last == '=')
7600                 olength--;
7601
7602         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7603         res_ptr = mono_array_addr (result, guchar, 0);
7604         for (i = 0; i < ilength; ) {
7605                 int k;
7606
7607                 for (k = 0; k < 4 && i < ilength;) {
7608                         c = start [i++];
7609                         if (isspace (c))
7610                                 continue;
7611
7612                         a [k] = (guchar) c;
7613                         if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7614                                 exc = mono_exception_from_name_msg (mono_get_corlib (),
7615                                         "System", "FormatException",
7616                                         "Invalid character found.");
7617                                 mono_raise_exception (exc);
7618                         }
7619                         k++;
7620                 }
7621
7622                 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7623                 if (a [2] != '=')
7624                         *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7625                 if (a [3] != '=')
7626                         *res_ptr++ = (b [2] << 6) | b [3];
7627
7628                 while (i < ilength && isspace (start [i]))
7629                         i++;
7630         }
7631
7632         return result;
7633 }
7634
7635 static MonoArray *
7636 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7637 {
7638         MONO_ARCH_SAVE_REGS;
7639
7640         return base64_to_byte_array (mono_string_chars (str), 
7641                 mono_string_length (str), allowWhitespaceOnly);
7642 }
7643
7644 static MonoArray *
7645 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7646 {
7647         MONO_ARCH_SAVE_REGS;
7648
7649         return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7650                 length, FALSE);
7651 }
7652
7653 #define ICALL_TYPE(id,name,first)
7654 #define ICALL(id,name,func) Icall_ ## id,
7655
7656 enum {
7657 #include "metadata/icall-def.h"
7658         Icall_last
7659 };
7660
7661 #undef ICALL_TYPE
7662 #undef ICALL
7663 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7664 #define ICALL(id,name,func)
7665 enum {
7666 #include "metadata/icall-def.h"
7667         Icall_type_num
7668 };
7669
7670 #undef ICALL_TYPE
7671 #undef ICALL
7672 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7673 #define ICALL(id,name,func)
7674 typedef struct {
7675         guint16 first_icall;
7676 } IcallTypeDesc;
7677
7678 static const IcallTypeDesc
7679 icall_type_descs [] = {
7680 #include "metadata/icall-def.h"
7681         {Icall_last}
7682 };
7683
7684 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7685
7686 #undef ICALL_TYPE
7687 #define ICALL_TYPE(id,name,first)
7688 #undef ICALL
7689
7690 #ifdef HAVE_ARRAY_ELEM_INIT
7691 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7692 #define MSGSTRFIELD1(line) str##line
7693
7694 static const struct msgstrtn_t {
7695 #define ICALL(id,name,func)
7696 #undef ICALL_TYPE
7697 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7698 #include "metadata/icall-def.h"
7699 #undef ICALL_TYPE
7700 } icall_type_names_str = {
7701 #define ICALL_TYPE(id,name,first) (name),
7702 #include "metadata/icall-def.h"
7703 #undef ICALL_TYPE
7704 };
7705 static const guint16 icall_type_names_idx [] = {
7706 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7707 #include "metadata/icall-def.h"
7708 #undef ICALL_TYPE
7709 };
7710 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7711
7712 static const struct msgstr_t {
7713 #undef ICALL
7714 #define ICALL_TYPE(id,name,first)
7715 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7716 #include "metadata/icall-def.h"
7717 #undef ICALL
7718 } icall_names_str = {
7719 #define ICALL(id,name,func) (name),
7720 #include "metadata/icall-def.h"
7721 #undef ICALL
7722 };
7723 static const guint16 icall_names_idx [] = {
7724 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7725 #include "metadata/icall-def.h"
7726 #undef ICALL
7727 };
7728 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7729
7730 #else
7731
7732 #undef ICALL_TYPE
7733 #undef ICALL
7734 #define ICALL_TYPE(id,name,first) name,
7735 #define ICALL(id,name,func)
7736 static const char* const
7737 icall_type_names [] = {
7738 #include "metadata/icall-def.h"
7739         NULL
7740 };
7741
7742 #define icall_type_name_get(id) (icall_type_names [(id)])
7743
7744 #undef ICALL_TYPE
7745 #undef ICALL
7746 #define ICALL_TYPE(id,name,first)
7747 #define ICALL(id,name,func) name,
7748 static const char* const
7749 icall_names [] = {
7750 #include "metadata/icall-def.h"
7751         NULL
7752 };
7753 #define icall_name_get(id) icall_names [(id)]
7754
7755 #endif /* !HAVE_ARRAY_ELEM_INIT */
7756
7757 #undef ICALL_TYPE
7758 #undef ICALL
7759 #define ICALL_TYPE(id,name,first)
7760 #define ICALL(id,name,func) func,
7761 static const gconstpointer
7762 icall_functions [] = {
7763 #include "metadata/icall-def.h"
7764         NULL
7765 };
7766
7767 static GHashTable *icall_hash = NULL;
7768 static GHashTable *jit_icall_hash_name = NULL;
7769 static GHashTable *jit_icall_hash_addr = NULL;
7770
7771 void
7772 mono_icall_init (void)
7773 {
7774         int i = 0;
7775
7776         /* check that tables are sorted: disable in release */
7777         if (TRUE) {
7778                 int j;
7779                 const char *prev_class = NULL;
7780                 const char *prev_method;
7781                 
7782                 for (i = 0; i < Icall_type_num; ++i) {
7783                         const IcallTypeDesc *desc;
7784                         int num_icalls;
7785                         prev_method = NULL;
7786                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7787                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7788                         prev_class = icall_type_name_get (i);
7789                         desc = &icall_type_descs [i];
7790                         num_icalls = icall_desc_num_icalls (desc);
7791                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7792                         for (j = 0; j < num_icalls; ++j) {
7793                                 const char *methodn = icall_name_get (desc->first_icall + j);
7794                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
7795                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
7796                                 prev_method = methodn;
7797                         }
7798                 }
7799         }
7800
7801         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7802 }
7803
7804 void
7805 mono_icall_cleanup (void)
7806 {
7807         g_hash_table_destroy (icall_hash);
7808         g_hash_table_destroy (jit_icall_hash_name);
7809         g_hash_table_destroy (jit_icall_hash_addr);
7810 }
7811
7812 void
7813 mono_add_internal_call (const char *name, gconstpointer method)
7814 {
7815         mono_loader_lock ();
7816
7817         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7818
7819         mono_loader_unlock ();
7820 }
7821
7822 #ifdef HAVE_ARRAY_ELEM_INIT
7823 static int
7824 compare_method_imap (const void *key, const void *elem)
7825 {
7826         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7827         return strcmp (key, method_name);
7828 }
7829
7830 static gpointer
7831 find_method_icall (const IcallTypeDesc *imap, const char *name)
7832 {
7833         const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7834         if (!nameslot)
7835                 return NULL;
7836         return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7837 }
7838
7839 static int
7840 compare_class_imap (const void *key, const void *elem)
7841 {
7842         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7843         return strcmp (key, class_name);
7844 }
7845
7846 static const IcallTypeDesc*
7847 find_class_icalls (const char *name)
7848 {
7849         const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7850         if (!nameslot)
7851                 return NULL;
7852         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7853 }
7854
7855 #else
7856 static int
7857 compare_method_imap (const void *key, const void *elem)
7858 {
7859         const char** method_name = (const char**)elem;
7860         return strcmp (key, *method_name);
7861 }
7862
7863 static gpointer
7864 find_method_icall (const IcallTypeDesc *imap, const char *name)
7865 {
7866         const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7867         if (!nameslot)
7868                 return NULL;
7869         return (gpointer)icall_functions [(nameslot - icall_names)];
7870 }
7871
7872 static int
7873 compare_class_imap (const void *key, const void *elem)
7874 {
7875         const char** class_name = (const char**)elem;
7876         return strcmp (key, *class_name);
7877 }
7878
7879 static const IcallTypeDesc*
7880 find_class_icalls (const char *name)
7881 {
7882         const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7883         if (!nameslot)
7884                 return NULL;
7885         return &icall_type_descs [nameslot - icall_type_names];
7886 }
7887
7888 #endif
7889
7890 /* 
7891  * we should probably export this as an helper (handle nested types).
7892  * Returns the number of chars written in buf.
7893  */
7894 static int
7895 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7896 {
7897         int nspacelen, cnamelen;
7898         nspacelen = strlen (klass->name_space);
7899         cnamelen = strlen (klass->name);
7900         if (nspacelen + cnamelen + 2 > bufsize)
7901                 return 0;
7902         if (nspacelen) {
7903                 memcpy (buf, klass->name_space, nspacelen);
7904                 buf [nspacelen ++] = '.';
7905         }
7906         memcpy (buf + nspacelen, klass->name, cnamelen);
7907         buf [nspacelen + cnamelen] = 0;
7908         return nspacelen + cnamelen;
7909 }
7910
7911 gpointer
7912 mono_lookup_internal_call (MonoMethod *method)
7913 {
7914         char *sigstart;
7915         char *tmpsig;
7916         char mname [2048];
7917         int typelen = 0, mlen, siglen;
7918         gpointer res;
7919         const IcallTypeDesc *imap;
7920
7921         g_assert (method != NULL);
7922
7923         if (method->is_inflated)
7924                 method = ((MonoMethodInflated *) method)->declaring;
7925
7926         if (method->klass->nested_in) {
7927                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7928                 if (!pos)
7929                         return NULL;
7930
7931                 mname [pos++] = '/';
7932                 mname [pos] = 0;
7933
7934                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7935                 if (!typelen)
7936                         return NULL;
7937
7938                 typelen += pos;
7939         } else {
7940                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7941                 if (!typelen)
7942                         return NULL;
7943         }
7944
7945         imap = find_class_icalls (mname);
7946
7947         mname [typelen] = ':';
7948         mname [typelen + 1] = ':';
7949
7950         mlen = strlen (method->name);
7951         memcpy (mname + typelen + 2, method->name, mlen);
7952         sigstart = mname + typelen + 2 + mlen;
7953         *sigstart = 0;
7954
7955         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7956         siglen = strlen (tmpsig);
7957         if (typelen + mlen + siglen + 6 > sizeof (mname))
7958                 return NULL;
7959         sigstart [0] = '(';
7960         memcpy (sigstart + 1, tmpsig, siglen);
7961         sigstart [siglen + 1] = ')';
7962         sigstart [siglen + 2] = 0;
7963         g_free (tmpsig);
7964         
7965         mono_loader_lock ();
7966
7967         res = g_hash_table_lookup (icall_hash, mname);
7968         if (res) {
7969                 mono_loader_unlock ();
7970                 return res;
7971         }
7972         /* try without signature */
7973         *sigstart = 0;
7974         res = g_hash_table_lookup (icall_hash, mname);
7975         if (res) {
7976                 mono_loader_unlock ();
7977                 return res;
7978         }
7979
7980         /* it wasn't found in the static call tables */
7981         if (!imap) {
7982                 mono_loader_unlock ();
7983                 return NULL;
7984         }
7985         res = find_method_icall (imap, sigstart - mlen);
7986         if (res) {
7987                 mono_loader_unlock ();
7988                 return res;
7989         }
7990         /* try _with_ signature */
7991         *sigstart = '(';
7992         res = find_method_icall (imap, sigstart - mlen);
7993         if (res) {
7994                 mono_loader_unlock ();
7995                 return res;
7996         }
7997
7998         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7999         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8000         g_print ("The out of sync library is: %s\n", method->klass->image->name);
8001         g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8002         g_print ("Do not report this as a bug unless you're sure you have updated correctly:\nyou probably have a broken mono install.\n");
8003         g_print ("If you see other errors or faults after this message they are probably related\n");
8004         g_print ("and you need to fix your mono install first.\n");
8005
8006         mono_loader_unlock ();
8007
8008         return NULL;
8009 }
8010
8011 static MonoType*
8012 type_from_typename (char *typename)
8013 {
8014         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
8015
8016         if (!strcmp (typename, "int"))
8017                 klass = mono_defaults.int_class;
8018         else if (!strcmp (typename, "ptr"))
8019                 klass = mono_defaults.int_class;
8020         else if (!strcmp (typename, "void"))
8021                 klass = mono_defaults.void_class;
8022         else if (!strcmp (typename, "int32"))
8023                 klass = mono_defaults.int32_class;
8024         else if (!strcmp (typename, "uint32"))
8025                 klass = mono_defaults.uint32_class;
8026         else if (!strcmp (typename, "int8"))
8027                 klass = mono_defaults.sbyte_class;
8028         else if (!strcmp (typename, "uint8"))
8029                 klass = mono_defaults.byte_class;
8030         else if (!strcmp (typename, "int16"))
8031                 klass = mono_defaults.int16_class;
8032         else if (!strcmp (typename, "uint16"))
8033                 klass = mono_defaults.uint16_class;
8034         else if (!strcmp (typename, "long"))
8035                 klass = mono_defaults.int64_class;
8036         else if (!strcmp (typename, "ulong"))
8037                 klass = mono_defaults.uint64_class;
8038         else if (!strcmp (typename, "float"))
8039                 klass = mono_defaults.single_class;
8040         else if (!strcmp (typename, "double"))
8041                 klass = mono_defaults.double_class;
8042         else if (!strcmp (typename, "object"))
8043                 klass = mono_defaults.object_class;
8044         else if (!strcmp (typename, "obj"))
8045                 klass = mono_defaults.object_class;
8046         else if (!strcmp (typename, "string"))
8047                 klass = mono_defaults.string_class;
8048         else if (!strcmp (typename, "bool"))
8049                 klass = mono_defaults.boolean_class;
8050         else if (!strcmp (typename, "boolean"))
8051                 klass = mono_defaults.boolean_class;
8052         else {
8053                 g_error ("%s", typename);
8054                 g_assert_not_reached ();
8055         }
8056         return &klass->byval_arg;
8057 }
8058
8059 MonoMethodSignature*
8060 mono_create_icall_signature (const char *sigstr)
8061 {
8062         gchar **parts;
8063         int i, len;
8064         gchar **tmp;
8065         MonoMethodSignature *res;
8066
8067         mono_loader_lock ();
8068         res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8069         if (res) {
8070                 mono_loader_unlock ();
8071                 return res;
8072         }
8073
8074         parts = g_strsplit (sigstr, " ", 256);
8075
8076         tmp = parts;
8077         len = 0;
8078         while (*tmp) {
8079                 len ++;
8080                 tmp ++;
8081         }
8082
8083         res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8084         res->pinvoke = 1;
8085
8086 #ifdef HOST_WIN32
8087         /* 
8088          * Under windows, the default pinvoke calling convention is STDCALL but
8089          * we need CDECL.
8090          */
8091         res->call_convention = MONO_CALL_C;
8092 #endif
8093
8094         res->ret = type_from_typename (parts [0]);
8095         for (i = 1; i < len; ++i) {
8096                 res->params [i - 1] = type_from_typename (parts [i]);
8097         }
8098
8099         g_strfreev (parts);
8100
8101         g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8102
8103         mono_loader_unlock ();
8104
8105         return res;
8106 }
8107
8108 MonoJitICallInfo *
8109 mono_find_jit_icall_by_name (const char *name)
8110 {
8111         MonoJitICallInfo *info;
8112         g_assert (jit_icall_hash_name);
8113
8114         mono_loader_lock ();
8115         info = g_hash_table_lookup (jit_icall_hash_name, name);
8116         mono_loader_unlock ();
8117         return info;
8118 }
8119
8120 MonoJitICallInfo *
8121 mono_find_jit_icall_by_addr (gconstpointer addr)
8122 {
8123         MonoJitICallInfo *info;
8124         g_assert (jit_icall_hash_addr);
8125
8126         mono_loader_lock ();
8127         info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8128         mono_loader_unlock ();
8129
8130         return info;
8131 }
8132
8133 /*
8134  * mono_get_jit_icall_info:
8135  *
8136  *   Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8137  * caller should access it while holding the loader lock.
8138  */
8139 GHashTable*
8140 mono_get_jit_icall_info (void)
8141 {
8142         return jit_icall_hash_name;
8143 }
8144
8145 void
8146 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8147 {
8148         mono_loader_lock ();
8149         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8150         mono_loader_unlock ();
8151 }
8152
8153 MonoJitICallInfo *
8154 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8155 {
8156         MonoJitICallInfo *info;
8157         
8158         g_assert (func);
8159         g_assert (name);
8160
8161         mono_loader_lock ();
8162
8163         if (!jit_icall_hash_name) {
8164                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8165                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8166         }
8167
8168         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8169                 g_warning ("jit icall already defined \"%s\"\n", name);
8170                 g_assert_not_reached ();
8171         }
8172
8173         info = g_new0 (MonoJitICallInfo, 1);
8174         
8175         info->name = name;
8176         info->func = func;
8177         info->sig = sig;
8178
8179         if (is_save) {
8180                 info->wrapper = func;
8181         } else {
8182                 info->wrapper = NULL;
8183         }
8184
8185         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8186         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8187
8188         mono_loader_unlock ();
8189         return info;
8190 }