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