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