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