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