Merge pull request #505 from roji/shutdown_flow
[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 (klass && klass->is_com_object);
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         return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4857 }
4858
4859
4860 ICALL_EXPORT MonoReflectionAssembly*
4861 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4862 {
4863         MonoDomain* domain = mono_domain_get ();
4864
4865         MONO_ARCH_SAVE_REGS;
4866
4867         if (!domain->entry_assembly)
4868                 return NULL;
4869
4870         return mono_assembly_get_object (domain, domain->entry_assembly);
4871 }
4872
4873 ICALL_EXPORT MonoReflectionAssembly*
4874 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4875 {
4876         MonoMethod *m;
4877         MonoMethod *dest;
4878
4879         MONO_ARCH_SAVE_REGS;
4880
4881         dest = NULL;
4882         mono_stack_walk_no_il (get_executing, &dest);
4883         m = dest;
4884         mono_stack_walk_no_il (get_caller, &dest);
4885         if (!dest)
4886                 dest = m;
4887         return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4888 }
4889
4890 ICALL_EXPORT MonoString *
4891 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4892                                        gboolean assembly_qualified)
4893 {
4894         MonoDomain *domain = mono_object_domain (object); 
4895         MonoTypeNameFormat format;
4896         MonoString *res;
4897         gchar *name;
4898
4899         if (full_name)
4900                 format = assembly_qualified ?
4901                         MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4902                         MONO_TYPE_NAME_FORMAT_FULL_NAME;
4903         else
4904                 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4905  
4906         name = mono_type_get_name_full (object->type, format);
4907         if (!name)
4908                 return NULL;
4909
4910         if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4911                 g_free (name);
4912                 return NULL;
4913         }
4914
4915         res = mono_string_new (domain, name);
4916         g_free (name);
4917
4918         return res;
4919 }
4920
4921 ICALL_EXPORT int
4922 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4923 {
4924         MonoClass *klass = mono_class_from_mono_type (this->type);
4925         mono_class_init_or_throw (klass);
4926         return mono_security_core_clr_class_level (klass);
4927 }
4928
4929 static void
4930 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4931 {
4932         static MonoMethod *create_culture = NULL;
4933         gpointer args [2];
4934         guint32 pkey_len;
4935         const char *pkey_ptr;
4936         gchar *codebase;
4937         MonoBoolean assembly_ref = 0;
4938
4939         MONO_ARCH_SAVE_REGS;
4940
4941         MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4942         aname->major = name->major;
4943         aname->minor = name->minor;
4944         aname->build = name->build;
4945         aname->flags = name->flags;
4946         aname->revision = name->revision;
4947         aname->hashalg = name->hash_alg;
4948         aname->versioncompat = 1; /* SameMachine (default) */
4949         aname->processor_architecture = name->arch;
4950
4951         if (by_default_version)
4952                 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4953
4954         codebase = NULL;
4955         if (absolute != NULL && *absolute != '\0') {
4956                 const gchar *prepend = "file://";
4957                 gchar *result;
4958
4959                 codebase = g_strdup (absolute);
4960
4961 #if HOST_WIN32
4962                 {
4963                         gint i;
4964                         for (i = strlen (codebase) - 1; i >= 0; i--)
4965                                 if (codebase [i] == '\\')
4966                                         codebase [i] = '/';
4967
4968                         if (*codebase == '/' && *(codebase + 1) == '/') {
4969                                 prepend = "file:";
4970                         } else {
4971                                 prepend = "file:///";
4972                         }
4973                 }
4974 #endif
4975                 result = g_strconcat (prepend, codebase, NULL);
4976                 g_free (codebase);
4977                 codebase = result;
4978         }
4979
4980         if (codebase) {
4981                 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4982                 g_free (codebase);
4983         }
4984
4985         if (!create_culture) {
4986                 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4987                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4988                 g_assert (create_culture);
4989                 mono_method_desc_free (desc);
4990         }
4991
4992         if (name->culture) {
4993                 args [0] = mono_string_new (domain, name->culture);
4994                 args [1] = &assembly_ref;
4995                 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4996         }
4997
4998         if (name->public_key) {
4999                 pkey_ptr = (char*)name->public_key;
5000                 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5001
5002                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5003                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5004                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5005         } else if (default_publickey) {
5006                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5007                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5008         }
5009
5010         /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5011         if (name->public_key_token [0]) {
5012                 int i, j;
5013                 char *p;
5014
5015                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5016                 p = mono_array_addr (aname->keyToken, char, 0);
5017
5018                 for (i = 0, j = 0; i < 8; i++) {
5019                         *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5020                         *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5021                         p++;
5022                 }
5023         } else if (default_token) {
5024                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5025         }
5026 }
5027
5028 ICALL_EXPORT MonoString *
5029 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5030 {
5031         MonoDomain *domain = mono_object_domain (assembly); 
5032         MonoAssembly *mass = assembly->assembly;
5033         MonoString *res;
5034         gchar *name;
5035
5036         name = mono_stringify_assembly_name (&mass->aname);
5037         res = mono_string_new (domain, name);
5038         g_free (name);
5039
5040         return res;
5041 }
5042
5043 ICALL_EXPORT void
5044 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5045 {
5046         gchar *absolute;
5047         MonoAssembly *mass = assembly->assembly;
5048
5049         MONO_ARCH_SAVE_REGS;
5050
5051         if (g_path_is_absolute (mass->image->name)) {
5052                 fill_reflection_assembly_name (mono_object_domain (assembly),
5053                         aname, &mass->aname, mass->image->name, TRUE,
5054                         TRUE, TRUE);
5055                 return;
5056         }
5057         absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5058
5059         fill_reflection_assembly_name (mono_object_domain (assembly),
5060                 aname, &mass->aname, absolute, TRUE, TRUE,
5061                 TRUE);
5062
5063         g_free (absolute);
5064 }
5065
5066 ICALL_EXPORT void
5067 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5068 {
5069         char *filename;
5070         MonoImageOpenStatus status = MONO_IMAGE_OK;
5071         gboolean res;
5072         MonoImage *image;
5073         MonoAssemblyName name;
5074         char *dirname
5075
5076         MONO_ARCH_SAVE_REGS;
5077
5078         filename = mono_string_to_utf8 (fname);
5079
5080         dirname = g_path_get_dirname (filename);
5081         replace_shadow_path (mono_domain_get (), dirname, &filename);
5082         g_free (dirname);
5083
5084         image = mono_image_open (filename, &status);
5085
5086         if (!image){
5087                 MonoException *exc;
5088
5089                 g_free (filename);
5090                 if (status == MONO_IMAGE_IMAGE_INVALID)
5091                         exc = mono_get_exception_bad_image_format2 (NULL, fname);
5092                 else
5093                         exc = mono_get_exception_file_not_found2 (NULL, fname);
5094                 mono_raise_exception (exc);
5095         }
5096
5097         res = mono_assembly_fill_assembly_name (image, &name);
5098         if (!res) {
5099                 mono_image_close (image);
5100                 g_free (filename);
5101                 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5102         }
5103
5104         fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5105                 TRUE, FALSE, TRUE);
5106
5107         g_free (filename);
5108         mono_image_close (image);
5109 }
5110
5111 ICALL_EXPORT MonoBoolean
5112 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5113         char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5114 {
5115         MonoBoolean result = FALSE;
5116         MonoDeclSecurityEntry entry;
5117
5118         /* SecurityAction.RequestMinimum */
5119         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5120                 *minimum = entry.blob;
5121                 *minLength = entry.size;
5122                 result = TRUE;
5123         }
5124         /* SecurityAction.RequestOptional */
5125         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5126                 *optional = entry.blob;
5127                 *optLength = entry.size;
5128                 result = TRUE;
5129         }
5130         /* SecurityAction.RequestRefuse */
5131         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5132                 *refused = entry.blob;
5133                 *refLength = entry.size;
5134                 result = TRUE;
5135         }
5136
5137         return result;  
5138 }
5139
5140 static MonoArray*
5141 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5142 {
5143         MonoArray *res;
5144         MonoClass *klass;
5145         MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5146         int i, count;
5147         guint32 attrs, visibility;
5148
5149         /* we start the count from 1 because we skip the special type <Module> */
5150         if (exportedOnly) {
5151                 count = 0;
5152                 for (i = 1; i < tdef->rows; ++i) {
5153                         attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5154                         visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5155                         if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5156                                 count++;
5157                 }
5158         } else {
5159                 count = tdef->rows - 1;
5160         }
5161         res = mono_array_new (domain, mono_defaults.monotype_class, count);
5162         *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5163         count = 0;
5164         for (i = 1; i < tdef->rows; ++i) {
5165                 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5166                 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5167                 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5168                         klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5169                         if (klass) {
5170                                 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5171                         } else {
5172                                 MonoLoaderError *error;
5173                                 MonoException *ex;
5174                                 
5175                                 error = mono_loader_get_last_error ();
5176                                 g_assert (error != NULL);
5177         
5178                                 ex = mono_loader_error_prepare_exception (error);
5179                                 mono_array_setref (*exceptions, count, ex);
5180                         }
5181                         if (mono_loader_get_last_error ())
5182                                 mono_loader_clear_error ();
5183                         count++;
5184                 }
5185         }
5186         
5187         return res;
5188 }
5189
5190 ICALL_EXPORT MonoArray*
5191 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5192 {
5193         MonoArray *res = NULL;
5194         MonoArray *exceptions = NULL;
5195         MonoImage *image = NULL;
5196         MonoTableInfo *table = NULL;
5197         MonoDomain *domain;
5198         GList *list = NULL;
5199         int i, len, ex_count;
5200
5201         MONO_ARCH_SAVE_REGS;
5202
5203         domain = mono_object_domain (assembly);
5204
5205         g_assert (!assembly->assembly->dynamic);
5206         image = assembly->assembly->image;
5207         table = &image->tables [MONO_TABLE_FILE];
5208         res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5209
5210         /* Append data from all modules in the assembly */
5211         for (i = 0; i < table->rows; ++i) {
5212                 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5213                         MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5214                         if (loaded_image) {
5215                                 MonoArray *ex2;
5216                                 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5217                                 /* Append the new types to the end of the array */
5218                                 if (mono_array_length (res2) > 0) {
5219                                         guint32 len1, len2;
5220                                         MonoArray *res3, *ex3;
5221
5222                                         len1 = mono_array_length (res);
5223                                         len2 = mono_array_length (res2);
5224
5225                                         res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5226                                         mono_array_memcpy_refs (res3, 0, res, 0, len1);
5227                                         mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5228                                         res = res3;
5229
5230                                         ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5231                                         mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5232                                         mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5233                                         exceptions = ex3;
5234                                 }
5235                         }
5236                 }
5237         }
5238
5239         /* the ReflectionTypeLoadException must have all the types (Types property), 
5240          * NULL replacing types which throws an exception. The LoaderException must
5241          * contain all exceptions for NULL items.
5242          */
5243
5244         len = mono_array_length (res);
5245
5246         ex_count = 0;
5247         for (i = 0; i < len; i++) {
5248                 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5249                 MonoClass *klass;
5250
5251                 if (t) {
5252                         klass = mono_type_get_class (t->type);
5253                         if ((klass != NULL) && klass->exception_type) {
5254                                 /* keep the class in the list */
5255                                 list = g_list_append (list, klass);
5256                                 /* and replace Type with NULL */
5257                                 mono_array_setref (res, i, NULL);
5258                         }
5259                 } else {
5260                         ex_count ++;
5261                 }
5262         }
5263
5264         if (list || ex_count) {
5265                 GList *tmp = NULL;
5266                 MonoException *exc = NULL;
5267                 MonoArray *exl = NULL;
5268                 int j, length = g_list_length (list) + ex_count;
5269
5270                 mono_loader_clear_error ();
5271
5272                 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5273                 /* Types for which mono_class_get () succeeded */
5274                 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5275                         MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5276                         mono_array_setref (exl, i, exc);
5277                 }
5278                 /* Types for which it don't */
5279                 for (j = 0; j < mono_array_length (exceptions); ++j) {
5280                         MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5281                         if (exc) {
5282                                 g_assert (i < length);
5283                                 mono_array_setref (exl, i, exc);
5284                                 i ++;
5285                         }
5286                 }
5287                 g_list_free (list);
5288                 list = NULL;
5289
5290                 exc = mono_get_exception_reflection_type_load (res, exl);
5291                 mono_loader_clear_error ();
5292                 mono_raise_exception (exc);
5293         }
5294                 
5295         return res;
5296 }
5297
5298 ICALL_EXPORT gboolean
5299 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5300 {
5301         MonoAssemblyName aname;
5302         MonoDomain *domain = mono_object_domain (name);
5303         char *val;
5304         gboolean is_version_defined;
5305         gboolean is_token_defined;
5306
5307         aname.public_key = NULL;
5308         val = mono_string_to_utf8 (assname);
5309         if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5310                 g_free ((guint8*) aname.public_key);
5311                 g_free (val);
5312                 return FALSE;
5313         }
5314         
5315         fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5316                 FALSE, is_token_defined);
5317
5318         mono_assembly_name_free (&aname);
5319         g_free ((guint8*) aname.public_key);
5320         g_free (val);
5321
5322         return TRUE;
5323 }
5324
5325 ICALL_EXPORT MonoReflectionType*
5326 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5327 {
5328         MonoDomain *domain = mono_object_domain (module); 
5329         MonoClass *klass;
5330
5331         MONO_ARCH_SAVE_REGS;
5332
5333         g_assert (module->image);
5334
5335         if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5336                 /* These images do not have a global type */
5337                 return NULL;
5338
5339         klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5340         return mono_type_get_object (domain, &klass->byval_arg);
5341 }
5342
5343 ICALL_EXPORT void
5344 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5345 {
5346         /*if (module->image)
5347                 mono_image_close (module->image);*/
5348 }
5349
5350 ICALL_EXPORT MonoString*
5351 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5352 {
5353         MonoDomain *domain = mono_object_domain (module); 
5354
5355         MONO_ARCH_SAVE_REGS;
5356
5357         g_assert (module->image);
5358         return mono_string_new (domain, module->image->guid);
5359 }
5360
5361 ICALL_EXPORT gpointer
5362 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5363 {
5364 #ifdef HOST_WIN32
5365         if (module->image && module->image->is_module_handle)
5366                 return module->image->raw_data;
5367 #endif
5368
5369         return (gpointer) (-1);
5370 }
5371
5372 ICALL_EXPORT void
5373 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5374 {
5375         if (image->dynamic) {
5376                 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5377                 *pe_kind = dyn->pe_kind;
5378                 *machine = dyn->machine;
5379         }
5380         else {
5381                 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5382                 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5383         }
5384 }
5385
5386 ICALL_EXPORT gint32
5387 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5388 {
5389         return (image->md_version_major << 16) | (image->md_version_minor);
5390 }
5391
5392 ICALL_EXPORT MonoArray*
5393 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5394 {
5395         MonoArray *exceptions;
5396         int i;
5397
5398         MONO_ARCH_SAVE_REGS;
5399
5400         if (!module->image)
5401                 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5402         else {
5403                 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5404                 for (i = 0; i < mono_array_length (exceptions); ++i) {
5405                         MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5406                         if (ex)
5407                                 mono_raise_exception (ex);
5408                 }
5409                 return res;
5410         }
5411 }
5412
5413 static gboolean
5414 mono_memberref_is_method (MonoImage *image, guint32 token)
5415 {
5416         if (!image->dynamic) {
5417                 guint32 cols [MONO_MEMBERREF_SIZE];
5418                 const char *sig;
5419                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5420                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5421                 mono_metadata_decode_blob_size (sig, &sig);
5422                 return (*sig != 0x6);
5423         } else {
5424                 MonoClass *handle_class;
5425
5426                 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5427                         return FALSE;
5428
5429                 return mono_defaults.methodhandle_class == handle_class;
5430         }
5431 }
5432
5433 static void
5434 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5435 {
5436         if (type_args)
5437                 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5438                                                                       mono_array_addr (type_args, MonoType*, 0));
5439         else
5440                 context->class_inst = NULL;
5441         if (method_args)
5442                 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5443                                                                        mono_array_addr (method_args, MonoType*, 0));
5444         else
5445                 context->method_inst = NULL;
5446 }
5447
5448 ICALL_EXPORT MonoType*
5449 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5450 {
5451         MonoClass *klass;
5452         int table = mono_metadata_token_table (token);
5453         int index = mono_metadata_token_index (token);
5454         MonoGenericContext context;
5455
5456         *error = ResolveTokenError_Other;
5457
5458         /* Validate token */
5459         if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) && 
5460                 (table != MONO_TABLE_TYPESPEC)) {
5461                 *error = ResolveTokenError_BadTable;
5462                 return NULL;
5463         }
5464
5465         if (image->dynamic) {
5466                 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5467                         klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5468                         return klass ? &klass->byval_arg : NULL;
5469                 }
5470
5471                 init_generic_context_from_args (&context, type_args, method_args);
5472                 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5473                 return klass ? &klass->byval_arg : NULL;
5474         }
5475
5476         if ((index <= 0) || (index > image->tables [table].rows)) {
5477                 *error = ResolveTokenError_OutOfRange;
5478                 return NULL;
5479         }
5480
5481         init_generic_context_from_args (&context, type_args, method_args);
5482         klass = mono_class_get_full (image, token, &context);
5483
5484         if (mono_loader_get_last_error ())
5485                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5486
5487         if (klass)
5488                 return &klass->byval_arg;
5489         else
5490                 return NULL;
5491 }
5492
5493 ICALL_EXPORT MonoMethod*
5494 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5495 {
5496         int table = mono_metadata_token_table (token);
5497         int index = mono_metadata_token_index (token);
5498         MonoGenericContext context;
5499         MonoMethod *method;
5500
5501         *error = ResolveTokenError_Other;
5502
5503         /* Validate token */
5504         if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) && 
5505                 (table != MONO_TABLE_MEMBERREF)) {
5506                 *error = ResolveTokenError_BadTable;
5507                 return NULL;
5508         }
5509
5510         if (image->dynamic) {
5511                 if (table == MONO_TABLE_METHOD)
5512                         return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5513
5514                 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5515                         *error = ResolveTokenError_BadTable;
5516                         return NULL;
5517                 }
5518
5519                 init_generic_context_from_args (&context, type_args, method_args);
5520                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5521         }
5522
5523         if ((index <= 0) || (index > image->tables [table].rows)) {
5524                 *error = ResolveTokenError_OutOfRange;
5525                 return NULL;
5526         }
5527         if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5528                 *error = ResolveTokenError_BadTable;
5529                 return NULL;
5530         }
5531
5532         init_generic_context_from_args (&context, type_args, method_args);
5533         method = mono_get_method_full (image, token, NULL, &context);
5534
5535         if (mono_loader_get_last_error ())
5536                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5537
5538         return method;
5539 }
5540
5541 ICALL_EXPORT MonoString*
5542 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5543 {
5544         int index = mono_metadata_token_index (token);
5545
5546         *error = ResolveTokenError_Other;
5547
5548         /* Validate token */
5549         if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5550                 *error = ResolveTokenError_BadTable;
5551                 return NULL;
5552         }
5553
5554         if (image->dynamic)
5555                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5556
5557         if ((index <= 0) || (index >= image->heap_us.size)) {
5558                 *error = ResolveTokenError_OutOfRange;
5559                 return NULL;
5560         }
5561
5562         /* FIXME: What to do if the index points into the middle of a string ? */
5563
5564         return mono_ldstr (mono_domain_get (), image, index);
5565 }
5566
5567 ICALL_EXPORT MonoClassField*
5568 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5569 {
5570         MonoClass *klass;
5571         int table = mono_metadata_token_table (token);
5572         int index = mono_metadata_token_index (token);
5573         MonoGenericContext context;
5574         MonoClassField *field;
5575
5576         *error = ResolveTokenError_Other;
5577
5578         /* Validate token */
5579         if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5580                 *error = ResolveTokenError_BadTable;
5581                 return NULL;
5582         }
5583
5584         if (image->dynamic) {
5585                 if (table == MONO_TABLE_FIELD)
5586                         return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5587
5588                 if (mono_memberref_is_method (image, token)) {
5589                         *error = ResolveTokenError_BadTable;
5590                         return NULL;
5591                 }
5592
5593                 init_generic_context_from_args (&context, type_args, method_args);
5594                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5595         }
5596
5597         if ((index <= 0) || (index > image->tables [table].rows)) {
5598                 *error = ResolveTokenError_OutOfRange;
5599                 return NULL;
5600         }
5601         if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5602                 *error = ResolveTokenError_BadTable;
5603                 return NULL;
5604         }
5605
5606         init_generic_context_from_args (&context, type_args, method_args);
5607         field = mono_field_from_token (image, token, &klass, &context);
5608
5609         if (mono_loader_get_last_error ())
5610                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5611         
5612         return field;
5613 }
5614
5615
5616 ICALL_EXPORT MonoObject*
5617 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5618 {
5619         int table = mono_metadata_token_table (token);
5620
5621         *error = ResolveTokenError_Other;
5622
5623         switch (table) {
5624         case MONO_TABLE_TYPEDEF:
5625         case MONO_TABLE_TYPEREF:
5626         case MONO_TABLE_TYPESPEC: {
5627                 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5628                 if (t)
5629                         return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5630                 else
5631                         return NULL;
5632         }
5633         case MONO_TABLE_METHOD:
5634         case MONO_TABLE_METHODSPEC: {
5635                 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5636                 if (m)
5637                         return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5638                 else
5639                         return NULL;
5640         }               
5641         case MONO_TABLE_FIELD: {
5642                 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5643                 if (f)
5644                         return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5645                 else
5646                         return NULL;
5647         }
5648         case MONO_TABLE_MEMBERREF:
5649                 if (mono_memberref_is_method (image, token)) {
5650                         MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5651                         if (m)
5652                                 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5653                         else
5654                                 return NULL;
5655                 }
5656                 else {
5657                         MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5658                         if (f)
5659                                 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5660                         else
5661                                 return NULL;
5662                 }
5663                 break;
5664
5665         default:
5666                 *error = ResolveTokenError_BadTable;
5667         }
5668
5669         return NULL;
5670 }
5671
5672 ICALL_EXPORT MonoArray*
5673 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5674 {
5675         int table = mono_metadata_token_table (token);
5676         int idx = mono_metadata_token_index (token);
5677         MonoTableInfo *tables = image->tables;
5678         guint32 sig, len;
5679         const char *ptr;
5680         MonoArray *res;
5681
5682         *error = ResolveTokenError_OutOfRange;
5683
5684         /* FIXME: Support other tables ? */
5685         if (table != MONO_TABLE_STANDALONESIG)
5686                 return NULL;
5687
5688         if (image->dynamic)
5689                 return NULL;
5690
5691         if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5692                 return NULL;
5693
5694         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5695
5696         ptr = mono_metadata_blob_heap (image, sig);
5697         len = mono_metadata_decode_blob_size (ptr, &ptr);
5698
5699         res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5700         memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5701         return res;
5702 }
5703
5704 ICALL_EXPORT MonoReflectionType*
5705 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5706 {
5707         MonoClass *klass;
5708         int isbyref = 0, rank;
5709         char *str = mono_string_to_utf8 (smodifiers);
5710         char *p;
5711
5712         MONO_ARCH_SAVE_REGS;
5713
5714         klass = mono_class_from_mono_type (tb->type.type);
5715         p = str;
5716         /* logic taken from mono_reflection_parse_type(): keep in sync */
5717         while (*p) {
5718                 switch (*p) {
5719                 case '&':
5720                         if (isbyref) { /* only one level allowed by the spec */
5721                                 g_free (str);
5722                                 return NULL;
5723                         }
5724                         isbyref = 1;
5725                         p++;
5726                         g_free (str);
5727                         return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5728                         break;
5729                 case '*':
5730                         klass = mono_ptr_class_get (&klass->byval_arg);
5731                         mono_class_init (klass);
5732                         p++;
5733                         break;
5734                 case '[':
5735                         rank = 1;
5736                         p++;
5737                         while (*p) {
5738                                 if (*p == ']')
5739                                         break;
5740                                 if (*p == ',')
5741                                         rank++;
5742                                 else if (*p != '*') { /* '*' means unknown lower bound */
5743                                         g_free (str);
5744                                         return NULL;
5745                                 }
5746                                 ++p;
5747                         }
5748                         if (*p != ']') {
5749                                 g_free (str);
5750                                 return NULL;
5751                         }
5752                         p++;
5753                         klass = mono_array_class_get (klass, rank);
5754                         mono_class_init (klass);
5755                         break;
5756                 default:
5757                         break;
5758                 }
5759         }
5760         g_free (str);
5761         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5762 }
5763
5764 ICALL_EXPORT MonoBoolean
5765 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5766 {
5767         MonoType *type;
5768         MonoBoolean res;
5769
5770         MONO_ARCH_SAVE_REGS;
5771
5772         type = t->type;
5773         res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5774
5775         return res;
5776 }
5777
5778 static void
5779 check_for_invalid_type (MonoClass *klass)
5780 {
5781         char *name;
5782         MonoString *str;
5783         if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5784                 return;
5785
5786         name = mono_type_get_full_name (klass);
5787         str =  mono_string_new (mono_domain_get (), name);
5788         g_free (name);
5789         mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5790
5791 }
5792 ICALL_EXPORT MonoReflectionType *
5793 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5794 {
5795         MonoClass *klass, *aklass;
5796
5797         MONO_ARCH_SAVE_REGS;
5798
5799         klass = mono_class_from_mono_type (type->type);
5800         check_for_invalid_type (klass);
5801
5802         if (rank == 0) //single dimentional array
5803                 aklass = mono_array_class_get (klass, 1);
5804         else
5805                 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5806
5807         return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5808 }
5809
5810 ICALL_EXPORT MonoReflectionType *
5811 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5812 {
5813         MonoClass *klass;
5814
5815         MONO_ARCH_SAVE_REGS;
5816
5817         klass = mono_class_from_mono_type (type->type);
5818         mono_class_init_or_throw (klass);
5819         check_for_invalid_type (klass);
5820
5821         return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5822 }
5823
5824 ICALL_EXPORT MonoReflectionType *
5825 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5826 {
5827         MonoClass *klass, *pklass;
5828
5829         klass = mono_class_from_mono_type (type->type);
5830         mono_class_init_or_throw (klass);
5831         check_for_invalid_type (klass);
5832
5833         pklass = mono_ptr_class_get (type->type);
5834
5835         return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5836 }
5837
5838 ICALL_EXPORT MonoObject *
5839 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5840                                                    MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5841 {
5842         MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5843         MonoObject *delegate;
5844         gpointer func;
5845         MonoMethod *method = info->method;
5846
5847         MONO_ARCH_SAVE_REGS;
5848
5849         mono_class_init_or_throw (delegate_class);
5850
5851         mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5852
5853         if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5854                 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5855                         return NULL;
5856         }
5857
5858         delegate = mono_object_new (mono_object_domain (type), delegate_class);
5859
5860         if (method->dynamic) {
5861                 /* Creating a trampoline would leak memory */
5862                 func = mono_compile_method (method);
5863         } else {
5864                 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5865                         method = mono_object_get_virtual_method (target, method);
5866                 func = mono_create_ftnptr (mono_domain_get (),
5867                         mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5868         }
5869
5870         mono_delegate_ctor_with_method (delegate, target, func, method);
5871
5872         return delegate;
5873 }
5874
5875 ICALL_EXPORT void
5876 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5877 {
5878         /* Reset the invoke impl to the default one */
5879         this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5880 }
5881
5882 /*
5883  * Magic number to convert a time which is relative to
5884  * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5885  */
5886 #define EPOCH_ADJUST    ((guint64)62135596800LL)
5887
5888 /*
5889  * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5890  */
5891 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5892
5893 #ifdef HOST_WIN32
5894 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5895 static void
5896 convert_to_absolute_date(SYSTEMTIME *date)
5897 {
5898 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5899         static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5900         static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5901         /* from the calendar FAQ */
5902         int a = (14 - date->wMonth) / 12;
5903         int y = date->wYear - a;
5904         int m = date->wMonth + 12 * a - 2;
5905         int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5906
5907         /* d is now the day of the week for the first of the month (0 == Sunday) */
5908
5909         int day_of_week = date->wDayOfWeek;
5910
5911         /* set day_in_month to the first day in the month which falls on day_of_week */    
5912         int day_in_month = 1 + (day_of_week - d);
5913         if (day_in_month <= 0)
5914                 day_in_month += 7;
5915
5916         /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5917         date->wDay = day_in_month + (date->wDay - 1) * 7;
5918         if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5919                 date->wDay -= 7;
5920 }
5921 #endif
5922
5923 #ifndef HOST_WIN32
5924 /*
5925  * Return's the offset from GMT of a local time.
5926  * 
5927  *  tm is a local time
5928  *  t  is the same local time as seconds.
5929  */
5930 static int 
5931 gmt_offset(struct tm *tm, time_t t)
5932 {
5933 #if defined (HAVE_TM_GMTOFF)
5934         return tm->tm_gmtoff;
5935 #else
5936         struct tm g;
5937         time_t t2;
5938         g = *gmtime(&t);
5939         g.tm_isdst = tm->tm_isdst;
5940         t2 = mktime(&g);
5941         return (int)difftime(t, t2);
5942 #endif
5943 }
5944 #endif
5945 /*
5946  * This is heavily based on zdump.c from glibc 2.2.
5947  *
5948  *  * data[0]:  start of daylight saving time (in DateTime ticks).
5949  *  * data[1]:  end of daylight saving time (in DateTime ticks).
5950  *  * data[2]:  utcoffset (in TimeSpan ticks).
5951  *  * data[3]:  additional offset when daylight saving (in TimeSpan ticks).
5952  *  * name[0]:  name of this timezone when not daylight saving.
5953  *  * name[1]:  name of this timezone when daylight saving.
5954  *
5955  *  FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5956  *         the class library allows years between 1 and 9999.
5957  *
5958  *  Returns true on success and zero on failure.
5959  */
5960 ICALL_EXPORT guint32
5961 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5962 {
5963 #ifndef HOST_WIN32
5964         MonoDomain *domain = mono_domain_get ();
5965         struct tm start, tt;
5966         time_t t;
5967
5968         long int gmtoff;
5969         int is_daylight = 0, day;
5970         char tzone [64];
5971
5972         MONO_ARCH_SAVE_REGS;
5973
5974         MONO_CHECK_ARG_NULL (data);
5975         MONO_CHECK_ARG_NULL (names);
5976
5977         mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5978         mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5979
5980         /* 
5981          * no info is better than crashing: we'll need our own tz data
5982          * to make this work properly, anyway. The range is probably
5983          * reduced to 1970 .. 2037 because that is what mktime is
5984          * guaranteed to support (we get into an infinite loop
5985          * otherwise).
5986          */
5987
5988         memset (&start, 0, sizeof (start));
5989
5990         start.tm_mday = 1;
5991         start.tm_year = year-1900;
5992
5993         t = mktime (&start);
5994
5995         if ((year < 1970) || (year > 2037) || (t == -1)) {
5996                 t = time (NULL);
5997                 tt = *localtime (&t);
5998                 strftime (tzone, sizeof (tzone), "%Z", &tt);
5999                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6000                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6001                 return 1;
6002         }
6003
6004         gmtoff = gmt_offset (&start, t);
6005
6006         /* For each day of the year, calculate the tm_gmtoff. */
6007         for (day = 0; day < 365; day++) {
6008
6009                 t += 3600*24;
6010                 tt = *localtime (&t);
6011
6012                 /* Daylight saving starts or ends here. */
6013                 if (gmt_offset (&tt, t) != gmtoff) {
6014                         struct tm tt1;
6015                         time_t t1;
6016
6017                         /* Try to find the exact hour when daylight saving starts/ends. */
6018                         t1 = t;
6019                         do {
6020                                 t1 -= 3600;
6021                                 tt1 = *localtime (&t1);
6022                         } while (gmt_offset (&tt1, t1) != gmtoff);
6023
6024                         /* Try to find the exact minute when daylight saving starts/ends. */
6025                         do {
6026                                 t1 += 60;
6027                                 tt1 = *localtime (&t1);
6028                         } while (gmt_offset (&tt1, t1) == gmtoff);
6029                         t1+=gmtoff;
6030                         strftime (tzone, sizeof (tzone), "%Z", &tt);
6031                         
6032                         /* Write data, if we're already in daylight saving, we're done. */
6033                         if (is_daylight) {
6034                                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6035                                 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6036                                 return 1;
6037                         } else {
6038                                 struct tm end;
6039                                 time_t te;
6040                                 
6041                                 memset (&end, 0, sizeof (end));
6042                                 end.tm_year = year-1900 + 1;
6043                                 end.tm_mday = 1;
6044                                 
6045                                 te = mktime (&end);
6046                                 
6047                                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6048                                 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6049                                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6050                                 mono_array_set ((*data), gint64, 1, ((gint64)te + EPOCH_ADJUST) * 10000000L);
6051                                 is_daylight = 1;
6052                         }
6053
6054                         /* This is only set once when we enter daylight saving. */
6055                         mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6056                         mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6057
6058                         gmtoff = gmt_offset (&tt, t);
6059                 }
6060         }
6061
6062         if (!is_daylight) {
6063                 strftime (tzone, sizeof (tzone), "%Z", &tt);
6064                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6065                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6066                 mono_array_set ((*data), gint64, 0, 0);
6067                 mono_array_set ((*data), gint64, 1, 0);
6068                 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6069                 mono_array_set ((*data), gint64, 3, 0);
6070         }
6071
6072         return 1;
6073 #else
6074         MonoDomain *domain = mono_domain_get ();
6075         TIME_ZONE_INFORMATION tz_info;
6076         FILETIME ft;
6077         int i;
6078         int err, tz_id;
6079
6080         tz_id = GetTimeZoneInformation (&tz_info);
6081         if (tz_id == TIME_ZONE_ID_INVALID)
6082                 return 0;
6083
6084         MONO_CHECK_ARG_NULL (data);
6085         MONO_CHECK_ARG_NULL (names);
6086
6087         mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6088         mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6089
6090         for (i = 0; i < 32; ++i)
6091                 if (!tz_info.DaylightName [i])
6092                         break;
6093         mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6094         for (i = 0; i < 32; ++i)
6095                 if (!tz_info.StandardName [i])
6096                         break;
6097         mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6098
6099         if ((year <= 1601) || (year > 30827)) {
6100                 /*
6101                  * According to MSDN, the MS time functions can't handle dates outside
6102                  * this interval.
6103                  */
6104                 return 1;
6105         }
6106
6107         /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6108         if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6109                 tz_info.StandardDate.wYear = year;
6110                 convert_to_absolute_date(&tz_info.StandardDate);
6111                 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6112                 //g_assert(err);
6113                 if (err == 0)
6114                         return 0;
6115                 
6116                 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6117                 tz_info.DaylightDate.wYear = year;
6118                 convert_to_absolute_date(&tz_info.DaylightDate);
6119                 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6120                 //g_assert(err);
6121                 if (err == 0)
6122                         return 0;
6123                 
6124                 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6125         }
6126         mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6127         mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6128
6129         return 1;
6130 #endif
6131 }
6132
6133 ICALL_EXPORT gpointer
6134 ves_icall_System_Object_obj_address (MonoObject *this) 
6135 {
6136         MONO_ARCH_SAVE_REGS;
6137
6138         return this;
6139 }
6140
6141 /* System.Buffer */
6142
6143 static inline gint32 
6144 mono_array_get_byte_length (MonoArray *array)
6145 {
6146         MonoClass *klass;
6147         int length;
6148         int i;
6149
6150         klass = array->obj.vtable->klass;
6151
6152         if (array->bounds == NULL)
6153                 length = array->max_length;
6154         else {
6155                 length = 1;
6156                 for (i = 0; i < klass->rank; ++ i)
6157                         length *= array->bounds [i].length;
6158         }
6159
6160         switch (klass->element_class->byval_arg.type) {
6161         case MONO_TYPE_I1:
6162         case MONO_TYPE_U1:
6163         case MONO_TYPE_BOOLEAN:
6164                 return length;
6165         case MONO_TYPE_I2:
6166         case MONO_TYPE_U2:
6167         case MONO_TYPE_CHAR:
6168                 return length << 1;
6169         case MONO_TYPE_I4:
6170         case MONO_TYPE_U4:
6171         case MONO_TYPE_R4:
6172                 return length << 2;
6173         case MONO_TYPE_I:
6174         case MONO_TYPE_U:
6175                 return length * sizeof (gpointer);
6176         case MONO_TYPE_I8:
6177         case MONO_TYPE_U8:
6178         case MONO_TYPE_R8:
6179                 return length << 3;
6180         default:
6181                 return -1;
6182         }
6183 }
6184
6185 ICALL_EXPORT gint32 
6186 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array) 
6187 {
6188         MONO_ARCH_SAVE_REGS;
6189
6190         return mono_array_get_byte_length (array);
6191 }
6192
6193 ICALL_EXPORT gint8 
6194 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx) 
6195 {
6196         MONO_ARCH_SAVE_REGS;
6197
6198         return mono_array_get (array, gint8, idx);
6199 }
6200
6201 ICALL_EXPORT void 
6202 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value) 
6203 {
6204         MONO_ARCH_SAVE_REGS;
6205
6206         mono_array_set (array, gint8, idx, value);
6207 }
6208
6209 ICALL_EXPORT MonoBoolean
6210 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count) 
6211 {
6212         guint8 *src_buf, *dest_buf;
6213
6214         MONO_ARCH_SAVE_REGS;
6215
6216         /* This is called directly from the class libraries without going through the managed wrapper */
6217         MONO_CHECK_ARG_NULL (src);
6218         MONO_CHECK_ARG_NULL (dest);
6219
6220         /* watch out for integer overflow */
6221         if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6222                 return FALSE;
6223
6224         src_buf = (guint8 *)src->vector + src_offset;
6225         dest_buf = (guint8 *)dest->vector + dest_offset;
6226
6227         if (src != dest)
6228                 memcpy (dest_buf, src_buf, count);
6229         else
6230                 mono_gc_memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6231
6232         return TRUE;
6233 }
6234
6235 #ifndef DISABLE_REMOTING
6236 ICALL_EXPORT MonoObject *
6237 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6238 {
6239         MonoDomain *domain = mono_object_domain (this); 
6240         MonoObject *res;
6241         MonoRealProxy *rp = ((MonoRealProxy *)this);
6242         MonoTransparentProxy *tp;
6243         MonoType *type;
6244         MonoClass *klass;
6245
6246         MONO_ARCH_SAVE_REGS;
6247
6248         res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6249         tp = (MonoTransparentProxy*) res;
6250         
6251         MONO_OBJECT_SETREF (tp, rp, rp);
6252         type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6253         klass = mono_class_from_mono_type (type);
6254
6255         tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6256         tp->remote_class = mono_remote_class (domain, class_name, klass);
6257
6258         res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6259         return res;
6260 }
6261
6262 ICALL_EXPORT MonoReflectionType *
6263 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6264 {
6265         return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6266 }
6267 #endif
6268
6269 /* System.Environment */
6270
6271 MonoString*
6272 ves_icall_System_Environment_get_UserName (void)
6273 {
6274         MONO_ARCH_SAVE_REGS;
6275
6276         /* using glib is more portable */
6277         return mono_string_new (mono_domain_get (), g_get_user_name ());
6278 }
6279
6280
6281 ICALL_EXPORT MonoString *
6282 ves_icall_System_Environment_get_MachineName (void)
6283 {
6284 #if defined (HOST_WIN32)
6285         gunichar2 *buf;
6286         guint32 len;
6287         MonoString *result;
6288
6289         len = MAX_COMPUTERNAME_LENGTH + 1;
6290         buf = g_new (gunichar2, len);
6291
6292         result = NULL;
6293         if (GetComputerName (buf, (PDWORD) &len))
6294                 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6295
6296         g_free (buf);
6297         return result;
6298 #elif !defined(DISABLE_SOCKETS)
6299         gchar buf [256];
6300         MonoString *result;
6301
6302         if (gethostname (buf, sizeof (buf)) == 0)
6303                 result = mono_string_new (mono_domain_get (), buf);
6304         else
6305                 result = NULL;
6306         
6307         return result;
6308 #else
6309         return mono_string_new (mono_domain_get (), "mono");
6310 #endif
6311 }
6312
6313 ICALL_EXPORT int
6314 ves_icall_System_Environment_get_Platform (void)
6315 {
6316 #if defined (TARGET_WIN32)
6317         /* Win32NT */
6318         return 2;
6319 #elif defined(__MACH__)
6320         /* OSX */
6321         //
6322         // Notice that the value is hidden from user code, and only exposed
6323         // to mscorlib.   This is due to Mono's Unix/MacOS code predating the
6324         // define and making assumptions based on Unix/128/4 values before there
6325         // was a MacOS define.    Lots of code would assume that not-Unix meant
6326         // Windows, but in this case, it would be OSX. 
6327         //
6328         return 6;
6329 #else
6330         /* Unix */
6331         return 4;
6332 #endif
6333 }
6334
6335 ICALL_EXPORT MonoString *
6336 ves_icall_System_Environment_get_NewLine (void)
6337 {
6338         MONO_ARCH_SAVE_REGS;
6339
6340 #if defined (HOST_WIN32)
6341         return mono_string_new (mono_domain_get (), "\r\n");
6342 #else
6343         return mono_string_new (mono_domain_get (), "\n");
6344 #endif
6345 }
6346
6347 ICALL_EXPORT MonoString *
6348 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6349 {
6350         const gchar *value;
6351         gchar *utf8_name;
6352
6353         MONO_ARCH_SAVE_REGS;
6354
6355         if (name == NULL)
6356                 return NULL;
6357
6358         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6359         value = g_getenv (utf8_name);
6360
6361         g_free (utf8_name);
6362
6363         if (value == 0)
6364                 return NULL;
6365         
6366         return mono_string_new (mono_domain_get (), value);
6367 }
6368
6369 /*
6370  * There is no standard way to get at environ.
6371  */
6372 #ifndef _MSC_VER
6373 #ifndef __MINGW32_VERSION
6374 #if defined(__APPLE__) && !defined (__arm__)
6375 /* Apple defines this in crt_externs.h but doesn't provide that header for 
6376  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
6377  * in fact exist on all implementations (so far) 
6378  */
6379 gchar ***_NSGetEnviron(void);
6380 #define environ (*_NSGetEnviron())
6381 #else
6382 extern
6383 char **environ;
6384 #endif
6385 #endif
6386 #endif
6387
6388 ICALL_EXPORT MonoArray *
6389 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6390 {
6391 #ifdef HOST_WIN32
6392         MonoArray *names;
6393         MonoDomain *domain;
6394         MonoString *str;
6395         WCHAR* env_strings;
6396         WCHAR* env_string;
6397         WCHAR* equal_str;
6398         int n = 0;
6399
6400         env_strings = GetEnvironmentStrings();
6401
6402         if (env_strings) {
6403                 env_string = env_strings;
6404                 while (*env_string != '\0') {
6405                 /* weird case that MS seems to skip */
6406                         if (*env_string != '=')
6407                                 n++;
6408                         while (*env_string != '\0')
6409                                 env_string++;
6410                         env_string++;
6411                 }
6412         }
6413
6414         domain = mono_domain_get ();
6415         names = mono_array_new (domain, mono_defaults.string_class, n);
6416
6417         if (env_strings) {
6418                 n = 0;
6419                 env_string = env_strings;
6420                 while (*env_string != '\0') {
6421                         /* weird case that MS seems to skip */
6422                         if (*env_string != '=') {
6423                                 equal_str = wcschr(env_string, '=');
6424                                 g_assert(equal_str);
6425                                 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6426                                 mono_array_setref (names, n, str);
6427                                 n++;
6428                         }
6429                         while (*env_string != '\0')
6430                                 env_string++;
6431                         env_string++;
6432                 }
6433
6434                 FreeEnvironmentStrings (env_strings);
6435         }
6436
6437         return names;
6438
6439 #else
6440         MonoArray *names;
6441         MonoDomain *domain;
6442         MonoString *str;
6443         gchar **e, **parts;
6444         int n;
6445
6446         MONO_ARCH_SAVE_REGS;
6447
6448         n = 0;
6449         for (e = environ; *e != 0; ++ e)
6450                 ++ n;
6451
6452         domain = mono_domain_get ();
6453         names = mono_array_new (domain, mono_defaults.string_class, n);
6454
6455         n = 0;
6456         for (e = environ; *e != 0; ++ e) {
6457                 parts = g_strsplit (*e, "=", 2);
6458                 if (*parts != 0) {
6459                         str = mono_string_new (domain, *parts);
6460                         mono_array_setref (names, n, str);
6461                 }
6462
6463                 g_strfreev (parts);
6464
6465                 ++ n;
6466         }
6467
6468         return names;
6469 #endif
6470 }
6471
6472 /*
6473  * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6474  */
6475 #if !GLIB_CHECK_VERSION(2,4,0)
6476 #define g_setenv(a,b,c)   setenv(a,b,c)
6477 #define g_unsetenv(a) unsetenv(a)
6478 #endif
6479
6480 ICALL_EXPORT void
6481 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6482 {
6483         MonoError error;
6484 #ifdef HOST_WIN32
6485
6486         gunichar2 *utf16_name, *utf16_value;
6487 #else
6488         gchar *utf8_name, *utf8_value;
6489 #endif
6490
6491         MONO_ARCH_SAVE_REGS;
6492         
6493 #ifdef HOST_WIN32
6494         utf16_name = mono_string_to_utf16 (name);
6495         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6496                 SetEnvironmentVariable (utf16_name, NULL);
6497                 g_free (utf16_name);
6498                 return;
6499         }
6500
6501         utf16_value = mono_string_to_utf16 (value);
6502
6503         SetEnvironmentVariable (utf16_name, utf16_value);
6504
6505         g_free (utf16_name);
6506         g_free (utf16_value);
6507 #else
6508         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6509
6510         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6511                 g_unsetenv (utf8_name);
6512                 g_free (utf8_name);
6513                 return;
6514         }
6515
6516         utf8_value = mono_string_to_utf8_checked (value, &error);
6517         if (!mono_error_ok (&error)) {
6518                 g_free (utf8_name);
6519                 mono_error_raise_exception (&error);
6520         }
6521         g_setenv (utf8_name, utf8_value, TRUE);
6522
6523         g_free (utf8_name);
6524         g_free (utf8_value);
6525 #endif
6526 }
6527
6528 ICALL_EXPORT void
6529 ves_icall_System_Environment_Exit (int result)
6530 {
6531         MONO_ARCH_SAVE_REGS;
6532
6533 #ifndef MONO_CROSS_COMPILE
6534         mono_runtime_shutdown ();
6535 #endif
6536
6537         mono_threads_set_shutting_down ();
6538
6539         mono_runtime_set_shutting_down ();
6540
6541         /* This will kill the tp threads which cannot be suspended */
6542         mono_thread_pool_cleanup ();
6543
6544         /* Suspend all managed threads since the runtime is going away */
6545         mono_thread_suspend_all_other_threads ();
6546
6547         mono_runtime_quit ();
6548
6549         /* we may need to do some cleanup here... */
6550         exit (result);
6551 }
6552
6553 ICALL_EXPORT MonoString*
6554 ves_icall_System_Environment_GetGacPath (void)
6555 {
6556         return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6557 }
6558
6559 ICALL_EXPORT MonoString*
6560 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6561 {
6562 #if defined (HOST_WIN32)
6563         #ifndef CSIDL_FLAG_CREATE
6564                 #define CSIDL_FLAG_CREATE       0x8000
6565         #endif
6566
6567         WCHAR path [MAX_PATH];
6568         /* Create directory if no existing */
6569         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6570                 int len = 0;
6571                 while (path [len])
6572                         ++ len;
6573                 return mono_string_new_utf16 (mono_domain_get (), path, len);
6574         }
6575 #else
6576         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6577 #endif
6578         return mono_string_new (mono_domain_get (), "");
6579 }
6580
6581 ICALL_EXPORT MonoArray *
6582 ves_icall_System_Environment_GetLogicalDrives (void)
6583 {
6584         gunichar2 buf [256], *ptr, *dname;
6585         gunichar2 *u16;
6586         guint initial_size = 127, size = 128;
6587         gint ndrives;
6588         MonoArray *result;
6589         MonoString *drivestr;
6590         MonoDomain *domain = mono_domain_get ();
6591         gint len;
6592
6593         MONO_ARCH_SAVE_REGS;
6594
6595         buf [0] = '\0';
6596         ptr = buf;
6597
6598         while (size > initial_size) {
6599                 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6600                 if (size > initial_size) {
6601                         if (ptr != buf)
6602                                 g_free (ptr);
6603                         ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6604                         initial_size = size;
6605                         size++;
6606                 }
6607         }
6608
6609         /* Count strings */
6610         dname = ptr;
6611         ndrives = 0;
6612         do {
6613                 while (*dname++);
6614                 ndrives++;
6615         } while (*dname);
6616
6617         dname = ptr;
6618         result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6619         ndrives = 0;
6620         do {
6621                 len = 0;
6622                 u16 = dname;
6623                 while (*u16) { u16++; len ++; }
6624                 drivestr = mono_string_new_utf16 (domain, dname, len);
6625                 mono_array_setref (result, ndrives++, drivestr);
6626                 while (*dname++);
6627         } while (*dname);
6628
6629         if (ptr != buf)
6630                 g_free (ptr);
6631
6632         return result;
6633 }
6634
6635 ICALL_EXPORT MonoString *
6636 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6637 {
6638         gunichar2 volume_name [MAX_PATH + 1];
6639         
6640         if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6641                 return NULL;
6642         return mono_string_from_utf16 (volume_name);
6643 }
6644
6645 ICALL_EXPORT MonoString *
6646 ves_icall_System_Environment_InternalGetHome (void)
6647 {
6648         MONO_ARCH_SAVE_REGS;
6649
6650         return mono_string_new (mono_domain_get (), g_get_home_dir ());
6651 }
6652
6653 static const char *encodings [] = {
6654         (char *) 1,
6655                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6656                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6657                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6658         (char *) 2,
6659                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6660                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6661                 "x_unicode_2_0_utf_7",
6662         (char *) 3,
6663                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6664                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6665         (char *) 4,
6666                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6667                 "iso_10646_ucs2",
6668         (char *) 5,
6669                 "unicodefffe", "utf_16be",
6670         (char *) 6,
6671                 "iso_8859_1",
6672         (char *) 0
6673 };
6674
6675 /*
6676  * Returns the internal codepage, if the value of "int_code_page" is
6677  * 1 at entry, and we can not compute a suitable code page number,
6678  * returns the code page as a string
6679  */
6680 ICALL_EXPORT MonoString*
6681 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page) 
6682 {
6683         const char *cset;
6684         const char *p;
6685         char *c;
6686         char *codepage = NULL;
6687         int code;
6688         int want_name = *int_code_page;
6689         int i;
6690         
6691         *int_code_page = -1;
6692         MONO_ARCH_SAVE_REGS;
6693
6694         g_get_charset (&cset);
6695         c = codepage = strdup (cset);
6696         for (c = codepage; *c; c++){
6697                 if (isascii (*c) && isalpha (*c))
6698                         *c = tolower (*c);
6699                 if (*c == '-')
6700                         *c = '_';
6701         }
6702         /* g_print ("charset: %s\n", cset); */
6703         
6704         /* handle some common aliases */
6705         p = encodings [0];
6706         code = 0;
6707         for (i = 0; p != 0; ){
6708                 if ((gssize) p < 7){
6709                         code = (gssize) p;
6710                         p = encodings [++i];
6711                         continue;
6712                 }
6713                 if (strcmp (p, codepage) == 0){
6714                         *int_code_page = code;
6715                         break;
6716                 }
6717                 p = encodings [++i];
6718         }
6719         
6720         if (strstr (codepage, "utf_8") != NULL)
6721                 *int_code_page |= 0x10000000;
6722         free (codepage);
6723         
6724         if (want_name && *int_code_page == -1)
6725                 return mono_string_new (mono_domain_get (), cset);
6726         else
6727                 return NULL;
6728 }
6729
6730 ICALL_EXPORT MonoBoolean
6731 ves_icall_System_Environment_get_HasShutdownStarted (void)
6732 {
6733         if (mono_runtime_is_shutting_down ())
6734                 return TRUE;
6735
6736         if (mono_domain_is_unloading (mono_domain_get ()))
6737                 return TRUE;
6738
6739         return FALSE;
6740 }
6741
6742 ICALL_EXPORT void
6743 ves_icall_System_Environment_BroadcastSettingChange (void)
6744 {
6745 #ifdef HOST_WIN32
6746         SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6747 #endif
6748 }
6749
6750 ICALL_EXPORT void
6751 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this, 
6752                                          MonoReflectionMethod *method,
6753                                          MonoArray *out_args)
6754 {
6755         MONO_ARCH_SAVE_REGS;
6756
6757         mono_message_init (mono_object_domain (this), this, method, out_args);
6758 }
6759
6760 #ifndef DISABLE_REMOTING
6761 ICALL_EXPORT MonoBoolean
6762 ves_icall_IsTransparentProxy (MonoObject *proxy)
6763 {
6764         MONO_ARCH_SAVE_REGS;
6765
6766         if (!proxy)
6767                 return 0;
6768
6769         if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6770                 return 1;
6771
6772         return 0;
6773 }
6774
6775 ICALL_EXPORT MonoReflectionMethod *
6776 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6777         MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6778 {
6779         MonoClass *klass;
6780         MonoMethod *method;
6781         MonoMethod **vtable;
6782         MonoMethod *res = NULL;
6783
6784         MONO_CHECK_ARG_NULL (rtype);
6785         MONO_CHECK_ARG_NULL (rmethod);
6786
6787         method = rmethod->method;
6788         klass = mono_class_from_mono_type (rtype->type);
6789         mono_class_init_or_throw (klass);
6790
6791         if (MONO_CLASS_IS_INTERFACE (klass))
6792                 return NULL;
6793
6794         if (method->flags & METHOD_ATTRIBUTE_STATIC)
6795                 return NULL;
6796
6797         if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6798                 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6799                         return rmethod;
6800                 else
6801                         return NULL;
6802         }
6803
6804         mono_class_setup_vtable (klass);
6805         vtable = klass->vtable;
6806
6807         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6808                 gboolean variance_used = FALSE;
6809                 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6810                 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6811                 if (offs >= 0)
6812                         res = vtable [offs + method->slot];
6813         } else {
6814                 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6815                         return NULL;
6816
6817                 if (method->slot != -1)
6818                         res = vtable [method->slot];
6819         }
6820
6821         if (!res)
6822                 return NULL;
6823
6824         return mono_method_get_object (mono_domain_get (), res, NULL);
6825 }
6826
6827 ICALL_EXPORT void
6828 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6829 {
6830         MonoClass *klass;
6831         MonoVTable* vtable;
6832
6833         MONO_ARCH_SAVE_REGS;
6834
6835         klass = mono_class_from_mono_type (type->type);
6836         vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6837
6838         if (enable) vtable->remote = 1;
6839         else vtable->remote = 0;
6840 }
6841 #endif
6842
6843 ICALL_EXPORT MonoObject *
6844 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6845 {
6846         MonoClass *klass;
6847         MonoDomain *domain;
6848         
6849         MONO_ARCH_SAVE_REGS;
6850
6851         domain = mono_object_domain (type);
6852         klass = mono_class_from_mono_type (type->type);
6853         mono_class_init_or_throw (klass);
6854
6855         if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6856                 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6857
6858         if (klass->rank >= 1) {
6859                 g_assert (klass->rank == 1);
6860                 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6861         } else {
6862                 /* Bypass remoting object creation check */
6863                 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6864         }
6865 }
6866
6867 ICALL_EXPORT MonoString *
6868 ves_icall_System_IO_get_temp_path (void)
6869 {
6870         MONO_ARCH_SAVE_REGS;
6871
6872         return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6873 }
6874
6875 #ifndef PLATFORM_NO_DRIVEINFO
6876 ICALL_EXPORT MonoBoolean
6877 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6878                                                 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6879                                                 gint32 *error)
6880 {
6881         gboolean result;
6882         ULARGE_INTEGER wapi_free_bytes_avail;
6883         ULARGE_INTEGER wapi_total_number_of_bytes;
6884         ULARGE_INTEGER wapi_total_number_of_free_bytes;
6885
6886         MONO_ARCH_SAVE_REGS;
6887
6888         *error = ERROR_SUCCESS;
6889         result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6890                                      &wapi_total_number_of_free_bytes);
6891
6892         if (result) {
6893                 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6894                 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6895                 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6896         } else {
6897                 *free_bytes_avail = 0;
6898                 *total_number_of_bytes = 0;
6899                 *total_number_of_free_bytes = 0;
6900                 *error = GetLastError ();
6901         }
6902
6903         return result;
6904 }
6905
6906 ICALL_EXPORT guint32
6907 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6908 {
6909         MONO_ARCH_SAVE_REGS;
6910
6911         return GetDriveType (mono_string_chars (root_path_name));
6912 }
6913 #endif
6914
6915 ICALL_EXPORT gpointer
6916 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6917 {
6918         MONO_ARCH_SAVE_REGS;
6919
6920         return mono_compile_method (method);
6921 }
6922
6923 ICALL_EXPORT MonoString *
6924 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6925 {
6926         MonoString *mcpath;
6927         gchar *path;
6928
6929         MONO_ARCH_SAVE_REGS;
6930
6931         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6932
6933 #if defined (HOST_WIN32)
6934         /* Avoid mixing '/' and '\\' */
6935         {
6936                 gint i;
6937                 for (i = strlen (path) - 1; i >= 0; i--)
6938                         if (path [i] == '/')
6939                                 path [i] = '\\';
6940         }
6941 #endif
6942         mcpath = mono_string_new (mono_domain_get (), path);
6943         g_free (path);
6944
6945         return mcpath;
6946 }
6947
6948 static MonoString *
6949 get_bundled_app_config (void)
6950 {
6951         const gchar *app_config;
6952         MonoDomain *domain;
6953         MonoString *file;
6954         gchar *config_file_name, *config_file_path;
6955         gsize len;
6956         gchar *module;
6957
6958         MONO_ARCH_SAVE_REGS;
6959
6960         domain = mono_domain_get ();
6961         file = domain->setup->configuration_file;
6962         if (!file)
6963                 return NULL;
6964
6965         // Retrieve config file and remove the extension
6966         config_file_name = mono_string_to_utf8 (file);
6967         config_file_path = mono_portability_find_file (config_file_name, TRUE);
6968         if (!config_file_path)
6969                 config_file_path = config_file_name;
6970         len = strlen (config_file_path) - strlen (".config");
6971         module = g_malloc0 (len + 1);
6972         memcpy (module, config_file_path, len);
6973         // Get the config file from the module name
6974         app_config = mono_config_string_for_assembly_file (module);
6975         // Clean-up
6976         g_free (module);
6977         if (config_file_name != config_file_path)
6978                 g_free (config_file_name);
6979         g_free (config_file_path);
6980
6981         if (!app_config)
6982                 return NULL;
6983
6984         return mono_string_new (mono_domain_get (), app_config);
6985 }
6986
6987 static MonoString *
6988 get_bundled_machine_config (void)
6989 {
6990         const gchar *machine_config;
6991
6992         MONO_ARCH_SAVE_REGS;
6993
6994         machine_config = mono_get_machine_config ();
6995
6996         if (!machine_config)
6997                 return NULL;
6998
6999         return mono_string_new (mono_domain_get (), machine_config);
7000 }
7001
7002 ICALL_EXPORT MonoString *
7003 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7004 {
7005         MonoString *ipath;
7006         gchar *path;
7007
7008         MONO_ARCH_SAVE_REGS;
7009
7010         path = g_path_get_dirname (mono_get_config_dir ());
7011
7012 #if defined (HOST_WIN32)
7013         /* Avoid mixing '/' and '\\' */
7014         {
7015                 gint i;
7016                 for (i = strlen (path) - 1; i >= 0; i--)
7017                         if (path [i] == '/')
7018                                 path [i] = '\\';
7019         }
7020 #endif
7021         ipath = mono_string_new (mono_domain_get (), path);
7022         g_free (path);
7023
7024         return ipath;
7025 }
7026
7027 ICALL_EXPORT gboolean
7028 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7029 {
7030         MonoPEResourceDataEntry *entry;
7031         MonoImage *image;
7032
7033         MONO_ARCH_SAVE_REGS;
7034
7035         if (!assembly || !result || !size)
7036                 return FALSE;
7037
7038         *result = NULL;
7039         *size = 0;
7040         image = assembly->assembly->image;
7041         entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7042         if (!entry)
7043                 return FALSE;
7044
7045         *result = mono_image_rva_map (image, entry->rde_data_offset);
7046         if (!(*result)) {
7047                 g_free (entry);
7048                 return FALSE;
7049         }
7050         *size = entry->rde_size;
7051         g_free (entry);
7052         return TRUE;
7053 }
7054
7055 ICALL_EXPORT MonoBoolean
7056 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7057 {
7058         return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
7059 }
7060
7061 ICALL_EXPORT MonoBoolean
7062 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7063 {
7064         if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7065                 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7066         else
7067                 return FALSE;
7068 }
7069
7070 ICALL_EXPORT void
7071 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7072 {
7073         if (mono_get_runtime_callbacks ()->debug_log)
7074                 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7075 }
7076
7077 ICALL_EXPORT void
7078 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7079 {
7080 #if defined (HOST_WIN32)
7081         OutputDebugString (mono_string_chars (message));
7082 #else
7083         g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7084 #endif
7085 }
7086
7087 /* Only used for value types */
7088 ICALL_EXPORT MonoObject *
7089 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7090 {
7091         MonoClass *klass;
7092         MonoDomain *domain;
7093         
7094         MONO_ARCH_SAVE_REGS;
7095
7096         domain = mono_object_domain (type);
7097         klass = mono_class_from_mono_type (type->type);
7098         mono_class_init_or_throw (klass);
7099
7100         if (mono_class_is_nullable (klass))
7101                 /* No arguments -> null */
7102                 return NULL;
7103
7104         return mono_object_new (domain, klass);
7105 }
7106
7107 ICALL_EXPORT MonoReflectionMethod *
7108 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7109 {
7110         MonoClass *klass, *parent;
7111         MonoMethod *method = m->method;
7112         MonoMethod *result = NULL;
7113         int slot;
7114
7115         MONO_ARCH_SAVE_REGS;
7116
7117         if (method->klass == NULL)
7118                 return m;
7119
7120         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7121             MONO_CLASS_IS_INTERFACE (method->klass) ||
7122             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7123                 return m;
7124
7125         slot = mono_method_get_vtable_slot (method);
7126         if (slot == -1)
7127                 return m;
7128
7129         klass = method->klass;
7130         if (klass->generic_class)
7131                 klass = klass->generic_class->container_class;
7132
7133         if (definition) {
7134                 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7135                 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7136                         mono_class_setup_vtable (parent);
7137                         if (parent->vtable_size <= slot)
7138                                 break;
7139                         klass = parent;
7140                 }
7141         } else {
7142                 klass = klass->parent;
7143                 if (!klass)
7144                         return m;
7145         }
7146
7147         if (klass == method->klass)
7148                 return m;
7149
7150         /*This is possible if definition == FALSE.
7151          * Do it here to be really sure we don't read invalid memory.
7152          */
7153         if (slot >= klass->vtable_size)
7154                 return m;
7155
7156         mono_class_setup_vtable (klass);
7157
7158         result = klass->vtable [slot];
7159         if (result == NULL) {
7160                 /* It is an abstract method */
7161                 gpointer iter = NULL;
7162                 while ((result = mono_class_get_methods (klass, &iter)))
7163                         if (result->slot == slot)
7164                                 break;
7165         }
7166
7167         if (result == NULL)
7168                 return m;
7169
7170         return mono_method_get_object (mono_domain_get (), result, NULL);
7171 }
7172
7173 ICALL_EXPORT MonoString*
7174 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7175 {
7176         MonoMethod *method = m->method;
7177
7178         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7179         return m->name;
7180 }
7181
7182 ICALL_EXPORT void
7183 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7184 {
7185         MONO_ARCH_SAVE_REGS;
7186
7187         iter->sig = *(MonoMethodSignature**)argsp;
7188         
7189         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7190         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7191
7192         iter->next_arg = 0;
7193         /* FIXME: it's not documented what start is exactly... */
7194         if (start) {
7195                 iter->args = start;
7196         } else {
7197                 iter->args = argsp + sizeof (gpointer);
7198         }
7199         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7200
7201         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7202 }
7203
7204 ICALL_EXPORT MonoTypedRef
7205 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7206 {
7207         guint32 i, arg_size;
7208         gint32 align;
7209         MonoTypedRef res;
7210         MONO_ARCH_SAVE_REGS;
7211
7212         i = iter->sig->sentinelpos + iter->next_arg;
7213
7214         g_assert (i < iter->sig->param_count);
7215
7216         res.type = iter->sig->params [i];
7217         res.klass = mono_class_from_mono_type (res.type);
7218         arg_size = mono_type_stack_size (res.type, &align);
7219 #if defined(__arm__) || defined(__mips__)
7220         iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7221 #endif
7222         res.value = iter->args;
7223 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7224         if (arg_size <= sizeof (gpointer)) {
7225                 int dummy;
7226                 int padding = arg_size - mono_type_size (res.type, &dummy);
7227                 res.value = (guint8*)res.value + padding;
7228         }
7229 #endif
7230         iter->args = (char*)iter->args + arg_size;
7231         iter->next_arg++;
7232
7233         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7234
7235         return res;
7236 }
7237
7238 ICALL_EXPORT MonoTypedRef
7239 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7240 {
7241         guint32 i, arg_size;
7242         gint32 align;
7243         MonoTypedRef res;
7244         MONO_ARCH_SAVE_REGS;
7245
7246         i = iter->sig->sentinelpos + iter->next_arg;
7247
7248         g_assert (i < iter->sig->param_count);
7249
7250         while (i < iter->sig->param_count) {
7251                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7252                         continue;
7253                 res.type = iter->sig->params [i];
7254                 res.klass = mono_class_from_mono_type (res.type);
7255                 /* FIXME: endianess issue... */
7256                 arg_size = mono_type_stack_size (res.type, &align);
7257 #if defined(__arm__) || defined(__mips__)
7258                 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7259 #endif
7260                 res.value = iter->args;
7261                 iter->args = (char*)iter->args + arg_size;
7262                 iter->next_arg++;
7263                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7264                 return res;
7265         }
7266         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7267
7268         res.type = NULL;
7269         res.value = NULL;
7270         res.klass = NULL;
7271         return res;
7272 }
7273
7274 ICALL_EXPORT MonoType*
7275 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7276 {
7277         gint i;
7278         MONO_ARCH_SAVE_REGS;
7279         
7280         i = iter->sig->sentinelpos + iter->next_arg;
7281
7282         g_assert (i < iter->sig->param_count);
7283
7284         return iter->sig->params [i];
7285 }
7286
7287 ICALL_EXPORT MonoObject*
7288 mono_TypedReference_ToObject (MonoTypedRef tref)
7289 {
7290         MONO_ARCH_SAVE_REGS;
7291
7292         if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7293                 MonoObject** objp = tref.value;
7294                 return *objp;
7295         }
7296
7297         return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7298 }
7299
7300 ICALL_EXPORT MonoObject*
7301 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7302 {
7303         MONO_ARCH_SAVE_REGS;
7304
7305         if (MONO_TYPE_IS_REFERENCE (type)) {
7306                 MonoObject** objp = value;
7307                 return *objp;
7308         }
7309
7310         return mono_value_box (mono_domain_get (), klass, value);
7311 }
7312
7313 static void
7314 prelink_method (MonoMethod *method)
7315 {
7316         const char *exc_class, *exc_arg;
7317         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7318                 return;
7319         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7320         if (exc_class) {
7321                 mono_raise_exception( 
7322                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7323         }
7324         /* create the wrapper, too? */
7325 }
7326
7327 ICALL_EXPORT void
7328 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7329 {
7330         MONO_ARCH_SAVE_REGS;
7331         prelink_method (method->method);
7332 }
7333
7334 ICALL_EXPORT void
7335 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7336 {
7337         MonoClass *klass = mono_class_from_mono_type (type->type);
7338         MonoMethod* m;
7339         gpointer iter = NULL;
7340         MONO_ARCH_SAVE_REGS;
7341
7342         mono_class_init_or_throw (klass);
7343
7344         while ((m = mono_class_get_methods (klass, &iter)))
7345                 prelink_method (m);
7346 }
7347
7348 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7349 ICALL_EXPORT void
7350 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7351                                             gint32 const **exponents,
7352                                             gunichar2 const **digitLowerTable,
7353                                             gunichar2 const **digitUpperTable,
7354                                             gint64 const **tenPowersList,
7355                                             gint32 const **decHexDigits)
7356 {
7357         *mantissas = Formatter_MantissaBitsTable;
7358         *exponents = Formatter_TensExponentTable;
7359         *digitLowerTable = Formatter_DigitLowerTable;
7360         *digitUpperTable = Formatter_DigitUpperTable;
7361         *tenPowersList = Formatter_TenPowersList;
7362         *decHexDigits = Formatter_DecHexDigits;
7363 }
7364
7365 ICALL_EXPORT void
7366 get_category_data (int version,
7367                    guint8 const **category_data,
7368                    guint16 const **category_astral_index)
7369 {
7370         *category_astral_index = NULL;
7371
7372 #ifndef DISABLE_NET_4_0
7373         if (version == 4) {
7374                 *category_data = CategoryData_v4;
7375 #ifndef DISABLE_ASTRAL
7376                 *category_astral_index = CategoryData_v4_astral_index;
7377 #endif
7378                 return;
7379         }
7380 #endif
7381
7382         *category_data = CategoryData_v2;
7383 #ifndef DISABLE_ASTRAL
7384         *category_astral_index = CategoryData_v2_astral_index;
7385 #endif
7386 }
7387
7388 /* These parameters are "readonly" in corlib/System/Char.cs */
7389 ICALL_EXPORT void
7390 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7391                                             guint8 const **category_data,
7392                                             guint16 const **category_astral_index,
7393                                             guint8 const **numeric_data,
7394                                             gdouble const **numeric_data_values,
7395                                             guint16 const **to_lower_data_low,
7396                                             guint16 const **to_lower_data_high,
7397                                             guint16 const **to_upper_data_low,
7398                                             guint16 const **to_upper_data_high)
7399 {
7400         get_category_data (category_data_version, category_data, category_astral_index);
7401         *numeric_data = NumericData;
7402         *numeric_data_values = NumericDataValues;
7403         *to_lower_data_low = ToLowerDataLow;
7404         *to_lower_data_high = ToLowerDataHigh;
7405         *to_upper_data_low = ToUpperDataLow;
7406         *to_upper_data_high = ToUpperDataHigh;
7407 }
7408
7409 ICALL_EXPORT gint32
7410 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7411 {
7412         return method->method->token;
7413 }
7414
7415 /*
7416  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7417  * and avoid useless allocations.
7418  */
7419 static MonoArray*
7420 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7421 {
7422         MonoArray *res;
7423         int i, count = 0;
7424         for (i = 0; i < type->num_mods; ++i) {
7425                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7426                         count++;
7427         }
7428         if (!count)
7429                 return NULL;
7430         res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7431         count = 0;
7432         for (i = 0; i < type->num_mods; ++i) {
7433                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7434                         MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7435                         mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7436                         count++;
7437                 }
7438         }
7439         return res;
7440 }
7441
7442 ICALL_EXPORT MonoArray*
7443 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7444 {
7445         MonoType *type = param->ClassImpl->type;
7446         MonoClass *member_class = mono_object_class (param->MemberImpl);
7447         MonoMethod *method = NULL;
7448         MonoImage *image;
7449         int pos;
7450         MonoMethodSignature *sig;
7451
7452         if (mono_class_is_reflection_method_or_constructor (member_class)) {
7453                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7454                 method = rmethod->method;
7455         } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7456                 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7457                 if (!(method = prop->property->get))
7458                         method = prop->property->set;
7459                 g_assert (method);      
7460         } else {
7461                 char *type_name = mono_type_get_full_name (member_class);
7462                 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7463                 MonoException *ex = mono_get_exception_not_supported  (msg);
7464                 g_free (type_name);
7465                 g_free (msg);
7466                 mono_raise_exception (ex);
7467         }
7468
7469         image = method->klass->image;
7470         pos = param->PositionImpl;
7471         sig = mono_method_signature (method);
7472         if (pos == -1)
7473                 type = sig->ret;
7474         else
7475                 type = sig->params [pos];
7476
7477         return type_array_from_modifiers (image, type, optional);
7478 }
7479
7480 static MonoType*
7481 get_property_type (MonoProperty *prop)
7482 {
7483         MonoMethodSignature *sig;
7484         if (prop->get) {
7485                 sig = mono_method_signature (prop->get);
7486                 return sig->ret;
7487         } else if (prop->set) {
7488                 sig = mono_method_signature (prop->set);
7489                 return sig->params [sig->param_count - 1];
7490         }
7491         return NULL;
7492 }
7493
7494 ICALL_EXPORT MonoArray*
7495 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7496 {
7497         MonoType *type = get_property_type (property->property);
7498         MonoImage *image = property->klass->image;
7499
7500         if (!type)
7501                 return NULL;
7502         return type_array_from_modifiers (image, type, optional);
7503 }
7504
7505 /*
7506  *Construct a MonoType suited to be used to decode a constant blob object.
7507  *
7508  * @type is the target type which will be constructed
7509  * @blob_type is the blob type, for example, that comes from the constant table
7510  * @real_type is the expected constructed type.
7511  */
7512 static void
7513 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7514 {
7515         type->type = blob_type;
7516         type->data.klass = NULL;
7517         if (blob_type == MONO_TYPE_CLASS)
7518                 type->data.klass = mono_defaults.object_class;
7519         else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7520                 /* For enums, we need to use the base type */
7521                 type->type = MONO_TYPE_VALUETYPE;
7522                 type->data.klass = mono_class_from_mono_type (real_type);
7523         } else
7524                 type->data.klass = mono_class_from_mono_type (real_type);
7525 }
7526
7527 ICALL_EXPORT MonoObject*
7528 property_info_get_default_value (MonoReflectionProperty *property)
7529 {
7530         MonoType blob_type;
7531         MonoProperty *prop = property->property;
7532         MonoType *type = get_property_type (prop);
7533         MonoDomain *domain = mono_object_domain (property); 
7534         MonoTypeEnum def_type;
7535         const char *def_value;
7536         MonoObject *o;
7537
7538         mono_class_init (prop->parent);
7539
7540         if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7541                 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7542
7543         def_value = mono_class_get_property_default_value (prop, &def_type);
7544
7545         mono_type_from_blob_type (&blob_type, def_type, type);
7546         o = mono_get_object_from_blob (domain, &blob_type, def_value);
7547
7548         return o;
7549 }
7550
7551 ICALL_EXPORT MonoBoolean
7552 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7553 {
7554         MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7555         MonoCustomAttrInfo *cinfo;
7556         gboolean found;
7557
7558         mono_class_init_or_throw (attr_class);
7559
7560         cinfo = mono_reflection_get_custom_attrs_info (obj);
7561         if (!cinfo)
7562                 return FALSE;
7563         found = mono_custom_attrs_has_attr (cinfo, attr_class);
7564         if (!cinfo->cached)
7565                 mono_custom_attrs_free (cinfo);
7566         return found;
7567 }
7568
7569 ICALL_EXPORT MonoArray*
7570 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7571 {
7572         MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7573         MonoArray *res;
7574         MonoError error;
7575
7576         if (attr_class)
7577                 mono_class_init_or_throw (attr_class);
7578
7579         res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7580         if (!mono_error_ok (&error))
7581                 mono_error_raise_exception (&error);
7582         if (mono_loader_get_last_error ()) {
7583                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7584                 g_assert_not_reached ();
7585                 /* Not reached */
7586                 return NULL;
7587         } else {
7588                 return res;
7589         }
7590 }
7591
7592 ICALL_EXPORT MonoString*
7593 ves_icall_Mono_Runtime_GetDisplayName (void)
7594 {
7595         char *info;
7596         MonoString *display_name;
7597
7598         info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7599         display_name = mono_string_new (mono_domain_get (), info);
7600         g_free (info);
7601         return display_name;
7602 }
7603
7604 ICALL_EXPORT MonoString*
7605 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7606 {
7607         MonoString *message;
7608         guint32 ret;
7609         gunichar2 buf[256];
7610         
7611         ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7612                              FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7613                              buf, 255, NULL);
7614         if (ret == 0) {
7615                 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7616         } else {
7617                 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7618         }
7619         
7620         return message;
7621 }
7622
7623 const static guchar
7624 dbase64 [] = {
7625         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7626         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7627         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7628         52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7629         128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7630         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7631         128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7632         41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7633 };
7634
7635 static MonoArray *
7636 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7637 {
7638         gint ignored;
7639         gint i;
7640         gunichar2 c;
7641         gunichar2 last, prev_last, prev2_last;
7642         gint olength;
7643         MonoArray *result;
7644         guchar *res_ptr;
7645         gint a [4], b [4];
7646         MonoException *exc;
7647
7648         int havePadding = 0;
7649         ignored = 0;
7650         last = prev_last = 0, prev2_last = 0;
7651         for (i = 0; i < ilength; i++) {
7652                 c = start [i];
7653                 if (c >= sizeof (dbase64)) {
7654                         exc = mono_exception_from_name_msg (mono_get_corlib (),
7655                                 "System", "FormatException",
7656                                 "Invalid character found.");
7657                         mono_raise_exception (exc);
7658                 } else if (isspace (c)) {
7659                         ignored++;
7660                 } else if (havePadding && c != '=') {
7661                         exc = mono_exception_from_name_msg (mono_get_corlib (),
7662                                 "System", "FormatException",
7663                                 "Invalid character found.");
7664                         mono_raise_exception (exc);
7665                 } else {
7666                         if (c == '=') havePadding = 1;
7667                         prev2_last = prev_last;
7668                         prev_last = last;
7669                         last = c;
7670                 }
7671         }
7672
7673         olength = ilength - ignored;
7674
7675         if (allowWhitespaceOnly && olength == 0) {
7676                 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7677         }
7678
7679         if ((olength & 3) != 0 || olength <= 0) {
7680                 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7681                                         "FormatException", "Invalid length.");
7682                 mono_raise_exception (exc);
7683         }
7684
7685         if (prev2_last == '=') {
7686                 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7687                 mono_raise_exception (exc);
7688         }
7689
7690         olength = (olength * 3) / 4;
7691         if (last == '=')
7692                 olength--;
7693
7694         if (prev_last == '=')
7695                 olength--;
7696
7697         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7698         res_ptr = mono_array_addr (result, guchar, 0);
7699         for (i = 0; i < ilength; ) {
7700                 int k;
7701
7702                 for (k = 0; k < 4 && i < ilength;) {
7703                         c = start [i++];
7704                         if (isspace (c))
7705                                 continue;
7706
7707                         a [k] = (guchar) c;
7708                         if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7709                                 exc = mono_exception_from_name_msg (mono_get_corlib (),
7710                                         "System", "FormatException",
7711                                         "Invalid character found.");
7712                                 mono_raise_exception (exc);
7713                         }
7714                         k++;
7715                 }
7716
7717                 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7718                 if (a [2] != '=')
7719                         *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7720                 if (a [3] != '=')
7721                         *res_ptr++ = (b [2] << 6) | b [3];
7722
7723                 while (i < ilength && isspace (start [i]))
7724                         i++;
7725         }
7726
7727         return result;
7728 }
7729
7730 ICALL_EXPORT MonoArray *
7731 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7732 {
7733         MONO_ARCH_SAVE_REGS;
7734
7735         return base64_to_byte_array (mono_string_chars (str), 
7736                 mono_string_length (str), allowWhitespaceOnly);
7737 }
7738
7739 ICALL_EXPORT MonoArray *
7740 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7741 {
7742         MONO_ARCH_SAVE_REGS;
7743
7744         return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7745                 length, FALSE);
7746 }
7747
7748 #ifndef DISABLE_ICALL_TABLES
7749
7750 #define ICALL_TYPE(id,name,first)
7751 #define ICALL(id,name,func) Icall_ ## id,
7752
7753 enum {
7754 #include "metadata/icall-def.h"
7755         Icall_last
7756 };
7757
7758 #undef ICALL_TYPE
7759 #undef ICALL
7760 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7761 #define ICALL(id,name,func)
7762 enum {
7763 #include "metadata/icall-def.h"
7764         Icall_type_num
7765 };
7766
7767 #undef ICALL_TYPE
7768 #undef ICALL
7769 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7770 #define ICALL(id,name,func)
7771 typedef struct {
7772         guint16 first_icall;
7773 } IcallTypeDesc;
7774
7775 static const IcallTypeDesc
7776 icall_type_descs [] = {
7777 #include "metadata/icall-def.h"
7778         {Icall_last}
7779 };
7780
7781 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7782
7783 #undef ICALL_TYPE
7784 #define ICALL_TYPE(id,name,first)
7785 #undef ICALL
7786
7787 #ifdef HAVE_ARRAY_ELEM_INIT
7788 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7789 #define MSGSTRFIELD1(line) str##line
7790
7791 static const struct msgstrtn_t {
7792 #define ICALL(id,name,func)
7793 #undef ICALL_TYPE
7794 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7795 #include "metadata/icall-def.h"
7796 #undef ICALL_TYPE
7797 } icall_type_names_str = {
7798 #define ICALL_TYPE(id,name,first) (name),
7799 #include "metadata/icall-def.h"
7800 #undef ICALL_TYPE
7801 };
7802 static const guint16 icall_type_names_idx [] = {
7803 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7804 #include "metadata/icall-def.h"
7805 #undef ICALL_TYPE
7806 };
7807 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7808
7809 static const struct msgstr_t {
7810 #undef ICALL
7811 #define ICALL_TYPE(id,name,first)
7812 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7813 #include "metadata/icall-def.h"
7814 #undef ICALL
7815 } icall_names_str = {
7816 #define ICALL(id,name,func) (name),
7817 #include "metadata/icall-def.h"
7818 #undef ICALL
7819 };
7820 static const guint16 icall_names_idx [] = {
7821 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7822 #include "metadata/icall-def.h"
7823 #undef ICALL
7824 };
7825 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7826
7827 #else
7828
7829 #undef ICALL_TYPE
7830 #undef ICALL
7831 #define ICALL_TYPE(id,name,first) name,
7832 #define ICALL(id,name,func)
7833 static const char* const
7834 icall_type_names [] = {
7835 #include "metadata/icall-def.h"
7836         NULL
7837 };
7838
7839 #define icall_type_name_get(id) (icall_type_names [(id)])
7840
7841 #undef ICALL_TYPE
7842 #undef ICALL
7843 #define ICALL_TYPE(id,name,first)
7844 #define ICALL(id,name,func) name,
7845 static const char* const
7846 icall_names [] = {
7847 #include "metadata/icall-def.h"
7848         NULL
7849 };
7850 #define icall_name_get(id) icall_names [(id)]
7851
7852 #endif /* !HAVE_ARRAY_ELEM_INIT */
7853
7854 #undef ICALL_TYPE
7855 #undef ICALL
7856 #define ICALL_TYPE(id,name,first)
7857 #define ICALL(id,name,func) func,
7858 static const gconstpointer
7859 icall_functions [] = {
7860 #include "metadata/icall-def.h"
7861         NULL
7862 };
7863
7864 #ifdef ENABLE_ICALL_SYMBOL_MAP
7865 #undef ICALL_TYPE
7866 #undef ICALL
7867 #define ICALL_TYPE(id,name,first)
7868 #define ICALL(id,name,func) #func,
7869 static const gconstpointer
7870 icall_symbols [] = {
7871 #include "metadata/icall-def.h"
7872         NULL
7873 };
7874 #endif
7875
7876 #endif /* DISABLE_ICALL_TABLES */
7877
7878 static GHashTable *icall_hash = NULL;
7879 static GHashTable *jit_icall_hash_name = NULL;
7880 static GHashTable *jit_icall_hash_addr = NULL;
7881
7882 void
7883 mono_icall_init (void)
7884 {
7885 #ifndef DISABLE_ICALL_TABLES
7886         int i = 0;
7887
7888         /* check that tables are sorted: disable in release */
7889         if (TRUE) {
7890                 int j;
7891                 const char *prev_class = NULL;
7892                 const char *prev_method;
7893                 
7894                 for (i = 0; i < Icall_type_num; ++i) {
7895                         const IcallTypeDesc *desc;
7896                         int num_icalls;
7897                         prev_method = NULL;
7898                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7899                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7900                         prev_class = icall_type_name_get (i);
7901                         desc = &icall_type_descs [i];
7902                         num_icalls = icall_desc_num_icalls (desc);
7903                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7904                         for (j = 0; j < num_icalls; ++j) {
7905                                 const char *methodn = icall_name_get (desc->first_icall + j);
7906                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
7907                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
7908                                 prev_method = methodn;
7909                         }
7910                 }
7911         }
7912 #endif
7913
7914         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7915 }
7916
7917 void
7918 mono_icall_cleanup (void)
7919 {
7920         g_hash_table_destroy (icall_hash);
7921         g_hash_table_destroy (jit_icall_hash_name);
7922         g_hash_table_destroy (jit_icall_hash_addr);
7923 }
7924
7925 void
7926 mono_add_internal_call (const char *name, gconstpointer method)
7927 {
7928         mono_loader_lock ();
7929
7930         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7931
7932         mono_loader_unlock ();
7933 }
7934
7935 #ifndef DISABLE_ICALL_TABLES
7936
7937 #ifdef HAVE_ARRAY_ELEM_INIT
7938 static int
7939 compare_method_imap (const void *key, const void *elem)
7940 {
7941         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7942         return strcmp (key, method_name);
7943 }
7944
7945 static gpointer
7946 find_method_icall (const IcallTypeDesc *imap, const char *name)
7947 {
7948         const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7949         if (!nameslot)
7950                 return NULL;
7951         return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7952 }
7953
7954 static int
7955 compare_class_imap (const void *key, const void *elem)
7956 {
7957         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7958         return strcmp (key, class_name);
7959 }
7960
7961 static const IcallTypeDesc*
7962 find_class_icalls (const char *name)
7963 {
7964         const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7965         if (!nameslot)
7966                 return NULL;
7967         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7968 }
7969
7970 #else /* HAVE_ARRAY_ELEM_INIT */
7971
7972 static int
7973 compare_method_imap (const void *key, const void *elem)
7974 {
7975         const char** method_name = (const char**)elem;
7976         return strcmp (key, *method_name);
7977 }
7978
7979 static gpointer
7980 find_method_icall (const IcallTypeDesc *imap, const char *name)
7981 {
7982         const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7983         if (!nameslot)
7984                 return NULL;
7985         return (gpointer)icall_functions [(nameslot - icall_names)];
7986 }
7987
7988 static int
7989 compare_class_imap (const void *key, const void *elem)
7990 {
7991         const char** class_name = (const char**)elem;
7992         return strcmp (key, *class_name);
7993 }
7994
7995 static const IcallTypeDesc*
7996 find_class_icalls (const char *name)
7997 {
7998         const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7999         if (!nameslot)
8000                 return NULL;
8001         return &icall_type_descs [nameslot - icall_type_names];
8002 }
8003
8004 #endif /* HAVE_ARRAY_ELEM_INIT */
8005
8006 #endif /* DISABLE_ICALL_TABLES */
8007
8008 /* 
8009  * we should probably export this as an helper (handle nested types).
8010  * Returns the number of chars written in buf.
8011  */
8012 static int
8013 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8014 {
8015         int nspacelen, cnamelen;
8016         nspacelen = strlen (klass->name_space);
8017         cnamelen = strlen (klass->name);
8018         if (nspacelen + cnamelen + 2 > bufsize)
8019                 return 0;
8020         if (nspacelen) {
8021                 memcpy (buf, klass->name_space, nspacelen);
8022                 buf [nspacelen ++] = '.';
8023         }
8024         memcpy (buf + nspacelen, klass->name, cnamelen);
8025         buf [nspacelen + cnamelen] = 0;
8026         return nspacelen + cnamelen;
8027 }
8028
8029 #ifdef DISABLE_ICALL_TABLES
8030 static void
8031 no_icall_table (void)
8032 {
8033         g_assert_not_reached ();
8034 }
8035 #endif
8036
8037 gpointer
8038 mono_lookup_internal_call (MonoMethod *method)
8039 {
8040         char *sigstart;
8041         char *tmpsig;
8042         char mname [2048];
8043         int typelen = 0, mlen, siglen;
8044         gpointer res;
8045 #ifndef DISABLE_ICALL_TABLES
8046         const IcallTypeDesc *imap = NULL;
8047 #endif
8048
8049         g_assert (method != NULL);
8050
8051         if (method->is_inflated)
8052                 method = ((MonoMethodInflated *) method)->declaring;
8053
8054         if (method->klass->nested_in) {
8055                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8056                 if (!pos)
8057                         return NULL;
8058
8059                 mname [pos++] = '/';
8060                 mname [pos] = 0;
8061
8062                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8063                 if (!typelen)
8064                         return NULL;
8065
8066                 typelen += pos;
8067         } else {
8068                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8069                 if (!typelen)
8070                         return NULL;
8071         }
8072
8073 #ifndef DISABLE_ICALL_TABLES
8074         imap = find_class_icalls (mname);
8075 #endif
8076
8077         mname [typelen] = ':';
8078         mname [typelen + 1] = ':';
8079
8080         mlen = strlen (method->name);
8081         memcpy (mname + typelen + 2, method->name, mlen);
8082         sigstart = mname + typelen + 2 + mlen;
8083         *sigstart = 0;
8084
8085         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8086         siglen = strlen (tmpsig);
8087         if (typelen + mlen + siglen + 6 > sizeof (mname))
8088                 return NULL;
8089         sigstart [0] = '(';
8090         memcpy (sigstart + 1, tmpsig, siglen);
8091         sigstart [siglen + 1] = ')';
8092         sigstart [siglen + 2] = 0;
8093         g_free (tmpsig);
8094         
8095         mono_loader_lock ();
8096
8097         res = g_hash_table_lookup (icall_hash, mname);
8098         if (res) {
8099                 mono_loader_unlock ();
8100                 return res;
8101         }
8102         /* try without signature */
8103         *sigstart = 0;
8104         res = g_hash_table_lookup (icall_hash, mname);
8105         if (res) {
8106                 mono_loader_unlock ();
8107                 return res;
8108         }
8109
8110 #ifdef DISABLE_ICALL_TABLES
8111         mono_loader_unlock ();
8112         /* Fail only when the result is actually used */
8113         /* mono_marshal_get_native_wrapper () depends on this */
8114         if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8115                 return ves_icall_System_String_ctor_RedirectToCreateString;
8116         else
8117                 return no_icall_table;
8118 #else
8119         /* it wasn't found in the static call tables */
8120         if (!imap) {
8121                 mono_loader_unlock ();
8122                 return NULL;
8123         }
8124         res = find_method_icall (imap, sigstart - mlen);
8125         if (res) {
8126                 mono_loader_unlock ();
8127                 return res;
8128         }
8129         /* try _with_ signature */
8130         *sigstart = '(';
8131         res = find_method_icall (imap, sigstart - mlen);
8132         if (res) {
8133                 mono_loader_unlock ();
8134                 return res;
8135         }
8136
8137         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8138         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8139         g_print ("The out of sync library is: %s\n", method->klass->image->name);
8140         g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8141         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");
8142         g_print ("If you see other errors or faults after this message they are probably related\n");
8143         g_print ("and you need to fix your mono install first.\n");
8144
8145         mono_loader_unlock ();
8146
8147         return NULL;
8148 #endif
8149 }
8150
8151 #ifdef ENABLE_ICALL_SYMBOL_MAP
8152 static int
8153 func_cmp (gconstpointer key, gconstpointer p)
8154 {
8155         return (gsize)key - (gsize)*(gsize*)p;
8156 }
8157 #endif
8158
8159 /*
8160  * mono_lookup_icall_symbol:
8161  *
8162  *   Given the icall METHOD, returns its C symbol.
8163  */
8164 const char*
8165 mono_lookup_icall_symbol (MonoMethod *m)
8166 {
8167 #ifdef DISABLE_ICALL_TABLES
8168         g_assert_not_reached ();
8169         return NULL;
8170 #else
8171 #ifdef ENABLE_ICALL_SYMBOL_MAP
8172         gpointer func;
8173         int i;
8174         gpointer slot;
8175         static gconstpointer *functions_sorted;
8176         static const char**symbols_sorted;
8177         static gboolean inited;
8178
8179         if (!inited) {
8180                 gboolean changed;
8181
8182                 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8183                 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8184                 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8185                 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8186                 /* Bubble sort the two arrays */
8187                 changed = TRUE;
8188                 while (changed) {
8189                         changed = FALSE;
8190                         for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8191                                 if (functions_sorted [i] > functions_sorted [i + 1]) {
8192                                         gconstpointer tmp;
8193
8194                                         tmp = functions_sorted [i];
8195                                         functions_sorted [i] = functions_sorted [i + 1];
8196                                         functions_sorted [i + 1] = tmp;
8197                                         tmp = symbols_sorted [i];
8198                                         symbols_sorted [i] = symbols_sorted [i + 1];
8199                                         symbols_sorted [i + 1] = tmp;
8200                                         changed = TRUE;
8201                                 }
8202                         }
8203                 }
8204         }
8205
8206         func = mono_lookup_internal_call (m);
8207         if (!func)
8208                 return NULL;
8209         slot = bsearch (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8210         if (!slot)
8211                 return NULL;
8212         g_assert (slot);
8213         return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8214 #else
8215         fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8216         g_assert_not_reached ();
8217         return 0;
8218 #endif
8219 #endif
8220 }
8221
8222 static MonoType*
8223 type_from_typename (char *typename)
8224 {
8225         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
8226
8227         if (!strcmp (typename, "int"))
8228                 klass = mono_defaults.int_class;
8229         else if (!strcmp (typename, "ptr"))
8230                 klass = mono_defaults.int_class;
8231         else if (!strcmp (typename, "void"))
8232                 klass = mono_defaults.void_class;
8233         else if (!strcmp (typename, "int32"))
8234                 klass = mono_defaults.int32_class;
8235         else if (!strcmp (typename, "uint32"))
8236                 klass = mono_defaults.uint32_class;
8237         else if (!strcmp (typename, "int8"))
8238                 klass = mono_defaults.sbyte_class;
8239         else if (!strcmp (typename, "uint8"))
8240                 klass = mono_defaults.byte_class;
8241         else if (!strcmp (typename, "int16"))
8242                 klass = mono_defaults.int16_class;
8243         else if (!strcmp (typename, "uint16"))
8244                 klass = mono_defaults.uint16_class;
8245         else if (!strcmp (typename, "long"))
8246                 klass = mono_defaults.int64_class;
8247         else if (!strcmp (typename, "ulong"))
8248                 klass = mono_defaults.uint64_class;
8249         else if (!strcmp (typename, "float"))
8250                 klass = mono_defaults.single_class;
8251         else if (!strcmp (typename, "double"))
8252                 klass = mono_defaults.double_class;
8253         else if (!strcmp (typename, "object"))
8254                 klass = mono_defaults.object_class;
8255         else if (!strcmp (typename, "obj"))
8256                 klass = mono_defaults.object_class;
8257         else if (!strcmp (typename, "string"))
8258                 klass = mono_defaults.string_class;
8259         else if (!strcmp (typename, "bool"))
8260                 klass = mono_defaults.boolean_class;
8261         else if (!strcmp (typename, "boolean"))
8262                 klass = mono_defaults.boolean_class;
8263         else {
8264                 g_error ("%s", typename);
8265                 g_assert_not_reached ();
8266         }
8267         return &klass->byval_arg;
8268 }
8269
8270 MonoMethodSignature*
8271 mono_create_icall_signature (const char *sigstr)
8272 {
8273         gchar **parts;
8274         int i, len;
8275         gchar **tmp;
8276         MonoMethodSignature *res;
8277
8278         mono_loader_lock ();
8279         res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8280         if (res) {
8281                 mono_loader_unlock ();
8282                 return res;
8283         }
8284
8285         parts = g_strsplit (sigstr, " ", 256);
8286
8287         tmp = parts;
8288         len = 0;
8289         while (*tmp) {
8290                 len ++;
8291                 tmp ++;
8292         }
8293
8294         res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8295         res->pinvoke = 1;
8296
8297 #ifdef HOST_WIN32
8298         /* 
8299          * Under windows, the default pinvoke calling convention is STDCALL but
8300          * we need CDECL.
8301          */
8302         res->call_convention = MONO_CALL_C;
8303 #endif
8304
8305         res->ret = type_from_typename (parts [0]);
8306         for (i = 1; i < len; ++i) {
8307                 res->params [i - 1] = type_from_typename (parts [i]);
8308         }
8309
8310         g_strfreev (parts);
8311
8312         g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8313
8314         mono_loader_unlock ();
8315
8316         return res;
8317 }
8318
8319 MonoJitICallInfo *
8320 mono_find_jit_icall_by_name (const char *name)
8321 {
8322         MonoJitICallInfo *info;
8323         g_assert (jit_icall_hash_name);
8324
8325         mono_loader_lock ();
8326         info = g_hash_table_lookup (jit_icall_hash_name, name);
8327         mono_loader_unlock ();
8328         return info;
8329 }
8330
8331 MonoJitICallInfo *
8332 mono_find_jit_icall_by_addr (gconstpointer addr)
8333 {
8334         MonoJitICallInfo *info;
8335         g_assert (jit_icall_hash_addr);
8336
8337         mono_loader_lock ();
8338         info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8339         mono_loader_unlock ();
8340
8341         return info;
8342 }
8343
8344 /*
8345  * mono_get_jit_icall_info:
8346  *
8347  *   Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8348  * caller should access it while holding the loader lock.
8349  */
8350 GHashTable*
8351 mono_get_jit_icall_info (void)
8352 {
8353         return jit_icall_hash_name;
8354 }
8355
8356 /*
8357  * mono_lookup_jit_icall_symbol:
8358  *
8359  *   Given the jit icall NAME, returns its C symbol if possible, or NULL.
8360  */
8361 const char*
8362 mono_lookup_jit_icall_symbol (const char *name)
8363 {
8364         MonoJitICallInfo *info;
8365         const char *res = NULL;
8366
8367         mono_loader_lock ();
8368         info = g_hash_table_lookup (jit_icall_hash_name, name);
8369         if (info)
8370                 res = info->c_symbol;
8371         mono_loader_unlock ();
8372         return res;
8373 }
8374
8375 void
8376 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8377 {
8378         mono_loader_lock ();
8379         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8380         mono_loader_unlock ();
8381 }
8382
8383 MonoJitICallInfo *
8384 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8385 {
8386         MonoJitICallInfo *info;
8387         
8388         g_assert (func);
8389         g_assert (name);
8390
8391         mono_loader_lock ();
8392
8393         if (!jit_icall_hash_name) {
8394                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8395                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8396         }
8397
8398         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8399                 g_warning ("jit icall already defined \"%s\"\n", name);
8400                 g_assert_not_reached ();
8401         }
8402
8403         info = g_new0 (MonoJitICallInfo, 1);
8404         
8405         info->name = name;
8406         info->func = func;
8407         info->sig = sig;
8408         info->c_symbol = c_symbol;
8409
8410         if (is_save) {
8411                 info->wrapper = func;
8412         } else {
8413                 info->wrapper = NULL;
8414         }
8415
8416         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8417         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8418
8419         mono_loader_unlock ();
8420         return info;
8421 }
8422
8423 MonoJitICallInfo *
8424 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8425 {
8426         return mono_register_jit_icall_full (func, name, sig, is_save, NULL);
8427 }
8428