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