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