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