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