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