Merge pull request #960 from ermshiperete/ShowHelp
[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 *error)
5563 {
5564         MonoClass *klass;
5565         int table = mono_metadata_token_table (token);
5566         int index = mono_metadata_token_index (token);
5567         MonoGenericContext context;
5568         MonoClassField *field;
5569
5570         *error = ResolveTokenError_Other;
5571
5572         /* Validate token */
5573         if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5574                 *error = ResolveTokenError_BadTable;
5575                 return NULL;
5576         }
5577
5578         if (image_is_dynamic (image)) {
5579                 if (table == MONO_TABLE_FIELD)
5580                         return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5581
5582                 if (mono_memberref_is_method (image, token)) {
5583                         *error = ResolveTokenError_BadTable;
5584                         return NULL;
5585                 }
5586
5587                 init_generic_context_from_args (&context, type_args, method_args);
5588                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5589         }
5590
5591         if ((index <= 0) || (index > image->tables [table].rows)) {
5592                 *error = ResolveTokenError_OutOfRange;
5593                 return NULL;
5594         }
5595         if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5596                 *error = ResolveTokenError_BadTable;
5597                 return NULL;
5598         }
5599
5600         init_generic_context_from_args (&context, type_args, method_args);
5601         field = mono_field_from_token (image, token, &klass, &context);
5602
5603         if (mono_loader_get_last_error ())
5604                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5605         
5606         return field;
5607 }
5608
5609
5610 ICALL_EXPORT MonoObject*
5611 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5612 {
5613         int table = mono_metadata_token_table (token);
5614
5615         *error = ResolveTokenError_Other;
5616
5617         switch (table) {
5618         case MONO_TABLE_TYPEDEF:
5619         case MONO_TABLE_TYPEREF:
5620         case MONO_TABLE_TYPESPEC: {
5621                 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5622                 if (t)
5623                         return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5624                 else
5625                         return NULL;
5626         }
5627         case MONO_TABLE_METHOD:
5628         case MONO_TABLE_METHODSPEC: {
5629                 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5630                 if (m)
5631                         return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5632                 else
5633                         return NULL;
5634         }               
5635         case MONO_TABLE_FIELD: {
5636                 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5637                 if (f)
5638                         return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5639                 else
5640                         return NULL;
5641         }
5642         case MONO_TABLE_MEMBERREF:
5643                 if (mono_memberref_is_method (image, token)) {
5644                         MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5645                         if (m)
5646                                 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5647                         else
5648                                 return NULL;
5649                 }
5650                 else {
5651                         MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5652                         if (f)
5653                                 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5654                         else
5655                                 return NULL;
5656                 }
5657                 break;
5658
5659         default:
5660                 *error = ResolveTokenError_BadTable;
5661         }
5662
5663         return NULL;
5664 }
5665
5666 ICALL_EXPORT MonoArray*
5667 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5668 {
5669         int table = mono_metadata_token_table (token);
5670         int idx = mono_metadata_token_index (token);
5671         MonoTableInfo *tables = image->tables;
5672         guint32 sig, len;
5673         const char *ptr;
5674         MonoArray *res;
5675
5676         *error = ResolveTokenError_OutOfRange;
5677
5678         /* FIXME: Support other tables ? */
5679         if (table != MONO_TABLE_STANDALONESIG)
5680                 return NULL;
5681
5682         if (image_is_dynamic (image))
5683                 return NULL;
5684
5685         if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5686                 return NULL;
5687
5688         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5689
5690         ptr = mono_metadata_blob_heap (image, sig);
5691         len = mono_metadata_decode_blob_size (ptr, &ptr);
5692
5693         res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5694         memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5695         return res;
5696 }
5697
5698 ICALL_EXPORT MonoReflectionType*
5699 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5700 {
5701         MonoClass *klass;
5702         int isbyref = 0, rank;
5703         char *str = mono_string_to_utf8 (smodifiers);
5704         char *p;
5705
5706         MONO_ARCH_SAVE_REGS;
5707
5708         klass = mono_class_from_mono_type (tb->type.type);
5709         p = str;
5710         /* logic taken from mono_reflection_parse_type(): keep in sync */
5711         while (*p) {
5712                 switch (*p) {
5713                 case '&':
5714                         if (isbyref) { /* only one level allowed by the spec */
5715                                 g_free (str);
5716                                 return NULL;
5717                         }
5718                         isbyref = 1;
5719                         p++;
5720                         g_free (str);
5721                         return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5722                         break;
5723                 case '*':
5724                         klass = mono_ptr_class_get (&klass->byval_arg);
5725                         mono_class_init (klass);
5726                         p++;
5727                         break;
5728                 case '[':
5729                         rank = 1;
5730                         p++;
5731                         while (*p) {
5732                                 if (*p == ']')
5733                                         break;
5734                                 if (*p == ',')
5735                                         rank++;
5736                                 else if (*p != '*') { /* '*' means unknown lower bound */
5737                                         g_free (str);
5738                                         return NULL;
5739                                 }
5740                                 ++p;
5741                         }
5742                         if (*p != ']') {
5743                                 g_free (str);
5744                                 return NULL;
5745                         }
5746                         p++;
5747                         klass = mono_array_class_get (klass, rank);
5748                         mono_class_init (klass);
5749                         break;
5750                 default:
5751                         break;
5752                 }
5753         }
5754         g_free (str);
5755         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5756 }
5757
5758 ICALL_EXPORT MonoBoolean
5759 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5760 {
5761         MonoType *type;
5762         MonoBoolean res;
5763
5764         MONO_ARCH_SAVE_REGS;
5765
5766         type = t->type;
5767         res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5768
5769         return res;
5770 }
5771
5772 static void
5773 check_for_invalid_type (MonoClass *klass)
5774 {
5775         char *name;
5776         MonoString *str;
5777         if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5778                 return;
5779
5780         name = mono_type_get_full_name (klass);
5781         str =  mono_string_new (mono_domain_get (), name);
5782         g_free (name);
5783         mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5784
5785 }
5786 ICALL_EXPORT MonoReflectionType *
5787 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5788 {
5789         MonoClass *klass, *aklass;
5790
5791         MONO_ARCH_SAVE_REGS;
5792
5793         klass = mono_class_from_mono_type (type->type);
5794         check_for_invalid_type (klass);
5795
5796         if (rank == 0) //single dimentional array
5797                 aklass = mono_array_class_get (klass, 1);
5798         else
5799                 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5800
5801         return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5802 }
5803
5804 ICALL_EXPORT MonoReflectionType *
5805 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5806 {
5807         MonoClass *klass;
5808
5809         MONO_ARCH_SAVE_REGS;
5810
5811         klass = mono_class_from_mono_type (type->type);
5812         mono_class_init_or_throw (klass);
5813         check_for_invalid_type (klass);
5814
5815         return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5816 }
5817
5818 ICALL_EXPORT MonoReflectionType *
5819 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5820 {
5821         MonoClass *klass, *pklass;
5822
5823         klass = mono_class_from_mono_type (type->type);
5824         mono_class_init_or_throw (klass);
5825         check_for_invalid_type (klass);
5826
5827         pklass = mono_ptr_class_get (type->type);
5828
5829         return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5830 }
5831
5832 ICALL_EXPORT MonoObject *
5833 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5834                                                    MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5835 {
5836         MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5837         MonoObject *delegate;
5838         gpointer func;
5839         MonoMethod *method = info->method;
5840
5841         MONO_ARCH_SAVE_REGS;
5842
5843         mono_class_init_or_throw (delegate_class);
5844
5845         mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5846
5847         if (mono_security_core_clr_enabled ()) {
5848                 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5849                         return NULL;
5850         }
5851
5852         delegate = mono_object_new (mono_object_domain (type), delegate_class);
5853
5854         if (method_is_dynamic (method)) {
5855                 /* Creating a trampoline would leak memory */
5856                 func = mono_compile_method (method);
5857         } else {
5858                 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5859                         method = mono_object_get_virtual_method (target, method);
5860                 func = mono_create_ftnptr (mono_domain_get (),
5861                         mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5862         }
5863
5864         mono_delegate_ctor_with_method (delegate, target, func, method);
5865
5866         return delegate;
5867 }
5868
5869 ICALL_EXPORT void
5870 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5871 {
5872         /* Reset the invoke impl to the default one */
5873         this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5874 }
5875
5876 /*
5877  * Magic number to convert a time which is relative to
5878  * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5879  */
5880 #define EPOCH_ADJUST    ((guint64)62135596800LL)
5881
5882 /*
5883  * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5884  */
5885 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5886
5887 #ifdef HOST_WIN32
5888 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5889 static void
5890 convert_to_absolute_date(SYSTEMTIME *date)
5891 {
5892 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5893         static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5894         static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5895         /* from the calendar FAQ */
5896         int a = (14 - date->wMonth) / 12;
5897         int y = date->wYear - a;
5898         int m = date->wMonth + 12 * a - 2;
5899         int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5900
5901         /* d is now the day of the week for the first of the month (0 == Sunday) */
5902
5903         int day_of_week = date->wDayOfWeek;
5904
5905         /* set day_in_month to the first day in the month which falls on day_of_week */    
5906         int day_in_month = 1 + (day_of_week - d);
5907         if (day_in_month <= 0)
5908                 day_in_month += 7;
5909
5910         /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5911         date->wDay = day_in_month + (date->wDay - 1) * 7;
5912         if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5913                 date->wDay -= 7;
5914 }
5915 #endif
5916
5917 #ifndef HOST_WIN32
5918 /*
5919  * Return's the offset from GMT of a local time.
5920  * 
5921  *  tm is a local time
5922  *  t  is the same local time as seconds.
5923  */
5924 static int 
5925 gmt_offset(struct tm *tm, time_t t)
5926 {
5927 #if defined (HAVE_TM_GMTOFF)
5928         return tm->tm_gmtoff;
5929 #else
5930         struct tm g;
5931         time_t t2;
5932         g = *gmtime(&t);
5933         g.tm_isdst = tm->tm_isdst;
5934         t2 = mktime(&g);
5935         return (int)difftime(t, t2);
5936 #endif
5937 }
5938 #endif
5939 /*
5940  * This is heavily based on zdump.c from glibc 2.2.
5941  *
5942  *  * data[0]:  start of daylight saving time (in DateTime ticks).
5943  *  * data[1]:  end of daylight saving time (in DateTime ticks).
5944  *  * data[2]:  utcoffset (in TimeSpan ticks).
5945  *  * data[3]:  additional offset when daylight saving (in TimeSpan ticks).
5946  *  * name[0]:  name of this timezone when not daylight saving.
5947  *  * name[1]:  name of this timezone when daylight saving.
5948  *
5949  *  FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5950  *         the class library allows years between 1 and 9999.
5951  *
5952  *  Returns true on success and zero on failure.
5953  */
5954 ICALL_EXPORT guint32
5955 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5956 {
5957 #ifndef HOST_WIN32
5958         MonoDomain *domain = mono_domain_get ();
5959         struct tm start, tt;
5960         time_t t;
5961
5962         long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
5963         int day, transitioned;
5964         char tzone [64];
5965
5966         gmtoff_st = gmtoff_ds = transitioned = 0;
5967
5968         MONO_ARCH_SAVE_REGS;
5969
5970         MONO_CHECK_ARG_NULL (data);
5971         MONO_CHECK_ARG_NULL (names);
5972
5973         mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5974         mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5975
5976         /* 
5977          * no info is better than crashing: we'll need our own tz data
5978          * to make this work properly, anyway. The range is probably
5979          * reduced to 1970 .. 2037 because that is what mktime is
5980          * guaranteed to support (we get into an infinite loop
5981          * otherwise).
5982          */
5983
5984         memset (&start, 0, sizeof (start));
5985
5986         start.tm_mday = 1;
5987         start.tm_year = year-1900;
5988
5989         t = mktime (&start);
5990
5991         if ((year < 1970) || (year > 2037) || (t == -1)) {
5992                 t = time (NULL);
5993                 tt = *localtime (&t);
5994                 strftime (tzone, sizeof (tzone), "%Z", &tt);
5995                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5996                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5997                 return 1;
5998         }
5999
6000         gmtoff = gmt_offset (&start, t);
6001
6002         /* For each day of the year, calculate the tm_gmtoff. */
6003         for (day = 0; day < 365 && transitioned < 2; day++) {
6004
6005                 t += 3600*24;
6006                 tt = *localtime (&t);
6007
6008         gmtoff_after = gmt_offset(&tt, t);
6009
6010                 /* Daylight saving starts or ends here. */
6011                 if (gmtoff_after != gmtoff) {
6012                         struct tm tt1;
6013                         time_t t1;
6014
6015                         /* Try to find the exact hour when daylight saving starts/ends. */
6016                         t1 = t;
6017                         do {
6018                                 t1 -= 3600;
6019                                 tt1 = *localtime (&t1);
6020                         } while (gmt_offset (&tt1, t1) != gmtoff);
6021
6022                         /* Try to find the exact minute when daylight saving starts/ends. */
6023                         do {
6024                                 t1 += 60;
6025                                 tt1 = *localtime (&t1);
6026                         } while (gmt_offset (&tt1, t1) == gmtoff);
6027                         t1+=gmtoff;
6028                         strftime (tzone, sizeof (tzone), "%Z", &tt);
6029                         
6030                         /* Write data, if we're already in daylight saving, we're done. */
6031                         if (tt.tm_isdst) {
6032                                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6033                                 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6034                                 if (gmtoff_ds == 0) {
6035                                         gmtoff_st = gmtoff;
6036                                         gmtoff_ds = gmtoff_after;
6037                                 }
6038                                 transitioned++;
6039                         } else {
6040                                 time_t te;
6041                                 te = mktime (&tt);
6042                                 
6043                                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6044                                 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6045                                 if (gmtoff_ds == 0) {
6046                                         gmtoff_st = gmtoff_after;
6047                                         gmtoff_ds = gmtoff;
6048                                 }
6049                                 transitioned++;
6050                         }
6051
6052                         /* This is only set once when we enter daylight saving. */
6053                         if (tt1.tm_isdst) {
6054                                 mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
6055                                 mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
6056                         }
6057                         gmtoff = gmt_offset (&tt, t);
6058                 }
6059         }
6060
6061         if (transitioned < 2) {
6062                 strftime (tzone, sizeof (tzone), "%Z", &tt);
6063                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6064                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6065                 mono_array_set ((*data), gint64, 0, 0);
6066                 mono_array_set ((*data), gint64, 1, 0);
6067                 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6068                 mono_array_set ((*data), gint64, 3, 0);
6069         }
6070
6071         return 1;
6072 #else
6073         MonoDomain *domain = mono_domain_get ();
6074         TIME_ZONE_INFORMATION tz_info;
6075         FILETIME ft;
6076         int i;
6077         int err, tz_id;
6078
6079         tz_id = GetTimeZoneInformation (&tz_info);
6080         if (tz_id == TIME_ZONE_ID_INVALID)
6081                 return 0;
6082
6083         MONO_CHECK_ARG_NULL (data);
6084         MONO_CHECK_ARG_NULL (names);
6085
6086         mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6087         mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6088
6089         for (i = 0; i < 32; ++i)
6090                 if (!tz_info.DaylightName [i])
6091                         break;
6092         mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6093         for (i = 0; i < 32; ++i)
6094                 if (!tz_info.StandardName [i])
6095                         break;
6096         mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6097
6098         if ((year <= 1601) || (year > 30827)) {
6099                 /*
6100                  * According to MSDN, the MS time functions can't handle dates outside
6101                  * this interval.
6102                  */
6103                 return 1;
6104         }
6105
6106         /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6107         if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6108                 tz_info.StandardDate.wYear = year;
6109                 convert_to_absolute_date(&tz_info.StandardDate);
6110                 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6111                 //g_assert(err);
6112                 if (err == 0)
6113                         return 0;
6114                 
6115                 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6116                 tz_info.DaylightDate.wYear = year;
6117                 convert_to_absolute_date(&tz_info.DaylightDate);
6118                 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6119                 //g_assert(err);
6120                 if (err == 0)
6121                         return 0;
6122                 
6123                 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6124         }
6125         mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6126         mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6127
6128         return 1;
6129 #endif
6130 }
6131
6132 /* System.Buffer */
6133
6134 static inline gint32 
6135 mono_array_get_byte_length (MonoArray *array)
6136 {
6137         MonoClass *klass;
6138         int length;
6139         int i;
6140
6141         klass = array->obj.vtable->klass;
6142
6143         if (array->bounds == NULL)
6144                 length = array->max_length;
6145         else {
6146                 length = 1;
6147                 for (i = 0; i < klass->rank; ++ i)
6148                         length *= array->bounds [i].length;
6149         }
6150
6151         switch (klass->element_class->byval_arg.type) {
6152         case MONO_TYPE_I1:
6153         case MONO_TYPE_U1:
6154         case MONO_TYPE_BOOLEAN:
6155                 return length;
6156         case MONO_TYPE_I2:
6157         case MONO_TYPE_U2:
6158         case MONO_TYPE_CHAR:
6159                 return length << 1;
6160         case MONO_TYPE_I4:
6161         case MONO_TYPE_U4:
6162         case MONO_TYPE_R4:
6163                 return length << 2;
6164         case MONO_TYPE_I:
6165         case MONO_TYPE_U:
6166                 return length * sizeof (gpointer);
6167         case MONO_TYPE_I8:
6168         case MONO_TYPE_U8:
6169         case MONO_TYPE_R8:
6170                 return length << 3;
6171         default:
6172                 return -1;
6173         }
6174 }
6175
6176 ICALL_EXPORT gint32 
6177 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array) 
6178 {
6179         MONO_ARCH_SAVE_REGS;
6180
6181         return mono_array_get_byte_length (array);
6182 }
6183
6184 ICALL_EXPORT gint8 
6185 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx) 
6186 {
6187         MONO_ARCH_SAVE_REGS;
6188
6189         return mono_array_get (array, gint8, idx);
6190 }
6191
6192 ICALL_EXPORT void 
6193 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value) 
6194 {
6195         MONO_ARCH_SAVE_REGS;
6196
6197         mono_array_set (array, gint8, idx, value);
6198 }
6199
6200 ICALL_EXPORT MonoBoolean
6201 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count) 
6202 {
6203         guint8 *src_buf, *dest_buf;
6204
6205         MONO_ARCH_SAVE_REGS;
6206
6207         /* This is called directly from the class libraries without going through the managed wrapper */
6208         MONO_CHECK_ARG_NULL (src);
6209         MONO_CHECK_ARG_NULL (dest);
6210
6211         /* watch out for integer overflow */
6212         if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6213                 return FALSE;
6214
6215         src_buf = (guint8 *)src->vector + src_offset;
6216         dest_buf = (guint8 *)dest->vector + dest_offset;
6217
6218         if (src != dest)
6219                 memcpy (dest_buf, src_buf, count);
6220         else
6221                 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6222
6223         return TRUE;
6224 }
6225
6226 #ifndef DISABLE_REMOTING
6227 ICALL_EXPORT MonoObject *
6228 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6229 {
6230         MonoDomain *domain = mono_object_domain (this); 
6231         MonoObject *res;
6232         MonoRealProxy *rp = ((MonoRealProxy *)this);
6233         MonoTransparentProxy *tp;
6234         MonoType *type;
6235         MonoClass *klass;
6236
6237         MONO_ARCH_SAVE_REGS;
6238
6239         res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6240         tp = (MonoTransparentProxy*) res;
6241         
6242         MONO_OBJECT_SETREF (tp, rp, rp);
6243         type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6244         klass = mono_class_from_mono_type (type);
6245
6246         tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6247         tp->remote_class = mono_remote_class (domain, class_name, klass);
6248
6249         res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6250         return res;
6251 }
6252
6253 ICALL_EXPORT MonoReflectionType *
6254 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6255 {
6256         return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6257 }
6258 #endif
6259
6260 /* System.Environment */
6261
6262 MonoString*
6263 ves_icall_System_Environment_get_UserName (void)
6264 {
6265         MONO_ARCH_SAVE_REGS;
6266
6267         /* using glib is more portable */
6268         return mono_string_new (mono_domain_get (), g_get_user_name ());
6269 }
6270
6271
6272 ICALL_EXPORT MonoString *
6273 ves_icall_System_Environment_get_MachineName (void)
6274 {
6275 #if defined (HOST_WIN32)
6276         gunichar2 *buf;
6277         guint32 len;
6278         MonoString *result;
6279
6280         len = MAX_COMPUTERNAME_LENGTH + 1;
6281         buf = g_new (gunichar2, len);
6282
6283         result = NULL;
6284         if (GetComputerName (buf, (PDWORD) &len))
6285                 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6286
6287         g_free (buf);
6288         return result;
6289 #elif !defined(DISABLE_SOCKETS)
6290         gchar buf [256];
6291         MonoString *result;
6292
6293         if (gethostname (buf, sizeof (buf)) == 0)
6294                 result = mono_string_new (mono_domain_get (), buf);
6295         else
6296                 result = NULL;
6297         
6298         return result;
6299 #else
6300         return mono_string_new (mono_domain_get (), "mono");
6301 #endif
6302 }
6303
6304 ICALL_EXPORT int
6305 ves_icall_System_Environment_get_Platform (void)
6306 {
6307 #if defined (TARGET_WIN32)
6308         /* Win32NT */
6309         return 2;
6310 #elif defined(__MACH__)
6311         /* OSX */
6312         //
6313         // Notice that the value is hidden from user code, and only exposed
6314         // to mscorlib.   This is due to Mono's Unix/MacOS code predating the
6315         // define and making assumptions based on Unix/128/4 values before there
6316         // was a MacOS define.    Lots of code would assume that not-Unix meant
6317         // Windows, but in this case, it would be OSX. 
6318         //
6319         return 6;
6320 #else
6321         /* Unix */
6322         return 4;
6323 #endif
6324 }
6325
6326 ICALL_EXPORT MonoString *
6327 ves_icall_System_Environment_get_NewLine (void)
6328 {
6329         MONO_ARCH_SAVE_REGS;
6330
6331 #if defined (HOST_WIN32)
6332         return mono_string_new (mono_domain_get (), "\r\n");
6333 #else
6334         return mono_string_new (mono_domain_get (), "\n");
6335 #endif
6336 }
6337
6338 ICALL_EXPORT MonoString *
6339 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6340 {
6341         const gchar *value;
6342         gchar *utf8_name;
6343
6344         MONO_ARCH_SAVE_REGS;
6345
6346         if (name == NULL)
6347                 return NULL;
6348
6349         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6350         value = g_getenv (utf8_name);
6351
6352         g_free (utf8_name);
6353
6354         if (value == 0)
6355                 return NULL;
6356         
6357         return mono_string_new (mono_domain_get (), value);
6358 }
6359
6360 /*
6361  * There is no standard way to get at environ.
6362  */
6363 #ifndef _MSC_VER
6364 #ifndef __MINGW32_VERSION
6365 #if defined(__APPLE__) && !defined (__arm__)
6366 /* Apple defines this in crt_externs.h but doesn't provide that header for 
6367  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
6368  * in fact exist on all implementations (so far) 
6369  */
6370 gchar ***_NSGetEnviron(void);
6371 #define environ (*_NSGetEnviron())
6372 #else
6373 extern
6374 char **environ;
6375 #endif
6376 #endif
6377 #endif
6378
6379 ICALL_EXPORT MonoArray *
6380 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6381 {
6382 #ifdef HOST_WIN32
6383         MonoArray *names;
6384         MonoDomain *domain;
6385         MonoString *str;
6386         WCHAR* env_strings;
6387         WCHAR* env_string;
6388         WCHAR* equal_str;
6389         int n = 0;
6390
6391         env_strings = GetEnvironmentStrings();
6392
6393         if (env_strings) {
6394                 env_string = env_strings;
6395                 while (*env_string != '\0') {
6396                 /* weird case that MS seems to skip */
6397                         if (*env_string != '=')
6398                                 n++;
6399                         while (*env_string != '\0')
6400                                 env_string++;
6401                         env_string++;
6402                 }
6403         }
6404
6405         domain = mono_domain_get ();
6406         names = mono_array_new (domain, mono_defaults.string_class, n);
6407
6408         if (env_strings) {
6409                 n = 0;
6410                 env_string = env_strings;
6411                 while (*env_string != '\0') {
6412                         /* weird case that MS seems to skip */
6413                         if (*env_string != '=') {
6414                                 equal_str = wcschr(env_string, '=');
6415                                 g_assert(equal_str);
6416                                 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6417                                 mono_array_setref (names, n, str);
6418                                 n++;
6419                         }
6420                         while (*env_string != '\0')
6421                                 env_string++;
6422                         env_string++;
6423                 }
6424
6425                 FreeEnvironmentStrings (env_strings);
6426         }
6427
6428         return names;
6429
6430 #else
6431         MonoArray *names;
6432         MonoDomain *domain;
6433         MonoString *str;
6434         gchar **e, **parts;
6435         int n;
6436
6437         MONO_ARCH_SAVE_REGS;
6438
6439         n = 0;
6440         for (e = environ; *e != 0; ++ e)
6441                 ++ n;
6442
6443         domain = mono_domain_get ();
6444         names = mono_array_new (domain, mono_defaults.string_class, n);
6445
6446         n = 0;
6447         for (e = environ; *e != 0; ++ e) {
6448                 parts = g_strsplit (*e, "=", 2);
6449                 if (*parts != 0) {
6450                         str = mono_string_new (domain, *parts);
6451                         mono_array_setref (names, n, str);
6452                 }
6453
6454                 g_strfreev (parts);
6455
6456                 ++ n;
6457         }
6458
6459         return names;
6460 #endif
6461 }
6462
6463 /*
6464  * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6465  */
6466 #if !GLIB_CHECK_VERSION(2,4,0)
6467 #define g_setenv(a,b,c)   setenv(a,b,c)
6468 #define g_unsetenv(a) unsetenv(a)
6469 #endif
6470
6471 ICALL_EXPORT void
6472 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6473 {
6474 #ifdef HOST_WIN32
6475         gunichar2 *utf16_name, *utf16_value;
6476 #else
6477         gchar *utf8_name, *utf8_value;
6478         MonoError error;
6479 #endif
6480
6481         MONO_ARCH_SAVE_REGS;
6482         
6483 #ifdef HOST_WIN32
6484         utf16_name = mono_string_to_utf16 (name);
6485         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6486                 SetEnvironmentVariable (utf16_name, NULL);
6487                 g_free (utf16_name);
6488                 return;
6489         }
6490
6491         utf16_value = mono_string_to_utf16 (value);
6492
6493         SetEnvironmentVariable (utf16_name, utf16_value);
6494
6495         g_free (utf16_name);
6496         g_free (utf16_value);
6497 #else
6498         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6499
6500         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6501                 g_unsetenv (utf8_name);
6502                 g_free (utf8_name);
6503                 return;
6504         }
6505
6506         utf8_value = mono_string_to_utf8_checked (value, &error);
6507         if (!mono_error_ok (&error)) {
6508                 g_free (utf8_name);
6509                 mono_error_raise_exception (&error);
6510         }
6511         g_setenv (utf8_name, utf8_value, TRUE);
6512
6513         g_free (utf8_name);
6514         g_free (utf8_value);
6515 #endif
6516 }
6517
6518 ICALL_EXPORT void
6519 ves_icall_System_Environment_Exit (int result)
6520 {
6521         MONO_ARCH_SAVE_REGS;
6522
6523         mono_environment_exitcode_set (result);
6524
6525 /* FIXME: There are some cleanup hangs that should be worked out, but
6526  * if the program is going to exit, everything will be cleaned up when
6527  * NaCl exits anyway.
6528  */
6529 #ifndef __native_client__
6530         if (!mono_runtime_try_shutdown ())
6531                 mono_thread_exit ();
6532
6533         /* Suspend all managed threads since the runtime is going away */
6534         mono_thread_suspend_all_other_threads ();
6535
6536         mono_runtime_quit ();
6537 #endif
6538
6539         /* we may need to do some cleanup here... */
6540         exit (result);
6541 }
6542
6543 ICALL_EXPORT MonoString*
6544 ves_icall_System_Environment_GetGacPath (void)
6545 {
6546         return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6547 }
6548
6549 ICALL_EXPORT MonoString*
6550 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6551 {
6552 #if defined (HOST_WIN32)
6553         #ifndef CSIDL_FLAG_CREATE
6554                 #define CSIDL_FLAG_CREATE       0x8000
6555         #endif
6556
6557         WCHAR path [MAX_PATH];
6558         /* Create directory if no existing */
6559         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6560                 int len = 0;
6561                 while (path [len])
6562                         ++ len;
6563                 return mono_string_new_utf16 (mono_domain_get (), path, len);
6564         }
6565 #else
6566         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6567 #endif
6568         return mono_string_new (mono_domain_get (), "");
6569 }
6570
6571 ICALL_EXPORT MonoArray *
6572 ves_icall_System_Environment_GetLogicalDrives (void)
6573 {
6574         gunichar2 buf [256], *ptr, *dname;
6575         gunichar2 *u16;
6576         guint initial_size = 127, size = 128;
6577         gint ndrives;
6578         MonoArray *result;
6579         MonoString *drivestr;
6580         MonoDomain *domain = mono_domain_get ();
6581         gint len;
6582
6583         MONO_ARCH_SAVE_REGS;
6584
6585         buf [0] = '\0';
6586         ptr = buf;
6587
6588         while (size > initial_size) {
6589                 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6590                 if (size > initial_size) {
6591                         if (ptr != buf)
6592                                 g_free (ptr);
6593                         ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6594                         initial_size = size;
6595                         size++;
6596                 }
6597         }
6598
6599         /* Count strings */
6600         dname = ptr;
6601         ndrives = 0;
6602         do {
6603                 while (*dname++);
6604                 ndrives++;
6605         } while (*dname);
6606
6607         dname = ptr;
6608         result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6609         ndrives = 0;
6610         do {
6611                 len = 0;
6612                 u16 = dname;
6613                 while (*u16) { u16++; len ++; }
6614                 drivestr = mono_string_new_utf16 (domain, dname, len);
6615                 mono_array_setref (result, ndrives++, drivestr);
6616                 while (*dname++);
6617         } while (*dname);
6618
6619         if (ptr != buf)
6620                 g_free (ptr);
6621
6622         return result;
6623 }
6624
6625 ICALL_EXPORT MonoString *
6626 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6627 {
6628         gunichar2 volume_name [MAX_PATH + 1];
6629         
6630         if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6631                 return NULL;
6632         return mono_string_from_utf16 (volume_name);
6633 }
6634
6635 ICALL_EXPORT MonoString *
6636 ves_icall_System_Environment_InternalGetHome (void)
6637 {
6638         MONO_ARCH_SAVE_REGS;
6639
6640         return mono_string_new (mono_domain_get (), g_get_home_dir ());
6641 }
6642
6643 static const char *encodings [] = {
6644         (char *) 1,
6645                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6646                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6647                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6648         (char *) 2,
6649                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6650                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6651                 "x_unicode_2_0_utf_7",
6652         (char *) 3,
6653                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6654                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6655         (char *) 4,
6656                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6657                 "iso_10646_ucs2",
6658         (char *) 5,
6659                 "unicodefffe", "utf_16be",
6660         (char *) 6,
6661                 "iso_8859_1",
6662         (char *) 0
6663 };
6664
6665 /*
6666  * Returns the internal codepage, if the value of "int_code_page" is
6667  * 1 at entry, and we can not compute a suitable code page number,
6668  * returns the code page as a string
6669  */
6670 ICALL_EXPORT MonoString*
6671 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page) 
6672 {
6673         const char *cset;
6674         const char *p;
6675         char *c;
6676         char *codepage = NULL;
6677         int code;
6678         int want_name = *int_code_page;
6679         int i;
6680         
6681         *int_code_page = -1;
6682         MONO_ARCH_SAVE_REGS;
6683
6684         g_get_charset (&cset);
6685         c = codepage = strdup (cset);
6686         for (c = codepage; *c; c++){
6687                 if (isascii (*c) && isalpha (*c))
6688                         *c = tolower (*c);
6689                 if (*c == '-')
6690                         *c = '_';
6691         }
6692         /* g_print ("charset: %s\n", cset); */
6693         
6694         /* handle some common aliases */
6695         p = encodings [0];
6696         code = 0;
6697         for (i = 0; p != 0; ){
6698                 if ((gssize) p < 7){
6699                         code = (gssize) p;
6700                         p = encodings [++i];
6701                         continue;
6702                 }
6703                 if (strcmp (p, codepage) == 0){
6704                         *int_code_page = code;
6705                         break;
6706                 }
6707                 p = encodings [++i];
6708         }
6709         
6710         if (strstr (codepage, "utf_8") != NULL)
6711                 *int_code_page |= 0x10000000;
6712         free (codepage);
6713         
6714         if (want_name && *int_code_page == -1)
6715                 return mono_string_new (mono_domain_get (), cset);
6716         else
6717                 return NULL;
6718 }
6719
6720 ICALL_EXPORT MonoBoolean
6721 ves_icall_System_Environment_get_HasShutdownStarted (void)
6722 {
6723         if (mono_runtime_is_shutting_down ())
6724                 return TRUE;
6725
6726         if (mono_domain_is_unloading (mono_domain_get ()))
6727                 return TRUE;
6728
6729         return FALSE;
6730 }
6731
6732 ICALL_EXPORT void
6733 ves_icall_System_Environment_BroadcastSettingChange (void)
6734 {
6735 #ifdef HOST_WIN32
6736         SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6737 #endif
6738 }
6739
6740 ICALL_EXPORT void
6741 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this, 
6742                                          MonoReflectionMethod *method,
6743                                          MonoArray *out_args)
6744 {
6745         MONO_ARCH_SAVE_REGS;
6746
6747         mono_message_init (mono_object_domain (this), this, method, out_args);
6748 }
6749
6750 #ifndef DISABLE_REMOTING
6751 ICALL_EXPORT MonoBoolean
6752 ves_icall_IsTransparentProxy (MonoObject *proxy)
6753 {
6754         MONO_ARCH_SAVE_REGS;
6755
6756         if (!proxy)
6757                 return 0;
6758
6759         if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6760                 return 1;
6761
6762         return 0;
6763 }
6764
6765 ICALL_EXPORT MonoReflectionMethod *
6766 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6767         MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6768 {
6769         MonoClass *klass;
6770         MonoMethod *method;
6771         MonoMethod **vtable;
6772         MonoMethod *res = NULL;
6773
6774         MONO_CHECK_ARG_NULL (rtype);
6775         MONO_CHECK_ARG_NULL (rmethod);
6776
6777         method = rmethod->method;
6778         klass = mono_class_from_mono_type (rtype->type);
6779         mono_class_init_or_throw (klass);
6780
6781         if (MONO_CLASS_IS_INTERFACE (klass))
6782                 return NULL;
6783
6784         if (method->flags & METHOD_ATTRIBUTE_STATIC)
6785                 return NULL;
6786
6787         if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6788                 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6789                         return rmethod;
6790                 else
6791                         return NULL;
6792         }
6793
6794         mono_class_setup_vtable (klass);
6795         vtable = klass->vtable;
6796
6797         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6798                 gboolean variance_used = FALSE;
6799                 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6800                 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6801                 if (offs >= 0)
6802                         res = vtable [offs + method->slot];
6803         } else {
6804                 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6805                         return NULL;
6806
6807                 if (method->slot != -1)
6808                         res = vtable [method->slot];
6809         }
6810
6811         if (!res)
6812                 return NULL;
6813
6814         return mono_method_get_object (mono_domain_get (), res, NULL);
6815 }
6816
6817 ICALL_EXPORT void
6818 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6819 {
6820         MonoClass *klass;
6821         MonoVTable* vtable;
6822
6823         MONO_ARCH_SAVE_REGS;
6824
6825         klass = mono_class_from_mono_type (type->type);
6826         vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6827
6828         mono_vtable_set_is_remote (vtable, enable);
6829 }
6830
6831 #else /* DISABLE_REMOTING */
6832
6833 ICALL_EXPORT void
6834 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6835 {
6836         g_assert_not_reached ();
6837 }
6838
6839 #endif
6840
6841 ICALL_EXPORT MonoObject *
6842 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6843 {
6844         MonoClass *klass;
6845         MonoDomain *domain;
6846         
6847         MONO_ARCH_SAVE_REGS;
6848
6849         domain = mono_object_domain (type);
6850         klass = mono_class_from_mono_type (type->type);
6851         mono_class_init_or_throw (klass);
6852
6853         if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6854                 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6855
6856         if (klass->rank >= 1) {
6857                 g_assert (klass->rank == 1);
6858                 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6859         } else {
6860                 /* Bypass remoting object creation check */
6861                 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6862         }
6863 }
6864
6865 ICALL_EXPORT MonoString *
6866 ves_icall_System_IO_get_temp_path (void)
6867 {
6868         MONO_ARCH_SAVE_REGS;
6869
6870         return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6871 }
6872
6873 #ifndef PLATFORM_NO_DRIVEINFO
6874 ICALL_EXPORT MonoBoolean
6875 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6876                                                 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6877                                                 gint32 *error)
6878 {
6879         gboolean result;
6880         ULARGE_INTEGER wapi_free_bytes_avail;
6881         ULARGE_INTEGER wapi_total_number_of_bytes;
6882         ULARGE_INTEGER wapi_total_number_of_free_bytes;
6883
6884         MONO_ARCH_SAVE_REGS;
6885
6886         *error = ERROR_SUCCESS;
6887         result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6888                                      &wapi_total_number_of_free_bytes);
6889
6890         if (result) {
6891                 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6892                 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6893                 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6894         } else {
6895                 *free_bytes_avail = 0;
6896                 *total_number_of_bytes = 0;
6897                 *total_number_of_free_bytes = 0;
6898                 *error = GetLastError ();
6899         }
6900
6901         return result;
6902 }
6903
6904 ICALL_EXPORT guint32
6905 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6906 {
6907         MONO_ARCH_SAVE_REGS;
6908
6909         return GetDriveType (mono_string_chars (root_path_name));
6910 }
6911 #endif
6912
6913 ICALL_EXPORT gpointer
6914 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6915 {
6916         MONO_ARCH_SAVE_REGS;
6917
6918         return mono_compile_method (method);
6919 }
6920
6921 ICALL_EXPORT MonoString *
6922 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6923 {
6924         MonoString *mcpath;
6925         gchar *path;
6926
6927         MONO_ARCH_SAVE_REGS;
6928
6929         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6930
6931 #if defined (HOST_WIN32)
6932         /* Avoid mixing '/' and '\\' */
6933         {
6934                 gint i;
6935                 for (i = strlen (path) - 1; i >= 0; i--)
6936                         if (path [i] == '/')
6937                                 path [i] = '\\';
6938         }
6939 #endif
6940         mcpath = mono_string_new (mono_domain_get (), path);
6941         g_free (path);
6942
6943         return mcpath;
6944 }
6945
6946 static MonoString *
6947 get_bundled_app_config (void)
6948 {
6949         const gchar *app_config;
6950         MonoDomain *domain;
6951         MonoString *file;
6952         gchar *config_file_name, *config_file_path;
6953         gsize len;
6954         gchar *module;
6955
6956         MONO_ARCH_SAVE_REGS;
6957
6958         domain = mono_domain_get ();
6959         file = domain->setup->configuration_file;
6960         if (!file)
6961                 return NULL;
6962
6963         // Retrieve config file and remove the extension
6964         config_file_name = mono_string_to_utf8 (file);
6965         config_file_path = mono_portability_find_file (config_file_name, TRUE);
6966         if (!config_file_path)
6967                 config_file_path = config_file_name;
6968         len = strlen (config_file_path) - strlen (".config");
6969         module = g_malloc0 (len + 1);
6970         memcpy (module, config_file_path, len);
6971         // Get the config file from the module name
6972         app_config = mono_config_string_for_assembly_file (module);
6973         // Clean-up
6974         g_free (module);
6975         if (config_file_name != config_file_path)
6976                 g_free (config_file_name);
6977         g_free (config_file_path);
6978
6979         if (!app_config)
6980                 return NULL;
6981
6982         return mono_string_new (mono_domain_get (), app_config);
6983 }
6984
6985 static MonoString *
6986 get_bundled_machine_config (void)
6987 {
6988         const gchar *machine_config;
6989
6990         MONO_ARCH_SAVE_REGS;
6991
6992         machine_config = mono_get_machine_config ();
6993
6994         if (!machine_config)
6995                 return NULL;
6996
6997         return mono_string_new (mono_domain_get (), machine_config);
6998 }
6999
7000 ICALL_EXPORT MonoString *
7001 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7002 {
7003         MonoString *ipath;
7004         gchar *path;
7005
7006         MONO_ARCH_SAVE_REGS;
7007
7008         path = g_path_get_dirname (mono_get_config_dir ());
7009
7010 #if defined (HOST_WIN32)
7011         /* Avoid mixing '/' and '\\' */
7012         {
7013                 gint i;
7014                 for (i = strlen (path) - 1; i >= 0; i--)
7015                         if (path [i] == '/')
7016                                 path [i] = '\\';
7017         }
7018 #endif
7019         ipath = mono_string_new (mono_domain_get (), path);
7020         g_free (path);
7021
7022         return ipath;
7023 }
7024
7025 ICALL_EXPORT gboolean
7026 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7027 {
7028         MonoPEResourceDataEntry *entry;
7029         MonoImage *image;
7030
7031         MONO_ARCH_SAVE_REGS;
7032
7033         if (!assembly || !result || !size)
7034                 return FALSE;
7035
7036         *result = NULL;
7037         *size = 0;
7038         image = assembly->assembly->image;
7039         entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7040         if (!entry)
7041                 return FALSE;
7042
7043         *result = mono_image_rva_map (image, entry->rde_data_offset);
7044         if (!(*result)) {
7045                 g_free (entry);
7046                 return FALSE;
7047         }
7048         *size = entry->rde_size;
7049         g_free (entry);
7050         return TRUE;
7051 }
7052
7053 ICALL_EXPORT MonoBoolean
7054 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7055 {
7056         return mono_is_debugger_attached ();
7057 }
7058
7059 ICALL_EXPORT MonoBoolean
7060 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7061 {
7062         if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7063                 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7064         else
7065                 return FALSE;
7066 }
7067
7068 ICALL_EXPORT void
7069 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7070 {
7071         if (mono_get_runtime_callbacks ()->debug_log)
7072                 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7073 }
7074
7075 ICALL_EXPORT void
7076 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7077 {
7078 #if defined (HOST_WIN32)
7079         OutputDebugString (mono_string_chars (message));
7080 #else
7081         g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7082 #endif
7083 }
7084
7085 /* Only used for value types */
7086 ICALL_EXPORT MonoObject *
7087 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7088 {
7089         MonoClass *klass;
7090         MonoDomain *domain;
7091         
7092         MONO_ARCH_SAVE_REGS;
7093
7094         domain = mono_object_domain (type);
7095         klass = mono_class_from_mono_type (type->type);
7096         mono_class_init_or_throw (klass);
7097
7098         if (mono_class_is_nullable (klass))
7099                 /* No arguments -> null */
7100                 return NULL;
7101
7102         return mono_object_new (domain, klass);
7103 }
7104
7105 ICALL_EXPORT MonoReflectionMethod *
7106 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7107 {
7108         MonoClass *klass, *parent;
7109         MonoMethod *method = m->method;
7110         MonoMethod *result = NULL;
7111         int slot;
7112
7113         MONO_ARCH_SAVE_REGS;
7114
7115         if (method->klass == NULL)
7116                 return m;
7117
7118         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7119             MONO_CLASS_IS_INTERFACE (method->klass) ||
7120             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7121                 return m;
7122
7123         slot = mono_method_get_vtable_slot (method);
7124         if (slot == -1)
7125                 return m;
7126
7127         klass = method->klass;
7128         if (klass->generic_class)
7129                 klass = klass->generic_class->container_class;
7130
7131         if (definition) {
7132                 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7133                 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7134                         mono_class_setup_vtable (parent);
7135                         if (parent->vtable_size <= slot)
7136                                 break;
7137                         klass = parent;
7138                 }
7139         } else {
7140                 klass = klass->parent;
7141                 if (!klass)
7142                         return m;
7143         }
7144
7145         if (klass == method->klass)
7146                 return m;
7147
7148         /*This is possible if definition == FALSE.
7149          * Do it here to be really sure we don't read invalid memory.
7150          */
7151         if (slot >= klass->vtable_size)
7152                 return m;
7153
7154         mono_class_setup_vtable (klass);
7155
7156         result = klass->vtable [slot];
7157         if (result == NULL) {
7158                 /* It is an abstract method */
7159                 gpointer iter = NULL;
7160                 while ((result = mono_class_get_methods (klass, &iter)))
7161                         if (result->slot == slot)
7162                                 break;
7163         }
7164
7165         if (result == NULL)
7166                 return m;
7167
7168         return mono_method_get_object (mono_domain_get (), result, NULL);
7169 }
7170
7171 ICALL_EXPORT MonoString*
7172 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7173 {
7174         MonoMethod *method = m->method;
7175
7176         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7177         return m->name;
7178 }
7179
7180 ICALL_EXPORT void
7181 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7182 {
7183         MONO_ARCH_SAVE_REGS;
7184
7185         iter->sig = *(MonoMethodSignature**)argsp;
7186         
7187         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7188         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7189
7190         iter->next_arg = 0;
7191         /* FIXME: it's not documented what start is exactly... */
7192         if (start) {
7193                 iter->args = start;
7194         } else {
7195                 iter->args = argsp + sizeof (gpointer);
7196         }
7197         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7198
7199         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7200 }
7201
7202 ICALL_EXPORT MonoTypedRef
7203 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7204 {
7205         guint32 i, arg_size;
7206         gint32 align;
7207         MonoTypedRef res;
7208         MONO_ARCH_SAVE_REGS;
7209
7210         i = iter->sig->sentinelpos + iter->next_arg;
7211
7212         g_assert (i < iter->sig->param_count);
7213
7214         res.type = iter->sig->params [i];
7215         res.klass = mono_class_from_mono_type (res.type);
7216         arg_size = mono_type_stack_size (res.type, &align);
7217 #if defined(__arm__) || defined(__mips__)
7218         iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7219 #endif
7220         res.value = iter->args;
7221 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7222         /* Values are stored as 8 byte register sized objects, but 'value'
7223          * is dereferenced as a pointer in other routines.
7224          */
7225         res.value = (char*)res.value + 4;
7226 #endif
7227 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7228         if (arg_size <= sizeof (gpointer)) {
7229                 int dummy;
7230                 int padding = arg_size - mono_type_size (res.type, &dummy);
7231                 res.value = (guint8*)res.value + padding;
7232         }
7233 #endif
7234         iter->args = (char*)iter->args + arg_size;
7235         iter->next_arg++;
7236
7237         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7238
7239         return res;
7240 }
7241
7242 ICALL_EXPORT MonoTypedRef
7243 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7244 {
7245         guint32 i, arg_size;
7246         gint32 align;
7247         MonoTypedRef res;
7248         MONO_ARCH_SAVE_REGS;
7249
7250         i = iter->sig->sentinelpos + iter->next_arg;
7251
7252         g_assert (i < iter->sig->param_count);
7253
7254         while (i < iter->sig->param_count) {
7255                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7256                         continue;
7257                 res.type = iter->sig->params [i];
7258                 res.klass = mono_class_from_mono_type (res.type);
7259                 /* FIXME: endianess issue... */
7260                 arg_size = mono_type_stack_size (res.type, &align);
7261 #if defined(__arm__) || defined(__mips__)
7262                 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7263 #endif
7264                 res.value = iter->args;
7265                 iter->args = (char*)iter->args + arg_size;
7266                 iter->next_arg++;
7267                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7268                 return res;
7269         }
7270         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7271
7272         res.type = NULL;
7273         res.value = NULL;
7274         res.klass = NULL;
7275         return res;
7276 }
7277
7278 ICALL_EXPORT MonoType*
7279 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7280 {
7281         gint i;
7282         MONO_ARCH_SAVE_REGS;
7283         
7284         i = iter->sig->sentinelpos + iter->next_arg;
7285
7286         g_assert (i < iter->sig->param_count);
7287
7288         return iter->sig->params [i];
7289 }
7290
7291 ICALL_EXPORT MonoObject*
7292 mono_TypedReference_ToObject (MonoTypedRef tref)
7293 {
7294         MONO_ARCH_SAVE_REGS;
7295
7296         if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7297                 MonoObject** objp = tref.value;
7298                 return *objp;
7299         }
7300
7301         return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7302 }
7303
7304 ICALL_EXPORT MonoObject*
7305 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7306 {
7307         MONO_ARCH_SAVE_REGS;
7308
7309         if (MONO_TYPE_IS_REFERENCE (type)) {
7310                 MonoObject** objp = value;
7311                 return *objp;
7312         }
7313
7314         return mono_value_box (mono_domain_get (), klass, value);
7315 }
7316
7317 static void
7318 prelink_method (MonoMethod *method)
7319 {
7320         const char *exc_class, *exc_arg;
7321         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7322                 return;
7323         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7324         if (exc_class) {
7325                 mono_raise_exception( 
7326                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7327         }
7328         /* create the wrapper, too? */
7329 }
7330
7331 ICALL_EXPORT void
7332 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7333 {
7334         MONO_ARCH_SAVE_REGS;
7335         prelink_method (method->method);
7336 }
7337
7338 ICALL_EXPORT void
7339 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7340 {
7341         MonoClass *klass = mono_class_from_mono_type (type->type);
7342         MonoMethod* m;
7343         gpointer iter = NULL;
7344         MONO_ARCH_SAVE_REGS;
7345
7346         mono_class_init_or_throw (klass);
7347
7348         while ((m = mono_class_get_methods (klass, &iter)))
7349                 prelink_method (m);
7350 }
7351
7352 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7353 ICALL_EXPORT void
7354 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7355                                             gint32 const **exponents,
7356                                             gunichar2 const **digitLowerTable,
7357                                             gunichar2 const **digitUpperTable,
7358                                             gint64 const **tenPowersList,
7359                                             gint32 const **decHexDigits)
7360 {
7361         *mantissas = Formatter_MantissaBitsTable;
7362         *exponents = Formatter_TensExponentTable;
7363         *digitLowerTable = Formatter_DigitLowerTable;
7364         *digitUpperTable = Formatter_DigitUpperTable;
7365         *tenPowersList = Formatter_TenPowersList;
7366         *decHexDigits = Formatter_DecHexDigits;
7367 }
7368
7369 ICALL_EXPORT void
7370 get_category_data (int version,
7371                    guint8 const **category_data,
7372                    guint16 const **category_astral_index)
7373 {
7374         *category_astral_index = NULL;
7375
7376 #ifndef DISABLE_NET_4_0
7377         if (version == 4) {
7378                 *category_data = CategoryData_v4;
7379 #ifndef DISABLE_ASTRAL
7380                 *category_astral_index = CategoryData_v4_astral_index;
7381 #endif
7382                 return;
7383         }
7384 #endif
7385
7386         *category_data = CategoryData_v2;
7387 #ifndef DISABLE_ASTRAL
7388         *category_astral_index = CategoryData_v2_astral_index;
7389 #endif
7390 }
7391
7392 /* These parameters are "readonly" in corlib/System/Char.cs */
7393 ICALL_EXPORT void
7394 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7395                                             guint8 const **category_data,
7396                                             guint16 const **category_astral_index,
7397                                             guint8 const **numeric_data,
7398                                             gdouble const **numeric_data_values,
7399                                             guint16 const **to_lower_data_low,
7400                                             guint16 const **to_lower_data_high,
7401                                             guint16 const **to_upper_data_low,
7402                                             guint16 const **to_upper_data_high)
7403 {
7404         get_category_data (category_data_version, category_data, category_astral_index);
7405         *numeric_data = NumericData;
7406         *numeric_data_values = NumericDataValues;
7407         *to_lower_data_low = ToLowerDataLow;
7408         *to_lower_data_high = ToLowerDataHigh;
7409         *to_upper_data_low = ToUpperDataLow;
7410         *to_upper_data_high = ToUpperDataHigh;
7411 }
7412
7413 /*
7414  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7415  * and avoid useless allocations.
7416  * 
7417  * MAY THROW
7418  */
7419 static MonoArray*
7420 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7421 {
7422         MonoArray *res;
7423         int i, count = 0;
7424         for (i = 0; i < type->num_mods; ++i) {
7425                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7426                         count++;
7427         }
7428         if (!count)
7429                 return NULL;
7430         res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7431         count = 0;
7432         for (i = 0; i < type->num_mods; ++i) {
7433                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7434                         MonoError error;
7435                         MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
7436                         mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */ 
7437                         mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7438                         count++;
7439                 }
7440         }
7441         return res;
7442 }
7443
7444 ICALL_EXPORT MonoArray*
7445 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7446 {
7447         MonoType *type = param->ClassImpl->type;
7448         MonoClass *member_class = mono_object_class (param->MemberImpl);
7449         MonoMethod *method = NULL;
7450         MonoImage *image;
7451         int pos;
7452         MonoMethodSignature *sig;
7453
7454         if (mono_class_is_reflection_method_or_constructor (member_class)) {
7455                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7456                 method = rmethod->method;
7457         } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7458                 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7459                 if (!(method = prop->property->get))
7460                         method = prop->property->set;
7461                 g_assert (method);      
7462         } else {
7463                 char *type_name = mono_type_get_full_name (member_class);
7464                 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7465                 MonoException *ex = mono_get_exception_not_supported  (msg);
7466                 g_free (type_name);
7467                 g_free (msg);
7468                 mono_raise_exception (ex);
7469         }
7470
7471         image = method->klass->image;
7472         pos = param->PositionImpl;
7473         sig = mono_method_signature (method);
7474         if (pos == -1)
7475                 type = sig->ret;
7476         else
7477                 type = sig->params [pos];
7478
7479         return type_array_from_modifiers (image, type, optional);
7480 }
7481
7482 static MonoType*
7483 get_property_type (MonoProperty *prop)
7484 {
7485         MonoMethodSignature *sig;
7486         if (prop->get) {
7487                 sig = mono_method_signature (prop->get);
7488                 return sig->ret;
7489         } else if (prop->set) {
7490                 sig = mono_method_signature (prop->set);
7491                 return sig->params [sig->param_count - 1];
7492         }
7493         return NULL;
7494 }
7495
7496 ICALL_EXPORT MonoArray*
7497 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7498 {
7499         MonoType *type = get_property_type (property->property);
7500         MonoImage *image = property->klass->image;
7501
7502         if (!type)
7503                 return NULL;
7504         return type_array_from_modifiers (image, type, optional);
7505 }
7506
7507 /*
7508  *Construct a MonoType suited to be used to decode a constant blob object.
7509  *
7510  * @type is the target type which will be constructed
7511  * @blob_type is the blob type, for example, that comes from the constant table
7512  * @real_type is the expected constructed type.
7513  */
7514 static void
7515 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7516 {
7517         type->type = blob_type;
7518         type->data.klass = NULL;
7519         if (blob_type == MONO_TYPE_CLASS)
7520                 type->data.klass = mono_defaults.object_class;
7521         else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7522                 /* For enums, we need to use the base type */
7523                 type->type = MONO_TYPE_VALUETYPE;
7524                 type->data.klass = mono_class_from_mono_type (real_type);
7525         } else
7526                 type->data.klass = mono_class_from_mono_type (real_type);
7527 }
7528
7529 ICALL_EXPORT MonoObject*
7530 property_info_get_default_value (MonoReflectionProperty *property)
7531 {
7532         MonoType blob_type;
7533         MonoProperty *prop = property->property;
7534         MonoType *type = get_property_type (prop);
7535         MonoDomain *domain = mono_object_domain (property); 
7536         MonoTypeEnum def_type;
7537         const char *def_value;
7538         MonoObject *o;
7539
7540         mono_class_init (prop->parent);
7541
7542         if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7543                 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7544
7545         def_value = mono_class_get_property_default_value (prop, &def_type);
7546
7547         mono_type_from_blob_type (&blob_type, def_type, type);
7548         o = mono_get_object_from_blob (domain, &blob_type, def_value);
7549
7550         return o;
7551 }
7552
7553 ICALL_EXPORT MonoBoolean
7554 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7555 {
7556         MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7557         MonoCustomAttrInfo *cinfo;
7558         gboolean found;
7559
7560         mono_class_init_or_throw (attr_class);
7561
7562         cinfo = mono_reflection_get_custom_attrs_info (obj);
7563         if (!cinfo)
7564                 return FALSE;
7565         found = mono_custom_attrs_has_attr (cinfo, attr_class);
7566         if (!cinfo->cached)
7567                 mono_custom_attrs_free (cinfo);
7568         return found;
7569 }
7570
7571 ICALL_EXPORT MonoArray*
7572 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7573 {
7574         MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7575         MonoArray *res;
7576         MonoError error;
7577
7578         if (attr_class)
7579                 mono_class_init_or_throw (attr_class);
7580
7581         res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7582         mono_error_raise_exception (&error);
7583
7584         if (mono_loader_get_last_error ()) {
7585                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7586                 g_assert_not_reached ();
7587                 /* Not reached */
7588                 return NULL;
7589         } else {
7590                 return res;
7591         }
7592 }
7593
7594 ICALL_EXPORT MonoString*
7595 ves_icall_Mono_Runtime_GetDisplayName (void)
7596 {
7597         char *info;
7598         MonoString *display_name;
7599
7600         info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7601         display_name = mono_string_new (mono_domain_get (), info);
7602         g_free (info);
7603         return display_name;
7604 }
7605
7606 ICALL_EXPORT MonoString*
7607 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7608 {
7609         MonoString *message;
7610         guint32 ret;
7611         gunichar2 buf[256];
7612         
7613         ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7614                              FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7615                              buf, 255, NULL);
7616         if (ret == 0) {
7617                 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7618         } else {
7619                 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7620         }
7621         
7622         return message;
7623 }
7624
7625 const static guchar
7626 dbase64 [] = {
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, 128, 128, 128, 128, 128,
7629         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7630         52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7631         128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7632         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7633         128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7634         41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7635 };
7636
7637 static MonoArray *
7638 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7639 {
7640         gint ignored;
7641         gint i;
7642         gunichar2 c;
7643         gunichar2 last, prev_last, prev2_last;
7644         gint olength;
7645         MonoArray *result;
7646         guchar *res_ptr;
7647         gint a [4], b [4];
7648         MonoException *exc;
7649
7650         int havePadding = 0;
7651         ignored = 0;
7652         last = prev_last = 0, prev2_last = 0;
7653         for (i = 0; i < ilength; i++) {
7654                 c = start [i];
7655                 if (c >= sizeof (dbase64)) {
7656                         exc = mono_exception_from_name_msg (mono_get_corlib (),
7657                                 "System", "FormatException",
7658                                 "Invalid character found.");
7659                         mono_raise_exception (exc);
7660                 } else if (isspace (c)) {
7661                         ignored++;
7662                 } else if (havePadding && c != '=') {
7663                         exc = mono_exception_from_name_msg (mono_get_corlib (),
7664                                 "System", "FormatException",
7665                                 "Invalid character found.");
7666                         mono_raise_exception (exc);
7667                 } else {
7668                         if (c == '=') havePadding = 1;
7669                         prev2_last = prev_last;
7670                         prev_last = last;
7671                         last = c;
7672                 }
7673         }
7674
7675         olength = ilength - ignored;
7676
7677         if (allowWhitespaceOnly && olength == 0) {
7678                 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7679         }
7680
7681         if ((olength & 3) != 0 || olength <= 0) {
7682                 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7683                                         "FormatException", "Invalid length.");
7684                 mono_raise_exception (exc);
7685         }
7686
7687         if (prev2_last == '=') {
7688                 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7689                 mono_raise_exception (exc);
7690         }
7691
7692         olength = (olength * 3) / 4;
7693         if (last == '=')
7694                 olength--;
7695
7696         if (prev_last == '=')
7697                 olength--;
7698
7699         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7700         res_ptr = mono_array_addr (result, guchar, 0);
7701         for (i = 0; i < ilength; ) {
7702                 int k;
7703
7704                 for (k = 0; k < 4 && i < ilength;) {
7705                         c = start [i++];
7706                         if (isspace (c))
7707                                 continue;
7708
7709                         a [k] = (guchar) c;
7710                         if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7711                                 exc = mono_exception_from_name_msg (mono_get_corlib (),
7712                                         "System", "FormatException",
7713                                         "Invalid character found.");
7714                                 mono_raise_exception (exc);
7715                         }
7716                         k++;
7717                 }
7718
7719                 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7720                 if (a [2] != '=')
7721                         *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7722                 if (a [3] != '=')
7723                         *res_ptr++ = (b [2] << 6) | b [3];
7724
7725                 while (i < ilength && isspace (start [i]))
7726                         i++;
7727         }
7728
7729         return result;
7730 }
7731
7732 ICALL_EXPORT MonoArray *
7733 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7734 {
7735         MONO_ARCH_SAVE_REGS;
7736
7737         return base64_to_byte_array (mono_string_chars (str), 
7738                 mono_string_length (str), allowWhitespaceOnly);
7739 }
7740
7741 ICALL_EXPORT MonoArray *
7742 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7743 {
7744         MONO_ARCH_SAVE_REGS;
7745
7746         return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7747                 length, FALSE);
7748 }
7749
7750 #ifndef DISABLE_ICALL_TABLES
7751
7752 #define ICALL_TYPE(id,name,first)
7753 #define ICALL(id,name,func) Icall_ ## id,
7754
7755 enum {
7756 #include "metadata/icall-def.h"
7757         Icall_last
7758 };
7759
7760 #undef ICALL_TYPE
7761 #undef ICALL
7762 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7763 #define ICALL(id,name,func)
7764 enum {
7765 #include "metadata/icall-def.h"
7766         Icall_type_num
7767 };
7768
7769 #undef ICALL_TYPE
7770 #undef ICALL
7771 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7772 #define ICALL(id,name,func)
7773 typedef struct {
7774         guint16 first_icall;
7775 } IcallTypeDesc;
7776
7777 static const IcallTypeDesc
7778 icall_type_descs [] = {
7779 #include "metadata/icall-def.h"
7780         {Icall_last}
7781 };
7782
7783 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7784
7785 #undef ICALL_TYPE
7786 #define ICALL_TYPE(id,name,first)
7787 #undef ICALL
7788
7789 #ifdef HAVE_ARRAY_ELEM_INIT
7790 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7791 #define MSGSTRFIELD1(line) str##line
7792
7793 static const struct msgstrtn_t {
7794 #define ICALL(id,name,func)
7795 #undef ICALL_TYPE
7796 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7797 #include "metadata/icall-def.h"
7798 #undef ICALL_TYPE
7799 } icall_type_names_str = {
7800 #define ICALL_TYPE(id,name,first) (name),
7801 #include "metadata/icall-def.h"
7802 #undef ICALL_TYPE
7803 };
7804 static const guint16 icall_type_names_idx [] = {
7805 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7806 #include "metadata/icall-def.h"
7807 #undef ICALL_TYPE
7808 };
7809 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7810
7811 static const struct msgstr_t {
7812 #undef ICALL
7813 #define ICALL_TYPE(id,name,first)
7814 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7815 #include "metadata/icall-def.h"
7816 #undef ICALL
7817 } icall_names_str = {
7818 #define ICALL(id,name,func) (name),
7819 #include "metadata/icall-def.h"
7820 #undef ICALL
7821 };
7822 static const guint16 icall_names_idx [] = {
7823 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7824 #include "metadata/icall-def.h"
7825 #undef ICALL
7826 };
7827 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7828
7829 #else
7830
7831 #undef ICALL_TYPE
7832 #undef ICALL
7833 #define ICALL_TYPE(id,name,first) name,
7834 #define ICALL(id,name,func)
7835 static const char* const
7836 icall_type_names [] = {
7837 #include "metadata/icall-def.h"
7838         NULL
7839 };
7840
7841 #define icall_type_name_get(id) (icall_type_names [(id)])
7842
7843 #undef ICALL_TYPE
7844 #undef ICALL
7845 #define ICALL_TYPE(id,name,first)
7846 #define ICALL(id,name,func) name,
7847 static const char* const
7848 icall_names [] = {
7849 #include "metadata/icall-def.h"
7850         NULL
7851 };
7852 #define icall_name_get(id) icall_names [(id)]
7853
7854 #endif /* !HAVE_ARRAY_ELEM_INIT */
7855
7856 #undef ICALL_TYPE
7857 #undef ICALL
7858 #define ICALL_TYPE(id,name,first)
7859 #define ICALL(id,name,func) func,
7860 static const gconstpointer
7861 icall_functions [] = {
7862 #include "metadata/icall-def.h"
7863         NULL
7864 };
7865
7866 #ifdef ENABLE_ICALL_SYMBOL_MAP
7867 #undef ICALL_TYPE
7868 #undef ICALL
7869 #define ICALL_TYPE(id,name,first)
7870 #define ICALL(id,name,func) #func,
7871 static const gconstpointer
7872 icall_symbols [] = {
7873 #include "metadata/icall-def.h"
7874         NULL
7875 };
7876 #endif
7877
7878 #endif /* DISABLE_ICALL_TABLES */
7879
7880 static mono_mutex_t icall_mutex;
7881 static GHashTable *icall_hash = NULL;
7882 static GHashTable *jit_icall_hash_name = NULL;
7883 static GHashTable *jit_icall_hash_addr = NULL;
7884
7885 void
7886 mono_icall_init (void)
7887 {
7888 #ifndef DISABLE_ICALL_TABLES
7889         int i = 0;
7890
7891         /* check that tables are sorted: disable in release */
7892         if (TRUE) {
7893                 int j;
7894                 const char *prev_class = NULL;
7895                 const char *prev_method;
7896                 
7897                 for (i = 0; i < Icall_type_num; ++i) {
7898                         const IcallTypeDesc *desc;
7899                         int num_icalls;
7900                         prev_method = NULL;
7901                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7902                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7903                         prev_class = icall_type_name_get (i);
7904                         desc = &icall_type_descs [i];
7905                         num_icalls = icall_desc_num_icalls (desc);
7906                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7907                         for (j = 0; j < num_icalls; ++j) {
7908                                 const char *methodn = icall_name_get (desc->first_icall + j);
7909                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
7910                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
7911                                 prev_method = methodn;
7912                         }
7913                 }
7914         }
7915 #endif
7916
7917         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7918         mono_mutex_init (&icall_mutex);
7919 }
7920
7921 static void
7922 mono_icall_lock (void)
7923 {
7924         mono_locks_mutex_acquire (&icall_mutex, IcallLock);
7925 }
7926
7927 static void
7928 mono_icall_unlock (void)
7929 {
7930         mono_locks_mutex_release (&icall_mutex, IcallLock);
7931 }
7932
7933 void
7934 mono_icall_cleanup (void)
7935 {
7936         g_hash_table_destroy (icall_hash);
7937         g_hash_table_destroy (jit_icall_hash_name);
7938         g_hash_table_destroy (jit_icall_hash_addr);
7939         mono_mutex_destroy (&icall_mutex);
7940 }
7941
7942 void
7943 mono_add_internal_call (const char *name, gconstpointer method)
7944 {
7945         mono_icall_lock ();
7946
7947         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7948
7949         mono_icall_unlock ();
7950 }
7951
7952 #ifndef DISABLE_ICALL_TABLES
7953
7954 #ifdef HAVE_ARRAY_ELEM_INIT
7955 static int
7956 compare_method_imap (const void *key, const void *elem)
7957 {
7958         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7959         return strcmp (key, method_name);
7960 }
7961
7962 static gpointer
7963 find_method_icall (const IcallTypeDesc *imap, const char *name)
7964 {
7965         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);
7966         if (!nameslot)
7967                 return NULL;
7968         return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7969 }
7970
7971 static int
7972 compare_class_imap (const void *key, const void *elem)
7973 {
7974         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7975         return strcmp (key, class_name);
7976 }
7977
7978 static const IcallTypeDesc*
7979 find_class_icalls (const char *name)
7980 {
7981         const guint16 *nameslot = mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7982         if (!nameslot)
7983                 return NULL;
7984         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7985 }
7986
7987 #else /* HAVE_ARRAY_ELEM_INIT */
7988
7989 static int
7990 compare_method_imap (const void *key, const void *elem)
7991 {
7992         const char** method_name = (const char**)elem;
7993         return strcmp (key, *method_name);
7994 }
7995
7996 static gpointer
7997 find_method_icall (const IcallTypeDesc *imap, const char *name)
7998 {
7999         const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8000         if (!nameslot)
8001                 return NULL;
8002         return (gpointer)icall_functions [(nameslot - icall_names)];
8003 }
8004
8005 static int
8006 compare_class_imap (const void *key, const void *elem)
8007 {
8008         const char** class_name = (const char**)elem;
8009         return strcmp (key, *class_name);
8010 }
8011
8012 static const IcallTypeDesc*
8013 find_class_icalls (const char *name)
8014 {
8015         const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8016         if (!nameslot)
8017                 return NULL;
8018         return &icall_type_descs [nameslot - icall_type_names];
8019 }
8020
8021 #endif /* HAVE_ARRAY_ELEM_INIT */
8022
8023 #endif /* DISABLE_ICALL_TABLES */
8024
8025 /* 
8026  * we should probably export this as an helper (handle nested types).
8027  * Returns the number of chars written in buf.
8028  */
8029 static int
8030 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8031 {
8032         int nspacelen, cnamelen;
8033         nspacelen = strlen (klass->name_space);
8034         cnamelen = strlen (klass->name);
8035         if (nspacelen + cnamelen + 2 > bufsize)
8036                 return 0;
8037         if (nspacelen) {
8038                 memcpy (buf, klass->name_space, nspacelen);
8039                 buf [nspacelen ++] = '.';
8040         }
8041         memcpy (buf + nspacelen, klass->name, cnamelen);
8042         buf [nspacelen + cnamelen] = 0;
8043         return nspacelen + cnamelen;
8044 }
8045
8046 #ifdef DISABLE_ICALL_TABLES
8047 static void
8048 no_icall_table (void)
8049 {
8050         g_assert_not_reached ();
8051 }
8052 #endif
8053
8054 gpointer
8055 mono_lookup_internal_call (MonoMethod *method)
8056 {
8057         char *sigstart;
8058         char *tmpsig;
8059         char mname [2048];
8060         int typelen = 0, mlen, siglen;
8061         gpointer res;
8062 #ifndef DISABLE_ICALL_TABLES
8063         const IcallTypeDesc *imap = NULL;
8064 #endif
8065
8066         g_assert (method != NULL);
8067
8068         if (method->is_inflated)
8069                 method = ((MonoMethodInflated *) method)->declaring;
8070
8071         if (method->klass->nested_in) {
8072                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8073                 if (!pos)
8074                         return NULL;
8075
8076                 mname [pos++] = '/';
8077                 mname [pos] = 0;
8078
8079                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8080                 if (!typelen)
8081                         return NULL;
8082
8083                 typelen += pos;
8084         } else {
8085                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8086                 if (!typelen)
8087                         return NULL;
8088         }
8089
8090 #ifndef DISABLE_ICALL_TABLES
8091         imap = find_class_icalls (mname);
8092 #endif
8093
8094         mname [typelen] = ':';
8095         mname [typelen + 1] = ':';
8096
8097         mlen = strlen (method->name);
8098         memcpy (mname + typelen + 2, method->name, mlen);
8099         sigstart = mname + typelen + 2 + mlen;
8100         *sigstart = 0;
8101
8102         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8103         siglen = strlen (tmpsig);
8104         if (typelen + mlen + siglen + 6 > sizeof (mname))
8105                 return NULL;
8106         sigstart [0] = '(';
8107         memcpy (sigstart + 1, tmpsig, siglen);
8108         sigstart [siglen + 1] = ')';
8109         sigstart [siglen + 2] = 0;
8110         g_free (tmpsig);
8111         
8112         mono_icall_lock ();
8113
8114         res = g_hash_table_lookup (icall_hash, mname);
8115         if (res) {
8116                 mono_icall_unlock ();;
8117                 return res;
8118         }
8119         /* try without signature */
8120         *sigstart = 0;
8121         res = g_hash_table_lookup (icall_hash, mname);
8122         if (res) {
8123                 mono_icall_unlock ();
8124                 return res;
8125         }
8126
8127 #ifdef DISABLE_ICALL_TABLES
8128         mono_icall_unlock ();
8129         /* Fail only when the result is actually used */
8130         /* mono_marshal_get_native_wrapper () depends on this */
8131         if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8132                 return ves_icall_System_String_ctor_RedirectToCreateString;
8133         else
8134                 return no_icall_table;
8135 #else
8136         /* it wasn't found in the static call tables */
8137         if (!imap) {
8138                 mono_icall_unlock ();
8139                 return NULL;
8140         }
8141         res = find_method_icall (imap, sigstart - mlen);
8142         if (res) {
8143                 mono_icall_unlock ();
8144                 return res;
8145         }
8146         /* try _with_ signature */
8147         *sigstart = '(';
8148         res = find_method_icall (imap, sigstart - mlen);
8149         if (res) {
8150                 mono_icall_unlock ();
8151                 return res;
8152         }
8153
8154         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8155         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8156         g_print ("The out of sync library is: %s\n", method->klass->image->name);
8157         g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8158         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");
8159         g_print ("If you see other errors or faults after this message they are probably related\n");
8160         g_print ("and you need to fix your mono install first.\n");
8161
8162         mono_icall_unlock ();
8163
8164         return NULL;
8165 #endif
8166 }
8167
8168 #ifdef ENABLE_ICALL_SYMBOL_MAP
8169 static int
8170 func_cmp (gconstpointer key, gconstpointer p)
8171 {
8172         return (gsize)key - (gsize)*(gsize*)p;
8173 }
8174 #endif
8175
8176 /*
8177  * mono_lookup_icall_symbol:
8178  *
8179  *   Given the icall METHOD, returns its C symbol.
8180  */
8181 const char*
8182 mono_lookup_icall_symbol (MonoMethod *m)
8183 {
8184 #ifdef DISABLE_ICALL_TABLES
8185         g_assert_not_reached ();
8186         return NULL;
8187 #else
8188 #ifdef ENABLE_ICALL_SYMBOL_MAP
8189         gpointer func;
8190         int i;
8191         gpointer slot;
8192         static gconstpointer *functions_sorted;
8193         static const char**symbols_sorted;
8194         static gboolean inited;
8195
8196         if (!inited) {
8197                 gboolean changed;
8198
8199                 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8200                 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8201                 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8202                 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8203                 /* Bubble sort the two arrays */
8204                 changed = TRUE;
8205                 while (changed) {
8206                         changed = FALSE;
8207                         for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8208                                 if (functions_sorted [i] > functions_sorted [i + 1]) {
8209                                         gconstpointer tmp;
8210
8211                                         tmp = functions_sorted [i];
8212                                         functions_sorted [i] = functions_sorted [i + 1];
8213                                         functions_sorted [i + 1] = tmp;
8214                                         tmp = symbols_sorted [i];
8215                                         symbols_sorted [i] = symbols_sorted [i + 1];
8216                                         symbols_sorted [i + 1] = tmp;
8217                                         changed = TRUE;
8218                                 }
8219                         }
8220                 }
8221         }
8222
8223         func = mono_lookup_internal_call (m);
8224         if (!func)
8225                 return NULL;
8226         slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8227         if (!slot)
8228                 return NULL;
8229         g_assert (slot);
8230         return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8231 #else
8232         fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8233         g_assert_not_reached ();
8234         return 0;
8235 #endif
8236 #endif
8237 }
8238
8239 static MonoType*
8240 type_from_typename (char *typename)
8241 {
8242         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
8243
8244         if (!strcmp (typename, "int"))
8245                 klass = mono_defaults.int_class;
8246         else if (!strcmp (typename, "ptr"))
8247                 klass = mono_defaults.int_class;
8248         else if (!strcmp (typename, "void"))
8249                 klass = mono_defaults.void_class;
8250         else if (!strcmp (typename, "int32"))
8251                 klass = mono_defaults.int32_class;
8252         else if (!strcmp (typename, "uint32"))
8253                 klass = mono_defaults.uint32_class;
8254         else if (!strcmp (typename, "int8"))
8255                 klass = mono_defaults.sbyte_class;
8256         else if (!strcmp (typename, "uint8"))
8257                 klass = mono_defaults.byte_class;
8258         else if (!strcmp (typename, "int16"))
8259                 klass = mono_defaults.int16_class;
8260         else if (!strcmp (typename, "uint16"))
8261                 klass = mono_defaults.uint16_class;
8262         else if (!strcmp (typename, "long"))
8263                 klass = mono_defaults.int64_class;
8264         else if (!strcmp (typename, "ulong"))
8265                 klass = mono_defaults.uint64_class;
8266         else if (!strcmp (typename, "float"))
8267                 klass = mono_defaults.single_class;
8268         else if (!strcmp (typename, "double"))
8269                 klass = mono_defaults.double_class;
8270         else if (!strcmp (typename, "object"))
8271                 klass = mono_defaults.object_class;
8272         else if (!strcmp (typename, "obj"))
8273                 klass = mono_defaults.object_class;
8274         else if (!strcmp (typename, "string"))
8275                 klass = mono_defaults.string_class;
8276         else if (!strcmp (typename, "bool"))
8277                 klass = mono_defaults.boolean_class;
8278         else if (!strcmp (typename, "boolean"))
8279                 klass = mono_defaults.boolean_class;
8280         else {
8281                 g_error ("%s", typename);
8282                 g_assert_not_reached ();
8283         }
8284         return &klass->byval_arg;
8285 }
8286
8287 /**
8288  * LOCKING: Take the corlib image lock.
8289  */
8290 MonoMethodSignature*
8291 mono_create_icall_signature (const char *sigstr)
8292 {
8293         gchar **parts;
8294         int i, len;
8295         gchar **tmp;
8296         MonoMethodSignature *res, *res2;
8297         MonoImage *corlib = mono_defaults.corlib;
8298
8299         mono_image_lock (corlib);
8300         res = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8301         mono_image_unlock (corlib);
8302
8303         if (res)
8304                 return res;
8305
8306         parts = g_strsplit (sigstr, " ", 256);
8307
8308         tmp = parts;
8309         len = 0;
8310         while (*tmp) {
8311                 len ++;
8312                 tmp ++;
8313         }
8314
8315         res = mono_metadata_signature_alloc (corlib, len - 1);
8316         res->pinvoke = 1;
8317
8318 #ifdef HOST_WIN32
8319         /* 
8320          * Under windows, the default pinvoke calling convention is STDCALL but
8321          * we need CDECL.
8322          */
8323         res->call_convention = MONO_CALL_C;
8324 #endif
8325
8326         res->ret = type_from_typename (parts [0]);
8327         for (i = 1; i < len; ++i) {
8328                 res->params [i - 1] = type_from_typename (parts [i]);
8329         }
8330
8331         g_strfreev (parts);
8332
8333         mono_image_lock (corlib);
8334         res2 = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8335         if (res2)
8336                 res = res2; /*Value is allocated in the image pool*/
8337         else
8338                 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8339         mono_image_unlock (corlib);
8340
8341         return res;
8342 }
8343
8344 MonoJitICallInfo *
8345 mono_find_jit_icall_by_name (const char *name)
8346 {
8347         MonoJitICallInfo *info;
8348         g_assert (jit_icall_hash_name);
8349
8350         mono_icall_lock ();
8351         info = g_hash_table_lookup (jit_icall_hash_name, name);
8352         mono_icall_unlock ();
8353         return info;
8354 }
8355
8356 MonoJitICallInfo *
8357 mono_find_jit_icall_by_addr (gconstpointer addr)
8358 {
8359         MonoJitICallInfo *info;
8360         g_assert (jit_icall_hash_addr);
8361
8362         mono_icall_lock ();
8363         info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8364         mono_icall_unlock ();
8365
8366         return info;
8367 }
8368
8369 /*
8370  * mono_get_jit_icall_info:
8371  *
8372  *   Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8373  * caller should access it while holding the icall lock.
8374  */
8375 GHashTable*
8376 mono_get_jit_icall_info (void)
8377 {
8378         return jit_icall_hash_name;
8379 }
8380
8381 /*
8382  * mono_lookup_jit_icall_symbol:
8383  *
8384  *   Given the jit icall NAME, returns its C symbol if possible, or NULL.
8385  */
8386 const char*
8387 mono_lookup_jit_icall_symbol (const char *name)
8388 {
8389         MonoJitICallInfo *info;
8390         const char *res = NULL;
8391
8392         mono_icall_lock ();
8393         info = g_hash_table_lookup (jit_icall_hash_name, name);
8394         if (info)
8395                 res = info->c_symbol;
8396         mono_icall_unlock ();
8397         return res;
8398 }
8399
8400 void
8401 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8402 {
8403         mono_icall_lock ();
8404         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8405         mono_icall_unlock ();
8406 }
8407
8408 MonoJitICallInfo *
8409 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8410 {
8411         MonoJitICallInfo *info;
8412         
8413         g_assert (func);
8414         g_assert (name);
8415
8416         mono_icall_lock ();
8417
8418         if (!jit_icall_hash_name) {
8419                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8420                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8421         }
8422
8423         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8424                 g_warning ("jit icall already defined \"%s\"\n", name);
8425                 g_assert_not_reached ();
8426         }
8427
8428         info = g_new0 (MonoJitICallInfo, 1);
8429         
8430         info->name = name;
8431         info->func = func;
8432         info->sig = sig;
8433         info->c_symbol = c_symbol;
8434
8435         if (is_save) {
8436                 info->wrapper = func;
8437         } else {
8438                 info->wrapper = NULL;
8439         }
8440
8441         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8442         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8443
8444         mono_icall_unlock ();
8445         return info;
8446 }
8447
8448 MonoJitICallInfo *
8449 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8450 {
8451         return mono_register_jit_icall_full (func, name, sig, is_save, NULL);
8452 }
8453