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