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