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