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