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