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