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