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