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