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