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