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