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