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