Attempt to implement GetTimeZoneData to support all hemispheres
[mono.git] / mono / metadata / icall.c
1 /*
2  * icall.c:
3  *
4  * Authors:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *   Paolo Molaro (lupus@ximian.com)
7  *       Patrik Torstensson (patrik.torstensson@labs2.com)
8  *
9  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11  * Copyright 2011-2012 Xamarin Inc (http://www.xamarin.com).
12  */
13
14 #include <config.h>
15 #include <glib.h>
16 #include <stdarg.h>
17 #include <string.h>
18 #include <ctype.h>
19 #ifdef HAVE_ALLOCA_H
20 #include <alloca.h>
21 #endif
22 #ifdef HAVE_SYS_TIME_H
23 #include <sys/time.h>
24 #endif
25 #ifdef HAVE_UNISTD_H
26 #include <unistd.h>
27 #endif
28 #if defined (HOST_WIN32)
29 #include <stdlib.h>
30 #endif
31 #if defined (HAVE_WCHAR_H)
32 #include <wchar.h>
33 #endif
34
35 #include "mono/utils/mono-membar.h"
36 #include <mono/metadata/object.h>
37 #include <mono/metadata/threads.h>
38 #include <mono/metadata/threads-types.h>
39 #include <mono/metadata/threadpool.h>
40 #include <mono/metadata/monitor.h>
41 #include <mono/metadata/reflection.h>
42 #include <mono/metadata/assembly.h>
43 #include <mono/metadata/tabledefs.h>
44 #include <mono/metadata/exception.h>
45 #include <mono/metadata/file-io.h>
46 #include <mono/metadata/console-io.h>
47 #include <mono/metadata/socket-io.h>
48 #include <mono/metadata/mono-endian.h>
49 #include <mono/metadata/tokentype.h>
50 #include <mono/metadata/domain-internals.h>
51 #include <mono/metadata/metadata-internals.h>
52 #include <mono/metadata/class-internals.h>
53 #include <mono/metadata/marshal.h>
54 #include <mono/metadata/gc-internal.h>
55 #include <mono/metadata/mono-gc.h>
56 #include <mono/metadata/rand.h>
57 #include <mono/metadata/sysmath.h>
58 #include <mono/metadata/string-icalls.h>
59 #include <mono/metadata/debug-helpers.h>
60 #include <mono/metadata/process.h>
61 #include <mono/metadata/environment.h>
62 #include <mono/metadata/profiler-private.h>
63 #include <mono/metadata/locales.h>
64 #include <mono/metadata/filewatcher.h>
65 #include <mono/metadata/char-conversions.h>
66 #include <mono/metadata/security.h>
67 #include <mono/metadata/mono-config.h>
68 #include <mono/metadata/cil-coff.h>
69 #include <mono/metadata/number-formatter.h>
70 #include <mono/metadata/security-manager.h>
71 #include <mono/metadata/security-core-clr.h>
72 #include <mono/metadata/mono-perfcounters.h>
73 #include <mono/metadata/mono-debug.h>
74 #include <mono/metadata/mono-ptr-array.h>
75 #include <mono/metadata/verify-internals.h>
76 #include <mono/metadata/runtime.h>
77 #include <mono/io-layer/io-layer.h>
78 #include <mono/utils/strtod.h>
79 #include <mono/utils/monobitset.h>
80 #include <mono/utils/mono-time.h>
81 #include <mono/utils/mono-proclib.h>
82 #include <mono/utils/mono-string.h>
83 #include <mono/utils/mono-error-internals.h>
84 #include <mono/utils/mono-mmap.h>
85 #include <mono/utils/mono-io-portability.h>
86 #include <mono/utils/mono-digest.h>
87 #include <mono/utils/bsearch.h>
88
89 #if defined (HOST_WIN32)
90 #include <windows.h>
91 #include <shlobj.h>
92 #endif
93 #include "decimal.h"
94
95 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
96
97 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
98
99 static MonoArray*
100 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
101
102 static inline MonoBoolean
103 is_generic_parameter (MonoType *type)
104 {
105         return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
106 }
107
108 static void
109 mono_class_init_or_throw (MonoClass *klass)
110 {
111         if (!mono_class_init (klass))
112                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
113 }
114
115 /*
116  * We expect a pointer to a char, not a string
117  */
118 ICALL_EXPORT gboolean
119 mono_double_ParseImpl (char *ptr, double *result)
120 {
121         gchar *endptr = NULL;
122         *result = 0.0;
123
124         MONO_ARCH_SAVE_REGS;
125
126 #ifdef __arm__
127         if (*ptr)
128                 *result = strtod (ptr, &endptr);
129 #else
130         if (*ptr){
131                 /* mono_strtod () is not thread-safe */
132                 EnterCriticalSection (&mono_strtod_mutex);
133                 *result = mono_strtod (ptr, &endptr);
134                 LeaveCriticalSection (&mono_strtod_mutex);
135         }
136 #endif
137
138         if (!*ptr || (endptr && *endptr))
139                 return FALSE;
140         
141         return TRUE;
142 }
143
144 ICALL_EXPORT MonoObject *
145 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
146 {
147         MonoClass *ac;
148         MonoArray *ao;
149         gint32 esize;
150         gpointer *ea;
151
152         MONO_ARCH_SAVE_REGS;
153
154         ao = (MonoArray *)this;
155         ac = (MonoClass *)ao->obj.vtable->klass;
156
157         esize = mono_array_element_size (ac);
158         ea = (gpointer*)((char*)ao->vector + (pos * esize));
159
160         if (ac->element_class->valuetype)
161                 return mono_value_box (this->vtable->domain, ac->element_class, ea);
162         else
163                 return *ea;
164 }
165
166 ICALL_EXPORT MonoObject *
167 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
168 {
169         MonoClass *ac, *ic;
170         MonoArray *ao, *io;
171         gint32 i, pos, *ind;
172
173         MONO_ARCH_SAVE_REGS;
174
175         MONO_CHECK_ARG_NULL (idxs);
176
177         io = (MonoArray *)idxs;
178         ic = (MonoClass *)io->obj.vtable->klass;
179         
180         ao = (MonoArray *)this;
181         ac = (MonoClass *)ao->obj.vtable->klass;
182
183         g_assert (ic->rank == 1);
184         if (io->bounds != NULL || io->max_length !=  ac->rank)
185                 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
186
187         ind = (gint32 *)io->vector;
188
189         if (ao->bounds == NULL) {
190                 if (*ind < 0 || *ind >= ao->max_length)
191                         mono_raise_exception (mono_get_exception_index_out_of_range ());
192
193                 return ves_icall_System_Array_GetValueImpl (this, *ind);
194         }
195         
196         for (i = 0; i < ac->rank; i++)
197                 if ((ind [i] < ao->bounds [i].lower_bound) ||
198                     (ind [i] >=  (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
199                         mono_raise_exception (mono_get_exception_index_out_of_range ());
200
201         pos = ind [0] - ao->bounds [0].lower_bound;
202         for (i = 1; i < ac->rank; i++)
203                 pos = pos*ao->bounds [i].length + ind [i] - 
204                         ao->bounds [i].lower_bound;
205
206         return ves_icall_System_Array_GetValueImpl (this, pos);
207 }
208
209 ICALL_EXPORT void
210 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
211 {
212         MonoClass *ac, *vc, *ec;
213         gint32 esize, vsize;
214         gpointer *ea, *va;
215         int et, vt;
216
217         guint64 u64 = 0;
218         gint64 i64 = 0;
219         gdouble r64 = 0;
220
221         MONO_ARCH_SAVE_REGS;
222
223         if (value)
224                 vc = value->vtable->klass;
225         else
226                 vc = NULL;
227
228         ac = this->obj.vtable->klass;
229         ec = ac->element_class;
230
231         esize = mono_array_element_size (ac);
232         ea = (gpointer*)((char*)this->vector + (pos * esize));
233         va = (gpointer*)((char*)value + sizeof (MonoObject));
234
235         if (mono_class_is_nullable (ec)) {
236                 mono_nullable_init ((guint8*)ea, value, ec);
237                 return;
238         }
239
240         if (!value) {
241                 mono_gc_bzero (ea, esize);
242                 return;
243         }
244
245 #define NO_WIDENING_CONVERSION G_STMT_START{\
246         mono_raise_exception (mono_get_exception_argument ( \
247                 "value", "not a widening conversion")); \
248 }G_STMT_END
249
250 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
251         if (esize < vsize + (extra)) \
252                 mono_raise_exception (mono_get_exception_argument ( \
253                         "value", "not a widening conversion")); \
254 }G_STMT_END
255
256 #define INVALID_CAST G_STMT_START{ \
257                 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
258         mono_raise_exception (mono_get_exception_invalid_cast ()); \
259 }G_STMT_END
260
261         /* Check element (destination) type. */
262         switch (ec->byval_arg.type) {
263         case MONO_TYPE_STRING:
264                 switch (vc->byval_arg.type) {
265                 case MONO_TYPE_STRING:
266                         break;
267                 default:
268                         INVALID_CAST;
269                 }
270                 break;
271         case MONO_TYPE_BOOLEAN:
272                 switch (vc->byval_arg.type) {
273                 case MONO_TYPE_BOOLEAN:
274                         break;
275                 case MONO_TYPE_CHAR:
276                 case MONO_TYPE_U1:
277                 case MONO_TYPE_U2:
278                 case MONO_TYPE_U4:
279                 case MONO_TYPE_U8:
280                 case MONO_TYPE_I1:
281                 case MONO_TYPE_I2:
282                 case MONO_TYPE_I4:
283                 case MONO_TYPE_I8:
284                 case MONO_TYPE_R4:
285                 case MONO_TYPE_R8:
286                         NO_WIDENING_CONVERSION;
287                 default:
288                         INVALID_CAST;
289                 }
290                 break;
291         }
292
293         if (!ec->valuetype) {
294                 if (!mono_object_isinst (value, ec))
295                         INVALID_CAST;
296                 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
297                 return;
298         }
299
300         if (mono_object_isinst (value, ec)) {
301                 if (ec->has_references)
302                         mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
303                 else
304                         mono_gc_memmove (ea, (char *)value + sizeof (MonoObject), esize);
305                 return;
306         }
307
308         if (!vc->valuetype)
309                 INVALID_CAST;
310
311         vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
312
313         et = ec->byval_arg.type;
314         if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
315                 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
316
317         vt = vc->byval_arg.type;
318         if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
319                 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
320
321 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
322         switch (vt) { \
323         case MONO_TYPE_U1: \
324         case MONO_TYPE_U2: \
325         case MONO_TYPE_U4: \
326         case MONO_TYPE_U8: \
327         case MONO_TYPE_CHAR: \
328                 CHECK_WIDENING_CONVERSION(0); \
329                 *(etype *) ea = (etype) u64; \
330                 return; \
331         /* You can't assign a signed value to an unsigned array. */ \
332         case MONO_TYPE_I1: \
333         case MONO_TYPE_I2: \
334         case MONO_TYPE_I4: \
335         case MONO_TYPE_I8: \
336         /* You can't assign a floating point number to an integer array. */ \
337         case MONO_TYPE_R4: \
338         case MONO_TYPE_R8: \
339                 NO_WIDENING_CONVERSION; \
340         } \
341 }G_STMT_END
342
343 #define ASSIGN_SIGNED(etype) G_STMT_START{\
344         switch (vt) { \
345         case MONO_TYPE_I1: \
346         case MONO_TYPE_I2: \
347         case MONO_TYPE_I4: \
348         case MONO_TYPE_I8: \
349                 CHECK_WIDENING_CONVERSION(0); \
350                 *(etype *) ea = (etype) i64; \
351                 return; \
352         /* You can assign an unsigned value to a signed array if the array's */ \
353         /* element size is larger than the value size. */ \
354         case MONO_TYPE_U1: \
355         case MONO_TYPE_U2: \
356         case MONO_TYPE_U4: \
357         case MONO_TYPE_U8: \
358         case MONO_TYPE_CHAR: \
359                 CHECK_WIDENING_CONVERSION(1); \
360                 *(etype *) ea = (etype) u64; \
361                 return; \
362         /* You can't assign a floating point number to an integer array. */ \
363         case MONO_TYPE_R4: \
364         case MONO_TYPE_R8: \
365                 NO_WIDENING_CONVERSION; \
366         } \
367 }G_STMT_END
368
369 #define ASSIGN_REAL(etype) G_STMT_START{\
370         switch (vt) { \
371         case MONO_TYPE_R4: \
372         case MONO_TYPE_R8: \
373                 CHECK_WIDENING_CONVERSION(0); \
374                 *(etype *) ea = (etype) r64; \
375                 return; \
376         /* All integer values fit into a floating point array, so we don't */ \
377         /* need to CHECK_WIDENING_CONVERSION here. */ \
378         case MONO_TYPE_I1: \
379         case MONO_TYPE_I2: \
380         case MONO_TYPE_I4: \
381         case MONO_TYPE_I8: \
382                 *(etype *) ea = (etype) i64; \
383                 return; \
384         case MONO_TYPE_U1: \
385         case MONO_TYPE_U2: \
386         case MONO_TYPE_U4: \
387         case MONO_TYPE_U8: \
388         case MONO_TYPE_CHAR: \
389                 *(etype *) ea = (etype) u64; \
390                 return; \
391         } \
392 }G_STMT_END
393
394         switch (vt) {
395         case MONO_TYPE_U1:
396                 u64 = *(guint8 *) va;
397                 break;
398         case MONO_TYPE_U2:
399                 u64 = *(guint16 *) va;
400                 break;
401         case MONO_TYPE_U4:
402                 u64 = *(guint32 *) va;
403                 break;
404         case MONO_TYPE_U8:
405                 u64 = *(guint64 *) va;
406                 break;
407         case MONO_TYPE_I1:
408                 i64 = *(gint8 *) va;
409                 break;
410         case MONO_TYPE_I2:
411                 i64 = *(gint16 *) va;
412                 break;
413         case MONO_TYPE_I4:
414                 i64 = *(gint32 *) va;
415                 break;
416         case MONO_TYPE_I8:
417                 i64 = *(gint64 *) va;
418                 break;
419         case MONO_TYPE_R4:
420                 r64 = *(gfloat *) va;
421                 break;
422         case MONO_TYPE_R8:
423                 r64 = *(gdouble *) va;
424                 break;
425         case MONO_TYPE_CHAR:
426                 u64 = *(guint16 *) va;
427                 break;
428         case MONO_TYPE_BOOLEAN:
429                 /* Boolean is only compatible with itself. */
430                 switch (et) {
431                 case MONO_TYPE_CHAR:
432                 case MONO_TYPE_U1:
433                 case MONO_TYPE_U2:
434                 case MONO_TYPE_U4:
435                 case MONO_TYPE_U8:
436                 case MONO_TYPE_I1:
437                 case MONO_TYPE_I2:
438                 case MONO_TYPE_I4:
439                 case MONO_TYPE_I8:
440                 case MONO_TYPE_R4:
441                 case MONO_TYPE_R8:
442                         NO_WIDENING_CONVERSION;
443                 default:
444                         INVALID_CAST;
445                 }
446                 break;
447         }
448
449         /* If we can't do a direct copy, let's try a widening conversion. */
450         switch (et) {
451         case MONO_TYPE_CHAR:
452                 ASSIGN_UNSIGNED (guint16);
453         case MONO_TYPE_U1:
454                 ASSIGN_UNSIGNED (guint8);
455         case MONO_TYPE_U2:
456                 ASSIGN_UNSIGNED (guint16);
457         case MONO_TYPE_U4:
458                 ASSIGN_UNSIGNED (guint32);
459         case MONO_TYPE_U8:
460                 ASSIGN_UNSIGNED (guint64);
461         case MONO_TYPE_I1:
462                 ASSIGN_SIGNED (gint8);
463         case MONO_TYPE_I2:
464                 ASSIGN_SIGNED (gint16);
465         case MONO_TYPE_I4:
466                 ASSIGN_SIGNED (gint32);
467         case MONO_TYPE_I8:
468                 ASSIGN_SIGNED (gint64);
469         case MONO_TYPE_R4:
470                 ASSIGN_REAL (gfloat);
471         case MONO_TYPE_R8:
472                 ASSIGN_REAL (gdouble);
473         }
474
475         INVALID_CAST;
476         /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
477         return;
478
479 #undef INVALID_CAST
480 #undef NO_WIDENING_CONVERSION
481 #undef CHECK_WIDENING_CONVERSION
482 #undef ASSIGN_UNSIGNED
483 #undef ASSIGN_SIGNED
484 #undef ASSIGN_REAL
485 }
486
487 ICALL_EXPORT void 
488 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
489                                  MonoArray *idxs)
490 {
491         MonoClass *ac, *ic;
492         gint32 i, pos, *ind;
493
494         MONO_ARCH_SAVE_REGS;
495
496         MONO_CHECK_ARG_NULL (idxs);
497
498         ic = idxs->obj.vtable->klass;
499         ac = this->obj.vtable->klass;
500
501         g_assert (ic->rank == 1);
502         if (idxs->bounds != NULL || idxs->max_length != ac->rank)
503                 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
504
505         ind = (gint32 *)idxs->vector;
506
507         if (this->bounds == NULL) {
508                 if (*ind < 0 || *ind >= this->max_length)
509                         mono_raise_exception (mono_get_exception_index_out_of_range ());
510
511                 ves_icall_System_Array_SetValueImpl (this, value, *ind);
512                 return;
513         }
514         
515         for (i = 0; i < ac->rank; i++)
516                 if ((ind [i] < this->bounds [i].lower_bound) ||
517                     (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
518                         mono_raise_exception (mono_get_exception_index_out_of_range ());
519
520         pos = ind [0] - this->bounds [0].lower_bound;
521         for (i = 1; i < ac->rank; i++)
522                 pos = pos * this->bounds [i].length + ind [i] - 
523                         this->bounds [i].lower_bound;
524
525         ves_icall_System_Array_SetValueImpl (this, value, pos);
526 }
527
528 ICALL_EXPORT MonoArray *
529 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
530 {
531         MonoClass *aklass, *klass;
532         MonoArray *array;
533         uintptr_t *sizes, i;
534         gboolean bounded = FALSE;
535
536         MONO_ARCH_SAVE_REGS;
537
538         MONO_CHECK_ARG_NULL (type);
539         MONO_CHECK_ARG_NULL (lengths);
540
541         MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
542         if (bounds)
543                 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
544
545         for (i = 0; i < mono_array_length (lengths); i++)
546                 if (mono_array_get (lengths, gint32, i) < 0)
547                         mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
548
549         klass = mono_class_from_mono_type (type->type);
550         mono_class_init_or_throw (klass);
551
552         if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
553                 /* vectors are not the same as one dimensional arrays with no-zero bounds */
554                 bounded = TRUE;
555         else
556                 bounded = FALSE;
557
558         aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
559
560         sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
561         for (i = 0; i < aklass->rank; ++i) {
562                 sizes [i] = mono_array_get (lengths, guint32, i);
563                 if (bounds)
564                         sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
565                 else
566                         sizes [i + aklass->rank] = 0;
567         }
568
569         array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
570
571         return array;
572 }
573
574 ICALL_EXPORT MonoArray *
575 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
576 {
577         MonoClass *aklass, *klass;
578         MonoArray *array;
579         uintptr_t *sizes, i;
580         gboolean bounded = FALSE;
581
582         MONO_ARCH_SAVE_REGS;
583
584         MONO_CHECK_ARG_NULL (type);
585         MONO_CHECK_ARG_NULL (lengths);
586
587         MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
588         if (bounds)
589                 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
590
591         for (i = 0; i < mono_array_length (lengths); i++) 
592                 if ((mono_array_get (lengths, gint64, i) < 0) ||
593                     (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
594                         mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
595
596         klass = mono_class_from_mono_type (type->type);
597         mono_class_init_or_throw (klass);
598
599         if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
600                 /* vectors are not the same as one dimensional arrays with no-zero bounds */
601                 bounded = TRUE;
602         else
603                 bounded = FALSE;
604
605         aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
606
607         sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
608         for (i = 0; i < aklass->rank; ++i) {
609                 sizes [i] = mono_array_get (lengths, guint64, i);
610                 if (bounds)
611                         sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
612                 else
613                         sizes [i + aklass->rank] = 0;
614         }
615
616         array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
617
618         return array;
619 }
620
621 ICALL_EXPORT gint32 
622 ves_icall_System_Array_GetRank (MonoObject *this)
623 {
624         MONO_ARCH_SAVE_REGS;
625
626         return this->vtable->klass->rank;
627 }
628
629 ICALL_EXPORT gint32
630 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
631 {
632         gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
633         uintptr_t length;
634
635         MONO_ARCH_SAVE_REGS;
636
637         if ((dimension < 0) || (dimension >= rank))
638                 mono_raise_exception (mono_get_exception_index_out_of_range ());
639         
640         if (this->bounds == NULL)
641                 length = this->max_length;
642         else
643                 length = this->bounds [dimension].length;
644
645 #ifdef MONO_BIG_ARRAYS
646         if (length > G_MAXINT32)
647                 mono_raise_exception (mono_get_exception_overflow ());
648 #endif
649         return length;
650 }
651
652 ICALL_EXPORT gint64
653 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
654 {
655         gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
656
657         MONO_ARCH_SAVE_REGS;
658
659         if ((dimension < 0) || (dimension >= rank))
660                 mono_raise_exception (mono_get_exception_index_out_of_range ());
661         
662         if (this->bounds == NULL)
663                 return this->max_length;
664         
665         return this->bounds [dimension].length;
666 }
667
668 ICALL_EXPORT gint32
669 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
670 {
671         gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
672
673         MONO_ARCH_SAVE_REGS;
674
675         if ((dimension < 0) || (dimension >= rank))
676                 mono_raise_exception (mono_get_exception_index_out_of_range ());
677         
678         if (this->bounds == NULL)
679                 return 0;
680         
681         return this->bounds [dimension].lower_bound;
682 }
683
684 ICALL_EXPORT void
685 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
686 {
687         int sz = mono_array_element_size (mono_object_class (arr));
688         mono_gc_bzero (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
689 }
690
691 ICALL_EXPORT gboolean
692 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
693 {
694         int element_size;
695         void * dest_addr;
696         void * source_addr;
697         MonoVTable *src_vtable;
698         MonoVTable *dest_vtable;
699         MonoClass *src_class;
700         MonoClass *dest_class;
701
702         src_vtable = source->obj.vtable;
703         dest_vtable = dest->obj.vtable;
704
705         if (src_vtable->rank != dest_vtable->rank)
706                 return FALSE;
707
708         if (source->bounds || dest->bounds)
709                 return FALSE;
710
711         /* there's no integer overflow since mono_array_length returns an unsigned integer */
712         if ((dest_idx + length > mono_array_length_fast (dest)) ||
713                 (source_idx + length > mono_array_length_fast (source)))
714                 return FALSE;
715
716         src_class = src_vtable->klass->element_class;
717         dest_class = dest_vtable->klass->element_class;
718
719         /*
720          * Handle common cases.
721          */
722
723         /* Case1: object[] -> valuetype[] (ArrayList::ToArray) 
724         We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
725         */
726         if (src_class == mono_defaults.object_class && dest_class->valuetype)
727                 return FALSE;
728
729         /* Check if we're copying a char[] <==> (u)short[] */
730         if (src_class != dest_class) {
731                 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
732                         return FALSE;
733
734                 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
735                 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
736                         return FALSE;
737         }
738
739         if (dest_class->valuetype) {
740                 element_size = mono_array_element_size (source->obj.vtable->klass);
741                 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
742                 if (dest_class->has_references) {
743                         mono_value_copy_array (dest, dest_idx, source_addr, length);
744                 } else {
745                         dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
746                         mono_gc_memmove (dest_addr, source_addr, element_size * length);
747                 }
748         } else {
749                 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
750         }
751
752         return TRUE;
753 }
754
755 ICALL_EXPORT void
756 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
757 {
758         MonoClass *ac;
759         MonoArray *ao;
760         gint32 esize;
761         gpointer *ea;
762
763         MONO_ARCH_SAVE_REGS;
764
765         ao = (MonoArray *)this;
766         ac = (MonoClass *)ao->obj.vtable->klass;
767
768         esize = mono_array_element_size (ac);
769         ea = (gpointer*)((char*)ao->vector + (pos * esize));
770
771         mono_gc_memmove (value, ea, esize);
772 }
773
774 ICALL_EXPORT void
775 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
776 {
777         MonoClass *ac, *ec;
778         MonoArray *ao;
779         gint32 esize;
780         gpointer *ea;
781
782         MONO_ARCH_SAVE_REGS;
783
784         ao = (MonoArray *)this;
785         ac = (MonoClass *)ao->obj.vtable->klass;
786         ec = ac->element_class;
787
788         esize = mono_array_element_size (ac);
789         ea = (gpointer*)((char*)ao->vector + (pos * esize));
790
791         if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
792                 g_assert (esize == sizeof (gpointer));
793                 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
794         } else {
795                 g_assert (ec->inited);
796                 g_assert (esize == mono_class_value_size (ec, NULL));
797                 if (ec->has_references)
798                         mono_gc_wbarrier_value_copy (ea, value, 1, ec);
799                 else
800                         mono_gc_memmove (ea, value, esize);
801         }
802 }
803
804 ICALL_EXPORT void
805 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
806 {
807         MonoClass *klass = array->obj.vtable->klass;
808         guint32 size = mono_array_element_size (klass);
809         MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
810         int align;
811         const char *field_data;
812
813         if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
814                 MonoException *exc = mono_get_exception_argument("array",
815                         "Cannot initialize array of non-primitive type.");
816                 mono_raise_exception (exc);
817         }
818
819         if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
820                 MonoException *exc = mono_get_exception_argument("field_handle",
821                         "Field doesn't have an RVA");
822                 mono_raise_exception (exc);
823         }
824
825         size *= array->max_length;
826         field_data = mono_field_get_data (field_handle);
827
828         if (size > mono_type_size (field_handle->type, &align)) {
829                 MonoException *exc = mono_get_exception_argument("field_handle",
830                         "Field not large enough to fill array");
831                 mono_raise_exception (exc);
832         }
833
834 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
835 #define SWAP(n) {\
836         guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
837         guint ## n *src = (guint ## n *) field_data; \
838         guint ## n *end = (guint ## n *)((char*)src + size); \
839 \
840         for (; src < end; data++, src++) { \
841                 *data = read ## n (src); \
842         } \
843 }
844
845         /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
846
847         switch (type->type) {
848         case MONO_TYPE_CHAR:
849         case MONO_TYPE_I2:
850         case MONO_TYPE_U2:
851                 SWAP (16);
852                 break;
853         case MONO_TYPE_I4:
854         case MONO_TYPE_U4:
855         case MONO_TYPE_R4:
856                 SWAP (32);
857                 break;
858         case MONO_TYPE_I8:
859         case MONO_TYPE_U8:
860         case MONO_TYPE_R8:
861                 SWAP (64);
862                 break;
863         default:
864                 memcpy (mono_array_addr (array, char, 0), field_data, size);
865                 break;
866         }
867 #else
868         memcpy (mono_array_addr (array, char, 0), field_data, size);
869 #endif
870 }
871
872 ICALL_EXPORT gint
873 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
874 {
875         MONO_ARCH_SAVE_REGS;
876
877         return offsetof (MonoString, chars);
878 }
879
880 ICALL_EXPORT MonoObject *
881 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
882 {
883         MONO_ARCH_SAVE_REGS;
884
885         if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
886                 return obj;
887         else
888                 return mono_object_clone (obj);
889 }
890
891 ICALL_EXPORT void
892 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
893 {
894         MonoClass *klass;
895         MonoVTable *vtable;
896
897         MONO_CHECK_ARG_NULL (handle);
898
899         klass = mono_class_from_mono_type (handle);
900         MONO_CHECK_ARG (handle, klass);
901
902         vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
903
904         /* This will call the type constructor */
905         mono_runtime_class_init (vtable);
906 }
907
908 ICALL_EXPORT void
909 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
910 {
911         MONO_ARCH_SAVE_REGS;
912
913         mono_image_check_for_module_cctor (image);
914         if (image->has_module_cctor) {
915                 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
916                 /*It's fine to raise the exception here*/
917                 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
918         }
919 }
920
921 ICALL_EXPORT MonoBoolean
922 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
923 {
924         guint8 *stack_addr;
925         guint8 *current;
926         size_t stack_size;
927         /* later make this configurable and per-arch */
928         int min_size = 4096 * 4 * sizeof (void*);
929         mono_thread_get_stack_bounds (&stack_addr, &stack_size);
930         /* if we have no info we are optimistic and assume there is enough room */
931         if (!stack_addr)
932                 return TRUE;
933         current = (guint8 *)&stack_addr;
934         if (current > stack_addr) {
935                 if ((current - stack_addr) < min_size)
936                         return FALSE;
937         } else {
938                 if (current - (stack_addr - stack_size) < min_size)
939                         return FALSE;
940         }
941         return TRUE;
942 }
943
944 ICALL_EXPORT MonoObject *
945 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
946 {
947         MONO_ARCH_SAVE_REGS;
948
949         return mono_object_clone (this);
950 }
951
952 ICALL_EXPORT gint32
953 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
954 {
955         MonoClass *klass;
956         MonoObject **values = NULL;
957         MonoObject *o;
958         int count = 0;
959         gint32 result = 0;
960         MonoClassField* field;
961         gpointer iter;
962
963         MONO_ARCH_SAVE_REGS;
964
965         klass = mono_object_class (this);
966
967         if (mono_class_num_fields (klass) == 0)
968                 return mono_object_hash (this);
969
970         /*
971          * Compute the starting value of the hashcode for fields of primitive
972          * types, and return the remaining fields in an array to the managed side.
973          * This way, we can avoid costly reflection operations in managed code.
974          */
975         iter = NULL;
976         while ((field = mono_class_get_fields (klass, &iter))) {
977                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
978                         continue;
979                 if (mono_field_is_deleted (field))
980                         continue;
981                 /* FIXME: Add more types */
982                 switch (field->type->type) {
983                 case MONO_TYPE_I4:
984                         result ^= *(gint32*)((guint8*)this + field->offset);
985                         break;
986                 case MONO_TYPE_STRING: {
987                         MonoString *s;
988                         s = *(MonoString**)((guint8*)this + field->offset);
989                         if (s != NULL)
990                                 result ^= mono_string_hash (s);
991                         break;
992                 }
993                 default:
994                         if (!values)
995                                 values = g_newa (MonoObject*, mono_class_num_fields (klass));
996                         o = mono_field_get_value_object (mono_object_domain (this), field, this);
997                         values [count++] = o;
998                 }
999         }
1000
1001         if (values) {
1002                 int i;
1003                 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1004                 for (i = 0; i < count; ++i)
1005                         mono_array_setref (*fields, i, values [i]);
1006         } else {
1007                 *fields = NULL;
1008         }
1009         return result;
1010 }
1011
1012 ICALL_EXPORT MonoBoolean
1013 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1014 {
1015         MonoClass *klass;
1016         MonoObject **values = NULL;
1017         MonoObject *o;
1018         MonoClassField* field;
1019         gpointer iter;
1020         int count = 0;
1021
1022         MONO_ARCH_SAVE_REGS;
1023
1024         MONO_CHECK_ARG_NULL (that);
1025
1026         if (this->vtable != that->vtable)
1027                 return FALSE;
1028
1029         klass = mono_object_class (this);
1030
1031         if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1032                 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1033
1034         /*
1035          * Do the comparison for fields of primitive type and return a result if
1036          * possible. Otherwise, return the remaining fields in an array to the 
1037          * managed side. This way, we can avoid costly reflection operations in 
1038          * managed code.
1039          */
1040         *fields = NULL;
1041         iter = NULL;
1042         while ((field = mono_class_get_fields (klass, &iter))) {
1043                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1044                         continue;
1045                 if (mono_field_is_deleted (field))
1046                         continue;
1047                 /* FIXME: Add more types */
1048                 switch (field->type->type) {
1049                 case MONO_TYPE_U1:
1050                 case MONO_TYPE_I1:
1051                 case MONO_TYPE_BOOLEAN:
1052                         if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1053                                 return FALSE;
1054                         break;
1055                 case MONO_TYPE_U2:
1056                 case MONO_TYPE_I2:
1057                 case MONO_TYPE_CHAR:
1058                         if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1059                                 return FALSE;
1060                         break;
1061                 case MONO_TYPE_U4:
1062                 case MONO_TYPE_I4:
1063                         if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1064                                 return FALSE;
1065                         break;
1066                 case MONO_TYPE_U8:
1067                 case MONO_TYPE_I8:
1068                         if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1069                                 return FALSE;
1070                         break;
1071                 case MONO_TYPE_R4:
1072                         if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1073                                 return FALSE;
1074                         break;
1075                 case MONO_TYPE_R8:
1076                         if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1077                                 return FALSE;
1078                         break;
1079
1080
1081                 case MONO_TYPE_STRING: {
1082                         MonoString *s1, *s2;
1083                         guint32 s1len, s2len;
1084                         s1 = *(MonoString**)((guint8*)this + field->offset);
1085                         s2 = *(MonoString**)((guint8*)that + field->offset);
1086                         if (s1 == s2)
1087                                 break;
1088                         if ((s1 == NULL) || (s2 == NULL))
1089                                 return FALSE;
1090                         s1len = mono_string_length (s1);
1091                         s2len = mono_string_length (s2);
1092                         if (s1len != s2len)
1093                                 return FALSE;
1094
1095                         if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1096                                 return FALSE;
1097                         break;
1098                 }
1099                 default:
1100                         if (!values)
1101                                 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1102                         o = mono_field_get_value_object (mono_object_domain (this), field, this);
1103                         values [count++] = o;
1104                         o = mono_field_get_value_object (mono_object_domain (this), field, that);
1105                         values [count++] = o;
1106                 }
1107
1108                 if (klass->enumtype)
1109                         /* enums only have one non-static field */
1110                         break;
1111         }
1112
1113         if (values) {
1114                 int i;
1115                 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1116                 for (i = 0; i < count; ++i)
1117                         mono_array_setref_fast (*fields, i, values [i]);
1118                 return FALSE;
1119         } else {
1120                 return TRUE;
1121         }
1122 }
1123
1124 ICALL_EXPORT MonoReflectionType *
1125 ves_icall_System_Object_GetType (MonoObject *obj)
1126 {
1127         MONO_ARCH_SAVE_REGS;
1128
1129 #ifndef DISABLE_REMOTING
1130         if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1131                 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1132         else
1133 #endif
1134                 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1135 }
1136
1137 ICALL_EXPORT void
1138 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1139 {
1140         MONO_ARCH_SAVE_REGS;
1141
1142         mtype->type = &obj->vtable->klass->byval_arg;
1143         g_assert (mtype->type->type);
1144 }
1145
1146 ICALL_EXPORT gint32
1147 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1148 {
1149         MONO_ARCH_SAVE_REGS;
1150         
1151         MONO_CHECK_ARG_NULL (obj);
1152         
1153         return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1154 }
1155
1156 ICALL_EXPORT gint32
1157 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1158                                         MonoReflectionMethod *method,
1159                                         MonoArray *opt_param_types)
1160 {
1161         MONO_ARCH_SAVE_REGS;
1162
1163         MONO_CHECK_ARG_NULL (method);
1164         
1165         return mono_image_create_method_token (
1166                 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1167 }
1168
1169 ICALL_EXPORT void
1170 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1171 {
1172         MONO_ARCH_SAVE_REGS;
1173
1174         mono_image_create_pefile (mb, file);
1175 }
1176
1177 ICALL_EXPORT void
1178 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1179 {
1180         MONO_ARCH_SAVE_REGS;
1181
1182         mono_image_build_metadata (mb);
1183 }
1184
1185 ICALL_EXPORT void
1186 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1187 {
1188         MONO_ARCH_SAVE_REGS;
1189
1190         mono_image_register_token (mb->dynamic_image, token, obj);
1191 }
1192
1193 static gboolean
1194 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1195 {
1196         MonoMethod **dest = data;
1197
1198         /* skip unmanaged frames */
1199         if (!managed)
1200                 return FALSE;
1201
1202         if (m == *dest) {
1203                 *dest = NULL;
1204                 return FALSE;
1205         }
1206         if (!(*dest)) {
1207                 *dest = m;
1208                 return TRUE;
1209         }
1210         return FALSE;
1211 }
1212
1213 static gboolean
1214 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1215 {
1216         MonoMethod **dest = data;
1217
1218         /* skip unmanaged frames */
1219         if (!managed)
1220                 return FALSE;
1221
1222         if (!(*dest)) {
1223                 if (!strcmp (m->klass->name_space, "System.Reflection"))
1224                         return FALSE;
1225                 *dest = m;
1226                 return TRUE;
1227         }
1228         return FALSE;
1229 }
1230
1231 static gboolean
1232 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1233 {
1234         MonoMethod **dest = data;
1235
1236         /* skip unmanaged frames */
1237         if (!managed)
1238                 return FALSE;
1239
1240         if (m->wrapper_type != MONO_WRAPPER_NONE)
1241                 return FALSE;
1242
1243         if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1244                 return FALSE;
1245
1246         if (m == *dest) {
1247                 *dest = NULL;
1248                 return FALSE;
1249         }
1250         if (!(*dest)) {
1251                 *dest = m;
1252                 return TRUE;
1253         }
1254         return FALSE;
1255 }
1256
1257 static MonoReflectionType *
1258 type_from_name (const char *str, MonoBoolean ignoreCase)
1259 {
1260         MonoType *type = NULL;
1261         MonoAssembly *assembly = NULL;
1262         MonoTypeNameParse info;
1263         char *temp_str = g_strdup (str);
1264         gboolean type_resolve = FALSE;
1265
1266         MONO_ARCH_SAVE_REGS;
1267
1268         /* mono_reflection_parse_type() mangles the string */
1269         if (!mono_reflection_parse_type (temp_str, &info)) {
1270                 mono_reflection_free_type_info (&info);
1271                 g_free (temp_str);
1272                 return NULL;
1273         }
1274
1275         if (info.assembly.name) {
1276                 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1277         } else {
1278                 MonoMethod *m = mono_method_get_last_managed ();
1279                 MonoMethod *dest = m;
1280
1281                 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1282                 if (!dest)
1283                         dest = m;
1284
1285                 /*
1286                  * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1287                  *        causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1288                  *        to crash.  This only seems to happen in some strange remoting
1289                  *        scenarios and I was unable to figure out what's happening there.
1290                  *        Dec 10, 2005 - Martin.
1291                  */
1292
1293                 if (dest) {
1294                         assembly = dest->klass->image->assembly;
1295                         type_resolve = TRUE;
1296                 } else {
1297                         g_warning (G_STRLOC);
1298                 }
1299         }
1300
1301         if (assembly) {
1302                 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1303                 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1304         }
1305
1306         if (!info.assembly.name && !type) /* try mscorlib */
1307                 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1308
1309         if (assembly && !type && type_resolve) {
1310                 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1311                 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1312         }
1313
1314         mono_reflection_free_type_info (&info);
1315         g_free (temp_str);
1316
1317         if (!type) 
1318                 return NULL;
1319
1320         return mono_type_get_object (mono_domain_get (), type);
1321 }
1322
1323 #ifdef UNUSED
1324 MonoReflectionType *
1325 mono_type_get (const char *str)
1326 {
1327         char *copy = g_strdup (str);
1328         MonoReflectionType *type = type_from_name (copy, FALSE);
1329
1330         g_free (copy);
1331         return type;
1332 }
1333 #endif
1334
1335 ICALL_EXPORT MonoReflectionType*
1336 ves_icall_type_from_name (MonoString *name,
1337                           MonoBoolean throwOnError,
1338                           MonoBoolean ignoreCase)
1339 {
1340         char *str = mono_string_to_utf8 (name);
1341         MonoReflectionType *type;
1342
1343         type = type_from_name (str, ignoreCase);
1344         g_free (str);
1345         if (type == NULL){
1346                 MonoException *e = NULL;
1347                 
1348                 if (throwOnError)
1349                         e = mono_get_exception_type_load (name, NULL);
1350
1351                 mono_loader_clear_error ();
1352                 if (e != NULL)
1353                         mono_raise_exception (e);
1354         }
1355         
1356         return type;
1357 }
1358
1359
1360 ICALL_EXPORT MonoReflectionType*
1361 ves_icall_type_from_handle (MonoType *handle)
1362 {
1363         MonoDomain *domain = mono_domain_get (); 
1364
1365         MONO_ARCH_SAVE_REGS;
1366
1367         return mono_type_get_object (domain, handle);
1368 }
1369
1370 ICALL_EXPORT MonoBoolean
1371 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1372 {
1373         MONO_ARCH_SAVE_REGS;
1374
1375         if (c && type->type && c->type)
1376                 return mono_metadata_type_equal (type->type, c->type);
1377         else
1378                 return (type == c) ? TRUE : FALSE;
1379 }
1380
1381 /* System.TypeCode */
1382 typedef enum {
1383         TYPECODE_EMPTY,
1384         TYPECODE_OBJECT,
1385         TYPECODE_DBNULL,
1386         TYPECODE_BOOLEAN,
1387         TYPECODE_CHAR,
1388         TYPECODE_SBYTE,
1389         TYPECODE_BYTE,
1390         TYPECODE_INT16,
1391         TYPECODE_UINT16,
1392         TYPECODE_INT32,
1393         TYPECODE_UINT32,
1394         TYPECODE_INT64,
1395         TYPECODE_UINT64,
1396         TYPECODE_SINGLE,
1397         TYPECODE_DOUBLE,
1398         TYPECODE_DECIMAL,
1399         TYPECODE_DATETIME,
1400         TYPECODE_STRING = 18
1401 } TypeCode;
1402
1403 ICALL_EXPORT guint32
1404 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1405 {
1406         int t = type->type->type;
1407
1408         MONO_ARCH_SAVE_REGS;
1409
1410         if (type->type->byref)
1411                 return TYPECODE_OBJECT;
1412
1413 handle_enum:
1414         switch (t) {
1415         case MONO_TYPE_VOID:
1416                 return TYPECODE_OBJECT;
1417         case MONO_TYPE_BOOLEAN:
1418                 return TYPECODE_BOOLEAN;
1419         case MONO_TYPE_U1:
1420                 return TYPECODE_BYTE;
1421         case MONO_TYPE_I1:
1422                 return TYPECODE_SBYTE;
1423         case MONO_TYPE_U2:
1424                 return TYPECODE_UINT16;
1425         case MONO_TYPE_I2:
1426                 return TYPECODE_INT16;
1427         case MONO_TYPE_CHAR:
1428                 return TYPECODE_CHAR;
1429         case MONO_TYPE_PTR:
1430         case MONO_TYPE_U:
1431         case MONO_TYPE_I:
1432                 return TYPECODE_OBJECT;
1433         case MONO_TYPE_U4:
1434                 return TYPECODE_UINT32;
1435         case MONO_TYPE_I4:
1436                 return TYPECODE_INT32;
1437         case MONO_TYPE_U8:
1438                 return TYPECODE_UINT64;
1439         case MONO_TYPE_I8:
1440                 return TYPECODE_INT64;
1441         case MONO_TYPE_R4:
1442                 return TYPECODE_SINGLE;
1443         case MONO_TYPE_R8:
1444                 return TYPECODE_DOUBLE;
1445         case MONO_TYPE_VALUETYPE: {
1446                 MonoClass *klass = type->type->data.klass;
1447                 
1448                 if (klass->enumtype) {
1449                         t = mono_class_enum_basetype (klass)->type;
1450                         goto handle_enum;
1451                 } else if (mono_is_corlib_image (klass->image)) {
1452                         if (strcmp (klass->name_space, "System") == 0) {
1453                                 if (strcmp (klass->name, "Decimal") == 0)
1454                                         return TYPECODE_DECIMAL;
1455                                 else if (strcmp (klass->name, "DateTime") == 0)
1456                                         return TYPECODE_DATETIME;
1457                         }
1458                 }
1459                 return TYPECODE_OBJECT;
1460         }
1461         case MONO_TYPE_STRING:
1462                 return TYPECODE_STRING;
1463         case MONO_TYPE_SZARRAY:
1464         case MONO_TYPE_ARRAY:
1465         case MONO_TYPE_OBJECT:
1466         case MONO_TYPE_VAR:
1467         case MONO_TYPE_MVAR:
1468         case MONO_TYPE_TYPEDBYREF:
1469                 return TYPECODE_OBJECT;
1470         case MONO_TYPE_CLASS:
1471                 {
1472                         MonoClass *klass =  type->type->data.klass;
1473                         if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1474                                 if (strcmp (klass->name, "DBNull") == 0)
1475                                         return TYPECODE_DBNULL;
1476                         }
1477                 }
1478                 return TYPECODE_OBJECT;
1479         case MONO_TYPE_GENERICINST:
1480                 return TYPECODE_OBJECT;
1481         default:
1482                 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1483         }
1484         return 0;
1485 }
1486
1487 ICALL_EXPORT guint32
1488 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1489 {
1490         MonoDomain *domain; 
1491         MonoClass *klass;
1492         MonoClass *klassc;
1493
1494         MONO_ARCH_SAVE_REGS;
1495
1496         g_assert (type != NULL);
1497         
1498         domain = ((MonoObject *)type)->vtable->domain;
1499
1500         if (!c) /* FIXME: dont know what do do here */
1501                 return 0;
1502
1503         klass = mono_class_from_mono_type (type->type);
1504         klassc = mono_class_from_mono_type (c->type);
1505
1506         /* Interface check requires a more complex setup so we
1507          * only do for them. Otherwise we simply avoid mono_class_init.
1508          */
1509         if (check_interfaces) {
1510                 mono_class_init_or_throw (klass);
1511                 mono_class_init_or_throw (klassc);
1512         } else if (!klass->supertypes || !klassc->supertypes) {
1513                 mono_loader_lock ();
1514                 mono_class_setup_supertypes (klass);
1515                 mono_class_setup_supertypes (klassc);
1516                 mono_loader_unlock ();
1517         }
1518
1519         if (type->type->byref)
1520                 return klassc == mono_defaults.object_class;
1521
1522         return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1523 }
1524
1525 static gboolean
1526 mono_type_is_primitive (MonoType *type)
1527 {
1528         return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1529                         type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1530 }
1531
1532 static MonoType*
1533 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1534 {
1535         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1536                 return mono_class_enum_basetype (type->data.klass);
1537         if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1538                 return mono_class_enum_basetype (type->data.generic_class->container_class);
1539         return type;
1540 }
1541
1542 ICALL_EXPORT guint32
1543 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1544 {
1545         MonoDomain *domain; 
1546         MonoClass *klass;
1547         MonoClass *klassc;
1548
1549         MONO_ARCH_SAVE_REGS;
1550
1551         g_assert (type != NULL);
1552         
1553         domain = ((MonoObject *)type)->vtable->domain;
1554
1555         klass = mono_class_from_mono_type (type->type);
1556         klassc = mono_class_from_mono_type (c->type);
1557
1558         mono_class_init_or_throw (klass);
1559         mono_class_init_or_throw (klassc);
1560
1561         if (type->type->byref ^ c->type->byref)
1562                 return FALSE;
1563
1564         if (type->type->byref) {
1565                 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1566                 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1567
1568                 klass = mono_class_from_mono_type (t);
1569                 klassc = mono_class_from_mono_type (ot);
1570
1571                 if (mono_type_is_primitive (t)) {
1572                         return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1573                 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1574                         return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1575                 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1576                         return t->type == ot->type;
1577                 } else {
1578                          if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1579                                  return FALSE;
1580
1581                          if (klass->valuetype)
1582                                 return klass == klassc;
1583                         return klass->valuetype == klassc->valuetype;
1584                 }
1585         }
1586         return mono_class_is_assignable_from (klass, klassc);
1587 }
1588
1589 ICALL_EXPORT guint32
1590 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1591 {
1592         MonoClass *klass = mono_class_from_mono_type (type->type);
1593         mono_class_init_or_throw (klass);
1594         return mono_object_isinst (obj, klass) != NULL;
1595 }
1596
1597 ICALL_EXPORT guint32
1598 ves_icall_get_attributes (MonoReflectionType *type)
1599 {
1600         MonoClass *klass = mono_class_from_mono_type (type->type);
1601         return klass->flags;
1602 }
1603
1604 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1605 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1606 {
1607         MonoClass *klass = field->field->parent;
1608         MonoMarshalType *info;
1609         int i;
1610
1611         if (klass->generic_container ||
1612             (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1613                 return NULL;
1614
1615         info = mono_marshal_load_type_info (klass);
1616
1617         for (i = 0; i < info->num_fields; ++i) {
1618                 if (info->fields [i].field == field->field) {
1619                         if (!info->fields [i].mspec)
1620                                 return NULL;
1621                         else
1622                                 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1623                 }
1624         }
1625
1626         return NULL;
1627 }
1628
1629 ICALL_EXPORT MonoReflectionField*
1630 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1631 {
1632         gboolean found = FALSE;
1633         MonoClass *klass;
1634         MonoClass *k;
1635
1636         g_assert (handle);
1637
1638         if (!type) {
1639                 klass = handle->parent;
1640         } else {
1641                 klass = mono_class_from_mono_type (type);
1642
1643                 /* Check that the field belongs to the class */
1644                 for (k = klass; k; k = k->parent) {
1645                         if (k == handle->parent) {
1646                                 found = TRUE;
1647                                 break;
1648                         }
1649                 }
1650
1651                 if (!found)
1652                         /* The managed code will throw the exception */
1653                         return NULL;
1654         }
1655
1656         return mono_field_get_object (mono_domain_get (), klass, handle);
1657 }
1658
1659 ICALL_EXPORT MonoArray*
1660 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1661 {
1662         MonoError error;
1663         MonoType *type = mono_field_get_type_checked (field->field, &error);
1664         if (!mono_error_ok (&error))
1665                 mono_error_raise_exception (&error);
1666
1667         return type_array_from_modifiers (field->field->parent->image, type, optional);
1668 }
1669
1670 ICALL_EXPORT int
1671 vell_icall_get_method_attributes (MonoMethod *method)
1672 {
1673         return method->flags;
1674 }
1675
1676 ICALL_EXPORT void
1677 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1678 {
1679         MonoError error;
1680         MonoDomain *domain = mono_domain_get ();
1681         MonoMethodSignature* sig;
1682         MONO_ARCH_SAVE_REGS;
1683
1684         sig = mono_method_signature_checked (method, &error);
1685         if (!mono_error_ok (&error))
1686                 mono_error_raise_exception (&error);
1687
1688
1689         MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1690         MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1691         info->attrs = method->flags;
1692         info->implattrs = method->iflags;
1693         if (sig->call_convention == MONO_CALL_DEFAULT)
1694                 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1695         else {
1696                 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1697                         info->callconv = 2;
1698                 else
1699                         info->callconv = 1;
1700         }
1701         info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6); 
1702 }
1703
1704 ICALL_EXPORT MonoArray*
1705 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1706 {
1707         MonoDomain *domain = mono_domain_get (); 
1708
1709         return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1710 }
1711
1712 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1713 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1714 {
1715         MonoDomain *domain = mono_domain_get (); 
1716         MonoReflectionMarshalAsAttribute* res = NULL;
1717         MonoMarshalSpec **mspecs;
1718         int i;
1719
1720         mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1721         mono_method_get_marshal_info (method, mspecs);
1722
1723         if (mspecs [0])
1724                 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1725                 
1726         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1727                 if (mspecs [i])
1728                         mono_metadata_free_marshal_spec (mspecs [i]);
1729         g_free (mspecs);
1730
1731         return res;
1732 }
1733
1734 ICALL_EXPORT gint32
1735 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1736 {
1737         MonoClass *parent = field->field->parent;
1738         if (!parent->size_inited)
1739                 mono_class_init (parent);
1740
1741         return field->field->offset - sizeof (MonoObject);
1742 }
1743
1744 ICALL_EXPORT MonoReflectionType*
1745 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1746 {
1747         MonoClass *parent;
1748         MONO_ARCH_SAVE_REGS;
1749
1750         parent = declaring? field->field->parent: field->klass;
1751
1752         return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1753 }
1754
1755 ICALL_EXPORT MonoObject *
1756 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1757 {       
1758         MonoClass *fklass = field->klass;
1759         MonoClassField *cf = field->field;
1760         MonoDomain *domain = mono_object_domain (field);
1761
1762         if (fklass->image->assembly->ref_only)
1763                 mono_raise_exception (mono_get_exception_invalid_operation (
1764                                         "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1765
1766         if (mono_security_core_clr_enabled ())
1767                 mono_security_core_clr_ensure_reflection_access_field (cf);
1768
1769         return mono_field_get_value_object (domain, cf, obj);
1770 }
1771
1772 ICALL_EXPORT void
1773 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1774 {
1775         MonoError error;
1776         MonoClassField *cf = field->field;
1777         MonoType *type;
1778         gchar *v;
1779
1780         MONO_ARCH_SAVE_REGS;
1781
1782         if (field->klass->image->assembly->ref_only)
1783                 mono_raise_exception (mono_get_exception_invalid_operation (
1784                                         "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1785
1786         if (mono_security_core_clr_enabled ())
1787                 mono_security_core_clr_ensure_reflection_access_field (cf);
1788
1789         type = mono_field_get_type_checked (cf, &error);
1790         if (!mono_error_ok (&error))
1791                 mono_error_raise_exception (&error);
1792
1793         v = (gchar *) value;
1794         if (!type->byref) {
1795                 switch (type->type) {
1796                 case MONO_TYPE_U1:
1797                 case MONO_TYPE_I1:
1798                 case MONO_TYPE_BOOLEAN:
1799                 case MONO_TYPE_U2:
1800                 case MONO_TYPE_I2:
1801                 case MONO_TYPE_CHAR:
1802                 case MONO_TYPE_U:
1803                 case MONO_TYPE_I:
1804                 case MONO_TYPE_U4:
1805                 case MONO_TYPE_I4:
1806                 case MONO_TYPE_R4:
1807                 case MONO_TYPE_U8:
1808                 case MONO_TYPE_I8:
1809                 case MONO_TYPE_R8:
1810                 case MONO_TYPE_VALUETYPE:
1811                 case MONO_TYPE_PTR:
1812                         if (v != NULL)
1813                                 v += sizeof (MonoObject);
1814                         break;
1815                 case MONO_TYPE_STRING:
1816                 case MONO_TYPE_OBJECT:
1817                 case MONO_TYPE_CLASS:
1818                 case MONO_TYPE_ARRAY:
1819                 case MONO_TYPE_SZARRAY:
1820                         /* Do nothing */
1821                         break;
1822                 case MONO_TYPE_GENERICINST: {
1823                         MonoGenericClass *gclass = type->data.generic_class;
1824                         g_assert (!gclass->context.class_inst->is_open);
1825
1826                         if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1827                                 MonoClass *nklass = mono_class_from_mono_type (type);
1828                                 MonoObject *nullable;
1829
1830                                 /* 
1831                                  * Convert the boxed vtype into a Nullable structure.
1832                                  * This is complicated by the fact that Nullables have
1833                                  * a variable structure.
1834                                  */
1835                                 nullable = mono_object_new (mono_domain_get (), nklass);
1836
1837                                 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1838
1839                                 v = mono_object_unbox (nullable);
1840                         }
1841                         else 
1842                                 if (gclass->container_class->valuetype && (v != NULL))
1843                                         v += sizeof (MonoObject);
1844                         break;
1845                 }
1846                 default:
1847                         g_error ("type 0x%x not handled in "
1848                                  "ves_icall_FieldInfo_SetValueInternal", type->type);
1849                         return;
1850                 }
1851         }
1852
1853         if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1854                 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1855                 if (!vtable->initialized)
1856                         mono_runtime_class_init (vtable);
1857                 mono_field_static_set_value (vtable, cf, v);
1858         } else {
1859                 mono_field_set_value (obj, cf, v);
1860         }
1861 }
1862
1863 ICALL_EXPORT MonoObject *
1864 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1865 {       
1866         MonoObject *o = NULL;
1867         MonoClassField *field = this->field;
1868         MonoClass *klass;
1869         MonoDomain *domain = mono_object_domain (this); 
1870         gchar *v;
1871         MonoTypeEnum def_type;
1872         const char *def_value;
1873         MonoType *t;
1874         MonoError error;
1875
1876         MONO_ARCH_SAVE_REGS;
1877         
1878         mono_class_init (field->parent);
1879
1880         t = mono_field_get_type_checked (field, &error);
1881         if (!mono_error_ok (&error))
1882                 mono_error_raise_exception (&error);
1883
1884         if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1885                 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1886
1887         if (field->parent->image->dynamic) {
1888                 /* FIXME: */
1889                 g_assert_not_reached ();
1890         }
1891
1892         def_value = mono_class_get_field_default_value (field, &def_type);
1893         if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1894                 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1895
1896         /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1897         switch (def_type) {
1898         case MONO_TYPE_U1:
1899         case MONO_TYPE_I1:
1900         case MONO_TYPE_BOOLEAN:
1901         case MONO_TYPE_U2:
1902         case MONO_TYPE_I2:
1903         case MONO_TYPE_CHAR:
1904         case MONO_TYPE_U:
1905         case MONO_TYPE_I:
1906         case MONO_TYPE_U4:
1907         case MONO_TYPE_I4:
1908         case MONO_TYPE_R4:
1909         case MONO_TYPE_U8:
1910         case MONO_TYPE_I8:
1911         case MONO_TYPE_R8: {
1912                 MonoType *t;
1913
1914                 /* boxed value type */
1915                 t = g_new0 (MonoType, 1);
1916                 t->type = def_type;
1917                 klass = mono_class_from_mono_type (t);
1918                 g_free (t);
1919                 o = mono_object_new (domain, klass);
1920                 v = ((gchar *) o) + sizeof (MonoObject);
1921                 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1922                 break;
1923         }
1924         case MONO_TYPE_STRING:
1925         case MONO_TYPE_CLASS:
1926                 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1927                 break;
1928         default:
1929                 g_assert_not_reached ();
1930         }
1931
1932         return o;
1933 }
1934
1935 ICALL_EXPORT MonoReflectionType*
1936 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1937 {
1938         MonoError error;
1939         MonoClassField *field = ref_field->field;
1940         MonoType *type = mono_field_get_type_checked (field, &error);
1941         if (!mono_error_ok (&error))
1942                 mono_error_raise_exception (&error);
1943         return mono_type_get_object (mono_object_domain (ref_field), type);
1944 }
1945
1946 ICALL_EXPORT MonoReflectionType*
1947 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1948 {
1949         MonoMethod *method = rmethod->method.method;
1950
1951         return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1952 }
1953
1954 /* From MonoProperty.cs */
1955 typedef enum {
1956         PInfo_Attributes = 1,
1957         PInfo_GetMethod  = 1 << 1,
1958         PInfo_SetMethod  = 1 << 2,
1959         PInfo_ReflectedType = 1 << 3,
1960         PInfo_DeclaringType = 1 << 4,
1961         PInfo_Name = 1 << 5
1962 } PInfo;
1963
1964 ICALL_EXPORT void
1965 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1966 {
1967         MonoDomain *domain = mono_object_domain (property); 
1968
1969         MONO_ARCH_SAVE_REGS;
1970
1971         if ((req_info & PInfo_ReflectedType) != 0)
1972                 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1973         if ((req_info & PInfo_DeclaringType) != 0)
1974                 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
1975
1976         if ((req_info & PInfo_Name) != 0)
1977                 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1978
1979         if ((req_info & PInfo_Attributes) != 0)
1980                 info->attrs = property->property->attrs;
1981
1982         if ((req_info & PInfo_GetMethod) != 0)
1983                 MONO_STRUCT_SETREF (info, get, property->property->get ?
1984                                                         mono_method_get_object (domain, property->property->get, property->klass): NULL);
1985         
1986         if ((req_info & PInfo_SetMethod) != 0)
1987                 MONO_STRUCT_SETREF (info, set, property->property->set ?
1988                                                         mono_method_get_object (domain, property->property->set, property->klass): NULL);
1989         /* 
1990          * There may be other methods defined for properties, though, it seems they are not exposed 
1991          * in the reflection API 
1992          */
1993 }
1994
1995 ICALL_EXPORT void
1996 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
1997 {
1998         MonoDomain *domain = mono_object_domain (event); 
1999
2000         MONO_ARCH_SAVE_REGS;
2001
2002         MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2003         MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2004
2005         MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2006         info->attrs = event->event->attrs;
2007         MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2008         MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2009         MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2010
2011 #ifndef MONO_SMALL_CONFIG
2012         if (event->event->other) {
2013                 int i, n = 0;
2014                 while (event->event->other [n])
2015                         n++;
2016                 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2017
2018                 for (i = 0; i < n; i++)
2019                         mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2020         }               
2021 #endif
2022 }
2023
2024 static void
2025 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2026 {
2027         int i;
2028         MonoClass *ic;
2029
2030         mono_class_setup_interfaces (klass, error);
2031         if (!mono_error_ok (error))
2032                 return;
2033
2034         for (i = 0; i < klass->interface_count; i++) {
2035                 ic = klass->interfaces [i];
2036                 g_hash_table_insert (ifaces, ic, ic);
2037
2038                 collect_interfaces (ic, ifaces, error);
2039                 if (!mono_error_ok (error))
2040                         return;
2041         }
2042 }
2043
2044 typedef struct {
2045         MonoArray *iface_array;
2046         MonoGenericContext *context;
2047         MonoError *error;
2048         MonoDomain *domain;
2049         int next_idx;
2050 } FillIfaceArrayData;
2051
2052 static void
2053 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2054 {
2055         FillIfaceArrayData *data = user_data;
2056         MonoClass *ic = key;
2057         MonoType *ret = &ic->byval_arg, *inflated = NULL;
2058
2059         if (!mono_error_ok (data->error))
2060                 return;
2061
2062         if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2063                 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2064                 if (!mono_error_ok (data->error))
2065                         return;
2066         }
2067
2068         mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2069
2070         if (inflated)
2071                 mono_metadata_free_type (inflated);
2072 }
2073
2074 ICALL_EXPORT MonoArray*
2075 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2076 {
2077         MonoError error;
2078         MonoClass *class = mono_class_from_mono_type (type->type);
2079         MonoClass *parent;
2080         FillIfaceArrayData data = { 0 };
2081         int len;
2082
2083         GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2084
2085         if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2086                 data.context = mono_class_get_context (class);
2087                 class = class->generic_class->container_class;
2088         }
2089
2090         for (parent = class; parent; parent = parent->parent) {
2091                 mono_class_setup_interfaces (parent, &error);
2092                 if (!mono_error_ok (&error))
2093                         goto fail;
2094                 collect_interfaces (parent, iface_hash, &error);
2095                 if (!mono_error_ok (&error))
2096                         goto fail;
2097         }
2098
2099         data.error = &error;
2100         data.domain = mono_object_domain (type);
2101
2102         len = g_hash_table_size (iface_hash);
2103         if (len == 0) {
2104                 g_hash_table_destroy (iface_hash);
2105                 if (!data.domain->empty_types)
2106                         data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2107                 return data.domain->empty_types;
2108         }
2109
2110         data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2111         g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2112         if (!mono_error_ok (&error))
2113                 goto fail;
2114
2115         g_hash_table_destroy (iface_hash);
2116         return data.iface_array;
2117
2118 fail:
2119         g_hash_table_destroy (iface_hash);
2120         mono_error_raise_exception (&error);
2121         return NULL;
2122 }
2123
2124 ICALL_EXPORT void
2125 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2126 {
2127         gboolean variance_used;
2128         MonoClass *class = mono_class_from_mono_type (type->type);
2129         MonoClass *iclass = mono_class_from_mono_type (iface->type);
2130         MonoReflectionMethod *member;
2131         MonoMethod* method;
2132         gpointer iter;
2133         int i = 0, len, ioffset;
2134         MonoDomain *domain;
2135
2136         MONO_ARCH_SAVE_REGS;
2137         mono_class_init_or_throw (class);
2138         mono_class_init_or_throw (iclass);
2139
2140         mono_class_setup_vtable (class);
2141
2142         ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2143         if (ioffset == -1)
2144                 return;
2145
2146         len = mono_class_num_methods (iclass);
2147         domain = mono_object_domain (type);
2148         mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2149         mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2150         iter = NULL;
2151         while ((method = mono_class_get_methods (iclass, &iter))) {
2152                 member = mono_method_get_object (domain, method, iclass);
2153                 mono_array_setref (*methods, i, member);
2154                 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2155                 mono_array_setref (*targets, i, member);
2156                 
2157                 i ++;
2158         }
2159 }
2160
2161 ICALL_EXPORT void
2162 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2163 {
2164         MonoClass *klass = mono_class_from_mono_type (type->type);
2165         mono_class_init_or_throw (klass);
2166
2167         if (klass->image->dynamic) {
2168                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2169                 *packing = tb->packing_size;
2170                 *size = tb->class_size;
2171         } else {
2172                 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2173         }
2174 }
2175
2176 ICALL_EXPORT MonoReflectionType*
2177 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2178 {
2179         MonoClass *class;
2180
2181         MONO_ARCH_SAVE_REGS;
2182
2183         if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2184                 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2185
2186         class = mono_class_from_mono_type (type->type);
2187         mono_class_init_or_throw (class);
2188
2189         // GetElementType should only return a type for:
2190         // Array Pointer PassedByRef
2191         if (type->type->byref)
2192                 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2193         else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2194                 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2195         else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2196                 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2197         else
2198                 return NULL;
2199 }
2200
2201 ICALL_EXPORT MonoReflectionType*
2202 ves_icall_get_type_parent (MonoReflectionType *type)
2203 {
2204         MonoClass *class = mono_class_from_mono_type (type->type);
2205         return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2206 }
2207
2208 ICALL_EXPORT MonoBoolean
2209 ves_icall_type_ispointer (MonoReflectionType *type)
2210 {
2211         MONO_ARCH_SAVE_REGS;
2212
2213         return type->type->type == MONO_TYPE_PTR;
2214 }
2215
2216 ICALL_EXPORT MonoBoolean
2217 ves_icall_type_isprimitive (MonoReflectionType *type)
2218 {
2219         MONO_ARCH_SAVE_REGS;
2220
2221         return (!type->type->byref && (((type->type->type >= MONO_TYPE_BOOLEAN) && (type->type->type <= MONO_TYPE_R8)) || (type->type->type == MONO_TYPE_I) || (type->type->type == MONO_TYPE_U)));
2222 }
2223
2224 ICALL_EXPORT MonoBoolean
2225 ves_icall_type_isbyref (MonoReflectionType *type)
2226 {
2227         MONO_ARCH_SAVE_REGS;
2228
2229         return type->type->byref;
2230 }
2231
2232 ICALL_EXPORT MonoBoolean
2233 ves_icall_type_iscomobject (MonoReflectionType *type)
2234 {
2235         MonoClass *klass = mono_class_from_mono_type (type->type);
2236         mono_class_init_or_throw (klass);
2237
2238         return mono_class_is_com_object (klass);
2239 }
2240
2241 ICALL_EXPORT MonoReflectionModule*
2242 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2243 {
2244         MonoClass *class = mono_class_from_mono_type (type->type);
2245         return mono_module_get_object (mono_object_domain (type), class->image);
2246 }
2247
2248 ICALL_EXPORT MonoReflectionAssembly*
2249 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2250 {
2251         MonoDomain *domain = mono_domain_get (); 
2252         MonoClass *class = mono_class_from_mono_type (type->type);
2253         return mono_assembly_get_object (domain, class->image->assembly);
2254 }
2255
2256 ICALL_EXPORT MonoReflectionType*
2257 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2258 {
2259         MonoDomain *domain = mono_domain_get ();
2260         MonoClass *class;
2261
2262         MONO_ARCH_SAVE_REGS;
2263
2264         if (type->type->byref)
2265                 return NULL;
2266         if (type->type->type == MONO_TYPE_VAR)
2267                 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2268         else if (type->type->type == MONO_TYPE_MVAR)
2269                 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2270         else
2271                 class = mono_class_from_mono_type (type->type)->nested_in;
2272
2273         return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2274 }
2275
2276 ICALL_EXPORT MonoString*
2277 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2278 {
2279         MonoDomain *domain = mono_domain_get (); 
2280         MonoClass *class = mono_class_from_mono_type (type->type);
2281
2282         if (type->type->byref) {
2283                 char *n = g_strdup_printf ("%s&", class->name);
2284                 MonoString *res = mono_string_new (domain, n);
2285
2286                 g_free (n);
2287
2288                 return res;
2289         } else {
2290                 return mono_string_new (domain, class->name);
2291         }
2292 }
2293
2294 ICALL_EXPORT MonoString*
2295 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2296 {
2297         MonoDomain *domain = mono_domain_get (); 
2298         MonoClass *class = mono_class_from_mono_type (type->type);
2299
2300         while (class->nested_in)
2301                 class = class->nested_in;
2302
2303         if (class->name_space [0] == '\0')
2304                 return NULL;
2305         else
2306                 return mono_string_new (domain, class->name_space);
2307 }
2308
2309 ICALL_EXPORT gint32
2310 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2311 {
2312         MonoClass *class;
2313
2314         if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2315                 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2316
2317         class = mono_class_from_mono_type (type->type);
2318
2319         return class->rank;
2320 }
2321
2322 ICALL_EXPORT MonoArray*
2323 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2324 {
2325         MonoArray *res;
2326         MonoClass *klass, *pklass;
2327         MonoDomain *domain = mono_object_domain (type);
2328         MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2329         int i;
2330         MONO_ARCH_SAVE_REGS;
2331
2332         klass = mono_class_from_mono_type (type->type);
2333
2334         if (klass->generic_container) {
2335                 MonoGenericContainer *container = klass->generic_container;
2336                 res = mono_array_new_specific (array_vtable, container->type_argc);
2337                 for (i = 0; i < container->type_argc; ++i) {
2338                         pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2339                         mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2340                 }
2341         } else if (klass->generic_class) {
2342                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2343                 res = mono_array_new_specific (array_vtable, inst->type_argc);
2344                 for (i = 0; i < inst->type_argc; ++i)
2345                         mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2346         } else {
2347                 res = mono_array_new_specific (array_vtable, 0);
2348         }
2349         return res;
2350 }
2351
2352 ICALL_EXPORT gboolean
2353 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2354 {
2355         MonoClass *klass;
2356         MONO_ARCH_SAVE_REGS;
2357
2358         if (!IS_MONOTYPE (type))
2359                 return FALSE;
2360
2361         if (type->type->byref)
2362                 return FALSE;
2363
2364         klass = mono_class_from_mono_type (type->type);
2365         return klass->generic_container != NULL;
2366 }
2367
2368 ICALL_EXPORT MonoReflectionType*
2369 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2370 {
2371         MonoClass *klass;
2372         MONO_ARCH_SAVE_REGS;
2373
2374         if (type->type->byref)
2375                 return NULL;
2376
2377         klass = mono_class_from_mono_type (type->type);
2378
2379         if (klass->generic_container) {
2380                 return type; /* check this one */
2381         }
2382         if (klass->generic_class) {
2383                 MonoClass *generic_class = klass->generic_class->container_class;
2384                 gpointer tb;
2385
2386                 tb = mono_class_get_ref_info (generic_class);
2387
2388                 if (generic_class->wastypebuilder && tb)
2389                         return tb;
2390                 else
2391                         return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2392         }
2393         return NULL;
2394 }
2395
2396 ICALL_EXPORT MonoReflectionType*
2397 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2398 {
2399         MonoClass *class;
2400         MonoType *geninst, **types;
2401         int i, count;
2402
2403         g_assert (IS_MONOTYPE (type));
2404         mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2405
2406         count = mono_array_length (type_array);
2407         types = g_new0 (MonoType *, count);
2408
2409         for (i = 0; i < count; i++) {
2410                 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2411                 types [i] = t->type;
2412         }
2413
2414         geninst = mono_reflection_bind_generic_parameters (type, count, types);
2415         g_free (types);
2416         if (!geninst)
2417                 return NULL;
2418
2419         class = mono_class_from_mono_type (geninst);
2420
2421         /*we might inflate to the GTD*/
2422         if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2423                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2424
2425         return mono_type_get_object (mono_object_domain (type), geninst);
2426 }
2427
2428 ICALL_EXPORT gboolean
2429 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2430 {
2431         MonoClass *klass;
2432         MONO_ARCH_SAVE_REGS;
2433
2434         if (type->type->byref)
2435                 return FALSE;
2436
2437         klass = mono_class_from_mono_type (type->type);
2438
2439         return klass->generic_class != NULL;
2440 }
2441
2442 ICALL_EXPORT gboolean
2443 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2444 {
2445         MonoClass *klass;
2446         MONO_ARCH_SAVE_REGS;
2447
2448         if (!IS_MONOTYPE (type))
2449                 return FALSE;
2450
2451         if (type->type->byref)
2452                 return FALSE;
2453
2454         klass = mono_class_from_mono_type (type->type);
2455         return klass->generic_class != NULL || klass->generic_container != NULL;
2456 }
2457
2458 ICALL_EXPORT gint32
2459 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2460 {
2461         MONO_ARCH_SAVE_REGS;
2462
2463         if (!IS_MONOTYPE (type))
2464                 return -1;
2465
2466         if (is_generic_parameter (type->type))
2467                 return mono_type_get_generic_param_num (type->type);
2468         return -1;
2469 }
2470
2471 ICALL_EXPORT GenericParameterAttributes
2472 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2473 {
2474         MONO_ARCH_SAVE_REGS;
2475
2476         g_assert (IS_MONOTYPE (type));
2477         g_assert (is_generic_parameter (type->type));
2478         return mono_generic_param_info (type->type->data.generic_param)->flags;
2479 }
2480
2481 ICALL_EXPORT MonoArray *
2482 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2483 {
2484         MonoGenericParamInfo *param_info;
2485         MonoDomain *domain;
2486         MonoClass **ptr;
2487         MonoArray *res;
2488         int i, count;
2489
2490         MONO_ARCH_SAVE_REGS;
2491
2492         g_assert (IS_MONOTYPE (type));
2493
2494         domain = mono_object_domain (type);
2495         param_info = mono_generic_param_info (type->type->data.generic_param);
2496         for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2497                 ;
2498
2499         res = mono_array_new (domain, mono_defaults.monotype_class, count);
2500         for (i = 0; i < count; i++)
2501                 mono_array_setref (res, i, mono_type_get_object (domain, &param_info->constraints [i]->byval_arg));
2502
2503
2504         return res;
2505 }
2506
2507 ICALL_EXPORT MonoBoolean
2508 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2509 {
2510         MONO_ARCH_SAVE_REGS;
2511         return is_generic_parameter (type->type);
2512 }
2513
2514 ICALL_EXPORT MonoBoolean
2515 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2516 {
2517         MONO_ARCH_SAVE_REGS;
2518         return is_generic_parameter (tb->type.type);
2519 }
2520
2521 ICALL_EXPORT void
2522 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2523                                                                            MonoReflectionType *t)
2524 {
2525         enumtype->type = t->type;
2526 }
2527
2528 ICALL_EXPORT MonoReflectionMethod*
2529 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type, 
2530                                                    MonoReflectionMethod* generic)
2531 {
2532         MonoDomain *domain; 
2533         MonoClass *klass;
2534         MonoMethod *method;
2535         gpointer iter;
2536                 
2537         MONO_ARCH_SAVE_REGS;
2538
2539         domain = ((MonoObject *)type)->vtable->domain;
2540
2541         klass = mono_class_from_mono_type (type->type);
2542         mono_class_init_or_throw (klass);
2543
2544         iter = NULL;
2545         while ((method = mono_class_get_methods (klass, &iter))) {
2546                 if (method->token == generic->method->token)
2547                         return mono_method_get_object (domain, method, klass);
2548         }
2549
2550         return NULL;
2551 }
2552
2553
2554
2555 ICALL_EXPORT MonoReflectionMethod *
2556 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2557 {
2558         MonoMethod *method;
2559         MonoType *type = ref_type->type;
2560
2561         MONO_ARCH_SAVE_REGS;
2562
2563         if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2564                 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2565         if (type->type == MONO_TYPE_VAR)
2566                 return NULL;
2567
2568         method = mono_type_get_generic_param_owner (type)->owner.method;
2569         g_assert (method);
2570         return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2571 }
2572
2573 ICALL_EXPORT MonoReflectionDllImportAttribute*
2574 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2575 {
2576         static MonoClass *DllImportAttributeClass = NULL;
2577         MonoDomain *domain = mono_domain_get ();
2578         MonoReflectionDllImportAttribute *attr;
2579         MonoImage *image = method->klass->image;
2580         MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2581         MonoTableInfo *tables = image->tables;
2582         MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2583         MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2584         guint32 im_cols [MONO_IMPLMAP_SIZE];
2585         guint32 scope_token;
2586         const char *import = NULL;
2587         const char *scope = NULL;
2588         guint32 flags;
2589
2590         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2591                 return NULL;
2592
2593         if (!DllImportAttributeClass) {
2594                 DllImportAttributeClass = 
2595                         mono_class_from_name (mono_defaults.corlib,
2596                                                                   "System.Runtime.InteropServices", "DllImportAttribute");
2597                 g_assert (DllImportAttributeClass);
2598         }
2599                                                                                                                 
2600         if (method->klass->image->dynamic) {
2601                 MonoReflectionMethodAux *method_aux = 
2602                         g_hash_table_lookup (
2603                                                                           ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2604                 if (method_aux) {
2605                         import = method_aux->dllentry;
2606                         scope = method_aux->dll;
2607                 }
2608
2609                 if (!import || !scope) {
2610                         mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2611                         return NULL;
2612                 }
2613         }
2614         else {
2615                 if (piinfo->implmap_idx) {
2616                         mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2617                         
2618                         piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2619                         import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2620                         scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2621                         scope = mono_metadata_string_heap (image, scope_token);
2622                 }
2623         }
2624         flags = piinfo->piflags;
2625         
2626         attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2627
2628         MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2629         MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2630         attr->call_conv = (flags & 0x700) >> 8;
2631         attr->charset = ((flags & 0x6) >> 1) + 1;
2632         if (attr->charset == 1)
2633                 attr->charset = 2;
2634         attr->exact_spelling = (flags & 0x1) != 0;
2635         attr->set_last_error = (flags & 0x40) != 0;
2636         attr->best_fit_mapping = (flags & 0x30) == 0x10;
2637         attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2638         attr->preserve_sig = FALSE;
2639
2640         return attr;
2641 }
2642
2643 ICALL_EXPORT MonoReflectionMethod *
2644 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2645 {
2646         MonoMethodInflated *imethod;
2647         MonoMethod *result;
2648
2649         MONO_ARCH_SAVE_REGS;
2650
2651         if (method->method->is_generic)
2652                 return method;
2653
2654         if (!method->method->is_inflated)
2655                 return NULL;
2656
2657         imethod = (MonoMethodInflated *) method->method;
2658
2659         result = imethod->declaring;
2660         /* Not a generic method.  */
2661         if (!result->is_generic)
2662                 return NULL;
2663
2664         if (method->method->klass->image->dynamic) {
2665                 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2666                 MonoReflectionMethod *res;
2667
2668                 /*
2669                  * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2670                  * the dynamic case as well ?
2671                  */
2672                 mono_loader_lock ();
2673                 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2674                 mono_loader_unlock ();
2675
2676                 if (res)
2677                         return res;
2678         }
2679
2680         if (imethod->context.class_inst) {
2681                 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2682                 /*Generic methods gets the context of the GTD.*/
2683                 if (mono_class_get_context (klass))
2684                         result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2685         }
2686
2687         return mono_method_get_object (mono_object_domain (method), result, NULL);
2688 }
2689
2690 ICALL_EXPORT gboolean
2691 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2692 {
2693         MONO_ARCH_SAVE_REGS;
2694
2695         return mono_method_signature (method->method)->generic_param_count != 0;
2696 }
2697
2698 ICALL_EXPORT gboolean
2699 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2700 {
2701         MONO_ARCH_SAVE_REGS;
2702
2703         return method->method->is_generic;
2704 }
2705
2706 ICALL_EXPORT MonoArray*
2707 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2708 {
2709         MonoArray *res;
2710         MonoDomain *domain;
2711         int count, i;
2712         MONO_ARCH_SAVE_REGS;
2713
2714         domain = mono_object_domain (method);
2715
2716         if (method->method->is_inflated) {
2717                 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2718
2719                 if (inst) {
2720                         count = inst->type_argc;
2721                         res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2722
2723                         for (i = 0; i < count; i++)
2724                                 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2725
2726                         return res;
2727                 }
2728         }
2729
2730         count = mono_method_signature (method->method)->generic_param_count;
2731         res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2732
2733         for (i = 0; i < count; i++) {
2734                 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2735                 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2736                 MonoClass *pklass = mono_class_from_generic_parameter (
2737                         param, method->method->klass->image, TRUE);
2738                 mono_array_setref (res, i,
2739                                 mono_type_get_object (domain, &pklass->byval_arg));
2740         }
2741
2742         return res;
2743 }
2744
2745 ICALL_EXPORT MonoObject *
2746 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc) 
2747 {
2748         /* 
2749          * Invoke from reflection is supposed to always be a virtual call (the API
2750          * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2751          * greater flexibility.
2752          */
2753         MonoMethod *m = method->method;
2754         MonoMethodSignature *sig = mono_method_signature (m);
2755         MonoImage *image;
2756         int pcount;
2757         void *obj = this;
2758
2759         MONO_ARCH_SAVE_REGS;
2760
2761         *exc = NULL;
2762
2763         if (mono_security_core_clr_enabled ())
2764                 mono_security_core_clr_ensure_reflection_access_method (m);
2765
2766         if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2767                 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2768                         mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2769                         return NULL;
2770                 }
2771
2772                 if (this) {
2773                         if (!mono_object_isinst (this, m->klass)) {
2774                                 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2775                                 char *target_name = mono_type_get_full_name (m->klass);
2776                                 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2777                                 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2778                                 g_free (msg);
2779                                 g_free (target_name);
2780                                 g_free (this_name);
2781                                 return NULL;
2782                         }
2783                         m = mono_object_get_virtual_method (this, m);
2784                         /* must pass the pointer to the value for valuetype methods */
2785                         if (m->klass->valuetype)
2786                                 obj = mono_object_unbox (this);
2787                 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2788                         mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2789                         return NULL;
2790                 }
2791         }
2792
2793         if (sig->ret->byref) {
2794                 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "Cannot invoke method returning ByRef type via reflection"));
2795                 return NULL;
2796         }
2797
2798         pcount = params? mono_array_length (params): 0;
2799         if (pcount != sig->param_count) {
2800                 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2801                 return NULL;
2802         }
2803
2804         if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2805                 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class."));
2806                 return NULL;
2807         }
2808
2809         image = m->klass->image;
2810         if (image->assembly->ref_only) {
2811                 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
2812                 return NULL;
2813         }
2814
2815         if (image->dynamic && !((MonoDynamicImage*)image)->run) {
2816                 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2817                 return NULL;
2818         }
2819         
2820         if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2821                 int i;
2822                 uintptr_t *lengths;
2823                 intptr_t *lower_bounds;
2824                 pcount = mono_array_length (params);
2825                 lengths = alloca (sizeof (uintptr_t) * pcount);
2826                 /* Note: the synthetized array .ctors have int32 as argument type */
2827                 for (i = 0; i < pcount; ++i)
2828                         lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2829
2830                 if (m->klass->rank == pcount) {
2831                         /* Only lengths provided. */
2832                         lower_bounds = NULL;
2833                 } else {
2834                         g_assert (pcount == (m->klass->rank * 2));
2835                         /* lower bounds are first. */
2836                         lower_bounds = (intptr_t*)lengths;
2837                         lengths += m->klass->rank;
2838                 }
2839
2840                 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2841         }
2842         return mono_runtime_invoke_array (m, obj, params, NULL);
2843 }
2844
2845 #ifndef DISABLE_REMOTING
2846 ICALL_EXPORT MonoObject *
2847 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs) 
2848 {
2849         MonoDomain *domain = mono_object_domain (method); 
2850         MonoMethod *m = method->method;
2851         MonoMethodSignature *sig = mono_method_signature (m);
2852         MonoArray *out_args;
2853         MonoObject *result;
2854         int i, j, outarg_count = 0;
2855
2856         MONO_ARCH_SAVE_REGS;
2857
2858         if (m->klass == mono_defaults.object_class) {
2859
2860                 if (!strcmp (m->name, "FieldGetter")) {
2861                         MonoClass *k = this->vtable->klass;
2862                         MonoString *name;
2863                         char *str;
2864                         
2865                         /* If this is a proxy, then it must be a CBO */
2866                         if (k == mono_defaults.transparent_proxy_class) {
2867                                 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2868                                 this = tp->rp->unwrapped_server;
2869                                 g_assert (this);
2870                                 k = this->vtable->klass;
2871                         }
2872                         
2873                         name = mono_array_get (params, MonoString *, 1);
2874                         str = mono_string_to_utf8 (name);
2875                 
2876                         do {
2877                                 MonoClassField* field = mono_class_get_field_from_name (k, str);
2878                                 if (field) {
2879                                         MonoClass *field_klass =  mono_class_from_mono_type (field->type);
2880                                         if (field_klass->valuetype)
2881                                                 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2882                                         else 
2883                                                 result = *((gpointer *)((char *)this + field->offset));
2884                                 
2885                                         out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2886                                         mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2887                                         mono_array_setref (out_args, 0, result);
2888                                         g_free (str);
2889                                         return NULL;
2890                                 }
2891                                 k = k->parent;
2892                         } while (k);
2893
2894                         g_free (str);
2895                         g_assert_not_reached ();
2896
2897                 } else if (!strcmp (m->name, "FieldSetter")) {
2898                         MonoClass *k = this->vtable->klass;
2899                         MonoString *name;
2900                         guint32 size;
2901                         gint32 align;
2902                         char *str;
2903                         
2904                         /* If this is a proxy, then it must be a CBO */
2905                         if (k == mono_defaults.transparent_proxy_class) {
2906                                 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2907                                 this = tp->rp->unwrapped_server;
2908                                 g_assert (this);
2909                                 k = this->vtable->klass;
2910                         }
2911                         
2912                         name = mono_array_get (params, MonoString *, 1);
2913                         str = mono_string_to_utf8 (name);
2914                 
2915                         do {
2916                                 MonoClassField* field = mono_class_get_field_from_name (k, str);
2917                                 if (field) {
2918                                         MonoClass *field_klass =  mono_class_from_mono_type (field->type);
2919                                         MonoObject *val = mono_array_get (params, gpointer, 2);
2920
2921                                         if (field_klass->valuetype) {
2922                                                 size = mono_type_size (field->type, &align);
2923                                                 g_assert (size == mono_class_value_size (field_klass, NULL));
2924                                                 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2925                                         } else {
2926                                                 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2927                                         }
2928                                 
2929                                         out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2930                                         mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2931
2932                                         g_free (str);
2933                                         return NULL;
2934                                 }
2935                                 
2936                                 k = k->parent;
2937                         } while (k);
2938
2939                         g_free (str);
2940                         g_assert_not_reached ();
2941
2942                 }
2943         }
2944
2945         for (i = 0; i < mono_array_length (params); i++) {
2946                 if (sig->params [i]->byref) 
2947                         outarg_count++;
2948         }
2949
2950         out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2951         
2952         /* handle constructors only for objects already allocated */
2953         if (!strcmp (method->method->name, ".ctor"))
2954                 g_assert (this);
2955
2956         /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2957         g_assert (!method->method->klass->valuetype);
2958         result = mono_runtime_invoke_array (method->method, this, params, NULL);
2959
2960         for (i = 0, j = 0; i < mono_array_length (params); i++) {
2961                 if (sig->params [i]->byref) {
2962                         gpointer arg;
2963                         arg = mono_array_get (params, gpointer, i);
2964                         mono_array_setref (out_args, j, arg);
2965                         j++;
2966                 }
2967         }
2968
2969         mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2970
2971         return result;
2972 }
2973 #endif
2974
2975 static guint64
2976 read_enum_value (char *mem, int type)
2977 {
2978         switch (type) {
2979         case MONO_TYPE_U1:
2980                 return *(guint8*)mem;
2981         case MONO_TYPE_I1:
2982                 return *(gint8*)mem;
2983         case MONO_TYPE_U2:
2984                 return *(guint16*)mem;
2985         case MONO_TYPE_I2:
2986                 return *(gint16*)mem;
2987         case MONO_TYPE_U4:
2988                 return *(guint32*)mem;
2989         case MONO_TYPE_I4:
2990                 return *(gint32*)mem;
2991         case MONO_TYPE_U8:
2992                 return *(guint64*)mem;
2993         case MONO_TYPE_I8:
2994                 return *(gint64*)mem;
2995         default:
2996                 g_assert_not_reached ();
2997         }
2998         return 0;
2999 }
3000
3001 static void
3002 write_enum_value (char *mem, int type, guint64 value)
3003 {
3004         switch (type) {
3005         case MONO_TYPE_U1:
3006         case MONO_TYPE_I1: {
3007                 guint8 *p = (guint8*)mem;
3008                 *p = value;
3009                 break;
3010         }
3011         case MONO_TYPE_U2:
3012         case MONO_TYPE_I2: {
3013                 guint16 *p = (void*)mem;
3014                 *p = value;
3015                 break;
3016         }
3017         case MONO_TYPE_U4:
3018         case MONO_TYPE_I4: {
3019                 guint32 *p = (void*)mem;
3020                 *p = value;
3021                 break;
3022         }
3023         case MONO_TYPE_U8:
3024         case MONO_TYPE_I8: {
3025                 guint64 *p = (void*)mem;
3026                 *p = value;
3027                 break;
3028         }
3029         default:
3030                 g_assert_not_reached ();
3031         }
3032         return;
3033 }
3034
3035 ICALL_EXPORT MonoObject *
3036 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3037 {
3038         MonoDomain *domain; 
3039         MonoClass *enumc, *objc;
3040         MonoObject *res;
3041         MonoType *etype;
3042         guint64 val;
3043         
3044         MONO_ARCH_SAVE_REGS;
3045
3046         MONO_CHECK_ARG_NULL (enumType);
3047         MONO_CHECK_ARG_NULL (value);
3048
3049         domain = mono_object_domain (enumType); 
3050         enumc = mono_class_from_mono_type (enumType->type);
3051
3052         mono_class_init_or_throw (enumc);
3053
3054         objc = value->vtable->klass;
3055
3056         if (!enumc->enumtype)
3057                 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3058         if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3059                 mono_raise_exception (mono_get_exception_argument ("value", "The value passed in must be an enum base or an underlying type for an enum, such as an Int32."));
3060
3061         etype = mono_class_enum_basetype (enumc);
3062         if (!etype)
3063                 /* MS throws this for typebuilders */
3064                 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3065
3066         res = mono_object_new (domain, enumc);
3067         val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3068         write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3069
3070         return res;
3071 }
3072
3073 ICALL_EXPORT MonoObject *
3074 ves_icall_System_Enum_get_value (MonoObject *this)
3075 {
3076         MonoObject *res;
3077         MonoClass *enumc;
3078         gpointer dst;
3079         gpointer src;
3080         int size;
3081
3082         MONO_ARCH_SAVE_REGS;
3083
3084         if (!this)
3085                 return NULL;
3086
3087         g_assert (this->vtable->klass->enumtype);
3088         
3089         enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3090         res = mono_object_new (mono_object_domain (this), enumc);
3091         dst = (char *)res + sizeof (MonoObject);
3092         src = (char *)this + sizeof (MonoObject);
3093         size = mono_class_value_size (enumc, NULL);
3094
3095         memcpy (dst, src, size);
3096
3097         return res;
3098 }
3099
3100 ICALL_EXPORT MonoReflectionType *
3101 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3102 {
3103         MonoType *etype;
3104         MonoClass *klass;
3105
3106         MONO_ARCH_SAVE_REGS;
3107
3108         klass = mono_class_from_mono_type (type->type);
3109         mono_class_init_or_throw (klass);
3110
3111         etype = mono_class_enum_basetype (klass);
3112         if (!etype)
3113                 /* MS throws this for typebuilders */
3114                 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3115
3116         return mono_type_get_object (mono_object_domain (type), etype);
3117 }
3118
3119 ICALL_EXPORT int
3120 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3121 {
3122         gpointer tdata = (char *)this + sizeof (MonoObject);
3123         gpointer odata = (char *)other + sizeof (MonoObject);
3124         MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3125         g_assert (basetype);
3126
3127 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3128                 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3129                 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3130                 if (me == other) \
3131                         return 0; \
3132                 return me > other ? 1 : -1; \
3133         } while (0)
3134
3135 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3136                 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3137                 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3138                 if (me == other) \
3139                         return 0; \
3140                 return me - other; \
3141         } while (0)
3142
3143         switch (basetype->type) {
3144                 case MONO_TYPE_U1:
3145                         COMPARE_ENUM_VALUES (guint8);
3146                 case MONO_TYPE_I1:
3147                         COMPARE_ENUM_VALUES (gint8);
3148                 case MONO_TYPE_CHAR:
3149                 case MONO_TYPE_U2:
3150                         COMPARE_ENUM_VALUES_RANGE (guint16);
3151                 case MONO_TYPE_I2:
3152                         COMPARE_ENUM_VALUES (gint16);
3153                 case MONO_TYPE_U4:
3154                         COMPARE_ENUM_VALUES (guint32);
3155                 case MONO_TYPE_I4:
3156                         COMPARE_ENUM_VALUES (gint32);
3157                 case MONO_TYPE_U8:
3158                         COMPARE_ENUM_VALUES (guint64);
3159                 case MONO_TYPE_I8:
3160                         COMPARE_ENUM_VALUES (gint64);
3161                 default:
3162                         g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3163         }
3164 #undef COMPARE_ENUM_VALUES_RANGE
3165 #undef COMPARE_ENUM_VALUES
3166         return 0;
3167 }
3168
3169 ICALL_EXPORT int
3170 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3171 {
3172         gpointer data = (char *)this + sizeof (MonoObject);
3173         MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3174         g_assert (basetype);
3175
3176         switch (basetype->type) {
3177                 case MONO_TYPE_I1:      
3178                         return *((gint8*)data);
3179                 case MONO_TYPE_U1:
3180                         return *((guint8*)data);
3181                 case MONO_TYPE_CHAR:
3182                 case MONO_TYPE_U2:
3183                         return *((guint16*)data);
3184                 
3185                 case MONO_TYPE_I2:
3186                         return *((gint16*)data);
3187                 case MONO_TYPE_U4:
3188                         return *((guint32*)data);
3189                 case MONO_TYPE_I4:
3190                         return *((gint32*)data);
3191                 case MONO_TYPE_U8:
3192                 case MONO_TYPE_I8: {
3193                         gint64 value = *((gint64*)data);
3194                         return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3195                 }
3196                 default:
3197                         g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3198         }
3199         return 0;
3200 }
3201
3202 ICALL_EXPORT void
3203 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3204 {
3205         MonoDomain *domain = mono_object_domain (type); 
3206         MonoClass *enumc = mono_class_from_mono_type (type->type);
3207         guint j = 0, nvalues, crow;
3208         gpointer iter;
3209         MonoClassField *field;
3210
3211         MONO_ARCH_SAVE_REGS;
3212
3213         mono_class_init_or_throw (enumc);
3214
3215         MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3216         nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3217         MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3218         MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3219
3220         crow = -1;
3221         iter = NULL;
3222         while ((field = mono_class_get_fields (enumc, &iter))) {
3223                 const char *p;
3224                 int len;
3225                 MonoTypeEnum def_type;
3226                 
3227                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3228                         continue;
3229                 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3230                         continue;
3231                 if (mono_field_is_deleted (field))
3232                         continue;
3233                 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3234
3235                 p = mono_class_get_field_default_value (field, &def_type);
3236                 len = mono_metadata_decode_blob_size (p, &p);
3237                 switch (mono_class_enum_basetype (enumc)->type) {
3238                 case MONO_TYPE_U1:
3239                 case MONO_TYPE_I1:
3240                         mono_array_set (info->values, gchar, j, *p);
3241                         break;
3242                 case MONO_TYPE_CHAR:
3243                 case MONO_TYPE_U2:
3244                 case MONO_TYPE_I2:
3245                         mono_array_set (info->values, gint16, j, read16 (p));
3246                         break;
3247                 case MONO_TYPE_U4:
3248                 case MONO_TYPE_I4:
3249                         mono_array_set (info->values, gint32, j, read32 (p));
3250                         break;
3251                 case MONO_TYPE_U8:
3252                 case MONO_TYPE_I8:
3253                         mono_array_set (info->values, gint64, j, read64 (p));
3254                         break;
3255                 default:
3256                         g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3257                 }
3258                 ++j;
3259         }
3260 }
3261
3262 enum {
3263         BFLAGS_IgnoreCase = 1,
3264         BFLAGS_DeclaredOnly = 2,
3265         BFLAGS_Instance = 4,
3266         BFLAGS_Static = 8,
3267         BFLAGS_Public = 0x10,
3268         BFLAGS_NonPublic = 0x20,
3269         BFLAGS_FlattenHierarchy = 0x40,
3270         BFLAGS_InvokeMethod = 0x100,
3271         BFLAGS_CreateInstance = 0x200,
3272         BFLAGS_GetField = 0x400,
3273         BFLAGS_SetField = 0x800,
3274         BFLAGS_GetProperty = 0x1000,
3275         BFLAGS_SetProperty = 0x2000,
3276         BFLAGS_ExactBinding = 0x10000,
3277         BFLAGS_SuppressChangeType = 0x20000,
3278         BFLAGS_OptionalParamBinding = 0x40000
3279 };
3280
3281 ICALL_EXPORT MonoReflectionField *
3282 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3283 {
3284         MonoDomain *domain; 
3285         MonoClass *startklass, *klass;
3286         int match;
3287         MonoClassField *field;
3288         gpointer iter;
3289         char *utf8_name;
3290         int (*compare_func) (const char *s1, const char *s2) = NULL;
3291         domain = ((MonoObject *)type)->vtable->domain;
3292         klass = startklass = mono_class_from_mono_type (type->type);
3293
3294         if (!name)
3295                 mono_raise_exception (mono_get_exception_argument_null ("name"));
3296         if (type->type->byref)
3297                 return NULL;
3298
3299         compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3300
3301 handle_parent:
3302         if (klass->exception_type != MONO_EXCEPTION_NONE)
3303                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3304
3305         iter = NULL;
3306         while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3307                 guint32 flags = mono_field_get_flags (field);
3308                 match = 0;
3309
3310                 if (mono_field_is_deleted_with_flags (field, flags))
3311                         continue;
3312                 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3313                         if (bflags & BFLAGS_Public)
3314                                 match++;
3315                 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3316                         if (bflags & BFLAGS_NonPublic) {
3317                                 match++;
3318                         }
3319                 }
3320                 if (!match)
3321                         continue;
3322                 match = 0;
3323                 if (flags & FIELD_ATTRIBUTE_STATIC) {
3324                         if (bflags & BFLAGS_Static)
3325                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3326                                         match++;
3327                 } else {
3328                         if (bflags & BFLAGS_Instance)
3329                                 match++;
3330                 }
3331
3332                 if (!match)
3333                         continue;
3334                 
3335                 utf8_name = mono_string_to_utf8 (name);
3336
3337                 if (compare_func (mono_field_get_name (field), utf8_name)) {
3338                         g_free (utf8_name);
3339                         continue;
3340                 }
3341                 g_free (utf8_name);
3342                 
3343                 return mono_field_get_object (domain, klass, field);
3344         }
3345         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3346                 goto handle_parent;
3347
3348         return NULL;
3349 }
3350
3351 ICALL_EXPORT MonoArray*
3352 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3353 {
3354         MonoDomain *domain; 
3355         MonoClass *startklass, *klass, *refklass;
3356         MonoArray *res;
3357         MonoObject *member;
3358         int i, match;
3359         gpointer iter;
3360         MonoClassField *field;
3361         MonoPtrArray tmp_array;
3362
3363         MONO_ARCH_SAVE_REGS;
3364
3365         domain = ((MonoObject *)type)->vtable->domain;
3366         if (type->type->byref)
3367                 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3368         klass = startklass = mono_class_from_mono_type (type->type);
3369         refklass = mono_class_from_mono_type (reftype->type);
3370
3371         mono_ptr_array_init (tmp_array, 2);
3372         
3373 handle_parent:  
3374         if (klass->exception_type != MONO_EXCEPTION_NONE) {
3375                 mono_ptr_array_destroy (tmp_array);
3376                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3377         }
3378
3379         iter = NULL;
3380         while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3381                 guint32 flags = mono_field_get_flags (field);
3382                 match = 0;
3383                 if (mono_field_is_deleted_with_flags (field, flags))
3384                         continue;
3385                 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3386                         if (bflags & BFLAGS_Public)
3387                                 match++;
3388                 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3389                         if (bflags & BFLAGS_NonPublic) {
3390                                 match++;
3391                         }
3392                 }
3393                 if (!match)
3394                         continue;
3395                 match = 0;
3396                 if (flags & FIELD_ATTRIBUTE_STATIC) {
3397                         if (bflags & BFLAGS_Static)
3398                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3399                                         match++;
3400                 } else {
3401                         if (bflags & BFLAGS_Instance)
3402                                 match++;
3403                 }
3404
3405                 if (!match)
3406                         continue;
3407                 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3408                 mono_ptr_array_append (tmp_array, member);
3409         }
3410         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3411                 goto handle_parent;
3412
3413         res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3414
3415         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3416                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3417
3418         mono_ptr_array_destroy (tmp_array);
3419
3420         return res;
3421 }
3422
3423 static gboolean
3424 method_nonpublic (MonoMethod* method, gboolean start_klass)
3425 {
3426         switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3427                 case METHOD_ATTRIBUTE_ASSEM:
3428                         return (start_klass || mono_defaults.generic_ilist_class);
3429                 case METHOD_ATTRIBUTE_PRIVATE:
3430                         return start_klass;
3431                 case METHOD_ATTRIBUTE_PUBLIC:
3432                         return FALSE;
3433                 default:
3434                         return TRUE;
3435         }
3436 }
3437
3438 GPtrArray*
3439 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3440 {
3441         GPtrArray *array;
3442         MonoClass *startklass;
3443         MonoMethod *method;
3444         gpointer iter;
3445         int len, match, nslots;
3446         /*FIXME, use MonoBitSet*/
3447         guint32 method_slots_default [8];
3448         guint32 *method_slots = NULL;
3449         int (*compare_func) (const char *s1, const char *s2) = NULL;
3450
3451         array = g_ptr_array_new ();
3452         startklass = klass;
3453         *ex = NULL;
3454
3455         len = 0;
3456         if (name != NULL)
3457                 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3458
3459         /* An optimization for calls made from Delegate:CreateDelegate () */
3460         if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3461                 method = mono_get_delegate_invoke (klass);
3462                 if (mono_loader_get_last_error ())
3463                         goto loader_error;
3464
3465                 g_ptr_array_add (array, method);
3466                 return array;
3467         }
3468
3469         mono_class_setup_vtable (klass);
3470         if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3471                 goto loader_error;
3472
3473         if (is_generic_parameter (&klass->byval_arg))
3474                 nslots = mono_class_get_vtable_size (klass->parent);
3475         else
3476                 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3477         if (nslots >= sizeof (method_slots_default) * 8) {
3478                 method_slots = g_new0 (guint32, nslots / 32 + 1);
3479         } else {
3480                 method_slots = method_slots_default;
3481                 memset (method_slots, 0, sizeof (method_slots_default));
3482         }
3483 handle_parent:
3484         mono_class_setup_vtable (klass);
3485         if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3486                 goto loader_error;              
3487
3488         iter = NULL;
3489         while ((method = mono_class_get_methods (klass, &iter))) {
3490                 match = 0;
3491                 if (method->slot != -1) {
3492                         g_assert (method->slot < nslots);
3493                         if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3494                                 continue;
3495                         if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3496                                 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3497                 }
3498
3499                 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3500                         continue;
3501                 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3502                         if (bflags & BFLAGS_Public)
3503                                 match++;
3504                 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3505                                 match++;
3506                 }
3507                 if (!match)
3508                         continue;
3509                 match = 0;
3510                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3511                         if (bflags & BFLAGS_Static)
3512                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3513                                         match++;
3514                 } else {
3515                         if (bflags & BFLAGS_Instance)
3516                                 match++;
3517                 }
3518
3519                 if (!match)
3520                         continue;
3521
3522                 if (name != NULL) {
3523                         if (compare_func (name, method->name))
3524                                 continue;
3525                 }
3526                 
3527                 match = 0;
3528                 g_ptr_array_add (array, method);
3529         }
3530         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3531                 goto handle_parent;
3532         if (method_slots != method_slots_default)
3533                 g_free (method_slots);
3534
3535         return array;
3536
3537 loader_error:
3538         if (method_slots != method_slots_default)
3539                 g_free (method_slots);
3540         g_ptr_array_free (array, TRUE);
3541
3542         if (klass->exception_type != MONO_EXCEPTION_NONE) {
3543                 *ex = mono_class_get_exception_for_failure (klass);
3544         } else {
3545                 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3546                 mono_loader_clear_error ();
3547         }
3548         return NULL;
3549 }
3550
3551 ICALL_EXPORT MonoArray*
3552 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3553 {
3554         static MonoClass *MethodInfo_array;
3555         MonoDomain *domain; 
3556         MonoArray *res;
3557         MonoVTable *array_vtable;
3558         MonoException *ex = NULL;
3559         const char *mname = NULL;
3560         GPtrArray *method_array;
3561         MonoClass *klass, *refklass;
3562         int i;
3563
3564         if (!MethodInfo_array) {
3565                 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3566                 mono_memory_barrier ();
3567                 MethodInfo_array = klass;
3568         }
3569
3570         klass = mono_class_from_mono_type (type->type);
3571         refklass = mono_class_from_mono_type (reftype->type);
3572         domain = ((MonoObject *)type)->vtable->domain;
3573         array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3574         if (type->type->byref)
3575                 return mono_array_new_specific (array_vtable, 0);
3576
3577         if (name)
3578                 mname = mono_string_to_utf8 (name);
3579
3580         method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3581         g_free ((char*)mname);
3582         if (ex)
3583                 mono_raise_exception (ex);
3584
3585         res = mono_array_new_specific (array_vtable, method_array->len);
3586
3587
3588         for (i = 0; i < method_array->len; ++i) {
3589                 MonoMethod *method = g_ptr_array_index (method_array, i);
3590                 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3591         }
3592
3593         g_ptr_array_free (method_array, TRUE);
3594         return res;
3595 }
3596
3597 ICALL_EXPORT MonoArray*
3598 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3599 {
3600         MonoDomain *domain; 
3601         static MonoClass *System_Reflection_ConstructorInfo;
3602         MonoClass *startklass, *klass, *refklass;
3603         MonoArray *res;
3604         MonoMethod *method;
3605         MonoObject *member;
3606         int i, match;
3607         gpointer iter = NULL;
3608         MonoPtrArray tmp_array;
3609         
3610         MONO_ARCH_SAVE_REGS;
3611
3612         mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3613
3614         domain = ((MonoObject *)type)->vtable->domain;
3615         if (type->type->byref)
3616                 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3617         klass = startklass = mono_class_from_mono_type (type->type);
3618         refklass = mono_class_from_mono_type (reftype->type);
3619
3620         if (!System_Reflection_ConstructorInfo)
3621                 System_Reflection_ConstructorInfo = mono_class_from_name (
3622                         mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3623
3624         iter = NULL;
3625         while ((method = mono_class_get_methods (klass, &iter))) {
3626                 match = 0;
3627                 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3628                         continue;
3629                 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3630                         if (bflags & BFLAGS_Public)
3631                                 match++;
3632                 } else {
3633                         if (bflags & BFLAGS_NonPublic)
3634                                 match++;
3635                 }
3636                 if (!match)
3637                         continue;
3638                 match = 0;
3639                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3640                         if (bflags & BFLAGS_Static)
3641                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3642                                         match++;
3643                 } else {
3644                         if (bflags & BFLAGS_Instance)
3645                                 match++;
3646                 }
3647
3648                 if (!match)
3649                         continue;
3650                 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3651
3652                 mono_ptr_array_append (tmp_array, member);
3653         }
3654
3655         res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3656
3657         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3658                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3659
3660         mono_ptr_array_destroy (tmp_array);
3661
3662         return res;
3663 }
3664
3665 static guint
3666 property_hash (gconstpointer data)
3667 {
3668         MonoProperty *prop = (MonoProperty*)data;
3669
3670         return g_str_hash (prop->name);
3671 }
3672
3673 static gboolean
3674 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3675 {
3676         // Properties are hide-by-name-and-signature
3677         if (!g_str_equal (prop1->name, prop2->name))
3678                 return FALSE;
3679
3680         if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3681                 return FALSE;
3682         if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3683                 return FALSE;
3684         return TRUE;
3685 }
3686
3687 static gboolean
3688 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3689 {
3690         if (!accessor)
3691                 return FALSE;
3692
3693         return method_nonpublic (accessor, start_klass);
3694 }
3695
3696 ICALL_EXPORT MonoArray*
3697 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3698 {
3699         MonoException *ex;
3700         MonoDomain *domain; 
3701         static MonoClass *System_Reflection_PropertyInfo;
3702         MonoClass *startklass, *klass;
3703         MonoArray *res;
3704         MonoMethod *method;
3705         MonoProperty *prop;
3706         int i, match;
3707         guint32 flags;
3708         gchar *propname = NULL;
3709         int (*compare_func) (const char *s1, const char *s2) = NULL;
3710         gpointer iter;
3711         GHashTable *properties = NULL;
3712         MonoPtrArray tmp_array;
3713
3714         MONO_ARCH_SAVE_REGS;
3715
3716         mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3717
3718         if (!System_Reflection_PropertyInfo)
3719                 System_Reflection_PropertyInfo = mono_class_from_name (
3720                         mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3721
3722         domain = ((MonoObject *)type)->vtable->domain;
3723         if (type->type->byref)
3724                 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3725         klass = startklass = mono_class_from_mono_type (type->type);
3726
3727         if (name != NULL) {
3728                 propname = mono_string_to_utf8 (name);
3729                 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3730         }
3731
3732         properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3733 handle_parent:
3734         mono_class_setup_vtable (klass);
3735         if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3736                 goto loader_error;
3737
3738         iter = NULL;
3739         while ((prop = mono_class_get_properties (klass, &iter))) {
3740                 match = 0;
3741                 method = prop->get;
3742                 if (!method)
3743                         method = prop->set;
3744                 if (method)
3745                         flags = method->flags;
3746                 else
3747                         flags = 0;
3748                 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3749                         (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3750                         if (bflags & BFLAGS_Public)
3751                                 match++;
3752                 } else if (bflags & BFLAGS_NonPublic) {
3753                         if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3754                                 property_accessor_nonpublic(prop->set, startklass == klass)) {
3755                                 match++;
3756                         }
3757                 }
3758                 if (!match)
3759                         continue;
3760                 match = 0;
3761                 if (flags & METHOD_ATTRIBUTE_STATIC) {
3762                         if (bflags & BFLAGS_Static)
3763                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3764                                         match++;
3765                 } else {
3766                         if (bflags & BFLAGS_Instance)
3767                                 match++;
3768                 }
3769
3770                 if (!match)
3771                         continue;
3772                 match = 0;
3773
3774                 if (name != NULL) {
3775                         if (compare_func (propname, prop->name))
3776                                 continue;
3777                 }
3778                 
3779                 if (g_hash_table_lookup (properties, prop))
3780                         continue;
3781
3782                 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3783                 
3784                 g_hash_table_insert (properties, prop, prop);
3785         }
3786         if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3787                 goto handle_parent;
3788
3789         g_hash_table_destroy (properties);
3790         g_free (propname);
3791
3792         res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3793         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3794                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3795
3796         mono_ptr_array_destroy (tmp_array);
3797
3798         return res;
3799
3800 loader_error:
3801         if (properties)
3802                 g_hash_table_destroy (properties);
3803         if (name)
3804                 g_free (propname);
3805         mono_ptr_array_destroy (tmp_array);
3806
3807         if (klass->exception_type != MONO_EXCEPTION_NONE) {
3808                 ex = mono_class_get_exception_for_failure (klass);
3809         } else {
3810                 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3811                 mono_loader_clear_error ();
3812         }
3813         mono_raise_exception (ex);
3814         return NULL;
3815 }
3816
3817 ICALL_EXPORT MonoReflectionEvent *
3818 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3819 {
3820         MonoDomain *domain;
3821         MonoClass *klass, *startklass;
3822         gpointer iter;
3823         MonoEvent *event;
3824         MonoMethod *method;
3825         gchar *event_name;
3826         int (*compare_func) (const char *s1, const char *s2);
3827
3828         MONO_ARCH_SAVE_REGS;
3829
3830         event_name = mono_string_to_utf8 (name);
3831         if (type->type->byref)
3832                 return NULL;
3833         klass = startklass = mono_class_from_mono_type (type->type);
3834         domain = mono_object_domain (type);
3835
3836         mono_class_init_or_throw (klass);
3837
3838         compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3839 handle_parent:  
3840         if (klass->exception_type != MONO_EXCEPTION_NONE)
3841                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3842
3843         iter = NULL;
3844         while ((event = mono_class_get_events (klass, &iter))) {
3845                 if (compare_func (event->name, event_name))
3846                         continue;
3847
3848                 method = event->add;
3849                 if (!method)
3850                         method = event->remove;
3851                 if (!method)
3852                         method = event->raise;
3853                 if (method) {
3854                         if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3855                                 if (!(bflags & BFLAGS_Public))
3856                                         continue;
3857                         } else {
3858                                 if (!(bflags & BFLAGS_NonPublic))
3859                                         continue;
3860                                 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3861                                         continue;
3862                         }
3863
3864                         if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3865                                 if (!(bflags & BFLAGS_Static))
3866                                         continue;
3867                                 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3868                                         continue;
3869                         } else {
3870                                 if (!(bflags & BFLAGS_Instance))
3871                                         continue;
3872                         }
3873                 } else 
3874                         if (!(bflags & BFLAGS_NonPublic))
3875                                 continue;
3876                 
3877                 g_free (event_name);
3878                 return mono_event_get_object (domain, startklass, event);
3879         }
3880
3881         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3882                 goto handle_parent;
3883
3884         g_free (event_name);
3885         return NULL;
3886 }
3887
3888 ICALL_EXPORT MonoArray*
3889 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3890 {
3891         MonoException *ex;
3892         MonoDomain *domain; 
3893         static MonoClass *System_Reflection_EventInfo;
3894         MonoClass *startklass, *klass;
3895         MonoArray *res;
3896         MonoMethod *method;
3897         MonoEvent *event;
3898         int i, match;
3899         gpointer iter;
3900         
3901         MonoPtrArray tmp_array;
3902
3903         MONO_ARCH_SAVE_REGS;
3904
3905         mono_ptr_array_init (tmp_array, 4);
3906
3907         if (!System_Reflection_EventInfo)
3908                 System_Reflection_EventInfo = mono_class_from_name (
3909                         mono_defaults.corlib, "System.Reflection", "EventInfo");
3910
3911         domain = mono_object_domain (type);
3912         if (type->type->byref)
3913                 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3914         klass = startklass = mono_class_from_mono_type (type->type);
3915
3916 handle_parent:
3917         mono_class_setup_vtable (klass);
3918         if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3919                 goto loader_error;
3920
3921         iter = NULL;
3922         while ((event = mono_class_get_events (klass, &iter))) {
3923                 match = 0;
3924                 method = event->add;
3925                 if (!method)
3926                         method = event->remove;
3927                 if (!method)
3928                         method = event->raise;
3929                 if (method) {
3930                         if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3931                                 if (bflags & BFLAGS_Public)
3932                                         match++;
3933                         } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3934                                 if (bflags & BFLAGS_NonPublic)
3935                                         match++;
3936                         }
3937                 }
3938                 else
3939                         if (bflags & BFLAGS_NonPublic)
3940                                 match ++;
3941                 if (!match)
3942                         continue;
3943                 match = 0;
3944                 if (method) {
3945                         if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3946                                 if (bflags & BFLAGS_Static)
3947                                         if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3948                                                 match++;
3949                         } else {
3950                                 if (bflags & BFLAGS_Instance)
3951                                         match++;
3952                         }
3953                 }
3954                 else
3955                         if (bflags & BFLAGS_Instance)
3956                                 match ++;
3957                 if (!match)
3958                         continue;
3959                 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3960         }
3961         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3962                 goto handle_parent;
3963
3964         res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3965
3966         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3967                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3968
3969         mono_ptr_array_destroy (tmp_array);
3970
3971         return res;
3972
3973 loader_error:
3974         mono_ptr_array_destroy (tmp_array);
3975         if (klass->exception_type != MONO_EXCEPTION_NONE) {
3976                 ex = mono_class_get_exception_for_failure (klass);
3977         } else {
3978                 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3979                 mono_loader_clear_error ();
3980         }
3981         mono_raise_exception (ex);
3982         return NULL;
3983 }
3984
3985 ICALL_EXPORT MonoReflectionType *
3986 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3987 {
3988         MonoDomain *domain; 
3989         MonoClass *klass;
3990         MonoClass *nested;
3991         char *str;
3992         gpointer iter;
3993         
3994         MONO_ARCH_SAVE_REGS;
3995
3996         if (name == NULL)
3997                 mono_raise_exception (mono_get_exception_argument_null ("name"));
3998         
3999         domain = ((MonoObject *)type)->vtable->domain;
4000         if (type->type->byref)
4001                 return NULL;
4002         klass = mono_class_from_mono_type (type->type);
4003
4004         str = mono_string_to_utf8 (name);
4005
4006  handle_parent:
4007         if (klass->exception_type != MONO_EXCEPTION_NONE)
4008                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4009
4010         /*
4011          * If a nested type is generic, return its generic type definition.
4012          * Note that this means that the return value is essentially a
4013          * nested type of the generic type definition of @klass.
4014          *
4015          * A note in MSDN claims that a generic type definition can have
4016          * nested types that aren't generic.  In any case, the container of that
4017          * nested type would be the generic type definition.
4018          */
4019         if (klass->generic_class)
4020                 klass = klass->generic_class->container_class;
4021
4022         iter = NULL;
4023         while ((nested = mono_class_get_nested_types (klass, &iter))) {
4024                 int match = 0;
4025                 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4026                         if (bflags & BFLAGS_Public)
4027                                 match++;
4028                 } else {
4029                         if (bflags & BFLAGS_NonPublic)
4030                                 match++;
4031                 }
4032                 if (!match)
4033                         continue;
4034                 if (strcmp (nested->name, str) == 0){
4035                         g_free (str);
4036                         return mono_type_get_object (domain, &nested->byval_arg);
4037                 }
4038         }
4039         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4040                 goto handle_parent;
4041         g_free (str);
4042         return NULL;
4043 }
4044
4045 ICALL_EXPORT MonoArray*
4046 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4047 {
4048         MonoDomain *domain; 
4049         MonoClass *klass;
4050         MonoArray *res;
4051         MonoObject *member;
4052         int i, match;
4053         MonoClass *nested;
4054         gpointer iter;
4055         MonoPtrArray tmp_array;
4056
4057         MONO_ARCH_SAVE_REGS;
4058
4059         domain = ((MonoObject *)type)->vtable->domain;
4060         if (type->type->byref)
4061                 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4062         klass = mono_class_from_mono_type (type->type);
4063
4064         /*
4065          * If a nested type is generic, return its generic type definition.
4066          * Note that this means that the return value is essentially the set
4067          * of nested types of the generic type definition of @klass.
4068          *
4069          * A note in MSDN claims that a generic type definition can have
4070          * nested types that aren't generic.  In any case, the container of that
4071          * nested type would be the generic type definition.
4072          */
4073         if (klass->generic_class)
4074                 klass = klass->generic_class->container_class;
4075
4076         mono_ptr_array_init (tmp_array, 1);
4077         iter = NULL;
4078         while ((nested = mono_class_get_nested_types (klass, &iter))) {
4079                 match = 0;
4080                 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4081                         if (bflags & BFLAGS_Public)
4082                                 match++;
4083                 } else {
4084                         if (bflags & BFLAGS_NonPublic)
4085                                 match++;
4086                 }
4087                 if (!match)
4088                         continue;
4089                 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4090                 mono_ptr_array_append (tmp_array, member);
4091         }
4092
4093         res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4094
4095         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4096                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4097
4098         mono_ptr_array_destroy (tmp_array);
4099
4100         return res;
4101 }
4102
4103 ICALL_EXPORT MonoReflectionType*
4104 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4105 {
4106         gchar *str;
4107         MonoType *type = NULL;
4108         MonoTypeNameParse info;
4109         gboolean type_resolve;
4110
4111         MONO_ARCH_SAVE_REGS;
4112
4113         /* On MS.NET, this does not fire a TypeResolve event */
4114         type_resolve = TRUE;
4115         str = mono_string_to_utf8 (name);
4116         /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4117         if (!mono_reflection_parse_type (str, &info)) {
4118                 g_free (str);
4119                 mono_reflection_free_type_info (&info);
4120                 if (throwOnError) /* uhm: this is a parse error, though... */
4121                         mono_raise_exception (mono_get_exception_type_load (name, NULL));
4122                 /*g_print ("failed parse\n");*/
4123                 return NULL;
4124         }
4125
4126         if (info.assembly.name) {
4127                 g_free (str);
4128                 mono_reflection_free_type_info (&info);
4129                 if (throwOnError) {
4130                         /* 1.0 and 2.0 throw different exceptions */
4131                         if (mono_defaults.generic_ilist_class)
4132                                 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4133                         else
4134                                 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4135                 }
4136                 return NULL;
4137         }
4138
4139         if (module != NULL) {
4140                 if (module->image)
4141                         type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4142                 else
4143                         type = NULL;
4144         }
4145         else
4146                 if (assembly->assembly->dynamic) {
4147                         /* Enumerate all modules */
4148                         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4149                         int i;
4150
4151                         type = NULL;
4152                         if (abuilder->modules) {
4153                                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4154                                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4155                                         type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4156                                         if (type)
4157                                                 break;
4158                                 }
4159                         }
4160
4161                         if (!type && abuilder->loaded_modules) {
4162                                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4163                                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4164                                         type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4165                                         if (type)
4166                                                 break;
4167                                 }
4168                         }
4169                 }
4170                 else
4171                         type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4172         g_free (str);
4173         mono_reflection_free_type_info (&info);
4174         if (!type) {
4175                 MonoException *e = NULL;
4176                 
4177                 if (throwOnError)
4178                         e = mono_get_exception_type_load (name, NULL);
4179
4180                 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4181                         e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4182
4183                 mono_loader_clear_error ();
4184
4185                 if (e != NULL)
4186                         mono_raise_exception (e);
4187
4188                 return NULL;
4189         } else if (mono_loader_get_last_error ()) {
4190                 if (throwOnError)
4191                         mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4192                 mono_loader_clear_error ();
4193         }
4194
4195         if (type->type == MONO_TYPE_CLASS) {
4196                 MonoClass *klass = mono_type_get_class (type);
4197
4198                 if (mono_security_enabled () && !klass->exception_type)
4199                         /* Some security problems are detected during generic vtable construction */
4200                         mono_class_setup_vtable (klass);
4201
4202                 /* need to report exceptions ? */
4203                 if (throwOnError && klass->exception_type) {
4204                         /* report SecurityException (or others) that occured when loading the assembly */
4205                         MonoException *exc = mono_class_get_exception_for_failure (klass);
4206                         mono_loader_clear_error ();
4207                         mono_raise_exception (exc);
4208                 } else if (mono_security_enabled () && klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4209                         return NULL;
4210                 }
4211         }
4212
4213         /* g_print ("got it\n"); */
4214         return mono_type_get_object (mono_object_domain (assembly), type);
4215 }
4216
4217 static gboolean
4218 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4219 {
4220         gchar *content;
4221         gchar *shadow_ini_file;
4222         gsize len;
4223
4224         /* Check for shadow-copied assembly */
4225         if (mono_is_shadow_copy_enabled (domain, dirname)) {
4226                 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4227                 content = NULL;
4228                 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4229                         !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4230                         if (content) {
4231                                 g_free (content);
4232                                 content = NULL;
4233                         }
4234                 }
4235                 g_free (shadow_ini_file);
4236                 if (content != NULL) {
4237                         if (*filename)
4238                                 g_free (*filename);
4239                         *filename = content;
4240                         return TRUE;
4241                 }
4242         }
4243         return FALSE;
4244 }
4245
4246 ICALL_EXPORT MonoString *
4247 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4248 {
4249         MonoDomain *domain = mono_object_domain (assembly); 
4250         MonoAssembly *mass = assembly->assembly;
4251         MonoString *res = NULL;
4252         gchar *uri;
4253         gchar *absolute;
4254         gchar *dirname;
4255         
4256         MONO_ARCH_SAVE_REGS;
4257
4258         if (g_path_is_absolute (mass->image->name)) {
4259                 absolute = g_strdup (mass->image->name);
4260                 dirname = g_path_get_dirname (absolute);
4261         } else {
4262                 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4263                 dirname = g_strdup (mass->basedir);
4264         }
4265
4266         replace_shadow_path (domain, dirname, &absolute);
4267         g_free (dirname);
4268 #if HOST_WIN32
4269         {
4270                 gint i;
4271                 for (i = strlen (absolute) - 1; i >= 0; i--)
4272                         if (absolute [i] == '\\')
4273                                 absolute [i] = '/';
4274         }
4275 #endif
4276         if (escaped) {
4277                 uri = g_filename_to_uri (absolute, NULL, NULL);
4278         } else {
4279                 const char *prepend = "file://";
4280 #if HOST_WIN32
4281                 if (*absolute == '/' && *(absolute + 1) == '/') {
4282                         prepend = "file:";
4283                 } else {
4284                         prepend = "file:///";
4285                 }
4286 #endif
4287                 uri = g_strconcat (prepend, absolute, NULL);
4288         }
4289
4290         if (uri) {
4291                 res = mono_string_new (domain, uri);
4292                 g_free (uri);
4293         }
4294         g_free (absolute);
4295         return res;
4296 }
4297
4298 ICALL_EXPORT MonoBoolean
4299 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4300 {
4301         MonoAssembly *mass = assembly->assembly;
4302
4303         MONO_ARCH_SAVE_REGS;
4304
4305         return mass->in_gac;
4306 }
4307
4308 ICALL_EXPORT MonoReflectionAssembly*
4309 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4310 {
4311         gchar *name;
4312         MonoAssembly *res;
4313         MonoImageOpenStatus status;
4314         
4315         MONO_ARCH_SAVE_REGS;
4316
4317         name = mono_string_to_utf8 (mname);
4318         res = mono_assembly_load_with_partial_name (name, &status);
4319
4320         g_free (name);
4321
4322         if (res == NULL)
4323                 return NULL;
4324         return mono_assembly_get_object (mono_domain_get (), res);
4325 }
4326
4327 ICALL_EXPORT MonoString *
4328 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4329 {
4330         MonoDomain *domain = mono_object_domain (assembly); 
4331         MonoString *res;
4332
4333         MONO_ARCH_SAVE_REGS;
4334
4335         res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4336
4337         return res;
4338 }
4339
4340 ICALL_EXPORT MonoBoolean
4341 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4342 {
4343         MONO_ARCH_SAVE_REGS;
4344
4345         return assembly->assembly->ref_only;
4346 }
4347
4348 ICALL_EXPORT MonoString *
4349 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4350 {
4351         MonoDomain *domain = mono_object_domain (assembly); 
4352
4353         MONO_ARCH_SAVE_REGS;
4354
4355         return mono_string_new (domain, assembly->assembly->image->version);
4356 }
4357
4358 ICALL_EXPORT MonoReflectionMethod*
4359 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly) 
4360 {
4361         guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4362
4363         MONO_ARCH_SAVE_REGS;
4364
4365         if (!token)
4366                 return NULL;
4367         return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4368 }
4369
4370 ICALL_EXPORT MonoReflectionModule*
4371 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly) 
4372 {
4373         return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4374 }
4375
4376 ICALL_EXPORT MonoArray*
4377 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly) 
4378 {
4379         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4380         MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4381         int i;
4382         const char *val;
4383
4384         MONO_ARCH_SAVE_REGS;
4385
4386         for (i = 0; i < table->rows; ++i) {
4387                 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4388                 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4389         }
4390         return result;
4391 }
4392
4393 static MonoObject*
4394 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4395 {
4396         static MonoClass *System_Version = NULL;
4397         static MonoMethod *create_version = NULL;
4398         MonoObject *result;
4399         gpointer args [4];
4400         
4401         if (!System_Version) {
4402                 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4403                 g_assert (System_Version);
4404         }
4405
4406         if (!create_version) {
4407                 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4408                 create_version = mono_method_desc_search_in_class (desc, System_Version);
4409                 g_assert (create_version);
4410                 mono_method_desc_free (desc);
4411         }
4412
4413         args [0] = &major;
4414         args [1] = &minor;
4415         args [2] = &build;
4416         args [3] = &revision;
4417         result = mono_object_new (domain, System_Version);
4418         mono_runtime_invoke (create_version, result, args, NULL);
4419
4420         return result;
4421 }
4422
4423 ICALL_EXPORT MonoArray*
4424 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly) 
4425 {
4426         static MonoClass *System_Reflection_AssemblyName;
4427         MonoArray *result;
4428         MonoDomain *domain = mono_object_domain (assembly);
4429         int i, count = 0;
4430         static MonoMethod *create_culture = NULL;
4431         MonoImage *image = assembly->assembly->image;
4432         MonoTableInfo *t;
4433
4434         MONO_ARCH_SAVE_REGS;
4435
4436         if (!System_Reflection_AssemblyName)
4437                 System_Reflection_AssemblyName = mono_class_from_name (
4438                         mono_defaults.corlib, "System.Reflection", "AssemblyName");
4439
4440         t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4441         count = t->rows;
4442
4443         result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4444
4445         if (count > 0 && !create_culture) {
4446                 MonoMethodDesc *desc = mono_method_desc_new (
4447                         "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4448                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4449                 g_assert (create_culture);
4450                 mono_method_desc_free (desc);
4451         }
4452
4453         for (i = 0; i < count; i++) {
4454                 MonoReflectionAssemblyName *aname;
4455                 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4456
4457                 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4458
4459                 aname = (MonoReflectionAssemblyName *) mono_object_new (
4460                         domain, System_Reflection_AssemblyName);
4461
4462                 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4463
4464                 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4465                 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4466                 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4467                 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4468                 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4469                 aname->versioncompat = 1; /* SameMachine (default) */
4470                 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4471                 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4472
4473                 if (create_culture) {
4474                         gpointer args [2];
4475                         MonoBoolean assembly_ref = 1;
4476                         args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4477                         args [1] = &assembly_ref;
4478                         MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4479                 }
4480                 
4481                 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4482                         const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4483                         guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4484
4485                         if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4486                                 /* public key token isn't copied - the class library will 
4487                                 automatically generate it from the public key if required */
4488                                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4489                                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4490                         } else {
4491                                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4492                                 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4493                         }
4494                 } else {
4495                         MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4496                 }
4497                 
4498                 /* note: this function doesn't return the codebase on purpose (i.e. it can
4499                          be used under partial trust as path information isn't present). */
4500
4501                 mono_array_setref (result, i, aname);
4502         }
4503         return result;
4504 }
4505
4506 /* move this in some file in mono/util/ */
4507 static char *
4508 g_concat_dir_and_file (const char *dir, const char *file)
4509 {
4510         g_return_val_if_fail (dir != NULL, NULL);
4511         g_return_val_if_fail (file != NULL, NULL);
4512
4513         /*
4514          * If the directory name doesn't have a / on the end, we need
4515          * to add one so we get a proper path to the file
4516          */
4517         if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4518                 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4519         else
4520                 return g_strconcat (dir, file, NULL);
4521 }
4522
4523 ICALL_EXPORT void *
4524 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module) 
4525 {
4526         char *n = mono_string_to_utf8 (name);
4527         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4528         guint32 i;
4529         guint32 cols [MONO_MANIFEST_SIZE];
4530         guint32 impl, file_idx;
4531         const char *val;
4532         MonoImage *module;
4533
4534         MONO_ARCH_SAVE_REGS;
4535
4536         for (i = 0; i < table->rows; ++i) {
4537                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4538                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4539                 if (strcmp (val, n) == 0)
4540                         break;
4541         }
4542         g_free (n);
4543         if (i == table->rows)
4544                 return NULL;
4545         /* FIXME */
4546         impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4547         if (impl) {
4548                 /*
4549                  * this code should only be called after obtaining the 
4550                  * ResourceInfo and handling the other cases.
4551                  */
4552                 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4553                 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4554
4555                 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4556                 if (!module)
4557                         return NULL;
4558         }
4559         else
4560                 module = assembly->assembly->image;
4561
4562         mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4563
4564         return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4565 }
4566
4567 ICALL_EXPORT gboolean
4568 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4569 {
4570         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4571         int i;
4572         guint32 cols [MONO_MANIFEST_SIZE];
4573         guint32 file_cols [MONO_FILE_SIZE];
4574         const char *val;
4575         char *n;
4576
4577         MONO_ARCH_SAVE_REGS;
4578
4579         n = mono_string_to_utf8 (name);
4580         for (i = 0; i < table->rows; ++i) {
4581                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4582                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4583                 if (strcmp (val, n) == 0)
4584                         break;
4585         }
4586         g_free (n);
4587         if (i == table->rows)
4588                 return FALSE;
4589
4590         if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4591                 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4592         }
4593         else {
4594                 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4595                 case MONO_IMPLEMENTATION_FILE:
4596                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4597                         table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4598                         mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4599                         val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4600                         MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4601                         if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4602                                 info->location = 0;
4603                         else
4604                                 info->location = RESOURCE_LOCATION_EMBEDDED;
4605                         break;
4606
4607                 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4608                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4609                         mono_assembly_load_reference (assembly->assembly->image, i - 1);
4610                         if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4611                                 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4612                                 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4613                                 g_free (msg);
4614                                 mono_raise_exception (ex);
4615                         }
4616                         MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4617
4618                         /* Obtain info recursively */
4619                         ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4620                         info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4621                         break;
4622
4623                 case MONO_IMPLEMENTATION_EXP_TYPE:
4624                         g_assert_not_reached ();
4625                         break;
4626                 }
4627         }
4628
4629         return TRUE;
4630 }
4631
4632 ICALL_EXPORT MonoObject*
4633 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules) 
4634 {
4635         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4636         MonoArray *result = NULL;
4637         int i, count;
4638         const char *val;
4639         char *n;
4640
4641         MONO_ARCH_SAVE_REGS;
4642
4643         /* check hash if needed */
4644         if (name) {
4645                 n = mono_string_to_utf8 (name);
4646                 for (i = 0; i < table->rows; ++i) {
4647                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4648                         if (strcmp (val, n) == 0) {
4649                                 MonoString *fn;
4650                                 g_free (n);
4651                                 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4652                                 fn = mono_string_new (mono_object_domain (assembly), n);
4653                                 g_free (n);
4654                                 return (MonoObject*)fn;
4655                         }
4656                 }
4657                 g_free (n);
4658                 return NULL;
4659         }
4660
4661         count = 0;
4662         for (i = 0; i < table->rows; ++i) {
4663                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4664                         count ++;
4665         }
4666
4667         result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4668
4669         count = 0;
4670         for (i = 0; i < table->rows; ++i) {
4671                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4672                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4673                         n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4674                         mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4675                         g_free (n);
4676                         count ++;
4677                 }
4678         }
4679         return (MonoObject*)result;
4680 }
4681
4682 ICALL_EXPORT MonoArray*
4683 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4684 {
4685         MonoDomain *domain = mono_domain_get();
4686         MonoArray *res;
4687         MonoClass *klass;
4688         int i, j, file_count = 0;
4689         MonoImage **modules;
4690         guint32 module_count, real_module_count;
4691         MonoTableInfo *table;
4692         guint32 cols [MONO_FILE_SIZE];
4693         MonoImage *image = assembly->assembly->image;
4694
4695         g_assert (image != NULL);
4696         g_assert (!assembly->assembly->dynamic);
4697
4698         table = &image->tables [MONO_TABLE_FILE];
4699         file_count = table->rows;
4700
4701         modules = image->modules;
4702         module_count = image->module_count;
4703
4704         real_module_count = 0;
4705         for (i = 0; i < module_count; ++i)
4706                 if (modules [i])
4707                         real_module_count ++;
4708
4709         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4710         res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4711
4712         mono_array_setref (res, 0, mono_module_get_object (domain, image));
4713         j = 1;
4714         for (i = 0; i < module_count; ++i)
4715                 if (modules [i]) {
4716                         mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4717                         ++j;
4718                 }
4719
4720         for (i = 0; i < file_count; ++i, ++j) {
4721                 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4722                 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4723                         mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4724                 else {
4725                         MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4726                         if (!m) {
4727                                 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4728                                 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4729                         }
4730                         mono_array_setref (res, j, mono_module_get_object (domain, m));
4731                 }
4732         }
4733
4734         return res;
4735 }
4736
4737 ICALL_EXPORT MonoReflectionMethod*
4738 ves_icall_GetCurrentMethod (void) 
4739 {
4740         MonoMethod *m = mono_method_get_last_managed ();
4741
4742         while (m->is_inflated)
4743                 m = ((MonoMethodInflated*)m)->declaring;
4744
4745         return mono_method_get_object (mono_domain_get (), m, NULL);
4746 }
4747
4748
4749 static MonoMethod*
4750 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4751 {
4752         int offset = -1, i;
4753         if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4754                 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4755                 //method is inflated, we should inflate it on the other class
4756                 MonoGenericContext ctx;
4757                 ctx.method_inst = inflated->context.method_inst;
4758                 ctx.class_inst = inflated->context.class_inst;
4759                 if (klass->generic_class)
4760                         ctx.class_inst = klass->generic_class->context.class_inst;
4761                 else if (klass->generic_container)
4762                         ctx.class_inst = klass->generic_container->context.class_inst;
4763                 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4764         }
4765
4766         mono_class_setup_methods (method->klass);
4767         if (method->klass->exception_type)
4768                 return NULL;
4769         for (i = 0; i < method->klass->method.count; ++i) {
4770                 if (method->klass->methods [i] == method) {
4771                         offset = i;
4772                         break;
4773                 }       
4774         }
4775         mono_class_setup_methods (klass);
4776         if (klass->exception_type)
4777                 return NULL;
4778         g_assert (offset >= 0 && offset < klass->method.count);
4779         return klass->methods [offset];
4780 }
4781
4782 ICALL_EXPORT MonoReflectionMethod*
4783 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4784 {
4785         MonoClass *klass;
4786         if (type) {
4787                 klass = mono_class_from_mono_type (type);
4788                 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass)) 
4789                         return NULL;
4790                 if (method->klass != klass) {
4791                         method = mono_method_get_equivalent_method (method, klass);
4792                         if (!method)
4793                                 return NULL;
4794                 }
4795         } else
4796                 klass = method->klass;
4797         return mono_method_get_object (mono_domain_get (), method, klass);
4798 }
4799
4800 ICALL_EXPORT MonoReflectionMethod*
4801 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4802 {
4803         return mono_method_get_object (mono_domain_get (), method, NULL);
4804 }
4805
4806 ICALL_EXPORT MonoReflectionMethodBody*
4807 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4808 {
4809         return mono_method_body_get_object (mono_domain_get (), method);
4810 }
4811
4812 ICALL_EXPORT MonoReflectionAssembly*
4813 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4814 {
4815         MonoMethod *dest = NULL;
4816
4817         MONO_ARCH_SAVE_REGS;
4818
4819         mono_stack_walk_no_il (get_executing, &dest);
4820         g_assert (dest);
4821         return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4822 }
4823
4824
4825 ICALL_EXPORT MonoReflectionAssembly*
4826 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4827 {
4828         MonoDomain* domain = mono_domain_get ();
4829
4830         MONO_ARCH_SAVE_REGS;
4831
4832         if (!domain->entry_assembly)
4833                 return NULL;
4834
4835         return mono_assembly_get_object (domain, domain->entry_assembly);
4836 }
4837
4838 ICALL_EXPORT MonoReflectionAssembly*
4839 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4840 {
4841         MonoMethod *m;
4842         MonoMethod *dest;
4843
4844         MONO_ARCH_SAVE_REGS;
4845
4846         dest = NULL;
4847         mono_stack_walk_no_il (get_executing, &dest);
4848         m = dest;
4849         mono_stack_walk_no_il (get_caller, &dest);
4850         if (!dest)
4851                 dest = m;
4852         return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4853 }
4854
4855 ICALL_EXPORT MonoString *
4856 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4857                                        gboolean assembly_qualified)
4858 {
4859         MonoDomain *domain = mono_object_domain (object); 
4860         MonoTypeNameFormat format;
4861         MonoString *res;
4862         gchar *name;
4863
4864         if (full_name)
4865                 format = assembly_qualified ?
4866                         MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4867                         MONO_TYPE_NAME_FORMAT_FULL_NAME;
4868         else
4869                 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4870  
4871         name = mono_type_get_name_full (object->type, format);
4872         if (!name)
4873                 return NULL;
4874
4875         if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4876                 g_free (name);
4877                 return NULL;
4878         }
4879
4880         res = mono_string_new (domain, name);
4881         g_free (name);
4882
4883         return res;
4884 }
4885
4886 ICALL_EXPORT int
4887 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4888 {
4889         MonoClass *klass = mono_class_from_mono_type (this->type);
4890         mono_class_init_or_throw (klass);
4891         return mono_security_core_clr_class_level (klass);
4892 }
4893
4894 static void
4895 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4896 {
4897         static MonoMethod *create_culture = NULL;
4898         gpointer args [2];
4899         guint32 pkey_len;
4900         const char *pkey_ptr;
4901         gchar *codebase;
4902         MonoBoolean assembly_ref = 0;
4903
4904         MONO_ARCH_SAVE_REGS;
4905
4906         MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4907         aname->major = name->major;
4908         aname->minor = name->minor;
4909         aname->build = name->build;
4910         aname->flags = name->flags;
4911         aname->revision = name->revision;
4912         aname->hashalg = name->hash_alg;
4913         aname->versioncompat = 1; /* SameMachine (default) */
4914         aname->processor_architecture = name->arch;
4915
4916         if (by_default_version)
4917                 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4918
4919         codebase = NULL;
4920         if (absolute != NULL && *absolute != '\0') {
4921                 const gchar *prepend = "file://";
4922                 gchar *result;
4923
4924                 codebase = g_strdup (absolute);
4925
4926 #if HOST_WIN32
4927                 {
4928                         gint i;
4929                         for (i = strlen (codebase) - 1; i >= 0; i--)
4930                                 if (codebase [i] == '\\')
4931                                         codebase [i] = '/';
4932
4933                         if (*codebase == '/' && *(codebase + 1) == '/') {
4934                                 prepend = "file:";
4935                         } else {
4936                                 prepend = "file:///";
4937                         }
4938                 }
4939 #endif
4940                 result = g_strconcat (prepend, codebase, NULL);
4941                 g_free (codebase);
4942                 codebase = result;
4943         }
4944
4945         if (codebase) {
4946                 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4947                 g_free (codebase);
4948         }
4949
4950         if (!create_culture) {
4951                 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4952                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4953                 g_assert (create_culture);
4954                 mono_method_desc_free (desc);
4955         }
4956
4957         if (name->culture) {
4958                 args [0] = mono_string_new (domain, name->culture);
4959                 args [1] = &assembly_ref;
4960                 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4961         }
4962
4963         if (name->public_key) {
4964                 pkey_ptr = (char*)name->public_key;
4965                 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4966
4967                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4968                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4969                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4970         } else if (default_publickey) {
4971                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4972                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4973         }
4974
4975         /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4976         if (name->public_key_token [0]) {
4977                 int i, j;
4978                 char *p;
4979
4980                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4981                 p = mono_array_addr (aname->keyToken, char, 0);
4982
4983                 for (i = 0, j = 0; i < 8; i++) {
4984                         *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4985                         *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4986                         p++;
4987                 }
4988         } else if (default_token) {
4989                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4990         }
4991 }
4992
4993 ICALL_EXPORT MonoString *
4994 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
4995 {
4996         MonoDomain *domain = mono_object_domain (assembly); 
4997         MonoAssembly *mass = assembly->assembly;
4998         MonoString *res;
4999         gchar *name;
5000
5001         name = mono_stringify_assembly_name (&mass->aname);
5002         res = mono_string_new (domain, name);
5003         g_free (name);
5004
5005         return res;
5006 }
5007
5008 ICALL_EXPORT void
5009 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5010 {
5011         gchar *absolute;
5012         MonoAssembly *mass = assembly->assembly;
5013
5014         MONO_ARCH_SAVE_REGS;
5015
5016         if (g_path_is_absolute (mass->image->name)) {
5017                 fill_reflection_assembly_name (mono_object_domain (assembly),
5018                         aname, &mass->aname, mass->image->name, TRUE,
5019                         TRUE, TRUE);
5020                 return;
5021         }
5022         absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5023
5024         fill_reflection_assembly_name (mono_object_domain (assembly),
5025                 aname, &mass->aname, absolute, TRUE, TRUE,
5026                 TRUE);
5027
5028         g_free (absolute);
5029 }
5030
5031 ICALL_EXPORT void
5032 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5033 {
5034         char *filename;
5035         MonoImageOpenStatus status = MONO_IMAGE_OK;
5036         gboolean res;
5037         MonoImage *image;
5038         MonoAssemblyName name;
5039         char *dirname
5040
5041         MONO_ARCH_SAVE_REGS;
5042
5043         filename = mono_string_to_utf8 (fname);
5044
5045         dirname = g_path_get_dirname (filename);
5046         replace_shadow_path (mono_domain_get (), dirname, &filename);
5047         g_free (dirname);
5048
5049         image = mono_image_open (filename, &status);
5050
5051         if (!image){
5052                 MonoException *exc;
5053
5054                 g_free (filename);
5055                 if (status == MONO_IMAGE_IMAGE_INVALID)
5056                         exc = mono_get_exception_bad_image_format2 (NULL, fname);
5057                 else
5058                         exc = mono_get_exception_file_not_found2 (NULL, fname);
5059                 mono_raise_exception (exc);
5060         }
5061
5062         res = mono_assembly_fill_assembly_name (image, &name);
5063         if (!res) {
5064                 mono_image_close (image);
5065                 g_free (filename);
5066                 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5067         }
5068
5069         fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5070                 TRUE, FALSE, TRUE);
5071
5072         g_free (filename);
5073         mono_image_close (image);
5074 }
5075
5076 ICALL_EXPORT MonoBoolean
5077 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5078         char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5079 {
5080         MonoBoolean result = FALSE;
5081         MonoDeclSecurityEntry entry;
5082
5083         /* SecurityAction.RequestMinimum */
5084         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5085                 *minimum = entry.blob;
5086                 *minLength = entry.size;
5087                 result = TRUE;
5088         }
5089         /* SecurityAction.RequestOptional */
5090         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5091                 *optional = entry.blob;
5092                 *optLength = entry.size;
5093                 result = TRUE;
5094         }
5095         /* SecurityAction.RequestRefuse */
5096         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5097                 *refused = entry.blob;
5098                 *refLength = entry.size;
5099                 result = TRUE;
5100         }
5101
5102         return result;  
5103 }
5104
5105 static MonoArray*
5106 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5107 {
5108         MonoArray *res;
5109         MonoClass *klass;
5110         MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5111         int i, count;
5112         guint32 attrs, visibility;
5113
5114         /* we start the count from 1 because we skip the special type <Module> */
5115         if (exportedOnly) {
5116                 count = 0;
5117                 for (i = 1; i < tdef->rows; ++i) {
5118                         attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5119                         visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5120                         if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5121                                 count++;
5122                 }
5123         } else {
5124                 count = tdef->rows - 1;
5125         }
5126         res = mono_array_new (domain, mono_defaults.monotype_class, count);
5127         *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5128         count = 0;
5129         for (i = 1; i < tdef->rows; ++i) {
5130                 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5131                 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5132                 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5133                         klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5134                         if (klass) {
5135                                 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5136                         } else {
5137                                 MonoLoaderError *error;
5138                                 MonoException *ex;
5139                                 
5140                                 error = mono_loader_get_last_error ();
5141                                 g_assert (error != NULL);
5142         
5143                                 ex = mono_loader_error_prepare_exception (error);
5144                                 mono_array_setref (*exceptions, count, ex);
5145                         }
5146                         if (mono_loader_get_last_error ())
5147                                 mono_loader_clear_error ();
5148                         count++;
5149                 }
5150         }
5151         
5152         return res;
5153 }
5154
5155 ICALL_EXPORT MonoArray*
5156 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5157 {
5158         MonoArray *res = NULL;
5159         MonoArray *exceptions = NULL;
5160         MonoImage *image = NULL;
5161         MonoTableInfo *table = NULL;
5162         MonoDomain *domain;
5163         GList *list = NULL;
5164         int i, len, ex_count;
5165
5166         MONO_ARCH_SAVE_REGS;
5167
5168         domain = mono_object_domain (assembly);
5169
5170         g_assert (!assembly->assembly->dynamic);
5171         image = assembly->assembly->image;
5172         table = &image->tables [MONO_TABLE_FILE];
5173         res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5174
5175         /* Append data from all modules in the assembly */
5176         for (i = 0; i < table->rows; ++i) {
5177                 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5178                         MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5179                         if (loaded_image) {
5180                                 MonoArray *ex2;
5181                                 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5182                                 /* Append the new types to the end of the array */
5183                                 if (mono_array_length (res2) > 0) {
5184                                         guint32 len1, len2;
5185                                         MonoArray *res3, *ex3;
5186
5187                                         len1 = mono_array_length (res);
5188                                         len2 = mono_array_length (res2);
5189
5190                                         res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5191                                         mono_array_memcpy_refs (res3, 0, res, 0, len1);
5192                                         mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5193                                         res = res3;
5194
5195                                         ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5196                                         mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5197                                         mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5198                                         exceptions = ex3;
5199                                 }
5200                         }
5201                 }
5202         }
5203
5204         /* the ReflectionTypeLoadException must have all the types (Types property), 
5205          * NULL replacing types which throws an exception. The LoaderException must
5206          * contain all exceptions for NULL items.
5207          */
5208
5209         len = mono_array_length (res);
5210
5211         ex_count = 0;
5212         for (i = 0; i < len; i++) {
5213                 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5214                 MonoClass *klass;
5215
5216                 if (t) {
5217                         klass = mono_type_get_class (t->type);
5218                         if ((klass != NULL) && klass->exception_type) {
5219                                 /* keep the class in the list */
5220                                 list = g_list_append (list, klass);
5221                                 /* and replace Type with NULL */
5222                                 mono_array_setref (res, i, NULL);
5223                         }
5224                 } else {
5225                         ex_count ++;
5226                 }
5227         }
5228
5229         if (list || ex_count) {
5230                 GList *tmp = NULL;
5231                 MonoException *exc = NULL;
5232                 MonoArray *exl = NULL;
5233                 int j, length = g_list_length (list) + ex_count;
5234
5235                 mono_loader_clear_error ();
5236
5237                 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5238                 /* Types for which mono_class_get () succeeded */
5239                 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5240                         MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5241                         mono_array_setref (exl, i, exc);
5242                 }
5243                 /* Types for which it don't */
5244                 for (j = 0; j < mono_array_length (exceptions); ++j) {
5245                         MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5246                         if (exc) {
5247                                 g_assert (i < length);
5248                                 mono_array_setref (exl, i, exc);
5249                                 i ++;
5250                         }
5251                 }
5252                 g_list_free (list);
5253                 list = NULL;
5254
5255                 exc = mono_get_exception_reflection_type_load (res, exl);
5256                 mono_loader_clear_error ();
5257                 mono_raise_exception (exc);
5258         }
5259                 
5260         return res;
5261 }
5262
5263 ICALL_EXPORT gboolean
5264 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5265 {
5266         MonoAssemblyName aname;
5267         MonoDomain *domain = mono_object_domain (name);
5268         char *val;
5269         gboolean is_version_defined;
5270         gboolean is_token_defined;
5271
5272         aname.public_key = NULL;
5273         val = mono_string_to_utf8 (assname);
5274         if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5275                 g_free ((guint8*) aname.public_key);
5276                 g_free (val);
5277                 return FALSE;
5278         }
5279         
5280         fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5281                 FALSE, is_token_defined);
5282
5283         mono_assembly_name_free (&aname);
5284         g_free ((guint8*) aname.public_key);
5285         g_free (val);
5286
5287         return TRUE;
5288 }
5289
5290 ICALL_EXPORT MonoReflectionType*
5291 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5292 {
5293         MonoDomain *domain = mono_object_domain (module); 
5294         MonoClass *klass;
5295
5296         MONO_ARCH_SAVE_REGS;
5297
5298         g_assert (module->image);
5299
5300         if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5301                 /* These images do not have a global type */
5302                 return NULL;
5303
5304         klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5305         return mono_type_get_object (domain, &klass->byval_arg);
5306 }
5307
5308 ICALL_EXPORT void
5309 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5310 {
5311         /*if (module->image)
5312                 mono_image_close (module->image);*/
5313 }
5314
5315 ICALL_EXPORT MonoString*
5316 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5317 {
5318         MonoDomain *domain = mono_object_domain (module); 
5319
5320         MONO_ARCH_SAVE_REGS;
5321
5322         g_assert (module->image);
5323         return mono_string_new (domain, module->image->guid);
5324 }
5325
5326 ICALL_EXPORT gpointer
5327 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5328 {
5329 #ifdef HOST_WIN32
5330         if (module->image && module->image->is_module_handle)
5331                 return module->image->raw_data;
5332 #endif
5333
5334         return (gpointer) (-1);
5335 }
5336
5337 ICALL_EXPORT void
5338 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5339 {
5340         if (image->dynamic) {
5341                 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5342                 *pe_kind = dyn->pe_kind;
5343                 *machine = dyn->machine;
5344         }
5345         else {
5346                 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5347                 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5348         }
5349 }
5350
5351 ICALL_EXPORT gint32
5352 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5353 {
5354         return (image->md_version_major << 16) | (image->md_version_minor);
5355 }
5356
5357 ICALL_EXPORT MonoArray*
5358 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5359 {
5360         MonoArray *exceptions;
5361         int i;
5362
5363         MONO_ARCH_SAVE_REGS;
5364
5365         if (!module->image)
5366                 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5367         else {
5368                 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5369                 for (i = 0; i < mono_array_length (exceptions); ++i) {
5370                         MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5371                         if (ex)
5372                                 mono_raise_exception (ex);
5373                 }
5374                 return res;
5375         }
5376 }
5377
5378 static gboolean
5379 mono_memberref_is_method (MonoImage *image, guint32 token)
5380 {
5381         if (!image->dynamic) {
5382                 guint32 cols [MONO_MEMBERREF_SIZE];
5383                 const char *sig;
5384                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5385                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5386                 mono_metadata_decode_blob_size (sig, &sig);
5387                 return (*sig != 0x6);
5388         } else {
5389                 MonoClass *handle_class;
5390
5391                 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5392                         return FALSE;
5393
5394                 return mono_defaults.methodhandle_class == handle_class;
5395         }
5396 }
5397
5398 static void
5399 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5400 {
5401         if (type_args)
5402                 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5403                                                                       mono_array_addr (type_args, MonoType*, 0));
5404         else
5405                 context->class_inst = NULL;
5406         if (method_args)
5407                 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5408                                                                        mono_array_addr (method_args, MonoType*, 0));
5409         else
5410                 context->method_inst = NULL;
5411 }
5412
5413 ICALL_EXPORT MonoType*
5414 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5415 {
5416         MonoClass *klass;
5417         int table = mono_metadata_token_table (token);
5418         int index = mono_metadata_token_index (token);
5419         MonoGenericContext context;
5420
5421         *error = ResolveTokenError_Other;
5422
5423         /* Validate token */
5424         if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) && 
5425                 (table != MONO_TABLE_TYPESPEC)) {
5426                 *error = ResolveTokenError_BadTable;
5427                 return NULL;
5428         }
5429
5430         if (image->dynamic) {
5431                 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5432                         klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5433                         return klass ? &klass->byval_arg : NULL;
5434                 }
5435
5436                 init_generic_context_from_args (&context, type_args, method_args);
5437                 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5438                 return klass ? &klass->byval_arg : NULL;
5439         }
5440
5441         if ((index <= 0) || (index > image->tables [table].rows)) {
5442                 *error = ResolveTokenError_OutOfRange;
5443                 return NULL;
5444         }
5445
5446         init_generic_context_from_args (&context, type_args, method_args);
5447         klass = mono_class_get_full (image, token, &context);
5448
5449         if (mono_loader_get_last_error ())
5450                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5451
5452         if (klass)
5453                 return &klass->byval_arg;
5454         else
5455                 return NULL;
5456 }
5457
5458 ICALL_EXPORT MonoMethod*
5459 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5460 {
5461         int table = mono_metadata_token_table (token);
5462         int index = mono_metadata_token_index (token);
5463         MonoGenericContext context;
5464         MonoMethod *method;
5465
5466         *error = ResolveTokenError_Other;
5467
5468         /* Validate token */
5469         if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) && 
5470                 (table != MONO_TABLE_MEMBERREF)) {
5471                 *error = ResolveTokenError_BadTable;
5472                 return NULL;
5473         }
5474
5475         if (image->dynamic) {
5476                 if (table == MONO_TABLE_METHOD)
5477                         return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5478
5479                 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5480                         *error = ResolveTokenError_BadTable;
5481                         return NULL;
5482                 }
5483
5484                 init_generic_context_from_args (&context, type_args, method_args);
5485                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5486         }
5487
5488         if ((index <= 0) || (index > image->tables [table].rows)) {
5489                 *error = ResolveTokenError_OutOfRange;
5490                 return NULL;
5491         }
5492         if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5493                 *error = ResolveTokenError_BadTable;
5494                 return NULL;
5495         }
5496
5497         init_generic_context_from_args (&context, type_args, method_args);
5498         method = mono_get_method_full (image, token, NULL, &context);
5499
5500         if (mono_loader_get_last_error ())
5501                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5502
5503         return method;
5504 }
5505
5506 ICALL_EXPORT MonoString*
5507 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5508 {
5509         int index = mono_metadata_token_index (token);
5510
5511         *error = ResolveTokenError_Other;
5512
5513         /* Validate token */
5514         if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5515                 *error = ResolveTokenError_BadTable;
5516                 return NULL;
5517         }
5518
5519         if (image->dynamic)
5520                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5521
5522         if ((index <= 0) || (index >= image->heap_us.size)) {
5523                 *error = ResolveTokenError_OutOfRange;
5524                 return NULL;
5525         }
5526
5527         /* FIXME: What to do if the index points into the middle of a string ? */
5528
5529         return mono_ldstr (mono_domain_get (), image, index);
5530 }
5531
5532 ICALL_EXPORT MonoClassField*
5533 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5534 {
5535         MonoClass *klass;
5536         int table = mono_metadata_token_table (token);
5537         int index = mono_metadata_token_index (token);
5538         MonoGenericContext context;
5539         MonoClassField *field;
5540
5541         *error = ResolveTokenError_Other;
5542
5543         /* Validate token */
5544         if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5545                 *error = ResolveTokenError_BadTable;
5546                 return NULL;
5547         }
5548
5549         if (image->dynamic) {
5550                 if (table == MONO_TABLE_FIELD)
5551                         return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5552
5553                 if (mono_memberref_is_method (image, token)) {
5554                         *error = ResolveTokenError_BadTable;
5555                         return NULL;
5556                 }
5557
5558                 init_generic_context_from_args (&context, type_args, method_args);
5559                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5560         }
5561
5562         if ((index <= 0) || (index > image->tables [table].rows)) {
5563                 *error = ResolveTokenError_OutOfRange;
5564                 return NULL;
5565         }
5566         if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5567                 *error = ResolveTokenError_BadTable;
5568                 return NULL;
5569         }
5570
5571         init_generic_context_from_args (&context, type_args, method_args);
5572         field = mono_field_from_token (image, token, &klass, &context);
5573
5574         if (mono_loader_get_last_error ())
5575                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5576         
5577         return field;
5578 }
5579
5580
5581 ICALL_EXPORT MonoObject*
5582 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5583 {
5584         int table = mono_metadata_token_table (token);
5585
5586         *error = ResolveTokenError_Other;
5587
5588         switch (table) {
5589         case MONO_TABLE_TYPEDEF:
5590         case MONO_TABLE_TYPEREF:
5591         case MONO_TABLE_TYPESPEC: {
5592                 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5593                 if (t)
5594                         return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5595                 else
5596                         return NULL;
5597         }
5598         case MONO_TABLE_METHOD:
5599         case MONO_TABLE_METHODSPEC: {
5600                 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5601                 if (m)
5602                         return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5603                 else
5604                         return NULL;
5605         }               
5606         case MONO_TABLE_FIELD: {
5607                 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5608                 if (f)
5609                         return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5610                 else
5611                         return NULL;
5612         }
5613         case MONO_TABLE_MEMBERREF:
5614                 if (mono_memberref_is_method (image, token)) {
5615                         MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5616                         if (m)
5617                                 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5618                         else
5619                                 return NULL;
5620                 }
5621                 else {
5622                         MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5623                         if (f)
5624                                 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5625                         else
5626                                 return NULL;
5627                 }
5628                 break;
5629
5630         default:
5631                 *error = ResolveTokenError_BadTable;
5632         }
5633
5634         return NULL;
5635 }
5636
5637 ICALL_EXPORT MonoArray*
5638 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5639 {
5640         int table = mono_metadata_token_table (token);
5641         int idx = mono_metadata_token_index (token);
5642         MonoTableInfo *tables = image->tables;
5643         guint32 sig, len;
5644         const char *ptr;
5645         MonoArray *res;
5646
5647         *error = ResolveTokenError_OutOfRange;
5648
5649         /* FIXME: Support other tables ? */
5650         if (table != MONO_TABLE_STANDALONESIG)
5651                 return NULL;
5652
5653         if (image->dynamic)
5654                 return NULL;
5655
5656         if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5657                 return NULL;
5658
5659         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5660
5661         ptr = mono_metadata_blob_heap (image, sig);
5662         len = mono_metadata_decode_blob_size (ptr, &ptr);
5663
5664         res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5665         memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5666         return res;
5667 }
5668
5669 ICALL_EXPORT MonoReflectionType*
5670 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5671 {
5672         MonoClass *klass;
5673         int isbyref = 0, rank;
5674         char *str = mono_string_to_utf8 (smodifiers);
5675         char *p;
5676
5677         MONO_ARCH_SAVE_REGS;
5678
5679         klass = mono_class_from_mono_type (tb->type.type);
5680         p = str;
5681         /* logic taken from mono_reflection_parse_type(): keep in sync */
5682         while (*p) {
5683                 switch (*p) {
5684                 case '&':
5685                         if (isbyref) { /* only one level allowed by the spec */
5686                                 g_free (str);
5687                                 return NULL;
5688                         }
5689                         isbyref = 1;
5690                         p++;
5691                         g_free (str);
5692                         return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5693                         break;
5694                 case '*':
5695                         klass = mono_ptr_class_get (&klass->byval_arg);
5696                         mono_class_init (klass);
5697                         p++;
5698                         break;
5699                 case '[':
5700                         rank = 1;
5701                         p++;
5702                         while (*p) {
5703                                 if (*p == ']')
5704                                         break;
5705                                 if (*p == ',')
5706                                         rank++;
5707                                 else if (*p != '*') { /* '*' means unknown lower bound */
5708                                         g_free (str);
5709                                         return NULL;
5710                                 }
5711                                 ++p;
5712                         }
5713                         if (*p != ']') {
5714                                 g_free (str);
5715                                 return NULL;
5716                         }
5717                         p++;
5718                         klass = mono_array_class_get (klass, rank);
5719                         mono_class_init (klass);
5720                         break;
5721                 default:
5722                         break;
5723                 }
5724         }
5725         g_free (str);
5726         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5727 }
5728
5729 ICALL_EXPORT MonoBoolean
5730 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5731 {
5732         MonoType *type;
5733         MonoBoolean res;
5734
5735         MONO_ARCH_SAVE_REGS;
5736
5737         type = t->type;
5738         res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5739
5740         return res;
5741 }
5742
5743 static void
5744 check_for_invalid_type (MonoClass *klass)
5745 {
5746         char *name;
5747         MonoString *str;
5748         if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5749                 return;
5750
5751         name = mono_type_get_full_name (klass);
5752         str =  mono_string_new (mono_domain_get (), name);
5753         g_free (name);
5754         mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5755
5756 }
5757 ICALL_EXPORT MonoReflectionType *
5758 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5759 {
5760         MonoClass *klass, *aklass;
5761
5762         MONO_ARCH_SAVE_REGS;
5763
5764         klass = mono_class_from_mono_type (type->type);
5765         check_for_invalid_type (klass);
5766
5767         if (rank == 0) //single dimentional array
5768                 aklass = mono_array_class_get (klass, 1);
5769         else
5770                 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5771
5772         return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5773 }
5774
5775 ICALL_EXPORT MonoReflectionType *
5776 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5777 {
5778         MonoClass *klass;
5779
5780         MONO_ARCH_SAVE_REGS;
5781
5782         klass = mono_class_from_mono_type (type->type);
5783         mono_class_init_or_throw (klass);
5784         check_for_invalid_type (klass);
5785
5786         return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5787 }
5788
5789 ICALL_EXPORT MonoReflectionType *
5790 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5791 {
5792         MonoClass *klass, *pklass;
5793
5794         klass = mono_class_from_mono_type (type->type);
5795         mono_class_init_or_throw (klass);
5796         check_for_invalid_type (klass);
5797
5798         pklass = mono_ptr_class_get (type->type);
5799
5800         return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5801 }
5802
5803 ICALL_EXPORT MonoObject *
5804 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5805                                                    MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5806 {
5807         MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5808         MonoObject *delegate;
5809         gpointer func;
5810         MonoMethod *method = info->method;
5811
5812         MONO_ARCH_SAVE_REGS;
5813
5814         mono_class_init_or_throw (delegate_class);
5815
5816         mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5817
5818         if (mono_security_core_clr_enabled ()) {
5819                 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5820                         return NULL;
5821         }
5822
5823         delegate = mono_object_new (mono_object_domain (type), delegate_class);
5824
5825         if (method->dynamic) {
5826                 /* Creating a trampoline would leak memory */
5827                 func = mono_compile_method (method);
5828         } else {
5829                 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5830                         method = mono_object_get_virtual_method (target, method);
5831                 func = mono_create_ftnptr (mono_domain_get (),
5832                         mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5833         }
5834
5835         mono_delegate_ctor_with_method (delegate, target, func, method);
5836
5837         return delegate;
5838 }
5839
5840 ICALL_EXPORT void
5841 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5842 {
5843         /* Reset the invoke impl to the default one */
5844         this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5845 }
5846
5847 /*
5848  * Magic number to convert a time which is relative to
5849  * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5850  */
5851 #define EPOCH_ADJUST    ((guint64)62135596800LL)
5852
5853 /*
5854  * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5855  */
5856 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5857
5858 #ifdef HOST_WIN32
5859 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5860 static void
5861 convert_to_absolute_date(SYSTEMTIME *date)
5862 {
5863 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5864         static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5865         static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5866         /* from the calendar FAQ */
5867         int a = (14 - date->wMonth) / 12;
5868         int y = date->wYear - a;
5869         int m = date->wMonth + 12 * a - 2;
5870         int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5871
5872         /* d is now the day of the week for the first of the month (0 == Sunday) */
5873
5874         int day_of_week = date->wDayOfWeek;
5875
5876         /* set day_in_month to the first day in the month which falls on day_of_week */    
5877         int day_in_month = 1 + (day_of_week - d);
5878         if (day_in_month <= 0)
5879                 day_in_month += 7;
5880
5881         /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5882         date->wDay = day_in_month + (date->wDay - 1) * 7;
5883         if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5884                 date->wDay -= 7;
5885 }
5886 #endif
5887
5888 #ifndef HOST_WIN32
5889 /*
5890  * Return's the offset from GMT of a local time.
5891  * 
5892  *  tm is a local time
5893  *  t  is the same local time as seconds.
5894  */
5895 static int 
5896 gmt_offset(struct tm *tm, time_t t)
5897 {
5898 #if defined (HAVE_TM_GMTOFF)
5899         return tm->tm_gmtoff;
5900 #else
5901         struct tm g;
5902         time_t t2;
5903         g = *gmtime(&t);
5904         g.tm_isdst = tm->tm_isdst;
5905         t2 = mktime(&g);
5906         return (int)difftime(t, t2);
5907 #endif
5908 }
5909 #endif
5910 /*
5911  * This is heavily based on zdump.c from glibc 2.2.
5912  *
5913  *  * data[0]:  start of daylight saving time (in DateTime ticks).
5914  *  * data[1]:  end of daylight saving time (in DateTime ticks).
5915  *  * data[2]:  utcoffset (in TimeSpan ticks).
5916  *  * data[3]:  additional offset when daylight saving (in TimeSpan ticks).
5917  *  * name[0]:  name of this timezone when not daylight saving.
5918  *  * name[1]:  name of this timezone when daylight saving.
5919  *
5920  *  FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5921  *         the class library allows years between 1 and 9999.
5922  *
5923  *  Returns true on success and zero on failure.
5924  */
5925 ICALL_EXPORT guint32
5926 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5927 {
5928 #ifndef HOST_WIN32
5929         MonoDomain *domain = mono_domain_get ();
5930         struct tm start, tt;
5931         time_t t;
5932
5933         long int gmtoff, gmtoff_st, gmtoff_ds;
5934         int day, transitioned;
5935         char tzone [64];
5936
5937         gmtoff_st = gmtoff_ds = transitioned = 0;
5938
5939         MONO_ARCH_SAVE_REGS;
5940
5941         MONO_CHECK_ARG_NULL (data);
5942         MONO_CHECK_ARG_NULL (names);
5943
5944         mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5945         mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5946
5947         /* 
5948          * no info is better than crashing: we'll need our own tz data
5949          * to make this work properly, anyway. The range is probably
5950          * reduced to 1970 .. 2037 because that is what mktime is
5951          * guaranteed to support (we get into an infinite loop
5952          * otherwise).
5953          */
5954
5955         memset (&start, 0, sizeof (start));
5956
5957         start.tm_mday = 1;
5958         start.tm_year = year-1900;
5959
5960         t = mktime (&start);
5961
5962         if ((year < 1970) || (year > 2037) || (t == -1)) {
5963                 t = time (NULL);
5964                 tt = *localtime (&t);
5965                 strftime (tzone, sizeof (tzone), "%Z", &tt);
5966                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5967                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5968                 return 1;
5969         }
5970
5971         gmtoff = gmt_offset (&start, t);
5972
5973         /* For each day of the year, calculate the tm_gmtoff. */
5974         for (day = 0; day < 365; day++) {
5975
5976                 t += 3600*24;
5977                 tt = *localtime (&t);
5978
5979         long int gmtoff_after = gmt_offset(&tt, t);
5980
5981                 /* Daylight saving starts or ends here. */
5982                 if (gmtoff_after != gmtoff) {
5983                         struct tm tt1;
5984                         time_t t1;
5985
5986                         /* Try to find the exact hour when daylight saving starts/ends. */
5987                         t1 = t;
5988                         do {
5989                                 t1 -= 3600;
5990                                 tt1 = *localtime (&t1);
5991                         } while (gmt_offset (&tt1, t1) != gmtoff);
5992
5993                         /* Try to find the exact minute when daylight saving starts/ends. */
5994                         do {
5995                                 t1 += 60;
5996                                 tt1 = *localtime (&t1);
5997                         } while (gmt_offset (&tt1, t1) == gmtoff);
5998                         t1+=gmtoff;
5999                         strftime (tzone, sizeof (tzone), "%Z", &tt);
6000                         
6001                         /* Write data, if we're already in daylight saving, we're done. */
6002                         if (tt.tm_isdst) {
6003                                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6004                                 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6005                                 if (gmtoff_ds == 0) {
6006                                         gmtoff_st = gmtoff;
6007                                         gmtoff_ds = gmtoff_after;
6008                                 }
6009                                 transitioned++;
6010                         } else {
6011                                 time_t te;
6012                                 te = mktime (&tt);
6013                                 
6014                                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6015                                 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6016                                 if (gmtoff_ds == 0) {
6017                                         gmtoff_st = gmtoff_after;
6018                                         gmtoff_ds = gmtoff;
6019                                 }
6020                                 transitioned++;
6021                         }
6022
6023                         /* This is only set once when we enter daylight saving. */
6024                         if (tt1.tm_isdst) {
6025                                 mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
6026                                 mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
6027                         }
6028                         gmtoff = gmt_offset (&tt, t);
6029                 }
6030         }
6031
6032         if (transitioned < 2) {
6033                 strftime (tzone, sizeof (tzone), "%Z", &tt);
6034                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6035                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6036                 mono_array_set ((*data), gint64, 0, 0);
6037                 mono_array_set ((*data), gint64, 1, 0);
6038                 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6039                 mono_array_set ((*data), gint64, 3, 0);
6040         }
6041
6042         return 1;
6043 #else
6044         MonoDomain *domain = mono_domain_get ();
6045         TIME_ZONE_INFORMATION tz_info;
6046         FILETIME ft;
6047         int i;
6048         int err, tz_id;
6049
6050         tz_id = GetTimeZoneInformation (&tz_info);
6051         if (tz_id == TIME_ZONE_ID_INVALID)
6052                 return 0;
6053
6054         MONO_CHECK_ARG_NULL (data);
6055         MONO_CHECK_ARG_NULL (names);
6056
6057         mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6058         mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6059
6060         for (i = 0; i < 32; ++i)
6061                 if (!tz_info.DaylightName [i])
6062                         break;
6063         mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6064         for (i = 0; i < 32; ++i)
6065                 if (!tz_info.StandardName [i])
6066                         break;
6067         mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6068
6069         if ((year <= 1601) || (year > 30827)) {
6070                 /*
6071                  * According to MSDN, the MS time functions can't handle dates outside
6072                  * this interval.
6073                  */
6074                 return 1;
6075         }
6076
6077         /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6078         if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6079                 tz_info.StandardDate.wYear = year;
6080                 convert_to_absolute_date(&tz_info.StandardDate);
6081                 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6082                 //g_assert(err);
6083                 if (err == 0)
6084                         return 0;
6085                 
6086                 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6087                 tz_info.DaylightDate.wYear = year;
6088                 convert_to_absolute_date(&tz_info.DaylightDate);
6089                 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6090                 //g_assert(err);
6091                 if (err == 0)
6092                         return 0;
6093                 
6094                 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6095         }
6096         mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6097         mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6098
6099         return 1;
6100 #endif
6101 }
6102
6103 ICALL_EXPORT gpointer
6104 ves_icall_System_Object_obj_address (MonoObject *this) 
6105 {
6106         MONO_ARCH_SAVE_REGS;
6107
6108         return this;
6109 }
6110
6111 /* System.Buffer */
6112
6113 static inline gint32 
6114 mono_array_get_byte_length (MonoArray *array)
6115 {
6116         MonoClass *klass;
6117         int length;
6118         int i;
6119
6120         klass = array->obj.vtable->klass;
6121
6122         if (array->bounds == NULL)
6123                 length = array->max_length;
6124         else {
6125                 length = 1;
6126                 for (i = 0; i < klass->rank; ++ i)
6127                         length *= array->bounds [i].length;
6128         }
6129
6130         switch (klass->element_class->byval_arg.type) {
6131         case MONO_TYPE_I1:
6132         case MONO_TYPE_U1:
6133         case MONO_TYPE_BOOLEAN:
6134                 return length;
6135         case MONO_TYPE_I2:
6136         case MONO_TYPE_U2:
6137         case MONO_TYPE_CHAR:
6138                 return length << 1;
6139         case MONO_TYPE_I4:
6140         case MONO_TYPE_U4:
6141         case MONO_TYPE_R4:
6142                 return length << 2;
6143         case MONO_TYPE_I:
6144         case MONO_TYPE_U:
6145                 return length * sizeof (gpointer);
6146         case MONO_TYPE_I8:
6147         case MONO_TYPE_U8:
6148         case MONO_TYPE_R8:
6149                 return length << 3;
6150         default:
6151                 return -1;
6152         }
6153 }
6154
6155 ICALL_EXPORT gint32 
6156 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array) 
6157 {
6158         MONO_ARCH_SAVE_REGS;
6159
6160         return mono_array_get_byte_length (array);
6161 }
6162
6163 ICALL_EXPORT gint8 
6164 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx) 
6165 {
6166         MONO_ARCH_SAVE_REGS;
6167
6168         return mono_array_get (array, gint8, idx);
6169 }
6170
6171 ICALL_EXPORT void 
6172 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value) 
6173 {
6174         MONO_ARCH_SAVE_REGS;
6175
6176         mono_array_set (array, gint8, idx, value);
6177 }
6178
6179 ICALL_EXPORT MonoBoolean
6180 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count) 
6181 {
6182         guint8 *src_buf, *dest_buf;
6183
6184         MONO_ARCH_SAVE_REGS;
6185
6186         /* This is called directly from the class libraries without going through the managed wrapper */
6187         MONO_CHECK_ARG_NULL (src);
6188         MONO_CHECK_ARG_NULL (dest);
6189
6190         /* watch out for integer overflow */
6191         if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6192                 return FALSE;
6193
6194         src_buf = (guint8 *)src->vector + src_offset;
6195         dest_buf = (guint8 *)dest->vector + dest_offset;
6196
6197         if (src != dest)
6198                 memcpy (dest_buf, src_buf, count);
6199         else
6200                 mono_gc_memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6201
6202         return TRUE;
6203 }
6204
6205 #ifndef DISABLE_REMOTING
6206 ICALL_EXPORT MonoObject *
6207 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6208 {
6209         MonoDomain *domain = mono_object_domain (this); 
6210         MonoObject *res;
6211         MonoRealProxy *rp = ((MonoRealProxy *)this);
6212         MonoTransparentProxy *tp;
6213         MonoType *type;
6214         MonoClass *klass;
6215
6216         MONO_ARCH_SAVE_REGS;
6217
6218         res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6219         tp = (MonoTransparentProxy*) res;
6220         
6221         MONO_OBJECT_SETREF (tp, rp, rp);
6222         type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6223         klass = mono_class_from_mono_type (type);
6224
6225         tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6226         tp->remote_class = mono_remote_class (domain, class_name, klass);
6227
6228         res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6229         return res;
6230 }
6231
6232 ICALL_EXPORT MonoReflectionType *
6233 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6234 {
6235         return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6236 }
6237 #endif
6238
6239 /* System.Environment */
6240
6241 MonoString*
6242 ves_icall_System_Environment_get_UserName (void)
6243 {
6244         MONO_ARCH_SAVE_REGS;
6245
6246         /* using glib is more portable */
6247         return mono_string_new (mono_domain_get (), g_get_user_name ());
6248 }
6249
6250
6251 ICALL_EXPORT MonoString *
6252 ves_icall_System_Environment_get_MachineName (void)
6253 {
6254 #if defined (HOST_WIN32)
6255         gunichar2 *buf;
6256         guint32 len;
6257         MonoString *result;
6258
6259         len = MAX_COMPUTERNAME_LENGTH + 1;
6260         buf = g_new (gunichar2, len);
6261
6262         result = NULL;
6263         if (GetComputerName (buf, (PDWORD) &len))
6264                 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6265
6266         g_free (buf);
6267         return result;
6268 #elif !defined(DISABLE_SOCKETS)
6269         gchar buf [256];
6270         MonoString *result;
6271
6272         if (gethostname (buf, sizeof (buf)) == 0)
6273                 result = mono_string_new (mono_domain_get (), buf);
6274         else
6275                 result = NULL;
6276         
6277         return result;
6278 #else
6279         return mono_string_new (mono_domain_get (), "mono");
6280 #endif
6281 }
6282
6283 ICALL_EXPORT int
6284 ves_icall_System_Environment_get_Platform (void)
6285 {
6286 #if defined (TARGET_WIN32)
6287         /* Win32NT */
6288         return 2;
6289 #elif defined(__MACH__)
6290         /* OSX */
6291         //
6292         // Notice that the value is hidden from user code, and only exposed
6293         // to mscorlib.   This is due to Mono's Unix/MacOS code predating the
6294         // define and making assumptions based on Unix/128/4 values before there
6295         // was a MacOS define.    Lots of code would assume that not-Unix meant
6296         // Windows, but in this case, it would be OSX. 
6297         //
6298         return 6;
6299 #else
6300         /* Unix */
6301         return 4;
6302 #endif
6303 }
6304
6305 ICALL_EXPORT MonoString *
6306 ves_icall_System_Environment_get_NewLine (void)
6307 {
6308         MONO_ARCH_SAVE_REGS;
6309
6310 #if defined (HOST_WIN32)
6311         return mono_string_new (mono_domain_get (), "\r\n");
6312 #else
6313         return mono_string_new (mono_domain_get (), "\n");
6314 #endif
6315 }
6316
6317 ICALL_EXPORT MonoString *
6318 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6319 {
6320         const gchar *value;
6321         gchar *utf8_name;
6322
6323         MONO_ARCH_SAVE_REGS;
6324
6325         if (name == NULL)
6326                 return NULL;
6327
6328         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6329         value = g_getenv (utf8_name);
6330
6331         g_free (utf8_name);
6332
6333         if (value == 0)
6334                 return NULL;
6335         
6336         return mono_string_new (mono_domain_get (), value);
6337 }
6338
6339 /*
6340  * There is no standard way to get at environ.
6341  */
6342 #ifndef _MSC_VER
6343 #ifndef __MINGW32_VERSION
6344 #if defined(__APPLE__) && !defined (__arm__)
6345 /* Apple defines this in crt_externs.h but doesn't provide that header for 
6346  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
6347  * in fact exist on all implementations (so far) 
6348  */
6349 gchar ***_NSGetEnviron(void);
6350 #define environ (*_NSGetEnviron())
6351 #else
6352 extern
6353 char **environ;
6354 #endif
6355 #endif
6356 #endif
6357
6358 ICALL_EXPORT MonoArray *
6359 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6360 {
6361 #ifdef HOST_WIN32
6362         MonoArray *names;
6363         MonoDomain *domain;
6364         MonoString *str;
6365         WCHAR* env_strings;
6366         WCHAR* env_string;
6367         WCHAR* equal_str;
6368         int n = 0;
6369
6370         env_strings = GetEnvironmentStrings();
6371
6372         if (env_strings) {
6373                 env_string = env_strings;
6374                 while (*env_string != '\0') {
6375                 /* weird case that MS seems to skip */
6376                         if (*env_string != '=')
6377                                 n++;
6378                         while (*env_string != '\0')
6379                                 env_string++;
6380                         env_string++;
6381                 }
6382         }
6383
6384         domain = mono_domain_get ();
6385         names = mono_array_new (domain, mono_defaults.string_class, n);
6386
6387         if (env_strings) {
6388                 n = 0;
6389                 env_string = env_strings;
6390                 while (*env_string != '\0') {
6391                         /* weird case that MS seems to skip */
6392                         if (*env_string != '=') {
6393                                 equal_str = wcschr(env_string, '=');
6394                                 g_assert(equal_str);
6395                                 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6396                                 mono_array_setref (names, n, str);
6397                                 n++;
6398                         }
6399                         while (*env_string != '\0')
6400                                 env_string++;
6401                         env_string++;
6402                 }
6403
6404                 FreeEnvironmentStrings (env_strings);
6405         }
6406
6407         return names;
6408
6409 #else
6410         MonoArray *names;
6411         MonoDomain *domain;
6412         MonoString *str;
6413         gchar **e, **parts;
6414         int n;
6415
6416         MONO_ARCH_SAVE_REGS;
6417
6418         n = 0;
6419         for (e = environ; *e != 0; ++ e)
6420                 ++ n;
6421
6422         domain = mono_domain_get ();
6423         names = mono_array_new (domain, mono_defaults.string_class, n);
6424
6425         n = 0;
6426         for (e = environ; *e != 0; ++ e) {
6427                 parts = g_strsplit (*e, "=", 2);
6428                 if (*parts != 0) {
6429                         str = mono_string_new (domain, *parts);
6430                         mono_array_setref (names, n, str);
6431                 }
6432
6433                 g_strfreev (parts);
6434
6435                 ++ n;
6436         }
6437
6438         return names;
6439 #endif
6440 }
6441
6442 /*
6443  * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6444  */
6445 #if !GLIB_CHECK_VERSION(2,4,0)
6446 #define g_setenv(a,b,c)   setenv(a,b,c)
6447 #define g_unsetenv(a) unsetenv(a)
6448 #endif
6449
6450 ICALL_EXPORT void
6451 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6452 {
6453         MonoError error;
6454 #ifdef HOST_WIN32
6455
6456         gunichar2 *utf16_name, *utf16_value;
6457 #else
6458         gchar *utf8_name, *utf8_value;
6459 #endif
6460
6461         MONO_ARCH_SAVE_REGS;
6462         
6463 #ifdef HOST_WIN32
6464         utf16_name = mono_string_to_utf16 (name);
6465         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6466                 SetEnvironmentVariable (utf16_name, NULL);
6467                 g_free (utf16_name);
6468                 return;
6469         }
6470
6471         utf16_value = mono_string_to_utf16 (value);
6472
6473         SetEnvironmentVariable (utf16_name, utf16_value);
6474
6475         g_free (utf16_name);
6476         g_free (utf16_value);
6477 #else
6478         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6479
6480         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6481                 g_unsetenv (utf8_name);
6482                 g_free (utf8_name);
6483                 return;
6484         }
6485
6486         utf8_value = mono_string_to_utf8_checked (value, &error);
6487         if (!mono_error_ok (&error)) {
6488                 g_free (utf8_name);
6489                 mono_error_raise_exception (&error);
6490         }
6491         g_setenv (utf8_name, utf8_value, TRUE);
6492
6493         g_free (utf8_name);
6494         g_free (utf8_value);
6495 #endif
6496 }
6497
6498 ICALL_EXPORT void
6499 ves_icall_System_Environment_Exit (int result)
6500 {
6501         MONO_ARCH_SAVE_REGS;
6502
6503 /* 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_debug_using_mono_debugger () || 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