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