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