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