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