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