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