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