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