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