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