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