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