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