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