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