Merge pull request #1398 from jwestfall69/dgv-first_row_index
[mono.git] / mono / metadata / icall.c
1 /*
2  * icall.c:
3  *
4  * Authors:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *   Paolo Molaro (lupus@ximian.com)
7  *       Patrik Torstensson (patrik.torstensson@labs2.com)
8  *   Marek Safar (marek.safar@gmail.com)
9  *
10  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
11  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12  * Copyright 2011-2014 Xamarin Inc (http://www.xamarin.com).
13  */
14
15 #include <config.h>
16 #include <glib.h>
17 #include <stdarg.h>
18 #include <string.h>
19 #include <ctype.h>
20 #ifdef HAVE_ALLOCA_H
21 #include <alloca.h>
22 #endif
23 #ifdef HAVE_SYS_TIME_H
24 #include <sys/time.h>
25 #endif
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29 #if defined (HOST_WIN32)
30 #include <stdlib.h>
31 #endif
32 #if defined (HAVE_WCHAR_H)
33 #include <wchar.h>
34 #endif
35
36 #include "mono/utils/mono-membar.h"
37 #include <mono/metadata/object.h>
38 #include <mono/metadata/threads.h>
39 #include <mono/metadata/threads-types.h>
40 #include <mono/metadata/threadpool.h>
41 #include <mono/metadata/monitor.h>
42 #include <mono/metadata/reflection.h>
43 #include <mono/metadata/assembly.h>
44 #include <mono/metadata/tabledefs.h>
45 #include <mono/metadata/exception.h>
46 #include <mono/metadata/file-io.h>
47 #include <mono/metadata/console-io.h>
48 #include <mono/metadata/socket-io.h>
49 #include <mono/metadata/mono-endian.h>
50 #include <mono/metadata/tokentype.h>
51 #include <mono/metadata/domain-internals.h>
52 #include <mono/metadata/metadata-internals.h>
53 #include <mono/metadata/class-internals.h>
54 #include <mono/metadata/marshal.h>
55 #include <mono/metadata/gc-internal.h>
56 #include <mono/metadata/mono-gc.h>
57 #include <mono/metadata/rand.h>
58 #include <mono/metadata/sysmath.h>
59 #include <mono/metadata/string-icalls.h>
60 #include <mono/metadata/debug-helpers.h>
61 #include <mono/metadata/process.h>
62 #include <mono/metadata/environment.h>
63 #include <mono/metadata/profiler-private.h>
64 #include <mono/metadata/locales.h>
65 #include <mono/metadata/filewatcher.h>
66 #include <mono/metadata/char-conversions.h>
67 #include <mono/metadata/security.h>
68 #include <mono/metadata/mono-config.h>
69 #include <mono/metadata/cil-coff.h>
70 #include <mono/metadata/number-formatter.h>
71 #include <mono/metadata/security-manager.h>
72 #include <mono/metadata/security-core-clr.h>
73 #include <mono/metadata/mono-perfcounters.h>
74 #include <mono/metadata/mono-debug.h>
75 #include <mono/metadata/mono-ptr-array.h>
76 #include <mono/metadata/verify-internals.h>
77 #include <mono/metadata/runtime.h>
78 #include <mono/metadata/file-mmap.h>
79 #include <mono/io-layer/io-layer.h>
80 #include <mono/utils/strtod.h>
81 #include <mono/utils/monobitset.h>
82 #include <mono/utils/mono-time.h>
83 #include <mono/utils/mono-proclib.h>
84 #include <mono/utils/mono-string.h>
85 #include <mono/utils/mono-error-internals.h>
86 #include <mono/utils/mono-mmap.h>
87 #include <mono/utils/mono-io-portability.h>
88 #include <mono/utils/mono-digest.h>
89 #include <mono/utils/bsearch.h>
90 #include <mono/utils/mono-mutex.h>
91 #include <mono/utils/mono-threads.h>
92
93 #if defined (HOST_WIN32)
94 #include <windows.h>
95 #include <shlobj.h>
96 #endif
97 #include "decimal.h"
98
99 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
100
101 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
102
103 static MonoArray*
104 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
105
106 static inline MonoBoolean
107 is_generic_parameter (MonoType *type)
108 {
109         return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
110 }
111
112 static void
113 mono_class_init_or_throw (MonoClass *klass)
114 {
115         if (!mono_class_init (klass))
116                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
117 }
118
119 /*
120  * We expect a pointer to a char, not a string
121  */
122 ICALL_EXPORT gboolean
123 mono_double_ParseImpl (char *ptr, double *result)
124 {
125         gchar *endptr = NULL;
126         *result = 0.0;
127
128         MONO_ARCH_SAVE_REGS;
129
130         if (*ptr){
131                 /* mono_strtod () is not thread-safe */
132                 mono_mutex_lock (&mono_strtod_mutex);
133                 *result = mono_strtod (ptr, &endptr);
134                 mono_mutex_unlock (&mono_strtod_mutex);
135         }
136
137         if (!*ptr || (endptr && *endptr))
138                 return FALSE;
139         
140         return TRUE;
141 }
142
143 ICALL_EXPORT MonoObject *
144 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
145 {
146         MonoClass *ac;
147         MonoArray *ao;
148         gint32 esize;
149         gpointer *ea;
150
151         MONO_ARCH_SAVE_REGS;
152
153         ao = (MonoArray *)this;
154         ac = (MonoClass *)ao->obj.vtable->klass;
155
156         esize = mono_array_element_size (ac);
157         ea = (gpointer*)((char*)ao->vector + (pos * esize));
158
159         if (ac->element_class->valuetype)
160                 return mono_value_box (this->vtable->domain, ac->element_class, ea);
161         else
162                 return *ea;
163 }
164
165 ICALL_EXPORT MonoObject *
166 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
167 {
168         MonoClass *ac, *ic;
169         MonoArray *ao, *io;
170         gint32 i, pos, *ind;
171
172         MONO_ARCH_SAVE_REGS;
173
174         MONO_CHECK_ARG_NULL (idxs);
175
176         io = (MonoArray *)idxs;
177         ic = (MonoClass *)io->obj.vtable->klass;
178         
179         ao = (MonoArray *)this;
180         ac = (MonoClass *)ao->obj.vtable->klass;
181
182         g_assert (ic->rank == 1);
183         if (io->bounds != NULL || io->max_length !=  ac->rank)
184                 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
185
186         ind = (gint32 *)io->vector;
187
188         if (ao->bounds == NULL) {
189                 if (*ind < 0 || *ind >= ao->max_length)
190                         mono_raise_exception (mono_get_exception_index_out_of_range ());
191
192                 return ves_icall_System_Array_GetValueImpl (this, *ind);
193         }
194         
195         for (i = 0; i < ac->rank; i++)
196                 if ((ind [i] < ao->bounds [i].lower_bound) ||
197                     (ind [i] >=  (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
198                         mono_raise_exception (mono_get_exception_index_out_of_range ());
199
200         pos = ind [0] - ao->bounds [0].lower_bound;
201         for (i = 1; i < ac->rank; i++)
202                 pos = pos*ao->bounds [i].length + ind [i] - 
203                         ao->bounds [i].lower_bound;
204
205         return ves_icall_System_Array_GetValueImpl (this, pos);
206 }
207
208 ICALL_EXPORT void
209 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
210 {
211         MonoClass *ac, *vc, *ec;
212         gint32 esize, vsize;
213         gpointer *ea, *va;
214         int et, vt;
215
216         guint64 u64 = 0;
217         gint64 i64 = 0;
218         gdouble r64 = 0;
219
220         MONO_ARCH_SAVE_REGS;
221
222         if (value)
223                 vc = value->vtable->klass;
224         else
225                 vc = NULL;
226
227         ac = this->obj.vtable->klass;
228         ec = ac->element_class;
229
230         esize = mono_array_element_size (ac);
231         ea = (gpointer*)((char*)this->vector + (pos * esize));
232         va = (gpointer*)((char*)value + sizeof (MonoObject));
233
234         if (mono_class_is_nullable (ec)) {
235                 mono_nullable_init ((guint8*)ea, value, ec);
236                 return;
237         }
238
239         if (!value) {
240                 mono_gc_bzero_atomic (ea, esize);
241                 return;
242         }
243
244 #define NO_WIDENING_CONVERSION G_STMT_START{\
245         mono_raise_exception (mono_get_exception_argument ( \
246                 "value", "not a widening conversion")); \
247 }G_STMT_END
248
249 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
250         if (esize < vsize + (extra)) \
251                 mono_raise_exception (mono_get_exception_argument ( \
252                         "value", "not a widening conversion")); \
253 }G_STMT_END
254
255 #define INVALID_CAST G_STMT_START{ \
256                 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
257         mono_raise_exception (mono_get_exception_invalid_cast ()); \
258 }G_STMT_END
259
260         /* Check element (destination) type. */
261         switch (ec->byval_arg.type) {
262         case MONO_TYPE_STRING:
263                 switch (vc->byval_arg.type) {
264                 case MONO_TYPE_STRING:
265                         break;
266                 default:
267                         INVALID_CAST;
268                 }
269                 break;
270         case MONO_TYPE_BOOLEAN:
271                 switch (vc->byval_arg.type) {
272                 case MONO_TYPE_BOOLEAN:
273                         break;
274                 case MONO_TYPE_CHAR:
275                 case MONO_TYPE_U1:
276                 case MONO_TYPE_U2:
277                 case MONO_TYPE_U4:
278                 case MONO_TYPE_U8:
279                 case MONO_TYPE_I1:
280                 case MONO_TYPE_I2:
281                 case MONO_TYPE_I4:
282                 case MONO_TYPE_I8:
283                 case MONO_TYPE_R4:
284                 case MONO_TYPE_R8:
285                         NO_WIDENING_CONVERSION;
286                 default:
287                         INVALID_CAST;
288                 }
289                 break;
290         }
291
292         if (!ec->valuetype) {
293                 if (!mono_object_isinst (value, ec))
294                         INVALID_CAST;
295                 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
296                 return;
297         }
298
299         if (mono_object_isinst (value, ec)) {
300                 if (ec->has_references)
301                         mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
302                 else
303                         mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
304                 return;
305         }
306
307         if (!vc->valuetype)
308                 INVALID_CAST;
309
310         vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
311
312         et = ec->byval_arg.type;
313         if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
314                 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
315
316         vt = vc->byval_arg.type;
317         if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
318                 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
319
320 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
321         switch (vt) { \
322         case MONO_TYPE_U1: \
323         case MONO_TYPE_U2: \
324         case MONO_TYPE_U4: \
325         case MONO_TYPE_U8: \
326         case MONO_TYPE_CHAR: \
327                 CHECK_WIDENING_CONVERSION(0); \
328                 *(etype *) ea = (etype) u64; \
329                 return; \
330         /* You can't assign a signed value to an unsigned array. */ \
331         case MONO_TYPE_I1: \
332         case MONO_TYPE_I2: \
333         case MONO_TYPE_I4: \
334         case MONO_TYPE_I8: \
335         /* You can't assign a floating point number to an integer array. */ \
336         case MONO_TYPE_R4: \
337         case MONO_TYPE_R8: \
338                 NO_WIDENING_CONVERSION; \
339         } \
340 }G_STMT_END
341
342 #define ASSIGN_SIGNED(etype) G_STMT_START{\
343         switch (vt) { \
344         case MONO_TYPE_I1: \
345         case MONO_TYPE_I2: \
346         case MONO_TYPE_I4: \
347         case MONO_TYPE_I8: \
348                 CHECK_WIDENING_CONVERSION(0); \
349                 *(etype *) ea = (etype) i64; \
350                 return; \
351         /* You can assign an unsigned value to a signed array if the array's */ \
352         /* element size is larger than the value size. */ \
353         case MONO_TYPE_U1: \
354         case MONO_TYPE_U2: \
355         case MONO_TYPE_U4: \
356         case MONO_TYPE_U8: \
357         case MONO_TYPE_CHAR: \
358                 CHECK_WIDENING_CONVERSION(1); \
359                 *(etype *) ea = (etype) u64; \
360                 return; \
361         /* You can't assign a floating point number to an integer array. */ \
362         case MONO_TYPE_R4: \
363         case MONO_TYPE_R8: \
364                 NO_WIDENING_CONVERSION; \
365         } \
366 }G_STMT_END
367
368 #define ASSIGN_REAL(etype) G_STMT_START{\
369         switch (vt) { \
370         case MONO_TYPE_R4: \
371         case MONO_TYPE_R8: \
372                 CHECK_WIDENING_CONVERSION(0); \
373                 *(etype *) ea = (etype) r64; \
374                 return; \
375         /* All integer values fit into a floating point array, so we don't */ \
376         /* need to CHECK_WIDENING_CONVERSION here. */ \
377         case MONO_TYPE_I1: \
378         case MONO_TYPE_I2: \
379         case MONO_TYPE_I4: \
380         case MONO_TYPE_I8: \
381                 *(etype *) ea = (etype) i64; \
382                 return; \
383         case MONO_TYPE_U1: \
384         case MONO_TYPE_U2: \
385         case MONO_TYPE_U4: \
386         case MONO_TYPE_U8: \
387         case MONO_TYPE_CHAR: \
388                 *(etype *) ea = (etype) u64; \
389                 return; \
390         } \
391 }G_STMT_END
392
393         switch (vt) {
394         case MONO_TYPE_U1:
395                 u64 = *(guint8 *) va;
396                 break;
397         case MONO_TYPE_U2:
398                 u64 = *(guint16 *) va;
399                 break;
400         case MONO_TYPE_U4:
401                 u64 = *(guint32 *) va;
402                 break;
403         case MONO_TYPE_U8:
404                 u64 = *(guint64 *) va;
405                 break;
406         case MONO_TYPE_I1:
407                 i64 = *(gint8 *) va;
408                 break;
409         case MONO_TYPE_I2:
410                 i64 = *(gint16 *) va;
411                 break;
412         case MONO_TYPE_I4:
413                 i64 = *(gint32 *) va;
414                 break;
415         case MONO_TYPE_I8:
416                 i64 = *(gint64 *) va;
417                 break;
418         case MONO_TYPE_R4:
419                 r64 = *(gfloat *) va;
420                 break;
421         case MONO_TYPE_R8:
422                 r64 = *(gdouble *) va;
423                 break;
424         case MONO_TYPE_CHAR:
425                 u64 = *(guint16 *) va;
426                 break;
427         case MONO_TYPE_BOOLEAN:
428                 /* Boolean is only compatible with itself. */
429                 switch (et) {
430                 case MONO_TYPE_CHAR:
431                 case MONO_TYPE_U1:
432                 case MONO_TYPE_U2:
433                 case MONO_TYPE_U4:
434                 case MONO_TYPE_U8:
435                 case MONO_TYPE_I1:
436                 case MONO_TYPE_I2:
437                 case MONO_TYPE_I4:
438                 case MONO_TYPE_I8:
439                 case MONO_TYPE_R4:
440                 case MONO_TYPE_R8:
441                         NO_WIDENING_CONVERSION;
442                 default:
443                         INVALID_CAST;
444                 }
445                 break;
446         }
447
448         /* If we can't do a direct copy, let's try a widening conversion. */
449         switch (et) {
450         case MONO_TYPE_CHAR:
451                 ASSIGN_UNSIGNED (guint16);
452         case MONO_TYPE_U1:
453                 ASSIGN_UNSIGNED (guint8);
454         case MONO_TYPE_U2:
455                 ASSIGN_UNSIGNED (guint16);
456         case MONO_TYPE_U4:
457                 ASSIGN_UNSIGNED (guint32);
458         case MONO_TYPE_U8:
459                 ASSIGN_UNSIGNED (guint64);
460         case MONO_TYPE_I1:
461                 ASSIGN_SIGNED (gint8);
462         case MONO_TYPE_I2:
463                 ASSIGN_SIGNED (gint16);
464         case MONO_TYPE_I4:
465                 ASSIGN_SIGNED (gint32);
466         case MONO_TYPE_I8:
467                 ASSIGN_SIGNED (gint64);
468         case MONO_TYPE_R4:
469                 ASSIGN_REAL (gfloat);
470         case MONO_TYPE_R8:
471                 ASSIGN_REAL (gdouble);
472         }
473
474         INVALID_CAST;
475         /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
476         return;
477
478 #undef INVALID_CAST
479 #undef NO_WIDENING_CONVERSION
480 #undef CHECK_WIDENING_CONVERSION
481 #undef ASSIGN_UNSIGNED
482 #undef ASSIGN_SIGNED
483 #undef ASSIGN_REAL
484 }
485
486 ICALL_EXPORT void 
487 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
488                                  MonoArray *idxs)
489 {
490         MonoClass *ac, *ic;
491         gint32 i, pos, *ind;
492
493         MONO_ARCH_SAVE_REGS;
494
495         MONO_CHECK_ARG_NULL (idxs);
496
497         ic = idxs->obj.vtable->klass;
498         ac = this->obj.vtable->klass;
499
500         g_assert (ic->rank == 1);
501         if (idxs->bounds != NULL || idxs->max_length != ac->rank)
502                 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
503
504         ind = (gint32 *)idxs->vector;
505
506         if (this->bounds == NULL) {
507                 if (*ind < 0 || *ind >= this->max_length)
508                         mono_raise_exception (mono_get_exception_index_out_of_range ());
509
510                 ves_icall_System_Array_SetValueImpl (this, value, *ind);
511                 return;
512         }
513         
514         for (i = 0; i < ac->rank; i++)
515                 if ((ind [i] < this->bounds [i].lower_bound) ||
516                     (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
517                         mono_raise_exception (mono_get_exception_index_out_of_range ());
518
519         pos = ind [0] - this->bounds [0].lower_bound;
520         for (i = 1; i < ac->rank; i++)
521                 pos = pos * this->bounds [i].length + ind [i] - 
522                         this->bounds [i].lower_bound;
523
524         ves_icall_System_Array_SetValueImpl (this, value, pos);
525 }
526
527 ICALL_EXPORT MonoArray *
528 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
529 {
530         MonoClass *aklass, *klass;
531         MonoArray *array;
532         uintptr_t *sizes, i;
533         gboolean bounded = FALSE;
534
535         MONO_ARCH_SAVE_REGS;
536
537         MONO_CHECK_ARG_NULL (type);
538         MONO_CHECK_ARG_NULL (lengths);
539
540         MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
541         if (bounds)
542                 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
543
544         for (i = 0; i < mono_array_length (lengths); i++)
545                 if (mono_array_get (lengths, gint32, i) < 0)
546                         mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
547
548         klass = mono_class_from_mono_type (type->type);
549         mono_class_init_or_throw (klass);
550
551         if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
552                 /* vectors are not the same as one dimensional arrays with no-zero bounds */
553                 bounded = TRUE;
554         else
555                 bounded = FALSE;
556
557         aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
558
559         sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
560         for (i = 0; i < aklass->rank; ++i) {
561                 sizes [i] = mono_array_get (lengths, guint32, i);
562                 if (bounds)
563                         sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
564                 else
565                         sizes [i + aklass->rank] = 0;
566         }
567
568         array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
569
570         return array;
571 }
572
573 ICALL_EXPORT MonoArray *
574 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
575 {
576         MonoClass *aklass, *klass;
577         MonoArray *array;
578         uintptr_t *sizes, i;
579         gboolean bounded = FALSE;
580
581         MONO_ARCH_SAVE_REGS;
582
583         MONO_CHECK_ARG_NULL (type);
584         MONO_CHECK_ARG_NULL (lengths);
585
586         MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
587         if (bounds)
588                 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
589
590         for (i = 0; i < mono_array_length (lengths); i++) 
591                 if ((mono_array_get (lengths, gint64, i) < 0) ||
592                     (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
593                         mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
594
595         klass = mono_class_from_mono_type (type->type);
596         mono_class_init_or_throw (klass);
597
598         if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
599                 /* vectors are not the same as one dimensional arrays with no-zero bounds */
600                 bounded = TRUE;
601         else
602                 bounded = FALSE;
603
604         aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
605
606         sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
607         for (i = 0; i < aklass->rank; ++i) {
608                 sizes [i] = mono_array_get (lengths, guint64, i);
609                 if (bounds)
610                         sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
611                 else
612                         sizes [i + aklass->rank] = 0;
613         }
614
615         array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
616
617         return array;
618 }
619
620 ICALL_EXPORT gint32 
621 ves_icall_System_Array_GetRank (MonoObject *this)
622 {
623         MONO_ARCH_SAVE_REGS;
624
625         return this->vtable->klass->rank;
626 }
627
628 ICALL_EXPORT gint32
629 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
630 {
631         gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
632         uintptr_t length;
633
634         MONO_ARCH_SAVE_REGS;
635
636         if ((dimension < 0) || (dimension >= rank))
637                 mono_raise_exception (mono_get_exception_index_out_of_range ());
638         
639         if (this->bounds == NULL)
640                 length = this->max_length;
641         else
642                 length = this->bounds [dimension].length;
643
644 #ifdef MONO_BIG_ARRAYS
645         if (length > G_MAXINT32)
646                 mono_raise_exception (mono_get_exception_overflow ());
647 #endif
648         return length;
649 }
650
651 ICALL_EXPORT gint64
652 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
653 {
654         gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
655
656         MONO_ARCH_SAVE_REGS;
657
658         if ((dimension < 0) || (dimension >= rank))
659                 mono_raise_exception (mono_get_exception_index_out_of_range ());
660         
661         if (this->bounds == NULL)
662                 return this->max_length;
663         
664         return this->bounds [dimension].length;
665 }
666
667 ICALL_EXPORT gint32
668 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
669 {
670         gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
671
672         MONO_ARCH_SAVE_REGS;
673
674         if ((dimension < 0) || (dimension >= rank))
675                 mono_raise_exception (mono_get_exception_index_out_of_range ());
676         
677         if (this->bounds == NULL)
678                 return 0;
679         
680         return this->bounds [dimension].lower_bound;
681 }
682
683 ICALL_EXPORT void
684 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
685 {
686         int sz = mono_array_element_size (mono_object_class (arr));
687         mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
688 }
689
690 ICALL_EXPORT gboolean
691 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
692 {
693         int element_size;
694         void * dest_addr;
695         void * source_addr;
696         MonoVTable *src_vtable;
697         MonoVTable *dest_vtable;
698         MonoClass *src_class;
699         MonoClass *dest_class;
700
701         src_vtable = source->obj.vtable;
702         dest_vtable = dest->obj.vtable;
703
704         if (src_vtable->rank != dest_vtable->rank)
705                 return FALSE;
706
707         if (source->bounds || dest->bounds)
708                 return FALSE;
709
710         /* there's no integer overflow since mono_array_length returns an unsigned integer */
711         if ((dest_idx + length > mono_array_length_fast (dest)) ||
712                 (source_idx + length > mono_array_length_fast (source)))
713                 return FALSE;
714
715         src_class = src_vtable->klass->element_class;
716         dest_class = dest_vtable->klass->element_class;
717
718         /*
719          * Handle common cases.
720          */
721
722         /* Case1: object[] -> valuetype[] (ArrayList::ToArray) 
723         We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
724         */
725         if (src_class == mono_defaults.object_class && dest_class->valuetype)
726                 return FALSE;
727
728         /* Check if we're copying a char[] <==> (u)short[] */
729         if (src_class != dest_class) {
730                 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
731                         return FALSE;
732
733                 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
734                 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
735                         return FALSE;
736         }
737
738         if (dest_class->valuetype) {
739                 element_size = mono_array_element_size (source->obj.vtable->klass);
740                 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
741                 if (dest_class->has_references) {
742                         mono_value_copy_array (dest, dest_idx, source_addr, length);
743                 } else {
744                         dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
745                         mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
746                 }
747         } else {
748                 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
749         }
750
751         return TRUE;
752 }
753
754 ICALL_EXPORT void
755 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
756 {
757         MonoClass *ac;
758         MonoArray *ao;
759         gint32 esize;
760         gpointer *ea;
761
762         MONO_ARCH_SAVE_REGS;
763
764         ao = (MonoArray *)this;
765         ac = (MonoClass *)ao->obj.vtable->klass;
766
767         esize = mono_array_element_size (ac);
768         ea = (gpointer*)((char*)ao->vector + (pos * esize));
769
770         mono_gc_memmove_atomic (value, ea, esize);
771 }
772
773 ICALL_EXPORT void
774 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
775 {
776         MonoClass *ac, *ec;
777         MonoArray *ao;
778         gint32 esize;
779         gpointer *ea;
780
781         MONO_ARCH_SAVE_REGS;
782
783         ao = (MonoArray *)this;
784         ac = (MonoClass *)ao->obj.vtable->klass;
785         ec = ac->element_class;
786
787         esize = mono_array_element_size (ac);
788         ea = (gpointer*)((char*)ao->vector + (pos * esize));
789
790         if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
791                 g_assert (esize == sizeof (gpointer));
792                 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
793         } else {
794                 g_assert (ec->inited);
795                 g_assert (esize == mono_class_value_size (ec, NULL));
796                 if (ec->has_references)
797                         mono_gc_wbarrier_value_copy (ea, value, 1, ec);
798                 else
799                         mono_gc_memmove_atomic (ea, value, esize);
800         }
801 }
802
803 ICALL_EXPORT void
804 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
805 {
806         MonoClass *klass = array->obj.vtable->klass;
807         guint32 size = mono_array_element_size (klass);
808         MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
809         int align;
810         const char *field_data;
811
812         if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
813                 MonoException *exc = mono_get_exception_argument("array",
814                         "Cannot initialize array of non-primitive type.");
815                 mono_raise_exception (exc);
816         }
817
818         if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
819                 MonoException *exc = mono_get_exception_argument("field_handle",
820                         "Field doesn't have an RVA");
821                 mono_raise_exception (exc);
822         }
823
824         size *= array->max_length;
825         field_data = mono_field_get_data (field_handle);
826
827         if (size > mono_type_size (field_handle->type, &align)) {
828                 MonoException *exc = mono_get_exception_argument("field_handle",
829                         "Field not large enough to fill array");
830                 mono_raise_exception (exc);
831         }
832
833 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
834 #define SWAP(n) {\
835         guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
836         guint ## n *src = (guint ## n *) field_data; \
837         guint ## n *end = (guint ## n *)((char*)src + size); \
838 \
839         for (; src < end; data++, src++) { \
840                 *data = read ## n (src); \
841         } \
842 }
843
844         /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
845
846         switch (type->type) {
847         case MONO_TYPE_CHAR:
848         case MONO_TYPE_I2:
849         case MONO_TYPE_U2:
850                 SWAP (16);
851                 break;
852         case MONO_TYPE_I4:
853         case MONO_TYPE_U4:
854         case MONO_TYPE_R4:
855                 SWAP (32);
856                 break;
857         case MONO_TYPE_I8:
858         case MONO_TYPE_U8:
859         case MONO_TYPE_R8:
860                 SWAP (64);
861                 break;
862         default:
863                 memcpy (mono_array_addr (array, char, 0), field_data, size);
864                 break;
865         }
866 #else
867         memcpy (mono_array_addr (array, char, 0), field_data, size);
868 #endif
869 }
870
871 ICALL_EXPORT gint
872 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
873 {
874         MONO_ARCH_SAVE_REGS;
875
876         return offsetof (MonoString, chars);
877 }
878
879 ICALL_EXPORT MonoObject *
880 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
881 {
882         MONO_ARCH_SAVE_REGS;
883
884         if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
885                 return obj;
886         else
887                 return mono_object_clone (obj);
888 }
889
890 ICALL_EXPORT void
891 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
892 {
893         MonoClass *klass;
894         MonoVTable *vtable;
895
896         MONO_CHECK_ARG_NULL (handle);
897
898         klass = mono_class_from_mono_type (handle);
899         MONO_CHECK_ARG (handle, klass);
900
901         vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
902
903         /* This will call the type constructor */
904         mono_runtime_class_init (vtable);
905 }
906
907 ICALL_EXPORT void
908 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
909 {
910         MonoError error;
911
912         mono_image_check_for_module_cctor (image);
913         if (image->has_module_cctor) {
914                 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
915                 mono_error_raise_exception (&error);
916                 /*It's fine to raise the exception here*/
917                 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
918         }
919 }
920
921 ICALL_EXPORT MonoBoolean
922 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
923 {
924         guint8 *stack_addr;
925         guint8 *current;
926         size_t stack_size;
927         /* later make this configurable and per-arch */
928         int min_size = 4096 * 4 * sizeof (void*);
929         mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
930         /* if we have no info we are optimistic and assume there is enough room */
931         if (!stack_addr)
932                 return TRUE;
933 #ifdef HOST_WIN32
934         // FIXME: Windows dynamically extends the stack, so stack_addr might be close
935         // to the current sp
936         return TRUE;
937 #endif
938         current = (guint8 *)&stack_addr;
939         if (current > stack_addr) {
940                 if ((current - stack_addr) < min_size)
941                         return FALSE;
942         } else {
943                 if (current - (stack_addr - stack_size) < min_size)
944                         return FALSE;
945         }
946         return TRUE;
947 }
948
949 ICALL_EXPORT MonoObject *
950 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
951 {
952         MONO_ARCH_SAVE_REGS;
953
954         return mono_object_clone (this);
955 }
956
957 ICALL_EXPORT gint32
958 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
959 {
960         MonoClass *klass;
961         MonoObject **values = NULL;
962         MonoObject *o;
963         int count = 0;
964         gint32 result = (int)(gsize)mono_defaults.int32_class;
965         MonoClassField* field;
966         gpointer iter;
967
968         MONO_ARCH_SAVE_REGS;
969
970         klass = mono_object_class (this);
971
972         if (mono_class_num_fields (klass) == 0)
973                 return result;
974
975         /*
976          * Compute the starting value of the hashcode for fields of primitive
977          * types, and return the remaining fields in an array to the managed side.
978          * This way, we can avoid costly reflection operations in managed code.
979          */
980         iter = NULL;
981         while ((field = mono_class_get_fields (klass, &iter))) {
982                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
983                         continue;
984                 if (mono_field_is_deleted (field))
985                         continue;
986                 /* FIXME: Add more types */
987                 switch (field->type->type) {
988                 case MONO_TYPE_I4:
989                         result ^= *(gint32*)((guint8*)this + field->offset);
990                         break;
991                 case MONO_TYPE_STRING: {
992                         MonoString *s;
993                         s = *(MonoString**)((guint8*)this + field->offset);
994                         if (s != NULL)
995                                 result ^= mono_string_hash (s);
996                         break;
997                 }
998                 default:
999                         if (!values)
1000                                 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1001                         o = mono_field_get_value_object (mono_object_domain (this), field, this);
1002                         values [count++] = o;
1003                 }
1004         }
1005
1006         if (values) {
1007                 int i;
1008                 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1009                 for (i = 0; i < count; ++i)
1010                         mono_array_setref (*fields, i, values [i]);
1011         } else {
1012                 *fields = NULL;
1013         }
1014         return result;
1015 }
1016
1017 ICALL_EXPORT MonoBoolean
1018 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1019 {
1020         MonoClass *klass;
1021         MonoObject **values = NULL;
1022         MonoObject *o;
1023         MonoClassField* field;
1024         gpointer iter;
1025         int count = 0;
1026
1027         MONO_ARCH_SAVE_REGS;
1028
1029         MONO_CHECK_ARG_NULL (that);
1030
1031         if (this->vtable != that->vtable)
1032                 return FALSE;
1033
1034         klass = mono_object_class (this);
1035
1036         if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1037                 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1038
1039         /*
1040          * Do the comparison for fields of primitive type and return a result if
1041          * possible. Otherwise, return the remaining fields in an array to the 
1042          * managed side. This way, we can avoid costly reflection operations in 
1043          * managed code.
1044          */
1045         *fields = NULL;
1046         iter = NULL;
1047         while ((field = mono_class_get_fields (klass, &iter))) {
1048                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1049                         continue;
1050                 if (mono_field_is_deleted (field))
1051                         continue;
1052                 /* FIXME: Add more types */
1053                 switch (field->type->type) {
1054                 case MONO_TYPE_U1:
1055                 case MONO_TYPE_I1:
1056                 case MONO_TYPE_BOOLEAN:
1057                         if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1058                                 return FALSE;
1059                         break;
1060                 case MONO_TYPE_U2:
1061                 case MONO_TYPE_I2:
1062                 case MONO_TYPE_CHAR:
1063                         if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1064                                 return FALSE;
1065                         break;
1066                 case MONO_TYPE_U4:
1067                 case MONO_TYPE_I4:
1068                         if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1069                                 return FALSE;
1070                         break;
1071                 case MONO_TYPE_U8:
1072                 case MONO_TYPE_I8:
1073                         if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1074                                 return FALSE;
1075                         break;
1076                 case MONO_TYPE_R4:
1077                         if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1078                                 return FALSE;
1079                         break;
1080                 case MONO_TYPE_R8:
1081                         if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1082                                 return FALSE;
1083                         break;
1084
1085
1086                 case MONO_TYPE_STRING: {
1087                         MonoString *s1, *s2;
1088                         guint32 s1len, s2len;
1089                         s1 = *(MonoString**)((guint8*)this + field->offset);
1090                         s2 = *(MonoString**)((guint8*)that + field->offset);
1091                         if (s1 == s2)
1092                                 break;
1093                         if ((s1 == NULL) || (s2 == NULL))
1094                                 return FALSE;
1095                         s1len = mono_string_length (s1);
1096                         s2len = mono_string_length (s2);
1097                         if (s1len != s2len)
1098                                 return FALSE;
1099
1100                         if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1101                                 return FALSE;
1102                         break;
1103                 }
1104                 default:
1105                         if (!values)
1106                                 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1107                         o = mono_field_get_value_object (mono_object_domain (this), field, this);
1108                         values [count++] = o;
1109                         o = mono_field_get_value_object (mono_object_domain (this), field, that);
1110                         values [count++] = o;
1111                 }
1112
1113                 if (klass->enumtype)
1114                         /* enums only have one non-static field */
1115                         break;
1116         }
1117
1118         if (values) {
1119                 int i;
1120                 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1121                 for (i = 0; i < count; ++i)
1122                         mono_array_setref_fast (*fields, i, values [i]);
1123                 return FALSE;
1124         } else {
1125                 return TRUE;
1126         }
1127 }
1128
1129 ICALL_EXPORT MonoReflectionType *
1130 ves_icall_System_Object_GetType (MonoObject *obj)
1131 {
1132         MONO_ARCH_SAVE_REGS;
1133
1134 #ifndef DISABLE_REMOTING
1135         if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1136                 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1137         else
1138 #endif
1139                 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1140 }
1141
1142 ICALL_EXPORT void
1143 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1144 {
1145         MONO_ARCH_SAVE_REGS;
1146
1147         mtype->type = &obj->vtable->klass->byval_arg;
1148         g_assert (mtype->type->type);
1149 }
1150
1151 ICALL_EXPORT gint32
1152 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1153 {
1154         MONO_ARCH_SAVE_REGS;
1155         
1156         MONO_CHECK_ARG_NULL (obj);
1157         
1158         return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1159 }
1160
1161 ICALL_EXPORT gint32
1162 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1163                                         MonoReflectionMethod *method,
1164                                         MonoArray *opt_param_types)
1165 {
1166         MONO_ARCH_SAVE_REGS;
1167
1168         MONO_CHECK_ARG_NULL (method);
1169         
1170         return mono_image_create_method_token (
1171                 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1172 }
1173
1174 ICALL_EXPORT void
1175 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1176 {
1177         MONO_ARCH_SAVE_REGS;
1178
1179         mono_image_create_pefile (mb, file);
1180 }
1181
1182 ICALL_EXPORT void
1183 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1184 {
1185         MONO_ARCH_SAVE_REGS;
1186
1187         mono_image_build_metadata (mb);
1188 }
1189
1190 ICALL_EXPORT void
1191 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1192 {
1193         MONO_ARCH_SAVE_REGS;
1194
1195         mono_image_register_token (mb->dynamic_image, token, obj);
1196 }
1197
1198 static gboolean
1199 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1200 {
1201         MonoMethod **dest = data;
1202
1203         /* skip unmanaged frames */
1204         if (!managed)
1205                 return FALSE;
1206
1207         if (m == *dest) {
1208                 *dest = NULL;
1209                 return FALSE;
1210         }
1211         if (!(*dest)) {
1212                 *dest = m;
1213                 return TRUE;
1214         }
1215         return FALSE;
1216 }
1217
1218 static gboolean
1219 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1220 {
1221         MonoMethod **dest = data;
1222
1223         /* skip unmanaged frames */
1224         if (!managed)
1225                 return FALSE;
1226
1227         if (!(*dest)) {
1228                 if (!strcmp (m->klass->name_space, "System.Reflection"))
1229                         return FALSE;
1230                 *dest = m;
1231                 return TRUE;
1232         }
1233         return FALSE;
1234 }
1235
1236 static gboolean
1237 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1238 {
1239         MonoMethod **dest = data;
1240
1241         /* skip unmanaged frames */
1242         if (!managed)
1243                 return FALSE;
1244
1245         if (m->wrapper_type != MONO_WRAPPER_NONE)
1246                 return FALSE;
1247
1248         if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1249                 return FALSE;
1250
1251         if (m == *dest) {
1252                 *dest = NULL;
1253                 return FALSE;
1254         }
1255         if (!(*dest)) {
1256                 *dest = m;
1257                 return TRUE;
1258         }
1259         return FALSE;
1260 }
1261
1262 static MonoReflectionType *
1263 type_from_name (const char *str, MonoBoolean ignoreCase)
1264 {
1265         MonoMethod *m, *dest;
1266
1267         MonoType *type = NULL;
1268         MonoAssembly *assembly = NULL;
1269         MonoTypeNameParse info;
1270         char *temp_str = g_strdup (str);
1271         gboolean type_resolve = FALSE;
1272
1273         MONO_ARCH_SAVE_REGS;
1274
1275         /* mono_reflection_parse_type() mangles the string */
1276         if (!mono_reflection_parse_type (temp_str, &info)) {
1277                 mono_reflection_free_type_info (&info);
1278                 g_free (temp_str);
1279                 return NULL;
1280         }
1281
1282
1283         /*
1284          * We must compute the calling assembly as type loading must happen under a metadata context.
1285          * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1286          * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1287          */
1288         m = mono_method_get_last_managed ();
1289         dest = m;
1290
1291         mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1292         if (!dest)
1293                 dest = m;
1294
1295         /*
1296          * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1297          *        causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1298          *        to crash.  This only seems to happen in some strange remoting
1299          *        scenarios and I was unable to figure out what's happening there.
1300          *        Dec 10, 2005 - Martin.
1301          */
1302
1303         if (dest) {
1304                 assembly = dest->klass->image->assembly;
1305                 type_resolve = TRUE;
1306         } else {
1307                 g_warning (G_STRLOC);
1308         }
1309
1310         if (info.assembly.name)
1311                 assembly = mono_assembly_load (&info.assembly, assembly ? assembly->basedir : NULL, NULL);
1312
1313
1314         if (assembly) {
1315                 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1316                 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1317         }
1318
1319         if (!info.assembly.name && !type) /* try mscorlib */
1320                 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1321
1322         if (assembly && !type && type_resolve) {
1323                 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1324                 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1325         }
1326
1327         mono_reflection_free_type_info (&info);
1328         g_free (temp_str);
1329
1330         if (!type) 
1331                 return NULL;
1332
1333         return mono_type_get_object (mono_domain_get (), type);
1334 }
1335
1336 #ifdef UNUSED
1337 MonoReflectionType *
1338 mono_type_get (const char *str)
1339 {
1340         char *copy = g_strdup (str);
1341         MonoReflectionType *type = type_from_name (copy, FALSE);
1342
1343         g_free (copy);
1344         return type;
1345 }
1346 #endif
1347
1348 ICALL_EXPORT MonoReflectionType*
1349 ves_icall_type_from_name (MonoString *name,
1350                           MonoBoolean throwOnError,
1351                           MonoBoolean ignoreCase)
1352 {
1353         char *str = mono_string_to_utf8 (name);
1354         MonoReflectionType *type;
1355
1356         type = type_from_name (str, ignoreCase);
1357         g_free (str);
1358         if (type == NULL){
1359                 MonoException *e = NULL;
1360                 
1361                 if (throwOnError)
1362                         e = mono_get_exception_type_load (name, NULL);
1363
1364                 mono_loader_clear_error ();
1365                 if (e != NULL)
1366                         mono_raise_exception (e);
1367         }
1368         
1369         return type;
1370 }
1371
1372
1373 ICALL_EXPORT MonoReflectionType*
1374 ves_icall_type_from_handle (MonoType *handle)
1375 {
1376         MonoDomain *domain = mono_domain_get (); 
1377
1378         MONO_ARCH_SAVE_REGS;
1379
1380         return mono_type_get_object (domain, handle);
1381 }
1382
1383 ICALL_EXPORT MonoBoolean
1384 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1385 {
1386         MONO_ARCH_SAVE_REGS;
1387
1388         if (c && type->type && c->type)
1389                 return mono_metadata_type_equal (type->type, c->type);
1390         else
1391                 return (type == c) ? TRUE : FALSE;
1392 }
1393
1394 /* System.TypeCode */
1395 typedef enum {
1396         TYPECODE_EMPTY,
1397         TYPECODE_OBJECT,
1398         TYPECODE_DBNULL,
1399         TYPECODE_BOOLEAN,
1400         TYPECODE_CHAR,
1401         TYPECODE_SBYTE,
1402         TYPECODE_BYTE,
1403         TYPECODE_INT16,
1404         TYPECODE_UINT16,
1405         TYPECODE_INT32,
1406         TYPECODE_UINT32,
1407         TYPECODE_INT64,
1408         TYPECODE_UINT64,
1409         TYPECODE_SINGLE,
1410         TYPECODE_DOUBLE,
1411         TYPECODE_DECIMAL,
1412         TYPECODE_DATETIME,
1413         TYPECODE_STRING = 18
1414 } TypeCode;
1415
1416 ICALL_EXPORT guint32
1417 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1418 {
1419         int t = type->type->type;
1420
1421         MONO_ARCH_SAVE_REGS;
1422
1423         if (type->type->byref)
1424                 return TYPECODE_OBJECT;
1425
1426 handle_enum:
1427         switch (t) {
1428         case MONO_TYPE_VOID:
1429                 return TYPECODE_OBJECT;
1430         case MONO_TYPE_BOOLEAN:
1431                 return TYPECODE_BOOLEAN;
1432         case MONO_TYPE_U1:
1433                 return TYPECODE_BYTE;
1434         case MONO_TYPE_I1:
1435                 return TYPECODE_SBYTE;
1436         case MONO_TYPE_U2:
1437                 return TYPECODE_UINT16;
1438         case MONO_TYPE_I2:
1439                 return TYPECODE_INT16;
1440         case MONO_TYPE_CHAR:
1441                 return TYPECODE_CHAR;
1442         case MONO_TYPE_PTR:
1443         case MONO_TYPE_U:
1444         case MONO_TYPE_I:
1445                 return TYPECODE_OBJECT;
1446         case MONO_TYPE_U4:
1447                 return TYPECODE_UINT32;
1448         case MONO_TYPE_I4:
1449                 return TYPECODE_INT32;
1450         case MONO_TYPE_U8:
1451                 return TYPECODE_UINT64;
1452         case MONO_TYPE_I8:
1453                 return TYPECODE_INT64;
1454         case MONO_TYPE_R4:
1455                 return TYPECODE_SINGLE;
1456         case MONO_TYPE_R8:
1457                 return TYPECODE_DOUBLE;
1458         case MONO_TYPE_VALUETYPE: {
1459                 MonoClass *klass = type->type->data.klass;
1460                 
1461                 if (klass->enumtype) {
1462                         t = mono_class_enum_basetype (klass)->type;
1463                         goto handle_enum;
1464                 } else if (mono_is_corlib_image (klass->image)) {
1465                         if (strcmp (klass->name_space, "System") == 0) {
1466                                 if (strcmp (klass->name, "Decimal") == 0)
1467                                         return TYPECODE_DECIMAL;
1468                                 else if (strcmp (klass->name, "DateTime") == 0)
1469                                         return TYPECODE_DATETIME;
1470                         }
1471                 }
1472                 return TYPECODE_OBJECT;
1473         }
1474         case MONO_TYPE_STRING:
1475                 return TYPECODE_STRING;
1476         case MONO_TYPE_SZARRAY:
1477         case MONO_TYPE_ARRAY:
1478         case MONO_TYPE_OBJECT:
1479         case MONO_TYPE_VAR:
1480         case MONO_TYPE_MVAR:
1481         case MONO_TYPE_TYPEDBYREF:
1482                 return TYPECODE_OBJECT;
1483         case MONO_TYPE_CLASS:
1484                 {
1485                         MonoClass *klass =  type->type->data.klass;
1486                         if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1487                                 if (strcmp (klass->name, "DBNull") == 0)
1488                                         return TYPECODE_DBNULL;
1489                         }
1490                 }
1491                 return TYPECODE_OBJECT;
1492         case MONO_TYPE_GENERICINST:
1493                 return TYPECODE_OBJECT;
1494         default:
1495                 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1496         }
1497         return 0;
1498 }
1499
1500 ICALL_EXPORT guint32
1501 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1502 {
1503         MonoDomain *domain; 
1504         MonoClass *klass;
1505         MonoClass *klassc;
1506
1507         MONO_ARCH_SAVE_REGS;
1508
1509         g_assert (type != NULL);
1510         
1511         domain = ((MonoObject *)type)->vtable->domain;
1512
1513         if (!c) /* FIXME: dont know what do do here */
1514                 return 0;
1515
1516         klass = mono_class_from_mono_type (type->type);
1517         klassc = mono_class_from_mono_type (c->type);
1518
1519         /* Interface check requires a more complex setup so we
1520          * only do for them. Otherwise we simply avoid mono_class_init.
1521          */
1522         if (check_interfaces) {
1523                 mono_class_init_or_throw (klass);
1524                 mono_class_init_or_throw (klassc);
1525         } else if (!klass->supertypes || !klassc->supertypes) {
1526                 mono_class_setup_supertypes (klass);
1527                 mono_class_setup_supertypes (klassc);
1528         }
1529
1530         if (type->type->byref)
1531                 return klassc == mono_defaults.object_class;
1532
1533         return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1534 }
1535
1536 static gboolean
1537 mono_type_is_primitive (MonoType *type)
1538 {
1539         return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1540                         type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1541 }
1542
1543 static MonoType*
1544 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1545 {
1546         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1547                 return mono_class_enum_basetype (type->data.klass);
1548         if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1549                 return mono_class_enum_basetype (type->data.generic_class->container_class);
1550         return type;
1551 }
1552
1553 ICALL_EXPORT guint32
1554 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1555 {
1556         MonoDomain *domain; 
1557         MonoClass *klass;
1558         MonoClass *klassc;
1559
1560         MONO_ARCH_SAVE_REGS;
1561
1562         g_assert (type != NULL);
1563         
1564         domain = ((MonoObject *)type)->vtable->domain;
1565
1566         klass = mono_class_from_mono_type (type->type);
1567         klassc = mono_class_from_mono_type (c->type);
1568
1569         if (type->type->byref ^ c->type->byref)
1570                 return FALSE;
1571
1572         if (type->type->byref) {
1573                 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1574                 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1575
1576                 klass = mono_class_from_mono_type (t);
1577                 klassc = mono_class_from_mono_type (ot);
1578
1579                 if (mono_type_is_primitive (t)) {
1580                         return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1581                 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1582                         return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1583                 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1584                         return t->type == ot->type;
1585                 } else {
1586                          if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1587                                  return FALSE;
1588
1589                          if (klass->valuetype)
1590                                 return klass == klassc;
1591                         return klass->valuetype == klassc->valuetype;
1592                 }
1593         }
1594         return mono_class_is_assignable_from (klass, klassc);
1595 }
1596
1597 ICALL_EXPORT guint32
1598 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1599 {
1600         MonoClass *klass = mono_class_from_mono_type (type->type);
1601         mono_class_init_or_throw (klass);
1602         return mono_object_isinst (obj, klass) != NULL;
1603 }
1604
1605 ICALL_EXPORT guint32
1606 ves_icall_get_attributes (MonoReflectionType *type)
1607 {
1608         MonoClass *klass = mono_class_from_mono_type (type->type);
1609         return klass->flags;
1610 }
1611
1612 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1613 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1614 {
1615         MonoClass *klass = field->field->parent;
1616         MonoMarshalType *info;
1617         MonoType *ftype;
1618         int i;
1619
1620         if (klass->generic_container ||
1621             (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1622                 return NULL;
1623
1624         ftype = mono_field_get_type (field->field);
1625         if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1626                 return NULL;
1627
1628         info = mono_marshal_load_type_info (klass);
1629
1630         for (i = 0; i < info->num_fields; ++i) {
1631                 if (info->fields [i].field == field->field) {
1632                         if (!info->fields [i].mspec)
1633                                 return NULL;
1634                         else
1635                                 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1636                 }
1637         }
1638
1639         return NULL;
1640 }
1641
1642 ICALL_EXPORT MonoReflectionField*
1643 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1644 {
1645         gboolean found = FALSE;
1646         MonoClass *klass;
1647         MonoClass *k;
1648
1649         g_assert (handle);
1650
1651         if (!type) {
1652                 klass = handle->parent;
1653         } else {
1654                 klass = mono_class_from_mono_type (type);
1655
1656                 /* Check that the field belongs to the class */
1657                 for (k = klass; k; k = k->parent) {
1658                         if (k == handle->parent) {
1659                                 found = TRUE;
1660                                 break;
1661                         }
1662                 }
1663
1664                 if (!found)
1665                         /* The managed code will throw the exception */
1666                         return NULL;
1667         }
1668
1669         return mono_field_get_object (mono_domain_get (), klass, handle);
1670 }
1671
1672 ICALL_EXPORT MonoArray*
1673 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1674 {
1675         MonoError error;
1676         MonoType *type = mono_field_get_type_checked (field->field, &error);
1677         mono_error_raise_exception (&error);
1678
1679         return type_array_from_modifiers (field->field->parent->image, type, optional);
1680 }
1681
1682 ICALL_EXPORT int
1683 vell_icall_get_method_attributes (MonoMethod *method)
1684 {
1685         return method->flags;
1686 }
1687
1688 ICALL_EXPORT void
1689 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1690 {
1691         MonoError error;
1692         MonoDomain *domain = mono_domain_get ();
1693         MonoMethodSignature* sig;
1694         MONO_ARCH_SAVE_REGS;
1695
1696         sig = mono_method_signature_checked (method, &error);
1697         if (!mono_error_ok (&error))
1698                 mono_error_raise_exception (&error);
1699
1700
1701         MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1702         MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1703         info->attrs = method->flags;
1704         info->implattrs = method->iflags;
1705         if (sig->call_convention == MONO_CALL_DEFAULT)
1706                 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1707         else {
1708                 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1709                         info->callconv = 2;
1710                 else
1711                         info->callconv = 1;
1712         }
1713         info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6); 
1714 }
1715
1716 ICALL_EXPORT MonoArray*
1717 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1718 {
1719         MonoDomain *domain = mono_domain_get (); 
1720
1721         return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1722 }
1723
1724 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1725 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1726 {
1727         MonoDomain *domain = mono_domain_get (); 
1728         MonoReflectionMarshalAsAttribute* res = NULL;
1729         MonoMarshalSpec **mspecs;
1730         int i;
1731
1732         mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1733         mono_method_get_marshal_info (method, mspecs);
1734
1735         if (mspecs [0])
1736                 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1737                 
1738         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1739                 if (mspecs [i])
1740                         mono_metadata_free_marshal_spec (mspecs [i]);
1741         g_free (mspecs);
1742
1743         return res;
1744 }
1745
1746 ICALL_EXPORT gint32
1747 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1748 {
1749         MonoClass *parent = field->field->parent;
1750         if (!parent->size_inited)
1751                 mono_class_init (parent);
1752         mono_class_setup_fields_locking (parent);
1753
1754         return field->field->offset - sizeof (MonoObject);
1755 }
1756
1757 ICALL_EXPORT MonoReflectionType*
1758 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1759 {
1760         MonoClass *parent;
1761         MONO_ARCH_SAVE_REGS;
1762
1763         parent = declaring? field->field->parent: field->klass;
1764
1765         return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1766 }
1767
1768 ICALL_EXPORT MonoObject *
1769 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1770 {       
1771         MonoClass *fklass = field->klass;
1772         MonoClassField *cf = field->field;
1773         MonoDomain *domain = mono_object_domain (field);
1774
1775         if (fklass->image->assembly->ref_only)
1776                 mono_raise_exception (mono_get_exception_invalid_operation (
1777                                         "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1778
1779         if (mono_security_core_clr_enabled ())
1780                 mono_security_core_clr_ensure_reflection_access_field (cf);
1781
1782         return mono_field_get_value_object (domain, cf, obj);
1783 }
1784
1785 ICALL_EXPORT void
1786 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1787 {
1788         MonoError error;
1789         MonoClassField *cf = field->field;
1790         MonoType *type;
1791         gchar *v;
1792
1793         MONO_ARCH_SAVE_REGS;
1794
1795         if (field->klass->image->assembly->ref_only)
1796                 mono_raise_exception (mono_get_exception_invalid_operation (
1797                                         "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1798
1799         if (mono_security_core_clr_enabled ())
1800                 mono_security_core_clr_ensure_reflection_access_field (cf);
1801
1802         type = mono_field_get_type_checked (cf, &error);
1803         if (!mono_error_ok (&error))
1804                 mono_error_raise_exception (&error);
1805
1806         v = (gchar *) value;
1807         if (!type->byref) {
1808                 switch (type->type) {
1809                 case MONO_TYPE_U1:
1810                 case MONO_TYPE_I1:
1811                 case MONO_TYPE_BOOLEAN:
1812                 case MONO_TYPE_U2:
1813                 case MONO_TYPE_I2:
1814                 case MONO_TYPE_CHAR:
1815                 case MONO_TYPE_U:
1816                 case MONO_TYPE_I:
1817                 case MONO_TYPE_U4:
1818                 case MONO_TYPE_I4:
1819                 case MONO_TYPE_R4:
1820                 case MONO_TYPE_U8:
1821                 case MONO_TYPE_I8:
1822                 case MONO_TYPE_R8:
1823                 case MONO_TYPE_VALUETYPE:
1824                 case MONO_TYPE_PTR:
1825                         if (v != NULL)
1826                                 v += sizeof (MonoObject);
1827                         break;
1828                 case MONO_TYPE_STRING:
1829                 case MONO_TYPE_OBJECT:
1830                 case MONO_TYPE_CLASS:
1831                 case MONO_TYPE_ARRAY:
1832                 case MONO_TYPE_SZARRAY:
1833                         /* Do nothing */
1834                         break;
1835                 case MONO_TYPE_GENERICINST: {
1836                         MonoGenericClass *gclass = type->data.generic_class;
1837                         g_assert (!gclass->context.class_inst->is_open);
1838
1839                         if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1840                                 MonoClass *nklass = mono_class_from_mono_type (type);
1841                                 MonoObject *nullable;
1842
1843                                 /* 
1844                                  * Convert the boxed vtype into a Nullable structure.
1845                                  * This is complicated by the fact that Nullables have
1846                                  * a variable structure.
1847                                  */
1848                                 nullable = mono_object_new (mono_domain_get (), nklass);
1849
1850                                 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1851
1852                                 v = mono_object_unbox (nullable);
1853                         }
1854                         else 
1855                                 if (gclass->container_class->valuetype && (v != NULL))
1856                                         v += sizeof (MonoObject);
1857                         break;
1858                 }
1859                 default:
1860                         g_error ("type 0x%x not handled in "
1861                                  "ves_icall_FieldInfo_SetValueInternal", type->type);
1862                         return;
1863                 }
1864         }
1865
1866         if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1867                 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1868                 if (!vtable->initialized)
1869                         mono_runtime_class_init (vtable);
1870                 mono_field_static_set_value (vtable, cf, v);
1871         } else {
1872                 mono_field_set_value (obj, cf, v);
1873         }
1874 }
1875
1876 ICALL_EXPORT MonoObject *
1877 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1878 {       
1879         MonoObject *o = NULL;
1880         MonoClassField *field = this->field;
1881         MonoClass *klass;
1882         MonoDomain *domain = mono_object_domain (this); 
1883         gchar *v;
1884         MonoTypeEnum def_type;
1885         const char *def_value;
1886         MonoType *t;
1887         MonoError error;
1888
1889         MONO_ARCH_SAVE_REGS;
1890         
1891         mono_class_init (field->parent);
1892
1893         t = mono_field_get_type_checked (field, &error);
1894         if (!mono_error_ok (&error))
1895                 mono_error_raise_exception (&error);
1896
1897         if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1898                 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1899
1900         if (image_is_dynamic (field->parent->image)) {
1901                 /* 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                         MonoError error;
5165                         klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, &error);
5166                         g_assert (!mono_loader_get_last_error ()); /* Plug any leaks */
5167                         
5168                         if (klass) {
5169                                 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5170                         } else {
5171                                 MonoException *ex = mono_error_convert_to_exception (&error);
5172                                 mono_array_setref (*exceptions, count, ex);
5173                         }
5174                         count++;
5175                 }
5176         }
5177         
5178         return res;
5179 }
5180
5181 ICALL_EXPORT MonoArray*
5182 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5183 {
5184         MonoArray *res = NULL;
5185         MonoArray *exceptions = NULL;
5186         MonoImage *image = NULL;
5187         MonoTableInfo *table = NULL;
5188         MonoDomain *domain;
5189         GList *list = NULL;
5190         int i, len, ex_count;
5191
5192         MONO_ARCH_SAVE_REGS;
5193
5194         domain = mono_object_domain (assembly);
5195
5196         g_assert (!assembly_is_dynamic (assembly->assembly));
5197         image = assembly->assembly->image;
5198         table = &image->tables [MONO_TABLE_FILE];
5199         res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5200
5201         /* Append data from all modules in the assembly */
5202         for (i = 0; i < table->rows; ++i) {
5203                 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5204                         MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5205                         if (loaded_image) {
5206                                 MonoArray *ex2;
5207                                 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5208                                 /* Append the new types to the end of the array */
5209                                 if (mono_array_length (res2) > 0) {
5210                                         guint32 len1, len2;
5211                                         MonoArray *res3, *ex3;
5212
5213                                         len1 = mono_array_length (res);
5214                                         len2 = mono_array_length (res2);
5215
5216                                         res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5217                                         mono_array_memcpy_refs (res3, 0, res, 0, len1);
5218                                         mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5219                                         res = res3;
5220
5221                                         ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5222                                         mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5223                                         mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5224                                         exceptions = ex3;
5225                                 }
5226                         }
5227                 }
5228         }
5229
5230         /* the ReflectionTypeLoadException must have all the types (Types property), 
5231          * NULL replacing types which throws an exception. The LoaderException must
5232          * contain all exceptions for NULL items.
5233          */
5234
5235         len = mono_array_length (res);
5236
5237         ex_count = 0;
5238         for (i = 0; i < len; i++) {
5239                 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5240                 MonoClass *klass;
5241
5242                 if (t) {
5243                         klass = mono_type_get_class (t->type);
5244                         if ((klass != NULL) && klass->exception_type) {
5245                                 /* keep the class in the list */
5246                                 list = g_list_append (list, klass);
5247                                 /* and replace Type with NULL */
5248                                 mono_array_setref (res, i, NULL);
5249                         }
5250                 } else {
5251                         ex_count ++;
5252                 }
5253         }
5254
5255         if (list || ex_count) {
5256                 GList *tmp = NULL;
5257                 MonoException *exc = NULL;
5258                 MonoArray *exl = NULL;
5259                 int j, length = g_list_length (list) + ex_count;
5260
5261                 mono_loader_clear_error ();
5262
5263                 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5264                 /* Types for which mono_class_get_checked () succeeded */
5265                 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5266                         MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5267                         mono_array_setref (exl, i, exc);
5268                 }
5269                 /* Types for which it don't */
5270                 for (j = 0; j < mono_array_length (exceptions); ++j) {
5271                         MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5272                         if (exc) {
5273                                 g_assert (i < length);
5274                                 mono_array_setref (exl, i, exc);
5275                                 i ++;
5276                         }
5277                 }
5278                 g_list_free (list);
5279                 list = NULL;
5280
5281                 exc = mono_get_exception_reflection_type_load (res, exl);
5282                 mono_loader_clear_error ();
5283                 mono_raise_exception (exc);
5284         }
5285                 
5286         return res;
5287 }
5288
5289 ICALL_EXPORT gboolean
5290 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5291 {
5292         MonoAssemblyName aname;
5293         MonoDomain *domain = mono_object_domain (name);
5294         char *val;
5295         gboolean is_version_defined;
5296         gboolean is_token_defined;
5297
5298         aname.public_key = NULL;
5299         val = mono_string_to_utf8 (assname);
5300         if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5301                 g_free ((guint8*) aname.public_key);
5302                 g_free (val);
5303                 return FALSE;
5304         }
5305         
5306         fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5307                 FALSE, is_token_defined);
5308
5309         mono_assembly_name_free (&aname);
5310         g_free ((guint8*) aname.public_key);
5311         g_free (val);
5312
5313         return TRUE;
5314 }
5315
5316 ICALL_EXPORT MonoReflectionType*
5317 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5318 {
5319         MonoError error;
5320         MonoDomain *domain = mono_object_domain (module); 
5321         MonoClass *klass;
5322
5323         MONO_ARCH_SAVE_REGS;
5324
5325         g_assert (module->image);
5326
5327         if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5328                 /* These images do not have a global type */
5329                 return NULL;
5330
5331         klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5332         mono_error_raise_exception (&error);
5333         return mono_type_get_object (domain, &klass->byval_arg);
5334 }
5335
5336 ICALL_EXPORT void
5337 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5338 {
5339         /*if (module->image)
5340                 mono_image_close (module->image);*/
5341 }
5342
5343 ICALL_EXPORT MonoString*
5344 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5345 {
5346         MonoDomain *domain = mono_object_domain (module); 
5347
5348         MONO_ARCH_SAVE_REGS;
5349
5350         g_assert (module->image);
5351         return mono_string_new (domain, module->image->guid);
5352 }
5353
5354 ICALL_EXPORT gpointer
5355 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5356 {
5357 #ifdef HOST_WIN32
5358         if (module->image && module->image->is_module_handle)
5359                 return module->image->raw_data;
5360 #endif
5361
5362         return (gpointer) (-1);
5363 }
5364
5365 ICALL_EXPORT void
5366 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5367 {
5368         if (image_is_dynamic (image)) {
5369                 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5370                 *pe_kind = dyn->pe_kind;
5371                 *machine = dyn->machine;
5372         }
5373         else {
5374                 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5375                 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5376         }
5377 }
5378
5379 ICALL_EXPORT gint32
5380 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5381 {
5382         return (image->md_version_major << 16) | (image->md_version_minor);
5383 }
5384
5385 ICALL_EXPORT MonoArray*
5386 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5387 {
5388         MonoArray *exceptions;
5389         int i;
5390
5391         MONO_ARCH_SAVE_REGS;
5392
5393         if (!module->image)
5394                 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5395         else {
5396                 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5397                 for (i = 0; i < mono_array_length (exceptions); ++i) {
5398                         MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5399                         if (ex)
5400                                 mono_raise_exception (ex);
5401                 }
5402                 return res;
5403         }
5404 }
5405
5406 static gboolean
5407 mono_memberref_is_method (MonoImage *image, guint32 token)
5408 {
5409         if (!image_is_dynamic (image)) {
5410                 guint32 cols [MONO_MEMBERREF_SIZE];
5411                 const char *sig;
5412                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5413                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5414                 mono_metadata_decode_blob_size (sig, &sig);
5415                 return (*sig != 0x6);
5416         } else {
5417                 MonoClass *handle_class;
5418
5419                 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5420                         return FALSE;
5421
5422                 return mono_defaults.methodhandle_class == handle_class;
5423         }
5424 }
5425
5426 static void
5427 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5428 {
5429         if (type_args)
5430                 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5431                                                                       mono_array_addr (type_args, MonoType*, 0));
5432         else
5433                 context->class_inst = NULL;
5434         if (method_args)
5435                 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5436                                                                        mono_array_addr (method_args, MonoType*, 0));
5437         else
5438                 context->method_inst = NULL;
5439 }
5440
5441 ICALL_EXPORT MonoType*
5442 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5443 {
5444         MonoClass *klass;
5445         int table = mono_metadata_token_table (token);
5446         int index = mono_metadata_token_index (token);
5447         MonoGenericContext context;
5448         MonoError error;
5449
5450         *resolve_error = ResolveTokenError_Other;
5451
5452         /* Validate token */
5453         if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) && 
5454                 (table != MONO_TABLE_TYPESPEC)) {
5455                 *resolve_error = ResolveTokenError_BadTable;
5456                 return NULL;
5457         }
5458
5459         if (image_is_dynamic (image)) {
5460                 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5461                         klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5462                         return klass ? &klass->byval_arg : NULL;
5463                 }
5464
5465                 init_generic_context_from_args (&context, type_args, method_args);
5466                 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5467                 return klass ? &klass->byval_arg : NULL;
5468         }
5469
5470         if ((index <= 0) || (index > image->tables [table].rows)) {
5471                 *resolve_error = ResolveTokenError_OutOfRange;
5472                 return NULL;
5473         }
5474
5475         init_generic_context_from_args (&context, type_args, method_args);
5476         klass = mono_class_get_checked (image, token, &error);
5477         if (klass)
5478                 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5479         mono_error_raise_exception (&error);
5480
5481         if (klass)
5482                 return &klass->byval_arg;
5483         else
5484                 return NULL;
5485 }
5486
5487 ICALL_EXPORT MonoMethod*
5488 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5489 {
5490         int table = mono_metadata_token_table (token);
5491         int index = mono_metadata_token_index (token);
5492         MonoGenericContext context;
5493         MonoMethod *method;
5494
5495         *error = ResolveTokenError_Other;
5496
5497         /* Validate token */
5498         if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) && 
5499                 (table != MONO_TABLE_MEMBERREF)) {
5500                 *error = ResolveTokenError_BadTable;
5501                 return NULL;
5502         }
5503
5504         if (image_is_dynamic (image)) {
5505                 if (table == MONO_TABLE_METHOD)
5506                         return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5507
5508                 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5509                         *error = ResolveTokenError_BadTable;
5510                         return NULL;
5511                 }
5512
5513                 init_generic_context_from_args (&context, type_args, method_args);
5514                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5515         }
5516
5517         if ((index <= 0) || (index > image->tables [table].rows)) {
5518                 *error = ResolveTokenError_OutOfRange;
5519                 return NULL;
5520         }
5521         if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5522                 *error = ResolveTokenError_BadTable;
5523                 return NULL;
5524         }
5525
5526         init_generic_context_from_args (&context, type_args, method_args);
5527         method = mono_get_method_full (image, token, NULL, &context);
5528
5529         if (mono_loader_get_last_error ())
5530                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5531
5532         return method;
5533 }
5534
5535 ICALL_EXPORT MonoString*
5536 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5537 {
5538         int index = mono_metadata_token_index (token);
5539
5540         *error = ResolveTokenError_Other;
5541
5542         /* Validate token */
5543         if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5544                 *error = ResolveTokenError_BadTable;
5545                 return NULL;
5546         }
5547
5548         if (image_is_dynamic (image))
5549                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5550
5551         if ((index <= 0) || (index >= image->heap_us.size)) {
5552                 *error = ResolveTokenError_OutOfRange;
5553                 return NULL;
5554         }
5555
5556         /* FIXME: What to do if the index points into the middle of a string ? */
5557
5558         return mono_ldstr (mono_domain_get (), image, index);
5559 }
5560
5561 ICALL_EXPORT MonoClassField*
5562 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5563 {
5564         MonoError error;
5565         MonoClass *klass;
5566         int table = mono_metadata_token_table (token);
5567         int index = mono_metadata_token_index (token);
5568         MonoGenericContext context;
5569         MonoClassField *field;
5570
5571         *resolve_error = ResolveTokenError_Other;
5572
5573         /* Validate token */
5574         if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5575                 *resolve_error = ResolveTokenError_BadTable;
5576                 return NULL;
5577         }
5578
5579         if (image_is_dynamic (image)) {
5580                 if (table == MONO_TABLE_FIELD)
5581                         return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5582
5583                 if (mono_memberref_is_method (image, token)) {
5584                         *resolve_error = ResolveTokenError_BadTable;
5585                         return NULL;
5586                 }
5587
5588                 init_generic_context_from_args (&context, type_args, method_args);
5589                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5590         }
5591
5592         if ((index <= 0) || (index > image->tables [table].rows)) {
5593                 *resolve_error = ResolveTokenError_OutOfRange;
5594                 return NULL;
5595         }
5596         if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5597                 *resolve_error = ResolveTokenError_BadTable;
5598                 return NULL;
5599         }
5600
5601         init_generic_context_from_args (&context, type_args, method_args);
5602         field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5603         mono_error_raise_exception (&error);
5604         
5605         return field;
5606 }
5607
5608
5609 ICALL_EXPORT MonoObject*
5610 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5611 {
5612         int table = mono_metadata_token_table (token);
5613
5614         *error = ResolveTokenError_Other;
5615
5616         switch (table) {
5617         case MONO_TABLE_TYPEDEF:
5618         case MONO_TABLE_TYPEREF:
5619         case MONO_TABLE_TYPESPEC: {
5620                 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5621                 if (t)
5622                         return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5623                 else
5624                         return NULL;
5625         }
5626         case MONO_TABLE_METHOD:
5627         case MONO_TABLE_METHODSPEC: {
5628                 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5629                 if (m)
5630                         return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5631                 else
5632                         return NULL;
5633         }               
5634         case MONO_TABLE_FIELD: {
5635                 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5636                 if (f)
5637                         return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5638                 else
5639                         return NULL;
5640         }
5641         case MONO_TABLE_MEMBERREF:
5642                 if (mono_memberref_is_method (image, token)) {
5643                         MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5644                         if (m)
5645                                 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5646                         else
5647                                 return NULL;
5648                 }
5649                 else {
5650                         MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5651                         if (f)
5652                                 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5653                         else
5654                                 return NULL;
5655                 }
5656                 break;
5657
5658         default:
5659                 *error = ResolveTokenError_BadTable;
5660         }
5661
5662         return NULL;
5663 }
5664
5665 ICALL_EXPORT MonoArray*
5666 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5667 {
5668         int table = mono_metadata_token_table (token);
5669         int idx = mono_metadata_token_index (token);
5670         MonoTableInfo *tables = image->tables;
5671         guint32 sig, len;
5672         const char *ptr;
5673         MonoArray *res;
5674
5675         *error = ResolveTokenError_OutOfRange;
5676
5677         /* FIXME: Support other tables ? */
5678         if (table != MONO_TABLE_STANDALONESIG)
5679                 return NULL;
5680
5681         if (image_is_dynamic (image))
5682                 return NULL;
5683
5684         if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5685                 return NULL;
5686
5687         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5688
5689         ptr = mono_metadata_blob_heap (image, sig);
5690         len = mono_metadata_decode_blob_size (ptr, &ptr);
5691
5692         res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5693         memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5694         return res;
5695 }
5696
5697 ICALL_EXPORT MonoReflectionType*
5698 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5699 {
5700         MonoClass *klass;
5701         int isbyref = 0, rank;
5702         char *str = mono_string_to_utf8 (smodifiers);
5703         char *p;
5704
5705         MONO_ARCH_SAVE_REGS;
5706
5707         klass = mono_class_from_mono_type (tb->type.type);
5708         p = str;
5709         /* logic taken from mono_reflection_parse_type(): keep in sync */
5710         while (*p) {
5711                 switch (*p) {
5712                 case '&':
5713                         if (isbyref) { /* only one level allowed by the spec */
5714                                 g_free (str);
5715                                 return NULL;
5716                         }
5717                         isbyref = 1;
5718                         p++;
5719                         g_free (str);
5720                         return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5721                         break;
5722                 case '*':
5723                         klass = mono_ptr_class_get (&klass->byval_arg);
5724                         mono_class_init (klass);
5725                         p++;
5726                         break;
5727                 case '[':
5728                         rank = 1;
5729                         p++;
5730                         while (*p) {
5731                                 if (*p == ']')
5732                                         break;
5733                                 if (*p == ',')
5734                                         rank++;
5735                                 else if (*p != '*') { /* '*' means unknown lower bound */
5736                                         g_free (str);
5737                                         return NULL;
5738                                 }
5739                                 ++p;
5740                         }
5741                         if (*p != ']') {
5742                                 g_free (str);
5743                                 return NULL;
5744                         }
5745                         p++;
5746                         klass = mono_array_class_get (klass, rank);
5747                         mono_class_init (klass);
5748                         break;
5749                 default:
5750                         break;
5751                 }
5752         }
5753         g_free (str);
5754         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5755 }
5756
5757 ICALL_EXPORT MonoBoolean
5758 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5759 {
5760         MonoType *type;
5761         MonoBoolean res;
5762
5763         MONO_ARCH_SAVE_REGS;
5764
5765         type = t->type;
5766         res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5767
5768         return res;
5769 }
5770
5771 static void
5772 check_for_invalid_type (MonoClass *klass)
5773 {
5774         char *name;
5775         MonoString *str;
5776         if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5777                 return;
5778
5779         name = mono_type_get_full_name (klass);
5780         str =  mono_string_new (mono_domain_get (), name);
5781         g_free (name);
5782         mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5783
5784 }
5785 ICALL_EXPORT MonoReflectionType *
5786 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5787 {
5788         MonoClass *klass, *aklass;
5789
5790         MONO_ARCH_SAVE_REGS;
5791
5792         klass = mono_class_from_mono_type (type->type);
5793         check_for_invalid_type (klass);
5794
5795         if (rank == 0) //single dimentional array
5796                 aklass = mono_array_class_get (klass, 1);
5797         else
5798                 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5799
5800         return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5801 }
5802
5803 ICALL_EXPORT MonoReflectionType *
5804 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5805 {
5806         MonoClass *klass;
5807
5808         MONO_ARCH_SAVE_REGS;
5809
5810         klass = mono_class_from_mono_type (type->type);
5811         mono_class_init_or_throw (klass);
5812         check_for_invalid_type (klass);
5813
5814         return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5815 }
5816
5817 ICALL_EXPORT MonoReflectionType *
5818 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5819 {
5820         MonoClass *klass, *pklass;
5821
5822         klass = mono_class_from_mono_type (type->type);
5823         mono_class_init_or_throw (klass);
5824         check_for_invalid_type (klass);
5825
5826         pklass = mono_ptr_class_get (type->type);
5827
5828         return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5829 }
5830
5831 ICALL_EXPORT MonoObject *
5832 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5833                                                    MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5834 {
5835         MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5836         MonoObject *delegate;
5837         gpointer func;
5838         MonoMethod *method = info->method;
5839
5840         MONO_ARCH_SAVE_REGS;
5841
5842         mono_class_init_or_throw (delegate_class);
5843
5844         mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5845
5846         if (mono_security_core_clr_enabled ()) {
5847                 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5848                         return NULL;
5849         }
5850
5851         delegate = mono_object_new (mono_object_domain (type), delegate_class);
5852
5853         if (method_is_dynamic (method)) {
5854                 /* Creating a trampoline would leak memory */
5855                 func = mono_compile_method (method);
5856         } else {
5857                 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5858                         method = mono_object_get_virtual_method (target, method);
5859                 func = mono_create_ftnptr (mono_domain_get (),
5860                         mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5861         }
5862
5863         mono_delegate_ctor_with_method (delegate, target, func, method);
5864
5865         return delegate;
5866 }
5867
5868 ICALL_EXPORT void
5869 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5870 {
5871         /* Reset the invoke impl to the default one */
5872         this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5873 }
5874
5875 /*
5876  * Magic number to convert a time which is relative to
5877  * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5878  */
5879 #define EPOCH_ADJUST    ((guint64)62135596800LL)
5880
5881 /*
5882  * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5883  */
5884 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5885
5886 #ifdef HOST_WIN32
5887 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5888 static void
5889 convert_to_absolute_date(SYSTEMTIME *date)
5890 {
5891 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5892         static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5893         static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5894         /* from the calendar FAQ */
5895         int a = (14 - date->wMonth) / 12;
5896         int y = date->wYear - a;
5897         int m = date->wMonth + 12 * a - 2;
5898         int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5899
5900         /* d is now the day of the week for the first of the month (0 == Sunday) */
5901
5902         int day_of_week = date->wDayOfWeek;
5903
5904         /* set day_in_month to the first day in the month which falls on day_of_week */    
5905         int day_in_month = 1 + (day_of_week - d);
5906         if (day_in_month <= 0)
5907                 day_in_month += 7;
5908
5909         /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5910         date->wDay = day_in_month + (date->wDay - 1) * 7;
5911         if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5912                 date->wDay -= 7;
5913 }
5914 #endif
5915
5916 #ifndef HOST_WIN32
5917 /*
5918  * Return's the offset from GMT of a local time.
5919  * 
5920  *  tm is a local time
5921  *  t  is the same local time as seconds.
5922  */
5923 static int 
5924 gmt_offset(struct tm *tm, time_t t)
5925 {
5926 #if defined (HAVE_TM_GMTOFF)
5927         return tm->tm_gmtoff;
5928 #else
5929         struct tm g;
5930         time_t t2;
5931         g = *gmtime(&t);
5932         g.tm_isdst = tm->tm_isdst;
5933         t2 = mktime(&g);
5934         return (int)difftime(t, t2);
5935 #endif
5936 }
5937 #endif
5938 /*
5939  * This is heavily based on zdump.c from glibc 2.2.
5940  *
5941  *  * data[0]:  start of daylight saving time (in DateTime ticks).
5942  *  * data[1]:  end of daylight saving time (in DateTime ticks).
5943  *  * data[2]:  utcoffset (in TimeSpan ticks).
5944  *  * data[3]:  additional offset when daylight saving (in TimeSpan ticks).
5945  *  * name[0]:  name of this timezone when not daylight saving.
5946  *  * name[1]:  name of this timezone when daylight saving.
5947  *
5948  *  FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5949  *         the class library allows years between 1 and 9999.
5950  *
5951  *  Returns true on success and zero on failure.
5952  */
5953 ICALL_EXPORT guint32
5954 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5955 {
5956 #ifndef HOST_WIN32
5957         MonoDomain *domain = mono_domain_get ();
5958         struct tm start, tt;
5959         time_t t;
5960
5961         long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
5962         int day, transitioned;
5963         char tzone [64];
5964
5965         gmtoff_st = gmtoff_ds = transitioned = 0;
5966
5967         MONO_ARCH_SAVE_REGS;
5968
5969         MONO_CHECK_ARG_NULL (data);
5970         MONO_CHECK_ARG_NULL (names);
5971
5972         mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5973         mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5974
5975         /* 
5976          * no info is better than crashing: we'll need our own tz data
5977          * to make this work properly, anyway. The range is probably
5978          * reduced to 1970 .. 2037 because that is what mktime is
5979          * guaranteed to support (we get into an infinite loop
5980          * otherwise).
5981          */
5982
5983         memset (&start, 0, sizeof (start));
5984
5985         start.tm_mday = 1;
5986         start.tm_year = year-1900;
5987
5988         t = mktime (&start);
5989
5990         if ((year < 1970) || (year > 2037) || (t == -1)) {
5991                 t = time (NULL);
5992                 tt = *localtime (&t);
5993                 strftime (tzone, sizeof (tzone), "%Z", &tt);
5994                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5995                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5996                 return 1;
5997         }
5998
5999         gmtoff = gmt_offset (&start, t);
6000
6001         /* For each day of the year, calculate the tm_gmtoff. */
6002         for (day = 0; day < 365 && transitioned < 2; day++) {
6003
6004                 t += 3600*24;
6005                 tt = *localtime (&t);
6006
6007         gmtoff_after = gmt_offset(&tt, t);
6008
6009                 /* Daylight saving starts or ends here. */
6010                 if (gmtoff_after != gmtoff) {
6011                         struct tm tt1;
6012                         time_t t1;
6013
6014                         /* Try to find the exact hour when daylight saving starts/ends. */
6015                         t1 = t;
6016                         do {
6017                                 t1 -= 3600;
6018                                 tt1 = *localtime (&t1);
6019                         } while (gmt_offset (&tt1, t1) != gmtoff);
6020
6021                         /* Try to find the exact minute when daylight saving starts/ends. */
6022                         do {
6023                                 t1 += 60;
6024                                 tt1 = *localtime (&t1);
6025                         } while (gmt_offset (&tt1, t1) == gmtoff);
6026                         t1+=gmtoff;
6027                         strftime (tzone, sizeof (tzone), "%Z", &tt);
6028                         
6029                         /* Write data, if we're already in daylight saving, we're done. */
6030                         if (tt.tm_isdst) {
6031                                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6032                                 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6033                                 if (gmtoff_ds == 0) {
6034                                         gmtoff_st = gmtoff;
6035                                         gmtoff_ds = gmtoff_after;
6036                                 }
6037                                 transitioned++;
6038                         } else {
6039                                 time_t te;
6040                                 te = mktime (&tt);
6041                                 
6042                                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6043                                 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6044                                 if (gmtoff_ds == 0) {
6045                                         gmtoff_st = gmtoff_after;
6046                                         gmtoff_ds = gmtoff;
6047                                 }
6048                                 transitioned++;
6049                         }
6050
6051                         /* This is only set once when we enter daylight saving. */
6052                         if (tt1.tm_isdst) {
6053                                 mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
6054                                 mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
6055                         }
6056                         gmtoff = gmt_offset (&tt, t);
6057                 }
6058         }
6059
6060         if (transitioned < 2) {
6061                 strftime (tzone, sizeof (tzone), "%Z", &tt);
6062                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6063                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6064                 mono_array_set ((*data), gint64, 0, 0);
6065                 mono_array_set ((*data), gint64, 1, 0);
6066                 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6067                 mono_array_set ((*data), gint64, 3, 0);
6068         }
6069
6070         return 1;
6071 #else
6072         MonoDomain *domain = mono_domain_get ();
6073         TIME_ZONE_INFORMATION tz_info;
6074         FILETIME ft;
6075         int i;
6076         int err, tz_id;
6077
6078         tz_id = GetTimeZoneInformation (&tz_info);
6079         if (tz_id == TIME_ZONE_ID_INVALID)
6080                 return 0;
6081
6082         MONO_CHECK_ARG_NULL (data);
6083         MONO_CHECK_ARG_NULL (names);
6084
6085         mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6086         mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6087
6088         for (i = 0; i < 32; ++i)
6089                 if (!tz_info.DaylightName [i])
6090                         break;
6091         mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6092         for (i = 0; i < 32; ++i)
6093                 if (!tz_info.StandardName [i])
6094                         break;
6095         mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6096
6097         if ((year <= 1601) || (year > 30827)) {
6098                 /*
6099                  * According to MSDN, the MS time functions can't handle dates outside
6100                  * this interval.
6101                  */
6102                 return 1;
6103         }
6104
6105         /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6106         if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6107                 tz_info.StandardDate.wYear = year;
6108                 convert_to_absolute_date(&tz_info.StandardDate);
6109                 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6110                 //g_assert(err);
6111                 if (err == 0)
6112                         return 0;
6113                 
6114                 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6115                 tz_info.DaylightDate.wYear = year;
6116                 convert_to_absolute_date(&tz_info.DaylightDate);
6117                 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6118                 //g_assert(err);
6119                 if (err == 0)
6120                         return 0;
6121                 
6122                 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6123         }
6124         mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6125         mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6126
6127         return 1;
6128 #endif
6129 }
6130
6131 /* System.Buffer */
6132
6133 static inline gint32 
6134 mono_array_get_byte_length (MonoArray *array)
6135 {
6136         MonoClass *klass;
6137         int length;
6138         int i;
6139
6140         klass = array->obj.vtable->klass;
6141
6142         if (array->bounds == NULL)
6143                 length = array->max_length;
6144         else {
6145                 length = 1;
6146                 for (i = 0; i < klass->rank; ++ i)
6147                         length *= array->bounds [i].length;
6148         }
6149
6150         switch (klass->element_class->byval_arg.type) {
6151         case MONO_TYPE_I1:
6152         case MONO_TYPE_U1:
6153         case MONO_TYPE_BOOLEAN:
6154                 return length;
6155         case MONO_TYPE_I2:
6156         case MONO_TYPE_U2:
6157         case MONO_TYPE_CHAR:
6158                 return length << 1;
6159         case MONO_TYPE_I4:
6160         case MONO_TYPE_U4:
6161         case MONO_TYPE_R4:
6162                 return length << 2;
6163         case MONO_TYPE_I:
6164         case MONO_TYPE_U:
6165                 return length * sizeof (gpointer);
6166         case MONO_TYPE_I8:
6167         case MONO_TYPE_U8:
6168         case MONO_TYPE_R8:
6169                 return length << 3;
6170         default:
6171                 return -1;
6172         }
6173 }
6174
6175 ICALL_EXPORT gint32 
6176 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array) 
6177 {
6178         MONO_ARCH_SAVE_REGS;
6179
6180         return mono_array_get_byte_length (array);
6181 }
6182
6183 ICALL_EXPORT gint8 
6184 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx) 
6185 {
6186         MONO_ARCH_SAVE_REGS;
6187
6188         return mono_array_get (array, gint8, idx);
6189 }
6190
6191 ICALL_EXPORT void 
6192 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value) 
6193 {
6194         MONO_ARCH_SAVE_REGS;
6195
6196         mono_array_set (array, gint8, idx, value);
6197 }
6198
6199 ICALL_EXPORT MonoBoolean
6200 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count) 
6201 {
6202         guint8 *src_buf, *dest_buf;
6203
6204         MONO_ARCH_SAVE_REGS;
6205
6206         /* This is called directly from the class libraries without going through the managed wrapper */
6207         MONO_CHECK_ARG_NULL (src);
6208         MONO_CHECK_ARG_NULL (dest);
6209
6210         /* watch out for integer overflow */
6211         if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6212                 return FALSE;
6213
6214         src_buf = (guint8 *)src->vector + src_offset;
6215         dest_buf = (guint8 *)dest->vector + dest_offset;
6216
6217         if (src != dest)
6218                 memcpy (dest_buf, src_buf, count);
6219         else
6220                 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6221
6222         return TRUE;
6223 }
6224
6225 #ifndef DISABLE_REMOTING
6226 ICALL_EXPORT MonoObject *
6227 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6228 {
6229         MonoDomain *domain = mono_object_domain (this); 
6230         MonoObject *res;
6231         MonoRealProxy *rp = ((MonoRealProxy *)this);
6232         MonoTransparentProxy *tp;
6233         MonoType *type;
6234         MonoClass *klass;
6235
6236         MONO_ARCH_SAVE_REGS;
6237
6238         res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6239         tp = (MonoTransparentProxy*) res;
6240         
6241         MONO_OBJECT_SETREF (tp, rp, rp);
6242         type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6243         klass = mono_class_from_mono_type (type);
6244
6245         tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6246         tp->remote_class = mono_remote_class (domain, class_name, klass);
6247
6248         res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6249         return res;
6250 }
6251
6252 ICALL_EXPORT MonoReflectionType *
6253 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6254 {
6255         return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6256 }
6257 #endif
6258
6259 /* System.Environment */
6260
6261 MonoString*
6262 ves_icall_System_Environment_get_UserName (void)
6263 {
6264         MONO_ARCH_SAVE_REGS;
6265
6266         /* using glib is more portable */
6267         return mono_string_new (mono_domain_get (), g_get_user_name ());
6268 }
6269
6270
6271 ICALL_EXPORT MonoString *
6272 ves_icall_System_Environment_get_MachineName (void)
6273 {
6274 #if defined (HOST_WIN32)
6275         gunichar2 *buf;
6276         guint32 len;
6277         MonoString *result;
6278
6279         len = MAX_COMPUTERNAME_LENGTH + 1;
6280         buf = g_new (gunichar2, len);
6281
6282         result = NULL;
6283         if (GetComputerName (buf, (PDWORD) &len))
6284                 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6285
6286         g_free (buf);
6287         return result;
6288 #elif !defined(DISABLE_SOCKETS)
6289         gchar buf [256];
6290         MonoString *result;
6291
6292         if (gethostname (buf, sizeof (buf)) == 0)
6293                 result = mono_string_new (mono_domain_get (), buf);
6294         else
6295                 result = NULL;
6296         
6297         return result;
6298 #else
6299         return mono_string_new (mono_domain_get (), "mono");
6300 #endif
6301 }
6302
6303 ICALL_EXPORT int
6304 ves_icall_System_Environment_get_Platform (void)
6305 {
6306 #if defined (TARGET_WIN32)
6307         /* Win32NT */
6308         return 2;
6309 #elif defined(__MACH__)
6310         /* OSX */
6311         //
6312         // Notice that the value is hidden from user code, and only exposed
6313         // to mscorlib.   This is due to Mono's Unix/MacOS code predating the
6314         // define and making assumptions based on Unix/128/4 values before there
6315         // was a MacOS define.    Lots of code would assume that not-Unix meant
6316         // Windows, but in this case, it would be OSX. 
6317         //
6318         return 6;
6319 #else
6320         /* Unix */
6321         return 4;
6322 #endif
6323 }
6324
6325 ICALL_EXPORT MonoString *
6326 ves_icall_System_Environment_get_NewLine (void)
6327 {
6328         MONO_ARCH_SAVE_REGS;
6329
6330 #if defined (HOST_WIN32)
6331         return mono_string_new (mono_domain_get (), "\r\n");
6332 #else
6333         return mono_string_new (mono_domain_get (), "\n");
6334 #endif
6335 }
6336
6337 ICALL_EXPORT MonoString *
6338 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6339 {
6340         const gchar *value;
6341         gchar *utf8_name;
6342
6343         MONO_ARCH_SAVE_REGS;
6344
6345         if (name == NULL)
6346                 return NULL;
6347
6348         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6349         value = g_getenv (utf8_name);
6350
6351         g_free (utf8_name);
6352
6353         if (value == 0)
6354                 return NULL;
6355         
6356         return mono_string_new (mono_domain_get (), value);
6357 }
6358
6359 /*
6360  * There is no standard way to get at environ.
6361  */
6362 #ifndef _MSC_VER
6363 #ifndef __MINGW32_VERSION
6364 #if defined(__APPLE__) && !defined (__arm__)
6365 /* Apple defines this in crt_externs.h but doesn't provide that header for 
6366  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
6367  * in fact exist on all implementations (so far) 
6368  */
6369 gchar ***_NSGetEnviron(void);
6370 #define environ (*_NSGetEnviron())
6371 #else
6372 extern
6373 char **environ;
6374 #endif
6375 #endif
6376 #endif
6377
6378 ICALL_EXPORT MonoArray *
6379 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6380 {
6381 #ifdef HOST_WIN32
6382         MonoArray *names;
6383         MonoDomain *domain;
6384         MonoString *str;
6385         WCHAR* env_strings;
6386         WCHAR* env_string;
6387         WCHAR* equal_str;
6388         int n = 0;
6389
6390         env_strings = GetEnvironmentStrings();
6391
6392         if (env_strings) {
6393                 env_string = env_strings;
6394                 while (*env_string != '\0') {
6395                 /* weird case that MS seems to skip */
6396                         if (*env_string != '=')
6397                                 n++;
6398                         while (*env_string != '\0')
6399                                 env_string++;
6400                         env_string++;
6401                 }
6402         }
6403
6404         domain = mono_domain_get ();
6405         names = mono_array_new (domain, mono_defaults.string_class, n);
6406
6407         if (env_strings) {
6408                 n = 0;
6409                 env_string = env_strings;
6410                 while (*env_string != '\0') {
6411                         /* weird case that MS seems to skip */
6412                         if (*env_string != '=') {
6413                                 equal_str = wcschr(env_string, '=');
6414                                 g_assert(equal_str);
6415                                 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6416                                 mono_array_setref (names, n, str);
6417                                 n++;
6418                         }
6419                         while (*env_string != '\0')
6420                                 env_string++;
6421                         env_string++;
6422                 }
6423
6424                 FreeEnvironmentStrings (env_strings);
6425         }
6426
6427         return names;
6428
6429 #else
6430         MonoArray *names;
6431         MonoDomain *domain;
6432         MonoString *str;
6433         gchar **e, **parts;
6434         int n;
6435
6436         MONO_ARCH_SAVE_REGS;
6437
6438         n = 0;
6439         for (e = environ; *e != 0; ++ e)
6440                 ++ n;
6441
6442         domain = mono_domain_get ();
6443         names = mono_array_new (domain, mono_defaults.string_class, n);
6444
6445         n = 0;
6446         for (e = environ; *e != 0; ++ e) {
6447                 parts = g_strsplit (*e, "=", 2);
6448                 if (*parts != 0) {
6449                         str = mono_string_new (domain, *parts);
6450                         mono_array_setref (names, n, str);
6451                 }
6452
6453                 g_strfreev (parts);
6454
6455                 ++ n;
6456         }
6457
6458         return names;
6459 #endif
6460 }
6461
6462 /*
6463  * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6464  */
6465 #if !GLIB_CHECK_VERSION(2,4,0)
6466 #define g_setenv(a,b,c)   setenv(a,b,c)
6467 #define g_unsetenv(a) unsetenv(a)
6468 #endif
6469
6470 ICALL_EXPORT void
6471 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6472 {
6473 #ifdef HOST_WIN32
6474         gunichar2 *utf16_name, *utf16_value;
6475 #else
6476         gchar *utf8_name, *utf8_value;
6477         MonoError error;
6478 #endif
6479
6480         MONO_ARCH_SAVE_REGS;
6481         
6482 #ifdef HOST_WIN32
6483         utf16_name = mono_string_to_utf16 (name);
6484         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6485                 SetEnvironmentVariable (utf16_name, NULL);
6486                 g_free (utf16_name);
6487                 return;
6488         }
6489
6490         utf16_value = mono_string_to_utf16 (value);
6491
6492         SetEnvironmentVariable (utf16_name, utf16_value);
6493
6494         g_free (utf16_name);
6495         g_free (utf16_value);
6496 #else
6497         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6498
6499         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6500                 g_unsetenv (utf8_name);
6501                 g_free (utf8_name);
6502                 return;
6503         }
6504
6505         utf8_value = mono_string_to_utf8_checked (value, &error);
6506         if (!mono_error_ok (&error)) {
6507                 g_free (utf8_name);
6508                 mono_error_raise_exception (&error);
6509         }
6510         g_setenv (utf8_name, utf8_value, TRUE);
6511
6512         g_free (utf8_name);
6513         g_free (utf8_value);
6514 #endif
6515 }
6516
6517 ICALL_EXPORT void
6518 ves_icall_System_Environment_Exit (int result)
6519 {
6520         MONO_ARCH_SAVE_REGS;
6521
6522         mono_environment_exitcode_set (result);
6523
6524 /* FIXME: There are some cleanup hangs that should be worked out, but
6525  * if the program is going to exit, everything will be cleaned up when
6526  * NaCl exits anyway.
6527  */
6528 #ifndef __native_client__
6529         if (!mono_runtime_try_shutdown ())
6530                 mono_thread_exit ();
6531
6532         /* Suspend all managed threads since the runtime is going away */
6533         mono_thread_suspend_all_other_threads ();
6534
6535         mono_runtime_quit ();
6536 #endif
6537
6538         /* we may need to do some cleanup here... */
6539         exit (result);
6540 }
6541
6542 ICALL_EXPORT MonoString*
6543 ves_icall_System_Environment_GetGacPath (void)
6544 {
6545         return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6546 }
6547
6548 ICALL_EXPORT MonoString*
6549 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6550 {
6551 #if defined (HOST_WIN32)
6552         #ifndef CSIDL_FLAG_CREATE
6553                 #define CSIDL_FLAG_CREATE       0x8000
6554         #endif
6555
6556         WCHAR path [MAX_PATH];
6557         /* Create directory if no existing */
6558         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6559                 int len = 0;
6560                 while (path [len])
6561                         ++ len;
6562                 return mono_string_new_utf16 (mono_domain_get (), path, len);
6563         }
6564 #else
6565         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6566 #endif
6567         return mono_string_new (mono_domain_get (), "");
6568 }
6569
6570 ICALL_EXPORT MonoArray *
6571 ves_icall_System_Environment_GetLogicalDrives (void)
6572 {
6573         gunichar2 buf [256], *ptr, *dname;
6574         gunichar2 *u16;
6575         guint initial_size = 127, size = 128;
6576         gint ndrives;
6577         MonoArray *result;
6578         MonoString *drivestr;
6579         MonoDomain *domain = mono_domain_get ();
6580         gint len;
6581
6582         MONO_ARCH_SAVE_REGS;
6583
6584         buf [0] = '\0';
6585         ptr = buf;
6586
6587         while (size > initial_size) {
6588                 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6589                 if (size > initial_size) {
6590                         if (ptr != buf)
6591                                 g_free (ptr);
6592                         ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6593                         initial_size = size;
6594                         size++;
6595                 }
6596         }
6597
6598         /* Count strings */
6599         dname = ptr;
6600         ndrives = 0;
6601         do {
6602                 while (*dname++);
6603                 ndrives++;
6604         } while (*dname);
6605
6606         dname = ptr;
6607         result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6608         ndrives = 0;
6609         do {
6610                 len = 0;
6611                 u16 = dname;
6612                 while (*u16) { u16++; len ++; }
6613                 drivestr = mono_string_new_utf16 (domain, dname, len);
6614                 mono_array_setref (result, ndrives++, drivestr);
6615                 while (*dname++);
6616         } while (*dname);
6617
6618         if (ptr != buf)
6619                 g_free (ptr);
6620
6621         return result;
6622 }
6623
6624 ICALL_EXPORT MonoString *
6625 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6626 {
6627         gunichar2 volume_name [MAX_PATH + 1];
6628         
6629         if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6630                 return NULL;
6631         return mono_string_from_utf16 (volume_name);
6632 }
6633
6634 ICALL_EXPORT MonoString *
6635 ves_icall_System_Environment_InternalGetHome (void)
6636 {
6637         MONO_ARCH_SAVE_REGS;
6638
6639         return mono_string_new (mono_domain_get (), g_get_home_dir ());
6640 }
6641
6642 static const char *encodings [] = {
6643         (char *) 1,
6644                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6645                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6646                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6647         (char *) 2,
6648                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6649                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6650                 "x_unicode_2_0_utf_7",
6651         (char *) 3,
6652                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6653                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6654         (char *) 4,
6655                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6656                 "iso_10646_ucs2",
6657         (char *) 5,
6658                 "unicodefffe", "utf_16be",
6659         (char *) 6,
6660                 "iso_8859_1",
6661         (char *) 0
6662 };
6663
6664 /*
6665  * Returns the internal codepage, if the value of "int_code_page" is
6666  * 1 at entry, and we can not compute a suitable code page number,
6667  * returns the code page as a string
6668  */
6669 ICALL_EXPORT MonoString*
6670 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page) 
6671 {
6672         const char *cset;
6673         const char *p;
6674         char *c;
6675         char *codepage = NULL;
6676         int code;
6677         int want_name = *int_code_page;
6678         int i;
6679         
6680         *int_code_page = -1;
6681         MONO_ARCH_SAVE_REGS;
6682
6683         g_get_charset (&cset);
6684         c = codepage = strdup (cset);
6685         for (c = codepage; *c; c++){
6686                 if (isascii (*c) && isalpha (*c))
6687                         *c = tolower (*c);
6688                 if (*c == '-')
6689                         *c = '_';
6690         }
6691         /* g_print ("charset: %s\n", cset); */
6692         
6693         /* handle some common aliases */
6694         p = encodings [0];
6695         code = 0;
6696         for (i = 0; p != 0; ){
6697                 if ((gssize) p < 7){
6698                         code = (gssize) p;
6699                         p = encodings [++i];
6700                         continue;
6701                 }
6702                 if (strcmp (p, codepage) == 0){
6703                         *int_code_page = code;
6704                         break;
6705                 }
6706                 p = encodings [++i];
6707         }
6708         
6709         if (strstr (codepage, "utf_8") != NULL)
6710                 *int_code_page |= 0x10000000;
6711         free (codepage);
6712         
6713         if (want_name && *int_code_page == -1)
6714                 return mono_string_new (mono_domain_get (), cset);
6715         else
6716                 return NULL;
6717 }
6718
6719 ICALL_EXPORT MonoBoolean
6720 ves_icall_System_Environment_get_HasShutdownStarted (void)
6721 {
6722         if (mono_runtime_is_shutting_down ())
6723                 return TRUE;
6724
6725         if (mono_domain_is_unloading (mono_domain_get ()))
6726                 return TRUE;
6727
6728         return FALSE;
6729 }
6730
6731 ICALL_EXPORT void
6732 ves_icall_System_Environment_BroadcastSettingChange (void)
6733 {
6734 #ifdef HOST_WIN32
6735         SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6736 #endif
6737 }
6738
6739 ICALL_EXPORT void
6740 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this, 
6741                                          MonoReflectionMethod *method,
6742                                          MonoArray *out_args)
6743 {
6744         MONO_ARCH_SAVE_REGS;
6745
6746         mono_message_init (mono_object_domain (this), this, method, out_args);
6747 }
6748
6749 #ifndef DISABLE_REMOTING
6750 ICALL_EXPORT MonoBoolean
6751 ves_icall_IsTransparentProxy (MonoObject *proxy)
6752 {
6753         MONO_ARCH_SAVE_REGS;
6754
6755         if (!proxy)
6756                 return 0;
6757
6758         if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6759                 return 1;
6760
6761         return 0;
6762 }
6763
6764 ICALL_EXPORT MonoReflectionMethod *
6765 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6766         MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6767 {
6768         MonoClass *klass;
6769         MonoMethod *method;
6770         MonoMethod **vtable;
6771         MonoMethod *res = NULL;
6772
6773         MONO_CHECK_ARG_NULL (rtype);
6774         MONO_CHECK_ARG_NULL (rmethod);
6775
6776         method = rmethod->method;
6777         klass = mono_class_from_mono_type (rtype->type);
6778         mono_class_init_or_throw (klass);
6779
6780         if (MONO_CLASS_IS_INTERFACE (klass))
6781                 return NULL;
6782
6783         if (method->flags & METHOD_ATTRIBUTE_STATIC)
6784                 return NULL;
6785
6786         if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6787                 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6788                         return rmethod;
6789                 else
6790                         return NULL;
6791         }
6792
6793         mono_class_setup_vtable (klass);
6794         vtable = klass->vtable;
6795
6796         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6797                 gboolean variance_used = FALSE;
6798                 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6799                 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6800                 if (offs >= 0)
6801                         res = vtable [offs + method->slot];
6802         } else {
6803                 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6804                         return NULL;
6805
6806                 if (method->slot != -1)
6807                         res = vtable [method->slot];
6808         }
6809
6810         if (!res)
6811                 return NULL;
6812
6813         return mono_method_get_object (mono_domain_get (), res, NULL);
6814 }
6815
6816 ICALL_EXPORT void
6817 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6818 {
6819         MonoClass *klass;
6820         MonoVTable* vtable;
6821
6822         MONO_ARCH_SAVE_REGS;
6823
6824         klass = mono_class_from_mono_type (type->type);
6825         vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6826
6827         mono_vtable_set_is_remote (vtable, enable);
6828 }
6829
6830 #else /* DISABLE_REMOTING */
6831
6832 ICALL_EXPORT void
6833 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6834 {
6835         g_assert_not_reached ();
6836 }
6837
6838 #endif
6839
6840 ICALL_EXPORT MonoObject *
6841 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6842 {
6843         MonoClass *klass;
6844         MonoDomain *domain;
6845         
6846         MONO_ARCH_SAVE_REGS;
6847
6848         domain = mono_object_domain (type);
6849         klass = mono_class_from_mono_type (type->type);
6850         mono_class_init_or_throw (klass);
6851
6852         if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6853                 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6854
6855         if (klass->rank >= 1) {
6856                 g_assert (klass->rank == 1);
6857                 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6858         } else {
6859                 /* Bypass remoting object creation check */
6860                 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6861         }
6862 }
6863
6864 ICALL_EXPORT MonoString *
6865 ves_icall_System_IO_get_temp_path (void)
6866 {
6867         MONO_ARCH_SAVE_REGS;
6868
6869         return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6870 }
6871
6872 #ifndef PLATFORM_NO_DRIVEINFO
6873 ICALL_EXPORT MonoBoolean
6874 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6875                                                 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6876                                                 gint32 *error)
6877 {
6878         gboolean result;
6879         ULARGE_INTEGER wapi_free_bytes_avail;
6880         ULARGE_INTEGER wapi_total_number_of_bytes;
6881         ULARGE_INTEGER wapi_total_number_of_free_bytes;
6882
6883         MONO_ARCH_SAVE_REGS;
6884
6885         *error = ERROR_SUCCESS;
6886         result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6887                                      &wapi_total_number_of_free_bytes);
6888
6889         if (result) {
6890                 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6891                 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6892                 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6893         } else {
6894                 *free_bytes_avail = 0;
6895                 *total_number_of_bytes = 0;
6896                 *total_number_of_free_bytes = 0;
6897                 *error = GetLastError ();
6898         }
6899
6900         return result;
6901 }
6902
6903 ICALL_EXPORT guint32
6904 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6905 {
6906         MONO_ARCH_SAVE_REGS;
6907
6908         return GetDriveType (mono_string_chars (root_path_name));
6909 }
6910 #endif
6911
6912 ICALL_EXPORT gpointer
6913 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6914 {
6915         MONO_ARCH_SAVE_REGS;
6916
6917         return mono_compile_method (method);
6918 }
6919
6920 ICALL_EXPORT MonoString *
6921 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6922 {
6923         MonoString *mcpath;
6924         gchar *path;
6925
6926         MONO_ARCH_SAVE_REGS;
6927
6928         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6929
6930 #if defined (HOST_WIN32)
6931         /* Avoid mixing '/' and '\\' */
6932         {
6933                 gint i;
6934                 for (i = strlen (path) - 1; i >= 0; i--)
6935                         if (path [i] == '/')
6936                                 path [i] = '\\';
6937         }
6938 #endif
6939         mcpath = mono_string_new (mono_domain_get (), path);
6940         g_free (path);
6941
6942         return mcpath;
6943 }
6944
6945 static MonoString *
6946 get_bundled_app_config (void)
6947 {
6948         const gchar *app_config;
6949         MonoDomain *domain;
6950         MonoString *file;
6951         gchar *config_file_name, *config_file_path;
6952         gsize len;
6953         gchar *module;
6954
6955         MONO_ARCH_SAVE_REGS;
6956
6957         domain = mono_domain_get ();
6958         file = domain->setup->configuration_file;
6959         if (!file)
6960                 return NULL;
6961
6962         // Retrieve config file and remove the extension
6963         config_file_name = mono_string_to_utf8 (file);
6964         config_file_path = mono_portability_find_file (config_file_name, TRUE);
6965         if (!config_file_path)
6966                 config_file_path = config_file_name;
6967         len = strlen (config_file_path) - strlen (".config");
6968         module = g_malloc0 (len + 1);
6969         memcpy (module, config_file_path, len);
6970         // Get the config file from the module name
6971         app_config = mono_config_string_for_assembly_file (module);
6972         // Clean-up
6973         g_free (module);
6974         if (config_file_name != config_file_path)
6975                 g_free (config_file_name);
6976         g_free (config_file_path);
6977
6978         if (!app_config)
6979                 return NULL;
6980
6981         return mono_string_new (mono_domain_get (), app_config);
6982 }
6983
6984 static MonoString *
6985 get_bundled_machine_config (void)
6986 {
6987         const gchar *machine_config;
6988
6989         MONO_ARCH_SAVE_REGS;
6990
6991         machine_config = mono_get_machine_config ();
6992
6993         if (!machine_config)
6994                 return NULL;
6995
6996         return mono_string_new (mono_domain_get (), machine_config);
6997 }
6998
6999 ICALL_EXPORT MonoString *
7000 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7001 {
7002         MonoString *ipath;
7003         gchar *path;
7004
7005         MONO_ARCH_SAVE_REGS;
7006
7007         path = g_path_get_dirname (mono_get_config_dir ());
7008
7009 #if defined (HOST_WIN32)
7010         /* Avoid mixing '/' and '\\' */
7011         {
7012                 gint i;
7013                 for (i = strlen (path) - 1; i >= 0; i--)
7014                         if (path [i] == '/')
7015                                 path [i] = '\\';
7016         }
7017 #endif
7018         ipath = mono_string_new (mono_domain_get (), path);
7019         g_free (path);
7020
7021         return ipath;
7022 }
7023
7024 ICALL_EXPORT gboolean
7025 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7026 {
7027         MonoPEResourceDataEntry *entry;
7028         MonoImage *image;
7029
7030         MONO_ARCH_SAVE_REGS;
7031
7032         if (!assembly || !result || !size)
7033                 return FALSE;
7034
7035         *result = NULL;
7036         *size = 0;
7037         image = assembly->assembly->image;
7038         entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7039         if (!entry)
7040                 return FALSE;
7041
7042         *result = mono_image_rva_map (image, entry->rde_data_offset);
7043         if (!(*result)) {
7044                 g_free (entry);
7045                 return FALSE;
7046         }
7047         *size = entry->rde_size;
7048         g_free (entry);
7049         return TRUE;
7050 }
7051
7052 ICALL_EXPORT MonoBoolean
7053 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7054 {
7055         return mono_is_debugger_attached ();
7056 }
7057
7058 ICALL_EXPORT MonoBoolean
7059 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7060 {
7061         if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7062                 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7063         else
7064                 return FALSE;
7065 }
7066
7067 ICALL_EXPORT void
7068 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7069 {
7070         if (mono_get_runtime_callbacks ()->debug_log)
7071                 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7072 }
7073
7074 ICALL_EXPORT void
7075 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7076 {
7077 #if defined (HOST_WIN32)
7078         OutputDebugString (mono_string_chars (message));
7079 #else
7080         g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7081 #endif
7082 }
7083
7084 /* Only used for value types */
7085 ICALL_EXPORT MonoObject *
7086 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7087 {
7088         MonoClass *klass;
7089         MonoDomain *domain;
7090         
7091         MONO_ARCH_SAVE_REGS;
7092
7093         domain = mono_object_domain (type);
7094         klass = mono_class_from_mono_type (type->type);
7095         mono_class_init_or_throw (klass);
7096
7097         if (mono_class_is_nullable (klass))
7098                 /* No arguments -> null */
7099                 return NULL;
7100
7101         return mono_object_new (domain, klass);
7102 }
7103
7104 ICALL_EXPORT MonoReflectionMethod *
7105 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7106 {
7107         MonoClass *klass, *parent;
7108         MonoMethod *method = m->method;
7109         MonoMethod *result = NULL;
7110         int slot;
7111
7112         MONO_ARCH_SAVE_REGS;
7113
7114         if (method->klass == NULL)
7115                 return m;
7116
7117         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7118             MONO_CLASS_IS_INTERFACE (method->klass) ||
7119             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7120                 return m;
7121
7122         slot = mono_method_get_vtable_slot (method);
7123         if (slot == -1)
7124                 return m;
7125
7126         klass = method->klass;
7127         if (klass->generic_class)
7128                 klass = klass->generic_class->container_class;
7129
7130         if (definition) {
7131                 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7132                 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7133                         mono_class_setup_vtable (parent);
7134                         if (parent->vtable_size <= slot)
7135                                 break;
7136                         klass = parent;
7137                 }
7138         } else {
7139                 klass = klass->parent;
7140                 if (!klass)
7141                         return m;
7142         }
7143
7144         if (klass == method->klass)
7145                 return m;
7146
7147         /*This is possible if definition == FALSE.
7148          * Do it here to be really sure we don't read invalid memory.
7149          */
7150         if (slot >= klass->vtable_size)
7151                 return m;
7152
7153         mono_class_setup_vtable (klass);
7154
7155         result = klass->vtable [slot];
7156         if (result == NULL) {
7157                 /* It is an abstract method */
7158                 gpointer iter = NULL;
7159                 while ((result = mono_class_get_methods (klass, &iter)))
7160                         if (result->slot == slot)
7161                                 break;
7162         }
7163
7164         if (result == NULL)
7165                 return m;
7166
7167         return mono_method_get_object (mono_domain_get (), result, NULL);
7168 }
7169
7170 ICALL_EXPORT MonoString*
7171 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7172 {
7173         MonoMethod *method = m->method;
7174
7175         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7176         return m->name;
7177 }
7178
7179 ICALL_EXPORT void
7180 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7181 {
7182         MONO_ARCH_SAVE_REGS;
7183
7184         iter->sig = *(MonoMethodSignature**)argsp;
7185         
7186         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7187         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7188
7189         iter->next_arg = 0;
7190         /* FIXME: it's not documented what start is exactly... */
7191         if (start) {
7192                 iter->args = start;
7193         } else {
7194                 iter->args = argsp + sizeof (gpointer);
7195         }
7196         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7197
7198         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7199 }
7200
7201 ICALL_EXPORT MonoTypedRef
7202 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7203 {
7204         guint32 i, arg_size;
7205         gint32 align;
7206         MonoTypedRef res;
7207         MONO_ARCH_SAVE_REGS;
7208
7209         i = iter->sig->sentinelpos + iter->next_arg;
7210
7211         g_assert (i < iter->sig->param_count);
7212
7213         res.type = iter->sig->params [i];
7214         res.klass = mono_class_from_mono_type (res.type);
7215         arg_size = mono_type_stack_size (res.type, &align);
7216 #if defined(__arm__) || defined(__mips__)
7217         iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7218 #endif
7219         res.value = iter->args;
7220 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7221         /* Values are stored as 8 byte register sized objects, but 'value'
7222          * is dereferenced as a pointer in other routines.
7223          */
7224         res.value = (char*)res.value + 4;
7225 #endif
7226 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7227         if (arg_size <= sizeof (gpointer)) {
7228                 int dummy;
7229                 int padding = arg_size - mono_type_size (res.type, &dummy);
7230                 res.value = (guint8*)res.value + padding;
7231         }
7232 #endif
7233         iter->args = (char*)iter->args + arg_size;
7234         iter->next_arg++;
7235
7236         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7237
7238         return res;
7239 }
7240
7241 ICALL_EXPORT MonoTypedRef
7242 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7243 {
7244         guint32 i, arg_size;
7245         gint32 align;
7246         MonoTypedRef res;
7247         MONO_ARCH_SAVE_REGS;
7248
7249         i = iter->sig->sentinelpos + iter->next_arg;
7250
7251         g_assert (i < iter->sig->param_count);
7252
7253         while (i < iter->sig->param_count) {
7254                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7255                         continue;
7256                 res.type = iter->sig->params [i];
7257                 res.klass = mono_class_from_mono_type (res.type);
7258                 /* FIXME: endianess issue... */
7259                 arg_size = mono_type_stack_size (res.type, &align);
7260 #if defined(__arm__) || defined(__mips__)
7261                 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7262 #endif
7263                 res.value = iter->args;
7264                 iter->args = (char*)iter->args + arg_size;
7265                 iter->next_arg++;
7266                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7267                 return res;
7268         }
7269         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7270
7271         res.type = NULL;
7272         res.value = NULL;
7273         res.klass = NULL;
7274         return res;
7275 }
7276
7277 ICALL_EXPORT MonoType*
7278 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7279 {
7280         gint i;
7281         MONO_ARCH_SAVE_REGS;
7282         
7283         i = iter->sig->sentinelpos + iter->next_arg;
7284
7285         g_assert (i < iter->sig->param_count);
7286
7287         return iter->sig->params [i];
7288 }
7289
7290 ICALL_EXPORT MonoObject*
7291 mono_TypedReference_ToObject (MonoTypedRef tref)
7292 {
7293         MONO_ARCH_SAVE_REGS;
7294
7295         if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7296                 MonoObject** objp = tref.value;
7297                 return *objp;
7298         }
7299
7300         return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7301 }
7302
7303 ICALL_EXPORT MonoObject*
7304 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7305 {
7306         MONO_ARCH_SAVE_REGS;
7307
7308         if (MONO_TYPE_IS_REFERENCE (type)) {
7309                 MonoObject** objp = value;
7310                 return *objp;
7311         }
7312
7313         return mono_value_box (mono_domain_get (), klass, value);
7314 }
7315
7316 static void
7317 prelink_method (MonoMethod *method)
7318 {
7319         const char *exc_class, *exc_arg;
7320         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7321                 return;
7322         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7323         if (exc_class) {
7324                 mono_raise_exception( 
7325                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7326         }
7327         /* create the wrapper, too? */
7328 }
7329
7330 ICALL_EXPORT void
7331 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7332 {
7333         MONO_ARCH_SAVE_REGS;
7334         prelink_method (method->method);
7335 }
7336
7337 ICALL_EXPORT void
7338 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7339 {
7340         MonoClass *klass = mono_class_from_mono_type (type->type);
7341         MonoMethod* m;
7342         gpointer iter = NULL;
7343         MONO_ARCH_SAVE_REGS;
7344
7345         mono_class_init_or_throw (klass);
7346
7347         while ((m = mono_class_get_methods (klass, &iter)))
7348                 prelink_method (m);
7349 }
7350
7351 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7352 ICALL_EXPORT void
7353 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7354                                             gint32 const **exponents,
7355                                             gunichar2 const **digitLowerTable,
7356                                             gunichar2 const **digitUpperTable,
7357                                             gint64 const **tenPowersList,
7358                                             gint32 const **decHexDigits)
7359 {
7360         *mantissas = Formatter_MantissaBitsTable;
7361         *exponents = Formatter_TensExponentTable;
7362         *digitLowerTable = Formatter_DigitLowerTable;
7363         *digitUpperTable = Formatter_DigitUpperTable;
7364         *tenPowersList = Formatter_TenPowersList;
7365         *decHexDigits = Formatter_DecHexDigits;
7366 }
7367
7368 ICALL_EXPORT void
7369 get_category_data (int version,
7370                    guint8 const **category_data,
7371                    guint16 const **category_astral_index)
7372 {
7373         *category_astral_index = NULL;
7374
7375 #ifndef DISABLE_NET_4_0
7376         if (version == 4) {
7377                 *category_data = CategoryData_v4;
7378 #ifndef DISABLE_ASTRAL
7379                 *category_astral_index = CategoryData_v4_astral_index;
7380 #endif
7381                 return;
7382         }
7383 #endif
7384
7385         *category_data = CategoryData_v2;
7386 #ifndef DISABLE_ASTRAL
7387         *category_astral_index = CategoryData_v2_astral_index;
7388 #endif
7389 }
7390
7391 /* These parameters are "readonly" in corlib/System/Char.cs */
7392 ICALL_EXPORT void
7393 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7394                                             guint8 const **category_data,
7395                                             guint16 const **category_astral_index,
7396                                             guint8 const **numeric_data,
7397                                             gdouble const **numeric_data_values,
7398                                             guint16 const **to_lower_data_low,
7399                                             guint16 const **to_lower_data_high,
7400                                             guint16 const **to_upper_data_low,
7401                                             guint16 const **to_upper_data_high)
7402 {
7403         get_category_data (category_data_version, category_data, category_astral_index);
7404         *numeric_data = NumericData;
7405         *numeric_data_values = NumericDataValues;
7406         *to_lower_data_low = ToLowerDataLow;
7407         *to_lower_data_high = ToLowerDataHigh;
7408         *to_upper_data_low = ToUpperDataLow;
7409         *to_upper_data_high = ToUpperDataHigh;
7410 }
7411
7412 /*
7413  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7414  * and avoid useless allocations.
7415  * 
7416  * MAY THROW
7417  */
7418 static MonoArray*
7419 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7420 {
7421         MonoArray *res;
7422         int i, count = 0;
7423         for (i = 0; i < type->num_mods; ++i) {
7424                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7425                         count++;
7426         }
7427         if (!count)
7428                 return NULL;
7429         res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7430         count = 0;
7431         for (i = 0; i < type->num_mods; ++i) {
7432                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7433                         MonoError error;
7434                         MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
7435                         mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */ 
7436                         mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7437                         count++;
7438                 }
7439         }
7440         return res;
7441 }
7442
7443 ICALL_EXPORT MonoArray*
7444 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7445 {
7446         MonoType *type = param->ClassImpl->type;
7447         MonoClass *member_class = mono_object_class (param->MemberImpl);
7448         MonoMethod *method = NULL;
7449         MonoImage *image;
7450         int pos;
7451         MonoMethodSignature *sig;
7452
7453         if (mono_class_is_reflection_method_or_constructor (member_class)) {
7454                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7455                 method = rmethod->method;
7456         } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7457                 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7458                 if (!(method = prop->property->get))
7459                         method = prop->property->set;
7460                 g_assert (method);      
7461         } else {
7462                 char *type_name = mono_type_get_full_name (member_class);
7463                 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7464                 MonoException *ex = mono_get_exception_not_supported  (msg);
7465                 g_free (type_name);
7466                 g_free (msg);
7467                 mono_raise_exception (ex);
7468         }
7469
7470         image = method->klass->image;
7471         pos = param->PositionImpl;
7472         sig = mono_method_signature (method);
7473         if (pos == -1)
7474                 type = sig->ret;
7475         else
7476                 type = sig->params [pos];
7477
7478         return type_array_from_modifiers (image, type, optional);
7479 }
7480
7481 static MonoType*
7482 get_property_type (MonoProperty *prop)
7483 {
7484         MonoMethodSignature *sig;
7485         if (prop->get) {
7486                 sig = mono_method_signature (prop->get);
7487                 return sig->ret;
7488         } else if (prop->set) {
7489                 sig = mono_method_signature (prop->set);
7490                 return sig->params [sig->param_count - 1];
7491         }
7492         return NULL;
7493 }
7494
7495 ICALL_EXPORT MonoArray*
7496 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7497 {
7498         MonoType *type = get_property_type (property->property);
7499         MonoImage *image = property->klass->image;
7500
7501         if (!type)
7502                 return NULL;
7503         return type_array_from_modifiers (image, type, optional);
7504 }
7505
7506 /*
7507  *Construct a MonoType suited to be used to decode a constant blob object.
7508  *
7509  * @type is the target type which will be constructed
7510  * @blob_type is the blob type, for example, that comes from the constant table
7511  * @real_type is the expected constructed type.
7512  */
7513 static void
7514 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7515 {
7516         type->type = blob_type;
7517         type->data.klass = NULL;
7518         if (blob_type == MONO_TYPE_CLASS)
7519                 type->data.klass = mono_defaults.object_class;
7520         else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7521                 /* For enums, we need to use the base type */
7522                 type->type = MONO_TYPE_VALUETYPE;
7523                 type->data.klass = mono_class_from_mono_type (real_type);
7524         } else
7525                 type->data.klass = mono_class_from_mono_type (real_type);
7526 }
7527
7528 ICALL_EXPORT MonoObject*
7529 property_info_get_default_value (MonoReflectionProperty *property)
7530 {
7531         MonoType blob_type;
7532         MonoProperty *prop = property->property;
7533         MonoType *type = get_property_type (prop);
7534         MonoDomain *domain = mono_object_domain (property); 
7535         MonoTypeEnum def_type;
7536         const char *def_value;
7537         MonoObject *o;
7538
7539         mono_class_init (prop->parent);
7540
7541         if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7542                 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7543
7544         def_value = mono_class_get_property_default_value (prop, &def_type);
7545
7546         mono_type_from_blob_type (&blob_type, def_type, type);
7547         o = mono_get_object_from_blob (domain, &blob_type, def_value);
7548
7549         return o;
7550 }
7551
7552 ICALL_EXPORT MonoBoolean
7553 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7554 {
7555         MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7556         MonoCustomAttrInfo *cinfo;
7557         gboolean found;
7558
7559         mono_class_init_or_throw (attr_class);
7560
7561         cinfo = mono_reflection_get_custom_attrs_info (obj);
7562         if (!cinfo)
7563                 return FALSE;
7564         found = mono_custom_attrs_has_attr (cinfo, attr_class);
7565         if (!cinfo->cached)
7566                 mono_custom_attrs_free (cinfo);
7567         return found;
7568 }
7569
7570 ICALL_EXPORT MonoArray*
7571 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7572 {
7573         MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7574         MonoArray *res;
7575         MonoError error;
7576
7577         if (attr_class)
7578                 mono_class_init_or_throw (attr_class);
7579
7580         res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7581         mono_error_raise_exception (&error);
7582
7583         if (mono_loader_get_last_error ()) {
7584                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7585                 g_assert_not_reached ();
7586                 /* Not reached */
7587                 return NULL;
7588         } else {
7589                 return res;
7590         }
7591 }
7592
7593 ICALL_EXPORT MonoString*
7594 ves_icall_Mono_Runtime_GetDisplayName (void)
7595 {
7596         char *info;
7597         MonoString *display_name;
7598
7599         info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7600         display_name = mono_string_new (mono_domain_get (), info);
7601         g_free (info);
7602         return display_name;
7603 }
7604
7605 ICALL_EXPORT MonoString*
7606 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7607 {
7608         MonoString *message;
7609         guint32 ret;
7610         gunichar2 buf[256];
7611         
7612         ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7613                              FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7614                              buf, 255, NULL);
7615         if (ret == 0) {
7616                 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7617         } else {
7618                 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7619         }
7620         
7621         return message;
7622 }
7623
7624 const static guchar
7625 dbase64 [] = {
7626         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7627         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7628         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7629         52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7630         128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7631         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7632         128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7633         41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7634 };
7635
7636 static MonoArray *
7637 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7638 {
7639         gint ignored;
7640         gint i;
7641         gunichar2 c;
7642         gunichar2 last, prev_last, prev2_last;
7643         gint olength;
7644         MonoArray *result;
7645         guchar *res_ptr;
7646         gint a [4], b [4];
7647         MonoException *exc;
7648
7649         int havePadding = 0;
7650         ignored = 0;
7651         last = prev_last = 0, prev2_last = 0;
7652         for (i = 0; i < ilength; i++) {
7653                 c = start [i];
7654                 if (c >= sizeof (dbase64)) {
7655                         exc = mono_exception_from_name_msg (mono_get_corlib (),
7656                                 "System", "FormatException",
7657                                 "Invalid character found.");
7658                         mono_raise_exception (exc);
7659                 } else if (isspace (c)) {
7660                         ignored++;
7661                 } else if (havePadding && c != '=') {
7662                         exc = mono_exception_from_name_msg (mono_get_corlib (),
7663                                 "System", "FormatException",
7664                                 "Invalid character found.");
7665                         mono_raise_exception (exc);
7666                 } else {
7667                         if (c == '=') havePadding = 1;
7668                         prev2_last = prev_last;
7669                         prev_last = last;
7670                         last = c;
7671                 }
7672         }
7673
7674         olength = ilength - ignored;
7675
7676         if (allowWhitespaceOnly && olength == 0) {
7677                 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7678         }
7679
7680         if ((olength & 3) != 0 || olength <= 0) {
7681                 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7682                                         "FormatException", "Invalid length.");
7683                 mono_raise_exception (exc);
7684         }
7685
7686         if (prev2_last == '=') {
7687                 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7688                 mono_raise_exception (exc);
7689         }
7690
7691         olength = (olength * 3) / 4;
7692         if (last == '=')
7693                 olength--;
7694
7695         if (prev_last == '=')
7696                 olength--;
7697
7698         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7699         res_ptr = mono_array_addr (result, guchar, 0);
7700         for (i = 0; i < ilength; ) {
7701                 int k;
7702
7703                 for (k = 0; k < 4 && i < ilength;) {
7704                         c = start [i++];
7705                         if (isspace (c))
7706                                 continue;
7707
7708                         a [k] = (guchar) c;
7709                         if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7710                                 exc = mono_exception_from_name_msg (mono_get_corlib (),
7711                                         "System", "FormatException",
7712                                         "Invalid character found.");
7713                                 mono_raise_exception (exc);
7714                         }
7715                         k++;
7716                 }
7717
7718                 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7719                 if (a [2] != '=')
7720                         *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7721                 if (a [3] != '=')
7722                         *res_ptr++ = (b [2] << 6) | b [3];
7723
7724                 while (i < ilength && isspace (start [i]))
7725                         i++;
7726         }
7727
7728         return result;
7729 }
7730
7731 ICALL_EXPORT MonoArray *
7732 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7733 {
7734         MONO_ARCH_SAVE_REGS;
7735
7736         return base64_to_byte_array (mono_string_chars (str), 
7737                 mono_string_length (str), allowWhitespaceOnly);
7738 }
7739
7740 ICALL_EXPORT MonoArray *
7741 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7742 {
7743         MONO_ARCH_SAVE_REGS;
7744
7745         return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7746                 length, FALSE);
7747 }
7748
7749 #ifndef DISABLE_ICALL_TABLES
7750
7751 #define ICALL_TYPE(id,name,first)
7752 #define ICALL(id,name,func) Icall_ ## id,
7753
7754 enum {
7755 #include "metadata/icall-def.h"
7756         Icall_last
7757 };
7758
7759 #undef ICALL_TYPE
7760 #undef ICALL
7761 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7762 #define ICALL(id,name,func)
7763 enum {
7764 #include "metadata/icall-def.h"
7765         Icall_type_num
7766 };
7767
7768 #undef ICALL_TYPE
7769 #undef ICALL
7770 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7771 #define ICALL(id,name,func)
7772 typedef struct {
7773         guint16 first_icall;
7774 } IcallTypeDesc;
7775
7776 static const IcallTypeDesc
7777 icall_type_descs [] = {
7778 #include "metadata/icall-def.h"
7779         {Icall_last}
7780 };
7781
7782 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7783
7784 #undef ICALL_TYPE
7785 #define ICALL_TYPE(id,name,first)
7786 #undef ICALL
7787
7788 #ifdef HAVE_ARRAY_ELEM_INIT
7789 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7790 #define MSGSTRFIELD1(line) str##line
7791
7792 static const struct msgstrtn_t {
7793 #define ICALL(id,name,func)
7794 #undef ICALL_TYPE
7795 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7796 #include "metadata/icall-def.h"
7797 #undef ICALL_TYPE
7798 } icall_type_names_str = {
7799 #define ICALL_TYPE(id,name,first) (name),
7800 #include "metadata/icall-def.h"
7801 #undef ICALL_TYPE
7802 };
7803 static const guint16 icall_type_names_idx [] = {
7804 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7805 #include "metadata/icall-def.h"
7806 #undef ICALL_TYPE
7807 };
7808 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7809
7810 static const struct msgstr_t {
7811 #undef ICALL
7812 #define ICALL_TYPE(id,name,first)
7813 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7814 #include "metadata/icall-def.h"
7815 #undef ICALL
7816 } icall_names_str = {
7817 #define ICALL(id,name,func) (name),
7818 #include "metadata/icall-def.h"
7819 #undef ICALL
7820 };
7821 static const guint16 icall_names_idx [] = {
7822 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7823 #include "metadata/icall-def.h"
7824 #undef ICALL
7825 };
7826 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7827
7828 #else
7829
7830 #undef ICALL_TYPE
7831 #undef ICALL
7832 #define ICALL_TYPE(id,name,first) name,
7833 #define ICALL(id,name,func)
7834 static const char* const
7835 icall_type_names [] = {
7836 #include "metadata/icall-def.h"
7837         NULL
7838 };
7839
7840 #define icall_type_name_get(id) (icall_type_names [(id)])
7841
7842 #undef ICALL_TYPE
7843 #undef ICALL
7844 #define ICALL_TYPE(id,name,first)
7845 #define ICALL(id,name,func) name,
7846 static const char* const
7847 icall_names [] = {
7848 #include "metadata/icall-def.h"
7849         NULL
7850 };
7851 #define icall_name_get(id) icall_names [(id)]
7852
7853 #endif /* !HAVE_ARRAY_ELEM_INIT */
7854
7855 #undef ICALL_TYPE
7856 #undef ICALL
7857 #define ICALL_TYPE(id,name,first)
7858 #define ICALL(id,name,func) func,
7859 static const gconstpointer
7860 icall_functions [] = {
7861 #include "metadata/icall-def.h"
7862         NULL
7863 };
7864
7865 #ifdef ENABLE_ICALL_SYMBOL_MAP
7866 #undef ICALL_TYPE
7867 #undef ICALL
7868 #define ICALL_TYPE(id,name,first)
7869 #define ICALL(id,name,func) #func,
7870 static const gconstpointer
7871 icall_symbols [] = {
7872 #include "metadata/icall-def.h"
7873         NULL
7874 };
7875 #endif
7876
7877 #endif /* DISABLE_ICALL_TABLES */
7878
7879 static mono_mutex_t icall_mutex;
7880 static GHashTable *icall_hash = NULL;
7881 static GHashTable *jit_icall_hash_name = NULL;
7882 static GHashTable *jit_icall_hash_addr = NULL;
7883
7884 void
7885 mono_icall_init (void)
7886 {
7887 #ifndef DISABLE_ICALL_TABLES
7888         int i = 0;
7889
7890         /* check that tables are sorted: disable in release */
7891         if (TRUE) {
7892                 int j;
7893                 const char *prev_class = NULL;
7894                 const char *prev_method;
7895                 
7896                 for (i = 0; i < Icall_type_num; ++i) {
7897                         const IcallTypeDesc *desc;
7898                         int num_icalls;
7899                         prev_method = NULL;
7900                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7901                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7902                         prev_class = icall_type_name_get (i);
7903                         desc = &icall_type_descs [i];
7904                         num_icalls = icall_desc_num_icalls (desc);
7905                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7906                         for (j = 0; j < num_icalls; ++j) {
7907                                 const char *methodn = icall_name_get (desc->first_icall + j);
7908                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
7909                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
7910                                 prev_method = methodn;
7911                         }
7912                 }
7913         }
7914 #endif
7915
7916         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7917         mono_mutex_init (&icall_mutex);
7918 }
7919
7920 static void
7921 mono_icall_lock (void)
7922 {
7923         mono_locks_mutex_acquire (&icall_mutex, IcallLock);
7924 }
7925
7926 static void
7927 mono_icall_unlock (void)
7928 {
7929         mono_locks_mutex_release (&icall_mutex, IcallLock);
7930 }
7931
7932 void
7933 mono_icall_cleanup (void)
7934 {
7935         g_hash_table_destroy (icall_hash);
7936         g_hash_table_destroy (jit_icall_hash_name);
7937         g_hash_table_destroy (jit_icall_hash_addr);
7938         mono_mutex_destroy (&icall_mutex);
7939 }
7940
7941 void
7942 mono_add_internal_call (const char *name, gconstpointer method)
7943 {
7944         mono_icall_lock ();
7945
7946         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7947
7948         mono_icall_unlock ();
7949 }
7950
7951 #ifndef DISABLE_ICALL_TABLES
7952
7953 #ifdef HAVE_ARRAY_ELEM_INIT
7954 static int
7955 compare_method_imap (const void *key, const void *elem)
7956 {
7957         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7958         return strcmp (key, method_name);
7959 }
7960
7961 static gpointer
7962 find_method_icall (const IcallTypeDesc *imap, const char *name)
7963 {
7964         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);
7965         if (!nameslot)
7966                 return NULL;
7967         return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7968 }
7969
7970 static int
7971 compare_class_imap (const void *key, const void *elem)
7972 {
7973         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7974         return strcmp (key, class_name);
7975 }
7976
7977 static const IcallTypeDesc*
7978 find_class_icalls (const char *name)
7979 {
7980         const guint16 *nameslot = mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7981         if (!nameslot)
7982                 return NULL;
7983         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7984 }
7985
7986 #else /* HAVE_ARRAY_ELEM_INIT */
7987
7988 static int
7989 compare_method_imap (const void *key, const void *elem)
7990 {
7991         const char** method_name = (const char**)elem;
7992         return strcmp (key, *method_name);
7993 }
7994
7995 static gpointer
7996 find_method_icall (const IcallTypeDesc *imap, const char *name)
7997 {
7998         const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7999         if (!nameslot)
8000                 return NULL;
8001         return (gpointer)icall_functions [(nameslot - icall_names)];
8002 }
8003
8004 static int
8005 compare_class_imap (const void *key, const void *elem)
8006 {
8007         const char** class_name = (const char**)elem;
8008         return strcmp (key, *class_name);
8009 }
8010
8011 static const IcallTypeDesc*
8012 find_class_icalls (const char *name)
8013 {
8014         const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8015         if (!nameslot)
8016                 return NULL;
8017         return &icall_type_descs [nameslot - icall_type_names];
8018 }
8019
8020 #endif /* HAVE_ARRAY_ELEM_INIT */
8021
8022 #endif /* DISABLE_ICALL_TABLES */
8023
8024 /* 
8025  * we should probably export this as an helper (handle nested types).
8026  * Returns the number of chars written in buf.
8027  */
8028 static int
8029 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8030 {
8031         int nspacelen, cnamelen;
8032         nspacelen = strlen (klass->name_space);
8033         cnamelen = strlen (klass->name);
8034         if (nspacelen + cnamelen + 2 > bufsize)
8035                 return 0;
8036         if (nspacelen) {
8037                 memcpy (buf, klass->name_space, nspacelen);
8038                 buf [nspacelen ++] = '.';
8039         }
8040         memcpy (buf + nspacelen, klass->name, cnamelen);
8041         buf [nspacelen + cnamelen] = 0;
8042         return nspacelen + cnamelen;
8043 }
8044
8045 #ifdef DISABLE_ICALL_TABLES
8046 static void
8047 no_icall_table (void)
8048 {
8049         g_assert_not_reached ();
8050 }
8051 #endif
8052
8053 gpointer
8054 mono_lookup_internal_call (MonoMethod *method)
8055 {
8056         char *sigstart;
8057         char *tmpsig;
8058         char mname [2048];
8059         int typelen = 0, mlen, siglen;
8060         gpointer res;
8061 #ifndef DISABLE_ICALL_TABLES
8062         const IcallTypeDesc *imap = NULL;
8063 #endif
8064
8065         g_assert (method != NULL);
8066
8067         if (method->is_inflated)
8068                 method = ((MonoMethodInflated *) method)->declaring;
8069
8070         if (method->klass->nested_in) {
8071                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8072                 if (!pos)
8073                         return NULL;
8074
8075                 mname [pos++] = '/';
8076                 mname [pos] = 0;
8077
8078                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8079                 if (!typelen)
8080                         return NULL;
8081
8082                 typelen += pos;
8083         } else {
8084                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8085                 if (!typelen)
8086                         return NULL;
8087         }
8088
8089 #ifndef DISABLE_ICALL_TABLES
8090         imap = find_class_icalls (mname);
8091 #endif
8092
8093         mname [typelen] = ':';
8094         mname [typelen + 1] = ':';
8095
8096         mlen = strlen (method->name);
8097         memcpy (mname + typelen + 2, method->name, mlen);
8098         sigstart = mname + typelen + 2 + mlen;
8099         *sigstart = 0;
8100
8101         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8102         siglen = strlen (tmpsig);
8103         if (typelen + mlen + siglen + 6 > sizeof (mname))
8104                 return NULL;
8105         sigstart [0] = '(';
8106         memcpy (sigstart + 1, tmpsig, siglen);
8107         sigstart [siglen + 1] = ')';
8108         sigstart [siglen + 2] = 0;
8109         g_free (tmpsig);
8110         
8111         mono_icall_lock ();
8112
8113         res = g_hash_table_lookup (icall_hash, mname);
8114         if (res) {
8115                 mono_icall_unlock ();;
8116                 return res;
8117         }
8118         /* try without signature */
8119         *sigstart = 0;
8120         res = g_hash_table_lookup (icall_hash, mname);
8121         if (res) {
8122                 mono_icall_unlock ();
8123                 return res;
8124         }
8125
8126 #ifdef DISABLE_ICALL_TABLES
8127         mono_icall_unlock ();
8128         /* Fail only when the result is actually used */
8129         /* mono_marshal_get_native_wrapper () depends on this */
8130         if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8131                 return ves_icall_System_String_ctor_RedirectToCreateString;
8132         else
8133                 return no_icall_table;
8134 #else
8135         /* it wasn't found in the static call tables */
8136         if (!imap) {
8137                 mono_icall_unlock ();
8138                 return NULL;
8139         }
8140         res = find_method_icall (imap, sigstart - mlen);
8141         if (res) {
8142                 mono_icall_unlock ();
8143                 return res;
8144         }
8145         /* try _with_ signature */
8146         *sigstart = '(';
8147         res = find_method_icall (imap, sigstart - mlen);
8148         if (res) {
8149                 mono_icall_unlock ();
8150                 return res;
8151         }
8152
8153         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8154         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8155         g_print ("The out of sync library is: %s\n", method->klass->image->name);
8156         g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8157         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");
8158         g_print ("If you see other errors or faults after this message they are probably related\n");
8159         g_print ("and you need to fix your mono install first.\n");
8160
8161         mono_icall_unlock ();
8162
8163         return NULL;
8164 #endif
8165 }
8166
8167 #ifdef ENABLE_ICALL_SYMBOL_MAP
8168 static int
8169 func_cmp (gconstpointer key, gconstpointer p)
8170 {
8171         return (gsize)key - (gsize)*(gsize*)p;
8172 }
8173 #endif
8174
8175 /*
8176  * mono_lookup_icall_symbol:
8177  *
8178  *   Given the icall METHOD, returns its C symbol.
8179  */
8180 const char*
8181 mono_lookup_icall_symbol (MonoMethod *m)
8182 {
8183 #ifdef DISABLE_ICALL_TABLES
8184         g_assert_not_reached ();
8185         return NULL;
8186 #else
8187 #ifdef ENABLE_ICALL_SYMBOL_MAP
8188         gpointer func;
8189         int i;
8190         gpointer slot;
8191         static gconstpointer *functions_sorted;
8192         static const char**symbols_sorted;
8193         static gboolean inited;
8194
8195         if (!inited) {
8196                 gboolean changed;
8197
8198                 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8199                 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8200                 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8201                 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8202                 /* Bubble sort the two arrays */
8203                 changed = TRUE;
8204                 while (changed) {
8205                         changed = FALSE;
8206                         for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8207                                 if (functions_sorted [i] > functions_sorted [i + 1]) {
8208                                         gconstpointer tmp;
8209
8210                                         tmp = functions_sorted [i];
8211                                         functions_sorted [i] = functions_sorted [i + 1];
8212                                         functions_sorted [i + 1] = tmp;
8213                                         tmp = symbols_sorted [i];
8214                                         symbols_sorted [i] = symbols_sorted [i + 1];
8215                                         symbols_sorted [i + 1] = tmp;
8216                                         changed = TRUE;
8217                                 }
8218                         }
8219                 }
8220         }
8221
8222         func = mono_lookup_internal_call (m);
8223         if (!func)
8224                 return NULL;
8225         slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8226         if (!slot)
8227                 return NULL;
8228         g_assert (slot);
8229         return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8230 #else
8231         fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8232         g_assert_not_reached ();
8233         return 0;
8234 #endif
8235 #endif
8236 }
8237
8238 static MonoType*
8239 type_from_typename (char *typename)
8240 {
8241         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
8242
8243         if (!strcmp (typename, "int"))
8244                 klass = mono_defaults.int_class;
8245         else if (!strcmp (typename, "ptr"))
8246                 klass = mono_defaults.int_class;
8247         else if (!strcmp (typename, "void"))
8248                 klass = mono_defaults.void_class;
8249         else if (!strcmp (typename, "int32"))
8250                 klass = mono_defaults.int32_class;
8251         else if (!strcmp (typename, "uint32"))
8252                 klass = mono_defaults.uint32_class;
8253         else if (!strcmp (typename, "int8"))
8254                 klass = mono_defaults.sbyte_class;
8255         else if (!strcmp (typename, "uint8"))
8256                 klass = mono_defaults.byte_class;
8257         else if (!strcmp (typename, "int16"))
8258                 klass = mono_defaults.int16_class;
8259         else if (!strcmp (typename, "uint16"))
8260                 klass = mono_defaults.uint16_class;
8261         else if (!strcmp (typename, "long"))
8262                 klass = mono_defaults.int64_class;
8263         else if (!strcmp (typename, "ulong"))
8264                 klass = mono_defaults.uint64_class;
8265         else if (!strcmp (typename, "float"))
8266                 klass = mono_defaults.single_class;
8267         else if (!strcmp (typename, "double"))
8268                 klass = mono_defaults.double_class;
8269         else if (!strcmp (typename, "object"))
8270                 klass = mono_defaults.object_class;
8271         else if (!strcmp (typename, "obj"))
8272                 klass = mono_defaults.object_class;
8273         else if (!strcmp (typename, "string"))
8274                 klass = mono_defaults.string_class;
8275         else if (!strcmp (typename, "bool"))
8276                 klass = mono_defaults.boolean_class;
8277         else if (!strcmp (typename, "boolean"))
8278                 klass = mono_defaults.boolean_class;
8279         else {
8280                 g_error ("%s", typename);
8281                 g_assert_not_reached ();
8282         }
8283         return &klass->byval_arg;
8284 }
8285
8286 /**
8287  * LOCKING: Take the corlib image lock.
8288  */
8289 MonoMethodSignature*
8290 mono_create_icall_signature (const char *sigstr)
8291 {
8292         gchar **parts;
8293         int i, len;
8294         gchar **tmp;
8295         MonoMethodSignature *res, *res2;
8296         MonoImage *corlib = mono_defaults.corlib;
8297
8298         mono_image_lock (corlib);
8299         res = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8300         mono_image_unlock (corlib);
8301
8302         if (res)
8303                 return res;
8304
8305         parts = g_strsplit (sigstr, " ", 256);
8306
8307         tmp = parts;
8308         len = 0;
8309         while (*tmp) {
8310                 len ++;
8311                 tmp ++;
8312         }
8313
8314         res = mono_metadata_signature_alloc (corlib, len - 1);
8315         res->pinvoke = 1;
8316
8317 #ifdef HOST_WIN32
8318         /* 
8319          * Under windows, the default pinvoke calling convention is STDCALL but
8320          * we need CDECL.
8321          */
8322         res->call_convention = MONO_CALL_C;
8323 #endif
8324
8325         res->ret = type_from_typename (parts [0]);
8326         for (i = 1; i < len; ++i) {
8327                 res->params [i - 1] = type_from_typename (parts [i]);
8328         }
8329
8330         g_strfreev (parts);
8331
8332         mono_image_lock (corlib);
8333         res2 = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8334         if (res2)
8335                 res = res2; /*Value is allocated in the image pool*/
8336         else
8337                 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8338         mono_image_unlock (corlib);
8339
8340         return res;
8341 }
8342
8343 MonoJitICallInfo *
8344 mono_find_jit_icall_by_name (const char *name)
8345 {
8346         MonoJitICallInfo *info;
8347         g_assert (jit_icall_hash_name);
8348
8349         mono_icall_lock ();
8350         info = g_hash_table_lookup (jit_icall_hash_name, name);
8351         mono_icall_unlock ();
8352         return info;
8353 }
8354
8355 MonoJitICallInfo *
8356 mono_find_jit_icall_by_addr (gconstpointer addr)
8357 {
8358         MonoJitICallInfo *info;
8359         g_assert (jit_icall_hash_addr);
8360
8361         mono_icall_lock ();
8362         info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8363         mono_icall_unlock ();
8364
8365         return info;
8366 }
8367
8368 /*
8369  * mono_get_jit_icall_info:
8370  *
8371  *   Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8372  * caller should access it while holding the icall lock.
8373  */
8374 GHashTable*
8375 mono_get_jit_icall_info (void)
8376 {
8377         return jit_icall_hash_name;
8378 }
8379
8380 /*
8381  * mono_lookup_jit_icall_symbol:
8382  *
8383  *   Given the jit icall NAME, returns its C symbol if possible, or NULL.
8384  */
8385 const char*
8386 mono_lookup_jit_icall_symbol (const char *name)
8387 {
8388         MonoJitICallInfo *info;
8389         const char *res = NULL;
8390
8391         mono_icall_lock ();
8392         info = g_hash_table_lookup (jit_icall_hash_name, name);
8393         if (info)
8394                 res = info->c_symbol;
8395         mono_icall_unlock ();
8396         return res;
8397 }
8398
8399 void
8400 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8401 {
8402         mono_icall_lock ();
8403         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8404         mono_icall_unlock ();
8405 }
8406
8407 MonoJitICallInfo *
8408 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8409 {
8410         MonoJitICallInfo *info;
8411         
8412         g_assert (func);
8413         g_assert (name);
8414
8415         mono_icall_lock ();
8416
8417         if (!jit_icall_hash_name) {
8418                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8419                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8420         }
8421
8422         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8423                 g_warning ("jit icall already defined \"%s\"\n", name);
8424                 g_assert_not_reached ();
8425         }
8426
8427         info = g_new0 (MonoJitICallInfo, 1);
8428         
8429         info->name = name;
8430         info->func = func;
8431         info->sig = sig;
8432         info->c_symbol = c_symbol;
8433
8434         if (is_save) {
8435                 info->wrapper = func;
8436         } else {
8437                 info->wrapper = NULL;
8438         }
8439
8440         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8441         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8442
8443         mono_icall_unlock ();
8444         return info;
8445 }
8446
8447 MonoJitICallInfo *
8448 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8449 {
8450         return mono_register_jit_icall_full (func, name, sig, is_save, NULL);
8451 }
8452