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