2010-05-10 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / metadata / icall.c
1 /*
2  * icall.c:
3  *
4  * Authors:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *   Paolo Molaro (lupus@ximian.com)
7  *       Patrik Torstensson (patrik.torstensson@labs2.com)
8  *
9  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11  */
12
13 #include <config.h>
14 #include <glib.h>
15 #include <stdarg.h>
16 #include <string.h>
17 #include <ctype.h>
18 #ifdef HAVE_ALLOCA_H
19 #include <alloca.h>
20 #endif
21 #ifdef HAVE_SYS_TIME_H
22 #include <sys/time.h>
23 #endif
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #if defined (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 MonoArray*
2057 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2058 {
2059         MonoError error;
2060         MonoDomain *domain = mono_object_domain (type); 
2061         MonoArray *intf;
2062         GPtrArray *ifaces = NULL;
2063         int i;
2064         MonoClass *class = mono_class_from_mono_type (type->type);
2065         MonoClass *parent;
2066         MonoBitSet *slots;
2067         MonoGenericContext *context = NULL;
2068
2069         mono_class_init_or_throw (class);
2070
2071         if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2072                 context = mono_class_get_context (class);
2073                 class = class->generic_class->container_class;
2074         }
2075
2076         mono_class_setup_vtable (class);
2077
2078         slots = mono_bitset_new (class->max_interface_id + 1, 0);
2079
2080         for (parent = class; parent; parent = parent->parent) {
2081                 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent, &error);
2082                 if (!mono_error_ok (&error)) {
2083                         mono_bitset_free (slots);
2084                         mono_error_raise_exception (&error);
2085                         return NULL;
2086                 } else if (tmp_ifaces) {
2087                         for (i = 0; i < tmp_ifaces->len; ++i) {
2088                                 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
2089
2090                                 if (mono_bitset_test (slots, ic->interface_id))
2091                                         continue;
2092
2093                                 mono_bitset_set (slots, ic->interface_id);
2094                                 if (ifaces == NULL)
2095                                         ifaces = g_ptr_array_new ();
2096                                 g_ptr_array_add (ifaces, ic);
2097                         }
2098                         g_ptr_array_free (tmp_ifaces, TRUE);
2099                 }
2100         }
2101         mono_bitset_free (slots);
2102
2103         if (!ifaces)
2104                 return mono_array_new_cached (domain, mono_defaults.monotype_class, 0);
2105                 
2106         intf = mono_array_new_cached (domain, mono_defaults.monotype_class, ifaces->len);
2107         for (i = 0; i < ifaces->len; ++i) {
2108                 MonoClass *ic = g_ptr_array_index (ifaces, i);
2109                 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2110                 if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open)
2111                         inflated = ret = mono_class_inflate_generic_type (ret, context);
2112                 
2113                 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
2114                 if (inflated)
2115                         mono_metadata_free_type (inflated);
2116         }
2117         g_ptr_array_free (ifaces, TRUE);
2118
2119         return intf;
2120 }
2121
2122 static void
2123 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2124 {
2125         gboolean variance_used;
2126         MonoClass *class = mono_class_from_mono_type (type->type);
2127         MonoClass *iclass = mono_class_from_mono_type (iface->type);
2128         MonoReflectionMethod *member;
2129         MonoMethod* method;
2130         gpointer iter;
2131         int i = 0, len, ioffset;
2132         MonoDomain *domain;
2133
2134         MONO_ARCH_SAVE_REGS;
2135         mono_class_init_or_throw (class);
2136         mono_class_init_or_throw (iclass);
2137
2138         mono_class_setup_vtable (class);
2139
2140         ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2141         if (ioffset == -1)
2142                 return;
2143
2144         len = mono_class_num_methods (iclass);
2145         domain = mono_object_domain (type);
2146         mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2147         mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2148         iter = NULL;
2149         while ((method = mono_class_get_methods (iclass, &iter))) {
2150                 member = mono_method_get_object (domain, method, iclass);
2151                 mono_array_setref (*methods, i, member);
2152                 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2153                 mono_array_setref (*targets, i, member);
2154                 
2155                 i ++;
2156         }
2157 }
2158
2159 static void
2160 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2161 {
2162         MonoClass *klass = mono_class_from_mono_type (type->type);
2163         mono_class_init_or_throw (klass);
2164
2165         if (klass->image->dynamic) {
2166                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2167                 *packing = tb->packing_size;
2168                 *size = tb->class_size;
2169         } else {
2170                 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2171         }
2172 }
2173
2174 static MonoReflectionType*
2175 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2176 {
2177         MonoClass *class;
2178
2179         MONO_ARCH_SAVE_REGS;
2180
2181         if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2182                 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2183
2184         class = mono_class_from_mono_type (type->type);
2185         mono_class_init_or_throw (class);
2186
2187         // GetElementType should only return a type for:
2188         // Array Pointer PassedByRef
2189         if (type->type->byref)
2190                 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2191         else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2192                 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2193         else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2194                 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2195         else
2196                 return NULL;
2197 }
2198
2199 static MonoReflectionType*
2200 ves_icall_get_type_parent (MonoReflectionType *type)
2201 {
2202         MonoClass *class = mono_class_from_mono_type (type->type);
2203         return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2204 }
2205
2206 static MonoBoolean
2207 ves_icall_type_ispointer (MonoReflectionType *type)
2208 {
2209         MONO_ARCH_SAVE_REGS;
2210
2211         return type->type->type == MONO_TYPE_PTR;
2212 }
2213
2214 static MonoBoolean
2215 ves_icall_type_isprimitive (MonoReflectionType *type)
2216 {
2217         MONO_ARCH_SAVE_REGS;
2218
2219         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)));
2220 }
2221
2222 static MonoBoolean
2223 ves_icall_type_isbyref (MonoReflectionType *type)
2224 {
2225         MONO_ARCH_SAVE_REGS;
2226
2227         return type->type->byref;
2228 }
2229
2230 static MonoBoolean
2231 ves_icall_type_iscomobject (MonoReflectionType *type)
2232 {
2233         MonoClass *klass = mono_class_from_mono_type (type->type);
2234         mono_class_init_or_throw (klass);
2235
2236         return (klass && klass->is_com_object);
2237 }
2238
2239 static MonoReflectionModule*
2240 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2241 {
2242         MonoClass *class = mono_class_from_mono_type (type->type);
2243         mono_class_init_or_throw (class);
2244
2245         return mono_module_get_object (mono_object_domain (type), class->image);
2246 }
2247
2248 static MonoReflectionAssembly*
2249 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2250 {
2251         MonoDomain *domain = mono_domain_get (); 
2252         MonoClass *class = mono_class_from_mono_type (type->type);
2253
2254         mono_class_init_or_throw (class);
2255
2256         return mono_assembly_get_object (domain, class->image->assembly);
2257 }
2258
2259 static MonoReflectionType*
2260 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2261 {
2262         MonoDomain *domain = mono_domain_get ();
2263         MonoClass *class;
2264
2265         MONO_ARCH_SAVE_REGS;
2266
2267         if (type->type->byref)
2268                 return NULL;
2269         if (type->type->type == MONO_TYPE_VAR)
2270                 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2271         else if (type->type->type == MONO_TYPE_MVAR)
2272                 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2273         else
2274                 class = mono_class_from_mono_type (type->type)->nested_in;
2275
2276         return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2277 }
2278
2279 static MonoString*
2280 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2281 {
2282         MonoDomain *domain = mono_domain_get (); 
2283         MonoClass *class = mono_class_from_mono_type (type->type);
2284
2285         if (type->type->byref) {
2286                 char *n = g_strdup_printf ("%s&", class->name);
2287                 MonoString *res = mono_string_new (domain, n);
2288
2289                 g_free (n);
2290
2291                 return res;
2292         } else {
2293                 return mono_string_new (domain, class->name);
2294         }
2295 }
2296
2297 static MonoString*
2298 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2299 {
2300         MonoDomain *domain = mono_domain_get (); 
2301         MonoClass *class = mono_class_from_mono_type (type->type);
2302
2303         while (class->nested_in)
2304                 class = class->nested_in;
2305
2306         if (class->name_space [0] == '\0')
2307                 return NULL;
2308         else
2309                 return mono_string_new (domain, class->name_space);
2310 }
2311
2312 static gint32
2313 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2314 {
2315         MonoClass *class;
2316
2317         if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2318                 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2319
2320         class = mono_class_from_mono_type (type->type);
2321         mono_class_init_or_throw (class);
2322
2323         return class->rank;
2324 }
2325
2326 static MonoArray*
2327 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2328 {
2329         MonoArray *res;
2330         MonoClass *klass, *pklass;
2331         MonoDomain *domain = mono_object_domain (type);
2332         MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2333         int i;
2334         MONO_ARCH_SAVE_REGS;
2335
2336         klass = mono_class_from_mono_type (type->type);
2337         mono_class_init_or_throw (klass);
2338
2339         if (klass->generic_container) {
2340                 MonoGenericContainer *container = klass->generic_container;
2341                 res = mono_array_new_specific (array_vtable, container->type_argc);
2342                 for (i = 0; i < container->type_argc; ++i) {
2343                         pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2344                         mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2345                 }
2346         } else if (klass->generic_class) {
2347                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2348                 res = mono_array_new_specific (array_vtable, inst->type_argc);
2349                 for (i = 0; i < inst->type_argc; ++i)
2350                         mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2351         } else {
2352                 res = mono_array_new_specific (array_vtable, 0);
2353         }
2354         return res;
2355 }
2356
2357 static gboolean
2358 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2359 {
2360         MonoClass *klass;
2361         MONO_ARCH_SAVE_REGS;
2362
2363         if (!IS_MONOTYPE (type))
2364                 return FALSE;
2365
2366         if (type->type->byref)
2367                 return FALSE;
2368
2369         klass = mono_class_from_mono_type (type->type);
2370         return klass->generic_container != NULL;
2371 }
2372
2373 static MonoReflectionType*
2374 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2375 {
2376         MonoClass *klass;
2377         MONO_ARCH_SAVE_REGS;
2378
2379         if (type->type->byref)
2380                 return NULL;
2381
2382         klass = mono_class_from_mono_type (type->type);
2383         mono_class_init_or_throw (klass);
2384
2385         if (klass->generic_container) {
2386                 return type; /* check this one */
2387         }
2388         if (klass->generic_class) {
2389                 MonoClass *generic_class = klass->generic_class->container_class;
2390                 gpointer tb;
2391
2392                 tb = mono_class_get_ref_info (generic_class);
2393
2394                 if (generic_class->wastypebuilder && tb)
2395                         return tb;
2396                 else
2397                         return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2398         }
2399         return NULL;
2400 }
2401
2402 static MonoReflectionType*
2403 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2404 {
2405         MonoType *geninst, **types;
2406         int i, count;
2407
2408         g_assert (IS_MONOTYPE (type));
2409         mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2410
2411         count = mono_array_length (type_array);
2412         types = g_new0 (MonoType *, count);
2413
2414         for (i = 0; i < count; i++) {
2415                 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2416                 types [i] = t->type;
2417         }
2418
2419         geninst = mono_reflection_bind_generic_parameters (type, count, types);
2420         g_free (types);
2421         if (!geninst)
2422                 return NULL;
2423
2424         return mono_type_get_object (mono_object_domain (type), geninst);
2425 }
2426
2427 static gboolean
2428 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2429 {
2430         MonoClass *klass;
2431         MONO_ARCH_SAVE_REGS;
2432
2433         if (type->type->byref)
2434                 return FALSE;
2435
2436         klass = mono_class_from_mono_type (type->type);
2437
2438         return klass->generic_class != NULL;
2439 }
2440
2441 static gboolean
2442 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2443 {
2444         MonoClass *klass;
2445         MONO_ARCH_SAVE_REGS;
2446
2447         if (!IS_MONOTYPE (type))
2448                 return FALSE;
2449
2450         if (type->type->byref)
2451                 return FALSE;
2452
2453         klass = mono_class_from_mono_type (type->type);
2454         return klass->generic_class != NULL || klass->generic_container != NULL;
2455 }
2456
2457 static gint32
2458 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2459 {
2460         MONO_ARCH_SAVE_REGS;
2461
2462         if (!IS_MONOTYPE (type))
2463                 return -1;
2464
2465         if (is_generic_parameter (type->type))
2466                 return mono_type_get_generic_param_num (type->type);
2467         return -1;
2468 }
2469
2470 static GenericParameterAttributes
2471 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2472 {
2473         MONO_ARCH_SAVE_REGS;
2474
2475         g_assert (IS_MONOTYPE (type));
2476         g_assert (is_generic_parameter (type->type));
2477         return mono_generic_param_info (type->type->data.generic_param)->flags;
2478 }
2479
2480 static MonoArray *
2481 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2482 {
2483         MonoGenericParamInfo *param_info;
2484         MonoDomain *domain;
2485         MonoClass **ptr;
2486         MonoArray *res;
2487         int i, count;
2488
2489         MONO_ARCH_SAVE_REGS;
2490
2491         g_assert (IS_MONOTYPE (type));
2492
2493         domain = mono_object_domain (type);
2494         param_info = mono_generic_param_info (type->type->data.generic_param);
2495         for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2496                 ;
2497
2498         res = mono_array_new (domain, mono_defaults.monotype_class, count);
2499         for (i = 0; i < count; i++)
2500                 mono_array_setref (res, i, mono_type_get_object (domain, &param_info->constraints [i]->byval_arg));
2501
2502
2503         return res;
2504 }
2505
2506 static MonoBoolean
2507 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2508 {
2509         MONO_ARCH_SAVE_REGS;
2510         return is_generic_parameter (type->type);
2511 }
2512
2513 static MonoBoolean
2514 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2515 {
2516         MONO_ARCH_SAVE_REGS;
2517         return is_generic_parameter (tb->type.type);
2518 }
2519
2520 static void
2521 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2522                                                                            MonoReflectionType *t)
2523 {
2524         enumtype->type = t->type;
2525 }
2526
2527 static MonoReflectionMethod*
2528 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type, 
2529                                                    MonoReflectionMethod* generic)
2530 {
2531         MonoDomain *domain; 
2532         MonoClass *klass;
2533         MonoMethod *method;
2534         gpointer iter;
2535                 
2536         MONO_ARCH_SAVE_REGS;
2537
2538         domain = ((MonoObject *)type)->vtable->domain;
2539
2540         klass = mono_class_from_mono_type (type->type);
2541         mono_class_init_or_throw (klass);
2542
2543         iter = NULL;
2544         while ((method = mono_class_get_methods (klass, &iter))) {
2545                 if (method->token == generic->method->token)
2546                         return mono_method_get_object (domain, method, klass);
2547         }
2548
2549         return NULL;
2550 }
2551
2552
2553
2554 static MonoReflectionMethod *
2555 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2556 {
2557         MonoMethod *method;
2558         MonoType *type = ref_type->type;
2559
2560         MONO_ARCH_SAVE_REGS;
2561
2562         if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2563                 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2564         if (type->type == MONO_TYPE_VAR)
2565                 return NULL;
2566
2567         method = mono_type_get_generic_param_owner (type)->owner.method;
2568         g_assert (method);
2569         return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2570 }
2571
2572 static MonoReflectionDllImportAttribute*
2573 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2574 {
2575         static MonoClass *DllImportAttributeClass = NULL;
2576         MonoDomain *domain = mono_domain_get ();
2577         MonoReflectionDllImportAttribute *attr;
2578         MonoImage *image = method->klass->image;
2579         MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2580         MonoTableInfo *tables = image->tables;
2581         MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2582         MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2583         guint32 im_cols [MONO_IMPLMAP_SIZE];
2584         guint32 scope_token;
2585         const char *import = NULL;
2586         const char *scope = NULL;
2587         guint32 flags;
2588
2589         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2590                 return NULL;
2591
2592         if (!DllImportAttributeClass) {
2593                 DllImportAttributeClass = 
2594                         mono_class_from_name (mono_defaults.corlib,
2595                                                                   "System.Runtime.InteropServices", "DllImportAttribute");
2596                 g_assert (DllImportAttributeClass);
2597         }
2598                                                                                                                 
2599         if (method->klass->image->dynamic) {
2600                 MonoReflectionMethodAux *method_aux = 
2601                         g_hash_table_lookup (
2602                                                                           ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2603                 if (method_aux) {
2604                         import = method_aux->dllentry;
2605                         scope = method_aux->dll;
2606                 }
2607
2608                 if (!import || !scope) {
2609                         mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2610                         return NULL;
2611                 }
2612         }
2613         else {
2614                 if (piinfo->implmap_idx) {
2615                         mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2616                         
2617                         piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2618                         import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2619                         scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2620                         scope = mono_metadata_string_heap (image, scope_token);
2621                 }
2622         }
2623         flags = piinfo->piflags;
2624         
2625         attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2626
2627         MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2628         MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2629         attr->call_conv = (flags & 0x700) >> 8;
2630         attr->charset = ((flags & 0x6) >> 1) + 1;
2631         if (attr->charset == 1)
2632                 attr->charset = 2;
2633         attr->exact_spelling = (flags & 0x1) != 0;
2634         attr->set_last_error = (flags & 0x40) != 0;
2635         attr->best_fit_mapping = (flags & 0x30) == 0x10;
2636         attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2637         attr->preserve_sig = FALSE;
2638
2639         return attr;
2640 }
2641
2642 static MonoReflectionMethod *
2643 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2644 {
2645         MonoMethodInflated *imethod;
2646         MonoMethod *result;
2647
2648         MONO_ARCH_SAVE_REGS;
2649
2650         if (method->method->is_generic)
2651                 return method;
2652
2653         if (!method->method->is_inflated)
2654                 return NULL;
2655
2656         imethod = (MonoMethodInflated *) method->method;
2657
2658         result = imethod->declaring;
2659         /* Not a generic method.  */
2660         if (!result->is_generic)
2661                 return NULL;
2662
2663         if (method->method->klass->image->dynamic) {
2664                 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2665                 MonoReflectionMethod *res;
2666
2667                 /*
2668                  * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2669                  * the dynamic case as well ?
2670                  */
2671                 mono_loader_lock ();
2672                 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2673                 mono_loader_unlock ();
2674
2675                 if (res)
2676                         return res;
2677         }
2678
2679         if (imethod->context.class_inst) {
2680                 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2681                 /*Generic methods gets the context of the GTD.*/
2682                 if (mono_class_get_context (klass))
2683                         result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2684         }
2685
2686         return mono_method_get_object (mono_object_domain (method), result, NULL);
2687 }
2688
2689 static gboolean
2690 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2691 {
2692         MONO_ARCH_SAVE_REGS;
2693
2694         return mono_method_signature (method->method)->generic_param_count != 0;
2695 }
2696
2697 static gboolean
2698 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2699 {
2700         MONO_ARCH_SAVE_REGS;
2701
2702         return method->method->is_generic;
2703 }
2704
2705 static MonoArray*
2706 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2707 {
2708         MonoArray *res;
2709         MonoDomain *domain;
2710         int count, i;
2711         MONO_ARCH_SAVE_REGS;
2712
2713         domain = mono_object_domain (method);
2714
2715         if (method->method->is_inflated) {
2716                 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2717
2718                 if (inst) {
2719                         count = inst->type_argc;
2720                         res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2721
2722                         for (i = 0; i < count; i++)
2723                                 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2724
2725                         return res;
2726                 }
2727         }
2728
2729         count = mono_method_signature (method->method)->generic_param_count;
2730         res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2731
2732         for (i = 0; i < count; i++) {
2733                 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2734                 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2735                 MonoClass *pklass = mono_class_from_generic_parameter (
2736                         param, method->method->klass->image, TRUE);
2737                 mono_array_setref (res, i,
2738                                 mono_type_get_object (domain, &pklass->byval_arg));
2739         }
2740
2741         return res;
2742 }
2743
2744 static MonoObject *
2745 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc) 
2746 {
2747         /* 
2748          * Invoke from reflection is supposed to always be a virtual call (the API
2749          * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2750          * greater flexibility.
2751          */
2752         MonoMethod *m = method->method;
2753         int pcount;
2754         void *obj = this;
2755
2756         MONO_ARCH_SAVE_REGS;
2757
2758         *exc = NULL;
2759
2760         if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2761                 mono_security_core_clr_ensure_reflection_access_method (m);
2762
2763         if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2764                 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2765                         mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2766                         return NULL;
2767                 }
2768
2769                 if (this) {
2770                         if (!mono_object_isinst (this, m->klass)) {
2771                                 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2772                                 return NULL;
2773                         }
2774                         m = mono_object_get_virtual_method (this, m);
2775                         /* must pass the pointer to the value for valuetype methods */
2776                         if (m->klass->valuetype)
2777                                 obj = mono_object_unbox (this);
2778                 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2779                         mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2780                         return NULL;
2781                 }
2782         }
2783
2784         pcount = params? mono_array_length (params): 0;
2785         if (pcount != mono_method_signature (m)->param_count) {
2786                 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2787                 return NULL;
2788         }
2789
2790         if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2791                 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."));
2792                 return NULL;
2793         }
2794
2795         if (m->klass->image->assembly->ref_only) {
2796                 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."));
2797                 return NULL;
2798         }
2799         
2800         if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2801                 int i;
2802                 uintptr_t *lengths;
2803                 intptr_t *lower_bounds;
2804                 pcount = mono_array_length (params);
2805                 lengths = alloca (sizeof (uintptr_t) * pcount);
2806                 /* Note: the synthetized array .ctors have int32 as argument type */
2807                 for (i = 0; i < pcount; ++i)
2808                         lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2809
2810                 if (m->klass->rank == pcount) {
2811                         /* Only lengths provided. */
2812                         lower_bounds = NULL;
2813                 } else {
2814                         g_assert (pcount == (m->klass->rank * 2));
2815                         /* lower bounds are first. */
2816                         lower_bounds = (intptr_t*)lengths;
2817                         lengths += m->klass->rank;
2818                 }
2819
2820                 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2821         }
2822         return mono_runtime_invoke_array (m, obj, params, NULL);
2823 }
2824
2825 static MonoObject *
2826 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs) 
2827 {
2828         MonoDomain *domain = mono_object_domain (method); 
2829         MonoMethod *m = method->method;
2830         MonoMethodSignature *sig = mono_method_signature (m);
2831         MonoArray *out_args;
2832         MonoObject *result;
2833         int i, j, outarg_count = 0;
2834
2835         MONO_ARCH_SAVE_REGS;
2836
2837         if (m->klass == mono_defaults.object_class) {
2838
2839                 if (!strcmp (m->name, "FieldGetter")) {
2840                         MonoClass *k = this->vtable->klass;
2841                         MonoString *name;
2842                         char *str;
2843                         
2844                         /* If this is a proxy, then it must be a CBO */
2845                         if (k == mono_defaults.transparent_proxy_class) {
2846                                 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2847                                 this = tp->rp->unwrapped_server;
2848                                 g_assert (this);
2849                                 k = this->vtable->klass;
2850                         }
2851                         
2852                         name = mono_array_get (params, MonoString *, 1);
2853                         str = mono_string_to_utf8 (name);
2854                 
2855                         do {
2856                                 MonoClassField* field = mono_class_get_field_from_name (k, str);
2857                                 if (field) {
2858                                         MonoClass *field_klass =  mono_class_from_mono_type (field->type);
2859                                         if (field_klass->valuetype)
2860                                                 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2861                                         else 
2862                                                 result = *((gpointer *)((char *)this + field->offset));
2863                                 
2864                                         out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2865                                         mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2866                                         mono_array_setref (out_args, 0, result);
2867                                         g_free (str);
2868                                         return NULL;
2869                                 }
2870                                 k = k->parent;
2871                         } while (k);
2872
2873                         g_free (str);
2874                         g_assert_not_reached ();
2875
2876                 } else if (!strcmp (m->name, "FieldSetter")) {
2877                         MonoClass *k = this->vtable->klass;
2878                         MonoString *name;
2879                         guint32 size;
2880                         gint32 align;
2881                         char *str;
2882                         
2883                         /* If this is a proxy, then it must be a CBO */
2884                         if (k == mono_defaults.transparent_proxy_class) {
2885                                 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2886                                 this = tp->rp->unwrapped_server;
2887                                 g_assert (this);
2888                                 k = this->vtable->klass;
2889                         }
2890                         
2891                         name = mono_array_get (params, MonoString *, 1);
2892                         str = mono_string_to_utf8 (name);
2893                 
2894                         do {
2895                                 MonoClassField* field = mono_class_get_field_from_name (k, str);
2896                                 if (field) {
2897                                         MonoClass *field_klass =  mono_class_from_mono_type (field->type);
2898                                         MonoObject *val = mono_array_get (params, gpointer, 2);
2899
2900                                         if (field_klass->valuetype) {
2901                                                 size = mono_type_size (field->type, &align);
2902                                                 g_assert (size == mono_class_value_size (field_klass, NULL));
2903                                                 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2904                                         } else {
2905                                                 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2906                                         }
2907                                 
2908                                         out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2909                                         mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2910
2911                                         g_free (str);
2912                                         return NULL;
2913                                 }
2914                                 
2915                                 k = k->parent;
2916                         } while (k);
2917
2918                         g_free (str);
2919                         g_assert_not_reached ();
2920
2921                 }
2922         }
2923
2924         for (i = 0; i < mono_array_length (params); i++) {
2925                 if (sig->params [i]->byref) 
2926                         outarg_count++;
2927         }
2928
2929         out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2930         
2931         /* handle constructors only for objects already allocated */
2932         if (!strcmp (method->method->name, ".ctor"))
2933                 g_assert (this);
2934
2935         /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2936         g_assert (!method->method->klass->valuetype);
2937         result = mono_runtime_invoke_array (method->method, this, params, NULL);
2938
2939         for (i = 0, j = 0; i < mono_array_length (params); i++) {
2940                 if (sig->params [i]->byref) {
2941                         gpointer arg;
2942                         arg = mono_array_get (params, gpointer, i);
2943                         mono_array_setref (out_args, j, arg);
2944                         j++;
2945                 }
2946         }
2947
2948         mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2949
2950         return result;
2951 }
2952
2953 static guint64
2954 read_enum_value (char *mem, int type)
2955 {
2956         switch (type) {
2957         case MONO_TYPE_U1:
2958                 return *(guint8*)mem;
2959         case MONO_TYPE_I1:
2960                 return *(gint8*)mem;
2961         case MONO_TYPE_U2:
2962                 return *(guint16*)mem;
2963         case MONO_TYPE_I2:
2964                 return *(gint16*)mem;
2965         case MONO_TYPE_U4:
2966                 return *(guint32*)mem;
2967         case MONO_TYPE_I4:
2968                 return *(gint32*)mem;
2969         case MONO_TYPE_U8:
2970                 return *(guint64*)mem;
2971         case MONO_TYPE_I8:
2972                 return *(gint64*)mem;
2973         default:
2974                 g_assert_not_reached ();
2975         }
2976         return 0;
2977 }
2978
2979 static void
2980 write_enum_value (char *mem, int type, guint64 value)
2981 {
2982         switch (type) {
2983         case MONO_TYPE_U1:
2984         case MONO_TYPE_I1: {
2985                 guint8 *p = (guint8*)mem;
2986                 *p = value;
2987                 break;
2988         }
2989         case MONO_TYPE_U2:
2990         case MONO_TYPE_I2: {
2991                 guint16 *p = (void*)mem;
2992                 *p = value;
2993                 break;
2994         }
2995         case MONO_TYPE_U4:
2996         case MONO_TYPE_I4: {
2997                 guint32 *p = (void*)mem;
2998                 *p = value;
2999                 break;
3000         }
3001         case MONO_TYPE_U8:
3002         case MONO_TYPE_I8: {
3003                 guint64 *p = (void*)mem;
3004                 *p = value;
3005                 break;
3006         }
3007         default:
3008                 g_assert_not_reached ();
3009         }
3010         return;
3011 }
3012
3013 static MonoObject *
3014 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3015 {
3016         MonoDomain *domain; 
3017         MonoClass *enumc, *objc;
3018         MonoObject *res;
3019         MonoType *etype;
3020         guint64 val;
3021         
3022         MONO_ARCH_SAVE_REGS;
3023
3024         MONO_CHECK_ARG_NULL (enumType);
3025         MONO_CHECK_ARG_NULL (value);
3026
3027         domain = mono_object_domain (enumType); 
3028         enumc = mono_class_from_mono_type (enumType->type);
3029
3030         mono_class_init_or_throw (enumc);
3031
3032         objc = value->vtable->klass;
3033
3034         if (!enumc->enumtype)
3035                 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3036         if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3037                 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."));
3038
3039         etype = mono_class_enum_basetype (enumc);
3040         if (!etype)
3041                 /* MS throws this for typebuilders */
3042                 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3043
3044         res = mono_object_new (domain, enumc);
3045         val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3046         write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3047
3048         return res;
3049 }
3050
3051 static MonoObject *
3052 ves_icall_System_Enum_get_value (MonoObject *this)
3053 {
3054         MonoObject *res;
3055         MonoClass *enumc;
3056         gpointer dst;
3057         gpointer src;
3058         int size;
3059
3060         MONO_ARCH_SAVE_REGS;
3061
3062         if (!this)
3063                 return NULL;
3064
3065         g_assert (this->vtable->klass->enumtype);
3066         
3067         enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3068         res = mono_object_new (mono_object_domain (this), enumc);
3069         dst = (char *)res + sizeof (MonoObject);
3070         src = (char *)this + sizeof (MonoObject);
3071         size = mono_class_value_size (enumc, NULL);
3072
3073         memcpy (dst, src, size);
3074
3075         return res;
3076 }
3077
3078 static MonoReflectionType *
3079 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3080 {
3081         MonoType *etype;
3082         MonoClass *klass;
3083
3084         MONO_ARCH_SAVE_REGS;
3085
3086         klass = mono_class_from_mono_type (type->type);
3087         mono_class_init_or_throw (klass);
3088
3089         etype = mono_class_enum_basetype (klass);
3090         if (!etype)
3091                 /* MS throws this for typebuilders */
3092                 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3093
3094         return mono_type_get_object (mono_object_domain (type), etype);
3095 }
3096
3097 static int
3098 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3099 {
3100         gpointer tdata = (char *)this + sizeof (MonoObject);
3101         gpointer odata = (char *)other + sizeof (MonoObject);
3102         MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3103         g_assert (basetype);
3104
3105 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3106                 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3107                 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3108                 if (me == other) \
3109                         return 0; \
3110                 return me > other ? 1 : -1; \
3111         } while (0)
3112
3113 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3114                 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3115                 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3116                 if (me == other) \
3117                         return 0; \
3118                 return me - other; \
3119         } while (0)
3120
3121         switch (basetype->type) {
3122                 case MONO_TYPE_U1:
3123                         COMPARE_ENUM_VALUES (guint8);
3124                 case MONO_TYPE_I1:
3125                         COMPARE_ENUM_VALUES (gint8);
3126                 case MONO_TYPE_CHAR:
3127                 case MONO_TYPE_U2:
3128                         COMPARE_ENUM_VALUES_RANGE (guint16);
3129                 case MONO_TYPE_I2:
3130                         COMPARE_ENUM_VALUES (gint16);
3131                 case MONO_TYPE_U4:
3132                         COMPARE_ENUM_VALUES (guint32);
3133                 case MONO_TYPE_I4:
3134                         COMPARE_ENUM_VALUES (gint32);
3135                 case MONO_TYPE_U8:
3136                         COMPARE_ENUM_VALUES (guint64);
3137                 case MONO_TYPE_I8:
3138                         COMPARE_ENUM_VALUES (gint64);
3139                 default:
3140                         g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3141         }
3142 #undef COMPARE_ENUM_VALUES_RANGE
3143 #undef COMPARE_ENUM_VALUES
3144         return 0;
3145 }
3146
3147 static int
3148 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3149 {
3150         gpointer data = (char *)this + sizeof (MonoObject);
3151         MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3152         g_assert (basetype);
3153
3154         switch (basetype->type) {
3155                 case MONO_TYPE_I1:      
3156                         return *((gint8*)data);
3157                 case MONO_TYPE_U1:
3158                         return *((guint8*)data);
3159                 case MONO_TYPE_CHAR:
3160                 case MONO_TYPE_U2:
3161                         return *((guint16*)data);
3162                 
3163                 case MONO_TYPE_I2:
3164                         return *((gint16*)data);
3165                 case MONO_TYPE_U4:
3166                         return *((guint32*)data);
3167                 case MONO_TYPE_I4:
3168                         return *((gint32*)data);
3169                 case MONO_TYPE_U8:
3170                 case MONO_TYPE_I8: {
3171                         gint64 value = *((gint64*)data);
3172                         return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3173                 }
3174                 default:
3175                         g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3176         }
3177         return 0;
3178 }
3179
3180 static void
3181 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3182 {
3183         MonoDomain *domain = mono_object_domain (type); 
3184         MonoClass *enumc = mono_class_from_mono_type (type->type);
3185         guint j = 0, nvalues, crow;
3186         gpointer iter;
3187         MonoClassField *field;
3188
3189         MONO_ARCH_SAVE_REGS;
3190
3191         mono_class_init_or_throw (enumc);
3192
3193         MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3194         nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3195         MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3196         MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3197
3198         crow = -1;
3199         iter = NULL;
3200         while ((field = mono_class_get_fields (enumc, &iter))) {
3201                 const char *p;
3202                 int len;
3203                 MonoTypeEnum def_type;
3204                 
3205                 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3206                         continue;
3207                 if (mono_field_is_deleted (field))
3208                         continue;
3209                 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3210
3211                 p = mono_class_get_field_default_value (field, &def_type);
3212                 len = mono_metadata_decode_blob_size (p, &p);
3213                 switch (mono_class_enum_basetype (enumc)->type) {
3214                 case MONO_TYPE_U1:
3215                 case MONO_TYPE_I1:
3216                         mono_array_set (info->values, gchar, j, *p);
3217                         break;
3218                 case MONO_TYPE_CHAR:
3219                 case MONO_TYPE_U2:
3220                 case MONO_TYPE_I2:
3221                         mono_array_set (info->values, gint16, j, read16 (p));
3222                         break;
3223                 case MONO_TYPE_U4:
3224                 case MONO_TYPE_I4:
3225                         mono_array_set (info->values, gint32, j, read32 (p));
3226                         break;
3227                 case MONO_TYPE_U8:
3228                 case MONO_TYPE_I8:
3229                         mono_array_set (info->values, gint64, j, read64 (p));
3230                         break;
3231                 default:
3232                         g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3233                 }
3234                 ++j;
3235         }
3236 }
3237
3238 enum {
3239         BFLAGS_IgnoreCase = 1,
3240         BFLAGS_DeclaredOnly = 2,
3241         BFLAGS_Instance = 4,
3242         BFLAGS_Static = 8,
3243         BFLAGS_Public = 0x10,
3244         BFLAGS_NonPublic = 0x20,
3245         BFLAGS_FlattenHierarchy = 0x40,
3246         BFLAGS_InvokeMethod = 0x100,
3247         BFLAGS_CreateInstance = 0x200,
3248         BFLAGS_GetField = 0x400,
3249         BFLAGS_SetField = 0x800,
3250         BFLAGS_GetProperty = 0x1000,
3251         BFLAGS_SetProperty = 0x2000,
3252         BFLAGS_ExactBinding = 0x10000,
3253         BFLAGS_SuppressChangeType = 0x20000,
3254         BFLAGS_OptionalParamBinding = 0x40000
3255 };
3256
3257 static MonoReflectionField *
3258 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3259 {
3260         MonoDomain *domain; 
3261         MonoClass *startklass, *klass;
3262         int match;
3263         MonoClassField *field;
3264         gpointer iter;
3265         char *utf8_name;
3266         int (*compare_func) (const char *s1, const char *s2) = NULL;
3267         domain = ((MonoObject *)type)->vtable->domain;
3268         klass = startklass = mono_class_from_mono_type (type->type);
3269         mono_class_init_or_throw (klass);
3270
3271         if (!name)
3272                 mono_raise_exception (mono_get_exception_argument_null ("name"));
3273         if (type->type->byref)
3274                 return NULL;
3275
3276         compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3277
3278 handle_parent:
3279         if (klass->exception_type != MONO_EXCEPTION_NONE)
3280                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3281
3282         iter = NULL;
3283         while ((field = mono_class_get_fields (klass, &iter))) {
3284                 match = 0;
3285
3286                 if (field->type == NULL)
3287                         continue;
3288                 if (mono_field_is_deleted (field))
3289                         continue;
3290                 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3291                         if (bflags & BFLAGS_Public)
3292                                 match++;
3293                 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3294                         if (bflags & BFLAGS_NonPublic) {
3295                                 match++;
3296                         }
3297                 }
3298                 if (!match)
3299                         continue;
3300                 match = 0;
3301                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3302                         if (bflags & BFLAGS_Static)
3303                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3304                                         match++;
3305                 } else {
3306                         if (bflags & BFLAGS_Instance)
3307                                 match++;
3308                 }
3309
3310                 if (!match)
3311                         continue;
3312                 
3313                 utf8_name = mono_string_to_utf8 (name);
3314
3315                 if (compare_func (mono_field_get_name (field), utf8_name)) {
3316                         g_free (utf8_name);
3317                         continue;
3318                 }
3319                 g_free (utf8_name);
3320                 
3321                 return mono_field_get_object (domain, klass, field);
3322         }
3323         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3324                 goto handle_parent;
3325
3326         return NULL;
3327 }
3328
3329 static MonoArray*
3330 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3331 {
3332         MonoDomain *domain; 
3333         MonoClass *startklass, *klass, *refklass;
3334         MonoArray *res;
3335         MonoObject *member;
3336         int i, match;
3337         gpointer iter;
3338         MonoClassField *field;
3339         MonoPtrArray tmp_array;
3340
3341         MONO_ARCH_SAVE_REGS;
3342
3343         domain = ((MonoObject *)type)->vtable->domain;
3344         if (type->type->byref)
3345                 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3346         klass = startklass = mono_class_from_mono_type (type->type);
3347         refklass = mono_class_from_mono_type (reftype->type);
3348
3349         mono_class_init_or_throw (klass);
3350         mono_class_init_or_throw (refklass);
3351
3352         mono_ptr_array_init (tmp_array, 2);
3353         
3354 handle_parent:  
3355         if (klass->exception_type != MONO_EXCEPTION_NONE)
3356                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3357
3358         iter = NULL;
3359         while ((field = mono_class_get_fields (klass, &iter))) {
3360                 match = 0;
3361                 if (mono_field_is_deleted (field))
3362                         continue;
3363                 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3364                         if (bflags & BFLAGS_Public)
3365                                 match++;
3366                 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3367                         if (bflags & BFLAGS_NonPublic) {
3368                                 match++;
3369                         }
3370                 }
3371                 if (!match)
3372                         continue;
3373                 match = 0;
3374                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3375                         if (bflags & BFLAGS_Static)
3376                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3377                                         match++;
3378                 } else {
3379                         if (bflags & BFLAGS_Instance)
3380                                 match++;
3381                 }
3382
3383                 if (!match)
3384                         continue;
3385                 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3386                 mono_ptr_array_append (tmp_array, member);
3387         }
3388         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3389                 goto handle_parent;
3390
3391         res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3392
3393         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3394                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3395
3396         mono_ptr_array_destroy (tmp_array);
3397
3398         return res;
3399 }
3400
3401 static gboolean
3402 method_nonpublic (MonoMethod* method, gboolean start_klass)
3403 {
3404         switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3405                 case METHOD_ATTRIBUTE_ASSEM:
3406                         return (start_klass || mono_defaults.generic_ilist_class);
3407                 case METHOD_ATTRIBUTE_PRIVATE:
3408                         return start_klass;
3409                 case METHOD_ATTRIBUTE_PUBLIC:
3410                         return FALSE;
3411                 default:
3412                         return TRUE;
3413         }
3414 }
3415
3416 static MonoArray*
3417 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3418 {
3419         static MonoClass *MethodInfo_array;
3420         MonoDomain *domain; 
3421         MonoClass *startklass, *klass, *refklass;
3422         MonoArray *res;
3423         MonoMethod *method;
3424         gpointer iter;
3425         MonoObject *member;
3426         int i, len, match, nslots;
3427         /*FIXME, use MonoBitSet*/
3428         guint32 method_slots_default [8];
3429         guint32 *method_slots = NULL;
3430         gchar *mname = NULL;
3431         int (*compare_func) (const char *s1, const char *s2) = NULL;
3432         MonoVTable *array_vtable;
3433         MonoException *ex;
3434         MonoPtrArray tmp_array;
3435
3436         mono_ptr_array_init (tmp_array, 4);
3437
3438         if (!MethodInfo_array) {
3439                 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3440                 mono_memory_barrier ();
3441                 MethodInfo_array = klass;
3442         }
3443
3444         domain = ((MonoObject *)type)->vtable->domain;
3445         array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3446         if (type->type->byref)
3447                 return mono_array_new_specific (array_vtable, 0);
3448         klass = startklass = mono_class_from_mono_type (type->type);
3449         refklass = mono_class_from_mono_type (reftype->type);
3450
3451         mono_class_init_or_throw (klass);
3452         mono_class_init_or_throw (refklass);
3453
3454         len = 0;
3455         if (name != NULL) {
3456                 mname = mono_string_to_utf8 (name);
3457                 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3458         }
3459
3460         /* An optimization for calls made from Delegate:CreateDelegate () */
3461         if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3462                 method = mono_get_delegate_invoke (klass);
3463                 if (mono_loader_get_last_error ())
3464                         goto loader_error;
3465
3466                 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3467
3468                 res = mono_array_new_specific (array_vtable, 1);
3469                 mono_array_setref (res, 0, member);
3470                 g_free (mname);
3471                 return res;
3472         }
3473
3474         mono_class_setup_vtable (klass);
3475         if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3476                 goto loader_error;
3477
3478         if (is_generic_parameter (type->type))
3479                 nslots = mono_class_get_vtable_size (klass->parent);
3480         else
3481                 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3482         if (nslots >= sizeof (method_slots_default) * 8) {
3483                 method_slots = g_new0 (guint32, nslots / 32 + 1);
3484         } else {
3485                 method_slots = method_slots_default;
3486                 memset (method_slots, 0, sizeof (method_slots_default));
3487         }
3488 handle_parent:
3489         mono_class_setup_vtable (klass);
3490         if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3491                 goto loader_error;              
3492
3493         iter = NULL;
3494         while ((method = mono_class_get_methods (klass, &iter))) {
3495                 match = 0;
3496                 if (method->slot != -1) {
3497                         g_assert (method->slot < nslots);
3498                         if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3499                                 continue;
3500                         if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3501                                 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3502                 }
3503
3504                 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3505                         continue;
3506                 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3507                         if (bflags & BFLAGS_Public)
3508                                 match++;
3509                 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3510                                 match++;
3511                 }
3512                 if (!match)
3513                         continue;
3514                 match = 0;
3515                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3516                         if (bflags & BFLAGS_Static)
3517                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3518                                         match++;
3519                 } else {
3520                         if (bflags & BFLAGS_Instance)
3521                                 match++;
3522                 }
3523
3524                 if (!match)
3525                         continue;
3526
3527                 if (name != NULL) {
3528                         if (compare_func (mname, method->name))
3529                                 continue;
3530                 }
3531                 
3532                 match = 0;
3533                 
3534                 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3535                 
3536                 mono_ptr_array_append (tmp_array, member);
3537         }
3538         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3539                 goto handle_parent;
3540
3541         g_free (mname);
3542         if (method_slots != method_slots_default)
3543                 g_free (method_slots);
3544
3545         res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3546
3547         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3548                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3549
3550         mono_ptr_array_destroy (tmp_array);
3551         return res;
3552
3553 loader_error:
3554         g_free (mname);
3555         if (method_slots != method_slots_default)
3556                 g_free (method_slots);
3557         mono_ptr_array_destroy (tmp_array);
3558         if (klass->exception_type != MONO_EXCEPTION_NONE) {
3559                 ex = mono_class_get_exception_for_failure (klass);
3560         } else {
3561                 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3562                 mono_loader_clear_error ();
3563         }
3564         mono_raise_exception (ex);
3565         return NULL;
3566 }
3567
3568 static MonoArray*
3569 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3570 {
3571         MonoDomain *domain; 
3572         static MonoClass *System_Reflection_ConstructorInfo;
3573         MonoClass *startklass, *klass, *refklass;
3574         MonoArray *res;
3575         MonoMethod *method;
3576         MonoObject *member;
3577         int i, match;
3578         gpointer iter = NULL;
3579         MonoPtrArray tmp_array;
3580         
3581         MONO_ARCH_SAVE_REGS;
3582
3583         mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3584
3585         domain = ((MonoObject *)type)->vtable->domain;
3586         if (type->type->byref)
3587                 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3588         klass = startklass = mono_class_from_mono_type (type->type);
3589         refklass = mono_class_from_mono_type (reftype->type);
3590
3591         mono_class_init_or_throw (klass);
3592         mono_class_init_or_throw (refklass);
3593
3594         if (klass->exception_type != MONO_EXCEPTION_NONE)
3595                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3596
3597         if (!System_Reflection_ConstructorInfo)
3598                 System_Reflection_ConstructorInfo = mono_class_from_name (
3599                         mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3600
3601         iter = NULL;
3602         while ((method = mono_class_get_methods (klass, &iter))) {
3603                 match = 0;
3604                 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3605                         continue;
3606                 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3607                         if (bflags & BFLAGS_Public)
3608                                 match++;
3609                 } else {
3610                         if (bflags & BFLAGS_NonPublic)
3611                                 match++;
3612                 }
3613                 if (!match)
3614                         continue;
3615                 match = 0;
3616                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3617                         if (bflags & BFLAGS_Static)
3618                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3619                                         match++;
3620                 } else {
3621                         if (bflags & BFLAGS_Instance)
3622                                 match++;
3623                 }
3624
3625                 if (!match)
3626                         continue;
3627                 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3628
3629                 mono_ptr_array_append (tmp_array, member);
3630         }
3631
3632         res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3633
3634         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3635                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3636
3637         mono_ptr_array_destroy (tmp_array);
3638
3639         return res;
3640 }
3641
3642 static guint
3643 property_hash (gconstpointer data)
3644 {
3645         MonoProperty *prop = (MonoProperty*)data;
3646
3647         return g_str_hash (prop->name);
3648 }
3649
3650 static gboolean
3651 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3652 {
3653         // Properties are hide-by-name-and-signature
3654         if (!g_str_equal (prop1->name, prop2->name))
3655                 return FALSE;
3656
3657         if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3658                 return FALSE;
3659         if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3660                 return FALSE;
3661         return TRUE;
3662 }
3663
3664 static gboolean
3665 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3666 {
3667         if (!accessor)
3668                 return FALSE;
3669
3670         return method_nonpublic (accessor, start_klass);
3671 }
3672
3673 static MonoArray*
3674 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3675 {
3676         MonoDomain *domain; 
3677         static MonoClass *System_Reflection_PropertyInfo;
3678         MonoClass *startklass, *klass;
3679         MonoArray *res;
3680         MonoMethod *method;
3681         MonoProperty *prop;
3682         int i, match;
3683         guint32 flags;
3684         gchar *propname = NULL;
3685         int (*compare_func) (const char *s1, const char *s2) = NULL;
3686         gpointer iter;
3687         GHashTable *properties;
3688         MonoPtrArray tmp_array;
3689
3690         MONO_ARCH_SAVE_REGS;
3691
3692         mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3693
3694         if (!System_Reflection_PropertyInfo)
3695                 System_Reflection_PropertyInfo = mono_class_from_name (
3696                         mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3697
3698         domain = ((MonoObject *)type)->vtable->domain;
3699         if (type->type->byref)
3700                 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3701         klass = startklass = mono_class_from_mono_type (type->type);
3702         mono_class_init_or_throw (klass);
3703
3704
3705
3706         if (name != NULL) {
3707                 propname = mono_string_to_utf8 (name);
3708                 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3709         }
3710
3711         mono_class_setup_vtable (klass);
3712
3713         properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3714 handle_parent:
3715         mono_class_setup_vtable (klass);
3716         if (klass->exception_type != MONO_EXCEPTION_NONE) {
3717                 g_hash_table_destroy (properties);
3718                 if (name != NULL)
3719                         g_free (propname);
3720                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3721         }
3722
3723         iter = NULL;
3724         while ((prop = mono_class_get_properties (klass, &iter))) {
3725                 match = 0;
3726                 method = prop->get;
3727                 if (!method)
3728                         method = prop->set;
3729                 if (method)
3730                         flags = method->flags;
3731                 else
3732                         flags = 0;
3733                 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3734                         (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3735                         if (bflags & BFLAGS_Public)
3736                                 match++;
3737                 } else if (bflags & BFLAGS_NonPublic) {
3738                         if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3739                                 property_accessor_nonpublic(prop->set, startklass == klass)) {
3740                                 match++;
3741                         }
3742                 }
3743                 if (!match)
3744                         continue;
3745                 match = 0;
3746                 if (flags & METHOD_ATTRIBUTE_STATIC) {
3747                         if (bflags & BFLAGS_Static)
3748                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3749                                         match++;
3750                 } else {
3751                         if (bflags & BFLAGS_Instance)
3752                                 match++;
3753                 }
3754
3755                 if (!match)
3756                         continue;
3757                 match = 0;
3758
3759                 if (name != NULL) {
3760                         if (compare_func (propname, prop->name))
3761                                 continue;
3762                 }
3763                 
3764                 if (g_hash_table_lookup (properties, prop))
3765                         continue;
3766
3767                 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3768                 
3769                 g_hash_table_insert (properties, prop, prop);
3770         }
3771         if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3772                 goto handle_parent;
3773
3774         g_hash_table_destroy (properties);
3775         g_free (propname);
3776
3777         res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3778         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3779                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3780
3781         mono_ptr_array_destroy (tmp_array);
3782
3783         return res;
3784 }
3785
3786 static MonoReflectionEvent *
3787 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3788 {
3789         MonoDomain *domain;
3790         MonoClass *klass, *startklass;
3791         gpointer iter;
3792         MonoEvent *event;
3793         MonoMethod *method;
3794         gchar *event_name;
3795
3796         MONO_ARCH_SAVE_REGS;
3797
3798         event_name = mono_string_to_utf8 (name);
3799         if (type->type->byref)
3800                 return NULL;
3801         klass = startklass = mono_class_from_mono_type (type->type);
3802         domain = mono_object_domain (type);
3803
3804         mono_class_init_or_throw (klass);
3805
3806 handle_parent:  
3807         if (klass->exception_type != MONO_EXCEPTION_NONE)
3808                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3809
3810         iter = NULL;
3811         while ((event = mono_class_get_events (klass, &iter))) {
3812                 if (strcmp (event->name, event_name))
3813                         continue;
3814
3815                 method = event->add;
3816                 if (!method)
3817                         method = event->remove;
3818                 if (!method)
3819                         method = event->raise;
3820                 if (method) {
3821                         if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3822                                 if (!(bflags & BFLAGS_Public))
3823                                         continue;
3824                         } else {
3825                                 if (!(bflags & BFLAGS_NonPublic))
3826                                         continue;
3827                                 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3828                                         continue;
3829                         }
3830
3831                         if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3832                                 if (!(bflags & BFLAGS_Static))
3833                                         continue;
3834                                 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3835                                         continue;
3836                         } else {
3837                                 if (!(bflags & BFLAGS_Instance))
3838                                         continue;
3839                         }
3840                 } else 
3841                         if (!(bflags & BFLAGS_NonPublic))
3842                                 continue;
3843                 
3844                 g_free (event_name);
3845                 return mono_event_get_object (domain, startklass, event);
3846         }
3847
3848         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3849                 goto handle_parent;
3850
3851         g_free (event_name);
3852         return NULL;
3853 }
3854
3855 static MonoArray*
3856 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3857 {
3858         MonoDomain *domain; 
3859         static MonoClass *System_Reflection_EventInfo;
3860         MonoClass *startklass, *klass;
3861         MonoArray *res;
3862         MonoMethod *method;
3863         MonoEvent *event;
3864         int i, match;
3865         gpointer iter;
3866         
3867         MonoPtrArray tmp_array;
3868
3869         MONO_ARCH_SAVE_REGS;
3870
3871         mono_ptr_array_init (tmp_array, 4);
3872
3873         if (!System_Reflection_EventInfo)
3874                 System_Reflection_EventInfo = mono_class_from_name (
3875                         mono_defaults.corlib, "System.Reflection", "EventInfo");
3876
3877         domain = mono_object_domain (type);
3878         if (type->type->byref)
3879                 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3880         klass = startklass = mono_class_from_mono_type (type->type);
3881         mono_class_init_or_throw (klass);
3882
3883
3884 handle_parent:  
3885         if (klass->exception_type != MONO_EXCEPTION_NONE)
3886                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3887
3888         iter = NULL;
3889         while ((event = mono_class_get_events (klass, &iter))) {
3890                 match = 0;
3891                 method = event->add;
3892                 if (!method)
3893                         method = event->remove;
3894                 if (!method)
3895                         method = event->raise;
3896                 if (method) {
3897                         if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3898                                 if (bflags & BFLAGS_Public)
3899                                         match++;
3900                         } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3901                                 if (bflags & BFLAGS_NonPublic)
3902                                         match++;
3903                         }
3904                 }
3905                 else
3906                         if (bflags & BFLAGS_NonPublic)
3907                                 match ++;
3908                 if (!match)
3909                         continue;
3910                 match = 0;
3911                 if (method) {
3912                         if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3913                                 if (bflags & BFLAGS_Static)
3914                                         if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3915                                                 match++;
3916                         } else {
3917                                 if (bflags & BFLAGS_Instance)
3918                                         match++;
3919                         }
3920                 }
3921                 else
3922                         if (bflags & BFLAGS_Instance)
3923                                 match ++;
3924                 if (!match)
3925                         continue;
3926                 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3927         }
3928         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3929                 goto handle_parent;
3930
3931         res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3932
3933         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3934                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3935
3936         mono_ptr_array_destroy (tmp_array);
3937
3938         return res;
3939 }
3940
3941 static MonoReflectionType *
3942 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3943 {
3944         MonoDomain *domain; 
3945         MonoClass *klass;
3946         MonoClass *nested;
3947         char *str;
3948         gpointer iter;
3949         
3950         MONO_ARCH_SAVE_REGS;
3951
3952         if (name == NULL)
3953                 mono_raise_exception (mono_get_exception_argument_null ("name"));
3954         
3955         domain = ((MonoObject *)type)->vtable->domain;
3956         if (type->type->byref)
3957                 return NULL;
3958         klass = mono_class_from_mono_type (type->type);
3959         mono_class_init_or_throw (klass);
3960
3961         str = mono_string_to_utf8 (name);
3962
3963  handle_parent:
3964         if (klass->exception_type != MONO_EXCEPTION_NONE)
3965                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3966
3967         /*
3968          * If a nested type is generic, return its generic type definition.
3969          * Note that this means that the return value is essentially a
3970          * nested type of the generic type definition of @klass.
3971          *
3972          * A note in MSDN claims that a generic type definition can have
3973          * nested types that aren't generic.  In any case, the container of that
3974          * nested type would be the generic type definition.
3975          */
3976         if (klass->generic_class)
3977                 klass = klass->generic_class->container_class;
3978
3979         iter = NULL;
3980         while ((nested = mono_class_get_nested_types (klass, &iter))) {
3981                 int match = 0;
3982                 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3983                         if (bflags & BFLAGS_Public)
3984                                 match++;
3985                 } else {
3986                         if (bflags & BFLAGS_NonPublic)
3987                                 match++;
3988                 }
3989                 if (!match)
3990                         continue;
3991                 if (strcmp (nested->name, str) == 0){
3992                         g_free (str);
3993                         return mono_type_get_object (domain, &nested->byval_arg);
3994                 }
3995         }
3996         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3997                 goto handle_parent;
3998         g_free (str);
3999         return NULL;
4000 }
4001
4002 static MonoArray*
4003 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4004 {
4005         MonoDomain *domain; 
4006         MonoClass *klass;
4007         MonoArray *res;
4008         MonoObject *member;
4009         int i, match;
4010         MonoClass *nested;
4011         gpointer iter;
4012         MonoPtrArray tmp_array;
4013
4014         MONO_ARCH_SAVE_REGS;
4015
4016         domain = ((MonoObject *)type)->vtable->domain;
4017         if (type->type->byref)
4018                 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4019         klass = mono_class_from_mono_type (type->type);
4020         mono_class_init_or_throw (klass);
4021
4022         /*
4023          * If a nested type is generic, return its generic type definition.
4024          * Note that this means that the return value is essentially the set
4025          * of nested types of the generic type definition of @klass.
4026          *
4027          * A note in MSDN claims that a generic type definition can have
4028          * nested types that aren't generic.  In any case, the container of that
4029          * nested type would be the generic type definition.
4030          */
4031         if (klass->generic_class)
4032                 klass = klass->generic_class->container_class;
4033
4034         mono_ptr_array_init (tmp_array, 1);
4035         iter = NULL;
4036         while ((nested = mono_class_get_nested_types (klass, &iter))) {
4037                 match = 0;
4038                 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4039                         if (bflags & BFLAGS_Public)
4040                                 match++;
4041                 } else {
4042                         if (bflags & BFLAGS_NonPublic)
4043                                 match++;
4044                 }
4045                 if (!match)
4046                         continue;
4047                 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4048                 mono_ptr_array_append (tmp_array, member);
4049         }
4050
4051         res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4052
4053         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4054                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4055
4056         mono_ptr_array_destroy (tmp_array);
4057
4058         return res;
4059 }
4060
4061 static MonoReflectionType*
4062 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4063 {
4064         gchar *str;
4065         MonoType *type = NULL;
4066         MonoTypeNameParse info;
4067         gboolean type_resolve;
4068
4069         MONO_ARCH_SAVE_REGS;
4070
4071         /* On MS.NET, this does not fire a TypeResolve event */
4072         type_resolve = TRUE;
4073         str = mono_string_to_utf8 (name);
4074         /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4075         if (!mono_reflection_parse_type (str, &info)) {
4076                 g_free (str);
4077                 mono_reflection_free_type_info (&info);
4078                 if (throwOnError) /* uhm: this is a parse error, though... */
4079                         mono_raise_exception (mono_get_exception_type_load (name, NULL));
4080                 /*g_print ("failed parse\n");*/
4081                 return NULL;
4082         }
4083
4084         if (info.assembly.name) {
4085                 g_free (str);
4086                 mono_reflection_free_type_info (&info);
4087                 if (throwOnError) {
4088                         /* 1.0 and 2.0 throw different exceptions */
4089                         if (mono_defaults.generic_ilist_class)
4090                                 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4091                         else
4092                                 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4093                 }
4094                 return NULL;
4095         }
4096
4097         if (module != NULL) {
4098                 if (module->image)
4099                         type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4100                 else
4101                         type = NULL;
4102         }
4103         else
4104                 if (assembly->assembly->dynamic) {
4105                         /* Enumerate all modules */
4106                         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4107                         int i;
4108
4109                         type = NULL;
4110                         if (abuilder->modules) {
4111                                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4112                                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4113                                         type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4114                                         if (type)
4115                                                 break;
4116                                 }
4117                         }
4118
4119                         if (!type && abuilder->loaded_modules) {
4120                                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4121                                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4122                                         type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4123                                         if (type)
4124                                                 break;
4125                                 }
4126                         }
4127                 }
4128                 else
4129                         type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4130         g_free (str);
4131         mono_reflection_free_type_info (&info);
4132         if (!type) {
4133                 MonoException *e = NULL;
4134                 
4135                 if (throwOnError)
4136                         e = mono_get_exception_type_load (name, NULL);
4137
4138                 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4139                         e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4140
4141                 mono_loader_clear_error ();
4142
4143                 if (e != NULL)
4144                         mono_raise_exception (e);
4145
4146                 return NULL;
4147         }
4148
4149         if (type->type == MONO_TYPE_CLASS) {
4150                 MonoClass *klass = mono_type_get_class (type);
4151
4152                 if (mono_is_security_manager_active () && !klass->exception_type)
4153                         /* Some security problems are detected during generic vtable construction */
4154                         mono_class_setup_vtable (klass);
4155                 /* need to report exceptions ? */
4156                 if (throwOnError && klass->exception_type) {
4157                         /* report SecurityException (or others) that occured when loading the assembly */
4158                         MonoException *exc = mono_class_get_exception_for_failure (klass);
4159                         mono_loader_clear_error ();
4160                         mono_raise_exception (exc);
4161                 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4162                         return NULL;
4163                 }
4164         }
4165
4166         /* g_print ("got it\n"); */
4167         return mono_type_get_object (mono_object_domain (assembly), type);
4168 }
4169
4170 static gboolean
4171 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4172 {
4173         gchar *content;
4174         gchar *shadow_ini_file;
4175         gsize len;
4176
4177         /* Check for shadow-copied assembly */
4178         if (mono_is_shadow_copy_enabled (domain, dirname)) {
4179                 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4180                 content = NULL;
4181                 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4182                         !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4183                         if (content) {
4184                                 g_free (content);
4185                                 content = NULL;
4186                         }
4187                 }
4188                 g_free (shadow_ini_file);
4189                 if (content != NULL) {
4190                         if (*filename)
4191                                 g_free (*filename);
4192                         *filename = content;
4193                         return TRUE;
4194                 }
4195         }
4196         return FALSE;
4197 }
4198
4199 static MonoString *
4200 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4201 {
4202         MonoDomain *domain = mono_object_domain (assembly); 
4203         MonoAssembly *mass = assembly->assembly;
4204         MonoString *res = NULL;
4205         gchar *uri;
4206         gchar *absolute;
4207         gchar *dirname;
4208         
4209         MONO_ARCH_SAVE_REGS;
4210
4211         if (g_path_is_absolute (mass->image->name)) {
4212                 absolute = g_strdup (mass->image->name);
4213                 dirname = g_path_get_dirname (absolute);
4214         } else {
4215                 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4216                 dirname = g_strdup (mass->basedir);
4217         }
4218
4219         replace_shadow_path (domain, dirname, &absolute);
4220         g_free (dirname);
4221 #if HOST_WIN32
4222         {
4223                 gint i;
4224                 for (i = strlen (absolute) - 1; i >= 0; i--)
4225                         if (absolute [i] == '\\')
4226                                 absolute [i] = '/';
4227         }
4228 #endif
4229         if (escaped) {
4230                 uri = g_filename_to_uri (absolute, NULL, NULL);
4231         } else {
4232                 const char *prepend = "file://";
4233 #if HOST_WIN32
4234                 if (*absolute == '/' && *(absolute + 1) == '/') {
4235                         prepend = "file:";
4236                 } else {
4237                         prepend = "file:///";
4238                 }
4239 #endif
4240                 uri = g_strconcat (prepend, absolute, NULL);
4241         }
4242
4243         if (uri) {
4244                 res = mono_string_new (domain, uri);
4245                 g_free (uri);
4246         }
4247         g_free (absolute);
4248         return res;
4249 }
4250
4251 static MonoBoolean
4252 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4253 {
4254         MonoAssembly *mass = assembly->assembly;
4255
4256         MONO_ARCH_SAVE_REGS;
4257
4258         return mass->in_gac;
4259 }
4260
4261 static MonoReflectionAssembly*
4262 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4263 {
4264         gchar *name;
4265         MonoAssembly *res;
4266         MonoImageOpenStatus status;
4267         
4268         MONO_ARCH_SAVE_REGS;
4269
4270         name = mono_string_to_utf8 (mname);
4271         res = mono_assembly_load_with_partial_name (name, &status);
4272
4273         g_free (name);
4274
4275         if (res == NULL)
4276                 return NULL;
4277         return mono_assembly_get_object (mono_domain_get (), res);
4278 }
4279
4280 static MonoString *
4281 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4282 {
4283         MonoDomain *domain = mono_object_domain (assembly); 
4284         MonoString *res;
4285
4286         MONO_ARCH_SAVE_REGS;
4287
4288         res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4289
4290         return res;
4291 }
4292
4293 static MonoBoolean
4294 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4295 {
4296         MONO_ARCH_SAVE_REGS;
4297
4298         return assembly->assembly->ref_only;
4299 }
4300
4301 static MonoString *
4302 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4303 {
4304         MonoDomain *domain = mono_object_domain (assembly); 
4305
4306         MONO_ARCH_SAVE_REGS;
4307
4308         return mono_string_new (domain, assembly->assembly->image->version);
4309 }
4310
4311 static MonoReflectionMethod*
4312 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly) 
4313 {
4314         guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4315
4316         MONO_ARCH_SAVE_REGS;
4317
4318         if (!token)
4319                 return NULL;
4320         return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4321 }
4322
4323 static MonoReflectionModule*
4324 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly) 
4325 {
4326         return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4327 }
4328
4329 static MonoArray*
4330 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly) 
4331 {
4332         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4333         MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4334         int i;
4335         const char *val;
4336
4337         MONO_ARCH_SAVE_REGS;
4338
4339         for (i = 0; i < table->rows; ++i) {
4340                 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4341                 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4342         }
4343         return result;
4344 }
4345
4346 static MonoObject*
4347 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4348 {
4349         static MonoClass *System_Version = NULL;
4350         static MonoMethod *create_version = NULL;
4351         MonoObject *result;
4352         gpointer args [4];
4353         
4354         if (!System_Version) {
4355                 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4356                 g_assert (System_Version);
4357         }
4358
4359         if (!create_version) {
4360                 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4361                 create_version = mono_method_desc_search_in_class (desc, System_Version);
4362                 g_assert (create_version);
4363                 mono_method_desc_free (desc);
4364         }
4365
4366         args [0] = &major;
4367         args [1] = &minor;
4368         args [2] = &build;
4369         args [3] = &revision;
4370         result = mono_object_new (domain, System_Version);
4371         mono_runtime_invoke (create_version, result, args, NULL);
4372
4373         return result;
4374 }
4375
4376 static MonoArray*
4377 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly) 
4378 {
4379         static MonoClass *System_Reflection_AssemblyName;
4380         MonoArray *result;
4381         MonoDomain *domain = mono_object_domain (assembly);
4382         int i, count = 0;
4383         static MonoMethod *create_culture = NULL;
4384         MonoImage *image = assembly->assembly->image;
4385         MonoTableInfo *t;
4386
4387         MONO_ARCH_SAVE_REGS;
4388
4389         if (!System_Reflection_AssemblyName)
4390                 System_Reflection_AssemblyName = mono_class_from_name (
4391                         mono_defaults.corlib, "System.Reflection", "AssemblyName");
4392
4393         t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4394         count = t->rows;
4395
4396         result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4397
4398         if (count > 0 && !create_culture) {
4399                 MonoMethodDesc *desc = mono_method_desc_new (
4400                         "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4401                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4402                 g_assert (create_culture);
4403                 mono_method_desc_free (desc);
4404         }
4405
4406         for (i = 0; i < count; i++) {
4407                 MonoReflectionAssemblyName *aname;
4408                 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4409
4410                 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4411
4412                 aname = (MonoReflectionAssemblyName *) mono_object_new (
4413                         domain, System_Reflection_AssemblyName);
4414
4415                 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4416
4417                 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4418                 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4419                 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4420                 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4421                 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4422                 aname->versioncompat = 1; /* SameMachine (default) */
4423                 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4424                 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4425
4426                 if (create_culture) {
4427                         gpointer args [2];
4428                         MonoBoolean assembly_ref = 1;
4429                         args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4430                         args [1] = &assembly_ref;
4431                         MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4432                 }
4433                 
4434                 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4435                         const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4436                         guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4437
4438                         if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4439                                 /* public key token isn't copied - the class library will 
4440                                 automatically generate it from the public key if required */
4441                                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4442                                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4443                         } else {
4444                                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4445                                 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4446                         }
4447                 } else {
4448                         MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4449                 }
4450                 
4451                 /* note: this function doesn't return the codebase on purpose (i.e. it can
4452                          be used under partial trust as path information isn't present). */
4453
4454                 mono_array_setref (result, i, aname);
4455         }
4456         return result;
4457 }
4458
4459 typedef struct {
4460         MonoArray *res;
4461         int idx;
4462 } NameSpaceInfo;
4463
4464 static void
4465 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4466 {
4467         MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4468
4469         mono_array_setref (info->res, info->idx, name);
4470         info->idx++;
4471 }
4472
4473 static MonoArray*
4474 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly) 
4475 {
4476         MonoImage *img = assembly->assembly->image;
4477         MonoArray *res;
4478         NameSpaceInfo info;
4479         int len;
4480
4481         MONO_ARCH_SAVE_REGS;
4482
4483         mono_image_lock (img);
4484         mono_image_init_name_cache (img);
4485
4486 RETRY_LEN:
4487         len = g_hash_table_size (img->name_cache);
4488         mono_image_unlock (img);
4489
4490         /*we can't create objects holding the image lock */
4491         res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4492
4493         mono_image_lock (img);
4494         /*len might have changed, create a new array*/
4495         if (len != g_hash_table_size (img->name_cache))
4496                 goto RETRY_LEN;
4497
4498         info.res = res;
4499         info.idx = 0;
4500         g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4501         mono_image_unlock (img);
4502
4503         return res;
4504 }
4505
4506 /* move this in some file in mono/util/ */
4507 static char *
4508 g_concat_dir_and_file (const char *dir, const char *file)
4509 {
4510         g_return_val_if_fail (dir != NULL, NULL);
4511         g_return_val_if_fail (file != NULL, NULL);
4512
4513         /*
4514          * If the directory name doesn't have a / on the end, we need
4515          * to add one so we get a proper path to the file
4516          */
4517         if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4518                 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4519         else
4520                 return g_strconcat (dir, file, NULL);
4521 }
4522
4523 static void *
4524 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module) 
4525 {
4526         char *n = mono_string_to_utf8 (name);
4527         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4528         guint32 i;
4529         guint32 cols [MONO_MANIFEST_SIZE];
4530         guint32 impl, file_idx;
4531         const char *val;
4532         MonoImage *module;
4533
4534         MONO_ARCH_SAVE_REGS;
4535
4536         for (i = 0; i < table->rows; ++i) {
4537                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4538                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4539                 if (strcmp (val, n) == 0)
4540                         break;
4541         }
4542         g_free (n);
4543         if (i == table->rows)
4544                 return NULL;
4545         /* FIXME */
4546         impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4547         if (impl) {
4548                 /*
4549                  * this code should only be called after obtaining the 
4550                  * ResourceInfo and handling the other cases.
4551                  */
4552                 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4553                 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4554
4555                 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4556                 if (!module)
4557                         return NULL;
4558         }
4559         else
4560                 module = assembly->assembly->image;
4561
4562         mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4563
4564         return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4565 }
4566
4567 static gboolean
4568 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4569 {
4570         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4571         int i;
4572         guint32 cols [MONO_MANIFEST_SIZE];
4573         guint32 file_cols [MONO_FILE_SIZE];
4574         const char *val;
4575         char *n;
4576
4577         MONO_ARCH_SAVE_REGS;
4578
4579         n = mono_string_to_utf8 (name);
4580         for (i = 0; i < table->rows; ++i) {
4581                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4582                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4583                 if (strcmp (val, n) == 0)
4584                         break;
4585         }
4586         g_free (n);
4587         if (i == table->rows)
4588                 return FALSE;
4589
4590         if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4591                 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4592         }
4593         else {
4594                 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4595                 case MONO_IMPLEMENTATION_FILE:
4596                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4597                         table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4598                         mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4599                         val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4600                         MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4601                         if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4602                                 info->location = 0;
4603                         else
4604                                 info->location = RESOURCE_LOCATION_EMBEDDED;
4605                         break;
4606
4607                 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4608                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4609                         mono_assembly_load_reference (assembly->assembly->image, i - 1);
4610                         if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4611                                 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4612                                 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4613                                 g_free (msg);
4614                                 mono_raise_exception (ex);
4615                         }
4616                         MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4617
4618                         /* Obtain info recursively */
4619                         ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4620                         info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4621                         break;
4622
4623                 case MONO_IMPLEMENTATION_EXP_TYPE:
4624                         g_assert_not_reached ();
4625                         break;
4626                 }
4627         }
4628
4629         return TRUE;
4630 }
4631
4632 static MonoObject*
4633 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules) 
4634 {
4635         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4636         MonoArray *result = NULL;
4637         int i, count;
4638         const char *val;
4639         char *n;
4640
4641         MONO_ARCH_SAVE_REGS;
4642
4643         /* check hash if needed */
4644         if (name) {
4645                 n = mono_string_to_utf8 (name);
4646                 for (i = 0; i < table->rows; ++i) {
4647                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4648                         if (strcmp (val, n) == 0) {
4649                                 MonoString *fn;
4650                                 g_free (n);
4651                                 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4652                                 fn = mono_string_new (mono_object_domain (assembly), n);
4653                                 g_free (n);
4654                                 return (MonoObject*)fn;
4655                         }
4656                 }
4657                 g_free (n);
4658                 return NULL;
4659         }
4660
4661         count = 0;
4662         for (i = 0; i < table->rows; ++i) {
4663                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4664                         count ++;
4665         }
4666
4667         result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4668
4669         count = 0;
4670         for (i = 0; i < table->rows; ++i) {
4671                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4672                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4673                         n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4674                         mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4675                         g_free (n);
4676                         count ++;
4677                 }
4678         }
4679         return (MonoObject*)result;
4680 }
4681
4682 static MonoArray*
4683 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4684 {
4685         MonoDomain *domain = mono_domain_get();
4686         MonoArray *res;
4687         MonoClass *klass;
4688         int i, j, file_count = 0;
4689         MonoImage **modules;
4690         guint32 module_count, real_module_count;
4691         MonoTableInfo *table;
4692         guint32 cols [MONO_FILE_SIZE];
4693         MonoImage *image = assembly->assembly->image;
4694
4695         g_assert (image != NULL);
4696         g_assert (!assembly->assembly->dynamic);
4697
4698         table = &image->tables [MONO_TABLE_FILE];
4699         file_count = table->rows;
4700
4701         modules = image->modules;
4702         module_count = image->module_count;
4703
4704         real_module_count = 0;
4705         for (i = 0; i < module_count; ++i)
4706                 if (modules [i])
4707                         real_module_count ++;
4708
4709         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4710         res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4711
4712         mono_array_setref (res, 0, mono_module_get_object (domain, image));
4713         j = 1;
4714         for (i = 0; i < module_count; ++i)
4715                 if (modules [i]) {
4716                         mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4717                         ++j;
4718                 }
4719
4720         for (i = 0; i < file_count; ++i, ++j) {
4721                 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4722                 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4723                         mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4724                 else {
4725                         MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4726                         if (!m) {
4727                                 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4728                                 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4729                         }
4730                         mono_array_setref (res, j, mono_module_get_object (domain, m));
4731                 }
4732         }
4733
4734         return res;
4735 }
4736
4737 static MonoReflectionMethod*
4738 ves_icall_GetCurrentMethod (void) 
4739 {
4740         MonoMethod *m = mono_method_get_last_managed ();
4741
4742         while (m->is_inflated)
4743                 m = ((MonoMethodInflated*)m)->declaring;
4744
4745         return mono_method_get_object (mono_domain_get (), m, NULL);
4746 }
4747
4748
4749 static MonoMethod*
4750 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4751 {
4752         int offset = -1, i;
4753         if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4754                 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4755                 //method is inflated, we should inflate it on the other class
4756                 MonoGenericContext ctx;
4757                 ctx.method_inst = inflated->context.method_inst;
4758                 ctx.class_inst = inflated->context.class_inst;
4759                 if (klass->generic_class)
4760                         ctx.class_inst = klass->generic_class->context.class_inst;
4761                 else if (klass->generic_container)
4762                         ctx.class_inst = klass->generic_container->context.class_inst;
4763                 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4764         }
4765
4766         mono_class_setup_methods (method->klass);
4767         if (method->klass->exception_type)
4768                 return NULL;
4769         for (i = 0; i < method->klass->method.count; ++i) {
4770                 if (method->klass->methods [i] == method) {
4771                         offset = i;
4772                         break;
4773                 }       
4774         }
4775         mono_class_setup_methods (klass);
4776         if (klass->exception_type)
4777                 return NULL;
4778         g_assert (offset >= 0 && offset < klass->method.count);
4779         return klass->methods [offset];
4780 }
4781
4782 static MonoReflectionMethod*
4783 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4784 {
4785         MonoClass *klass;
4786         if (type) {
4787                 klass = mono_class_from_mono_type (type);
4788                 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass)) 
4789                         return NULL;
4790                 if (method->klass != klass) {
4791                         method = mono_method_get_equivalent_method (method, klass);
4792                         if (!method)
4793                                 return NULL;
4794                 }
4795         } else
4796                 klass = method->klass;
4797         return mono_method_get_object (mono_domain_get (), method, klass);
4798 }
4799
4800 static MonoReflectionMethod*
4801 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4802 {
4803         return mono_method_get_object (mono_domain_get (), method, NULL);
4804 }
4805
4806 static MonoReflectionMethodBody*
4807 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4808 {
4809         return mono_method_body_get_object (mono_domain_get (), method);
4810 }
4811
4812 static MonoReflectionAssembly*
4813 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4814 {
4815         MonoMethod *dest = NULL;
4816
4817         MONO_ARCH_SAVE_REGS;
4818
4819         mono_stack_walk_no_il (get_executing, &dest);
4820         return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4821 }
4822
4823
4824 static MonoReflectionAssembly*
4825 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4826 {
4827         MonoDomain* domain = mono_domain_get ();
4828
4829         MONO_ARCH_SAVE_REGS;
4830
4831         if (!domain->entry_assembly)
4832                 return NULL;
4833
4834         return mono_assembly_get_object (domain, domain->entry_assembly);
4835 }
4836
4837 static MonoReflectionAssembly*
4838 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4839 {
4840         MonoMethod *m;
4841         MonoMethod *dest;
4842
4843         MONO_ARCH_SAVE_REGS;
4844
4845         dest = NULL;
4846         mono_stack_walk_no_il (get_executing, &dest);
4847         m = dest;
4848         mono_stack_walk_no_il (get_caller, &dest);
4849         if (!dest)
4850                 dest = m;
4851         return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4852 }
4853
4854 static MonoString *
4855 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4856                                        gboolean assembly_qualified)
4857 {
4858         MonoDomain *domain = mono_object_domain (object); 
4859         MonoTypeNameFormat format;
4860         MonoString *res;
4861         gchar *name;
4862
4863         MONO_ARCH_SAVE_REGS;
4864
4865         mono_class_init_or_throw (mono_class_from_mono_type (object->type));
4866
4867         if (full_name)
4868                 format = assembly_qualified ?
4869                         MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4870                         MONO_TYPE_NAME_FORMAT_FULL_NAME;
4871         else
4872                 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4873  
4874         name = mono_type_get_name_full (object->type, format);
4875         if (!name)
4876                 return NULL;
4877
4878         if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4879                 g_free (name);
4880                 return NULL;
4881         }
4882
4883         res = mono_string_new (domain, name);
4884         g_free (name);
4885
4886         return res;
4887 }
4888
4889 static int
4890 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4891 {
4892         MonoClass *klass = mono_class_from_mono_type (this->type);
4893         mono_class_init_or_throw (klass);
4894         return mono_security_core_clr_class_level (klass);
4895 }
4896
4897 static void
4898 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4899 {
4900         static MonoMethod *create_culture = NULL;
4901         gpointer args [2];
4902         guint32 pkey_len;
4903         const char *pkey_ptr;
4904         gchar *codebase;
4905         MonoBoolean assembly_ref = 0;
4906
4907         MONO_ARCH_SAVE_REGS;
4908
4909         MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4910         aname->major = name->major;
4911         aname->minor = name->minor;
4912         aname->build = name->build;
4913         aname->flags = name->flags;
4914         aname->revision = name->revision;
4915         aname->hashalg = name->hash_alg;
4916         aname->versioncompat = 1; /* SameMachine (default) */
4917
4918         if (by_default_version)
4919                 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4920
4921         codebase = NULL;
4922         if (absolute != NULL && *absolute != '\0') {
4923                 const gchar *prepend = "file://";
4924                 gchar *result;
4925
4926                 codebase = g_strdup (absolute);
4927
4928 #if HOST_WIN32
4929                 {
4930                         gint i;
4931                         for (i = strlen (codebase) - 1; i >= 0; i--)
4932                                 if (codebase [i] == '\\')
4933                                         codebase [i] = '/';
4934
4935                         if (*codebase == '/' && *(codebase + 1) == '/') {
4936                                 prepend = "file:";
4937                         } else {
4938                                 prepend = "file:///";
4939                         }
4940                 }
4941 #endif
4942                 result = g_strconcat (prepend, codebase, NULL);
4943                 g_free (codebase);
4944                 codebase = result;
4945         }
4946
4947         if (codebase) {
4948                 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4949                 g_free (codebase);
4950         }
4951
4952         if (!create_culture) {
4953                 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4954                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4955                 g_assert (create_culture);
4956                 mono_method_desc_free (desc);
4957         }
4958
4959         if (name->culture) {
4960                 args [0] = mono_string_new (domain, name->culture);
4961                 args [1] = &assembly_ref;
4962                 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4963         }
4964
4965         if (name->public_key) {
4966                 pkey_ptr = (char*)name->public_key;
4967                 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4968
4969                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4970                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4971                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4972         } else if (default_publickey) {
4973                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4974                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4975         }
4976
4977         /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4978         if (name->public_key_token [0]) {
4979                 int i, j;
4980                 char *p;
4981
4982                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4983                 p = mono_array_addr (aname->keyToken, char, 0);
4984
4985                 for (i = 0, j = 0; i < 8; i++) {
4986                         *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4987                         *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4988                         p++;
4989                 }
4990         } else if (default_token) {
4991                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4992         }
4993 }
4994
4995 static MonoString *
4996 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
4997 {
4998         MonoDomain *domain = mono_object_domain (assembly); 
4999         MonoAssembly *mass = assembly->assembly;
5000         MonoString *res;
5001         gchar *name;
5002
5003         name = g_strdup_printf (
5004                 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5005                 mass->aname.name,
5006                 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5007                 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5008                 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5009                 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5010
5011         res = mono_string_new (domain, name);
5012         g_free (name);
5013
5014         return res;
5015 }
5016
5017 static void
5018 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5019 {
5020         gchar *absolute;
5021         MonoAssembly *mass = assembly->assembly;
5022
5023         MONO_ARCH_SAVE_REGS;
5024
5025         if (g_path_is_absolute (mass->image->name)) {
5026                 fill_reflection_assembly_name (mono_object_domain (assembly),
5027                         aname, &mass->aname, mass->image->name, TRUE,
5028                         TRUE, TRUE);
5029                 return;
5030         }
5031         absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5032
5033         fill_reflection_assembly_name (mono_object_domain (assembly),
5034                 aname, &mass->aname, absolute, TRUE, TRUE,
5035                 TRUE);
5036
5037         g_free (absolute);
5038 }
5039
5040 static void
5041 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5042 {
5043         char *filename;
5044         MonoImageOpenStatus status = MONO_IMAGE_OK;
5045         gboolean res;
5046         MonoImage *image;
5047         MonoAssemblyName name;
5048         char *dirname
5049
5050         MONO_ARCH_SAVE_REGS;
5051
5052         filename = mono_string_to_utf8 (fname);
5053
5054         dirname = g_path_get_dirname (filename);
5055         replace_shadow_path (mono_domain_get (), dirname, &filename);
5056         g_free (dirname);
5057
5058         image = mono_image_open (filename, &status);
5059
5060         if (!image){
5061                 MonoException *exc;
5062
5063                 g_free (filename);
5064                 if (status == MONO_IMAGE_IMAGE_INVALID)
5065                         exc = mono_get_exception_bad_image_format2 (NULL, fname);
5066                 else
5067                         exc = mono_get_exception_file_not_found2 (NULL, fname);
5068                 mono_raise_exception (exc);
5069         }
5070
5071         res = mono_assembly_fill_assembly_name (image, &name);
5072         if (!res) {
5073                 mono_image_close (image);
5074                 g_free (filename);
5075                 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5076         }
5077
5078         fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5079                 TRUE, FALSE, TRUE);
5080
5081         g_free (filename);
5082         mono_image_close (image);
5083 }
5084
5085 static MonoBoolean
5086 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5087         char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5088 {
5089         MonoBoolean result = FALSE;
5090         MonoDeclSecurityEntry entry;
5091
5092         /* SecurityAction.RequestMinimum */
5093         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5094                 *minimum = entry.blob;
5095                 *minLength = entry.size;
5096                 result = TRUE;
5097         }
5098         /* SecurityAction.RequestOptional */
5099         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5100                 *optional = entry.blob;
5101                 *optLength = entry.size;
5102                 result = TRUE;
5103         }
5104         /* SecurityAction.RequestRefuse */
5105         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5106                 *refused = entry.blob;
5107                 *refLength = entry.size;
5108                 result = TRUE;
5109         }
5110
5111         return result;  
5112 }
5113
5114 static MonoArray*
5115 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5116 {
5117         MonoArray *res;
5118         MonoClass *klass;
5119         MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5120         int i, count;
5121         guint32 attrs, visibility;
5122
5123         /* we start the count from 1 because we skip the special type <Module> */
5124         if (exportedOnly) {
5125                 count = 0;
5126                 for (i = 1; i < tdef->rows; ++i) {
5127                         attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5128                         visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5129                         if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5130                                 count++;
5131                 }
5132         } else {
5133                 count = tdef->rows - 1;
5134         }
5135         res = mono_array_new (domain, mono_defaults.monotype_class, count);
5136         *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5137         count = 0;
5138         for (i = 1; i < tdef->rows; ++i) {
5139                 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5140                 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5141                 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5142                         klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5143                         if (klass) {
5144                                 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5145                         } else {
5146                                 MonoLoaderError *error;
5147                                 MonoException *ex;
5148                                 
5149                                 error = mono_loader_get_last_error ();
5150                                 g_assert (error != NULL);
5151         
5152                                 ex = mono_loader_error_prepare_exception (error);
5153                                 mono_array_setref (*exceptions, count, ex);
5154                         }
5155                         if (mono_loader_get_last_error ())
5156                                 mono_loader_clear_error ();
5157                         count++;
5158                 }
5159         }
5160         
5161         return res;
5162 }
5163
5164 static MonoArray*
5165 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5166 {
5167         MonoArray *res = NULL;
5168         MonoArray *exceptions = NULL;
5169         MonoImage *image = NULL;
5170         MonoTableInfo *table = NULL;
5171         MonoDomain *domain;
5172         GList *list = NULL;
5173         int i, len, ex_count;
5174
5175         MONO_ARCH_SAVE_REGS;
5176
5177         domain = mono_object_domain (assembly);
5178
5179         g_assert (!assembly->assembly->dynamic);
5180         image = assembly->assembly->image;
5181         table = &image->tables [MONO_TABLE_FILE];
5182         res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5183
5184         /* Append data from all modules in the assembly */
5185         for (i = 0; i < table->rows; ++i) {
5186                 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5187                         MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5188                         if (loaded_image) {
5189                                 MonoArray *ex2;
5190                                 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5191                                 /* Append the new types to the end of the array */
5192                                 if (mono_array_length (res2) > 0) {
5193                                         guint32 len1, len2;
5194                                         MonoArray *res3, *ex3;
5195
5196                                         len1 = mono_array_length (res);
5197                                         len2 = mono_array_length (res2);
5198
5199                                         res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5200                                         mono_array_memcpy_refs (res3, 0, res, 0, len1);
5201                                         mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5202                                         res = res3;
5203
5204                                         ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5205                                         mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5206                                         mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5207                                         exceptions = ex3;
5208                                 }
5209                         }
5210                 }
5211         }
5212
5213         /* the ReflectionTypeLoadException must have all the types (Types property), 
5214          * NULL replacing types which throws an exception. The LoaderException must
5215          * contain all exceptions for NULL items.
5216          */
5217
5218         len = mono_array_length (res);
5219
5220         ex_count = 0;
5221         for (i = 0; i < len; i++) {
5222                 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5223                 MonoClass *klass;
5224
5225                 if (t) {
5226                         klass = mono_type_get_class (t->type);
5227                         if ((klass != NULL) && klass->exception_type) {
5228                                 /* keep the class in the list */
5229                                 list = g_list_append (list, klass);
5230                                 /* and replace Type with NULL */
5231                                 mono_array_setref (res, i, NULL);
5232                         }
5233                 } else {
5234                         ex_count ++;
5235                 }
5236         }
5237
5238         if (list || ex_count) {
5239                 GList *tmp = NULL;
5240                 MonoException *exc = NULL;
5241                 MonoArray *exl = NULL;
5242                 int j, length = g_list_length (list) + ex_count;
5243
5244                 mono_loader_clear_error ();
5245
5246                 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5247                 /* Types for which mono_class_get () succeeded */
5248                 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5249                         MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5250                         mono_array_setref (exl, i, exc);
5251                 }
5252                 /* Types for which it don't */
5253                 for (j = 0; j < mono_array_length (exceptions); ++j) {
5254                         MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5255                         if (exc) {
5256                                 g_assert (i < length);
5257                                 mono_array_setref (exl, i, exc);
5258                                 i ++;
5259                         }
5260                 }
5261                 g_list_free (list);
5262                 list = NULL;
5263
5264                 exc = mono_get_exception_reflection_type_load (res, exl);
5265                 mono_loader_clear_error ();
5266                 mono_raise_exception (exc);
5267         }
5268                 
5269         return res;
5270 }
5271
5272 static gboolean
5273 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5274 {
5275         MonoAssemblyName aname;
5276         MonoDomain *domain = mono_object_domain (name);
5277         char *val;
5278         gboolean is_version_defined;
5279         gboolean is_token_defined;
5280
5281         aname.public_key = NULL;
5282         val = mono_string_to_utf8 (assname);
5283         if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5284                 g_free ((guint8*) aname.public_key);
5285                 g_free (val);
5286                 return FALSE;
5287         }
5288         
5289         fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5290                 FALSE, is_token_defined);
5291
5292         mono_assembly_name_free (&aname);
5293         g_free ((guint8*) aname.public_key);
5294         g_free (val);
5295
5296         return TRUE;
5297 }
5298
5299 static MonoReflectionType*
5300 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5301 {
5302         MonoDomain *domain = mono_object_domain (module); 
5303         MonoClass *klass;
5304
5305         MONO_ARCH_SAVE_REGS;
5306
5307         g_assert (module->image);
5308
5309         if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5310                 /* These images do not have a global type */
5311                 return NULL;
5312
5313         klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5314         return mono_type_get_object (domain, &klass->byval_arg);
5315 }
5316
5317 static void
5318 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5319 {
5320         /*if (module->image)
5321                 mono_image_close (module->image);*/
5322 }
5323
5324 static MonoString*
5325 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5326 {
5327         MonoDomain *domain = mono_object_domain (module); 
5328
5329         MONO_ARCH_SAVE_REGS;
5330
5331         g_assert (module->image);
5332         return mono_string_new (domain, module->image->guid);
5333 }
5334
5335 static gpointer
5336 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5337 {
5338 #ifdef HOST_WIN32
5339         if (module->image && module->image->is_module_handle)
5340                 return module->image->raw_data;
5341 #endif
5342
5343         return (gpointer) (-1);
5344 }
5345
5346 static void
5347 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5348 {
5349         if (image->dynamic) {
5350                 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5351                 *pe_kind = dyn->pe_kind;
5352                 *machine = dyn->machine;
5353         }
5354         else {
5355                 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5356                 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5357         }
5358 }
5359
5360 static gint32
5361 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5362 {
5363         return (image->md_version_major << 16) | (image->md_version_minor);
5364 }
5365
5366 static MonoArray*
5367 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5368 {
5369         MonoArray *exceptions;
5370         int i;
5371
5372         MONO_ARCH_SAVE_REGS;
5373
5374         if (!module->image)
5375                 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5376         else {
5377                 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5378                 for (i = 0; i < mono_array_length (exceptions); ++i) {
5379                         MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5380                         if (ex)
5381                                 mono_raise_exception (ex);
5382                 }
5383                 return res;
5384         }
5385 }
5386
5387 static gboolean
5388 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5389 {
5390         guint32 cols [MONO_MEMBERREF_SIZE];
5391         const char *sig;
5392         mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5393         sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5394         mono_metadata_decode_blob_size (sig, &sig);
5395         return (*sig != 0x6);
5396 }
5397
5398 static void
5399 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5400 {
5401         if (type_args)
5402                 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5403                                                                       mono_array_addr (type_args, MonoType*, 0));
5404         else
5405                 context->class_inst = NULL;
5406         if (method_args)
5407                 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5408                                                                        mono_array_addr (method_args, MonoType*, 0));
5409         else
5410                 context->method_inst = NULL;
5411 }
5412
5413 static MonoType*
5414 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5415 {
5416         MonoClass *klass;
5417         int table = mono_metadata_token_table (token);
5418         int index = mono_metadata_token_index (token);
5419         MonoGenericContext context;
5420
5421         *error = ResolveTokenError_Other;
5422
5423         /* Validate token */
5424         if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) && 
5425                 (table != MONO_TABLE_TYPESPEC)) {
5426                 *error = ResolveTokenError_BadTable;
5427                 return NULL;
5428         }
5429
5430         if (image->dynamic) {
5431                 if (type_args || method_args)
5432                         mono_raise_exception (mono_get_exception_not_implemented (NULL));
5433                 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5434                 if (!klass)
5435                         return NULL;
5436                 return &klass->byval_arg;
5437         }
5438
5439         if ((index <= 0) || (index > image->tables [table].rows)) {
5440                 *error = ResolveTokenError_OutOfRange;
5441                 return NULL;
5442         }
5443
5444         init_generic_context_from_args (&context, type_args, method_args);
5445         klass = mono_class_get_full (image, token, &context);
5446
5447         if (mono_loader_get_last_error ())
5448                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5449
5450         if (klass)
5451                 return &klass->byval_arg;
5452         else
5453                 return NULL;
5454 }
5455
5456 static MonoMethod*
5457 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5458 {
5459         int table = mono_metadata_token_table (token);
5460         int index = mono_metadata_token_index (token);
5461         MonoGenericContext context;
5462         MonoMethod *method;
5463
5464         *error = ResolveTokenError_Other;
5465
5466         /* Validate token */
5467         if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) && 
5468                 (table != MONO_TABLE_MEMBERREF)) {
5469                 *error = ResolveTokenError_BadTable;
5470                 return NULL;
5471         }
5472
5473         if (image->dynamic) {
5474                 if (type_args || method_args)
5475                         mono_raise_exception (mono_get_exception_not_implemented (NULL));
5476                 /* FIXME: validate memberref token type */
5477                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5478         }
5479
5480         if ((index <= 0) || (index > image->tables [table].rows)) {
5481                 *error = ResolveTokenError_OutOfRange;
5482                 return NULL;
5483         }
5484         if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5485                 *error = ResolveTokenError_BadTable;
5486                 return NULL;
5487         }
5488
5489         init_generic_context_from_args (&context, type_args, method_args);
5490         method = mono_get_method_full (image, token, NULL, &context);
5491
5492         if (mono_loader_get_last_error ())
5493                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5494
5495         return method;
5496 }
5497
5498 static MonoString*
5499 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5500 {
5501         int index = mono_metadata_token_index (token);
5502
5503         *error = ResolveTokenError_Other;
5504
5505         /* Validate token */
5506         if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5507                 *error = ResolveTokenError_BadTable;
5508                 return NULL;
5509         }
5510
5511         if (image->dynamic)
5512                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5513
5514         if ((index <= 0) || (index >= image->heap_us.size)) {
5515                 *error = ResolveTokenError_OutOfRange;
5516                 return NULL;
5517         }
5518
5519         /* FIXME: What to do if the index points into the middle of a string ? */
5520
5521         return mono_ldstr (mono_domain_get (), image, index);
5522 }
5523
5524 static MonoClassField*
5525 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5526 {
5527         MonoClass *klass;
5528         int table = mono_metadata_token_table (token);
5529         int index = mono_metadata_token_index (token);
5530         MonoGenericContext context;
5531         MonoClassField *field;
5532
5533         *error = ResolveTokenError_Other;
5534
5535         /* Validate token */
5536         if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5537                 *error = ResolveTokenError_BadTable;
5538                 return NULL;
5539         }
5540
5541         if (image->dynamic) {
5542                 if (type_args || method_args)
5543                         mono_raise_exception (mono_get_exception_not_implemented (NULL));
5544                 /* FIXME: validate memberref token type */
5545                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5546         }
5547
5548         if ((index <= 0) || (index > image->tables [table].rows)) {
5549                 *error = ResolveTokenError_OutOfRange;
5550                 return NULL;
5551         }
5552         if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5553                 *error = ResolveTokenError_BadTable;
5554                 return NULL;
5555         }
5556
5557         init_generic_context_from_args (&context, type_args, method_args);
5558         field = mono_field_from_token (image, token, &klass, &context);
5559
5560         if (mono_loader_get_last_error ())
5561                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5562         
5563         return field;
5564 }
5565
5566
5567 static MonoObject*
5568 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5569 {
5570         int table = mono_metadata_token_table (token);
5571
5572         *error = ResolveTokenError_Other;
5573
5574         switch (table) {
5575         case MONO_TABLE_TYPEDEF:
5576         case MONO_TABLE_TYPEREF:
5577         case MONO_TABLE_TYPESPEC: {
5578                 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5579                 if (t)
5580                         return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5581                 else
5582                         return NULL;
5583         }
5584         case MONO_TABLE_METHOD:
5585         case MONO_TABLE_METHODSPEC: {
5586                 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5587                 if (m)
5588                         return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5589                 else
5590                         return NULL;
5591         }               
5592         case MONO_TABLE_FIELD: {
5593                 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5594                 if (f)
5595                         return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5596                 else
5597                         return NULL;
5598         }
5599         case MONO_TABLE_MEMBERREF:
5600                 if (mono_metadata_memberref_is_method (image, token)) {
5601                         MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5602                         if (m)
5603                                 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5604                         else
5605                                 return NULL;
5606                 }
5607                 else {
5608                         MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5609                         if (f)
5610                                 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5611                         else
5612                                 return NULL;
5613                 }
5614                 break;
5615
5616         default:
5617                 *error = ResolveTokenError_BadTable;
5618         }
5619
5620         return NULL;
5621 }
5622
5623 static MonoArray*
5624 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5625 {
5626         int table = mono_metadata_token_table (token);
5627         int idx = mono_metadata_token_index (token);
5628         MonoTableInfo *tables = image->tables;
5629         guint32 sig, len;
5630         const char *ptr;
5631         MonoArray *res;
5632
5633         *error = ResolveTokenError_OutOfRange;
5634
5635         /* FIXME: Support other tables ? */
5636         if (table != MONO_TABLE_STANDALONESIG)
5637                 return NULL;
5638
5639         if (image->dynamic)
5640                 return NULL;
5641
5642         if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5643                 return NULL;
5644
5645         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5646
5647         ptr = mono_metadata_blob_heap (image, sig);
5648         len = mono_metadata_decode_blob_size (ptr, &ptr);
5649
5650         res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5651         memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5652         return res;
5653 }
5654
5655 static MonoReflectionType*
5656 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5657 {
5658         MonoClass *klass;
5659         int isbyref = 0, rank;
5660         char *str = mono_string_to_utf8 (smodifiers);
5661         char *p;
5662
5663         MONO_ARCH_SAVE_REGS;
5664
5665         klass = mono_class_from_mono_type (tb->type.type);
5666         p = str;
5667         /* logic taken from mono_reflection_parse_type(): keep in sync */
5668         while (*p) {
5669                 switch (*p) {
5670                 case '&':
5671                         if (isbyref) { /* only one level allowed by the spec */
5672                                 g_free (str);
5673                                 return NULL;
5674                         }
5675                         isbyref = 1;
5676                         p++;
5677                         g_free (str);
5678                         return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5679                         break;
5680                 case '*':
5681                         klass = mono_ptr_class_get (&klass->byval_arg);
5682                         mono_class_init (klass);
5683                         p++;
5684                         break;
5685                 case '[':
5686                         rank = 1;
5687                         p++;
5688                         while (*p) {
5689                                 if (*p == ']')
5690                                         break;
5691                                 if (*p == ',')
5692                                         rank++;
5693                                 else if (*p != '*') { /* '*' means unknown lower bound */
5694                                         g_free (str);
5695                                         return NULL;
5696                                 }
5697                                 ++p;
5698                         }
5699                         if (*p != ']') {
5700                                 g_free (str);
5701                                 return NULL;
5702                         }
5703                         p++;
5704                         klass = mono_array_class_get (klass, rank);
5705                         mono_class_init (klass);
5706                         break;
5707                 default:
5708                         break;
5709                 }
5710         }
5711         g_free (str);
5712         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5713 }
5714
5715 static MonoBoolean
5716 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5717 {
5718         MonoType *type;
5719         MonoBoolean res;
5720
5721         MONO_ARCH_SAVE_REGS;
5722
5723         type = t->type;
5724         res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5725
5726         return res;
5727 }
5728
5729 static MonoReflectionType *
5730 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5731 {
5732         MonoClass *klass, *aklass;
5733
5734         MONO_ARCH_SAVE_REGS;
5735
5736         klass = mono_class_from_mono_type (type->type);
5737         mono_class_init_or_throw (klass);
5738
5739         if (rank == 0) //single dimentional array
5740                 aklass = mono_array_class_get (klass, 1);
5741         else
5742                 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5743
5744         return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5745 }
5746
5747 static MonoReflectionType *
5748 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5749 {
5750         MonoClass *klass;
5751
5752         MONO_ARCH_SAVE_REGS;
5753
5754         klass = mono_class_from_mono_type (type->type);
5755         mono_class_init_or_throw (klass);
5756
5757         return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5758 }
5759
5760 static MonoReflectionType *
5761 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5762 {
5763         MonoClass *pklass;
5764
5765         mono_class_init_or_throw (mono_class_from_mono_type (type->type));
5766
5767         pklass = mono_ptr_class_get (type->type);
5768
5769         return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5770 }
5771
5772 static MonoObject *
5773 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5774                                                    MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5775 {
5776         MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5777         MonoObject *delegate;
5778         gpointer func;
5779         MonoMethod *method = info->method;
5780
5781         MONO_ARCH_SAVE_REGS;
5782
5783         mono_class_init_or_throw (delegate_class);
5784
5785         mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5786
5787         if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5788                 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5789                         return NULL;
5790         }
5791
5792         delegate = mono_object_new (mono_object_domain (type), delegate_class);
5793
5794         if (method->dynamic) {
5795                 /* Creating a trampoline would leak memory */
5796                 func = mono_compile_method (method);
5797         } else {
5798                 func = mono_create_ftnptr (mono_domain_get (),
5799                         mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5800         }
5801
5802         mono_delegate_ctor_with_method (delegate, target, func, method);
5803
5804         return delegate;
5805 }
5806
5807 static void
5808 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5809 {
5810         /* Reset the invoke impl to the default one */
5811         this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5812 }
5813
5814 /*
5815  * Magic number to convert a time which is relative to
5816  * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5817  */
5818 #define EPOCH_ADJUST    ((guint64)62135596800LL)
5819
5820 /*
5821  * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5822  */
5823 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5824
5825 #ifdef HOST_WIN32
5826 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5827 static void
5828 convert_to_absolute_date(SYSTEMTIME *date)
5829 {
5830 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5831         static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5832         static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5833         /* from the calendar FAQ */
5834         int a = (14 - date->wMonth) / 12;
5835         int y = date->wYear - a;
5836         int m = date->wMonth + 12 * a - 2;
5837         int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5838
5839         /* d is now the day of the week for the first of the month (0 == Sunday) */
5840
5841         int day_of_week = date->wDayOfWeek;
5842
5843         /* set day_in_month to the first day in the month which falls on day_of_week */    
5844         int day_in_month = 1 + (day_of_week - d);
5845         if (day_in_month <= 0)
5846                 day_in_month += 7;
5847
5848         /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5849         date->wDay = day_in_month + (date->wDay - 1) * 7;
5850         if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5851                 date->wDay -= 7;
5852 }
5853 #endif
5854
5855 #ifndef HOST_WIN32
5856 /*
5857  * Return's the offset from GMT of a local time.
5858  * 
5859  *  tm is a local time
5860  *  t  is the same local time as seconds.
5861  */
5862 static int 
5863 gmt_offset(struct tm *tm, time_t t)
5864 {
5865 #if defined (HAVE_TM_GMTOFF)
5866         return tm->tm_gmtoff;
5867 #else
5868         struct tm g;
5869         time_t t2;
5870         g = *gmtime(&t);
5871         g.tm_isdst = tm->tm_isdst;
5872         t2 = mktime(&g);
5873         return (int)difftime(t, t2);
5874 #endif
5875 }
5876 #endif
5877 /*
5878  * This is heavily based on zdump.c from glibc 2.2.
5879  *
5880  *  * data[0]:  start of daylight saving time (in DateTime ticks).
5881  *  * data[1]:  end of daylight saving time (in DateTime ticks).
5882  *  * data[2]:  utcoffset (in TimeSpan ticks).
5883  *  * data[3]:  additional offset when daylight saving (in TimeSpan ticks).
5884  *  * name[0]:  name of this timezone when not daylight saving.
5885  *  * name[1]:  name of this timezone when daylight saving.
5886  *
5887  *  FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5888  *         the class library allows years between 1 and 9999.
5889  *
5890  *  Returns true on success and zero on failure.
5891  */
5892 static guint32
5893 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5894 {
5895 #ifndef HOST_WIN32
5896         MonoDomain *domain = mono_domain_get ();
5897         struct tm start, tt;
5898         time_t t;
5899
5900         long int gmtoff;
5901         int is_daylight = 0, day;
5902         char tzone [64];
5903
5904         MONO_ARCH_SAVE_REGS;
5905
5906         MONO_CHECK_ARG_NULL (data);
5907         MONO_CHECK_ARG_NULL (names);
5908
5909         mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5910         mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5911
5912         /* 
5913          * no info is better than crashing: we'll need our own tz data
5914          * to make this work properly, anyway. The range is probably
5915          * reduced to 1970 .. 2037 because that is what mktime is
5916          * guaranteed to support (we get into an infinite loop
5917          * otherwise).
5918          */
5919
5920         memset (&start, 0, sizeof (start));
5921
5922         start.tm_mday = 1;
5923         start.tm_year = year-1900;
5924
5925         t = mktime (&start);
5926
5927         if ((year < 1970) || (year > 2037) || (t == -1)) {
5928                 t = time (NULL);
5929                 tt = *localtime (&t);
5930                 strftime (tzone, sizeof (tzone), "%Z", &tt);
5931                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5932                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5933                 return 1;
5934         }
5935
5936         gmtoff = gmt_offset (&start, t);
5937
5938         /* For each day of the year, calculate the tm_gmtoff. */
5939         for (day = 0; day < 365; day++) {
5940
5941                 t += 3600*24;
5942                 tt = *localtime (&t);
5943
5944                 /* Daylight saving starts or ends here. */
5945                 if (gmt_offset (&tt, t) != gmtoff) {
5946                         struct tm tt1;
5947                         time_t t1;
5948
5949                         /* Try to find the exact hour when daylight saving starts/ends. */
5950                         t1 = t;
5951                         do {
5952                                 t1 -= 3600;
5953                                 tt1 = *localtime (&t1);
5954                         } while (gmt_offset (&tt1, t1) != gmtoff);
5955
5956                         /* Try to find the exact minute when daylight saving starts/ends. */
5957                         do {
5958                                 t1 += 60;
5959                                 tt1 = *localtime (&t1);
5960                         } while (gmt_offset (&tt1, t1) == gmtoff);
5961                         t1+=gmtoff;
5962                         strftime (tzone, sizeof (tzone), "%Z", &tt);
5963                         
5964                         /* Write data, if we're already in daylight saving, we're done. */
5965                         if (is_daylight) {
5966                                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5967                                 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5968                                 return 1;
5969                         } else {
5970                                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5971                                 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5972                                 is_daylight = 1;
5973                         }
5974
5975                         /* This is only set once when we enter daylight saving. */
5976                         mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
5977                         mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
5978
5979                         gmtoff = gmt_offset (&tt, t);
5980                 }
5981         }
5982
5983         if (!is_daylight) {
5984                 strftime (tzone, sizeof (tzone), "%Z", &tt);
5985                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5986                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5987                 mono_array_set ((*data), gint64, 0, 0);
5988                 mono_array_set ((*data), gint64, 1, 0);
5989                 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
5990                 mono_array_set ((*data), gint64, 3, 0);
5991         }
5992
5993         return 1;
5994 #else
5995         MonoDomain *domain = mono_domain_get ();
5996         TIME_ZONE_INFORMATION tz_info;
5997         FILETIME ft;
5998         int i;
5999         int err, tz_id;
6000
6001         tz_id = GetTimeZoneInformation (&tz_info);
6002         if (tz_id == TIME_ZONE_ID_INVALID)
6003                 return 0;
6004
6005         MONO_CHECK_ARG_NULL (data);
6006         MONO_CHECK_ARG_NULL (names);
6007
6008         mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6009         mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6010
6011         for (i = 0; i < 32; ++i)
6012                 if (!tz_info.DaylightName [i])
6013                         break;
6014         mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6015         for (i = 0; i < 32; ++i)
6016                 if (!tz_info.StandardName [i])
6017                         break;
6018         mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6019
6020         if ((year <= 1601) || (year > 30827)) {
6021                 /*
6022                  * According to MSDN, the MS time functions can't handle dates outside
6023                  * this interval.
6024                  */
6025                 return 1;
6026         }
6027
6028         /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6029         if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6030                 tz_info.StandardDate.wYear = year;
6031                 convert_to_absolute_date(&tz_info.StandardDate);
6032                 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6033                 //g_assert(err);
6034                 if (err == 0)
6035                         return 0;
6036                 
6037                 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6038                 tz_info.DaylightDate.wYear = year;
6039                 convert_to_absolute_date(&tz_info.DaylightDate);
6040                 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6041                 //g_assert(err);
6042                 if (err == 0)
6043                         return 0;
6044                 
6045                 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6046         }
6047         mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6048         mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6049
6050         return 1;
6051 #endif
6052 }
6053
6054 static gpointer
6055 ves_icall_System_Object_obj_address (MonoObject *this) 
6056 {
6057         MONO_ARCH_SAVE_REGS;
6058
6059         return this;
6060 }
6061
6062 /* System.Buffer */
6063
6064 static inline gint32 
6065 mono_array_get_byte_length (MonoArray *array)
6066 {
6067         MonoClass *klass;
6068         int length;
6069         int i;
6070
6071         klass = array->obj.vtable->klass;
6072
6073         if (array->bounds == NULL)
6074                 length = array->max_length;
6075         else {
6076                 length = 1;
6077                 for (i = 0; i < klass->rank; ++ i)
6078                         length *= array->bounds [i].length;
6079         }
6080
6081         switch (klass->element_class->byval_arg.type) {
6082         case MONO_TYPE_I1:
6083         case MONO_TYPE_U1:
6084         case MONO_TYPE_BOOLEAN:
6085                 return length;
6086         case MONO_TYPE_I2:
6087         case MONO_TYPE_U2:
6088         case MONO_TYPE_CHAR:
6089                 return length << 1;
6090         case MONO_TYPE_I4:
6091         case MONO_TYPE_U4:
6092         case MONO_TYPE_R4:
6093                 return length << 2;
6094         case MONO_TYPE_I:
6095         case MONO_TYPE_U:
6096                 return length * sizeof (gpointer);
6097         case MONO_TYPE_I8:
6098         case MONO_TYPE_U8:
6099         case MONO_TYPE_R8:
6100                 return length << 3;
6101         default:
6102                 return -1;
6103         }
6104 }
6105
6106 static gint32 
6107 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array) 
6108 {
6109         MONO_ARCH_SAVE_REGS;
6110
6111         return mono_array_get_byte_length (array);
6112 }
6113
6114 static gint8 
6115 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx) 
6116 {
6117         MONO_ARCH_SAVE_REGS;
6118
6119         return mono_array_get (array, gint8, idx);
6120 }
6121
6122 static void 
6123 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value) 
6124 {
6125         MONO_ARCH_SAVE_REGS;
6126
6127         mono_array_set (array, gint8, idx, value);
6128 }
6129
6130 static MonoBoolean
6131 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count) 
6132 {
6133         guint8 *src_buf, *dest_buf;
6134
6135         MONO_ARCH_SAVE_REGS;
6136
6137         /* watch out for integer overflow */
6138         if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6139                 return FALSE;
6140
6141         src_buf = (guint8 *)src->vector + src_offset;
6142         dest_buf = (guint8 *)dest->vector + dest_offset;
6143
6144         if (src != dest)
6145                 memcpy (dest_buf, src_buf, count);
6146         else
6147                 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6148
6149         return TRUE;
6150 }
6151
6152 static MonoObject *
6153 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6154 {
6155         MonoDomain *domain = mono_object_domain (this); 
6156         MonoObject *res;
6157         MonoRealProxy *rp = ((MonoRealProxy *)this);
6158         MonoTransparentProxy *tp;
6159         MonoType *type;
6160         MonoClass *klass;
6161
6162         MONO_ARCH_SAVE_REGS;
6163
6164         res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6165         tp = (MonoTransparentProxy*) res;
6166         
6167         MONO_OBJECT_SETREF (tp, rp, rp);
6168         type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6169         klass = mono_class_from_mono_type (type);
6170
6171         tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6172         tp->remote_class = mono_remote_class (domain, class_name, klass);
6173
6174         res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6175         return res;
6176 }
6177
6178 static MonoReflectionType *
6179 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6180 {
6181         return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6182 }
6183
6184 /* System.Environment */
6185
6186 MonoString*
6187 ves_icall_System_Environment_get_UserName (void)
6188 {
6189         MONO_ARCH_SAVE_REGS;
6190
6191         /* using glib is more portable */
6192         return mono_string_new (mono_domain_get (), g_get_user_name ());
6193 }
6194
6195
6196 static MonoString *
6197 ves_icall_System_Environment_get_MachineName (void)
6198 {
6199 #if defined (HOST_WIN32)
6200         gunichar2 *buf;
6201         guint32 len;
6202         MonoString *result;
6203
6204         len = MAX_COMPUTERNAME_LENGTH + 1;
6205         buf = g_new (gunichar2, len);
6206
6207         result = NULL;
6208         if (GetComputerName (buf, (PDWORD) &len))
6209                 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6210
6211         g_free (buf);
6212         return result;
6213 #elif !defined(DISABLE_SOCKETS)
6214         gchar buf [256];
6215         MonoString *result;
6216
6217         if (gethostname (buf, sizeof (buf)) == 0)
6218                 result = mono_string_new (mono_domain_get (), buf);
6219         else
6220                 result = NULL;
6221         
6222         return result;
6223 #else
6224         return mono_string_new (mono_domain_get (), "mono");
6225 #endif
6226 }
6227
6228 static int
6229 ves_icall_System_Environment_get_Platform (void)
6230 {
6231 #if defined (TARGET_WIN32)
6232         /* Win32NT */
6233         return 2;
6234 #elif defined(__MACH__)
6235         /* OSX */
6236         //
6237         // For compatibility with our client code, this will be 4 for a while.
6238         // We will eventually move to 6 to match .NET, but it requires all client
6239         // code to be updated and the documentation everywhere to be updated 
6240         // first.
6241         //
6242         return 4;
6243 #else
6244         /* Unix */
6245         return 4;
6246 #endif
6247 }
6248
6249 static MonoString *
6250 ves_icall_System_Environment_get_NewLine (void)
6251 {
6252         MONO_ARCH_SAVE_REGS;
6253
6254 #if defined (HOST_WIN32)
6255         return mono_string_new (mono_domain_get (), "\r\n");
6256 #else
6257         return mono_string_new (mono_domain_get (), "\n");
6258 #endif
6259 }
6260
6261 static MonoString *
6262 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6263 {
6264         const gchar *value;
6265         gchar *utf8_name;
6266
6267         MONO_ARCH_SAVE_REGS;
6268
6269         if (name == NULL)
6270                 return NULL;
6271
6272         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6273         value = g_getenv (utf8_name);
6274
6275         g_free (utf8_name);
6276
6277         if (value == 0)
6278                 return NULL;
6279         
6280         return mono_string_new (mono_domain_get (), value);
6281 }
6282
6283 /*
6284  * There is no standard way to get at environ.
6285  */
6286 #ifndef _MSC_VER
6287 #ifndef __MINGW32_VERSION
6288 #ifdef __APPLE__
6289 /* Apple defines this in crt_externs.h but doesn't provide that header for 
6290  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
6291  * in fact exist on all implementations (so far) 
6292  */
6293 gchar ***_NSGetEnviron(void);
6294 #define environ (*_NSGetEnviron())
6295 #else
6296 extern
6297 char **environ;
6298 #endif
6299 #endif
6300 #endif
6301
6302 static MonoArray *
6303 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6304 {
6305 #ifdef HOST_WIN32
6306         MonoArray *names;
6307         MonoDomain *domain;
6308         MonoString *str;
6309         WCHAR* env_strings;
6310         WCHAR* env_string;
6311         WCHAR* equal_str;
6312         int n = 0;
6313
6314         env_strings = GetEnvironmentStrings();
6315
6316         if (env_strings) {
6317                 env_string = env_strings;
6318                 while (*env_string != '\0') {
6319                 /* weird case that MS seems to skip */
6320                         if (*env_string != '=')
6321                                 n++;
6322                         while (*env_string != '\0')
6323                                 env_string++;
6324                         env_string++;
6325                 }
6326         }
6327
6328         domain = mono_domain_get ();
6329         names = mono_array_new (domain, mono_defaults.string_class, n);
6330
6331         if (env_strings) {
6332                 n = 0;
6333                 env_string = env_strings;
6334                 while (*env_string != '\0') {
6335                         /* weird case that MS seems to skip */
6336                         if (*env_string != '=') {
6337                                 equal_str = wcschr(env_string, '=');
6338                                 g_assert(equal_str);
6339                                 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6340                                 mono_array_setref (names, n, str);
6341                                 n++;
6342                         }
6343                         while (*env_string != '\0')
6344                                 env_string++;
6345                         env_string++;
6346                 }
6347
6348                 FreeEnvironmentStrings (env_strings);
6349         }
6350
6351         return names;
6352
6353 #else
6354         MonoArray *names;
6355         MonoDomain *domain;
6356         MonoString *str;
6357         gchar **e, **parts;
6358         int n;
6359
6360         MONO_ARCH_SAVE_REGS;
6361
6362         n = 0;
6363         for (e = environ; *e != 0; ++ e)
6364                 ++ n;
6365
6366         domain = mono_domain_get ();
6367         names = mono_array_new (domain, mono_defaults.string_class, n);
6368
6369         n = 0;
6370         for (e = environ; *e != 0; ++ e) {
6371                 parts = g_strsplit (*e, "=", 2);
6372                 if (*parts != 0) {
6373                         str = mono_string_new (domain, *parts);
6374                         mono_array_setref (names, n, str);
6375                 }
6376
6377                 g_strfreev (parts);
6378
6379                 ++ n;
6380         }
6381
6382         return names;
6383 #endif
6384 }
6385
6386 /*
6387  * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6388  */
6389 #if !GLIB_CHECK_VERSION(2,4,0)
6390 #define g_setenv(a,b,c)   setenv(a,b,c)
6391 #define g_unsetenv(a) unsetenv(a)
6392 #endif
6393
6394 static void
6395 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6396 {
6397         MonoError error;
6398 #ifdef HOST_WIN32
6399
6400         gunichar2 *utf16_name, *utf16_value;
6401 #else
6402         gchar *utf8_name, *utf8_value;
6403 #endif
6404
6405         MONO_ARCH_SAVE_REGS;
6406         
6407 #ifdef HOST_WIN32
6408         utf16_name = mono_string_to_utf16 (name);
6409         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6410                 SetEnvironmentVariable (utf16_name, NULL);
6411                 g_free (utf16_name);
6412                 return;
6413         }
6414
6415         utf16_value = mono_string_to_utf16 (value);
6416
6417         SetEnvironmentVariable (utf16_name, utf16_value);
6418
6419         g_free (utf16_name);
6420         g_free (utf16_value);
6421 #else
6422         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6423
6424         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6425                 g_unsetenv (utf8_name);
6426                 g_free (utf8_name);
6427                 return;
6428         }
6429
6430         utf8_value = mono_string_to_utf8_checked (value, &error);
6431         if (!mono_error_ok (&error)) {
6432                 g_free (utf8_name);
6433                 mono_error_raise_exception (&error);
6434         }
6435         g_setenv (utf8_name, utf8_value, TRUE);
6436
6437         g_free (utf8_name);
6438         g_free (utf8_value);
6439 #endif
6440 }
6441
6442 static void
6443 ves_icall_System_Environment_Exit (int result)
6444 {
6445         MONO_ARCH_SAVE_REGS;
6446
6447         mono_threads_set_shutting_down ();
6448
6449         mono_runtime_set_shutting_down ();
6450
6451         /* This will kill the tp threads which cannot be suspended */
6452         mono_thread_pool_cleanup ();
6453
6454         /* Suspend all managed threads since the runtime is going away */
6455         mono_thread_suspend_all_other_threads ();
6456
6457         mono_runtime_quit ();
6458
6459         /* we may need to do some cleanup here... */
6460         exit (result);
6461 }
6462
6463 static MonoString*
6464 ves_icall_System_Environment_GetGacPath (void)
6465 {
6466         return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6467 }
6468
6469 static MonoString*
6470 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6471 {
6472 #if defined (HOST_WIN32)
6473         #ifndef CSIDL_FLAG_CREATE
6474                 #define CSIDL_FLAG_CREATE       0x8000
6475         #endif
6476
6477         WCHAR path [MAX_PATH];
6478         /* Create directory if no existing */
6479         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6480                 int len = 0;
6481                 while (path [len])
6482                         ++ len;
6483                 return mono_string_new_utf16 (mono_domain_get (), path, len);
6484         }
6485 #else
6486         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6487 #endif
6488         return mono_string_new (mono_domain_get (), "");
6489 }
6490
6491 static MonoArray *
6492 ves_icall_System_Environment_GetLogicalDrives (void)
6493 {
6494         gunichar2 buf [128], *ptr, *dname;
6495         gunichar2 *u16;
6496         guint initial_size = 127, size = 128;
6497         gint ndrives;
6498         MonoArray *result;
6499         MonoString *drivestr;
6500         MonoDomain *domain = mono_domain_get ();
6501         gint len;
6502
6503         MONO_ARCH_SAVE_REGS;
6504
6505         buf [0] = '\0';
6506         ptr = buf;
6507
6508         while (size > initial_size) {
6509                 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6510                 if (size > initial_size) {
6511                         if (ptr != buf)
6512                                 g_free (ptr);
6513                         ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6514                         initial_size = size;
6515                         size++;
6516                 }
6517         }
6518
6519         /* Count strings */
6520         dname = ptr;
6521         ndrives = 0;
6522         do {
6523                 while (*dname++);
6524                 ndrives++;
6525         } while (*dname);
6526
6527         dname = ptr;
6528         result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6529         ndrives = 0;
6530         do {
6531                 len = 0;
6532                 u16 = dname;
6533                 while (*u16) { u16++; len ++; }
6534                 drivestr = mono_string_new_utf16 (domain, dname, len);
6535                 mono_array_setref (result, ndrives++, drivestr);
6536                 while (*dname++);
6537         } while (*dname);
6538
6539         if (ptr != buf)
6540                 g_free (ptr);
6541
6542         return result;
6543 }
6544
6545 static MonoString *
6546 ves_icall_System_Environment_InternalGetHome (void)
6547 {
6548         MONO_ARCH_SAVE_REGS;
6549
6550         return mono_string_new (mono_domain_get (), g_get_home_dir ());
6551 }
6552
6553 static const char *encodings [] = {
6554         (char *) 1,
6555                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6556                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6557                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6558         (char *) 2,
6559                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6560                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6561                 "x_unicode_2_0_utf_7",
6562         (char *) 3,
6563                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6564                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6565         (char *) 4,
6566                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6567                 "iso_10646_ucs2",
6568         (char *) 5,
6569                 "unicodefffe", "utf_16be",
6570         (char *) 6,
6571                 "iso_8859_1",
6572         (char *) 0
6573 };
6574
6575 /*
6576  * Returns the internal codepage, if the value of "int_code_page" is
6577  * 1 at entry, and we can not compute a suitable code page number,
6578  * returns the code page as a string
6579  */
6580 static MonoString*
6581 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page) 
6582 {
6583         const char *cset;
6584         const char *p;
6585         char *c;
6586         char *codepage = NULL;
6587         int code;
6588         int want_name = *int_code_page;
6589         int i;
6590         
6591         *int_code_page = -1;
6592         MONO_ARCH_SAVE_REGS;
6593
6594         g_get_charset (&cset);
6595         c = codepage = strdup (cset);
6596         for (c = codepage; *c; c++){
6597                 if (isascii (*c) && isalpha (*c))
6598                         *c = tolower (*c);
6599                 if (*c == '-')
6600                         *c = '_';
6601         }
6602         /* g_print ("charset: %s\n", cset); */
6603         
6604         /* handle some common aliases */
6605         p = encodings [0];
6606         code = 0;
6607         for (i = 0; p != 0; ){
6608                 if ((gssize) p < 7){
6609                         code = (gssize) p;
6610                         p = encodings [++i];
6611                         continue;
6612                 }
6613                 if (strcmp (p, codepage) == 0){
6614                         *int_code_page = code;
6615                         break;
6616                 }
6617                 p = encodings [++i];
6618         }
6619         
6620         if (strstr (codepage, "utf_8") != NULL)
6621                 *int_code_page |= 0x10000000;
6622         free (codepage);
6623         
6624         if (want_name && *int_code_page == -1)
6625                 return mono_string_new (mono_domain_get (), cset);
6626         else
6627                 return NULL;
6628 }
6629
6630 static MonoBoolean
6631 ves_icall_System_Environment_get_HasShutdownStarted (void)
6632 {
6633         if (mono_runtime_is_shutting_down ())
6634                 return TRUE;
6635
6636         if (mono_domain_is_unloading (mono_domain_get ()))
6637                 return TRUE;
6638
6639         return FALSE;
6640 }
6641
6642 static void
6643 ves_icall_System_Environment_BroadcastSettingChange (void)
6644 {
6645 #ifdef HOST_WIN32
6646         SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6647 #endif
6648 }
6649
6650 static void
6651 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this, 
6652                                          MonoReflectionMethod *method,
6653                                          MonoArray *out_args)
6654 {
6655         MONO_ARCH_SAVE_REGS;
6656
6657         mono_message_init (mono_object_domain (this), this, method, out_args);
6658 }
6659
6660 static MonoBoolean
6661 ves_icall_IsTransparentProxy (MonoObject *proxy)
6662 {
6663         MONO_ARCH_SAVE_REGS;
6664
6665         if (!proxy)
6666                 return 0;
6667
6668         if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6669                 return 1;
6670
6671         return 0;
6672 }
6673
6674 static MonoReflectionMethod *
6675 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6676         MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6677 {
6678         MonoClass *klass;
6679         MonoMethod *method;
6680         MonoMethod **vtable;
6681         MonoMethod *res = NULL;
6682
6683         MONO_CHECK_ARG_NULL (rtype);
6684         MONO_CHECK_ARG_NULL (rmethod);
6685
6686         method = rmethod->method;
6687         klass = mono_class_from_mono_type (rtype->type);
6688         mono_class_init_or_throw (klass);
6689
6690         if (MONO_CLASS_IS_INTERFACE (klass))
6691                 return NULL;
6692
6693         if (method->flags & METHOD_ATTRIBUTE_STATIC)
6694                 return NULL;
6695
6696         if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6697                 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6698                         return rmethod;
6699                 else
6700                         return NULL;
6701         }
6702
6703         mono_class_setup_vtable (klass);
6704         vtable = klass->vtable;
6705
6706         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6707                 gboolean variance_used = FALSE;
6708                 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6709                 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6710                 if (offs >= 0)
6711                         res = vtable [offs + method->slot];
6712         } else {
6713                 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6714                         return NULL;
6715
6716                 if (method->slot != -1)
6717                         res = vtable [method->slot];
6718         }
6719
6720         if (!res)
6721                 return NULL;
6722
6723         return mono_method_get_object (mono_domain_get (), res, NULL);
6724 }
6725
6726 static void
6727 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6728 {
6729         MonoClass *klass;
6730         MonoVTable* vtable;
6731
6732         MONO_ARCH_SAVE_REGS;
6733
6734         klass = mono_class_from_mono_type (type->type);
6735         vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6736
6737         if (enable) vtable->remote = 1;
6738         else vtable->remote = 0;
6739 }
6740
6741 static MonoObject *
6742 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6743 {
6744         MonoClass *klass;
6745         MonoDomain *domain;
6746         
6747         MONO_ARCH_SAVE_REGS;
6748
6749         domain = mono_object_domain (type);
6750         klass = mono_class_from_mono_type (type->type);
6751         mono_class_init_or_throw (klass);
6752
6753         if (klass->rank >= 1) {
6754                 g_assert (klass->rank == 1);
6755                 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6756         } else {
6757                 /* Bypass remoting object creation check */
6758                 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6759         }
6760 }
6761
6762 static MonoString *
6763 ves_icall_System_IO_get_temp_path (void)
6764 {
6765         MONO_ARCH_SAVE_REGS;
6766
6767         return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6768 }
6769
6770 #ifndef PLATFORM_NO_DRIVEINFO
6771 static MonoBoolean
6772 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6773                                                 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6774                                                 gint32 *error)
6775 {
6776         gboolean result;
6777         ULARGE_INTEGER wapi_free_bytes_avail;
6778         ULARGE_INTEGER wapi_total_number_of_bytes;
6779         ULARGE_INTEGER wapi_total_number_of_free_bytes;
6780
6781         MONO_ARCH_SAVE_REGS;
6782
6783         *error = ERROR_SUCCESS;
6784         result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6785                                      &wapi_total_number_of_free_bytes);
6786
6787         if (result) {
6788                 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6789                 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6790                 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6791         } else {
6792                 *free_bytes_avail = 0;
6793                 *total_number_of_bytes = 0;
6794                 *total_number_of_free_bytes = 0;
6795                 *error = GetLastError ();
6796         }
6797
6798         return result;
6799 }
6800
6801 static guint32
6802 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6803 {
6804         MONO_ARCH_SAVE_REGS;
6805
6806         return GetDriveType (mono_string_chars (root_path_name));
6807 }
6808 #endif
6809
6810 static gpointer
6811 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6812 {
6813         MONO_ARCH_SAVE_REGS;
6814
6815         return mono_compile_method (method);
6816 }
6817
6818 static MonoString *
6819 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6820 {
6821         MonoString *mcpath;
6822         gchar *path;
6823
6824         MONO_ARCH_SAVE_REGS;
6825
6826         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6827
6828 #if defined (HOST_WIN32)
6829         /* Avoid mixing '/' and '\\' */
6830         {
6831                 gint i;
6832                 for (i = strlen (path) - 1; i >= 0; i--)
6833                         if (path [i] == '/')
6834                                 path [i] = '\\';
6835         }
6836 #endif
6837         mcpath = mono_string_new (mono_domain_get (), path);
6838         g_free (path);
6839
6840         return mcpath;
6841 }
6842
6843 static MonoString *
6844 get_bundled_machine_config (void)
6845 {
6846         const gchar *machine_config;
6847
6848         MONO_ARCH_SAVE_REGS;
6849
6850         machine_config = mono_get_machine_config ();
6851
6852         if (!machine_config)
6853                 return NULL;
6854
6855         return mono_string_new (mono_domain_get (), machine_config);
6856 }
6857
6858 static MonoString *
6859 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6860 {
6861         MonoString *ipath;
6862         gchar *path;
6863
6864         MONO_ARCH_SAVE_REGS;
6865
6866         path = g_path_get_dirname (mono_get_config_dir ());
6867
6868 #if defined (HOST_WIN32)
6869         /* Avoid mixing '/' and '\\' */
6870         {
6871                 gint i;
6872                 for (i = strlen (path) - 1; i >= 0; i--)
6873                         if (path [i] == '/')
6874                                 path [i] = '\\';
6875         }
6876 #endif
6877         ipath = mono_string_new (mono_domain_get (), path);
6878         g_free (path);
6879
6880         return ipath;
6881 }
6882
6883 static gboolean
6884 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6885 {
6886         MonoPEResourceDataEntry *entry;
6887         MonoImage *image;
6888
6889         MONO_ARCH_SAVE_REGS;
6890
6891         if (!assembly || !result || !size)
6892                 return FALSE;
6893
6894         *result = NULL;
6895         *size = 0;
6896         image = assembly->assembly->image;
6897         entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6898         if (!entry)
6899                 return FALSE;
6900
6901         *result = mono_image_rva_map (image, entry->rde_data_offset);
6902         if (!(*result)) {
6903                 g_free (entry);
6904                 return FALSE;
6905         }
6906         *size = entry->rde_size;
6907         g_free (entry);
6908         return TRUE;
6909 }
6910
6911 static MonoBoolean
6912 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6913 {
6914         return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
6915 }
6916
6917 static void
6918 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6919 {
6920 #if defined (HOST_WIN32)
6921         OutputDebugString (mono_string_chars (message));
6922 #else
6923         g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6924 #endif
6925 }
6926
6927 /* Only used for value types */
6928 static MonoObject *
6929 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6930 {
6931         MonoClass *klass;
6932         MonoDomain *domain;
6933         
6934         MONO_ARCH_SAVE_REGS;
6935
6936         domain = mono_object_domain (type);
6937         klass = mono_class_from_mono_type (type->type);
6938         mono_class_init_or_throw (klass);
6939
6940         if (mono_class_is_nullable (klass))
6941                 /* No arguments -> null */
6942                 return NULL;
6943
6944         return mono_object_new (domain, klass);
6945 }
6946
6947 static MonoReflectionMethod *
6948 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
6949 {
6950         MonoClass *klass, *parent;
6951         MonoMethod *method = m->method;
6952         MonoMethod *result = NULL;
6953
6954         MONO_ARCH_SAVE_REGS;
6955
6956         if (method->klass == NULL)
6957                 return m;
6958
6959         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6960             MONO_CLASS_IS_INTERFACE (method->klass) ||
6961             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6962                 return m;
6963
6964         klass = method->klass;
6965         if (klass->generic_class)
6966                 klass = klass->generic_class->container_class;
6967
6968         if (definition) {
6969                 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6970                 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6971                         mono_class_setup_vtable (parent);
6972                         if (parent->vtable_size <= method->slot)
6973                                 break;
6974                         klass = parent;
6975                 }
6976         } else {
6977                 klass = klass->parent;
6978                 if (!klass)
6979                         return m;
6980         }
6981
6982         if (klass == method->klass)
6983                 return m;
6984
6985         result = klass->vtable [method->slot];
6986         if (result == NULL) {
6987                 /* It is an abstract method */
6988                 gpointer iter = NULL;
6989                 while ((result = mono_class_get_methods (klass, &iter)))
6990                         if (result->slot == method->slot)
6991                                 break;
6992         }
6993
6994         if (result == NULL)
6995                 return m;
6996
6997         return mono_method_get_object (mono_domain_get (), result, NULL);
6998 }
6999
7000 static MonoString*
7001 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7002 {
7003         MonoMethod *method = m->method;
7004
7005         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7006         return m->name;
7007 }
7008
7009 static void
7010 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7011 {
7012         MONO_ARCH_SAVE_REGS;
7013
7014         iter->sig = *(MonoMethodSignature**)argsp;
7015         
7016         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7017         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7018
7019         iter->next_arg = 0;
7020         /* FIXME: it's not documented what start is exactly... */
7021         if (start) {
7022                 iter->args = start;
7023         } else {
7024                 iter->args = argsp + sizeof (gpointer);
7025         }
7026         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7027
7028         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7029 }
7030
7031 static MonoTypedRef
7032 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7033 {
7034         guint32 i, arg_size;
7035         gint32 align;
7036         MonoTypedRef res;
7037         MONO_ARCH_SAVE_REGS;
7038
7039         i = iter->sig->sentinelpos + iter->next_arg;
7040
7041         g_assert (i < iter->sig->param_count);
7042
7043         res.type = iter->sig->params [i];
7044         res.klass = mono_class_from_mono_type (res.type);
7045         res.value = iter->args;
7046         arg_size = mono_type_stack_size (res.type, &align);
7047 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7048         if (arg_size <= sizeof (gpointer)) {
7049                 int dummy;
7050                 int padding = arg_size - mono_type_size (res.type, &dummy);
7051                 res.value = (guint8*)res.value + padding;
7052         }
7053 #endif
7054         iter->args = (char*)iter->args + arg_size;
7055         iter->next_arg++;
7056
7057         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7058
7059         return res;
7060 }
7061
7062 static MonoTypedRef
7063 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7064 {
7065         guint32 i, arg_size;
7066         gint32 align;
7067         MonoTypedRef res;
7068         MONO_ARCH_SAVE_REGS;
7069
7070         i = iter->sig->sentinelpos + iter->next_arg;
7071
7072         g_assert (i < iter->sig->param_count);
7073
7074         while (i < iter->sig->param_count) {
7075                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7076                         continue;
7077                 res.type = iter->sig->params [i];
7078                 res.klass = mono_class_from_mono_type (res.type);
7079                 /* FIXME: endianess issue... */
7080                 res.value = iter->args;
7081                 arg_size = mono_type_stack_size (res.type, &align);
7082                 iter->args = (char*)iter->args + arg_size;
7083                 iter->next_arg++;
7084                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7085                 return res;
7086         }
7087         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7088
7089         res.type = NULL;
7090         res.value = NULL;
7091         res.klass = NULL;
7092         return res;
7093 }
7094
7095 static MonoType*
7096 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7097 {
7098         gint i;
7099         MONO_ARCH_SAVE_REGS;
7100         
7101         i = iter->sig->sentinelpos + iter->next_arg;
7102
7103         g_assert (i < iter->sig->param_count);
7104
7105         return iter->sig->params [i];
7106 }
7107
7108 static MonoObject*
7109 mono_TypedReference_ToObject (MonoTypedRef tref)
7110 {
7111         MONO_ARCH_SAVE_REGS;
7112
7113         if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7114                 MonoObject** objp = tref.value;
7115                 return *objp;
7116         }
7117
7118         return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7119 }
7120
7121 static MonoObject*
7122 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7123 {
7124         MONO_ARCH_SAVE_REGS;
7125
7126         if (MONO_TYPE_IS_REFERENCE (type)) {
7127                 MonoObject** objp = value;
7128                 return *objp;
7129         }
7130
7131         return mono_value_box (mono_domain_get (), klass, value);
7132 }
7133
7134 static void
7135 prelink_method (MonoMethod *method)
7136 {
7137         const char *exc_class, *exc_arg;
7138         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7139                 return;
7140         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7141         if (exc_class) {
7142                 mono_raise_exception( 
7143                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7144         }
7145         /* create the wrapper, too? */
7146 }
7147
7148 static void
7149 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7150 {
7151         MONO_ARCH_SAVE_REGS;
7152         prelink_method (method->method);
7153 }
7154
7155 static void
7156 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7157 {
7158         MonoClass *klass = mono_class_from_mono_type (type->type);
7159         MonoMethod* m;
7160         gpointer iter = NULL;
7161         MONO_ARCH_SAVE_REGS;
7162
7163         mono_class_init_or_throw (klass);
7164
7165         while ((m = mono_class_get_methods (klass, &iter)))
7166                 prelink_method (m);
7167 }
7168
7169 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7170 static void
7171 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7172                                             gint32 const **exponents,
7173                                             gunichar2 const **digitLowerTable,
7174                                             gunichar2 const **digitUpperTable,
7175                                             gint64 const **tenPowersList,
7176                                             gint32 const **decHexDigits)
7177 {
7178         *mantissas = Formatter_MantissaBitsTable;
7179         *exponents = Formatter_TensExponentTable;
7180         *digitLowerTable = Formatter_DigitLowerTable;
7181         *digitUpperTable = Formatter_DigitUpperTable;
7182         *tenPowersList = Formatter_TenPowersList;
7183         *decHexDigits = Formatter_DecHexDigits;
7184 }
7185
7186 /* These parameters are "readonly" in corlib/System/Char.cs */
7187 static void
7188 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7189                                             guint8 const **numeric_data,
7190                                             gdouble const **numeric_data_values,
7191                                             guint16 const **to_lower_data_low,
7192                                             guint16 const **to_lower_data_high,
7193                                             guint16 const **to_upper_data_low,
7194                                             guint16 const **to_upper_data_high)
7195 {
7196         *category_data = CategoryData;
7197         *numeric_data = NumericData;
7198         *numeric_data_values = NumericDataValues;
7199         *to_lower_data_low = ToLowerDataLow;
7200         *to_lower_data_high = ToLowerDataHigh;
7201         *to_upper_data_low = ToUpperDataLow;
7202         *to_upper_data_high = ToUpperDataHigh;
7203 }
7204
7205 static gint32
7206 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7207 {
7208         return method->method->token;
7209 }
7210
7211 /*
7212  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7213  * and avoid useless allocations.
7214  */
7215 static MonoArray*
7216 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7217 {
7218         MonoArray *res;
7219         int i, count = 0;
7220         for (i = 0; i < type->num_mods; ++i) {
7221                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7222                         count++;
7223         }
7224         if (!count)
7225                 return NULL;
7226         res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7227         count = 0;
7228         for (i = 0; i < type->num_mods; ++i) {
7229                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7230                         MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7231                         mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7232                         count++;
7233                 }
7234         }
7235         return res;
7236 }
7237
7238 static MonoArray*
7239 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7240 {
7241         MonoType *type = param->ClassImpl->type;
7242         MonoClass *member_class = mono_object_class (param->MemberImpl);
7243         MonoMethod *method = NULL;
7244         MonoImage *image;
7245         int pos;
7246         MonoMethodSignature *sig;
7247
7248         if (mono_class_is_reflection_method_or_constructor (member_class)) {
7249                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7250                 method = rmethod->method;
7251         } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7252                 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7253                 if (!(method = prop->property->get))
7254                         method = prop->property->set;
7255                 g_assert (method);      
7256         } else {
7257                 char *type_name = mono_type_get_full_name (member_class);
7258                 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7259                 MonoException *ex = mono_get_exception_not_supported  (msg);
7260                 g_free (type_name);
7261                 g_free (msg);
7262                 mono_raise_exception (ex);
7263         }
7264
7265         image = method->klass->image;
7266         pos = param->PositionImpl;
7267         sig = mono_method_signature (method);
7268         if (pos == -1)
7269                 type = sig->ret;
7270         else
7271                 type = sig->params [pos];
7272
7273         return type_array_from_modifiers (image, type, optional);
7274 }
7275
7276 static MonoType*
7277 get_property_type (MonoProperty *prop)
7278 {
7279         MonoMethodSignature *sig;
7280         if (prop->get) {
7281                 sig = mono_method_signature (prop->get);
7282                 return sig->ret;
7283         } else if (prop->set) {
7284                 sig = mono_method_signature (prop->set);
7285                 return sig->params [sig->param_count - 1];
7286         }
7287         return NULL;
7288 }
7289
7290 static MonoArray*
7291 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7292 {
7293         MonoType *type = get_property_type (property->property);
7294         MonoImage *image = property->klass->image;
7295
7296         if (!type)
7297                 return NULL;
7298         return type_array_from_modifiers (image, type, optional);
7299 }
7300
7301 /*
7302  *Construct a MonoType suited to be used to decode a constant blob object.
7303  *
7304  * @type is the target type which will be constructed
7305  * @blob_type is the blob type, for example, that comes from the constant table
7306  * @real_type is the expected constructed type.
7307  */
7308 static void
7309 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7310 {
7311         type->type = blob_type;
7312         type->data.klass = NULL;
7313         if (blob_type == MONO_TYPE_CLASS)
7314                 type->data.klass = mono_defaults.object_class;
7315         else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7316                 /* For enums, we need to use the base type */
7317                 type->type = MONO_TYPE_VALUETYPE;
7318                 type->data.klass = mono_class_from_mono_type (real_type);
7319         } else
7320                 type->data.klass = mono_class_from_mono_type (real_type);
7321 }
7322
7323 static MonoObject*
7324 property_info_get_default_value (MonoReflectionProperty *property)
7325 {
7326         MonoType blob_type;
7327         MonoProperty *prop = property->property;
7328         MonoType *type = get_property_type (prop);
7329         MonoDomain *domain = mono_object_domain (property); 
7330         MonoTypeEnum def_type;
7331         const char *def_value;
7332         MonoObject *o;
7333
7334         g_assert (!prop->parent->image->dynamic);
7335
7336         mono_class_init (prop->parent);
7337
7338         if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7339                 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7340
7341         def_value = mono_class_get_property_default_value (prop, &def_type);
7342
7343         mono_type_from_blob_type (&blob_type, def_type, type);
7344         o = mono_get_object_from_blob (domain, &blob_type, def_value);
7345
7346         return o;
7347 }
7348
7349 static MonoBoolean
7350 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7351 {
7352         MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7353         MonoCustomAttrInfo *cinfo;
7354         gboolean found;
7355
7356         mono_class_init_or_throw (attr_class);
7357
7358         cinfo = mono_reflection_get_custom_attrs_info (obj);
7359         if (!cinfo)
7360                 return FALSE;
7361         found = mono_custom_attrs_has_attr (cinfo, attr_class);
7362         if (!cinfo->cached)
7363                 mono_custom_attrs_free (cinfo);
7364         return found;
7365 }
7366
7367 static MonoArray*
7368 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7369 {
7370         MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7371         MonoArray *res;
7372
7373         if (attr_class)
7374                 mono_class_init_or_throw (attr_class);
7375
7376         res = mono_reflection_get_custom_attrs_by_type (obj, attr_class);
7377
7378         if (mono_loader_get_last_error ()) {
7379                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7380                 g_assert_not_reached ();
7381                 /* Not reached */
7382                 return NULL;
7383         } else {
7384                 return res;
7385         }
7386 }
7387
7388 static MonoString*
7389 ves_icall_Mono_Runtime_GetDisplayName (void)
7390 {
7391         char *info;
7392         MonoString *display_name;
7393
7394         info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7395         display_name = mono_string_new (mono_domain_get (), info);
7396         g_free (info);
7397         return display_name;
7398 }
7399
7400 static MonoString*
7401 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7402 {
7403         MonoString *message;
7404         guint32 ret;
7405         gunichar2 buf[256];
7406         
7407         ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7408                              FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7409                              buf, 255, NULL);
7410         if (ret == 0) {
7411                 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7412         } else {
7413                 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7414         }
7415         
7416         return message;
7417 }
7418
7419 const static guchar
7420 dbase64 [] = {
7421         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7422         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7423         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7424         52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7425         128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7426         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7427         128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7428         41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7429 };
7430
7431 static MonoArray *
7432 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7433 {
7434         gint ignored;
7435         gint i;
7436         gunichar2 c;
7437         gunichar2 last, prev_last, prev2_last;
7438         gint olength;
7439         MonoArray *result;
7440         guchar *res_ptr;
7441         gint a [4], b [4];
7442         MonoException *exc;
7443
7444         ignored = 0;
7445         last = prev_last = 0, prev2_last = 0;
7446         for (i = 0; i < ilength; i++) {
7447                 c = start [i];
7448                 if (c >= sizeof (dbase64)) {
7449                         exc = mono_exception_from_name_msg (mono_get_corlib (),
7450                                 "System", "FormatException",
7451                                 "Invalid character found.");
7452                         mono_raise_exception (exc);
7453                 } else if (isspace (c)) {
7454                         ignored++;
7455                 } else {
7456                         prev2_last = prev_last;
7457                         prev_last = last;
7458                         last = c;
7459                 }
7460         }
7461
7462         olength = ilength - ignored;
7463
7464         if (allowWhitespaceOnly && olength == 0) {
7465                 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7466         }
7467
7468         if ((olength & 3) != 0 || olength <= 0) {
7469                 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7470                                         "FormatException", "Invalid length.");
7471                 mono_raise_exception (exc);
7472         }
7473
7474         if (prev2_last == '=') {
7475                 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7476                 mono_raise_exception (exc);
7477         }
7478
7479         olength = (olength * 3) / 4;
7480         if (last == '=')
7481                 olength--;
7482
7483         if (prev_last == '=')
7484                 olength--;
7485
7486         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7487         res_ptr = mono_array_addr (result, guchar, 0);
7488         for (i = 0; i < ilength; ) {
7489                 int k;
7490
7491                 for (k = 0; k < 4 && i < ilength;) {
7492                         c = start [i++];
7493                         if (isspace (c))
7494                                 continue;
7495
7496                         a [k] = (guchar) c;
7497                         if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7498                                 exc = mono_exception_from_name_msg (mono_get_corlib (),
7499                                         "System", "FormatException",
7500                                         "Invalid character found.");
7501                                 mono_raise_exception (exc);
7502                         }
7503                         k++;
7504                 }
7505
7506                 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7507                 if (a [2] != '=')
7508                         *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7509                 if (a [3] != '=')
7510                         *res_ptr++ = (b [2] << 6) | b [3];
7511
7512                 while (i < ilength && isspace (start [i]))
7513                         i++;
7514         }
7515
7516         return result;
7517 }
7518
7519 static MonoArray *
7520 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7521 {
7522         MONO_ARCH_SAVE_REGS;
7523
7524         return base64_to_byte_array (mono_string_chars (str), 
7525                 mono_string_length (str), allowWhitespaceOnly);
7526 }
7527
7528 static MonoArray *
7529 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7530 {
7531         MONO_ARCH_SAVE_REGS;
7532
7533         return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7534                 length, FALSE);
7535 }
7536
7537 #define ICALL_TYPE(id,name,first)
7538 #define ICALL(id,name,func) Icall_ ## id,
7539
7540 enum {
7541 #include "metadata/icall-def.h"
7542         Icall_last
7543 };
7544
7545 #undef ICALL_TYPE
7546 #undef ICALL
7547 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7548 #define ICALL(id,name,func)
7549 enum {
7550 #include "metadata/icall-def.h"
7551         Icall_type_num
7552 };
7553
7554 #undef ICALL_TYPE
7555 #undef ICALL
7556 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7557 #define ICALL(id,name,func)
7558 typedef struct {
7559         guint16 first_icall;
7560 } IcallTypeDesc;
7561
7562 static const IcallTypeDesc
7563 icall_type_descs [] = {
7564 #include "metadata/icall-def.h"
7565         {Icall_last}
7566 };
7567
7568 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7569
7570 #undef ICALL_TYPE
7571 #define ICALL_TYPE(id,name,first)
7572 #undef ICALL
7573
7574 #ifdef HAVE_ARRAY_ELEM_INIT
7575 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7576 #define MSGSTRFIELD1(line) str##line
7577
7578 static const struct msgstrtn_t {
7579 #define ICALL(id,name,func)
7580 #undef ICALL_TYPE
7581 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7582 #include "metadata/icall-def.h"
7583 #undef ICALL_TYPE
7584 } icall_type_names_str = {
7585 #define ICALL_TYPE(id,name,first) (name),
7586 #include "metadata/icall-def.h"
7587 #undef ICALL_TYPE
7588 };
7589 static const guint16 icall_type_names_idx [] = {
7590 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7591 #include "metadata/icall-def.h"
7592 #undef ICALL_TYPE
7593 };
7594 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7595
7596 static const struct msgstr_t {
7597 #undef ICALL
7598 #define ICALL_TYPE(id,name,first)
7599 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7600 #include "metadata/icall-def.h"
7601 #undef ICALL
7602 } icall_names_str = {
7603 #define ICALL(id,name,func) (name),
7604 #include "metadata/icall-def.h"
7605 #undef ICALL
7606 };
7607 static const guint16 icall_names_idx [] = {
7608 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7609 #include "metadata/icall-def.h"
7610 #undef ICALL
7611 };
7612 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7613
7614 #else
7615
7616 #undef ICALL_TYPE
7617 #undef ICALL
7618 #define ICALL_TYPE(id,name,first) name,
7619 #define ICALL(id,name,func)
7620 static const char* const
7621 icall_type_names [] = {
7622 #include "metadata/icall-def.h"
7623         NULL
7624 };
7625
7626 #define icall_type_name_get(id) (icall_type_names [(id)])
7627
7628 #undef ICALL_TYPE
7629 #undef ICALL
7630 #define ICALL_TYPE(id,name,first)
7631 #define ICALL(id,name,func) name,
7632 static const char* const
7633 icall_names [] = {
7634 #include "metadata/icall-def.h"
7635         NULL
7636 };
7637 #define icall_name_get(id) icall_names [(id)]
7638
7639 #endif /* !HAVE_ARRAY_ELEM_INIT */
7640
7641 #undef ICALL_TYPE
7642 #undef ICALL
7643 #define ICALL_TYPE(id,name,first)
7644 #define ICALL(id,name,func) func,
7645 static const gconstpointer
7646 icall_functions [] = {
7647 #include "metadata/icall-def.h"
7648         NULL
7649 };
7650
7651 static GHashTable *icall_hash = NULL;
7652 static GHashTable *jit_icall_hash_name = NULL;
7653 static GHashTable *jit_icall_hash_addr = NULL;
7654
7655 void
7656 mono_icall_init (void)
7657 {
7658         int i = 0;
7659
7660         /* check that tables are sorted: disable in release */
7661         if (TRUE) {
7662                 int j;
7663                 const char *prev_class = NULL;
7664                 const char *prev_method;
7665                 
7666                 for (i = 0; i < Icall_type_num; ++i) {
7667                         const IcallTypeDesc *desc;
7668                         int num_icalls;
7669                         prev_method = NULL;
7670                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7671                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7672                         prev_class = icall_type_name_get (i);
7673                         desc = &icall_type_descs [i];
7674                         num_icalls = icall_desc_num_icalls (desc);
7675                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7676                         for (j = 0; j < num_icalls; ++j) {
7677                                 const char *methodn = icall_name_get (desc->first_icall + j);
7678                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
7679                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
7680                                 prev_method = methodn;
7681                         }
7682                 }
7683         }
7684
7685         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7686 }
7687
7688 void
7689 mono_icall_cleanup (void)
7690 {
7691         g_hash_table_destroy (icall_hash);
7692         g_hash_table_destroy (jit_icall_hash_name);
7693         g_hash_table_destroy (jit_icall_hash_addr);
7694 }
7695
7696 void
7697 mono_add_internal_call (const char *name, gconstpointer method)
7698 {
7699         mono_loader_lock ();
7700
7701         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7702
7703         mono_loader_unlock ();
7704 }
7705
7706 #ifdef HAVE_ARRAY_ELEM_INIT
7707 static int
7708 compare_method_imap (const void *key, const void *elem)
7709 {
7710         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7711         return strcmp (key, method_name);
7712 }
7713
7714 static gpointer
7715 find_method_icall (const IcallTypeDesc *imap, const char *name)
7716 {
7717         const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7718         if (!nameslot)
7719                 return NULL;
7720         return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7721 }
7722
7723 static int
7724 compare_class_imap (const void *key, const void *elem)
7725 {
7726         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7727         return strcmp (key, class_name);
7728 }
7729
7730 static const IcallTypeDesc*
7731 find_class_icalls (const char *name)
7732 {
7733         const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7734         if (!nameslot)
7735                 return NULL;
7736         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7737 }
7738
7739 #else
7740 static int
7741 compare_method_imap (const void *key, const void *elem)
7742 {
7743         const char** method_name = (const char**)elem;
7744         return strcmp (key, *method_name);
7745 }
7746
7747 static gpointer
7748 find_method_icall (const IcallTypeDesc *imap, const char *name)
7749 {
7750         const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7751         if (!nameslot)
7752                 return NULL;
7753         return (gpointer)icall_functions [(nameslot - icall_names)];
7754 }
7755
7756 static int
7757 compare_class_imap (const void *key, const void *elem)
7758 {
7759         const char** class_name = (const char**)elem;
7760         return strcmp (key, *class_name);
7761 }
7762
7763 static const IcallTypeDesc*
7764 find_class_icalls (const char *name)
7765 {
7766         const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7767         if (!nameslot)
7768                 return NULL;
7769         return &icall_type_descs [nameslot - icall_type_names];
7770 }
7771
7772 #endif
7773
7774 /* 
7775  * we should probably export this as an helper (handle nested types).
7776  * Returns the number of chars written in buf.
7777  */
7778 static int
7779 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7780 {
7781         int nspacelen, cnamelen;
7782         nspacelen = strlen (klass->name_space);
7783         cnamelen = strlen (klass->name);
7784         if (nspacelen + cnamelen + 2 > bufsize)
7785                 return 0;
7786         if (nspacelen) {
7787                 memcpy (buf, klass->name_space, nspacelen);
7788                 buf [nspacelen ++] = '.';
7789         }
7790         memcpy (buf + nspacelen, klass->name, cnamelen);
7791         buf [nspacelen + cnamelen] = 0;
7792         return nspacelen + cnamelen;
7793 }
7794
7795 gpointer
7796 mono_lookup_internal_call (MonoMethod *method)
7797 {
7798         char *sigstart;
7799         char *tmpsig;
7800         char mname [2048];
7801         int typelen = 0, mlen, siglen;
7802         gpointer res;
7803         const IcallTypeDesc *imap;
7804
7805         g_assert (method != NULL);
7806
7807         if (method->is_inflated)
7808                 method = ((MonoMethodInflated *) method)->declaring;
7809
7810         if (method->klass->nested_in) {
7811                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7812                 if (!pos)
7813                         return NULL;
7814
7815                 mname [pos++] = '/';
7816                 mname [pos] = 0;
7817
7818                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7819                 if (!typelen)
7820                         return NULL;
7821
7822                 typelen += pos;
7823         } else {
7824                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7825                 if (!typelen)
7826                         return NULL;
7827         }
7828
7829         imap = find_class_icalls (mname);
7830
7831         mname [typelen] = ':';
7832         mname [typelen + 1] = ':';
7833
7834         mlen = strlen (method->name);
7835         memcpy (mname + typelen + 2, method->name, mlen);
7836         sigstart = mname + typelen + 2 + mlen;
7837         *sigstart = 0;
7838
7839         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7840         siglen = strlen (tmpsig);
7841         if (typelen + mlen + siglen + 6 > sizeof (mname))
7842                 return NULL;
7843         sigstart [0] = '(';
7844         memcpy (sigstart + 1, tmpsig, siglen);
7845         sigstart [siglen + 1] = ')';
7846         sigstart [siglen + 2] = 0;
7847         g_free (tmpsig);
7848         
7849         mono_loader_lock ();
7850
7851         res = g_hash_table_lookup (icall_hash, mname);
7852         if (res) {
7853                 mono_loader_unlock ();
7854                 return res;
7855         }
7856         /* try without signature */
7857         *sigstart = 0;
7858         res = g_hash_table_lookup (icall_hash, mname);
7859         if (res) {
7860                 mono_loader_unlock ();
7861                 return res;
7862         }
7863
7864         /* it wasn't found in the static call tables */
7865         if (!imap) {
7866                 mono_loader_unlock ();
7867                 return NULL;
7868         }
7869         res = find_method_icall (imap, sigstart - mlen);
7870         if (res) {
7871                 mono_loader_unlock ();
7872                 return res;
7873         }
7874         /* try _with_ signature */
7875         *sigstart = '(';
7876         res = find_method_icall (imap, sigstart - mlen);
7877         if (res) {
7878                 mono_loader_unlock ();
7879                 return res;
7880         }
7881
7882         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7883         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7884         g_print ("The out of sync library is: %s\n", method->klass->image->name);
7885         g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7886         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");
7887         g_print ("If you see other errors or faults after this message they are probably related\n");
7888         g_print ("and you need to fix your mono install first.\n");
7889
7890         mono_loader_unlock ();
7891
7892         return NULL;
7893 }
7894
7895 static MonoType*
7896 type_from_typename (char *typename)
7897 {
7898         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
7899
7900         if (!strcmp (typename, "int"))
7901                 klass = mono_defaults.int_class;
7902         else if (!strcmp (typename, "ptr"))
7903                 klass = mono_defaults.int_class;
7904         else if (!strcmp (typename, "void"))
7905                 klass = mono_defaults.void_class;
7906         else if (!strcmp (typename, "int32"))
7907                 klass = mono_defaults.int32_class;
7908         else if (!strcmp (typename, "uint32"))
7909                 klass = mono_defaults.uint32_class;
7910         else if (!strcmp (typename, "int8"))
7911                 klass = mono_defaults.sbyte_class;
7912         else if (!strcmp (typename, "uint8"))
7913                 klass = mono_defaults.byte_class;
7914         else if (!strcmp (typename, "int16"))
7915                 klass = mono_defaults.int16_class;
7916         else if (!strcmp (typename, "uint16"))
7917                 klass = mono_defaults.uint16_class;
7918         else if (!strcmp (typename, "long"))
7919                 klass = mono_defaults.int64_class;
7920         else if (!strcmp (typename, "ulong"))
7921                 klass = mono_defaults.uint64_class;
7922         else if (!strcmp (typename, "float"))
7923                 klass = mono_defaults.single_class;
7924         else if (!strcmp (typename, "double"))
7925                 klass = mono_defaults.double_class;
7926         else if (!strcmp (typename, "object"))
7927                 klass = mono_defaults.object_class;
7928         else if (!strcmp (typename, "obj"))
7929                 klass = mono_defaults.object_class;
7930         else if (!strcmp (typename, "string"))
7931                 klass = mono_defaults.string_class;
7932         else if (!strcmp (typename, "bool"))
7933                 klass = mono_defaults.boolean_class;
7934         else if (!strcmp (typename, "boolean"))
7935                 klass = mono_defaults.boolean_class;
7936         else {
7937                 g_error ("%s", typename);
7938                 g_assert_not_reached ();
7939         }
7940         return &klass->byval_arg;
7941 }
7942
7943 MonoMethodSignature*
7944 mono_create_icall_signature (const char *sigstr)
7945 {
7946         gchar **parts;
7947         int i, len;
7948         gchar **tmp;
7949         MonoMethodSignature *res;
7950
7951         mono_loader_lock ();
7952         res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7953         if (res) {
7954                 mono_loader_unlock ();
7955                 return res;
7956         }
7957
7958         parts = g_strsplit (sigstr, " ", 256);
7959
7960         tmp = parts;
7961         len = 0;
7962         while (*tmp) {
7963                 len ++;
7964                 tmp ++;
7965         }
7966
7967         res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
7968         res->pinvoke = 1;
7969
7970 #ifdef HOST_WIN32
7971         /* 
7972          * Under windows, the default pinvoke calling convention is STDCALL but
7973          * we need CDECL.
7974          */
7975         res->call_convention = MONO_CALL_C;
7976 #endif
7977
7978         res->ret = type_from_typename (parts [0]);
7979         for (i = 1; i < len; ++i) {
7980                 res->params [i - 1] = type_from_typename (parts [i]);
7981         }
7982
7983         g_strfreev (parts);
7984
7985         g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
7986
7987         mono_loader_unlock ();
7988
7989         return res;
7990 }
7991
7992 MonoJitICallInfo *
7993 mono_find_jit_icall_by_name (const char *name)
7994 {
7995         MonoJitICallInfo *info;
7996         g_assert (jit_icall_hash_name);
7997
7998         mono_loader_lock ();
7999         info = g_hash_table_lookup (jit_icall_hash_name, name);
8000         mono_loader_unlock ();
8001         return info;
8002 }
8003
8004 MonoJitICallInfo *
8005 mono_find_jit_icall_by_addr (gconstpointer addr)
8006 {
8007         MonoJitICallInfo *info;
8008         g_assert (jit_icall_hash_addr);
8009
8010         mono_loader_lock ();
8011         info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8012         mono_loader_unlock ();
8013
8014         return info;
8015 }
8016
8017 /*
8018  * mono_get_jit_icall_info:
8019  *
8020  *   Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8021  * caller should access it while holding the loader lock.
8022  */
8023 GHashTable*
8024 mono_get_jit_icall_info (void)
8025 {
8026         return jit_icall_hash_name;
8027 }
8028
8029 void
8030 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8031 {
8032         mono_loader_lock ();
8033         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8034         mono_loader_unlock ();
8035 }
8036
8037 MonoJitICallInfo *
8038 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8039 {
8040         MonoJitICallInfo *info;
8041         
8042         g_assert (func);
8043         g_assert (name);
8044
8045         mono_loader_lock ();
8046
8047         if (!jit_icall_hash_name) {
8048                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8049                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8050         }
8051
8052         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8053                 g_warning ("jit icall already defined \"%s\"\n", name);
8054                 g_assert_not_reached ();
8055         }
8056
8057         info = g_new0 (MonoJitICallInfo, 1);
8058         
8059         info->name = name;
8060         info->func = func;
8061         info->sig = sig;
8062
8063         if (is_save) {
8064                 info->wrapper = func;
8065         } else {
8066                 info->wrapper = NULL;
8067         }
8068
8069         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8070         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8071
8072         mono_loader_unlock ();
8073         return info;
8074 }