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