Making sure mono_marshal_free is used instead of g_free in mono_string_builder_to_utf8
[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, &error);
2156                 if (mono_error_set_pending_exception (&error))
2157                         return NULL;
2158                 break;
2159         }
2160         case MONO_TYPE_STRING:
2161         case MONO_TYPE_CLASS:
2162                 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2163                 if (mono_error_set_pending_exception (&error))
2164                         return NULL;
2165                 break;
2166         default:
2167                 g_assert_not_reached ();
2168         }
2169
2170         return o;
2171 }
2172
2173 ICALL_EXPORT MonoReflectionType*
2174 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2175 {
2176         MonoError error;
2177         MonoReflectionType *ret;
2178         MonoType *type;
2179
2180         type = mono_field_get_type_checked (ref_field->field, &error);
2181         if (!mono_error_ok (&error)) {
2182                 mono_error_set_pending_exception (&error);
2183                 return NULL;
2184         }
2185
2186         ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2187         if (!mono_error_ok (&error)) {
2188                 mono_error_set_pending_exception (&error);
2189                 return NULL;
2190         }
2191
2192         return ret;
2193 }
2194
2195 /* From MonoProperty.cs */
2196 typedef enum {
2197         PInfo_Attributes = 1,
2198         PInfo_GetMethod  = 1 << 1,
2199         PInfo_SetMethod  = 1 << 2,
2200         PInfo_ReflectedType = 1 << 3,
2201         PInfo_DeclaringType = 1 << 4,
2202         PInfo_Name = 1 << 5
2203 } PInfo;
2204
2205 ICALL_EXPORT void
2206 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2207 {
2208         MonoError error;
2209         MonoReflectionType *rt;
2210         MonoReflectionMethod *rm;
2211         MonoDomain *domain = mono_object_domain (property); 
2212         const MonoProperty *pproperty = property->property;
2213
2214         if ((req_info & PInfo_ReflectedType) != 0) {
2215                 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2216                 if (mono_error_set_pending_exception (&error))
2217                         return;
2218
2219                 MONO_STRUCT_SETREF (info, parent, rt);
2220         }
2221         if ((req_info & PInfo_DeclaringType) != 0) {
2222                 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2223                 if (mono_error_set_pending_exception (&error))
2224                         return;
2225
2226                 MONO_STRUCT_SETREF (info, declaring_type, rt);
2227         }
2228
2229         if ((req_info & PInfo_Name) != 0)
2230                 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2231
2232         if ((req_info & PInfo_Attributes) != 0)
2233                 info->attrs = pproperty->attrs;
2234
2235         if ((req_info & PInfo_GetMethod) != 0) {
2236                 if (pproperty->get &&
2237                     (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2238                      pproperty->get->klass == property->klass)) {
2239                         rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2240                         if (mono_error_set_pending_exception (&error))
2241                                 return;
2242                 } else {
2243                         rm = NULL;
2244                 }
2245
2246                 MONO_STRUCT_SETREF (info, get, rm);
2247         }
2248         if ((req_info & PInfo_SetMethod) != 0) {
2249                 if (pproperty->set &&
2250                     (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2251                      pproperty->set->klass == property->klass)) {
2252                         rm =  mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2253                         if (mono_error_set_pending_exception (&error))
2254                                 return;
2255                 } else {
2256                         rm = NULL;
2257                 }
2258
2259                 MONO_STRUCT_SETREF (info, set, rm);
2260         }
2261         /* 
2262          * There may be other methods defined for properties, though, it seems they are not exposed 
2263          * in the reflection API 
2264          */
2265 }
2266
2267 ICALL_EXPORT void
2268 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2269 {
2270         MonoError error;
2271         MonoReflectionType *rt;
2272         MonoReflectionMethod *rm;
2273         MonoDomain *domain = mono_object_domain (event); 
2274
2275         rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2276         if (mono_error_set_pending_exception (&error))
2277                 return;
2278
2279         MONO_STRUCT_SETREF (info, reflected_type, rt);
2280
2281         rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2282         if (mono_error_set_pending_exception (&error))
2283                 return;
2284
2285         MONO_STRUCT_SETREF (info, declaring_type, rt);
2286
2287         MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2288         info->attrs = event->event->attrs;
2289
2290         if (event->event->add) {
2291                 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2292                 if (mono_error_set_pending_exception (&error))
2293                         return;
2294         } else {
2295                 rm = NULL;
2296         }
2297
2298         MONO_STRUCT_SETREF (info, add_method, rm);
2299
2300         if (event->event->remove) {
2301                 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2302                 if (mono_error_set_pending_exception (&error))
2303                         return;
2304         } else {
2305                 rm = NULL;
2306         }
2307
2308         MONO_STRUCT_SETREF (info, remove_method, rm);
2309
2310         if (event->event->raise) {
2311                 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2312                 if (mono_error_set_pending_exception (&error))
2313                         return;
2314         } else {
2315                 rm = NULL;
2316         }
2317
2318         MONO_STRUCT_SETREF (info, raise_method, rm);
2319
2320 #ifndef MONO_SMALL_CONFIG
2321         if (event->event->other) {
2322                 int i, n = 0;
2323                 while (event->event->other [n])
2324                         n++;
2325                 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2326                 if (mono_error_set_pending_exception (&error))
2327                         return;
2328                 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2329
2330                 for (i = 0; i < n; i++) {
2331                         rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2332                         if (mono_error_set_pending_exception (&error))
2333                                 return;
2334                         mono_array_setref (info->other_methods, i, rm);
2335                 }
2336         }               
2337 #endif
2338 }
2339
2340 static void
2341 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2342 {
2343         int i;
2344         MonoClass *ic;
2345
2346         mono_class_setup_interfaces (klass, error);
2347         if (!mono_error_ok (error))
2348                 return;
2349
2350         for (i = 0; i < klass->interface_count; i++) {
2351                 ic = klass->interfaces [i];
2352                 g_hash_table_insert (ifaces, ic, ic);
2353
2354                 collect_interfaces (ic, ifaces, error);
2355                 if (!mono_error_ok (error))
2356                         return;
2357         }
2358 }
2359
2360 typedef struct {
2361         MonoArray *iface_array;
2362         MonoGenericContext *context;
2363         MonoError *error;
2364         MonoDomain *domain;
2365         int next_idx;
2366 } FillIfaceArrayData;
2367
2368 static void
2369 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2370 {
2371         MonoReflectionType *rt;
2372         FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2373         MonoClass *ic = (MonoClass *)key;
2374         MonoType *ret = &ic->byval_arg, *inflated = NULL;
2375
2376         if (!mono_error_ok (data->error))
2377                 return;
2378
2379         if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2380                 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2381                 if (!mono_error_ok (data->error))
2382                         return;
2383         }
2384
2385         rt = mono_type_get_object_checked (data->domain, ret, data->error);
2386         if (!mono_error_ok (data->error))
2387                 return;
2388
2389         mono_array_setref (data->iface_array, data->next_idx++, rt);
2390
2391         if (inflated)
2392                 mono_metadata_free_type (inflated);
2393 }
2394
2395 static guint
2396 get_interfaces_hash (gconstpointer v1)
2397 {
2398         MonoClass *k = (MonoClass*)v1;
2399
2400         return k->type_token;
2401 }
2402
2403 ICALL_EXPORT MonoArray*
2404 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2405 {
2406         MonoError error;
2407         MonoClass *klass = mono_class_from_mono_type (type->type);
2408         MonoClass *parent;
2409         FillIfaceArrayData data = { 0 };
2410         int len;
2411
2412         GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2413
2414         if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2415                 data.context = mono_class_get_context (klass);
2416                 klass = klass->generic_class->container_class;
2417         }
2418
2419         for (parent = klass; parent; parent = parent->parent) {
2420                 mono_class_setup_interfaces (parent, &error);
2421                 if (!mono_error_ok (&error))
2422                         goto fail;
2423                 collect_interfaces (parent, iface_hash, &error);
2424                 if (!mono_error_ok (&error))
2425                         goto fail;
2426         }
2427
2428         data.error = &error;
2429         data.domain = mono_object_domain (type);
2430
2431         len = g_hash_table_size (iface_hash);
2432         if (len == 0) {
2433                 g_hash_table_destroy (iface_hash);
2434                 if (!data.domain->empty_types) {
2435                         data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0, &error);
2436                         if (!is_ok (&error))
2437                                 goto fail;
2438                 }
2439                 return data.domain->empty_types;
2440         }
2441
2442         data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len, &error);
2443         if (!is_ok (&error))
2444                 goto fail;
2445         g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2446         if (!mono_error_ok (&error))
2447                 goto fail;
2448
2449         g_hash_table_destroy (iface_hash);
2450         return data.iface_array;
2451
2452 fail:
2453         g_hash_table_destroy (iface_hash);
2454         mono_error_set_pending_exception (&error);
2455         return NULL;
2456 }
2457
2458 ICALL_EXPORT void
2459 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2460 {
2461         gboolean variance_used;
2462         MonoClass *klass = mono_class_from_mono_type (type->type);
2463         MonoClass *iclass = mono_class_from_mono_type (iface->type);
2464         MonoReflectionMethod *member;
2465         MonoMethod* method;
2466         gpointer iter;
2467         int i = 0, len, ioffset;
2468         MonoDomain *domain;
2469         MonoError error;
2470
2471         mono_class_init_checked (klass, &error);
2472         if (mono_error_set_pending_exception (&error))
2473                 return;
2474         mono_class_init_checked (iclass, &error);
2475         if (mono_error_set_pending_exception (&error))
2476                 return;
2477
2478         mono_class_setup_vtable (klass);
2479
2480         ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2481         if (ioffset == -1)
2482                 return;
2483
2484         len = mono_class_num_methods (iclass);
2485         domain = mono_object_domain (type);
2486         MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2487         if (mono_error_set_pending_exception (&error))
2488                 return;
2489         mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2490         MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2491         if (mono_error_set_pending_exception (&error))
2492                 return;
2493         mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2494         iter = NULL;
2495         while ((method = mono_class_get_methods (iclass, &iter))) {
2496                 member = mono_method_get_object_checked (domain, method, iclass, &error);
2497                 if (mono_error_set_pending_exception (&error))
2498                         return;
2499                 mono_array_setref (*methods, i, member);
2500                 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2501                 if (mono_error_set_pending_exception (&error))
2502                         return;
2503                 mono_array_setref (*targets, i, member);
2504                 
2505                 i ++;
2506         }
2507 }
2508
2509 ICALL_EXPORT void
2510 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2511 {
2512         MonoError error;
2513         MonoClass *klass = mono_class_from_mono_type (type->type);
2514
2515         mono_class_init_checked (klass, &error);
2516         if (mono_error_set_pending_exception (&error))
2517                 return;
2518
2519         if (image_is_dynamic (klass->image)) {
2520                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2521                 *packing = tb->packing_size;
2522                 *size = tb->class_size;
2523         } else {
2524                 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2525         }
2526 }
2527
2528 ICALL_EXPORT MonoReflectionType*
2529 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2530 {
2531         MonoError error;
2532         MonoReflectionType *ret;
2533         MonoClass *klass;
2534
2535         if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2536                 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2537                 mono_error_set_pending_exception (&error);
2538                 return ret;
2539         }
2540
2541         klass = mono_class_from_mono_type (type->type);
2542         mono_class_init_checked (klass, &error);
2543         if (mono_error_set_pending_exception (&error))
2544                 return NULL;
2545
2546
2547         // GetElementType should only return a type for:
2548         // Array Pointer PassedByRef
2549         if (type->type->byref)
2550                 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2551         else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2552                 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2553         else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2554                 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2555         else
2556                 return NULL;
2557
2558         mono_error_set_pending_exception (&error);
2559
2560         return ret;
2561 }
2562
2563 ICALL_EXPORT MonoReflectionType*
2564 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2565 {
2566         MonoError error;
2567         MonoReflectionType *ret;
2568
2569         if (type->type->byref)
2570                 return NULL;
2571
2572         MonoClass *klass = mono_class_from_mono_type (type->type);
2573         if (!klass->parent)
2574                 return NULL;
2575
2576         ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2577         mono_error_set_pending_exception (&error);
2578
2579         return ret;
2580 }
2581
2582 ICALL_EXPORT MonoBoolean
2583 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2584 {
2585         return type->type->type == MONO_TYPE_PTR;
2586 }
2587
2588 ICALL_EXPORT MonoBoolean
2589 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2590 {
2591         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)));
2592 }
2593
2594 ICALL_EXPORT MonoBoolean
2595 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2596 {
2597         return type->type->byref;
2598 }
2599
2600 ICALL_EXPORT MonoBoolean
2601 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2602 {
2603         MonoError error;
2604         MonoClass *klass = mono_class_from_mono_type (type->type);
2605         mono_class_init_checked (klass, &error);
2606         if (mono_error_set_pending_exception (&error))
2607                 return FALSE;
2608
2609         return mono_class_is_com_object (klass);
2610 }
2611
2612 ICALL_EXPORT guint32
2613 ves_icall_reflection_get_token (MonoObject* obj)
2614 {
2615         MonoError error;
2616         guint32 result = mono_reflection_get_token_checked (obj, &error);
2617         mono_error_set_pending_exception (&error);
2618         return result;
2619 }
2620
2621 ICALL_EXPORT MonoReflectionModule*
2622 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2623 {
2624         MonoError error;
2625         MonoReflectionModule *result = NULL;
2626         MonoClass *klass = mono_class_from_mono_type (type->type);
2627         result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2628         mono_error_set_pending_exception (&error);
2629         return result;
2630 }
2631
2632 ICALL_EXPORT MonoReflectionAssembly*
2633 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2634 {
2635         MonoError error;
2636         MonoDomain *domain = mono_domain_get (); 
2637         MonoClass *klass = mono_class_from_mono_type (type->type);
2638         MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2639         mono_error_set_pending_exception (&error);
2640         return result;
2641 }
2642
2643 ICALL_EXPORT MonoReflectionType*
2644 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2645 {
2646         MonoError error;
2647         MonoReflectionType *ret;
2648         MonoDomain *domain = mono_domain_get ();
2649         MonoClass *klass;
2650
2651         if (type->type->byref)
2652                 return NULL;
2653         if (type->type->type == MONO_TYPE_VAR) {
2654                 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2655                 klass = param ? param->owner.klass : NULL;
2656         } else if (type->type->type == MONO_TYPE_MVAR) {
2657                 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2658                 klass = param ? param->owner.method->klass : NULL;
2659         } else {
2660                 klass = mono_class_from_mono_type (type->type)->nested_in;
2661         }
2662
2663         if (!klass)
2664                 return NULL;
2665
2666         ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2667         mono_error_set_pending_exception (&error);
2668
2669         return ret;
2670 }
2671
2672 ICALL_EXPORT MonoString*
2673 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2674 {
2675         MonoDomain *domain = mono_domain_get (); 
2676         MonoClass *klass = mono_class_from_mono_type (type->type);
2677
2678         if (type->type->byref) {
2679                 char *n = g_strdup_printf ("%s&", klass->name);
2680                 MonoString *res = mono_string_new (domain, n);
2681
2682                 g_free (n);
2683
2684                 return res;
2685         } else {
2686                 return mono_string_new (domain, klass->name);
2687         }
2688 }
2689
2690 ICALL_EXPORT MonoString*
2691 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2692 {
2693         MonoDomain *domain = mono_domain_get (); 
2694         MonoClass *klass = mono_class_from_mono_type (type->type);
2695
2696         while (klass->nested_in)
2697                 klass = klass->nested_in;
2698
2699         if (klass->name_space [0] == '\0')
2700                 return NULL;
2701         else
2702                 return mono_string_new (domain, klass->name_space);
2703 }
2704
2705 ICALL_EXPORT gint32
2706 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2707 {
2708         MonoClass *klass;
2709
2710         if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2711                 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2712                 return 0;
2713         }
2714
2715         klass = mono_class_from_mono_type (type->type);
2716
2717         return klass->rank;
2718 }
2719
2720 static MonoArray*
2721 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2722 {
2723         return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2724 }
2725
2726 ICALL_EXPORT MonoArray*
2727 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2728 {
2729         MonoError error;
2730         MonoReflectionType *rt;
2731         MonoArray *res;
2732         MonoClass *klass, *pklass;
2733         MonoDomain *domain = mono_object_domain (type);
2734         int i;
2735
2736         klass = mono_class_from_mono_type (type->type);
2737
2738         if (klass->generic_container) {
2739                 MonoGenericContainer *container = klass->generic_container;
2740                 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2741                 if (mono_error_set_pending_exception (&error))
2742                         return NULL;
2743                 for (i = 0; i < container->type_argc; ++i) {
2744                         pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2745
2746                         rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2747                         if (mono_error_set_pending_exception (&error))
2748                                 return NULL;
2749
2750                         mono_array_setref (res, i, rt);
2751                 }
2752         } else if (klass->generic_class) {
2753                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2754                 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2755                 if (mono_error_set_pending_exception (&error))
2756                         return NULL;
2757                 for (i = 0; i < inst->type_argc; ++i) {
2758                         rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2759                         if (mono_error_set_pending_exception (&error))
2760                                 return NULL;
2761
2762                         mono_array_setref (res, i, rt);
2763                 }
2764         } else {
2765                 res = NULL;
2766         }
2767         return res;
2768 }
2769
2770 ICALL_EXPORT gboolean
2771 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2772 {
2773         MonoClass *klass;
2774
2775         if (!IS_MONOTYPE (type))
2776                 return FALSE;
2777
2778         if (type->type->byref)
2779                 return FALSE;
2780
2781         klass = mono_class_from_mono_type (type->type);
2782         return klass->generic_container != NULL;
2783 }
2784
2785 ICALL_EXPORT MonoReflectionType*
2786 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2787 {
2788         MonoError error;
2789         MonoReflectionType *ret;
2790         MonoClass *klass;
2791
2792         if (type->type->byref)
2793                 return NULL;
2794
2795         klass = mono_class_from_mono_type (type->type);
2796
2797         if (klass->generic_container) {
2798                 return type; /* check this one */
2799         }
2800         if (klass->generic_class) {
2801                 MonoClass *generic_class = klass->generic_class->container_class;
2802                 gpointer tb;
2803
2804                 tb = mono_class_get_ref_info (generic_class);
2805
2806                 if (generic_class->wastypebuilder && tb)
2807                         return (MonoReflectionType *)tb;
2808                 else {
2809                         ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2810                         mono_error_set_pending_exception (&error);
2811
2812                         return ret;
2813                 }
2814         }
2815         return NULL;
2816 }
2817
2818 ICALL_EXPORT MonoReflectionType*
2819 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2820 {
2821         MonoError error;
2822         MonoReflectionType *ret;
2823         MonoClass *klass;
2824         MonoType *geninst, **types;
2825         int i, count;
2826
2827         g_assert (IS_MONOTYPE (type));
2828         mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2829         if (mono_error_set_pending_exception (&error))
2830                 return NULL;
2831
2832         count = mono_array_length (type_array);
2833         types = g_new0 (MonoType *, count);
2834
2835         for (i = 0; i < count; i++) {
2836                 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2837                 types [i] = t->type;
2838         }
2839
2840         geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2841         g_free (types);
2842         if (!geninst) {
2843                 mono_error_set_pending_exception (&error);
2844                 return NULL;
2845         }
2846
2847         klass = mono_class_from_mono_type (geninst);
2848
2849         /*we might inflate to the GTD*/
2850         if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2851                 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2852                 return NULL;
2853         }
2854
2855         ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2856         mono_error_set_pending_exception (&error);
2857
2858         return ret;
2859 }
2860
2861 ICALL_EXPORT gboolean
2862 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2863 {
2864         MonoClass *klass;
2865
2866         if (!IS_MONOTYPE (type))
2867                 return FALSE;
2868
2869         if (type->type->byref)
2870                 return FALSE;
2871
2872         klass = mono_class_from_mono_type (type->type);
2873         return klass->generic_class != NULL || klass->generic_container != NULL;
2874 }
2875
2876 ICALL_EXPORT gint32
2877 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2878 {
2879         if (!IS_MONOTYPE (type))
2880                 return -1;
2881
2882         if (is_generic_parameter (type->type))
2883                 return mono_type_get_generic_param_num (type->type);
2884         return -1;
2885 }
2886
2887 ICALL_EXPORT GenericParameterAttributes
2888 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2889 {
2890         g_assert (IS_MONOTYPE (type));
2891         g_assert (is_generic_parameter (type->type));
2892         return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2893 }
2894
2895 ICALL_EXPORT MonoArray *
2896 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2897 {
2898         MonoError error;
2899         MonoReflectionType *rt;
2900         MonoGenericParamInfo *param_info;
2901         MonoDomain *domain;
2902         MonoClass **ptr;
2903         MonoArray *res;
2904         int i, count;
2905
2906         g_assert (IS_MONOTYPE (type));
2907
2908         domain = mono_object_domain (type);
2909         param_info = mono_generic_param_info (type->type->data.generic_param);
2910         for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2911                 ;
2912
2913         res = mono_array_new_checked (domain, mono_defaults.monotype_class, count, &error);
2914         if (mono_error_set_pending_exception (&error))
2915                 return NULL;
2916         for (i = 0; i < count; i++) {
2917                 rt = mono_type_get_object_checked (domain, &param_info->constraints [i]->byval_arg, &error);
2918                 if (mono_error_set_pending_exception (&error))
2919                         return NULL;
2920
2921                 mono_array_setref (res, i, rt);
2922         }
2923
2924
2925         return res;
2926 }
2927
2928 ICALL_EXPORT MonoBoolean
2929 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2930 {
2931         return is_generic_parameter (type->type);
2932 }
2933
2934 ICALL_EXPORT MonoBoolean
2935 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2936 {
2937         return is_generic_parameter (tb->type.type);
2938 }
2939
2940 ICALL_EXPORT void
2941 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2942                                                                            MonoReflectionType *t)
2943 {
2944         enumtype->type = t->type;
2945 }
2946
2947 ICALL_EXPORT MonoReflectionMethod*
2948 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type, 
2949                                                    MonoReflectionMethod* generic)
2950 {
2951         MonoDomain *domain; 
2952         MonoClass *klass;
2953         MonoMethod *method;
2954         gpointer iter;
2955         MonoError error;
2956         MonoReflectionMethod *ret = NULL;
2957                 
2958         domain = ((MonoObject *)type)->vtable->domain;
2959
2960         klass = mono_class_from_mono_type (type->type);
2961         mono_class_init_checked (klass, &error);
2962         if (mono_error_set_pending_exception (&error))
2963                 return NULL;
2964
2965         iter = NULL;
2966         while ((method = mono_class_get_methods (klass, &iter))) {
2967                 if (method->token == generic->method->token) {
2968                         ret = mono_method_get_object_checked (domain, method, klass, &error);
2969                         if (mono_error_set_pending_exception (&error))
2970                                 return NULL;
2971                 }
2972         }
2973
2974         return ret;
2975 }
2976
2977 ICALL_EXPORT MonoReflectionMethod *
2978 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2979 {
2980         MonoMethod *method;
2981         MonoType *type = ref_type->type;
2982         MonoError error;
2983         MonoReflectionMethod *ret = NULL;
2984
2985         if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2986                 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2987                 return NULL;
2988         }
2989         if (type->type == MONO_TYPE_VAR)
2990                 return NULL;
2991
2992         method = mono_type_get_generic_param_owner (type)->owner.method;
2993         g_assert (method);
2994
2995         ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2996         if (!mono_error_ok (&error))
2997                 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2998         return ret;
2999 }
3000
3001 ICALL_EXPORT MonoBoolean
3002 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
3003 {
3004         mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3005         return FALSE;
3006 }
3007
3008 ICALL_EXPORT MonoBoolean
3009 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
3010 {
3011         mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3012         return FALSE;
3013 }
3014
3015 ICALL_EXPORT void
3016 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
3017 {
3018         MonoDomain *domain = mono_domain_get ();
3019         MonoImage *image = method->method->klass->image;
3020         MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
3021         MonoTableInfo *tables = image->tables;
3022         MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
3023         MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
3024         guint32 im_cols [MONO_IMPLMAP_SIZE];
3025         guint32 scope_token;
3026         const char *import = NULL;
3027         const char *scope = NULL;
3028
3029         if (image_is_dynamic (image)) {
3030                 MonoReflectionMethodAux *method_aux = 
3031                         (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
3032                 if (method_aux) {
3033                         import = method_aux->dllentry;
3034                         scope = method_aux->dll;
3035                 }
3036
3037                 if (!import || !scope) {
3038                         mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
3039                         return;
3040                 }
3041         }
3042         else {
3043                 if (piinfo->implmap_idx) {
3044                         mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
3045                         
3046                         piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3047                         import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3048                         scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3049                         scope = mono_metadata_string_heap (image, scope_token);
3050                 }
3051         }
3052         
3053         *flags = piinfo->piflags;
3054         *entry_point = mono_string_new (domain, import);
3055         *dll_name = mono_string_new (domain, scope);
3056 }
3057
3058 ICALL_EXPORT MonoReflectionMethod *
3059 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3060 {
3061         MonoMethodInflated *imethod;
3062         MonoMethod *result;
3063         MonoReflectionMethod *ret = NULL;
3064         MonoError error;
3065
3066         if (method->method->is_generic)
3067                 return method;
3068
3069         if (!method->method->is_inflated)
3070                 return NULL;
3071
3072         imethod = (MonoMethodInflated *) method->method;
3073
3074         result = imethod->declaring;
3075         /* Not a generic method.  */
3076         if (!result->is_generic)
3077                 return NULL;
3078
3079         if (image_is_dynamic (method->method->klass->image)) {
3080                 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3081                 MonoReflectionMethod *res;
3082
3083                 /*
3084                  * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3085                  * the dynamic case as well ?
3086                  */
3087                 mono_image_lock ((MonoImage*)image);
3088                 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3089                 mono_image_unlock ((MonoImage*)image);
3090
3091                 if (res)
3092                         return res;
3093         }
3094
3095         if (imethod->context.class_inst) {
3096                 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3097                 /*Generic methods gets the context of the GTD.*/
3098                 if (mono_class_get_context (klass)) {
3099                         result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3100                         if (!mono_error_ok (&error))
3101                                 goto leave;
3102                 }
3103         }
3104
3105         ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3106 leave:
3107         if (!mono_error_ok (&error))
3108                 mono_error_set_pending_exception (&error);
3109         return ret;
3110 }
3111
3112 ICALL_EXPORT gboolean
3113 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3114 {
3115         return mono_method_signature (method->method)->generic_param_count != 0;
3116 }
3117
3118 ICALL_EXPORT gboolean
3119 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3120 {
3121         return method->method->is_generic;
3122 }
3123
3124 ICALL_EXPORT MonoArray*
3125 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3126 {
3127         MonoError error;
3128         MonoReflectionType *rt;
3129         MonoArray *res;
3130         MonoDomain *domain;
3131         int count, i;
3132
3133         domain = mono_object_domain (method);
3134
3135         if (method->method->is_inflated) {
3136                 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3137
3138                 if (inst) {
3139                         count = inst->type_argc;
3140                         res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3141                         if (mono_error_set_pending_exception (&error))
3142                                 return NULL;
3143
3144                         for (i = 0; i < count; i++) {
3145                                 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3146                                 if (mono_error_set_pending_exception (&error))
3147                                         return NULL;
3148
3149                                 mono_array_setref (res, i, rt);
3150                         }
3151
3152                         return res;
3153                 }
3154         }
3155
3156         count = mono_method_signature (method->method)->generic_param_count;
3157         res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3158         if (mono_error_set_pending_exception (&error))
3159                 return NULL;
3160
3161         for (i = 0; i < count; i++) {
3162                 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3163                 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3164                 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3165
3166                 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3167                 if (mono_error_set_pending_exception (&error))
3168                         return NULL;
3169
3170                 mono_array_setref (res, i, rt);
3171         }
3172
3173         return res;
3174 }
3175
3176 ICALL_EXPORT MonoObject *
3177 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc) 
3178 {
3179         MonoError error;
3180         /* 
3181          * Invoke from reflection is supposed to always be a virtual call (the API
3182          * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3183          * greater flexibility.
3184          */
3185         MonoMethod *m = method->method;
3186         MonoMethodSignature *sig = mono_method_signature (m);
3187         MonoImage *image;
3188         int pcount;
3189         void *obj = this_arg;
3190
3191         *exc = NULL;
3192
3193         if (mono_security_core_clr_enabled () &&
3194             !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3195                 mono_error_set_pending_exception (&error);
3196                 return NULL;
3197         }
3198
3199         if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3200                 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3201                         mono_error_cleanup (&error); /* FIXME does this make sense? */
3202                         mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3203                         return NULL;
3204                 }
3205
3206                 if (this_arg) {
3207                         if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3208                                 if (!is_ok (&error)) {
3209                                         mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3210                                         return NULL;
3211                                 }
3212                                 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3213                                 char *target_name = mono_type_get_full_name (m->klass);
3214                                 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3215                                 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3216                                 g_free (msg);
3217                                 g_free (target_name);
3218                                 g_free (this_name);
3219                                 return NULL;
3220                         }
3221                         m = mono_object_get_virtual_method (this_arg, m);
3222                         /* must pass the pointer to the value for valuetype methods */
3223                         if (m->klass->valuetype)
3224                                 obj = mono_object_unbox (this_arg);
3225                 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3226                         mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3227                         return NULL;
3228                 }
3229         }
3230
3231         if (sig->ret->byref) {
3232                 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"));
3233                 return NULL;
3234         }
3235
3236         pcount = params? mono_array_length (params): 0;
3237         if (pcount != sig->param_count) {
3238                 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3239                 return NULL;
3240         }
3241
3242         if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3243                 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."));
3244                 return NULL;
3245         }
3246
3247         image = m->klass->image;
3248         if (image->assembly->ref_only) {
3249                 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."));
3250                 return NULL;
3251         }
3252
3253         if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3254                 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3255                 return NULL;
3256         }
3257         
3258         if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3259                 MonoArray *arr;
3260                 int i;
3261                 uintptr_t *lengths;
3262                 intptr_t *lower_bounds;
3263                 pcount = mono_array_length (params);
3264                 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3265                 /* Note: the synthetized array .ctors have int32 as argument type */
3266                 for (i = 0; i < pcount; ++i)
3267                         lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3268
3269                 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3270                         /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3271                         arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3272                         if (!mono_error_ok (&error)) {
3273                                 mono_error_set_pending_exception (&error);
3274                                 return NULL;
3275                         }
3276
3277                         for (i = 0; i < mono_array_length (arr); ++i) {
3278                                 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3279                                 if (!mono_error_ok (&error)) {
3280                                         mono_error_set_pending_exception (&error);
3281                                         return NULL;
3282                                 }
3283                                 mono_array_setref_fast (arr, i, subarray);
3284                         }
3285                         return (MonoObject*)arr;
3286                 }
3287
3288                 if (m->klass->rank == pcount) {
3289                         /* Only lengths provided. */
3290                         arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3291                         if (!mono_error_ok (&error)) {
3292                                 mono_error_set_pending_exception (&error);
3293                                 return NULL;
3294                         }
3295
3296                         return (MonoObject*)arr;
3297                 } else {
3298                         g_assert (pcount == (m->klass->rank * 2));
3299                         /* The arguments are lower-bound-length pairs */
3300                         lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3301
3302                         for (i = 0; i < pcount / 2; ++i) {
3303                                 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3304                                 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3305                         }
3306
3307                         arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3308                         if (!mono_error_ok (&error)) {
3309                                 mono_error_set_pending_exception (&error);
3310                                 return NULL;
3311                         }
3312
3313                         return (MonoObject*)arr;
3314                 }
3315         }
3316         return mono_runtime_invoke_array (m, obj, params, NULL);
3317 }
3318
3319 #ifndef DISABLE_REMOTING
3320 ICALL_EXPORT MonoObject *
3321 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs) 
3322 {
3323         MonoError error;
3324         MonoDomain *domain = mono_object_domain (method); 
3325         MonoMethod *m = method->method;
3326         MonoMethodSignature *sig = mono_method_signature (m);
3327         MonoArray *out_args;
3328         MonoObject *result;
3329         int i, j, outarg_count = 0;
3330
3331         if (m->klass == mono_defaults.object_class) {
3332                 if (!strcmp (m->name, "FieldGetter")) {
3333                         MonoClass *k = this_arg->vtable->klass;
3334                         MonoString *name;
3335                         char *str;
3336                         
3337                         /* If this is a proxy, then it must be a CBO */
3338                         if (k == mono_defaults.transparent_proxy_class) {
3339                                 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3340                                 this_arg = tp->rp->unwrapped_server;
3341                                 g_assert (this_arg);
3342                                 k = this_arg->vtable->klass;
3343                         }
3344                         
3345                         name = mono_array_get (params, MonoString *, 1);
3346                         str = mono_string_to_utf8 (name);
3347                 
3348                         do {
3349                                 MonoClassField* field = mono_class_get_field_from_name (k, str);
3350                                 if (field) {
3351                                         g_free (str);
3352                                         MonoClass *field_klass =  mono_class_from_mono_type (field->type);
3353                                         if (field_klass->valuetype) {
3354                                                 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3355                                                 if (mono_error_set_pending_exception (&error))
3356                                                         return NULL;
3357                                         } else 
3358                                                 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3359                                 
3360                                         out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3361                                         if (mono_error_set_pending_exception (&error))
3362                                                 return NULL;
3363                                         mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3364                                         mono_array_setref (out_args, 0, result);
3365                                         return NULL;
3366                                 }
3367                                 k = k->parent;
3368                         } while (k);
3369
3370                         g_free (str);
3371                         g_assert_not_reached ();
3372
3373                 } else if (!strcmp (m->name, "FieldSetter")) {
3374                         MonoClass *k = this_arg->vtable->klass;
3375                         MonoString *name;
3376                         guint32 size;
3377                         gint32 align;
3378                         char *str;
3379                         
3380                         /* If this is a proxy, then it must be a CBO */
3381                         if (k == mono_defaults.transparent_proxy_class) {
3382                                 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3383                                 this_arg = tp->rp->unwrapped_server;
3384                                 g_assert (this_arg);
3385                                 k = this_arg->vtable->klass;
3386                         }
3387                         
3388                         name = mono_array_get (params, MonoString *, 1);
3389                         str = mono_string_to_utf8 (name);
3390                 
3391                         do {
3392                                 MonoClassField* field = mono_class_get_field_from_name (k, str);
3393                                 if (field) {
3394                                         g_free (str);
3395                                         MonoClass *field_klass =  mono_class_from_mono_type (field->type);
3396                                         MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3397
3398                                         if (field_klass->valuetype) {
3399                                                 size = mono_type_size (field->type, &align);
3400                                                 g_assert (size == mono_class_value_size (field_klass, NULL));
3401                                                 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3402                                         } else {
3403                                                 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3404                                         }
3405                                 
3406                                         out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3407                                         if (mono_error_set_pending_exception (&error))
3408                                                 return NULL;
3409                                         mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3410
3411                                         return NULL;
3412                                 }
3413                                 
3414                                 k = k->parent;
3415                         } while (k);
3416
3417                         g_free (str);
3418                         g_assert_not_reached ();
3419
3420                 }
3421         }
3422
3423         for (i = 0; i < mono_array_length (params); i++) {
3424                 if (sig->params [i]->byref) 
3425                         outarg_count++;
3426         }
3427
3428         out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3429         if (mono_error_set_pending_exception (&error))
3430                 return NULL;
3431
3432         /* handle constructors only for objects already allocated */
3433         if (!strcmp (method->method->name, ".ctor"))
3434                 g_assert (this_arg);
3435
3436         /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3437         g_assert (!method->method->klass->valuetype);
3438         result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3439
3440         for (i = 0, j = 0; i < mono_array_length (params); i++) {
3441                 if (sig->params [i]->byref) {
3442                         gpointer arg;
3443                         arg = mono_array_get (params, gpointer, i);
3444                         mono_array_setref (out_args, j, arg);
3445                         j++;
3446                 }
3447         }
3448
3449         mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3450
3451         return result;
3452 }
3453 #endif
3454
3455 static guint64
3456 read_enum_value (const char *mem, int type)
3457 {
3458         switch (type) {
3459         case MONO_TYPE_BOOLEAN:
3460         case MONO_TYPE_U1:
3461                 return *(guint8*)mem;
3462         case MONO_TYPE_I1:
3463                 return *(gint8*)mem;
3464         case MONO_TYPE_CHAR:
3465         case MONO_TYPE_U2:
3466                 return read16 (mem);
3467         case MONO_TYPE_I2:
3468                 return (gint16) read16 (mem);
3469         case MONO_TYPE_U4:
3470                 return read32 (mem);
3471         case MONO_TYPE_I4:
3472                 return (gint32) read32 (mem);
3473         case MONO_TYPE_U8:
3474         case MONO_TYPE_I8:
3475                 return read64 (mem);
3476         default:
3477                 g_assert_not_reached ();
3478         }
3479         return 0;
3480 }
3481
3482 static void
3483 write_enum_value (char *mem, int type, guint64 value)
3484 {
3485         switch (type) {
3486         case MONO_TYPE_U1:
3487         case MONO_TYPE_I1: {
3488                 guint8 *p = (guint8*)mem;
3489                 *p = value;
3490                 break;
3491         }
3492         case MONO_TYPE_U2:
3493         case MONO_TYPE_I2:
3494         case MONO_TYPE_CHAR: {
3495                 guint16 *p = (guint16 *)mem;
3496                 *p = value;
3497                 break;
3498         }
3499         case MONO_TYPE_U4:
3500         case MONO_TYPE_I4: {
3501                 guint32 *p = (guint32 *)mem;
3502                 *p = value;
3503                 break;
3504         }
3505         case MONO_TYPE_U8:
3506         case MONO_TYPE_I8: {
3507                 guint64 *p = (guint64 *)mem;
3508                 *p = value;
3509                 break;
3510         }
3511         default:
3512                 g_assert_not_reached ();
3513         }
3514         return;
3515 }
3516
3517 ICALL_EXPORT MonoObject *
3518 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3519 {
3520         MonoError error;
3521         MonoDomain *domain; 
3522         MonoClass *enumc;
3523         MonoObject *res;
3524         MonoType *etype;
3525
3526         domain = mono_object_domain (enumType); 
3527         enumc = mono_class_from_mono_type (enumType->type);
3528
3529         mono_class_init_checked (enumc, &error);
3530         if (mono_error_set_pending_exception (&error))
3531                 return NULL;
3532
3533         etype = mono_class_enum_basetype (enumc);
3534
3535         res = mono_object_new_checked (domain, enumc, &error);
3536         if (mono_error_set_pending_exception (&error))
3537                 return NULL;
3538         write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3539
3540         return res;
3541 }
3542
3543 ICALL_EXPORT MonoBoolean
3544 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3545 {
3546         int size = mono_class_value_size (a->vtable->klass, NULL);
3547         guint64 a_val = 0, b_val = 0;
3548
3549         memcpy (&a_val, mono_object_unbox (a), size);
3550         memcpy (&b_val, mono_object_unbox (b), size);
3551
3552         return (a_val & b_val) == b_val;
3553 }
3554
3555 ICALL_EXPORT MonoObject *
3556 ves_icall_System_Enum_get_value (MonoObject *eobj)
3557 {
3558         MonoError error;
3559         MonoObject *res;
3560         MonoClass *enumc;
3561         gpointer dst;
3562         gpointer src;
3563         int size;
3564
3565         if (!eobj)
3566                 return NULL;
3567
3568         g_assert (eobj->vtable->klass->enumtype);
3569         
3570         enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3571         res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3572         if (mono_error_set_pending_exception (&error))
3573                 return NULL;
3574         dst = (char *)res + sizeof (MonoObject);
3575         src = (char *)eobj + sizeof (MonoObject);
3576         size = mono_class_value_size (enumc, NULL);
3577
3578         memcpy (dst, src, size);
3579
3580         return res;
3581 }
3582
3583 ICALL_EXPORT MonoReflectionType *
3584 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3585 {
3586         MonoError error;
3587         MonoReflectionType *ret;
3588         MonoType *etype;
3589         MonoClass *klass;
3590
3591         klass = mono_class_from_mono_type (type->type);
3592         mono_class_init_checked (klass, &error);
3593         if (mono_error_set_pending_exception (&error))
3594                 return NULL;
3595
3596         etype = mono_class_enum_basetype (klass);
3597         if (!etype) {
3598                 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3599                 return NULL;
3600         }
3601
3602         ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3603         mono_error_set_pending_exception (&error);
3604
3605         return ret;
3606 }
3607
3608 ICALL_EXPORT int
3609 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3610 {
3611         gpointer tdata = (char *)eobj + sizeof (MonoObject);
3612         gpointer odata = (char *)other + sizeof (MonoObject);
3613         MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3614         g_assert (basetype);
3615
3616         if (other == NULL)
3617                 return 1;
3618
3619         if (eobj->vtable->klass != other->vtable->klass)
3620                 return 2;
3621
3622 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3623                 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3624                 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3625                 if (me == other) \
3626                         return 0; \
3627                 return me > other ? 1 : -1; \
3628         } while (0)
3629
3630         switch (basetype->type) {
3631                 case MONO_TYPE_U1:
3632                         COMPARE_ENUM_VALUES (guint8);
3633                 case MONO_TYPE_I1:
3634                         COMPARE_ENUM_VALUES (gint8);
3635                 case MONO_TYPE_CHAR:
3636                 case MONO_TYPE_U2:
3637                         COMPARE_ENUM_VALUES (guint16);
3638                 case MONO_TYPE_I2:
3639                         COMPARE_ENUM_VALUES (gint16);
3640                 case MONO_TYPE_U4:
3641                         COMPARE_ENUM_VALUES (guint32);
3642                 case MONO_TYPE_I4:
3643                         COMPARE_ENUM_VALUES (gint32);
3644                 case MONO_TYPE_U8:
3645                         COMPARE_ENUM_VALUES (guint64);
3646                 case MONO_TYPE_I8:
3647                         COMPARE_ENUM_VALUES (gint64);
3648                 default:
3649                         break;
3650         }
3651 #undef COMPARE_ENUM_VALUES
3652         /* indicates that the enum was of an unsupported unerlying type */
3653         return 3;
3654 }
3655
3656 ICALL_EXPORT int
3657 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3658 {
3659         gpointer data = (char *)eobj + sizeof (MonoObject);
3660         MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3661         g_assert (basetype);
3662
3663         switch (basetype->type) {
3664                 case MONO_TYPE_I1:       {
3665                         gint8 value = *((gint8*)data);
3666                         return ((int)value ^ (int)value << 8);
3667                 }
3668                 case MONO_TYPE_U1:
3669                         return *((guint8*)data);
3670                 case MONO_TYPE_CHAR:
3671                 case MONO_TYPE_U2:
3672                         return *((guint16*)data);
3673                 
3674                 case MONO_TYPE_I2: {
3675                         gint16 value = *((gint16*)data);
3676                         return ((int)(guint16)value | (((int)value) << 16));
3677                 }
3678                 case MONO_TYPE_U4:
3679                         return *((guint32*)data);
3680                 case MONO_TYPE_I4:
3681                         return *((gint32*)data);
3682                 case MONO_TYPE_U8:
3683                 case MONO_TYPE_I8: {
3684                         gint64 value = *((gint64*)data);
3685                         return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3686                 }
3687                 default:
3688                         g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3689         }
3690         return 0;
3691 }
3692
3693 ICALL_EXPORT MonoBoolean
3694 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3695 {
3696         MonoError error;
3697         MonoDomain *domain = mono_object_domain (type); 
3698         MonoClass *enumc = mono_class_from_mono_type (type->type);
3699         guint j = 0, nvalues;
3700         gpointer iter;
3701         MonoClassField *field;
3702         int base_type;
3703         guint64 field_value, previous_value = 0;
3704         gboolean sorted = TRUE;
3705
3706         mono_class_init_checked (enumc, &error);
3707         if (mono_error_set_pending_exception (&error))
3708                 return FALSE;
3709
3710
3711         if (!enumc->enumtype) {
3712                 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3713                 return TRUE;
3714         }
3715
3716         base_type = mono_class_enum_basetype (enumc)->type;
3717
3718         nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3719         *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3720         if (mono_error_set_pending_exception (&error))
3721                 return FALSE;
3722         *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3723         if (mono_error_set_pending_exception (&error))
3724                 return FALSE;
3725
3726         iter = NULL;
3727         while ((field = mono_class_get_fields (enumc, &iter))) {
3728                 const char *p;
3729                 MonoTypeEnum def_type;
3730
3731                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3732                         continue;
3733                 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3734                         continue;
3735                 if (mono_field_is_deleted (field))
3736                         continue;
3737                 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3738
3739                 p = mono_class_get_field_default_value (field, &def_type);
3740                 /* len = */ mono_metadata_decode_blob_size (p, &p);
3741
3742                 field_value = read_enum_value (p, base_type);
3743                 mono_array_set (*values, guint64, j, field_value);
3744
3745                 if (previous_value > field_value)
3746                         sorted = FALSE;
3747
3748                 previous_value = field_value;
3749                 ++j;
3750         }
3751
3752         return sorted;
3753 }
3754
3755 enum {
3756         BFLAGS_IgnoreCase = 1,
3757         BFLAGS_DeclaredOnly = 2,
3758         BFLAGS_Instance = 4,
3759         BFLAGS_Static = 8,
3760         BFLAGS_Public = 0x10,
3761         BFLAGS_NonPublic = 0x20,
3762         BFLAGS_FlattenHierarchy = 0x40,
3763         BFLAGS_InvokeMethod = 0x100,
3764         BFLAGS_CreateInstance = 0x200,
3765         BFLAGS_GetField = 0x400,
3766         BFLAGS_SetField = 0x800,
3767         BFLAGS_GetProperty = 0x1000,
3768         BFLAGS_SetProperty = 0x2000,
3769         BFLAGS_ExactBinding = 0x10000,
3770         BFLAGS_SuppressChangeType = 0x20000,
3771         BFLAGS_OptionalParamBinding = 0x40000
3772 };
3773
3774 ICALL_EXPORT MonoArray*
3775 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3776 {
3777         MonoError error;
3778         MonoDomain *domain; 
3779         MonoClass *startklass, *klass, *refklass;
3780         MonoArray *res;
3781         MonoObject *member;
3782         int i, match;
3783         gpointer iter;
3784         char *utf8_name = NULL;
3785         int (*compare_func) (const char *s1, const char *s2) = NULL;    
3786         MonoClassField *field;
3787         MonoPtrArray tmp_array;
3788
3789         domain = ((MonoObject *)type)->vtable->domain;
3790         if (type->type->byref) {
3791                 MonoArray *result = mono_array_new_checked (domain, mono_defaults.field_info_class, 0, &error);
3792                 mono_error_set_pending_exception (&error);
3793                 return result;
3794         }
3795
3796         klass = startklass = mono_class_from_mono_type (type->type);
3797         refklass = mono_class_from_mono_type (reftype->type);
3798
3799         mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3800         
3801 handle_parent:  
3802         if (mono_class_has_failure (klass)) {
3803                 mono_ptr_array_destroy (tmp_array);
3804                 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3805                 return NULL;
3806         }
3807
3808         iter = NULL;
3809         while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3810                 guint32 flags = mono_field_get_flags (field);
3811                 match = 0;
3812                 if (mono_field_is_deleted_with_flags (field, flags))
3813                         continue;
3814                 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3815                         if (bflags & BFLAGS_Public)
3816                                 match++;
3817                 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3818                         if (bflags & BFLAGS_NonPublic) {
3819                                 match++;
3820                         }
3821                 }
3822                 if (!match)
3823                         continue;
3824                 match = 0;
3825                 if (flags & FIELD_ATTRIBUTE_STATIC) {
3826                         if (bflags & BFLAGS_Static)
3827                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3828                                         match++;
3829                 } else {
3830                         if (bflags & BFLAGS_Instance)
3831                                 match++;
3832                 }
3833
3834                 if (!match)
3835                         continue;
3836
3837                 if (name != NULL) {
3838                         if (utf8_name == NULL) {
3839                                 utf8_name = mono_string_to_utf8 (name);
3840                                 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3841                         }
3842
3843                         if (compare_func (mono_field_get_name (field), utf8_name))
3844                                 continue;
3845                 }
3846
3847                 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3848                 if (!mono_error_ok (&error))
3849                     goto fail;
3850                 mono_ptr_array_append (tmp_array, member);
3851         }
3852         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3853                 goto handle_parent;
3854
3855         res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array), &error);
3856         if (!is_ok (&error))
3857                 goto fail;
3858
3859         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3860                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3861
3862         mono_ptr_array_destroy (tmp_array);
3863
3864         if (utf8_name != NULL)
3865                 g_free (utf8_name);
3866
3867         return res;
3868 fail:
3869         mono_ptr_array_destroy (tmp_array);
3870         mono_error_set_pending_exception (&error);
3871         return NULL;
3872 }
3873
3874 static gboolean
3875 method_nonpublic (MonoMethod* method, gboolean start_klass)
3876 {
3877         switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3878                 case METHOD_ATTRIBUTE_ASSEM:
3879                         return (start_klass || mono_defaults.generic_ilist_class);
3880                 case METHOD_ATTRIBUTE_PRIVATE:
3881                         return start_klass;
3882                 case METHOD_ATTRIBUTE_PUBLIC:
3883                         return FALSE;
3884                 default:
3885                         return TRUE;
3886         }
3887 }
3888
3889 GPtrArray*
3890 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3891 {
3892         GPtrArray *array;
3893         MonoClass *startklass;
3894         MonoMethod *method;
3895         gpointer iter;
3896         int match, nslots;
3897         /*FIXME, use MonoBitSet*/
3898         guint32 method_slots_default [8];
3899         guint32 *method_slots = NULL;
3900         int (*compare_func) (const char *s1, const char *s2) = NULL;
3901
3902         array = g_ptr_array_new ();
3903         startklass = klass;
3904         *ex = NULL;
3905
3906         if (name != NULL)
3907                 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3908
3909         /* An optimization for calls made from Delegate:CreateDelegate () */
3910         if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3911                 method = mono_get_delegate_invoke (klass);
3912                 g_assert (method);
3913
3914                 g_ptr_array_add (array, method);
3915                 return array;
3916         }
3917
3918         mono_class_setup_methods (klass);
3919         mono_class_setup_vtable (klass);
3920         if (mono_class_has_failure (klass))
3921                 goto loader_error;
3922
3923         if (is_generic_parameter (&klass->byval_arg))
3924                 nslots = mono_class_get_vtable_size (klass->parent);
3925         else
3926                 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3927         if (nslots >= sizeof (method_slots_default) * 8) {
3928                 method_slots = g_new0 (guint32, nslots / 32 + 1);
3929         } else {
3930                 method_slots = method_slots_default;
3931                 memset (method_slots, 0, sizeof (method_slots_default));
3932         }
3933 handle_parent:
3934         mono_class_setup_methods (klass);
3935         mono_class_setup_vtable (klass);
3936         if (mono_class_has_failure (klass))
3937                 goto loader_error;              
3938
3939         iter = NULL;
3940         while ((method = mono_class_get_methods (klass, &iter))) {
3941                 match = 0;
3942                 if (method->slot != -1) {
3943                         g_assert (method->slot < nslots);
3944                         if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3945                                 continue;
3946                         if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3947                                 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3948                 }
3949
3950                 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3951                         continue;
3952                 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3953                         if (bflags & BFLAGS_Public)
3954                                 match++;
3955                 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3956                                 match++;
3957                 }
3958                 if (!match)
3959                         continue;
3960                 match = 0;
3961                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3962                         if (bflags & BFLAGS_Static)
3963                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3964                                         match++;
3965                 } else {
3966                         if (bflags & BFLAGS_Instance)
3967                                 match++;
3968                 }
3969
3970                 if (!match)
3971                         continue;
3972
3973                 if (name != NULL) {
3974                         if (compare_func (name, method->name))
3975                                 continue;
3976                 }
3977                 
3978                 match = 0;
3979                 g_ptr_array_add (array, method);
3980         }
3981         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3982                 goto handle_parent;
3983         if (method_slots != method_slots_default)
3984                 g_free (method_slots);
3985
3986         return array;
3987
3988 loader_error:
3989         if (method_slots != method_slots_default)
3990                 g_free (method_slots);
3991         g_ptr_array_free (array, TRUE);
3992
3993         if (mono_class_has_failure (klass)) {
3994                 *ex = mono_class_get_exception_for_failure (klass);
3995         } else {
3996                 *ex = mono_get_exception_execution_engine ("Unknown error");
3997         }
3998         return NULL;
3999 }
4000
4001 ICALL_EXPORT MonoArray*
4002 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4003 {
4004         static MonoClass *MethodInfo_array;
4005         MonoError error;
4006         MonoDomain *domain; 
4007         MonoArray *res;
4008         MonoVTable *array_vtable;
4009         MonoException *ex = NULL;
4010         const char *mname = NULL;
4011         GPtrArray *method_array;
4012         MonoClass *klass, *refklass;
4013         int i;
4014
4015         mono_error_init (&error);
4016
4017         if (!MethodInfo_array) {
4018                 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
4019                 mono_memory_barrier ();
4020                 MethodInfo_array = klass;
4021         }
4022
4023         klass = mono_class_from_mono_type (type->type);
4024         refklass = mono_class_from_mono_type (reftype->type);
4025         domain = ((MonoObject *)type)->vtable->domain;
4026         array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
4027         if (!is_ok (&error)) {
4028                 mono_error_set_pending_exception (&error);
4029                 return NULL;
4030         }
4031         if (type->type->byref) {
4032                 res = mono_array_new_specific_checked (array_vtable, 0, &error);
4033                 mono_error_set_pending_exception (&error);
4034
4035                 return res;
4036         }
4037
4038         if (name)
4039                 mname = mono_string_to_utf8 (name);
4040
4041         method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
4042         g_free ((char*)mname);
4043         if (ex) {
4044                 mono_set_pending_exception (ex);
4045                 return NULL;
4046         }
4047
4048         res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
4049         if (!mono_error_ok (&error)) {
4050                 mono_error_set_pending_exception (&error);
4051                 return NULL;
4052         }
4053
4054         for (i = 0; i < method_array->len; ++i) {
4055                 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
4056                 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
4057                 if (!mono_error_ok (&error))
4058                         goto failure;
4059                 mono_array_setref (res, i, rm);
4060         }
4061
4062 failure:
4063         g_ptr_array_free (method_array, TRUE);
4064         if (!mono_error_ok (&error))
4065                 mono_set_pending_exception (mono_error_convert_to_exception (&error));
4066         return res;
4067 }
4068
4069 ICALL_EXPORT MonoArray*
4070 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4071 {
4072         MonoDomain *domain; 
4073         MonoClass *startklass, *klass, *refklass;
4074         MonoArray *res = NULL;
4075         MonoMethod *method;
4076         MonoObject *member;
4077         int i, match;
4078         gpointer iter = NULL;
4079         MonoPtrArray tmp_array;
4080         MonoError error;
4081         
4082         domain = ((MonoObject *)type)->vtable->domain;
4083         if (type->type->byref) {
4084                 res = mono_array_new_cached (domain, mono_defaults.method_info_class, 0, &error);
4085                 mono_error_set_pending_exception (&error);
4086                 return res;
4087         }
4088
4089         mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
4090
4091
4092         klass = startklass = mono_class_from_mono_type (type->type);
4093         refklass = mono_class_from_mono_type (reftype->type);
4094
4095         mono_class_setup_methods (klass);
4096         if (mono_class_has_failure (klass)) {
4097                 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
4098                 goto leave;
4099         }
4100
4101         iter = NULL;
4102         while ((method = mono_class_get_methods (klass, &iter))) {
4103                 match = 0;
4104                 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
4105                         continue;
4106                 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4107                         if (bflags & BFLAGS_Public)
4108                                 match++;
4109                 } else {
4110                         if (bflags & BFLAGS_NonPublic)
4111                                 match++;
4112                 }
4113                 if (!match)
4114                         continue;
4115                 match = 0;
4116                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4117                         if (bflags & BFLAGS_Static)
4118                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4119                                         match++;
4120                 } else {
4121                         if (bflags & BFLAGS_Instance)
4122                                 match++;
4123                 }
4124
4125                 if (!match)
4126                         continue;
4127                 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
4128                 if (mono_error_set_pending_exception (&error))
4129                         goto leave;
4130
4131                 mono_ptr_array_append (tmp_array, member);
4132         }
4133
4134         res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array), &error);
4135         if (mono_error_set_pending_exception (&error))
4136                 goto leave;
4137
4138         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4139                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4140
4141 leave:
4142         mono_ptr_array_destroy (tmp_array);
4143
4144         return res;
4145 }
4146
4147 static guint
4148 property_hash (gconstpointer data)
4149 {
4150         MonoProperty *prop = (MonoProperty*)data;
4151
4152         return g_str_hash (prop->name);
4153 }
4154
4155 static gboolean
4156 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
4157 {
4158         if (method1->is_inflated)
4159                 method1 = ((MonoMethodInflated*) method1)->declaring;
4160         if (method2->is_inflated)
4161                 method2 = ((MonoMethodInflated*) method2)->declaring;
4162
4163         return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4164 }
4165
4166 static gboolean
4167 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4168 {
4169         // Properties are hide-by-name-and-signature
4170         if (!g_str_equal (prop1->name, prop2->name))
4171                 return FALSE;
4172
4173         /* If we see a property in a generic method, we want to
4174            compare the generic signatures, not the inflated signatures
4175            because we might conflate two properties that were
4176            distinct:
4177
4178            class Foo<T,U> {
4179              public T this[T t] { getter { return t; } } // method 1
4180              public U this[U u] { getter { return u; } } // method 2
4181            }
4182
4183            If we see int Foo<int,int>::Item[int] we need to know if
4184            the indexer came from method 1 or from method 2, and we
4185            shouldn't conflate them.   (Bugzilla 36283)
4186         */
4187         if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4188                 return FALSE;
4189
4190         if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4191                 return FALSE;
4192
4193         return TRUE;
4194 }
4195
4196 static gboolean
4197 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4198 {
4199         if (!accessor)
4200                 return FALSE;
4201
4202         return method_nonpublic (accessor, start_klass);
4203 }
4204
4205 ICALL_EXPORT MonoArray*
4206 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4207 {
4208         MonoError error;
4209         MonoDomain *domain; 
4210         MonoClass *startklass, *klass;
4211         MonoArray *res;
4212         MonoMethod *method;
4213         MonoProperty *prop;
4214         int i, match;
4215         guint32 flags;
4216         gchar *propname = NULL;
4217         int (*compare_func) (const char *s1, const char *s2) = NULL;
4218         gpointer iter;
4219         GHashTable *properties = NULL;
4220         MonoPtrArray tmp_array;
4221
4222         mono_error_init (&error);
4223         
4224         domain = ((MonoObject *)type)->vtable->domain;
4225         if (type->type->byref) {
4226                 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), 0, &error);
4227                 mono_error_set_pending_exception (&error);
4228                 return res;
4229         }
4230
4231         mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4232
4233         klass = startklass = mono_class_from_mono_type (type->type);
4234
4235         if (name != NULL) {
4236                 propname = mono_string_to_utf8 (name);
4237                 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4238         }
4239
4240         properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4241 handle_parent:
4242         mono_class_setup_methods (klass);
4243         mono_class_setup_vtable (klass);
4244         if (mono_class_has_failure (klass))
4245                 goto loader_error;
4246
4247         iter = NULL;
4248         while ((prop = mono_class_get_properties (klass, &iter))) {
4249                 match = 0;
4250                 method = prop->get;
4251                 if (!method)
4252                         method = prop->set;
4253                 if (method)
4254                         flags = method->flags;
4255                 else
4256                         flags = 0;
4257                 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4258                         (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4259                         if (bflags & BFLAGS_Public)
4260                                 match++;
4261                 } else if (bflags & BFLAGS_NonPublic) {
4262                         if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4263                                 property_accessor_nonpublic(prop->set, startklass == klass)) {
4264                                 match++;
4265                         }
4266                 }
4267                 if (!match)
4268                         continue;
4269                 match = 0;
4270                 if (flags & METHOD_ATTRIBUTE_STATIC) {
4271                         if (bflags & BFLAGS_Static)
4272                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4273                                         match++;
4274                 } else {
4275                         if (bflags & BFLAGS_Instance)
4276                                 match++;
4277                 }
4278
4279                 if (!match)
4280                         continue;
4281                 match = 0;
4282
4283                 if (name != NULL) {
4284                         if (compare_func (propname, prop->name))
4285                                 continue;
4286                 }
4287                 
4288                 if (g_hash_table_lookup (properties, prop))
4289                         continue;
4290
4291                 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4292                 if (!pr)
4293                         goto failure;
4294                 mono_ptr_array_append (tmp_array, pr);
4295                 
4296                 g_hash_table_insert (properties, prop, prop);
4297         }
4298         if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4299                 goto handle_parent;
4300
4301         g_hash_table_destroy (properties);
4302         g_free (propname);
4303
4304         res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array), &error);
4305         if (!is_ok (&error))
4306                 goto failure;
4307         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4308                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4309
4310         mono_ptr_array_destroy (tmp_array);
4311
4312         return res;
4313
4314
4315
4316 loader_error:
4317         if (mono_class_has_failure (klass)) {
4318                 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4319         }
4320
4321 failure:
4322         if (properties)
4323                 g_hash_table_destroy (properties);
4324         if (name)
4325                 g_free (propname);
4326         mono_ptr_array_destroy (tmp_array);
4327
4328         mono_error_set_pending_exception (&error);
4329
4330         return NULL;
4331 }
4332
4333 static guint
4334 event_hash (gconstpointer data)
4335 {
4336         MonoEvent *event = (MonoEvent*)data;
4337
4338         return g_str_hash (event->name);
4339 }
4340
4341 static gboolean
4342 event_equal (MonoEvent *event1, MonoEvent *event2)
4343 {
4344         // Events are hide-by-name
4345         return g_str_equal (event1->name, event2->name);
4346 }
4347
4348 ICALL_EXPORT MonoArray*
4349 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4350 {
4351         MonoError error;
4352         MonoDomain *domain; 
4353         MonoClass *startklass, *klass;
4354         MonoArray *res;
4355         MonoMethod *method;
4356         MonoEvent *event;
4357         int i, match;
4358         gpointer iter;
4359         char *utf8_name = NULL;
4360         int (*compare_func) (const char *s1, const char *s2) = NULL;    
4361         GHashTable *events = NULL;
4362         MonoPtrArray tmp_array;
4363
4364         mono_error_init (&error);
4365         
4366         domain = mono_object_domain (type);
4367         if (type->type->byref) {
4368                 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), 0, &error);
4369                 mono_error_set_pending_exception (&error);
4370                 return res;
4371         }
4372
4373         mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4374
4375         klass = startklass = mono_class_from_mono_type (type->type);
4376
4377         events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4378 handle_parent:
4379         mono_class_setup_methods (klass);
4380         mono_class_setup_vtable (klass);
4381         if (mono_class_has_failure (klass))
4382                 goto loader_error;
4383
4384         iter = NULL;
4385         while ((event = mono_class_get_events (klass, &iter))) {
4386                 match = 0;
4387                 method = event->add;
4388                 if (!method)
4389                         method = event->remove;
4390                 if (!method)
4391                         method = event->raise;
4392                 if (method) {
4393                         if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4394                                 if (bflags & BFLAGS_Public)
4395                                         match++;
4396                         } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4397                                 if (bflags & BFLAGS_NonPublic)
4398                                         match++;
4399                         }
4400                 }
4401                 else
4402                         if (bflags & BFLAGS_NonPublic)
4403                                 match ++;
4404                 if (!match)
4405                         continue;
4406                 match = 0;
4407                 if (method) {
4408                         if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4409                                 if (bflags & BFLAGS_Static)
4410                                         if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4411                                                 match++;
4412                         } else {
4413                                 if (bflags & BFLAGS_Instance)
4414                                         match++;
4415                         }
4416                 }
4417                 else
4418                         if (bflags & BFLAGS_Instance)
4419                                 match ++;
4420                 if (!match)
4421                         continue;
4422
4423                 if (name != NULL) {
4424                         if (utf8_name == NULL) {
4425                                 utf8_name = mono_string_to_utf8 (name);
4426                                 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4427                         }
4428
4429                         if (compare_func (event->name, utf8_name))
4430                                 continue;
4431                 }               
4432
4433                 if (g_hash_table_lookup (events, event))
4434                         continue;
4435
4436                 MonoReflectionEvent *ev_obj;
4437                 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4438                 if (!ev_obj)
4439                         goto failure;
4440                 mono_ptr_array_append (tmp_array, ev_obj);
4441
4442                 g_hash_table_insert (events, event, event);
4443         }
4444         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4445                 goto handle_parent;
4446
4447         g_hash_table_destroy (events);
4448
4449         res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array), &error);
4450         if (!is_ok (&error))
4451                 goto failure;
4452
4453         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4454                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4455
4456         mono_ptr_array_destroy (tmp_array);
4457
4458         if (utf8_name != NULL)
4459                 g_free (utf8_name);
4460
4461         return res;
4462
4463 loader_error:
4464         if (mono_class_has_failure (klass)) {
4465                 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4466         }
4467
4468 failure:
4469         
4470         if (events != NULL)
4471                 g_hash_table_destroy (events);
4472         if (utf8_name != NULL)
4473                 g_free (utf8_name);
4474
4475         mono_ptr_array_destroy (tmp_array);
4476
4477         mono_error_set_pending_exception (&error);
4478         return NULL;
4479 }
4480
4481 ICALL_EXPORT MonoArray*
4482 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4483 {
4484         MonoError error;
4485         MonoReflectionType *rt;
4486         MonoDomain *domain; 
4487         MonoClass *klass;
4488         MonoArray *res = NULL;
4489         int i, match;
4490         MonoClass *nested;
4491         gpointer iter;
4492         char *str = NULL;
4493         MonoPtrArray tmp_array;
4494
4495         mono_error_init (&error);
4496
4497         domain = ((MonoObject *)type)->vtable->domain;
4498         if (type->type->byref) {
4499                 MonoArray *result = mono_array_new_cached (domain, mono_defaults.monotype_class, 0, &error);
4500                 mono_error_set_pending_exception (&error);
4501                 return result;
4502         }
4503         klass = mono_class_from_mono_type (type->type);
4504
4505         /*
4506          * If a nested type is generic, return its generic type definition.
4507          * Note that this means that the return value is essentially the set
4508          * of nested types of the generic type definition of @klass.
4509          *
4510          * A note in MSDN claims that a generic type definition can have
4511          * nested types that aren't generic.  In any case, the container of that
4512          * nested type would be the generic type definition.
4513          */
4514         if (klass->generic_class)
4515                 klass = klass->generic_class->container_class;
4516
4517         mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4518         iter = NULL;
4519         while ((nested = mono_class_get_nested_types (klass, &iter))) {
4520                 match = 0;
4521                 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4522                         if (bflags & BFLAGS_Public)
4523                                 match++;
4524                 } else {
4525                         if (bflags & BFLAGS_NonPublic)
4526                                 match++;
4527                 }
4528                 if (!match)
4529                         continue;
4530
4531                 if (name != NULL) {
4532                         if (str == NULL) {
4533                                 str = mono_string_to_utf8 (name);
4534                                 mono_identifier_unescape_type_name_chars (str);
4535                         }
4536
4537                         if (strcmp (nested->name, str))
4538                                 continue;
4539                 }
4540
4541                 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4542                 if (!is_ok (&error))
4543                         goto leave;
4544
4545                 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4546         }
4547
4548         res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array), &error);
4549         if (!is_ok (&error))
4550                 goto leave;
4551
4552         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4553                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4554
4555 leave:
4556         mono_ptr_array_destroy (tmp_array);
4557
4558         g_free (str);
4559
4560         mono_error_set_pending_exception (&error);
4561         return res;
4562 }
4563
4564 ICALL_EXPORT MonoReflectionType*
4565 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4566 {
4567         MonoError error;
4568         MonoReflectionType *ret;
4569         gchar *str;
4570         MonoType *type = NULL;
4571         MonoTypeNameParse info;
4572         gboolean type_resolve;
4573
4574         /* On MS.NET, this does not fire a TypeResolve event */
4575         type_resolve = TRUE;
4576         str = mono_string_to_utf8 (name);
4577         /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4578         if (!mono_reflection_parse_type (str, &info)) {
4579                 g_free (str);
4580                 mono_reflection_free_type_info (&info);
4581                 if (throwOnError) {
4582                         mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4583                         return NULL;
4584                 }
4585                 /*g_print ("failed parse\n");*/
4586                 return NULL;
4587         }
4588
4589         if (info.assembly.name) {
4590                 g_free (str);
4591                 mono_reflection_free_type_info (&info);
4592                 if (throwOnError) {
4593                         /* 1.0 and 2.0 throw different exceptions */
4594                         if (mono_defaults.generic_ilist_class)
4595                                 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4596                         else
4597                                 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4598                         return NULL;
4599                 }
4600                 return NULL;
4601         }
4602
4603         if (module != NULL) {
4604                 if (module->image) {
4605                         type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4606                         if (!is_ok (&error)) {
4607                                 g_free (str);
4608                                 mono_reflection_free_type_info (&info);
4609                                 mono_error_set_pending_exception (&error);
4610                                 return NULL;
4611                         }
4612                 } else
4613                         type = NULL;
4614         }
4615         else
4616                 if (assembly_is_dynamic (assembly->assembly)) {
4617                         /* Enumerate all modules */
4618                         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4619                         int i;
4620
4621                         type = NULL;
4622                         if (abuilder->modules) {
4623                                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4624                                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4625                                         type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4626                                         if (!is_ok (&error)) {
4627                                                 g_free (str);
4628                                                 mono_reflection_free_type_info (&info);
4629                                                 mono_error_set_pending_exception (&error);
4630                                                 return NULL;
4631                                         }
4632                                         if (type)
4633                                                 break;
4634                                 }
4635                         }
4636
4637                         if (!type && abuilder->loaded_modules) {
4638                                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4639                                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4640                                         type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4641                                         if (!is_ok (&error)) {
4642                                                 g_free (str);
4643                                                 mono_reflection_free_type_info (&info);
4644                                                 mono_error_set_pending_exception (&error);
4645                                                 return NULL;
4646                                         }
4647                                         if (type)
4648                                                 break;
4649                                 }
4650                         }
4651                 }
4652                 else {
4653                         type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4654                         if (!is_ok (&error)) {
4655                                 g_free (str);
4656                                 mono_reflection_free_type_info (&info);
4657                                 mono_error_set_pending_exception (&error);
4658                                 return NULL;
4659                         }
4660                 }
4661         g_free (str);
4662         mono_reflection_free_type_info (&info);
4663         if (!type) {
4664                 MonoException *e = NULL;
4665                 
4666                 if (throwOnError)
4667                         e = mono_get_exception_type_load (name, NULL);
4668
4669                 if (e != NULL)
4670                         mono_set_pending_exception (e);
4671                 return NULL;
4672         }
4673
4674         if (type->type == MONO_TYPE_CLASS) {
4675                 MonoClass *klass = mono_type_get_class (type);
4676
4677                 /* need to report exceptions ? */
4678                 if (throwOnError && mono_class_has_failure (klass)) {
4679                         /* report SecurityException (or others) that occured when loading the assembly */
4680                         MonoException *exc = mono_class_get_exception_for_failure (klass);
4681                         mono_set_pending_exception (exc);
4682                         return NULL;
4683                 }
4684         }
4685
4686         /* g_print ("got it\n"); */
4687         ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4688         mono_error_set_pending_exception (&error);
4689
4690         return ret;
4691 }
4692
4693 static gboolean
4694 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4695 {
4696         gchar *content;
4697         gchar *shadow_ini_file;
4698         gsize len;
4699
4700         /* Check for shadow-copied assembly */
4701         if (mono_is_shadow_copy_enabled (domain, dirname)) {
4702                 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4703                 content = NULL;
4704                 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4705                         !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4706                         if (content) {
4707                                 g_free (content);
4708                                 content = NULL;
4709                         }
4710                 }
4711                 g_free (shadow_ini_file);
4712                 if (content != NULL) {
4713                         if (*filename)
4714                                 g_free (*filename);
4715                         *filename = content;
4716                         return TRUE;
4717                 }
4718         }
4719         return FALSE;
4720 }
4721
4722 ICALL_EXPORT MonoString *
4723 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4724 {
4725         MonoDomain *domain = mono_object_domain (assembly); 
4726         MonoAssembly *mass = assembly->assembly;
4727         MonoString *res = NULL;
4728         gchar *uri;
4729         gchar *absolute;
4730         gchar *dirname;
4731         
4732         if (g_path_is_absolute (mass->image->name)) {
4733                 absolute = g_strdup (mass->image->name);
4734                 dirname = g_path_get_dirname (absolute);
4735         } else {
4736                 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4737                 dirname = g_strdup (mass->basedir);
4738         }
4739
4740         replace_shadow_path (domain, dirname, &absolute);
4741         g_free (dirname);
4742 #if HOST_WIN32
4743         {
4744                 gint i;
4745                 for (i = strlen (absolute) - 1; i >= 0; i--)
4746                         if (absolute [i] == '\\')
4747                                 absolute [i] = '/';
4748         }
4749 #endif
4750         if (escaped) {
4751                 uri = g_filename_to_uri (absolute, NULL, NULL);
4752         } else {
4753                 const char *prepend = "file://";
4754 #if HOST_WIN32
4755                 if (*absolute == '/' && *(absolute + 1) == '/') {
4756                         prepend = "file:";
4757                 } else {
4758                         prepend = "file:///";
4759                 }
4760 #endif
4761                 uri = g_strconcat (prepend, absolute, NULL);
4762         }
4763
4764         if (uri) {
4765                 res = mono_string_new (domain, uri);
4766                 g_free (uri);
4767         }
4768         g_free (absolute);
4769         return res;
4770 }
4771
4772 ICALL_EXPORT MonoBoolean
4773 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4774 {
4775         MonoAssembly *mass = assembly->assembly;
4776
4777         return mass->in_gac;
4778 }
4779
4780 ICALL_EXPORT MonoReflectionAssembly*
4781 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4782 {
4783         MonoError error;
4784         gchar *name;
4785         MonoAssembly *res;
4786         MonoImageOpenStatus status;
4787         MonoReflectionAssembly* result = NULL;
4788         
4789         name = mono_string_to_utf8 (mname);
4790         res = mono_assembly_load_with_partial_name (name, &status);
4791
4792         g_free (name);
4793
4794         if (res == NULL)
4795                 return NULL;
4796         result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4797         if (!result)
4798                 mono_error_set_pending_exception (&error);
4799         return result;
4800 }
4801
4802 ICALL_EXPORT MonoString *
4803 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4804 {
4805         MonoDomain *domain = mono_object_domain (assembly); 
4806         MonoString *res;
4807
4808         res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4809
4810         return res;
4811 }
4812
4813 ICALL_EXPORT MonoBoolean
4814 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4815 {
4816         return assembly->assembly->ref_only;
4817 }
4818
4819 ICALL_EXPORT MonoString *
4820 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4821 {
4822         MonoDomain *domain = mono_object_domain (assembly); 
4823
4824         return mono_string_new (domain, assembly->assembly->image->version);
4825 }
4826
4827 ICALL_EXPORT MonoReflectionMethod*
4828 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly) 
4829 {
4830         MonoError error;
4831         MonoReflectionMethod *res = NULL;
4832         MonoMethod *method;
4833
4834         guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4835
4836         if (!token)
4837                 return NULL;
4838         method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4839         if (!mono_error_ok (&error))
4840                 goto leave;
4841
4842         res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4843
4844 leave:
4845         if (!mono_error_ok (&error))
4846                 mono_error_set_pending_exception (&error);
4847         return res;
4848 }
4849
4850 ICALL_EXPORT MonoReflectionModule*
4851 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly) 
4852 {
4853         MonoError error;
4854         MonoReflectionModule *result = NULL;
4855         result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4856         if (!mono_error_ok (&error))
4857                 mono_error_set_pending_exception (&error);
4858         return result;
4859 }
4860
4861 ICALL_EXPORT MonoArray*
4862 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly) 
4863 {
4864         MonoError error;
4865         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4866         MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4867         if (mono_error_set_pending_exception (&error))
4868                 return NULL;
4869         int i;
4870         const char *val;
4871
4872         for (i = 0; i < table->rows; ++i) {
4873                 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4874                 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4875         }
4876         return result;
4877 }
4878
4879 static MonoObject*
4880 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4881 {
4882         static MonoMethod *create_version = NULL;
4883         MonoObject *result;
4884         gpointer args [4];
4885
4886         mono_error_init (error);
4887         
4888
4889         if (!create_version) {
4890                 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4891                 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4892                 g_assert (create_version);
4893                 mono_method_desc_free (desc);
4894         }
4895
4896         args [0] = &major;
4897         args [1] = &minor;
4898         args [2] = &build;
4899         args [3] = &revision;
4900         result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4901         return_val_if_nok (error, NULL);
4902
4903         mono_runtime_invoke_checked (create_version, result, args, error);
4904         return_val_if_nok (error, NULL);
4905
4906         return result;
4907 }
4908
4909 ICALL_EXPORT MonoArray*
4910 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly) 
4911 {
4912         MonoError error;
4913         MonoArray *result;
4914         MonoDomain *domain = mono_object_domain (assembly);
4915         int i, count = 0;
4916         static MonoMethod *create_culture = NULL;
4917         MonoImage *image = assembly->assembly->image;
4918         MonoTableInfo *t;
4919         MonoObject *o;
4920
4921         t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4922         count = t->rows;
4923
4924         result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4925         if (mono_error_set_pending_exception (&error))
4926                 return NULL;
4927
4928
4929         if (count > 0 && !create_culture) {
4930                 MonoMethodDesc *desc = mono_method_desc_new (
4931                         "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4932                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4933                 g_assert (create_culture);
4934                 mono_method_desc_free (desc);
4935         }
4936
4937         for (i = 0; i < count; i++) {
4938                 MonoObject *version;
4939                 MonoReflectionAssemblyName *aname;
4940                 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4941
4942                 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4943
4944                 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4945                         domain, mono_class_get_assembly_name_class (), &error);
4946                 if (mono_error_set_pending_exception (&error))
4947                         return NULL;
4948
4949                 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4950
4951                 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4952                 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4953                 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4954                 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4955                 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4956                 aname->versioncompat = 1; /* SameMachine (default) */
4957                 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4958
4959                 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4960                 if (mono_error_set_pending_exception (&error))
4961                         return NULL;
4962
4963                 MONO_OBJECT_SETREF (aname, version, version);
4964
4965                 if (create_culture) {
4966                         gpointer args [2];
4967                         MonoBoolean assembly_ref = 1;
4968                         args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4969                         args [1] = &assembly_ref;
4970
4971                         o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4972                         if (mono_error_set_pending_exception (&error))
4973                                 return NULL;
4974
4975                         MONO_OBJECT_SETREF (aname, cultureInfo, o);
4976                 }
4977                 
4978                 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4979                         const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4980                         guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4981
4982                         if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4983                                 /* public key token isn't copied - the class library will 
4984                                 automatically generate it from the public key if required */
4985                                 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4986                                 if (mono_error_set_pending_exception (&error))
4987                                         return NULL;
4988
4989                                 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4990                                 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4991                         } else {
4992                                 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4993                                 if (mono_error_set_pending_exception (&error))
4994                                         return NULL;
4995
4996                                 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4997                                 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
4998                         }
4999                 } else {
5000                         MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
5001                         if (mono_error_set_pending_exception (&error))
5002                                 return NULL;
5003
5004                         MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5005                 }
5006                 
5007                 /* note: this function doesn't return the codebase on purpose (i.e. it can
5008                          be used under partial trust as path information isn't present). */
5009
5010                 mono_array_setref (result, i, aname);
5011         }
5012         return result;
5013 }
5014
5015 /* move this in some file in mono/util/ */
5016 static char *
5017 g_concat_dir_and_file (const char *dir, const char *file)
5018 {
5019         g_return_val_if_fail (dir != NULL, NULL);
5020         g_return_val_if_fail (file != NULL, NULL);
5021
5022         /*
5023          * If the directory name doesn't have a / on the end, we need
5024          * to add one so we get a proper path to the file
5025          */
5026         if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
5027                 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
5028         else
5029                 return g_strconcat (dir, file, NULL);
5030 }
5031
5032 ICALL_EXPORT void *
5033 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module) 
5034 {
5035         MonoError error;
5036         char *n = mono_string_to_utf8 (name);
5037         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5038         guint32 i;
5039         guint32 cols [MONO_MANIFEST_SIZE];
5040         guint32 impl, file_idx;
5041         const char *val;
5042         MonoImage *module;
5043
5044         for (i = 0; i < table->rows; ++i) {
5045                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5046                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5047                 if (strcmp (val, n) == 0)
5048                         break;
5049         }
5050         g_free (n);
5051         if (i == table->rows)
5052                 return NULL;
5053         /* FIXME */
5054         impl = cols [MONO_MANIFEST_IMPLEMENTATION];
5055         if (impl) {
5056                 /*
5057                  * this code should only be called after obtaining the 
5058                  * ResourceInfo and handling the other cases.
5059                  */
5060                 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
5061                 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
5062
5063                 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
5064                 if (!module)
5065                         return NULL;
5066         }
5067         else
5068                 module = assembly->assembly->image;
5069
5070         
5071         MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
5072         if (mono_error_set_pending_exception (&error))
5073                 return NULL;
5074         mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
5075
5076         return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
5077 }
5078
5079 ICALL_EXPORT gboolean
5080 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
5081 {
5082         MonoError error;
5083         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5084         int i;
5085         guint32 cols [MONO_MANIFEST_SIZE];
5086         guint32 file_cols [MONO_FILE_SIZE];
5087         const char *val;
5088         char *n;
5089
5090         n = mono_string_to_utf8 (name);
5091         for (i = 0; i < table->rows; ++i) {
5092                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5093                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5094                 if (strcmp (val, n) == 0)
5095                         break;
5096         }
5097         g_free (n);
5098         if (i == table->rows)
5099                 return FALSE;
5100
5101         if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
5102                 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
5103         }
5104         else {
5105                 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
5106                 case MONO_IMPLEMENTATION_FILE:
5107                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5108                         table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5109                         mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
5110                         val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
5111                         MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
5112                         if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
5113                                 info->location = 0;
5114                         else
5115                                 info->location = RESOURCE_LOCATION_EMBEDDED;
5116                         break;
5117
5118                 case MONO_IMPLEMENTATION_ASSEMBLYREF:
5119                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5120                         mono_assembly_load_reference (assembly->assembly->image, i - 1);
5121                         if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
5122                                 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
5123                                 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
5124                                 g_free (msg);
5125                                 mono_set_pending_exception (ex);
5126                                 return FALSE;
5127                         }
5128                         MonoReflectionAssembly *assm_obj;
5129                         assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5130                         if (!assm_obj) {
5131                                 mono_error_set_pending_exception (&error);
5132                                 return FALSE;
5133                         }
5134                         MONO_OBJECT_SETREF (info, assembly, assm_obj);
5135
5136                         /* Obtain info recursively */
5137                         ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5138                         info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5139                         break;
5140
5141                 case MONO_IMPLEMENTATION_EXP_TYPE:
5142                         g_assert_not_reached ();
5143                         break;
5144                 }
5145         }
5146
5147         return TRUE;
5148 }
5149
5150 ICALL_EXPORT MonoObject*
5151 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules) 
5152 {
5153         MonoError error;
5154         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5155         MonoArray *result = NULL;
5156         int i, count;
5157         const char *val;
5158         char *n;
5159
5160         /* check hash if needed */
5161         if (name) {
5162                 n = mono_string_to_utf8 (name);
5163                 for (i = 0; i < table->rows; ++i) {
5164                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5165                         if (strcmp (val, n) == 0) {
5166                                 MonoString *fn;
5167                                 g_free (n);
5168                                 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5169                                 fn = mono_string_new (mono_object_domain (assembly), n);
5170                                 g_free (n);
5171                                 return (MonoObject*)fn;
5172                         }
5173                 }
5174                 g_free (n);
5175                 return NULL;
5176         }
5177
5178         count = 0;
5179         for (i = 0; i < table->rows; ++i) {
5180                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5181                         count ++;
5182         }
5183
5184         result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
5185         if (mono_error_set_pending_exception (&error))
5186                 return NULL;
5187
5188
5189         count = 0;
5190         for (i = 0; i < table->rows; ++i) {
5191                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5192                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5193                         n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5194                         mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5195                         g_free (n);
5196                         count ++;
5197                 }
5198         }
5199         return (MonoObject*)result;
5200 }
5201
5202 ICALL_EXPORT MonoArray*
5203 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5204 {
5205         MonoError error;
5206         MonoDomain *domain = mono_domain_get();
5207         MonoArray *res;
5208         MonoClass *klass;
5209         int i, j, file_count = 0;
5210         MonoImage **modules;
5211         guint32 module_count, real_module_count;
5212         MonoTableInfo *table;
5213         guint32 cols [MONO_FILE_SIZE];
5214         MonoImage *image = assembly->assembly->image;
5215
5216         g_assert (image != NULL);
5217         g_assert (!assembly_is_dynamic (assembly->assembly));
5218
5219         table = &image->tables [MONO_TABLE_FILE];
5220         file_count = table->rows;
5221
5222         modules = image->modules;
5223         module_count = image->module_count;
5224
5225         real_module_count = 0;
5226         for (i = 0; i < module_count; ++i)
5227                 if (modules [i])
5228                         real_module_count ++;
5229
5230         klass = mono_class_get_module_class ();
5231         res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5232         if (mono_error_set_pending_exception (&error))
5233                 return NULL;
5234
5235         MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5236         if (mono_error_set_pending_exception (&error))
5237                 return NULL;
5238
5239         mono_array_setref (res, 0, image_obj);
5240         j = 1;
5241         for (i = 0; i < module_count; ++i)
5242                 if (modules [i]) {
5243                         MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5244                         if (mono_error_set_pending_exception (&error))
5245                                 return NULL;
5246                         mono_array_setref (res, j, rm);
5247                         ++j;
5248                 }
5249
5250         for (i = 0; i < file_count; ++i, ++j) {
5251                 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5252                 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5253                         MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5254                         if (mono_error_set_pending_exception (&error))
5255                                 return NULL;
5256                         mono_array_setref (res, j, rm);
5257                 }
5258                 else {
5259                         MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5260                         if (!m) {
5261                                 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5262                                 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5263                                 return NULL;
5264                         }
5265                         MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5266                         if (mono_error_set_pending_exception (&error))
5267                                 return NULL;
5268                         mono_array_setref (res, j, rm);
5269                 }
5270         }
5271
5272         return res;
5273 }
5274
5275 ICALL_EXPORT MonoReflectionMethod*
5276 ves_icall_GetCurrentMethod (void) 
5277 {
5278         MonoReflectionMethod *res = NULL;
5279         MonoError error;
5280
5281         MonoMethod *m = mono_method_get_last_managed ();
5282
5283         if (!m) {
5284                 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5285                 return NULL;
5286         }
5287
5288         while (m->is_inflated)
5289                 m = ((MonoMethodInflated*)m)->declaring;
5290
5291         res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5292         mono_error_set_pending_exception (&error);
5293         return res;
5294 }
5295
5296
5297 static MonoMethod*
5298 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5299 {
5300         int offset = -1, i;
5301         if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5302                 MonoError error;
5303                 MonoMethod *result;
5304                 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5305                 //method is inflated, we should inflate it on the other class
5306                 MonoGenericContext ctx;
5307                 ctx.method_inst = inflated->context.method_inst;
5308                 ctx.class_inst = inflated->context.class_inst;
5309                 if (klass->generic_class)
5310                         ctx.class_inst = klass->generic_class->context.class_inst;
5311                 else if (klass->generic_container)
5312                         ctx.class_inst = klass->generic_container->context.class_inst;
5313                 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5314                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5315                 return result;
5316         }
5317
5318         mono_class_setup_methods (method->klass);
5319         if (mono_class_has_failure (method->klass))
5320                 return NULL;
5321         for (i = 0; i < method->klass->method.count; ++i) {
5322                 if (method->klass->methods [i] == method) {
5323                         offset = i;
5324                         break;
5325                 }       
5326         }
5327         mono_class_setup_methods (klass);
5328         if (mono_class_has_failure (klass))
5329                 return NULL;
5330         g_assert (offset >= 0 && offset < klass->method.count);
5331         return klass->methods [offset];
5332 }
5333
5334 ICALL_EXPORT MonoReflectionMethod*
5335 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5336 {
5337         MonoReflectionMethod *res = NULL;
5338         MonoError error;
5339         MonoClass *klass;
5340         if (type) {
5341                 klass = mono_class_from_mono_type (type);
5342                 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass)) 
5343                         return NULL;
5344                 if (method->klass != klass) {
5345                         method = mono_method_get_equivalent_method (method, klass);
5346                         if (!method)
5347                                 return NULL;
5348                 }
5349         } else
5350                 klass = method->klass;
5351         res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5352         mono_error_set_pending_exception (&error);
5353         return res;
5354 }
5355
5356 ICALL_EXPORT MonoReflectionMethodBody*
5357 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5358 {
5359         MonoError error;
5360         MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5361         mono_error_set_pending_exception (&error);
5362         return result;
5363 }
5364
5365 ICALL_EXPORT MonoReflectionAssembly*
5366 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5367 {
5368         MonoError error;
5369         MonoReflectionAssembly *result;
5370         MonoMethod *dest = NULL;
5371
5372         mono_stack_walk_no_il (get_executing, &dest);
5373         g_assert (dest);
5374         result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5375         if (!result)
5376                 mono_error_set_pending_exception (&error);
5377         return result;
5378 }
5379
5380
5381 ICALL_EXPORT MonoReflectionAssembly*
5382 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5383 {
5384         MonoError error;
5385         MonoReflectionAssembly *result;
5386         MonoDomain* domain = mono_domain_get ();
5387
5388         if (!domain->entry_assembly)
5389                 return NULL;
5390
5391         result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5392         if (!result)
5393                 mono_error_set_pending_exception (&error);
5394         return result;
5395 }
5396
5397 ICALL_EXPORT MonoReflectionAssembly*
5398 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5399 {
5400         MonoError error;
5401         MonoMethod *m;
5402         MonoMethod *dest;
5403         MonoReflectionAssembly *result;
5404
5405         dest = NULL;
5406         mono_stack_walk_no_il (get_executing, &dest);
5407         m = dest;
5408         mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5409         if (!dest)
5410                 dest = m;
5411         if (!m) {
5412                 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5413                 return NULL;
5414         }
5415         result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5416         if (!result)
5417                 mono_error_set_pending_exception (&error);
5418         return result;
5419 }
5420
5421 ICALL_EXPORT MonoString *
5422 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5423                                        gboolean assembly_qualified)
5424 {
5425         MonoDomain *domain = mono_object_domain (object); 
5426         MonoTypeNameFormat format;
5427         MonoString *res;
5428         gchar *name;
5429
5430         if (full_name)
5431                 format = assembly_qualified ?
5432                         MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5433                         MONO_TYPE_NAME_FORMAT_FULL_NAME;
5434         else
5435                 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5436  
5437         name = mono_type_get_name_full (object->type, format);
5438         if (!name)
5439                 return NULL;
5440
5441         if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5442                 g_free (name);
5443                 return NULL;
5444         }
5445
5446         res = mono_string_new (domain, name);
5447         g_free (name);
5448
5449         return res;
5450 }
5451
5452 ICALL_EXPORT int
5453 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5454 {
5455         MonoError error;
5456         MonoClass *klass = mono_class_from_mono_type (rfield->type);
5457
5458         mono_class_init_checked (klass, &error);
5459         mono_error_set_pending_exception (&error);
5460         return mono_security_core_clr_class_level (klass);
5461 }
5462
5463 ICALL_EXPORT int
5464 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5465 {
5466         MonoClassField *field = rfield->field;
5467         return mono_security_core_clr_field_level (field, TRUE);
5468 }
5469
5470 ICALL_EXPORT int
5471 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5472 {
5473         MonoMethod *method = rfield->method;
5474         return mono_security_core_clr_method_level (method, TRUE);
5475 }
5476
5477 static void
5478 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)
5479 {
5480         static MonoMethod *create_culture = NULL;
5481         MonoObject *obj;
5482         gpointer args [2];
5483         guint32 pkey_len;
5484         const char *pkey_ptr;
5485         gchar *codebase;
5486         MonoBoolean assembly_ref = 0;
5487
5488         mono_error_init (error);
5489
5490         MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5491         aname->major = name->major;
5492         aname->minor = name->minor;
5493         aname->build = name->build;
5494         aname->flags = name->flags;
5495         aname->revision = name->revision;
5496         aname->hashalg = name->hash_alg;
5497         aname->versioncompat = 1; /* SameMachine (default) */
5498         aname->processor_architecture = name->arch;
5499
5500         if (by_default_version) {
5501                 MonoObject *version;
5502
5503                 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5504                 return_if_nok (error);
5505
5506                 MONO_OBJECT_SETREF (aname, version, version);
5507         }
5508
5509         codebase = NULL;
5510         if (absolute != NULL && *absolute != '\0') {
5511                 const gchar *prepend = "file://";
5512                 gchar *result;
5513
5514                 codebase = g_strdup (absolute);
5515
5516 #if HOST_WIN32
5517                 {
5518                         gint i;
5519                         for (i = strlen (codebase) - 1; i >= 0; i--)
5520                                 if (codebase [i] == '\\')
5521                                         codebase [i] = '/';
5522
5523                         if (*codebase == '/' && *(codebase + 1) == '/') {
5524                                 prepend = "file:";
5525                         } else {
5526                                 prepend = "file:///";
5527                         }
5528                 }
5529 #endif
5530                 result = g_strconcat (prepend, codebase, NULL);
5531                 g_free (codebase);
5532                 codebase = result;
5533         }
5534
5535         if (codebase) {
5536                 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5537                 g_free (codebase);
5538         }
5539
5540         if (!create_culture) {
5541                 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5542                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5543                 g_assert (create_culture);
5544                 mono_method_desc_free (desc);
5545         }
5546
5547         if (name->culture) {
5548                 args [0] = mono_string_new (domain, name->culture);
5549                 args [1] = &assembly_ref;
5550
5551                 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5552                 return_if_nok (error);
5553
5554                 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5555         }
5556
5557         if (name->public_key) {
5558                 pkey_ptr = (char*)name->public_key;
5559                 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5560
5561                 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5562                 return_if_nok (error);
5563                 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5564                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5565                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5566         } else if (default_publickey) {
5567                 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5568                 return_if_nok (error);
5569                 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5570                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5571         }
5572
5573         /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5574         if (name->public_key_token [0]) {
5575                 int i, j;
5576                 char *p;
5577
5578                 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5579                 return_if_nok (error);
5580                 
5581                 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5582                 p = mono_array_addr (keyToken, char, 0);
5583
5584                 for (i = 0, j = 0; i < 8; i++) {
5585                         *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5586                         *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5587                         p++;
5588                 }
5589         } else if (default_token) {
5590                 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5591                 return_if_nok (error);
5592                 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5593         }
5594 }
5595
5596 ICALL_EXPORT MonoString *
5597 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5598 {
5599         MonoDomain *domain = mono_object_domain (assembly); 
5600         MonoAssembly *mass = assembly->assembly;
5601         MonoString *res;
5602         gchar *name;
5603
5604         name = mono_stringify_assembly_name (&mass->aname);
5605         res = mono_string_new (domain, name);
5606         g_free (name);
5607
5608         return res;
5609 }
5610
5611 ICALL_EXPORT void
5612 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5613 {
5614         MonoError error;
5615         gchar *absolute;
5616         MonoAssembly *mass = assembly->assembly;
5617
5618         if (g_path_is_absolute (mass->image->name)) {
5619                 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5620                 mono_error_set_pending_exception (&error);
5621                 return;
5622         }
5623         absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5624
5625         fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5626         mono_error_set_pending_exception (&error);
5627
5628         g_free (absolute);
5629 }
5630
5631 ICALL_EXPORT void
5632 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5633 {
5634         MonoError error;
5635         char *filename;
5636         MonoImageOpenStatus status = MONO_IMAGE_OK;
5637         gboolean res;
5638         MonoImage *image;
5639         MonoAssemblyName name;
5640         char *dirname;
5641
5642         filename = mono_string_to_utf8 (fname);
5643
5644         dirname = g_path_get_dirname (filename);
5645         replace_shadow_path (mono_domain_get (), dirname, &filename);
5646         g_free (dirname);
5647
5648         image = mono_image_open (filename, &status);
5649
5650         if (!image){
5651                 MonoException *exc;
5652
5653                 g_free (filename);
5654                 if (status == MONO_IMAGE_IMAGE_INVALID)
5655                         exc = mono_get_exception_bad_image_format2 (NULL, fname);
5656                 else
5657                         exc = mono_get_exception_file_not_found2 (NULL, fname);
5658                 mono_set_pending_exception (exc);
5659                 return;
5660         }
5661
5662         res = mono_assembly_fill_assembly_name (image, &name);
5663         if (!res) {
5664                 mono_image_close (image);
5665                 g_free (filename);
5666                 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5667                 return;
5668         }
5669
5670         fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5671         mono_error_set_pending_exception (&error);
5672
5673         mono_image_close (image);
5674         g_free (filename);
5675 }
5676
5677 ICALL_EXPORT MonoBoolean
5678 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5679         char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5680 {
5681         MonoBoolean result = FALSE;
5682         MonoDeclSecurityEntry entry;
5683
5684         /* SecurityAction.RequestMinimum */
5685         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5686                 *minimum = entry.blob;
5687                 *minLength = entry.size;
5688                 result = TRUE;
5689         }
5690         /* SecurityAction.RequestOptional */
5691         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5692                 *optional = entry.blob;
5693                 *optLength = entry.size;
5694                 result = TRUE;
5695         }
5696         /* SecurityAction.RequestRefuse */
5697         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5698                 *refused = entry.blob;
5699                 *refLength = entry.size;
5700                 result = TRUE;
5701         }
5702
5703         return result;  
5704 }
5705
5706 static gboolean
5707 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5708 {
5709         guint32 attrs, visibility;
5710         do {
5711                 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5712                 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5713                 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5714                         return FALSE;
5715
5716         } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5717
5718         return TRUE;
5719 }
5720
5721 static MonoArray*
5722 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5723 {
5724         MonoReflectionType *rt;
5725         MonoArray *res;
5726         MonoClass *klass;
5727         MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5728         int i, count;
5729
5730         mono_error_init (error);
5731
5732         /* we start the count from 1 because we skip the special type <Module> */
5733         if (exportedOnly) {
5734                 count = 0;
5735                 for (i = 1; i < tdef->rows; ++i) {
5736                         if (mono_module_type_is_visible (tdef, image, i + 1))
5737                                 count++;
5738                 }
5739         } else {
5740                 count = tdef->rows - 1;
5741         }
5742         res = mono_array_new_checked (domain, mono_defaults.monotype_class, count, error);
5743         return_val_if_nok (error, NULL);
5744         *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5745         return_val_if_nok (error, NULL);
5746         count = 0;
5747         for (i = 1; i < tdef->rows; ++i) {
5748                 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5749                         klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5750                         
5751                         if (klass) {
5752                                 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5753                                 return_val_if_nok (error, NULL);
5754
5755                                 mono_array_setref (res, count, rt);
5756                         } else {
5757                                 MonoException *ex = mono_error_convert_to_exception (error);
5758                                 mono_array_setref (*exceptions, count, ex);
5759                         }
5760                         count++;
5761                 }
5762         }
5763         
5764         return res;
5765 }
5766
5767 ICALL_EXPORT MonoArray*
5768 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5769 {
5770         MonoError error;
5771         MonoArray *res = NULL;
5772         MonoArray *exceptions = NULL;
5773         MonoImage *image = NULL;
5774         MonoTableInfo *table = NULL;
5775         MonoDomain *domain;
5776         GList *list = NULL;
5777         int i, len, ex_count;
5778
5779         domain = mono_object_domain (assembly);
5780
5781         g_assert (!assembly_is_dynamic (assembly->assembly));
5782         image = assembly->assembly->image;
5783         table = &image->tables [MONO_TABLE_FILE];
5784         res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5785         if (mono_error_set_pending_exception (&error))
5786                 return NULL;
5787
5788         /* Append data from all modules in the assembly */
5789         for (i = 0; i < table->rows; ++i) {
5790                 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5791                         MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5792                         if (loaded_image) {
5793                                 MonoArray *ex2;
5794                                 MonoArray *res2;
5795
5796                                 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5797                                 if (mono_error_set_pending_exception (&error))
5798                                         return NULL;
5799
5800
5801                                 /* Append the new types to the end of the array */
5802                                 if (mono_array_length (res2) > 0) {
5803                                         guint32 len1, len2;
5804                                         MonoArray *res3, *ex3;
5805
5806                                         len1 = mono_array_length (res);
5807                                         len2 = mono_array_length (res2);
5808
5809                                         res3 = mono_array_new_checked (domain, mono_defaults.monotype_class, len1 + len2, &error);
5810                                         if (mono_error_set_pending_exception (&error))
5811                                                 return NULL;
5812                                         mono_array_memcpy_refs (res3, 0, res, 0, len1);
5813                                         mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5814                                         res = res3;
5815
5816                                         ex3 = mono_array_new_checked (domain, mono_defaults.monotype_class, len1 + len2, &error);
5817                                         if (mono_error_set_pending_exception (&error))
5818                                                 return NULL;
5819                                         mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5820                                         mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5821                                         exceptions = ex3;
5822                                 }
5823                         }
5824                 }
5825         }
5826
5827         /* the ReflectionTypeLoadException must have all the types (Types property), 
5828          * NULL replacing types which throws an exception. The LoaderException must
5829          * contain all exceptions for NULL items.
5830          */
5831
5832         len = mono_array_length (res);
5833
5834         ex_count = 0;
5835         for (i = 0; i < len; i++) {
5836                 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5837                 MonoClass *klass;
5838
5839                 if (t) {
5840                         klass = mono_type_get_class (t->type);
5841                         if ((klass != NULL) && mono_class_has_failure (klass)) {
5842                                 /* keep the class in the list */
5843                                 list = g_list_append (list, klass);
5844                                 /* and replace Type with NULL */
5845                                 mono_array_setref (res, i, NULL);
5846                         }
5847                 } else {
5848                         ex_count ++;
5849                 }
5850         }
5851
5852         if (list || ex_count) {
5853                 GList *tmp = NULL;
5854                 MonoException *exc = NULL;
5855                 MonoArray *exl = NULL;
5856                 int j, length = g_list_length (list) + ex_count;
5857
5858                 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5859                 if (mono_error_set_pending_exception (&error)) {
5860                         g_list_free (list);
5861                         return NULL;
5862                 }
5863                 /* Types for which mono_class_get_checked () succeeded */
5864                 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5865                         MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5866                         mono_array_setref (exl, i, exc);
5867                 }
5868                 /* Types for which it don't */
5869                 for (j = 0; j < mono_array_length (exceptions); ++j) {
5870                         MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5871                         if (exc) {
5872                                 g_assert (i < length);
5873                                 mono_array_setref (exl, i, exc);
5874                                 i ++;
5875                         }
5876                 }
5877                 g_list_free (list);
5878                 list = NULL;
5879
5880                 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5881                 if (!is_ok (&error)) {
5882                         mono_error_set_pending_exception (&error);
5883                         return NULL;
5884                 }
5885                 mono_set_pending_exception (exc);
5886                 return NULL;
5887         }
5888                 
5889         return res;
5890 }
5891
5892 ICALL_EXPORT gboolean
5893 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5894 {
5895         MonoError error;
5896         MonoAssemblyName aname;
5897         MonoDomain *domain = mono_object_domain (name);
5898         char *val;
5899         gboolean is_version_defined;
5900         gboolean is_token_defined;
5901
5902         aname.public_key = NULL;
5903         val = mono_string_to_utf8 (assname);
5904         if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5905                 g_free ((guint8*) aname.public_key);
5906                 g_free (val);
5907                 return FALSE;
5908         }
5909         
5910         fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5911         mono_error_set_pending_exception (&error);
5912
5913         mono_assembly_name_free (&aname);
5914         g_free ((guint8*) aname.public_key);
5915         g_free (val);
5916
5917         return TRUE;
5918 }
5919
5920 ICALL_EXPORT MonoReflectionType*
5921 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5922 {
5923         MonoError error;
5924         MonoReflectionType *ret;
5925         MonoDomain *domain = mono_object_domain (module); 
5926         MonoClass *klass;
5927
5928         g_assert (module->image);
5929
5930         if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5931                 /* These images do not have a global type */
5932                 return NULL;
5933
5934         klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5935         if (!mono_error_ok (&error)) {
5936                 mono_error_set_pending_exception (&error);
5937                 return NULL;
5938         }
5939
5940         ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5941         if (!mono_error_ok (&error)) {
5942                 mono_error_set_pending_exception (&error);
5943                 return NULL;
5944         }
5945
5946         return ret;
5947 }
5948
5949 ICALL_EXPORT void
5950 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5951 {
5952         /*if (module->image)
5953                 mono_image_close (module->image);*/
5954 }
5955
5956 ICALL_EXPORT MonoString*
5957 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5958 {
5959         MonoDomain *domain = mono_object_domain (module); 
5960
5961         g_assert (module->image);
5962         return mono_string_new (domain, module->image->guid);
5963 }
5964
5965 ICALL_EXPORT gpointer
5966 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5967 {
5968 #ifdef HOST_WIN32
5969         if (module->image && module->image->is_module_handle)
5970                 return module->image->raw_data;
5971 #endif
5972
5973         return (gpointer) (-1);
5974 }
5975
5976 ICALL_EXPORT void
5977 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5978 {
5979         if (image_is_dynamic (image)) {
5980                 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5981                 *pe_kind = dyn->pe_kind;
5982                 *machine = dyn->machine;
5983         }
5984         else {
5985                 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5986                 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5987         }
5988 }
5989
5990 ICALL_EXPORT gint32
5991 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5992 {
5993         return (image->md_version_major << 16) | (image->md_version_minor);
5994 }
5995
5996 ICALL_EXPORT MonoArray*
5997 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5998 {
5999         MonoError error;
6000         MonoArray *exceptions;
6001         int i;
6002
6003         if (!module->image) {
6004                 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.monotype_class, 0, &error);
6005                 mono_error_set_pending_exception (&error);
6006                 return arr;
6007         } else {
6008                 MonoArray *res;
6009
6010                 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
6011                 if (mono_error_set_pending_exception (&error))
6012                         return NULL;
6013
6014                 for (i = 0; i < mono_array_length (exceptions); ++i) {
6015                         MonoException *ex = mono_array_get (exceptions, MonoException *, i);
6016                         if (ex) {
6017                                 mono_set_pending_exception (ex);
6018                                 return NULL;
6019                         }
6020                 }
6021                 return res;
6022         }
6023 }
6024
6025 static gboolean
6026 mono_memberref_is_method (MonoImage *image, guint32 token)
6027 {
6028         if (!image_is_dynamic (image)) {
6029                 guint32 cols [MONO_MEMBERREF_SIZE];
6030                 const char *sig;
6031                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
6032                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
6033                 mono_metadata_decode_blob_size (sig, &sig);
6034                 return (*sig != 0x6);
6035         } else {
6036                 MonoError error;
6037                 MonoClass *handle_class;
6038
6039                 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
6040                         mono_error_cleanup (&error); /* just probing, ignore error */
6041                         return FALSE;
6042                 }
6043
6044                 return mono_defaults.methodhandle_class == handle_class;
6045         }
6046 }
6047
6048 static void
6049 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
6050 {
6051         if (type_args)
6052                 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
6053                                                                       mono_array_addr (type_args, MonoType*, 0));
6054         else
6055                 context->class_inst = NULL;
6056         if (method_args)
6057                 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
6058                                                                        mono_array_addr (method_args, MonoType*, 0));
6059         else
6060                 context->method_inst = NULL;
6061 }
6062
6063 ICALL_EXPORT MonoType*
6064 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6065 {
6066         MonoClass *klass;
6067         int table = mono_metadata_token_table (token);
6068         int index = mono_metadata_token_index (token);
6069         MonoGenericContext context;
6070         MonoError error;
6071
6072         *resolve_error = ResolveTokenError_Other;
6073
6074         /* Validate token */
6075         if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) && 
6076                 (table != MONO_TABLE_TYPESPEC)) {
6077                 *resolve_error = ResolveTokenError_BadTable;
6078                 return NULL;
6079         }
6080
6081         if (image_is_dynamic (image)) {
6082                 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
6083                         klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6084                         mono_error_cleanup (&error);
6085                         return klass ? &klass->byval_arg : NULL;
6086                 }
6087
6088                 init_generic_context_from_args (&context, type_args, method_args);
6089                 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6090                 mono_error_cleanup (&error);
6091                 return klass ? &klass->byval_arg : NULL;
6092         }
6093
6094         if ((index <= 0) || (index > image->tables [table].rows)) {
6095                 *resolve_error = ResolveTokenError_OutOfRange;
6096                 return NULL;
6097         }
6098
6099         init_generic_context_from_args (&context, type_args, method_args);
6100         klass = mono_class_get_checked (image, token, &error);
6101         if (klass)
6102                 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
6103         if (!mono_error_ok (&error)) {
6104                 mono_error_set_pending_exception (&error);
6105                 return NULL;
6106         }
6107
6108         if (klass)
6109                 return &klass->byval_arg;
6110         else
6111                 return NULL;
6112 }
6113
6114 ICALL_EXPORT MonoMethod*
6115 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6116 {
6117         MonoError error;
6118         int table = mono_metadata_token_table (token);
6119         int index = mono_metadata_token_index (token);
6120         MonoGenericContext context;
6121         MonoMethod *method;
6122
6123         *resolve_error = ResolveTokenError_Other;
6124
6125         /* Validate token */
6126         if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) && 
6127                 (table != MONO_TABLE_MEMBERREF)) {
6128                 *resolve_error = ResolveTokenError_BadTable;
6129                 return NULL;
6130         }
6131
6132         if (image_is_dynamic (image)) {
6133                 if (table == MONO_TABLE_METHOD) {
6134                         method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6135                         mono_error_cleanup (&error);
6136                         return method;
6137                 }
6138
6139                 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
6140                         *resolve_error = ResolveTokenError_BadTable;
6141                         return NULL;
6142                 }
6143
6144                 init_generic_context_from_args (&context, type_args, method_args);
6145                 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6146                 mono_error_cleanup (&error);
6147                 return method;
6148         }
6149
6150         if ((index <= 0) || (index > image->tables [table].rows)) {
6151                 *resolve_error = ResolveTokenError_OutOfRange;
6152                 return NULL;
6153         }
6154         if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6155                 *resolve_error = ResolveTokenError_BadTable;
6156                 return NULL;
6157         }
6158
6159         init_generic_context_from_args (&context, type_args, method_args);
6160         method = mono_get_method_checked (image, token, NULL, &context, &error);
6161         mono_error_set_pending_exception (&error);
6162
6163         return method;
6164 }
6165
6166 ICALL_EXPORT MonoString*
6167 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6168 {
6169         MonoError error;
6170         int index = mono_metadata_token_index (token);
6171
6172         *resolve_error = ResolveTokenError_Other;
6173
6174         /* Validate token */
6175         if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6176                 *resolve_error = ResolveTokenError_BadTable;
6177                 return NULL;
6178         }
6179
6180         if (image_is_dynamic (image)) {
6181                 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6182                 mono_error_cleanup (&error);
6183                 return result;
6184         }
6185
6186         if ((index <= 0) || (index >= image->heap_us.size)) {
6187                 *resolve_error = ResolveTokenError_OutOfRange;
6188                 return NULL;
6189         }
6190
6191         /* FIXME: What to do if the index points into the middle of a string ? */
6192
6193         return mono_ldstr (mono_domain_get (), image, index);
6194 }
6195
6196 ICALL_EXPORT MonoClassField*
6197 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6198 {
6199         MonoError error;
6200         MonoClass *klass;
6201         int table = mono_metadata_token_table (token);
6202         int index = mono_metadata_token_index (token);
6203         MonoGenericContext context;
6204         MonoClassField *field;
6205
6206         *resolve_error = ResolveTokenError_Other;
6207
6208         /* Validate token */
6209         if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6210                 *resolve_error = ResolveTokenError_BadTable;
6211                 return NULL;
6212         }
6213
6214         if (image_is_dynamic (image)) {
6215                 if (table == MONO_TABLE_FIELD) {
6216                         field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6217                         mono_error_cleanup (&error);
6218                         return field;
6219                 }
6220
6221                 if (mono_memberref_is_method (image, token)) {
6222                         *resolve_error = ResolveTokenError_BadTable;
6223                         return NULL;
6224                 }
6225
6226                 init_generic_context_from_args (&context, type_args, method_args);
6227                 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6228                 mono_error_cleanup (&error);
6229                 return field;
6230         }
6231
6232         if ((index <= 0) || (index > image->tables [table].rows)) {
6233                 *resolve_error = ResolveTokenError_OutOfRange;
6234                 return NULL;
6235         }
6236         if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6237                 *resolve_error = ResolveTokenError_BadTable;
6238                 return NULL;
6239         }
6240
6241         init_generic_context_from_args (&context, type_args, method_args);
6242         field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6243         mono_error_set_pending_exception (&error);
6244         
6245         return field;
6246 }
6247
6248
6249 ICALL_EXPORT MonoObject*
6250 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6251 {
6252         MonoError merror;
6253         MonoObject *ret;
6254         int table = mono_metadata_token_table (token);
6255
6256         *error = ResolveTokenError_Other;
6257
6258         switch (table) {
6259         case MONO_TABLE_TYPEDEF:
6260         case MONO_TABLE_TYPEREF:
6261         case MONO_TABLE_TYPESPEC: {
6262                 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6263                 if (t) {
6264                         ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6265                         mono_error_set_pending_exception (&merror);
6266
6267                         return ret;
6268                 }
6269                 else
6270                         return NULL;
6271         }
6272         case MONO_TABLE_METHOD:
6273         case MONO_TABLE_METHODSPEC: {
6274                 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6275                 if (m) {
6276                         ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6277                         mono_error_set_pending_exception (&merror);
6278
6279                         return ret;
6280                 } else
6281                         return NULL;
6282         }               
6283         case MONO_TABLE_FIELD: {
6284                 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6285                 if (f) {
6286                         ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6287                         mono_error_set_pending_exception (&merror);
6288                         return ret;
6289                 }
6290                 else
6291                         return NULL;
6292         }
6293         case MONO_TABLE_MEMBERREF:
6294                 if (mono_memberref_is_method (image, token)) {
6295                         MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6296                         if (m) {
6297                                 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6298                                 mono_error_set_pending_exception (&merror);
6299
6300                                 return ret;
6301                         } else
6302                                 return NULL;
6303                 }
6304                 else {
6305                         MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6306                         if (f) {
6307                                 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6308                                 mono_error_set_pending_exception (&merror);
6309                                 return ret;
6310                         }
6311                         else
6312                                 return NULL;
6313                 }
6314                 break;
6315
6316         default:
6317                 *error = ResolveTokenError_BadTable;
6318         }
6319
6320         return NULL;
6321 }
6322
6323 ICALL_EXPORT MonoArray*
6324 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6325 {
6326         MonoError error;
6327         int table = mono_metadata_token_table (token);
6328         int idx = mono_metadata_token_index (token);
6329         MonoTableInfo *tables = image->tables;
6330         guint32 sig, len;
6331         const char *ptr;
6332         MonoArray *res;
6333
6334         *resolve_error = ResolveTokenError_OutOfRange;
6335
6336         /* FIXME: Support other tables ? */
6337         if (table != MONO_TABLE_STANDALONESIG)
6338                 return NULL;
6339
6340         if (image_is_dynamic (image))
6341                 return NULL;
6342
6343         if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6344                 return NULL;
6345
6346         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6347
6348         ptr = mono_metadata_blob_heap (image, sig);
6349         len = mono_metadata_decode_blob_size (ptr, &ptr);
6350
6351         res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6352         if (mono_error_set_pending_exception (&error))
6353                 return NULL;
6354         memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6355         return res;
6356 }
6357
6358 ICALL_EXPORT MonoReflectionType*
6359 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6360 {
6361         MonoError error;
6362         MonoReflectionType *ret;
6363         MonoClass *klass;
6364         int isbyref = 0, rank;
6365         char *str = mono_string_to_utf8 (smodifiers);
6366         char *p;
6367
6368         klass = mono_class_from_mono_type (tb->type.type);
6369         p = str;
6370         /* logic taken from mono_reflection_parse_type(): keep in sync */
6371         while (*p) {
6372                 switch (*p) {
6373                 case '&':
6374                         if (isbyref) { /* only one level allowed by the spec */
6375                                 g_free (str);
6376                                 return NULL;
6377                         }
6378                         isbyref = 1;
6379                         p++;
6380
6381                         g_free (str);
6382
6383                         ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6384                         mono_error_set_pending_exception (&error);
6385
6386                         return ret;
6387                 case '*':
6388                         klass = mono_ptr_class_get (&klass->byval_arg);
6389                         mono_class_init (klass);
6390                         p++;
6391                         break;
6392                 case '[':
6393                         rank = 1;
6394                         p++;
6395                         while (*p) {
6396                                 if (*p == ']')
6397                                         break;
6398                                 if (*p == ',')
6399                                         rank++;
6400                                 else if (*p != '*') { /* '*' means unknown lower bound */
6401                                         g_free (str);
6402                                         return NULL;
6403                                 }
6404                                 ++p;
6405                         }
6406                         if (*p != ']') {
6407                                 g_free (str);
6408                                 return NULL;
6409                         }
6410                         p++;
6411                         klass = mono_array_class_get (klass, rank);
6412                         mono_class_init (klass);
6413                         break;
6414                 default:
6415                         break;
6416                 }
6417         }
6418
6419         g_free (str);
6420
6421         ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6422         mono_error_set_pending_exception (&error);
6423
6424         return ret;
6425 }
6426
6427 ICALL_EXPORT MonoBoolean
6428 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6429 {
6430         MonoType *type;
6431         MonoBoolean res;
6432
6433         type = t->type;
6434         res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6435
6436         return res;
6437 }
6438
6439 static void
6440 check_for_invalid_type (MonoClass *klass, MonoError *error)
6441 {
6442         char *name;
6443         MonoString *str;
6444
6445         mono_error_init (error);
6446
6447         if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6448                 return;
6449
6450         name = mono_type_get_full_name (klass);
6451         str =  mono_string_new (mono_domain_get (), name);
6452         g_free (name);
6453         mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6454
6455 }
6456 ICALL_EXPORT MonoReflectionType *
6457 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6458 {
6459         MonoError error;
6460         MonoReflectionType *ret;
6461         MonoClass *klass, *aklass;
6462
6463         klass = mono_class_from_mono_type (type->type);
6464         check_for_invalid_type (klass, &error);
6465         mono_error_set_pending_exception (&error);
6466
6467         if (rank == 0) //single dimentional array
6468                 aklass = mono_array_class_get (klass, 1);
6469         else
6470                 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6471
6472         ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6473         mono_error_set_pending_exception (&error);
6474
6475         return ret;
6476 }
6477
6478 ICALL_EXPORT MonoReflectionType *
6479 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6480 {
6481         MonoError error;
6482         MonoReflectionType *ret;
6483         MonoClass *klass;
6484
6485         klass = mono_class_from_mono_type (type->type);
6486         mono_class_init_checked (klass, &error);
6487         if (mono_error_set_pending_exception (&error))
6488                 return NULL;
6489
6490         check_for_invalid_type (klass, &error);
6491         if (mono_error_set_pending_exception (&error))
6492                 return NULL;
6493
6494         ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6495         mono_error_set_pending_exception (&error);
6496
6497         return ret;
6498 }
6499
6500 ICALL_EXPORT MonoReflectionType *
6501 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6502 {
6503         MonoError error;
6504         MonoReflectionType *ret;
6505         MonoClass *klass, *pklass;
6506
6507         klass = mono_class_from_mono_type (type->type);
6508         mono_class_init_checked (klass, &error);
6509         if (mono_error_set_pending_exception (&error))
6510                 return NULL;
6511         check_for_invalid_type (klass, &error);
6512         if (mono_error_set_pending_exception (&error))
6513                 return NULL;
6514
6515         pklass = mono_ptr_class_get (type->type);
6516
6517         ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6518         mono_error_set_pending_exception (&error);
6519
6520         return ret;
6521 }
6522
6523 ICALL_EXPORT MonoObject *
6524 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6525                                                    MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6526 {
6527         MonoError error;
6528         MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6529         MonoObject *delegate;
6530         gpointer func;
6531         MonoMethod *method = info->method;
6532
6533         mono_class_init_checked (delegate_class, &error);
6534         if (mono_error_set_pending_exception (&error))
6535                 return NULL;
6536
6537         if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6538                 /* FIXME improve this exception message */
6539                 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6540                                                  __func__,
6541                                                  "delegate_class->parent == mono_defaults.multicastdelegate_class");
6542                 mono_error_set_pending_exception (&error);
6543                 return NULL;
6544         }
6545
6546         if (mono_security_core_clr_enabled ()) {
6547                 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6548                         if (throwOnBindFailure)
6549                                 mono_error_set_pending_exception (&error);
6550                         else
6551                                 mono_error_cleanup (&error);
6552                         return NULL;
6553                 }
6554         }
6555
6556         delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6557         if (mono_error_set_pending_exception (&error))
6558                 return NULL;
6559
6560         if (method_is_dynamic (method)) {
6561                 /* Creating a trampoline would leak memory */
6562                 func = mono_compile_method (method);
6563         } else {
6564                 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6565                         method = mono_object_get_virtual_method (target, method);
6566                 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6567                 if (mono_error_set_pending_exception (&error))
6568                         return NULL;
6569                 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6570         }
6571
6572         mono_delegate_ctor_with_method (delegate, target, func, method);
6573
6574         return delegate;
6575 }
6576
6577 ICALL_EXPORT MonoMulticastDelegate *
6578 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6579 {
6580         MonoError error;
6581         MonoMulticastDelegate *ret;
6582
6583         g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6584
6585         ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6586         if (mono_error_set_pending_exception (&error))
6587                 return NULL;
6588
6589         ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6590
6591         return ret;
6592 }
6593
6594 ICALL_EXPORT MonoReflectionMethod*
6595 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6596 {
6597         MonoReflectionMethod *ret = NULL;
6598         MonoError error;
6599         ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6600         mono_error_set_pending_exception (&error);
6601         return ret;
6602 }
6603
6604 /* System.Buffer */
6605
6606 static inline gint32 
6607 mono_array_get_byte_length (MonoArray *array)
6608 {
6609         MonoClass *klass;
6610         int length;
6611         int i;
6612
6613         klass = array->obj.vtable->klass;
6614
6615         if (array->bounds == NULL)
6616                 length = array->max_length;
6617         else {
6618                 length = 1;
6619                 for (i = 0; i < klass->rank; ++ i)
6620                         length *= array->bounds [i].length;
6621         }
6622
6623         switch (klass->element_class->byval_arg.type) {
6624         case MONO_TYPE_I1:
6625         case MONO_TYPE_U1:
6626         case MONO_TYPE_BOOLEAN:
6627                 return length;
6628         case MONO_TYPE_I2:
6629         case MONO_TYPE_U2:
6630         case MONO_TYPE_CHAR:
6631                 return length << 1;
6632         case MONO_TYPE_I4:
6633         case MONO_TYPE_U4:
6634         case MONO_TYPE_R4:
6635                 return length << 2;
6636         case MONO_TYPE_I:
6637         case MONO_TYPE_U:
6638                 return length * sizeof (gpointer);
6639         case MONO_TYPE_I8:
6640         case MONO_TYPE_U8:
6641         case MONO_TYPE_R8:
6642                 return length << 3;
6643         default:
6644                 return -1;
6645         }
6646 }
6647
6648 ICALL_EXPORT gint32 
6649 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array) 
6650 {
6651         return mono_array_get_byte_length (array);
6652 }
6653
6654 ICALL_EXPORT gint8 
6655 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx) 
6656 {
6657         return mono_array_get (array, gint8, idx);
6658 }
6659
6660 ICALL_EXPORT void 
6661 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value) 
6662 {
6663         mono_array_set (array, gint8, idx, value);
6664 }
6665
6666 ICALL_EXPORT MonoBoolean
6667 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count) 
6668 {
6669         guint8 *src_buf, *dest_buf;
6670
6671         if (count < 0) {
6672                 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6673                 return FALSE;
6674         }
6675
6676         g_assert (count >= 0);
6677
6678         /* This is called directly from the class libraries without going through the managed wrapper */
6679         MONO_CHECK_ARG_NULL (src, FALSE);
6680         MONO_CHECK_ARG_NULL (dest, FALSE);
6681
6682         /* watch out for integer overflow */
6683         if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6684                 return FALSE;
6685
6686         src_buf = (guint8 *)src->vector + src_offset;
6687         dest_buf = (guint8 *)dest->vector + dest_offset;
6688
6689         if (src != dest)
6690                 memcpy (dest_buf, src_buf, count);
6691         else
6692                 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6693
6694         return TRUE;
6695 }
6696
6697 #ifndef DISABLE_REMOTING
6698 ICALL_EXPORT MonoObject *
6699 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6700 {
6701         MonoError error;
6702         MonoDomain *domain = mono_object_domain (this_obj); 
6703         MonoObject *res;
6704         MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6705         MonoTransparentProxy *tp;
6706         MonoType *type;
6707         MonoClass *klass;
6708
6709         res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6710         if (mono_error_set_pending_exception (&error))
6711                 return NULL;
6712
6713         tp = (MonoTransparentProxy*) res;
6714         
6715         MONO_OBJECT_SETREF (tp, rp, rp);
6716         type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6717         klass = mono_class_from_mono_type (type);
6718
6719         // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6720         mono_class_setup_vtable (klass);
6721         if (mono_class_has_failure (klass)) {
6722                 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6723                 return NULL;
6724         }
6725
6726         tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6727         if (!is_ok (&error)) {
6728                 mono_error_set_pending_exception (&error);
6729                 return NULL;
6730         }
6731         tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6732         if (!is_ok (&error)) {
6733                 mono_error_set_pending_exception (&error);
6734                 return NULL;
6735         }
6736
6737         res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6738         return res;
6739 }
6740
6741 ICALL_EXPORT MonoReflectionType *
6742 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6743 {
6744         MonoError error;
6745         MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6746         mono_error_set_pending_exception (&error);
6747
6748         return ret;
6749 }
6750 #endif
6751
6752 /* System.Environment */
6753
6754 MonoString*
6755 ves_icall_System_Environment_get_UserName (void)
6756 {
6757         /* using glib is more portable */
6758         return mono_string_new (mono_domain_get (), g_get_user_name ());
6759 }
6760
6761
6762 ICALL_EXPORT MonoString *
6763 ves_icall_System_Environment_get_MachineName (void)
6764 {
6765 #if defined (HOST_WIN32)
6766         gunichar2 *buf;
6767         guint32 len;
6768         MonoString *result;
6769
6770         len = MAX_COMPUTERNAME_LENGTH + 1;
6771         buf = g_new (gunichar2, len);
6772
6773         result = NULL;
6774         if (GetComputerName (buf, (PDWORD) &len)) {
6775                 MonoError error;
6776                 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6777                 mono_error_set_pending_exception (&error);
6778         }
6779
6780         g_free (buf);
6781         return result;
6782 #elif !defined(DISABLE_SOCKETS)
6783         MonoString *result;
6784         char *buf;
6785         int n;
6786 #if defined _SC_HOST_NAME_MAX
6787         n = sysconf (_SC_HOST_NAME_MAX);
6788         if (n == -1)
6789 #endif
6790         n = 512;
6791         buf = g_malloc (n+1);
6792         
6793         if (gethostname (buf, n) == 0){
6794                 buf [n] = 0;
6795                 result = mono_string_new (mono_domain_get (), buf);
6796         } else
6797                 result = NULL;
6798         g_free (buf);
6799         
6800         return result;
6801 #else
6802         return mono_string_new (mono_domain_get (), "mono");
6803 #endif
6804 }
6805
6806 ICALL_EXPORT int
6807 ves_icall_System_Environment_get_Platform (void)
6808 {
6809 #if defined (TARGET_WIN32)
6810         /* Win32NT */
6811         return 2;
6812 #elif defined(__MACH__)
6813         /* OSX */
6814         //
6815         // Notice that the value is hidden from user code, and only exposed
6816         // to mscorlib.   This is due to Mono's Unix/MacOS code predating the
6817         // define and making assumptions based on Unix/128/4 values before there
6818         // was a MacOS define.    Lots of code would assume that not-Unix meant
6819         // Windows, but in this case, it would be OSX. 
6820         //
6821         return 6;
6822 #else
6823         /* Unix */
6824         return 4;
6825 #endif
6826 }
6827
6828 ICALL_EXPORT MonoString *
6829 ves_icall_System_Environment_get_NewLine (void)
6830 {
6831 #if defined (HOST_WIN32)
6832         return mono_string_new (mono_domain_get (), "\r\n");
6833 #else
6834         return mono_string_new (mono_domain_get (), "\n");
6835 #endif
6836 }
6837
6838 ICALL_EXPORT MonoBoolean
6839 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6840 {
6841 #if SIZEOF_VOID_P == 8
6842         return TRUE;
6843 #else
6844 #ifdef HOST_WIN32
6845         gboolean isWow64Process = FALSE;
6846         if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6847                 return (MonoBoolean)isWow64Process;
6848         }
6849 #elif defined(HAVE_SYS_UTSNAME_H)
6850         struct utsname name;
6851
6852         if (uname (&name) >= 0) {
6853                 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6854         }
6855 #endif
6856         return FALSE;
6857 #endif
6858 }
6859
6860 ICALL_EXPORT MonoString *
6861 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6862 {
6863         const gchar *value;
6864         gchar *utf8_name;
6865
6866         if (name == NULL)
6867                 return NULL;
6868
6869         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6870         value = g_getenv (utf8_name);
6871
6872         g_free (utf8_name);
6873
6874         if (value == 0)
6875                 return NULL;
6876         
6877         return mono_string_new (mono_domain_get (), value);
6878 }
6879
6880 /*
6881  * There is no standard way to get at environ.
6882  */
6883 #ifndef _MSC_VER
6884 #ifndef __MINGW32_VERSION
6885 #if defined(__APPLE__)
6886 #if defined (TARGET_OSX)
6887 /* Apple defines this in crt_externs.h but doesn't provide that header for 
6888  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
6889  * in fact exist on all implementations (so far) 
6890  */
6891 gchar ***_NSGetEnviron(void);
6892 #define environ (*_NSGetEnviron())
6893 #else
6894 static char *mono_environ[1] = { NULL };
6895 #define environ mono_environ
6896 #endif /* defined (TARGET_OSX) */
6897 #else
6898 extern
6899 char **environ;
6900 #endif
6901 #endif
6902 #endif
6903
6904 ICALL_EXPORT MonoArray *
6905 ves_icall_System_Environment_GetCoomandLineArgs (void)
6906 {
6907         MonoError error;
6908         MonoArray *result = mono_runtime_get_main_args_checked (&error);
6909         mono_error_set_pending_exception (&error);
6910         return result;
6911 }
6912
6913 ICALL_EXPORT MonoArray *
6914 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6915 {
6916 #ifdef HOST_WIN32
6917         MonoError error;
6918         MonoArray *names;
6919         MonoDomain *domain;
6920         MonoString *str;
6921         WCHAR* env_strings;
6922         WCHAR* env_string;
6923         WCHAR* equal_str;
6924         int n = 0;
6925
6926         env_strings = GetEnvironmentStrings();
6927
6928         if (env_strings) {
6929                 env_string = env_strings;
6930                 while (*env_string != '\0') {
6931                 /* weird case that MS seems to skip */
6932                         if (*env_string != '=')
6933                                 n++;
6934                         while (*env_string != '\0')
6935                                 env_string++;
6936                         env_string++;
6937                 }
6938         }
6939
6940         domain = mono_domain_get ();
6941         names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6942         if (mono_error_set_pending_exception (&error))
6943                 return NULL;
6944
6945         if (env_strings) {
6946                 n = 0;
6947                 env_string = env_strings;
6948                 while (*env_string != '\0') {
6949                         /* weird case that MS seems to skip */
6950                         if (*env_string != '=') {
6951                                 equal_str = wcschr(env_string, '=');
6952                                 g_assert(equal_str);
6953                                 MonoError error;
6954                                 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6955                                 if (mono_error_set_pending_exception (&error))
6956                                         return NULL;
6957
6958                                 mono_array_setref (names, n, str);
6959                                 n++;
6960                         }
6961                         while (*env_string != '\0')
6962                                 env_string++;
6963                         env_string++;
6964                 }
6965
6966                 FreeEnvironmentStrings (env_strings);
6967         }
6968
6969         return names;
6970
6971 #else
6972         MonoError error;
6973         MonoArray *names;
6974         MonoDomain *domain;
6975         MonoString *str;
6976         gchar **e, **parts;
6977         int n;
6978
6979         n = 0;
6980         for (e = environ; *e != 0; ++ e)
6981                 ++ n;
6982
6983         domain = mono_domain_get ();
6984         names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6985         if (mono_error_set_pending_exception (&error))
6986                 return NULL;
6987
6988         n = 0;
6989         for (e = environ; *e != 0; ++ e) {
6990                 parts = g_strsplit (*e, "=", 2);
6991                 if (*parts != 0) {
6992                         str = mono_string_new (domain, *parts);
6993                         mono_array_setref (names, n, str);
6994                 }
6995
6996                 g_strfreev (parts);
6997
6998                 ++ n;
6999         }
7000
7001         return names;
7002 #endif
7003 }
7004
7005 /*
7006  * If your platform lacks setenv/unsetenv, you must upgrade your glib.
7007  */
7008 #if !GLIB_CHECK_VERSION(2,4,0)
7009 #define g_setenv(a,b,c)   setenv(a,b,c)
7010 #define g_unsetenv(a) unsetenv(a)
7011 #endif
7012
7013 ICALL_EXPORT void
7014 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
7015 {
7016 #ifdef HOST_WIN32
7017         gunichar2 *utf16_name, *utf16_value;
7018 #else
7019         gchar *utf8_name, *utf8_value;
7020         MonoError error;
7021 #endif
7022
7023 #ifdef HOST_WIN32
7024         utf16_name = mono_string_to_utf16 (name);
7025         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7026                 SetEnvironmentVariable (utf16_name, NULL);
7027                 g_free (utf16_name);
7028                 return;
7029         }
7030
7031         utf16_value = mono_string_to_utf16 (value);
7032
7033         SetEnvironmentVariable (utf16_name, utf16_value);
7034
7035         g_free (utf16_name);
7036         g_free (utf16_value);
7037 #else
7038         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
7039
7040         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7041                 g_unsetenv (utf8_name);
7042                 g_free (utf8_name);
7043                 return;
7044         }
7045
7046         utf8_value = mono_string_to_utf8_checked (value, &error);
7047         if (!mono_error_ok (&error)) {
7048                 g_free (utf8_name);
7049                 mono_error_set_pending_exception (&error);
7050                 return;
7051         }
7052         g_setenv (utf8_name, utf8_value, TRUE);
7053
7054         g_free (utf8_name);
7055         g_free (utf8_value);
7056 #endif
7057 }
7058
7059 ICALL_EXPORT void
7060 ves_icall_System_Environment_Exit (int result)
7061 {
7062         mono_environment_exitcode_set (result);
7063
7064 /* FIXME: There are some cleanup hangs that should be worked out, but
7065  * if the program is going to exit, everything will be cleaned up when
7066  * NaCl exits anyway.
7067  */
7068 #ifndef __native_client__
7069         if (!mono_runtime_try_shutdown ())
7070                 mono_thread_exit ();
7071
7072         /* Suspend all managed threads since the runtime is going away */
7073         mono_thread_suspend_all_other_threads ();
7074
7075         mono_runtime_quit ();
7076 #endif
7077
7078         /* we may need to do some cleanup here... */
7079         exit (result);
7080 }
7081
7082 ICALL_EXPORT MonoString*
7083 ves_icall_System_Environment_GetGacPath (void)
7084 {
7085         return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
7086 }
7087
7088 ICALL_EXPORT MonoString*
7089 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
7090 {
7091 #if defined (HOST_WIN32)
7092         #ifndef CSIDL_FLAG_CREATE
7093                 #define CSIDL_FLAG_CREATE       0x8000
7094         #endif
7095
7096         WCHAR path [MAX_PATH];
7097         /* Create directory if no existing */
7098         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
7099                 int len = 0;
7100                 while (path [len])
7101                         ++ len;
7102                 MonoError error;
7103                 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
7104                 mono_error_set_pending_exception (&error);
7105                 return res;
7106         }
7107 #else
7108         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7109 #endif
7110         return mono_string_new (mono_domain_get (), "");
7111 }
7112
7113 ICALL_EXPORT MonoArray *
7114 ves_icall_System_Environment_GetLogicalDrives (void)
7115 {
7116         MonoError error;
7117         gunichar2 buf [256], *ptr, *dname;
7118         gunichar2 *u16;
7119         guint initial_size = 127, size = 128;
7120         gint ndrives;
7121         MonoArray *result;
7122         MonoString *drivestr;
7123         MonoDomain *domain = mono_domain_get ();
7124         gint len;
7125
7126         buf [0] = '\0';
7127         ptr = buf;
7128
7129         while (size > initial_size) {
7130                 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7131                 if (size > initial_size) {
7132                         if (ptr != buf)
7133                                 g_free (ptr);
7134                         ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7135                         initial_size = size;
7136                         size++;
7137                 }
7138         }
7139
7140         /* Count strings */
7141         dname = ptr;
7142         ndrives = 0;
7143         do {
7144                 while (*dname++);
7145                 ndrives++;
7146         } while (*dname);
7147
7148         dname = ptr;
7149         result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7150         if (mono_error_set_pending_exception (&error))
7151                 goto leave;
7152
7153         ndrives = 0;
7154         do {
7155                 len = 0;
7156                 u16 = dname;
7157                 while (*u16) { u16++; len ++; }
7158                 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7159                 if (mono_error_set_pending_exception (&error))
7160                         goto leave;
7161
7162                 mono_array_setref (result, ndrives++, drivestr);
7163                 while (*dname++);
7164         } while (*dname);
7165
7166 leave:
7167         if (ptr != buf)
7168                 g_free (ptr);
7169
7170         return result;
7171 }
7172
7173 ICALL_EXPORT MonoString *
7174 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7175 {
7176         gunichar2 volume_name [MAX_PATH + 1];
7177         
7178         if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7179                 return NULL;
7180         return mono_string_from_utf16 (volume_name);
7181 }
7182
7183 ICALL_EXPORT MonoString *
7184 ves_icall_System_Environment_InternalGetHome (void)
7185 {
7186         return mono_string_new (mono_domain_get (), g_get_home_dir ());
7187 }
7188
7189 static const char *encodings [] = {
7190         (char *) 1,
7191                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7192                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7193                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7194         (char *) 2,
7195                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7196                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7197                 "x_unicode_2_0_utf_7",
7198         (char *) 3,
7199                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7200                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7201         (char *) 4,
7202                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7203                 "iso_10646_ucs2",
7204         (char *) 5,
7205                 "unicodefffe", "utf_16be",
7206         (char *) 6,
7207                 "iso_8859_1",
7208         (char *) 0
7209 };
7210
7211 /*
7212  * Returns the internal codepage, if the value of "int_code_page" is
7213  * 1 at entry, and we can not compute a suitable code page number,
7214  * returns the code page as a string
7215  */
7216 ICALL_EXPORT MonoString*
7217 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page) 
7218 {
7219         const char *cset;
7220         const char *p;
7221         char *c;
7222         char *codepage = NULL;
7223         int code;
7224         int want_name = *int_code_page;
7225         int i;
7226         
7227         *int_code_page = -1;
7228
7229         g_get_charset (&cset);
7230         c = codepage = strdup (cset);
7231         for (c = codepage; *c; c++){
7232                 if (isascii (*c) && isalpha (*c))
7233                         *c = tolower (*c);
7234                 if (*c == '-')
7235                         *c = '_';
7236         }
7237         /* g_print ("charset: %s\n", cset); */
7238         
7239         /* handle some common aliases */
7240         p = encodings [0];
7241         code = 0;
7242         for (i = 0; p != 0; ){
7243                 if ((gsize) p < 7){
7244                         code = (gssize) p;
7245                         p = encodings [++i];
7246                         continue;
7247                 }
7248                 if (strcmp (p, codepage) == 0){
7249                         *int_code_page = code;
7250                         break;
7251                 }
7252                 p = encodings [++i];
7253         }
7254         
7255         if (strstr (codepage, "utf_8") != NULL)
7256                 *int_code_page |= 0x10000000;
7257         free (codepage);
7258         
7259         if (want_name && *int_code_page == -1)
7260                 return mono_string_new (mono_domain_get (), cset);
7261         else
7262                 return NULL;
7263 }
7264
7265 ICALL_EXPORT MonoBoolean
7266 ves_icall_System_Environment_get_HasShutdownStarted (void)
7267 {
7268         if (mono_runtime_is_shutting_down ())
7269                 return TRUE;
7270
7271         if (mono_domain_is_unloading (mono_domain_get ()))
7272                 return TRUE;
7273
7274         return FALSE;
7275 }
7276
7277 ICALL_EXPORT void
7278 ves_icall_System_Environment_BroadcastSettingChange (void)
7279 {
7280 #ifdef HOST_WIN32
7281         SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7282 #endif
7283 }
7284
7285 ICALL_EXPORT
7286 gint32
7287 ves_icall_System_Environment_get_TickCount (void)
7288 {
7289         /* this will overflow after ~24 days */
7290         return (gint32) (mono_msec_boottime () & 0xffffffff);
7291 }
7292
7293 ICALL_EXPORT gint32
7294 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7295 {
7296         return 9;
7297 }
7298
7299 ICALL_EXPORT void
7300 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj, 
7301                                          MonoReflectionMethod *method,
7302                                          MonoArray *out_args)
7303 {
7304         mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
7305 }
7306
7307 #ifndef DISABLE_REMOTING
7308 ICALL_EXPORT MonoBoolean
7309 ves_icall_IsTransparentProxy (MonoObject *proxy)
7310 {
7311         if (!proxy)
7312                 return 0;
7313
7314         if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7315                 return 1;
7316
7317         return 0;
7318 }
7319
7320 ICALL_EXPORT MonoReflectionMethod *
7321 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7322         MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7323 {
7324         MonoReflectionMethod *ret = NULL;
7325         MonoError error;
7326
7327         MonoClass *klass;
7328         MonoMethod *method;
7329         MonoMethod **vtable;
7330         MonoMethod *res = NULL;
7331
7332         MONO_CHECK_ARG_NULL (rtype, NULL);
7333         MONO_CHECK_ARG_NULL (rmethod, NULL);
7334
7335         method = rmethod->method;
7336         klass = mono_class_from_mono_type (rtype->type);
7337         mono_class_init_checked (klass, &error);
7338         if (mono_error_set_pending_exception (&error))
7339                 return NULL;
7340
7341         if (MONO_CLASS_IS_INTERFACE (klass))
7342                 return NULL;
7343
7344         if (method->flags & METHOD_ATTRIBUTE_STATIC)
7345                 return NULL;
7346
7347         if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7348                 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7349                         return rmethod;
7350                 else
7351                         return NULL;
7352         }
7353
7354         mono_class_setup_vtable (klass);
7355         vtable = klass->vtable;
7356
7357         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7358                 gboolean variance_used = FALSE;
7359                 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7360                 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7361                 if (offs >= 0)
7362                         res = vtable [offs + method->slot];
7363         } else {
7364                 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7365                         return NULL;
7366
7367                 if (method->slot != -1)
7368                         res = vtable [method->slot];
7369         }
7370
7371         if (!res)
7372                 return NULL;
7373
7374         ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7375         mono_error_set_pending_exception (&error);
7376         return ret;
7377 }
7378
7379 ICALL_EXPORT void
7380 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7381 {
7382         MonoError error;
7383         MonoClass *klass;
7384         MonoVTable* vtable;
7385
7386         klass = mono_class_from_mono_type (type->type);
7387         vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7388         if (!is_ok (&error)) {
7389                 mono_error_set_pending_exception (&error);
7390                 return;
7391         }
7392
7393         mono_vtable_set_is_remote (vtable, enable);
7394 }
7395
7396 #else /* DISABLE_REMOTING */
7397
7398 ICALL_EXPORT void
7399 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7400 {
7401         g_assert_not_reached ();
7402 }
7403
7404 #endif
7405
7406 ICALL_EXPORT MonoObject *
7407 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7408 {
7409         MonoError error;
7410         MonoClass *klass;
7411         MonoDomain *domain;
7412         MonoObject *ret;
7413         
7414         domain = mono_object_domain (type);
7415         klass = mono_class_from_mono_type (type->type);
7416         mono_class_init_checked (klass, &error);
7417         if (mono_error_set_pending_exception (&error))
7418                 return NULL;
7419
7420         if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7421                 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7422                 return NULL;
7423         }
7424
7425         if (klass->rank >= 1) {
7426                 g_assert (klass->rank == 1);
7427                 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7428                 mono_error_set_pending_exception (&error);
7429                 return ret;
7430         } else {
7431                 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7432                 if (!is_ok (&error)) {
7433                         mono_error_set_pending_exception (&error);
7434                         return NULL;
7435                 }
7436                 /* Bypass remoting object creation check */
7437                 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7438                 mono_error_set_pending_exception (&error);
7439
7440                 return ret;
7441         }
7442 }
7443
7444 ICALL_EXPORT MonoString *
7445 ves_icall_System_IO_get_temp_path (void)
7446 {
7447         return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7448 }
7449
7450 #ifndef PLATFORM_NO_DRIVEINFO
7451 ICALL_EXPORT MonoBoolean
7452 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7453                                                 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7454                                                 gint32 *error)
7455 {
7456         gboolean result;
7457         ULARGE_INTEGER wapi_free_bytes_avail;
7458         ULARGE_INTEGER wapi_total_number_of_bytes;
7459         ULARGE_INTEGER wapi_total_number_of_free_bytes;
7460
7461         *error = ERROR_SUCCESS;
7462         result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7463                                      &wapi_total_number_of_free_bytes);
7464
7465         if (result) {
7466                 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7467                 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7468                 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7469         } else {
7470                 *free_bytes_avail = 0;
7471                 *total_number_of_bytes = 0;
7472                 *total_number_of_free_bytes = 0;
7473                 *error = GetLastError ();
7474         }
7475
7476         return result;
7477 }
7478
7479 ICALL_EXPORT guint32
7480 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7481 {
7482         return GetDriveType (mono_string_chars (root_path_name));
7483 }
7484 #endif
7485
7486 ICALL_EXPORT gpointer
7487 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7488 {
7489         return mono_compile_method (method);
7490 }
7491
7492 ICALL_EXPORT MonoString *
7493 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7494 {
7495         MonoString *mcpath;
7496         gchar *path;
7497
7498         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7499
7500 #if defined (HOST_WIN32)
7501         /* Avoid mixing '/' and '\\' */
7502         {
7503                 gint i;
7504                 for (i = strlen (path) - 1; i >= 0; i--)
7505                         if (path [i] == '/')
7506                                 path [i] = '\\';
7507         }
7508 #endif
7509         mcpath = mono_string_new (mono_domain_get (), path);
7510         g_free (path);
7511
7512         return mcpath;
7513 }
7514
7515 static MonoString *
7516 get_bundled_app_config (void)
7517 {
7518         const gchar *app_config;
7519         MonoDomain *domain;
7520         MonoString *file;
7521         gchar *config_file_name, *config_file_path;
7522         gsize len, config_file_path_length, config_ext_length;
7523         gchar *module;
7524
7525         domain = mono_domain_get ();
7526         file = domain->setup->configuration_file;
7527         if (!file || file->length == 0)
7528                 return NULL;
7529
7530         // Retrieve config file and remove the extension
7531         config_file_name = mono_string_to_utf8 (file);
7532         config_file_path = mono_portability_find_file (config_file_name, TRUE);
7533         if (!config_file_path)
7534                 config_file_path = config_file_name;
7535
7536         config_file_path_length = strlen (config_file_path);
7537         config_ext_length = strlen (".config");
7538         if (config_file_path_length <= config_ext_length)
7539                 return NULL;
7540
7541         len = config_file_path_length - config_ext_length;
7542         module = (gchar *)g_malloc0 (len + 1);
7543         memcpy (module, config_file_path, len);
7544         // Get the config file from the module name
7545         app_config = mono_config_string_for_assembly_file (module);
7546         // Clean-up
7547         g_free (module);
7548         if (config_file_name != config_file_path)
7549                 g_free (config_file_name);
7550         g_free (config_file_path);
7551
7552         if (!app_config)
7553                 return NULL;
7554
7555         return mono_string_new (mono_domain_get (), app_config);
7556 }
7557
7558 static MonoString *
7559 get_bundled_machine_config (void)
7560 {
7561         const gchar *machine_config;
7562
7563         machine_config = mono_get_machine_config ();
7564
7565         if (!machine_config)
7566                 return NULL;
7567
7568         return mono_string_new (mono_domain_get (), machine_config);
7569 }
7570
7571 ICALL_EXPORT MonoString *
7572 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7573 {
7574         MonoString *ipath;
7575         gchar *path;
7576
7577         path = g_path_get_dirname (mono_get_config_dir ());
7578
7579 #if defined (HOST_WIN32)
7580         /* Avoid mixing '/' and '\\' */
7581         {
7582                 gint i;
7583                 for (i = strlen (path) - 1; i >= 0; i--)
7584                         if (path [i] == '/')
7585                                 path [i] = '\\';
7586         }
7587 #endif
7588         ipath = mono_string_new (mono_domain_get (), path);
7589         g_free (path);
7590
7591         return ipath;
7592 }
7593
7594 ICALL_EXPORT gboolean
7595 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7596 {
7597         MonoPEResourceDataEntry *entry;
7598         MonoImage *image;
7599
7600         if (!assembly || !result || !size)
7601                 return FALSE;
7602
7603         *result = NULL;
7604         *size = 0;
7605         image = assembly->assembly->image;
7606         entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7607         if (!entry)
7608                 return FALSE;
7609
7610         *result = mono_image_rva_map (image, entry->rde_data_offset);
7611         if (!(*result)) {
7612                 g_free (entry);
7613                 return FALSE;
7614         }
7615         *size = entry->rde_size;
7616         g_free (entry);
7617         return TRUE;
7618 }
7619
7620 ICALL_EXPORT MonoBoolean
7621 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7622 {
7623         return mono_is_debugger_attached ();
7624 }
7625
7626 ICALL_EXPORT MonoBoolean
7627 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7628 {
7629         if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7630                 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7631         else
7632                 return FALSE;
7633 }
7634
7635 ICALL_EXPORT void
7636 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7637 {
7638         if (mono_get_runtime_callbacks ()->debug_log)
7639                 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7640 }
7641
7642 ICALL_EXPORT void
7643 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7644 {
7645 #if defined (HOST_WIN32)
7646         OutputDebugString (mono_string_chars (message));
7647 #else
7648         g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7649 #endif
7650 }
7651
7652 /* Only used for value types */
7653 ICALL_EXPORT MonoObject *
7654 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7655 {
7656         MonoError error;
7657         MonoObject *result;
7658         MonoClass *klass;
7659         MonoDomain *domain;
7660         
7661         domain = mono_object_domain (type);
7662         klass = mono_class_from_mono_type (type->type);
7663         mono_class_init_checked (klass, &error);
7664         if (mono_error_set_pending_exception (&error))
7665                 return NULL;
7666
7667         if (mono_class_is_nullable (klass))
7668                 /* No arguments -> null */
7669                 return NULL;
7670
7671         result = mono_object_new_checked (domain, klass, &error);
7672         mono_error_set_pending_exception (&error);
7673         return result;
7674 }
7675
7676 ICALL_EXPORT MonoReflectionMethod *
7677 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7678 {
7679         MonoReflectionMethod *ret = NULL;
7680         MonoError error;
7681
7682         MonoClass *klass, *parent;
7683         MonoGenericContext *generic_inst = NULL;
7684         MonoMethod *method = m->method;
7685         MonoMethod *result = NULL;
7686         int slot;
7687
7688         if (method->klass == NULL)
7689                 return m;
7690
7691         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7692             MONO_CLASS_IS_INTERFACE (method->klass) ||
7693             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7694                 return m;
7695
7696         slot = mono_method_get_vtable_slot (method);
7697         if (slot == -1)
7698                 return m;
7699
7700         klass = method->klass;
7701         if (klass->generic_class) {
7702                 generic_inst = mono_class_get_context (klass);
7703                 klass = klass->generic_class->container_class;
7704         }
7705
7706         if (definition) {
7707                 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7708                 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7709                         /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7710                            or klass is the generic container class and generic_inst is the instantiation.
7711
7712                            when we go to the parent, if the parent is an open constructed type, we need to
7713                            replace the type parameters by the definitions from the generic_inst, and then take it
7714                            apart again into the klass and the generic_inst.
7715
7716                            For cases like this:
7717                            class C<T> : B<T, int> {
7718                                public override void Foo () { ... }
7719                            }
7720                            class B<U,V> : A<HashMap<U,V>> {
7721                                public override void Foo () { ... }
7722                            }
7723                            class A<X> {
7724                                public virtual void Foo () { ... }
7725                            }
7726
7727                            if at each iteration the parent isn't open, we can skip inflating it.  if at some
7728                            iteration the parent isn't generic (after possible inflation), we set generic_inst to
7729                            NULL;
7730                         */
7731                         MonoGenericContext *parent_inst = NULL;
7732                         if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7733                                 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7734                                 if (!mono_error_ok (&error)) {
7735                                         mono_error_set_pending_exception (&error);
7736                                         return NULL;
7737                                 }
7738                         }
7739                         if (parent->generic_class) {
7740                                 parent_inst = mono_class_get_context (parent);
7741                                 parent = parent->generic_class->container_class;
7742                         }
7743
7744                         mono_class_setup_vtable (parent);
7745                         if (parent->vtable_size <= slot)
7746                                 break;
7747                         klass = parent;
7748                         generic_inst = parent_inst;
7749                 }
7750         } else {
7751                 klass = klass->parent;
7752                 if (!klass)
7753                         return m;
7754                 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7755                         klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7756                         if (!mono_error_ok (&error)) {
7757                                 mono_error_set_pending_exception (&error);
7758                                 return NULL;
7759                         }
7760
7761                         generic_inst = NULL;
7762                 }
7763                 if (klass->generic_class) {
7764                         generic_inst = mono_class_get_context (klass);
7765                         klass = klass->generic_class->container_class;
7766                 }
7767
7768         }
7769
7770         if (generic_inst) {
7771                 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7772                 if (!mono_error_ok (&error)) {
7773                         mono_error_set_pending_exception (&error);
7774                         return NULL;
7775                 }
7776         }
7777
7778         if (klass == method->klass)
7779                 return m;
7780
7781         /*This is possible if definition == FALSE.
7782          * Do it here to be really sure we don't read invalid memory.
7783          */
7784         if (slot >= klass->vtable_size)
7785                 return m;
7786
7787         mono_class_setup_vtable (klass);
7788
7789         result = klass->vtable [slot];
7790         if (result == NULL) {
7791                 /* It is an abstract method */
7792                 gpointer iter = NULL;
7793                 while ((result = mono_class_get_methods (klass, &iter)))
7794                         if (result->slot == slot)
7795                                 break;
7796         }
7797
7798         if (result == NULL)
7799                 return m;
7800
7801         ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7802         mono_error_set_pending_exception (&error);
7803         return ret;
7804 }
7805
7806 ICALL_EXPORT MonoString*
7807 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7808 {
7809         MonoMethod *method = m->method;
7810
7811         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7812         return m->name;
7813 }
7814
7815 ICALL_EXPORT void
7816 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7817 {
7818         iter->sig = *(MonoMethodSignature**)argsp;
7819         
7820         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7821         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7822
7823         iter->next_arg = 0;
7824         /* FIXME: it's not documented what start is exactly... */
7825         if (start) {
7826                 iter->args = start;
7827         } else {
7828                 iter->args = argsp + sizeof (gpointer);
7829         }
7830         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7831
7832         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7833 }
7834
7835 ICALL_EXPORT MonoTypedRef
7836 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7837 {
7838         guint32 i, arg_size;
7839         gint32 align;
7840         MonoTypedRef res;
7841
7842         i = iter->sig->sentinelpos + iter->next_arg;
7843
7844         g_assert (i < iter->sig->param_count);
7845
7846         res.type = iter->sig->params [i];
7847         res.klass = mono_class_from_mono_type (res.type);
7848         arg_size = mono_type_stack_size (res.type, &align);
7849 #if defined(__arm__) || defined(__mips__)
7850         iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7851 #endif
7852         res.value = iter->args;
7853 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7854         /* Values are stored as 8 byte register sized objects, but 'value'
7855          * is dereferenced as a pointer in other routines.
7856          */
7857         res.value = (char*)res.value + 4;
7858 #endif
7859 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7860         if (arg_size <= sizeof (gpointer)) {
7861                 int dummy;
7862                 int padding = arg_size - mono_type_size (res.type, &dummy);
7863                 res.value = (guint8*)res.value + padding;
7864         }
7865 #endif
7866         iter->args = (char*)iter->args + arg_size;
7867         iter->next_arg++;
7868
7869         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7870
7871         return res;
7872 }
7873
7874 ICALL_EXPORT MonoTypedRef
7875 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7876 {
7877         guint32 i, arg_size;
7878         gint32 align;
7879         MonoTypedRef res;
7880
7881         i = iter->sig->sentinelpos + iter->next_arg;
7882
7883         g_assert (i < iter->sig->param_count);
7884
7885         while (i < iter->sig->param_count) {
7886                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7887                         continue;
7888                 res.type = iter->sig->params [i];
7889                 res.klass = mono_class_from_mono_type (res.type);
7890                 /* FIXME: endianess issue... */
7891                 arg_size = mono_type_stack_size (res.type, &align);
7892 #if defined(__arm__) || defined(__mips__)
7893                 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7894 #endif
7895                 res.value = iter->args;
7896                 iter->args = (char*)iter->args + arg_size;
7897                 iter->next_arg++;
7898                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7899                 return res;
7900         }
7901         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7902
7903         res.type = NULL;
7904         res.value = NULL;
7905         res.klass = NULL;
7906         return res;
7907 }
7908
7909 ICALL_EXPORT MonoType*
7910 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7911 {
7912         gint i;
7913         
7914         i = iter->sig->sentinelpos + iter->next_arg;
7915
7916         g_assert (i < iter->sig->param_count);
7917
7918         return iter->sig->params [i];
7919 }
7920
7921 ICALL_EXPORT MonoObject*
7922 mono_TypedReference_ToObject (MonoTypedRef* tref)
7923 {
7924         MonoError error;
7925         MonoObject *result = NULL;
7926         if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7927                 MonoObject** objp = (MonoObject **)tref->value;
7928                 return *objp;
7929         }
7930
7931         result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7932         mono_error_set_pending_exception (&error);
7933         return result;
7934 }
7935
7936 ICALL_EXPORT MonoTypedRef
7937 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7938 {
7939         MonoTypedRef res;
7940         MonoReflectionField *f;
7941         MonoClass *klass;
7942         MonoType *ftype = NULL;
7943         guint8 *p = NULL;
7944         int i;
7945
7946         memset (&res, 0, sizeof (res));
7947
7948         g_assert (fields);
7949         g_assert (mono_array_length (fields) > 0);
7950
7951         klass = target->vtable->klass;
7952
7953         for (i = 0; i < mono_array_length (fields); ++i) {
7954                 f = mono_array_get (fields, MonoReflectionField*, i);
7955                 if (f == NULL) {
7956                         mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7957                         return res;
7958                 }
7959                 if (f->field->parent != klass) {
7960                         mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7961                         return res;
7962                 }
7963                 if (i == 0)
7964                         p = (guint8*)target + f->field->offset;
7965                 else
7966                         p += f->field->offset - sizeof (MonoObject);
7967                 klass = mono_class_from_mono_type (f->field->type);
7968                 ftype = f->field->type;
7969         }
7970
7971         res.type = ftype;
7972         res.klass = mono_class_from_mono_type (ftype);
7973         res.value = p;
7974
7975         return res;
7976 }
7977
7978 static void
7979 prelink_method (MonoMethod *method, MonoError *error)
7980 {
7981         const char *exc_class, *exc_arg;
7982
7983         mono_error_init (error);
7984         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7985                 return;
7986         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7987         if (exc_class) {
7988                 mono_error_set_exception_instance (error,
7989                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7990                 return;
7991         }
7992         /* create the wrapper, too? */
7993 }
7994
7995 ICALL_EXPORT void
7996 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7997 {
7998         MonoError error;
7999
8000         prelink_method (method->method, &error);
8001         mono_error_set_pending_exception (&error);
8002 }
8003
8004 ICALL_EXPORT void
8005 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
8006 {
8007         MonoError error;
8008         MonoClass *klass = mono_class_from_mono_type (type->type);
8009         MonoMethod* m;
8010         gpointer iter = NULL;
8011
8012         mono_class_init_checked (klass, &error);
8013         if (mono_error_set_pending_exception (&error))
8014                 return;
8015
8016         while ((m = mono_class_get_methods (klass, &iter))) {
8017                 prelink_method (m, &error);
8018                 if (mono_error_set_pending_exception (&error))
8019                         return;
8020         }
8021 }
8022
8023 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
8024 ICALL_EXPORT void
8025 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
8026                                             gint32 const **exponents,
8027                                             gunichar2 const **digitLowerTable,
8028                                             gunichar2 const **digitUpperTable,
8029                                             gint64 const **tenPowersList,
8030                                             gint32 const **decHexDigits)
8031 {
8032         *mantissas = Formatter_MantissaBitsTable;
8033         *exponents = Formatter_TensExponentTable;
8034         *digitLowerTable = Formatter_DigitLowerTable;
8035         *digitUpperTable = Formatter_DigitUpperTable;
8036         *tenPowersList = Formatter_TenPowersList;
8037         *decHexDigits = Formatter_DecHexDigits;
8038 }
8039
8040 /*
8041  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
8042  * and avoid useless allocations.
8043  */
8044 static MonoArray*
8045 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
8046 {
8047         MonoReflectionType *rt;
8048         MonoArray *res;
8049         int i, count = 0;
8050
8051         mono_error_init (error);
8052         for (i = 0; i < type->num_mods; ++i) {
8053                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
8054                         count++;
8055         }
8056         if (!count)
8057                 return NULL;
8058         res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
8059         return_val_if_nok (error, NULL);
8060         count = 0;
8061         for (i = 0; i < type->num_mods; ++i) {
8062                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
8063                         MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
8064                         return_val_if_nok (error, NULL);
8065
8066                         rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8067                         return_val_if_nok (error, NULL);
8068
8069                         mono_array_setref (res, count, rt);
8070                         count++;
8071                 }
8072         }
8073         return res;
8074 }
8075
8076 ICALL_EXPORT MonoArray*
8077 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
8078 {
8079         MonoError error;
8080         MonoType *type = param->ClassImpl->type;
8081         MonoClass *member_class = mono_object_class (param->MemberImpl);
8082         MonoMethod *method = NULL;
8083         MonoImage *image;
8084         int pos;
8085         MonoMethodSignature *sig;
8086         MonoArray *res;
8087
8088         if (mono_class_is_reflection_method_or_constructor (member_class)) {
8089                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8090                 method = rmethod->method;
8091         } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
8092                 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8093                 if (!(method = prop->property->get))
8094                         method = prop->property->set;
8095                 g_assert (method);      
8096         } else {
8097                 char *type_name = mono_type_get_full_name (member_class);
8098                 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
8099                 MonoException *ex = mono_get_exception_not_supported  (msg);
8100                 g_free (type_name);
8101                 g_free (msg);
8102                 mono_set_pending_exception (ex);
8103                 return NULL;
8104         }
8105
8106         image = method->klass->image;
8107         pos = param->PositionImpl;
8108         sig = mono_method_signature (method);
8109         if (pos == -1)
8110                 type = sig->ret;
8111         else
8112                 type = sig->params [pos];
8113
8114         res = type_array_from_modifiers (image, type, optional, &error);
8115         mono_error_set_pending_exception (&error);
8116         return res;
8117 }
8118
8119 static MonoType*
8120 get_property_type (MonoProperty *prop)
8121 {
8122         MonoMethodSignature *sig;
8123         if (prop->get) {
8124                 sig = mono_method_signature (prop->get);
8125                 return sig->ret;
8126         } else if (prop->set) {
8127                 sig = mono_method_signature (prop->set);
8128                 return sig->params [sig->param_count - 1];
8129         }
8130         return NULL;
8131 }
8132
8133 ICALL_EXPORT MonoArray*
8134 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8135 {
8136         MonoError error;
8137         MonoType *type = get_property_type (property->property);
8138         MonoImage *image = property->klass->image;
8139         MonoArray *res;
8140
8141         if (!type)
8142                 return NULL;
8143         res = type_array_from_modifiers (image, type, optional, &error);
8144         mono_error_set_pending_exception (&error);
8145         return res;
8146 }
8147
8148 /*
8149  *Construct a MonoType suited to be used to decode a constant blob object.
8150  *
8151  * @type is the target type which will be constructed
8152  * @blob_type is the blob type, for example, that comes from the constant table
8153  * @real_type is the expected constructed type.
8154  */
8155 static void
8156 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8157 {
8158         type->type = blob_type;
8159         type->data.klass = NULL;
8160         if (blob_type == MONO_TYPE_CLASS)
8161                 type->data.klass = mono_defaults.object_class;
8162         else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8163                 /* For enums, we need to use the base type */
8164                 type->type = MONO_TYPE_VALUETYPE;
8165                 type->data.klass = mono_class_from_mono_type (real_type);
8166         } else
8167                 type->data.klass = mono_class_from_mono_type (real_type);
8168 }
8169
8170 ICALL_EXPORT MonoObject*
8171 property_info_get_default_value (MonoReflectionProperty *property)
8172 {
8173         MonoError error;
8174         MonoType blob_type;
8175         MonoProperty *prop = property->property;
8176         MonoType *type = get_property_type (prop);
8177         MonoDomain *domain = mono_object_domain (property); 
8178         MonoTypeEnum def_type;
8179         const char *def_value;
8180         MonoObject *o;
8181
8182         mono_class_init (prop->parent);
8183
8184         if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8185                 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8186                 return NULL;
8187         }
8188
8189         def_value = mono_class_get_property_default_value (prop, &def_type);
8190
8191         mono_type_from_blob_type (&blob_type, def_type, type);
8192         o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8193
8194         mono_error_set_pending_exception (&error);
8195         return o;
8196 }
8197
8198 ICALL_EXPORT MonoBoolean
8199 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8200 {
8201         MonoError error;
8202         MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8203         MonoCustomAttrInfo *cinfo;
8204         gboolean found;
8205
8206         mono_class_init_checked (attr_class, &error);
8207         if (mono_error_set_pending_exception (&error))
8208                 return FALSE;
8209
8210         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8211         if (!is_ok (&error)) {
8212                 mono_error_set_pending_exception (&error);
8213                 return FALSE;
8214         }
8215         if (!cinfo)
8216                 return FALSE;
8217         found = mono_custom_attrs_has_attr (cinfo, attr_class);
8218         if (!cinfo->cached)
8219                 mono_custom_attrs_free (cinfo);
8220         return found;
8221 }
8222
8223 ICALL_EXPORT MonoArray*
8224 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8225 {
8226         MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8227         MonoArray *res;
8228         MonoError error;
8229
8230         if (attr_class) {
8231                 mono_class_init_checked (attr_class, &error);
8232                 if (mono_error_set_pending_exception (&error))
8233                         return NULL;
8234         }
8235
8236         res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8237         if (!mono_error_ok (&error)) {
8238                 mono_error_set_pending_exception (&error);
8239                 return NULL;
8240         }
8241
8242         return res;
8243 }
8244
8245 ICALL_EXPORT MonoArray*
8246 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8247 {
8248         MonoError error;
8249         MonoArray *result;
8250         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8251         mono_error_set_pending_exception (&error);
8252         return result;
8253 }
8254
8255
8256 ICALL_EXPORT MonoString*
8257 ves_icall_Mono_Runtime_GetDisplayName (void)
8258 {
8259         char *info;
8260         MonoString *display_name;
8261
8262         info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8263         display_name = mono_string_new (mono_domain_get (), info);
8264         g_free (info);
8265         return display_name;
8266 }
8267
8268 ICALL_EXPORT MonoString*
8269 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8270 {
8271         MonoError error;
8272         MonoString *message;
8273         guint32 ret;
8274         gunichar2 buf[256];
8275         
8276         ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8277                              FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8278                              buf, 255, NULL);
8279         if (ret == 0) {
8280                 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8281         } else {
8282                 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8283                 if (mono_error_set_pending_exception (&error))
8284                         return NULL;
8285         }
8286         
8287         return message;
8288 }
8289
8290 ICALL_EXPORT gpointer
8291 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8292 {
8293         return GetCurrentProcess ();
8294 }
8295
8296 ICALL_EXPORT MonoBoolean
8297 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8298 {
8299         return GetExitCodeProcess (handle, (guint32*) exitcode);
8300 }
8301
8302 ICALL_EXPORT MonoBoolean
8303 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8304 {
8305 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8306         return CloseHandle (handle);
8307 #else
8308         return CloseProcess (handle);
8309 #endif
8310 }
8311
8312 ICALL_EXPORT MonoBoolean
8313 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8314 {
8315         return TerminateProcess (handle, exitcode);
8316 }
8317
8318 ICALL_EXPORT gint32
8319 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8320 {
8321         return WaitForInputIdle (handle, milliseconds);
8322 }
8323
8324 ICALL_EXPORT MonoBoolean
8325 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8326 {
8327         return GetProcessWorkingSetSize (handle, min, max);
8328 }
8329
8330 ICALL_EXPORT MonoBoolean
8331 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8332 {
8333         return SetProcessWorkingSetSize (handle, min, max);
8334 }
8335
8336 ICALL_EXPORT MonoBoolean
8337 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8338 {
8339         return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8340 }
8341
8342 ICALL_EXPORT gint32
8343 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8344 {
8345         return mono_process_current_pid ();
8346 }
8347
8348 ICALL_EXPORT gint32
8349 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8350 {
8351         return GetPriorityClass (handle);
8352 }
8353
8354 ICALL_EXPORT MonoBoolean
8355 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8356 {
8357         return SetPriorityClass (handle, priorityClass);
8358 }
8359
8360 #ifndef DISABLE_ICALL_TABLES
8361
8362 #define ICALL_TYPE(id,name,first)
8363 #define ICALL(id,name,func) Icall_ ## id,
8364
8365 enum {
8366 #include "metadata/icall-def.h"
8367         Icall_last
8368 };
8369
8370 #undef ICALL_TYPE
8371 #undef ICALL
8372 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8373 #define ICALL(id,name,func)
8374 enum {
8375 #include "metadata/icall-def.h"
8376         Icall_type_num
8377 };
8378
8379 #undef ICALL_TYPE
8380 #undef ICALL
8381 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8382 #define ICALL(id,name,func)
8383 typedef struct {
8384         guint16 first_icall;
8385 } IcallTypeDesc;
8386
8387 static const IcallTypeDesc
8388 icall_type_descs [] = {
8389 #include "metadata/icall-def.h"
8390         {Icall_last}
8391 };
8392
8393 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8394
8395 #undef ICALL_TYPE
8396 #define ICALL_TYPE(id,name,first)
8397 #undef ICALL
8398
8399 #ifdef HAVE_ARRAY_ELEM_INIT
8400 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8401 #define MSGSTRFIELD1(line) str##line
8402
8403 static const struct msgstrtn_t {
8404 #define ICALL(id,name,func)
8405 #undef ICALL_TYPE
8406 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8407 #include "metadata/icall-def.h"
8408 #undef ICALL_TYPE
8409 } icall_type_names_str = {
8410 #define ICALL_TYPE(id,name,first) (name),
8411 #include "metadata/icall-def.h"
8412 #undef ICALL_TYPE
8413 };
8414 static const guint16 icall_type_names_idx [] = {
8415 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8416 #include "metadata/icall-def.h"
8417 #undef ICALL_TYPE
8418 };
8419 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8420
8421 static const struct msgstr_t {
8422 #undef ICALL
8423 #define ICALL_TYPE(id,name,first)
8424 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8425 #include "metadata/icall-def.h"
8426 #undef ICALL
8427 } icall_names_str = {
8428 #define ICALL(id,name,func) (name),
8429 #include "metadata/icall-def.h"
8430 #undef ICALL
8431 };
8432 static const guint16 icall_names_idx [] = {
8433 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8434 #include "metadata/icall-def.h"
8435 #undef ICALL
8436 };
8437 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8438
8439 #else
8440
8441 #undef ICALL_TYPE
8442 #undef ICALL
8443 #define ICALL_TYPE(id,name,first) name,
8444 #define ICALL(id,name,func)
8445 static const char* const
8446 icall_type_names [] = {
8447 #include "metadata/icall-def.h"
8448         NULL
8449 };
8450
8451 #define icall_type_name_get(id) (icall_type_names [(id)])
8452
8453 #undef ICALL_TYPE
8454 #undef ICALL
8455 #define ICALL_TYPE(id,name,first)
8456 #define ICALL(id,name,func) name,
8457 static const char* const
8458 icall_names [] = {
8459 #include "metadata/icall-def.h"
8460         NULL
8461 };
8462 #define icall_name_get(id) icall_names [(id)]
8463
8464 #endif /* !HAVE_ARRAY_ELEM_INIT */
8465
8466 #undef ICALL_TYPE
8467 #undef ICALL
8468 #define ICALL_TYPE(id,name,first)
8469 #define ICALL(id,name,func) func,
8470 static const gconstpointer
8471 icall_functions [] = {
8472 #include "metadata/icall-def.h"
8473         NULL
8474 };
8475
8476 #ifdef ENABLE_ICALL_SYMBOL_MAP
8477 #undef ICALL_TYPE
8478 #undef ICALL
8479 #define ICALL_TYPE(id,name,first)
8480 #define ICALL(id,name,func) #func,
8481 static const gconstpointer
8482 icall_symbols [] = {
8483 #include "metadata/icall-def.h"
8484         NULL
8485 };
8486 #endif
8487
8488 #endif /* DISABLE_ICALL_TABLES */
8489
8490 static mono_mutex_t icall_mutex;
8491 static GHashTable *icall_hash = NULL;
8492 static GHashTable *jit_icall_hash_name = NULL;
8493 static GHashTable *jit_icall_hash_addr = NULL;
8494
8495 void
8496 mono_icall_init (void)
8497 {
8498 #ifndef DISABLE_ICALL_TABLES
8499         int i = 0;
8500
8501         /* check that tables are sorted: disable in release */
8502         if (TRUE) {
8503                 int j;
8504                 const char *prev_class = NULL;
8505                 const char *prev_method;
8506                 
8507                 for (i = 0; i < Icall_type_num; ++i) {
8508                         const IcallTypeDesc *desc;
8509                         int num_icalls;
8510                         prev_method = NULL;
8511                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8512                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8513                         prev_class = icall_type_name_get (i);
8514                         desc = &icall_type_descs [i];
8515                         num_icalls = icall_desc_num_icalls (desc);
8516                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8517                         for (j = 0; j < num_icalls; ++j) {
8518                                 const char *methodn = icall_name_get (desc->first_icall + j);
8519                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
8520                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
8521                                 prev_method = methodn;
8522                         }
8523                 }
8524         }
8525 #endif
8526
8527         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8528         mono_os_mutex_init (&icall_mutex);
8529 }
8530
8531 static void
8532 mono_icall_lock (void)
8533 {
8534         mono_locks_os_acquire (&icall_mutex, IcallLock);
8535 }
8536
8537 static void
8538 mono_icall_unlock (void)
8539 {
8540         mono_locks_os_release (&icall_mutex, IcallLock);
8541 }
8542
8543 void
8544 mono_icall_cleanup (void)
8545 {
8546         g_hash_table_destroy (icall_hash);
8547         g_hash_table_destroy (jit_icall_hash_name);
8548         g_hash_table_destroy (jit_icall_hash_addr);
8549         mono_os_mutex_destroy (&icall_mutex);
8550 }
8551
8552 /**
8553  * mono_add_internal_call:
8554  * @name: method specification to surface to the managed world
8555  * @method: pointer to a C method to invoke when the method is called
8556  *
8557  * This method surfaces the C function pointed by @method as a method
8558  * that has been surfaced in managed code with the method specified in
8559  * @name as an internal call.
8560  *
8561  * Internal calls are surfaced to all app domains loaded and they are
8562  * accessibly by a type with the specified name.
8563  *
8564  * You must provide a fully qualified type name, that is namespaces
8565  * and type name, followed by a colon and the method name, with an
8566  * optional signature to bind.
8567  *
8568  * For example, the following are all valid declarations:
8569  *
8570  * "MyApp.Services.ScriptService:Accelerate"
8571  * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8572  *
8573  * You use method parameters in cases where there might be more than
8574  * one surface method to managed code.  That way you can register different
8575  * internal calls for different method overloads.
8576  *
8577  * The internal calls are invoked with no marshalling.   This means that .NET
8578  * types like System.String are exposed as `MonoString *` parameters.   This is
8579  * different than the way that strings are surfaced in P/Invoke.
8580  *
8581  * For more information on how the parameters are marshalled, see the
8582  * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8583  * page.
8584  *
8585  * See the <a  href="mono-api-methods.html#method-desc">Method Description</a>
8586  * reference for more information on the format of method descriptions.
8587  */
8588 void
8589 mono_add_internal_call (const char *name, gconstpointer method)
8590 {
8591         mono_icall_lock ();
8592
8593         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8594
8595         mono_icall_unlock ();
8596 }
8597
8598 #ifndef DISABLE_ICALL_TABLES
8599
8600 #ifdef HAVE_ARRAY_ELEM_INIT
8601 static int
8602 compare_method_imap (const void *key, const void *elem)
8603 {
8604         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8605         return strcmp (key, method_name);
8606 }
8607
8608 static gpointer
8609 find_method_icall (const IcallTypeDesc *imap, const char *name)
8610 {
8611         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);
8612         if (!nameslot)
8613                 return NULL;
8614         return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8615 }
8616
8617 static int
8618 compare_class_imap (const void *key, const void *elem)
8619 {
8620         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8621         return strcmp (key, class_name);
8622 }
8623
8624 static const IcallTypeDesc*
8625 find_class_icalls (const char *name)
8626 {
8627         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);
8628         if (!nameslot)
8629                 return NULL;
8630         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8631 }
8632
8633 #else /* HAVE_ARRAY_ELEM_INIT */
8634
8635 static int
8636 compare_method_imap (const void *key, const void *elem)
8637 {
8638         const char** method_name = (const char**)elem;
8639         return strcmp (key, *method_name);
8640 }
8641
8642 static gpointer
8643 find_method_icall (const IcallTypeDesc *imap, const char *name)
8644 {
8645         const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8646         if (!nameslot)
8647                 return NULL;
8648         return (gpointer)icall_functions [(nameslot - icall_names)];
8649 }
8650
8651 static int
8652 compare_class_imap (const void *key, const void *elem)
8653 {
8654         const char** class_name = (const char**)elem;
8655         return strcmp (key, *class_name);
8656 }
8657
8658 static const IcallTypeDesc*
8659 find_class_icalls (const char *name)
8660 {
8661         const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8662         if (!nameslot)
8663                 return NULL;
8664         return &icall_type_descs [nameslot - icall_type_names];
8665 }
8666
8667 #endif /* HAVE_ARRAY_ELEM_INIT */
8668
8669 #endif /* DISABLE_ICALL_TABLES */
8670
8671 /* 
8672  * we should probably export this as an helper (handle nested types).
8673  * Returns the number of chars written in buf.
8674  */
8675 static int
8676 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8677 {
8678         int nspacelen, cnamelen;
8679         nspacelen = strlen (klass->name_space);
8680         cnamelen = strlen (klass->name);
8681         if (nspacelen + cnamelen + 2 > bufsize)
8682                 return 0;
8683         if (nspacelen) {
8684                 memcpy (buf, klass->name_space, nspacelen);
8685                 buf [nspacelen ++] = '.';
8686         }
8687         memcpy (buf + nspacelen, klass->name, cnamelen);
8688         buf [nspacelen + cnamelen] = 0;
8689         return nspacelen + cnamelen;
8690 }
8691
8692 #ifdef DISABLE_ICALL_TABLES
8693 static void
8694 no_icall_table (void)
8695 {
8696         g_assert_not_reached ();
8697 }
8698 #endif
8699
8700 gpointer
8701 mono_lookup_internal_call (MonoMethod *method)
8702 {
8703         char *sigstart;
8704         char *tmpsig;
8705         char mname [2048];
8706         int typelen = 0, mlen, siglen;
8707         gpointer res;
8708 #ifndef DISABLE_ICALL_TABLES
8709         const IcallTypeDesc *imap = NULL;
8710 #endif
8711
8712         g_assert (method != NULL);
8713
8714         if (method->is_inflated)
8715                 method = ((MonoMethodInflated *) method)->declaring;
8716
8717         if (method->klass->nested_in) {
8718                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8719                 if (!pos)
8720                         return NULL;
8721
8722                 mname [pos++] = '/';
8723                 mname [pos] = 0;
8724
8725                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8726                 if (!typelen)
8727                         return NULL;
8728
8729                 typelen += pos;
8730         } else {
8731                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8732                 if (!typelen)
8733                         return NULL;
8734         }
8735
8736 #ifndef DISABLE_ICALL_TABLES
8737         imap = find_class_icalls (mname);
8738 #endif
8739
8740         mname [typelen] = ':';
8741         mname [typelen + 1] = ':';
8742
8743         mlen = strlen (method->name);
8744         memcpy (mname + typelen + 2, method->name, mlen);
8745         sigstart = mname + typelen + 2 + mlen;
8746         *sigstart = 0;
8747
8748         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8749         siglen = strlen (tmpsig);
8750         if (typelen + mlen + siglen + 6 > sizeof (mname))
8751                 return NULL;
8752         sigstart [0] = '(';
8753         memcpy (sigstart + 1, tmpsig, siglen);
8754         sigstart [siglen + 1] = ')';
8755         sigstart [siglen + 2] = 0;
8756         g_free (tmpsig);
8757         
8758         mono_icall_lock ();
8759
8760         res = g_hash_table_lookup (icall_hash, mname);
8761         if (res) {
8762                 mono_icall_unlock ();;
8763                 return res;
8764         }
8765         /* try without signature */
8766         *sigstart = 0;
8767         res = g_hash_table_lookup (icall_hash, mname);
8768         if (res) {
8769                 mono_icall_unlock ();
8770                 return res;
8771         }
8772
8773 #ifdef DISABLE_ICALL_TABLES
8774         mono_icall_unlock ();
8775         /* Fail only when the result is actually used */
8776         /* mono_marshal_get_native_wrapper () depends on this */
8777         if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8778                 return ves_icall_System_String_ctor_RedirectToCreateString;
8779         else
8780                 return no_icall_table;
8781 #else
8782         /* it wasn't found in the static call tables */
8783         if (!imap) {
8784                 mono_icall_unlock ();
8785                 return NULL;
8786         }
8787         res = find_method_icall (imap, sigstart - mlen);
8788         if (res) {
8789                 mono_icall_unlock ();
8790                 return res;
8791         }
8792         /* try _with_ signature */
8793         *sigstart = '(';
8794         res = find_method_icall (imap, sigstart - mlen);
8795         if (res) {
8796                 mono_icall_unlock ();
8797                 return res;
8798         }
8799
8800         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8801         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8802         g_print ("The out of sync library is: %s\n", method->klass->image->name);
8803         g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8804         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");
8805         g_print ("If you see other errors or faults after this message they are probably related\n");
8806         g_print ("and you need to fix your mono install first.\n");
8807
8808         mono_icall_unlock ();
8809
8810         return NULL;
8811 #endif
8812 }
8813
8814 #ifdef ENABLE_ICALL_SYMBOL_MAP
8815 static int
8816 func_cmp (gconstpointer key, gconstpointer p)
8817 {
8818         return (gsize)key - (gsize)*(gsize*)p;
8819 }
8820 #endif
8821
8822 /*
8823  * mono_lookup_icall_symbol:
8824  *
8825  *   Given the icall METHOD, returns its C symbol.
8826  */
8827 const char*
8828 mono_lookup_icall_symbol (MonoMethod *m)
8829 {
8830 #ifdef DISABLE_ICALL_TABLES
8831         g_assert_not_reached ();
8832         return NULL;
8833 #else
8834 #ifdef ENABLE_ICALL_SYMBOL_MAP
8835         gpointer func;
8836         int i;
8837         gpointer slot;
8838         static gconstpointer *functions_sorted;
8839         static const char**symbols_sorted;
8840         static gboolean inited;
8841
8842         if (!inited) {
8843                 gboolean changed;
8844
8845                 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8846                 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8847                 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8848                 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8849                 /* Bubble sort the two arrays */
8850                 changed = TRUE;
8851                 while (changed) {
8852                         changed = FALSE;
8853                         for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8854                                 if (functions_sorted [i] > functions_sorted [i + 1]) {
8855                                         gconstpointer tmp;
8856
8857                                         tmp = functions_sorted [i];
8858                                         functions_sorted [i] = functions_sorted [i + 1];
8859                                         functions_sorted [i + 1] = tmp;
8860                                         tmp = symbols_sorted [i];
8861                                         symbols_sorted [i] = symbols_sorted [i + 1];
8862                                         symbols_sorted [i + 1] = tmp;
8863                                         changed = TRUE;
8864                                 }
8865                         }
8866                 }
8867         }
8868
8869         func = mono_lookup_internal_call (m);
8870         if (!func)
8871                 return NULL;
8872         slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8873         if (!slot)
8874                 return NULL;
8875         g_assert (slot);
8876         return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8877 #else
8878         fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8879         g_assert_not_reached ();
8880         return 0;
8881 #endif
8882 #endif
8883 }
8884
8885 static MonoType*
8886 type_from_typename (char *type_name)
8887 {
8888         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
8889
8890         if (!strcmp (type_name, "int"))
8891                 klass = mono_defaults.int_class;
8892         else if (!strcmp (type_name, "ptr"))
8893                 klass = mono_defaults.int_class;
8894         else if (!strcmp (type_name, "void"))
8895                 klass = mono_defaults.void_class;
8896         else if (!strcmp (type_name, "int32"))
8897                 klass = mono_defaults.int32_class;
8898         else if (!strcmp (type_name, "uint32"))
8899                 klass = mono_defaults.uint32_class;
8900         else if (!strcmp (type_name, "int8"))
8901                 klass = mono_defaults.sbyte_class;
8902         else if (!strcmp (type_name, "uint8"))
8903                 klass = mono_defaults.byte_class;
8904         else if (!strcmp (type_name, "int16"))
8905                 klass = mono_defaults.int16_class;
8906         else if (!strcmp (type_name, "uint16"))
8907                 klass = mono_defaults.uint16_class;
8908         else if (!strcmp (type_name, "long"))
8909                 klass = mono_defaults.int64_class;
8910         else if (!strcmp (type_name, "ulong"))
8911                 klass = mono_defaults.uint64_class;
8912         else if (!strcmp (type_name, "float"))
8913                 klass = mono_defaults.single_class;
8914         else if (!strcmp (type_name, "double"))
8915                 klass = mono_defaults.double_class;
8916         else if (!strcmp (type_name, "object"))
8917                 klass = mono_defaults.object_class;
8918         else if (!strcmp (type_name, "obj"))
8919                 klass = mono_defaults.object_class;
8920         else if (!strcmp (type_name, "string"))
8921                 klass = mono_defaults.string_class;
8922         else if (!strcmp (type_name, "bool"))
8923                 klass = mono_defaults.boolean_class;
8924         else if (!strcmp (type_name, "boolean"))
8925                 klass = mono_defaults.boolean_class;
8926         else {
8927                 g_error ("%s", type_name);
8928                 g_assert_not_reached ();
8929         }
8930         return &klass->byval_arg;
8931 }
8932
8933 /**
8934  * LOCKING: Take the corlib image lock.
8935  */
8936 MonoMethodSignature*
8937 mono_create_icall_signature (const char *sigstr)
8938 {
8939         gchar **parts;
8940         int i, len;
8941         gchar **tmp;
8942         MonoMethodSignature *res, *res2;
8943         MonoImage *corlib = mono_defaults.corlib;
8944
8945         mono_image_lock (corlib);
8946         res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8947         mono_image_unlock (corlib);
8948
8949         if (res)
8950                 return res;
8951
8952         parts = g_strsplit (sigstr, " ", 256);
8953
8954         tmp = parts;
8955         len = 0;
8956         while (*tmp) {
8957                 len ++;
8958                 tmp ++;
8959         }
8960
8961         res = mono_metadata_signature_alloc (corlib, len - 1);
8962         res->pinvoke = 1;
8963
8964 #ifdef HOST_WIN32
8965         /* 
8966          * Under windows, the default pinvoke calling convention is STDCALL but
8967          * we need CDECL.
8968          */
8969         res->call_convention = MONO_CALL_C;
8970 #endif
8971
8972         res->ret = type_from_typename (parts [0]);
8973         for (i = 1; i < len; ++i) {
8974                 res->params [i - 1] = type_from_typename (parts [i]);
8975         }
8976
8977         g_strfreev (parts);
8978
8979         mono_image_lock (corlib);
8980         res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8981         if (res2)
8982                 res = res2; /*Value is allocated in the image pool*/
8983         else
8984                 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8985         mono_image_unlock (corlib);
8986
8987         return res;
8988 }
8989
8990 MonoJitICallInfo *
8991 mono_find_jit_icall_by_name (const char *name)
8992 {
8993         MonoJitICallInfo *info;
8994         g_assert (jit_icall_hash_name);
8995
8996         mono_icall_lock ();
8997         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8998         mono_icall_unlock ();
8999         return info;
9000 }
9001
9002 MonoJitICallInfo *
9003 mono_find_jit_icall_by_addr (gconstpointer addr)
9004 {
9005         MonoJitICallInfo *info;
9006         g_assert (jit_icall_hash_addr);
9007
9008         mono_icall_lock ();
9009         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
9010         mono_icall_unlock ();
9011
9012         return info;
9013 }
9014
9015 /*
9016  * mono_get_jit_icall_info:
9017  *
9018  *   Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
9019  * caller should access it while holding the icall lock.
9020  */
9021 GHashTable*
9022 mono_get_jit_icall_info (void)
9023 {
9024         return jit_icall_hash_name;
9025 }
9026
9027 /*
9028  * mono_lookup_jit_icall_symbol:
9029  *
9030  *   Given the jit icall NAME, returns its C symbol if possible, or NULL.
9031  */
9032 const char*
9033 mono_lookup_jit_icall_symbol (const char *name)
9034 {
9035         MonoJitICallInfo *info;
9036         const char *res = NULL;
9037
9038         mono_icall_lock ();
9039         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9040         if (info)
9041                 res = info->c_symbol;
9042         mono_icall_unlock ();
9043         return res;
9044 }
9045
9046 void
9047 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
9048 {
9049         mono_icall_lock ();
9050         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
9051         mono_icall_unlock ();
9052 }
9053
9054 /*
9055  * 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
9056  * icalls without wrappers in some cases.
9057  */
9058 MonoJitICallInfo *
9059 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
9060 {
9061         MonoJitICallInfo *info;
9062         
9063         g_assert (func);
9064         g_assert (name);
9065
9066         mono_icall_lock ();
9067
9068         if (!jit_icall_hash_name) {
9069                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
9070                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
9071         }
9072
9073         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
9074                 g_warning ("jit icall already defined \"%s\"\n", name);
9075                 g_assert_not_reached ();
9076         }
9077
9078         info = g_new0 (MonoJitICallInfo, 1);
9079         
9080         info->name = name;
9081         info->func = func;
9082         info->sig = sig;
9083         info->c_symbol = c_symbol;
9084         info->no_raise = no_raise;
9085
9086         if (is_save) {
9087                 info->wrapper = func;
9088         } else {
9089                 info->wrapper = NULL;
9090         }
9091
9092         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
9093         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
9094
9095         mono_icall_unlock ();
9096         return info;
9097 }
9098
9099 MonoJitICallInfo *
9100 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
9101 {
9102         return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);
9103 }
9104