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