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