[runtime] MonoError-ize mono_compile_method
[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_checked (method, &error);
6563                 if (mono_error_set_pending_exception (&error))
6564                         return NULL;
6565         } else {
6566                 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6567                         method = mono_object_get_virtual_method (target, method);
6568                 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6569                 if (mono_error_set_pending_exception (&error))
6570                         return NULL;
6571                 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6572         }
6573
6574         mono_delegate_ctor_with_method (delegate, target, func, method);
6575
6576         return delegate;
6577 }
6578
6579 ICALL_EXPORT MonoMulticastDelegate *
6580 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6581 {
6582         MonoError error;
6583         MonoMulticastDelegate *ret;
6584
6585         g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6586
6587         ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6588         if (mono_error_set_pending_exception (&error))
6589                 return NULL;
6590
6591         ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6592
6593         return ret;
6594 }
6595
6596 ICALL_EXPORT MonoReflectionMethod*
6597 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6598 {
6599         MonoReflectionMethod *ret = NULL;
6600         MonoError error;
6601         ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6602         mono_error_set_pending_exception (&error);
6603         return ret;
6604 }
6605
6606 /* System.Buffer */
6607
6608 static inline gint32 
6609 mono_array_get_byte_length (MonoArray *array)
6610 {
6611         MonoClass *klass;
6612         int length;
6613         int i;
6614
6615         klass = array->obj.vtable->klass;
6616
6617         if (array->bounds == NULL)
6618                 length = array->max_length;
6619         else {
6620                 length = 1;
6621                 for (i = 0; i < klass->rank; ++ i)
6622                         length *= array->bounds [i].length;
6623         }
6624
6625         switch (klass->element_class->byval_arg.type) {
6626         case MONO_TYPE_I1:
6627         case MONO_TYPE_U1:
6628         case MONO_TYPE_BOOLEAN:
6629                 return length;
6630         case MONO_TYPE_I2:
6631         case MONO_TYPE_U2:
6632         case MONO_TYPE_CHAR:
6633                 return length << 1;
6634         case MONO_TYPE_I4:
6635         case MONO_TYPE_U4:
6636         case MONO_TYPE_R4:
6637                 return length << 2;
6638         case MONO_TYPE_I:
6639         case MONO_TYPE_U:
6640                 return length * sizeof (gpointer);
6641         case MONO_TYPE_I8:
6642         case MONO_TYPE_U8:
6643         case MONO_TYPE_R8:
6644                 return length << 3;
6645         default:
6646                 return -1;
6647         }
6648 }
6649
6650 ICALL_EXPORT gint32 
6651 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array) 
6652 {
6653         return mono_array_get_byte_length (array);
6654 }
6655
6656 ICALL_EXPORT gint8 
6657 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx) 
6658 {
6659         return mono_array_get (array, gint8, idx);
6660 }
6661
6662 ICALL_EXPORT void 
6663 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value) 
6664 {
6665         mono_array_set (array, gint8, idx, value);
6666 }
6667
6668 ICALL_EXPORT MonoBoolean
6669 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count) 
6670 {
6671         guint8 *src_buf, *dest_buf;
6672
6673         if (count < 0) {
6674                 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6675                 return FALSE;
6676         }
6677
6678         g_assert (count >= 0);
6679
6680         /* This is called directly from the class libraries without going through the managed wrapper */
6681         MONO_CHECK_ARG_NULL (src, FALSE);
6682         MONO_CHECK_ARG_NULL (dest, FALSE);
6683
6684         /* watch out for integer overflow */
6685         if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6686                 return FALSE;
6687
6688         src_buf = (guint8 *)src->vector + src_offset;
6689         dest_buf = (guint8 *)dest->vector + dest_offset;
6690
6691         if (src != dest)
6692                 memcpy (dest_buf, src_buf, count);
6693         else
6694                 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6695
6696         return TRUE;
6697 }
6698
6699 #ifndef DISABLE_REMOTING
6700 ICALL_EXPORT MonoObject *
6701 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6702 {
6703         MonoError error;
6704         MonoDomain *domain = mono_object_domain (this_obj); 
6705         MonoObject *res;
6706         MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6707         MonoTransparentProxy *tp;
6708         MonoType *type;
6709         MonoClass *klass;
6710
6711         res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6712         if (mono_error_set_pending_exception (&error))
6713                 return NULL;
6714
6715         tp = (MonoTransparentProxy*) res;
6716         
6717         MONO_OBJECT_SETREF (tp, rp, rp);
6718         type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6719         klass = mono_class_from_mono_type (type);
6720
6721         // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6722         mono_class_setup_vtable (klass);
6723         if (mono_class_has_failure (klass)) {
6724                 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6725                 return NULL;
6726         }
6727
6728         tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6729         if (!is_ok (&error)) {
6730                 mono_error_set_pending_exception (&error);
6731                 return NULL;
6732         }
6733         tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6734         if (!is_ok (&error)) {
6735                 mono_error_set_pending_exception (&error);
6736                 return NULL;
6737         }
6738
6739         res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6740         return res;
6741 }
6742
6743 ICALL_EXPORT MonoReflectionType *
6744 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6745 {
6746         MonoError error;
6747         MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6748         mono_error_set_pending_exception (&error);
6749
6750         return ret;
6751 }
6752 #endif
6753
6754 /* System.Environment */
6755
6756 MonoString*
6757 ves_icall_System_Environment_get_UserName (void)
6758 {
6759         /* using glib is more portable */
6760         return mono_string_new (mono_domain_get (), g_get_user_name ());
6761 }
6762
6763
6764 ICALL_EXPORT MonoString *
6765 ves_icall_System_Environment_get_MachineName (void)
6766 {
6767 #if defined (HOST_WIN32)
6768         gunichar2 *buf;
6769         guint32 len;
6770         MonoString *result;
6771
6772         len = MAX_COMPUTERNAME_LENGTH + 1;
6773         buf = g_new (gunichar2, len);
6774
6775         result = NULL;
6776         if (GetComputerName (buf, (PDWORD) &len)) {
6777                 MonoError error;
6778                 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6779                 mono_error_set_pending_exception (&error);
6780         }
6781
6782         g_free (buf);
6783         return result;
6784 #elif !defined(DISABLE_SOCKETS)
6785         MonoString *result;
6786         char *buf;
6787         int n;
6788 #if defined _SC_HOST_NAME_MAX
6789         n = sysconf (_SC_HOST_NAME_MAX);
6790         if (n == -1)
6791 #endif
6792         n = 512;
6793         buf = g_malloc (n+1);
6794         
6795         if (gethostname (buf, n) == 0){
6796                 buf [n] = 0;
6797                 result = mono_string_new (mono_domain_get (), buf);
6798         } else
6799                 result = NULL;
6800         g_free (buf);
6801         
6802         return result;
6803 #else
6804         return mono_string_new (mono_domain_get (), "mono");
6805 #endif
6806 }
6807
6808 ICALL_EXPORT int
6809 ves_icall_System_Environment_get_Platform (void)
6810 {
6811 #if defined (TARGET_WIN32)
6812         /* Win32NT */
6813         return 2;
6814 #elif defined(__MACH__)
6815         /* OSX */
6816         //
6817         // Notice that the value is hidden from user code, and only exposed
6818         // to mscorlib.   This is due to Mono's Unix/MacOS code predating the
6819         // define and making assumptions based on Unix/128/4 values before there
6820         // was a MacOS define.    Lots of code would assume that not-Unix meant
6821         // Windows, but in this case, it would be OSX. 
6822         //
6823         return 6;
6824 #else
6825         /* Unix */
6826         return 4;
6827 #endif
6828 }
6829
6830 ICALL_EXPORT MonoString *
6831 ves_icall_System_Environment_get_NewLine (void)
6832 {
6833 #if defined (HOST_WIN32)
6834         return mono_string_new (mono_domain_get (), "\r\n");
6835 #else
6836         return mono_string_new (mono_domain_get (), "\n");
6837 #endif
6838 }
6839
6840 ICALL_EXPORT MonoBoolean
6841 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6842 {
6843 #if SIZEOF_VOID_P == 8
6844         return TRUE;
6845 #else
6846 #ifdef HOST_WIN32
6847         gboolean isWow64Process = FALSE;
6848         if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6849                 return (MonoBoolean)isWow64Process;
6850         }
6851 #elif defined(HAVE_SYS_UTSNAME_H)
6852         struct utsname name;
6853
6854         if (uname (&name) >= 0) {
6855                 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6856         }
6857 #endif
6858         return FALSE;
6859 #endif
6860 }
6861
6862 ICALL_EXPORT MonoString *
6863 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6864 {
6865         const gchar *value;
6866         gchar *utf8_name;
6867
6868         if (name == NULL)
6869                 return NULL;
6870
6871         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6872         value = g_getenv (utf8_name);
6873
6874         g_free (utf8_name);
6875
6876         if (value == 0)
6877                 return NULL;
6878         
6879         return mono_string_new (mono_domain_get (), value);
6880 }
6881
6882 /*
6883  * There is no standard way to get at environ.
6884  */
6885 #ifndef _MSC_VER
6886 #ifndef __MINGW32_VERSION
6887 #if defined(__APPLE__)
6888 #if defined (TARGET_OSX)
6889 /* Apple defines this in crt_externs.h but doesn't provide that header for 
6890  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
6891  * in fact exist on all implementations (so far) 
6892  */
6893 gchar ***_NSGetEnviron(void);
6894 #define environ (*_NSGetEnviron())
6895 #else
6896 static char *mono_environ[1] = { NULL };
6897 #define environ mono_environ
6898 #endif /* defined (TARGET_OSX) */
6899 #else
6900 extern
6901 char **environ;
6902 #endif
6903 #endif
6904 #endif
6905
6906 ICALL_EXPORT MonoArray *
6907 ves_icall_System_Environment_GetCoomandLineArgs (void)
6908 {
6909         MonoError error;
6910         MonoArray *result = mono_runtime_get_main_args_checked (&error);
6911         mono_error_set_pending_exception (&error);
6912         return result;
6913 }
6914
6915 ICALL_EXPORT MonoArray *
6916 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6917 {
6918 #ifdef HOST_WIN32
6919         MonoError error;
6920         MonoArray *names;
6921         MonoDomain *domain;
6922         MonoString *str;
6923         WCHAR* env_strings;
6924         WCHAR* env_string;
6925         WCHAR* equal_str;
6926         int n = 0;
6927
6928         env_strings = GetEnvironmentStrings();
6929
6930         if (env_strings) {
6931                 env_string = env_strings;
6932                 while (*env_string != '\0') {
6933                 /* weird case that MS seems to skip */
6934                         if (*env_string != '=')
6935                                 n++;
6936                         while (*env_string != '\0')
6937                                 env_string++;
6938                         env_string++;
6939                 }
6940         }
6941
6942         domain = mono_domain_get ();
6943         names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6944         if (mono_error_set_pending_exception (&error))
6945                 return NULL;
6946
6947         if (env_strings) {
6948                 n = 0;
6949                 env_string = env_strings;
6950                 while (*env_string != '\0') {
6951                         /* weird case that MS seems to skip */
6952                         if (*env_string != '=') {
6953                                 equal_str = wcschr(env_string, '=');
6954                                 g_assert(equal_str);
6955                                 MonoError error;
6956                                 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6957                                 if (mono_error_set_pending_exception (&error))
6958                                         return NULL;
6959
6960                                 mono_array_setref (names, n, str);
6961                                 n++;
6962                         }
6963                         while (*env_string != '\0')
6964                                 env_string++;
6965                         env_string++;
6966                 }
6967
6968                 FreeEnvironmentStrings (env_strings);
6969         }
6970
6971         return names;
6972
6973 #else
6974         MonoError error;
6975         MonoArray *names;
6976         MonoDomain *domain;
6977         MonoString *str;
6978         gchar **e, **parts;
6979         int n;
6980
6981         n = 0;
6982         for (e = environ; *e != 0; ++ e)
6983                 ++ n;
6984
6985         domain = mono_domain_get ();
6986         names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6987         if (mono_error_set_pending_exception (&error))
6988                 return NULL;
6989
6990         n = 0;
6991         for (e = environ; *e != 0; ++ e) {
6992                 parts = g_strsplit (*e, "=", 2);
6993                 if (*parts != 0) {
6994                         str = mono_string_new (domain, *parts);
6995                         mono_array_setref (names, n, str);
6996                 }
6997
6998                 g_strfreev (parts);
6999
7000                 ++ n;
7001         }
7002
7003         return names;
7004 #endif
7005 }
7006
7007 /*
7008  * If your platform lacks setenv/unsetenv, you must upgrade your glib.
7009  */
7010 #if !GLIB_CHECK_VERSION(2,4,0)
7011 #define g_setenv(a,b,c)   setenv(a,b,c)
7012 #define g_unsetenv(a) unsetenv(a)
7013 #endif
7014
7015 ICALL_EXPORT void
7016 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
7017 {
7018 #ifdef HOST_WIN32
7019         gunichar2 *utf16_name, *utf16_value;
7020 #else
7021         gchar *utf8_name, *utf8_value;
7022         MonoError error;
7023 #endif
7024
7025 #ifdef HOST_WIN32
7026         utf16_name = mono_string_to_utf16 (name);
7027         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7028                 SetEnvironmentVariable (utf16_name, NULL);
7029                 g_free (utf16_name);
7030                 return;
7031         }
7032
7033         utf16_value = mono_string_to_utf16 (value);
7034
7035         SetEnvironmentVariable (utf16_name, utf16_value);
7036
7037         g_free (utf16_name);
7038         g_free (utf16_value);
7039 #else
7040         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
7041
7042         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7043                 g_unsetenv (utf8_name);
7044                 g_free (utf8_name);
7045                 return;
7046         }
7047
7048         utf8_value = mono_string_to_utf8_checked (value, &error);
7049         if (!mono_error_ok (&error)) {
7050                 g_free (utf8_name);
7051                 mono_error_set_pending_exception (&error);
7052                 return;
7053         }
7054         g_setenv (utf8_name, utf8_value, TRUE);
7055
7056         g_free (utf8_name);
7057         g_free (utf8_value);
7058 #endif
7059 }
7060
7061 ICALL_EXPORT void
7062 ves_icall_System_Environment_Exit (int result)
7063 {
7064         mono_environment_exitcode_set (result);
7065
7066 /* FIXME: There are some cleanup hangs that should be worked out, but
7067  * if the program is going to exit, everything will be cleaned up when
7068  * NaCl exits anyway.
7069  */
7070 #ifndef __native_client__
7071         if (!mono_runtime_try_shutdown ())
7072                 mono_thread_exit ();
7073
7074         /* Suspend all managed threads since the runtime is going away */
7075         mono_thread_suspend_all_other_threads ();
7076
7077         mono_runtime_quit ();
7078 #endif
7079
7080         /* we may need to do some cleanup here... */
7081         exit (result);
7082 }
7083
7084 ICALL_EXPORT MonoString*
7085 ves_icall_System_Environment_GetGacPath (void)
7086 {
7087         return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
7088 }
7089
7090 ICALL_EXPORT MonoString*
7091 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
7092 {
7093 #if defined (HOST_WIN32)
7094         #ifndef CSIDL_FLAG_CREATE
7095                 #define CSIDL_FLAG_CREATE       0x8000
7096         #endif
7097
7098         WCHAR path [MAX_PATH];
7099         /* Create directory if no existing */
7100         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
7101                 int len = 0;
7102                 while (path [len])
7103                         ++ len;
7104                 MonoError error;
7105                 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
7106                 mono_error_set_pending_exception (&error);
7107                 return res;
7108         }
7109 #else
7110         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7111 #endif
7112         return mono_string_new (mono_domain_get (), "");
7113 }
7114
7115 ICALL_EXPORT MonoArray *
7116 ves_icall_System_Environment_GetLogicalDrives (void)
7117 {
7118         MonoError error;
7119         gunichar2 buf [256], *ptr, *dname;
7120         gunichar2 *u16;
7121         guint initial_size = 127, size = 128;
7122         gint ndrives;
7123         MonoArray *result;
7124         MonoString *drivestr;
7125         MonoDomain *domain = mono_domain_get ();
7126         gint len;
7127
7128         buf [0] = '\0';
7129         ptr = buf;
7130
7131         while (size > initial_size) {
7132                 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7133                 if (size > initial_size) {
7134                         if (ptr != buf)
7135                                 g_free (ptr);
7136                         ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7137                         initial_size = size;
7138                         size++;
7139                 }
7140         }
7141
7142         /* Count strings */
7143         dname = ptr;
7144         ndrives = 0;
7145         do {
7146                 while (*dname++);
7147                 ndrives++;
7148         } while (*dname);
7149
7150         dname = ptr;
7151         result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7152         if (mono_error_set_pending_exception (&error))
7153                 goto leave;
7154
7155         ndrives = 0;
7156         do {
7157                 len = 0;
7158                 u16 = dname;
7159                 while (*u16) { u16++; len ++; }
7160                 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7161                 if (mono_error_set_pending_exception (&error))
7162                         goto leave;
7163
7164                 mono_array_setref (result, ndrives++, drivestr);
7165                 while (*dname++);
7166         } while (*dname);
7167
7168 leave:
7169         if (ptr != buf)
7170                 g_free (ptr);
7171
7172         return result;
7173 }
7174
7175 ICALL_EXPORT MonoString *
7176 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7177 {
7178         MonoError error;
7179         gunichar2 volume_name [MAX_PATH + 1];
7180         
7181         if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7182                 return NULL;
7183         MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
7184         mono_error_set_pending_exception (&error);
7185         return result;
7186 }
7187
7188 ICALL_EXPORT MonoString *
7189 ves_icall_System_Environment_InternalGetHome (void)
7190 {
7191         return mono_string_new (mono_domain_get (), g_get_home_dir ());
7192 }
7193
7194 static const char *encodings [] = {
7195         (char *) 1,
7196                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7197                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7198                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7199         (char *) 2,
7200                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7201                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7202                 "x_unicode_2_0_utf_7",
7203         (char *) 3,
7204                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7205                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7206         (char *) 4,
7207                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7208                 "iso_10646_ucs2",
7209         (char *) 5,
7210                 "unicodefffe", "utf_16be",
7211         (char *) 6,
7212                 "iso_8859_1",
7213         (char *) 0
7214 };
7215
7216 /*
7217  * Returns the internal codepage, if the value of "int_code_page" is
7218  * 1 at entry, and we can not compute a suitable code page number,
7219  * returns the code page as a string
7220  */
7221 ICALL_EXPORT MonoString*
7222 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page) 
7223 {
7224         const char *cset;
7225         const char *p;
7226         char *c;
7227         char *codepage = NULL;
7228         int code;
7229         int want_name = *int_code_page;
7230         int i;
7231         
7232         *int_code_page = -1;
7233
7234         g_get_charset (&cset);
7235         c = codepage = strdup (cset);
7236         for (c = codepage; *c; c++){
7237                 if (isascii (*c) && isalpha (*c))
7238                         *c = tolower (*c);
7239                 if (*c == '-')
7240                         *c = '_';
7241         }
7242         /* g_print ("charset: %s\n", cset); */
7243         
7244         /* handle some common aliases */
7245         p = encodings [0];
7246         code = 0;
7247         for (i = 0; p != 0; ){
7248                 if ((gsize) p < 7){
7249                         code = (gssize) p;
7250                         p = encodings [++i];
7251                         continue;
7252                 }
7253                 if (strcmp (p, codepage) == 0){
7254                         *int_code_page = code;
7255                         break;
7256                 }
7257                 p = encodings [++i];
7258         }
7259         
7260         if (strstr (codepage, "utf_8") != NULL)
7261                 *int_code_page |= 0x10000000;
7262         free (codepage);
7263         
7264         if (want_name && *int_code_page == -1)
7265                 return mono_string_new (mono_domain_get (), cset);
7266         else
7267                 return NULL;
7268 }
7269
7270 ICALL_EXPORT MonoBoolean
7271 ves_icall_System_Environment_get_HasShutdownStarted (void)
7272 {
7273         if (mono_runtime_is_shutting_down ())
7274                 return TRUE;
7275
7276         if (mono_domain_is_unloading (mono_domain_get ()))
7277                 return TRUE;
7278
7279         return FALSE;
7280 }
7281
7282 ICALL_EXPORT void
7283 ves_icall_System_Environment_BroadcastSettingChange (void)
7284 {
7285 #ifdef HOST_WIN32
7286         SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7287 #endif
7288 }
7289
7290 ICALL_EXPORT
7291 gint32
7292 ves_icall_System_Environment_get_TickCount (void)
7293 {
7294         /* this will overflow after ~24 days */
7295         return (gint32) (mono_msec_boottime () & 0xffffffff);
7296 }
7297
7298 ICALL_EXPORT gint32
7299 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7300 {
7301         return 9;
7302 }
7303
7304 ICALL_EXPORT void
7305 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj, 
7306                                          MonoReflectionMethod *method,
7307                                          MonoArray *out_args)
7308 {
7309         mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
7310 }
7311
7312 #ifndef DISABLE_REMOTING
7313 ICALL_EXPORT MonoBoolean
7314 ves_icall_IsTransparentProxy (MonoObject *proxy)
7315 {
7316         if (!proxy)
7317                 return 0;
7318
7319         if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7320                 return 1;
7321
7322         return 0;
7323 }
7324
7325 ICALL_EXPORT MonoReflectionMethod *
7326 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7327         MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7328 {
7329         MonoReflectionMethod *ret = NULL;
7330         MonoError error;
7331
7332         MonoClass *klass;
7333         MonoMethod *method;
7334         MonoMethod **vtable;
7335         MonoMethod *res = NULL;
7336
7337         MONO_CHECK_ARG_NULL (rtype, NULL);
7338         MONO_CHECK_ARG_NULL (rmethod, NULL);
7339
7340         method = rmethod->method;
7341         klass = mono_class_from_mono_type (rtype->type);
7342         mono_class_init_checked (klass, &error);
7343         if (mono_error_set_pending_exception (&error))
7344                 return NULL;
7345
7346         if (MONO_CLASS_IS_INTERFACE (klass))
7347                 return NULL;
7348
7349         if (method->flags & METHOD_ATTRIBUTE_STATIC)
7350                 return NULL;
7351
7352         if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7353                 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7354                         return rmethod;
7355                 else
7356                         return NULL;
7357         }
7358
7359         mono_class_setup_vtable (klass);
7360         vtable = klass->vtable;
7361
7362         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7363                 gboolean variance_used = FALSE;
7364                 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7365                 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7366                 if (offs >= 0)
7367                         res = vtable [offs + method->slot];
7368         } else {
7369                 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7370                         return NULL;
7371
7372                 if (method->slot != -1)
7373                         res = vtable [method->slot];
7374         }
7375
7376         if (!res)
7377                 return NULL;
7378
7379         ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7380         mono_error_set_pending_exception (&error);
7381         return ret;
7382 }
7383
7384 ICALL_EXPORT void
7385 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7386 {
7387         MonoError error;
7388         MonoClass *klass;
7389         MonoVTable* vtable;
7390
7391         klass = mono_class_from_mono_type (type->type);
7392         vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7393         if (!is_ok (&error)) {
7394                 mono_error_set_pending_exception (&error);
7395                 return;
7396         }
7397
7398         mono_vtable_set_is_remote (vtable, enable);
7399 }
7400
7401 #else /* DISABLE_REMOTING */
7402
7403 ICALL_EXPORT void
7404 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7405 {
7406         g_assert_not_reached ();
7407 }
7408
7409 #endif
7410
7411 ICALL_EXPORT MonoObject *
7412 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7413 {
7414         MonoError error;
7415         MonoClass *klass;
7416         MonoDomain *domain;
7417         MonoObject *ret;
7418         
7419         domain = mono_object_domain (type);
7420         klass = mono_class_from_mono_type (type->type);
7421         mono_class_init_checked (klass, &error);
7422         if (mono_error_set_pending_exception (&error))
7423                 return NULL;
7424
7425         if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7426                 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7427                 return NULL;
7428         }
7429
7430         if (klass->rank >= 1) {
7431                 g_assert (klass->rank == 1);
7432                 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7433                 mono_error_set_pending_exception (&error);
7434                 return ret;
7435         } else {
7436                 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7437                 if (!is_ok (&error)) {
7438                         mono_error_set_pending_exception (&error);
7439                         return NULL;
7440                 }
7441                 /* Bypass remoting object creation check */
7442                 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7443                 mono_error_set_pending_exception (&error);
7444
7445                 return ret;
7446         }
7447 }
7448
7449 ICALL_EXPORT MonoString *
7450 ves_icall_System_IO_get_temp_path (void)
7451 {
7452         return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7453 }
7454
7455 #ifndef PLATFORM_NO_DRIVEINFO
7456 ICALL_EXPORT MonoBoolean
7457 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7458                                                 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7459                                                 gint32 *error)
7460 {
7461         gboolean result;
7462         ULARGE_INTEGER wapi_free_bytes_avail;
7463         ULARGE_INTEGER wapi_total_number_of_bytes;
7464         ULARGE_INTEGER wapi_total_number_of_free_bytes;
7465
7466         *error = ERROR_SUCCESS;
7467         result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7468                                      &wapi_total_number_of_free_bytes);
7469
7470         if (result) {
7471                 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7472                 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7473                 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7474         } else {
7475                 *free_bytes_avail = 0;
7476                 *total_number_of_bytes = 0;
7477                 *total_number_of_free_bytes = 0;
7478                 *error = GetLastError ();
7479         }
7480
7481         return result;
7482 }
7483
7484 ICALL_EXPORT guint32
7485 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7486 {
7487         return GetDriveType (mono_string_chars (root_path_name));
7488 }
7489 #endif
7490
7491 ICALL_EXPORT gpointer
7492 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7493 {
7494         MonoError error;
7495         gpointer result = mono_compile_method_checked (method, &error);
7496         mono_error_set_pending_exception (&error);
7497         return result;
7498 }
7499
7500 ICALL_EXPORT MonoString *
7501 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7502 {
7503         MonoString *mcpath;
7504         gchar *path;
7505
7506         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7507
7508 #if defined (HOST_WIN32)
7509         /* Avoid mixing '/' and '\\' */
7510         {
7511                 gint i;
7512                 for (i = strlen (path) - 1; i >= 0; i--)
7513                         if (path [i] == '/')
7514                                 path [i] = '\\';
7515         }
7516 #endif
7517         mcpath = mono_string_new (mono_domain_get (), path);
7518         g_free (path);
7519
7520         return mcpath;
7521 }
7522
7523 static MonoString *
7524 get_bundled_app_config (void)
7525 {
7526         const gchar *app_config;
7527         MonoDomain *domain;
7528         MonoString *file;
7529         gchar *config_file_name, *config_file_path;
7530         gsize len, config_file_path_length, config_ext_length;
7531         gchar *module;
7532
7533         domain = mono_domain_get ();
7534         file = domain->setup->configuration_file;
7535         if (!file || file->length == 0)
7536                 return NULL;
7537
7538         // Retrieve config file and remove the extension
7539         config_file_name = mono_string_to_utf8 (file);
7540         config_file_path = mono_portability_find_file (config_file_name, TRUE);
7541         if (!config_file_path)
7542                 config_file_path = config_file_name;
7543
7544         config_file_path_length = strlen (config_file_path);
7545         config_ext_length = strlen (".config");
7546         if (config_file_path_length <= config_ext_length)
7547                 return NULL;
7548
7549         len = config_file_path_length - config_ext_length;
7550         module = (gchar *)g_malloc0 (len + 1);
7551         memcpy (module, config_file_path, len);
7552         // Get the config file from the module name
7553         app_config = mono_config_string_for_assembly_file (module);
7554         // Clean-up
7555         g_free (module);
7556         if (config_file_name != config_file_path)
7557                 g_free (config_file_name);
7558         g_free (config_file_path);
7559
7560         if (!app_config)
7561                 return NULL;
7562
7563         return mono_string_new (mono_domain_get (), app_config);
7564 }
7565
7566 static MonoString *
7567 get_bundled_machine_config (void)
7568 {
7569         const gchar *machine_config;
7570
7571         machine_config = mono_get_machine_config ();
7572
7573         if (!machine_config)
7574                 return NULL;
7575
7576         return mono_string_new (mono_domain_get (), machine_config);
7577 }
7578
7579 ICALL_EXPORT MonoString *
7580 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7581 {
7582         MonoString *ipath;
7583         gchar *path;
7584
7585         path = g_path_get_dirname (mono_get_config_dir ());
7586
7587 #if defined (HOST_WIN32)
7588         /* Avoid mixing '/' and '\\' */
7589         {
7590                 gint i;
7591                 for (i = strlen (path) - 1; i >= 0; i--)
7592                         if (path [i] == '/')
7593                                 path [i] = '\\';
7594         }
7595 #endif
7596         ipath = mono_string_new (mono_domain_get (), path);
7597         g_free (path);
7598
7599         return ipath;
7600 }
7601
7602 ICALL_EXPORT gboolean
7603 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7604 {
7605         MonoPEResourceDataEntry *entry;
7606         MonoImage *image;
7607
7608         if (!assembly || !result || !size)
7609                 return FALSE;
7610
7611         *result = NULL;
7612         *size = 0;
7613         image = assembly->assembly->image;
7614         entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7615         if (!entry)
7616                 return FALSE;
7617
7618         *result = mono_image_rva_map (image, entry->rde_data_offset);
7619         if (!(*result)) {
7620                 g_free (entry);
7621                 return FALSE;
7622         }
7623         *size = entry->rde_size;
7624         g_free (entry);
7625         return TRUE;
7626 }
7627
7628 ICALL_EXPORT MonoBoolean
7629 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7630 {
7631         return mono_is_debugger_attached ();
7632 }
7633
7634 ICALL_EXPORT MonoBoolean
7635 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7636 {
7637         if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7638                 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7639         else
7640                 return FALSE;
7641 }
7642
7643 ICALL_EXPORT void
7644 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7645 {
7646         if (mono_get_runtime_callbacks ()->debug_log)
7647                 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7648 }
7649
7650 ICALL_EXPORT void
7651 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7652 {
7653 #if defined (HOST_WIN32)
7654         OutputDebugString (mono_string_chars (message));
7655 #else
7656         g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7657 #endif
7658 }
7659
7660 /* Only used for value types */
7661 ICALL_EXPORT MonoObject *
7662 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7663 {
7664         MonoError error;
7665         MonoObject *result;
7666         MonoClass *klass;
7667         MonoDomain *domain;
7668         
7669         domain = mono_object_domain (type);
7670         klass = mono_class_from_mono_type (type->type);
7671         mono_class_init_checked (klass, &error);
7672         if (mono_error_set_pending_exception (&error))
7673                 return NULL;
7674
7675         if (mono_class_is_nullable (klass))
7676                 /* No arguments -> null */
7677                 return NULL;
7678
7679         result = mono_object_new_checked (domain, klass, &error);
7680         mono_error_set_pending_exception (&error);
7681         return result;
7682 }
7683
7684 ICALL_EXPORT MonoReflectionMethod *
7685 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7686 {
7687         MonoReflectionMethod *ret = NULL;
7688         MonoError error;
7689
7690         MonoClass *klass, *parent;
7691         MonoGenericContext *generic_inst = NULL;
7692         MonoMethod *method = m->method;
7693         MonoMethod *result = NULL;
7694         int slot;
7695
7696         if (method->klass == NULL)
7697                 return m;
7698
7699         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7700             MONO_CLASS_IS_INTERFACE (method->klass) ||
7701             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7702                 return m;
7703
7704         slot = mono_method_get_vtable_slot (method);
7705         if (slot == -1)
7706                 return m;
7707
7708         klass = method->klass;
7709         if (klass->generic_class) {
7710                 generic_inst = mono_class_get_context (klass);
7711                 klass = klass->generic_class->container_class;
7712         }
7713
7714         if (definition) {
7715                 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7716                 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7717                         /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7718                            or klass is the generic container class and generic_inst is the instantiation.
7719
7720                            when we go to the parent, if the parent is an open constructed type, we need to
7721                            replace the type parameters by the definitions from the generic_inst, and then take it
7722                            apart again into the klass and the generic_inst.
7723
7724                            For cases like this:
7725                            class C<T> : B<T, int> {
7726                                public override void Foo () { ... }
7727                            }
7728                            class B<U,V> : A<HashMap<U,V>> {
7729                                public override void Foo () { ... }
7730                            }
7731                            class A<X> {
7732                                public virtual void Foo () { ... }
7733                            }
7734
7735                            if at each iteration the parent isn't open, we can skip inflating it.  if at some
7736                            iteration the parent isn't generic (after possible inflation), we set generic_inst to
7737                            NULL;
7738                         */
7739                         MonoGenericContext *parent_inst = NULL;
7740                         if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7741                                 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7742                                 if (!mono_error_ok (&error)) {
7743                                         mono_error_set_pending_exception (&error);
7744                                         return NULL;
7745                                 }
7746                         }
7747                         if (parent->generic_class) {
7748                                 parent_inst = mono_class_get_context (parent);
7749                                 parent = parent->generic_class->container_class;
7750                         }
7751
7752                         mono_class_setup_vtable (parent);
7753                         if (parent->vtable_size <= slot)
7754                                 break;
7755                         klass = parent;
7756                         generic_inst = parent_inst;
7757                 }
7758         } else {
7759                 klass = klass->parent;
7760                 if (!klass)
7761                         return m;
7762                 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7763                         klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7764                         if (!mono_error_ok (&error)) {
7765                                 mono_error_set_pending_exception (&error);
7766                                 return NULL;
7767                         }
7768
7769                         generic_inst = NULL;
7770                 }
7771                 if (klass->generic_class) {
7772                         generic_inst = mono_class_get_context (klass);
7773                         klass = klass->generic_class->container_class;
7774                 }
7775
7776         }
7777
7778         if (generic_inst) {
7779                 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7780                 if (!mono_error_ok (&error)) {
7781                         mono_error_set_pending_exception (&error);
7782                         return NULL;
7783                 }
7784         }
7785
7786         if (klass == method->klass)
7787                 return m;
7788
7789         /*This is possible if definition == FALSE.
7790          * Do it here to be really sure we don't read invalid memory.
7791          */
7792         if (slot >= klass->vtable_size)
7793                 return m;
7794
7795         mono_class_setup_vtable (klass);
7796
7797         result = klass->vtable [slot];
7798         if (result == NULL) {
7799                 /* It is an abstract method */
7800                 gpointer iter = NULL;
7801                 while ((result = mono_class_get_methods (klass, &iter)))
7802                         if (result->slot == slot)
7803                                 break;
7804         }
7805
7806         if (result == NULL)
7807                 return m;
7808
7809         ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7810         mono_error_set_pending_exception (&error);
7811         return ret;
7812 }
7813
7814 ICALL_EXPORT MonoString*
7815 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7816 {
7817         MonoMethod *method = m->method;
7818
7819         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7820         return m->name;
7821 }
7822
7823 ICALL_EXPORT void
7824 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7825 {
7826         iter->sig = *(MonoMethodSignature**)argsp;
7827         
7828         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7829         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7830
7831         iter->next_arg = 0;
7832         /* FIXME: it's not documented what start is exactly... */
7833         if (start) {
7834                 iter->args = start;
7835         } else {
7836                 iter->args = argsp + sizeof (gpointer);
7837         }
7838         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7839
7840         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7841 }
7842
7843 ICALL_EXPORT MonoTypedRef
7844 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7845 {
7846         guint32 i, arg_size;
7847         gint32 align;
7848         MonoTypedRef res;
7849
7850         i = iter->sig->sentinelpos + iter->next_arg;
7851
7852         g_assert (i < iter->sig->param_count);
7853
7854         res.type = iter->sig->params [i];
7855         res.klass = mono_class_from_mono_type (res.type);
7856         arg_size = mono_type_stack_size (res.type, &align);
7857 #if defined(__arm__) || defined(__mips__)
7858         iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7859 #endif
7860         res.value = iter->args;
7861 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7862         /* Values are stored as 8 byte register sized objects, but 'value'
7863          * is dereferenced as a pointer in other routines.
7864          */
7865         res.value = (char*)res.value + 4;
7866 #endif
7867 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7868         if (arg_size <= sizeof (gpointer)) {
7869                 int dummy;
7870                 int padding = arg_size - mono_type_size (res.type, &dummy);
7871                 res.value = (guint8*)res.value + padding;
7872         }
7873 #endif
7874         iter->args = (char*)iter->args + arg_size;
7875         iter->next_arg++;
7876
7877         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7878
7879         return res;
7880 }
7881
7882 ICALL_EXPORT MonoTypedRef
7883 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7884 {
7885         guint32 i, arg_size;
7886         gint32 align;
7887         MonoTypedRef res;
7888
7889         i = iter->sig->sentinelpos + iter->next_arg;
7890
7891         g_assert (i < iter->sig->param_count);
7892
7893         while (i < iter->sig->param_count) {
7894                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7895                         continue;
7896                 res.type = iter->sig->params [i];
7897                 res.klass = mono_class_from_mono_type (res.type);
7898                 /* FIXME: endianess issue... */
7899                 arg_size = mono_type_stack_size (res.type, &align);
7900 #if defined(__arm__) || defined(__mips__)
7901                 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7902 #endif
7903                 res.value = iter->args;
7904                 iter->args = (char*)iter->args + arg_size;
7905                 iter->next_arg++;
7906                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7907                 return res;
7908         }
7909         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7910
7911         res.type = NULL;
7912         res.value = NULL;
7913         res.klass = NULL;
7914         return res;
7915 }
7916
7917 ICALL_EXPORT MonoType*
7918 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7919 {
7920         gint i;
7921         
7922         i = iter->sig->sentinelpos + iter->next_arg;
7923
7924         g_assert (i < iter->sig->param_count);
7925
7926         return iter->sig->params [i];
7927 }
7928
7929 ICALL_EXPORT MonoObject*
7930 mono_TypedReference_ToObject (MonoTypedRef* tref)
7931 {
7932         MonoError error;
7933         MonoObject *result = NULL;
7934         if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7935                 MonoObject** objp = (MonoObject **)tref->value;
7936                 return *objp;
7937         }
7938
7939         result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7940         mono_error_set_pending_exception (&error);
7941         return result;
7942 }
7943
7944 ICALL_EXPORT MonoTypedRef
7945 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7946 {
7947         MonoTypedRef res;
7948         MonoReflectionField *f;
7949         MonoClass *klass;
7950         MonoType *ftype = NULL;
7951         guint8 *p = NULL;
7952         int i;
7953
7954         memset (&res, 0, sizeof (res));
7955
7956         g_assert (fields);
7957         g_assert (mono_array_length (fields) > 0);
7958
7959         klass = target->vtable->klass;
7960
7961         for (i = 0; i < mono_array_length (fields); ++i) {
7962                 f = mono_array_get (fields, MonoReflectionField*, i);
7963                 if (f == NULL) {
7964                         mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7965                         return res;
7966                 }
7967                 if (f->field->parent != klass) {
7968                         mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7969                         return res;
7970                 }
7971                 if (i == 0)
7972                         p = (guint8*)target + f->field->offset;
7973                 else
7974                         p += f->field->offset - sizeof (MonoObject);
7975                 klass = mono_class_from_mono_type (f->field->type);
7976                 ftype = f->field->type;
7977         }
7978
7979         res.type = ftype;
7980         res.klass = mono_class_from_mono_type (ftype);
7981         res.value = p;
7982
7983         return res;
7984 }
7985
7986 static void
7987 prelink_method (MonoMethod *method, MonoError *error)
7988 {
7989         const char *exc_class, *exc_arg;
7990
7991         mono_error_init (error);
7992         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7993                 return;
7994         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7995         if (exc_class) {
7996                 mono_error_set_exception_instance (error,
7997                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7998                 return;
7999         }
8000         /* create the wrapper, too? */
8001 }
8002
8003 ICALL_EXPORT void
8004 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
8005 {
8006         MonoError error;
8007
8008         prelink_method (method->method, &error);
8009         mono_error_set_pending_exception (&error);
8010 }
8011
8012 ICALL_EXPORT void
8013 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
8014 {
8015         MonoError error;
8016         MonoClass *klass = mono_class_from_mono_type (type->type);
8017         MonoMethod* m;
8018         gpointer iter = NULL;
8019
8020         mono_class_init_checked (klass, &error);
8021         if (mono_error_set_pending_exception (&error))
8022                 return;
8023
8024         while ((m = mono_class_get_methods (klass, &iter))) {
8025                 prelink_method (m, &error);
8026                 if (mono_error_set_pending_exception (&error))
8027                         return;
8028         }
8029 }
8030
8031 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
8032 ICALL_EXPORT void
8033 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
8034                                             gint32 const **exponents,
8035                                             gunichar2 const **digitLowerTable,
8036                                             gunichar2 const **digitUpperTable,
8037                                             gint64 const **tenPowersList,
8038                                             gint32 const **decHexDigits)
8039 {
8040         *mantissas = Formatter_MantissaBitsTable;
8041         *exponents = Formatter_TensExponentTable;
8042         *digitLowerTable = Formatter_DigitLowerTable;
8043         *digitUpperTable = Formatter_DigitUpperTable;
8044         *tenPowersList = Formatter_TenPowersList;
8045         *decHexDigits = Formatter_DecHexDigits;
8046 }
8047
8048 /*
8049  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
8050  * and avoid useless allocations.
8051  */
8052 static MonoArray*
8053 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
8054 {
8055         MonoReflectionType *rt;
8056         MonoArray *res;
8057         int i, count = 0;
8058
8059         mono_error_init (error);
8060         for (i = 0; i < type->num_mods; ++i) {
8061                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
8062                         count++;
8063         }
8064         if (!count)
8065                 return NULL;
8066         res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
8067         return_val_if_nok (error, NULL);
8068         count = 0;
8069         for (i = 0; i < type->num_mods; ++i) {
8070                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
8071                         MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
8072                         return_val_if_nok (error, NULL);
8073
8074                         rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8075                         return_val_if_nok (error, NULL);
8076
8077                         mono_array_setref (res, count, rt);
8078                         count++;
8079                 }
8080         }
8081         return res;
8082 }
8083
8084 ICALL_EXPORT MonoArray*
8085 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
8086 {
8087         MonoError error;
8088         MonoType *type = param->ClassImpl->type;
8089         MonoClass *member_class = mono_object_class (param->MemberImpl);
8090         MonoMethod *method = NULL;
8091         MonoImage *image;
8092         int pos;
8093         MonoMethodSignature *sig;
8094         MonoArray *res;
8095
8096         if (mono_class_is_reflection_method_or_constructor (member_class)) {
8097                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8098                 method = rmethod->method;
8099         } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
8100                 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8101                 if (!(method = prop->property->get))
8102                         method = prop->property->set;
8103                 g_assert (method);      
8104         } else {
8105                 char *type_name = mono_type_get_full_name (member_class);
8106                 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
8107                 MonoException *ex = mono_get_exception_not_supported  (msg);
8108                 g_free (type_name);
8109                 g_free (msg);
8110                 mono_set_pending_exception (ex);
8111                 return NULL;
8112         }
8113
8114         image = method->klass->image;
8115         pos = param->PositionImpl;
8116         sig = mono_method_signature (method);
8117         if (pos == -1)
8118                 type = sig->ret;
8119         else
8120                 type = sig->params [pos];
8121
8122         res = type_array_from_modifiers (image, type, optional, &error);
8123         mono_error_set_pending_exception (&error);
8124         return res;
8125 }
8126
8127 static MonoType*
8128 get_property_type (MonoProperty *prop)
8129 {
8130         MonoMethodSignature *sig;
8131         if (prop->get) {
8132                 sig = mono_method_signature (prop->get);
8133                 return sig->ret;
8134         } else if (prop->set) {
8135                 sig = mono_method_signature (prop->set);
8136                 return sig->params [sig->param_count - 1];
8137         }
8138         return NULL;
8139 }
8140
8141 ICALL_EXPORT MonoArray*
8142 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8143 {
8144         MonoError error;
8145         MonoType *type = get_property_type (property->property);
8146         MonoImage *image = property->klass->image;
8147         MonoArray *res;
8148
8149         if (!type)
8150                 return NULL;
8151         res = type_array_from_modifiers (image, type, optional, &error);
8152         mono_error_set_pending_exception (&error);
8153         return res;
8154 }
8155
8156 /*
8157  *Construct a MonoType suited to be used to decode a constant blob object.
8158  *
8159  * @type is the target type which will be constructed
8160  * @blob_type is the blob type, for example, that comes from the constant table
8161  * @real_type is the expected constructed type.
8162  */
8163 static void
8164 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8165 {
8166         type->type = blob_type;
8167         type->data.klass = NULL;
8168         if (blob_type == MONO_TYPE_CLASS)
8169                 type->data.klass = mono_defaults.object_class;
8170         else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8171                 /* For enums, we need to use the base type */
8172                 type->type = MONO_TYPE_VALUETYPE;
8173                 type->data.klass = mono_class_from_mono_type (real_type);
8174         } else
8175                 type->data.klass = mono_class_from_mono_type (real_type);
8176 }
8177
8178 ICALL_EXPORT MonoObject*
8179 property_info_get_default_value (MonoReflectionProperty *property)
8180 {
8181         MonoError error;
8182         MonoType blob_type;
8183         MonoProperty *prop = property->property;
8184         MonoType *type = get_property_type (prop);
8185         MonoDomain *domain = mono_object_domain (property); 
8186         MonoTypeEnum def_type;
8187         const char *def_value;
8188         MonoObject *o;
8189
8190         mono_class_init (prop->parent);
8191
8192         if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8193                 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8194                 return NULL;
8195         }
8196
8197         def_value = mono_class_get_property_default_value (prop, &def_type);
8198
8199         mono_type_from_blob_type (&blob_type, def_type, type);
8200         o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8201
8202         mono_error_set_pending_exception (&error);
8203         return o;
8204 }
8205
8206 ICALL_EXPORT MonoBoolean
8207 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8208 {
8209         MonoError error;
8210         MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8211         MonoCustomAttrInfo *cinfo;
8212         gboolean found;
8213
8214         mono_class_init_checked (attr_class, &error);
8215         if (mono_error_set_pending_exception (&error))
8216                 return FALSE;
8217
8218         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8219         if (!is_ok (&error)) {
8220                 mono_error_set_pending_exception (&error);
8221                 return FALSE;
8222         }
8223         if (!cinfo)
8224                 return FALSE;
8225         found = mono_custom_attrs_has_attr (cinfo, attr_class);
8226         if (!cinfo->cached)
8227                 mono_custom_attrs_free (cinfo);
8228         return found;
8229 }
8230
8231 ICALL_EXPORT MonoArray*
8232 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8233 {
8234         MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8235         MonoArray *res;
8236         MonoError error;
8237
8238         if (attr_class) {
8239                 mono_class_init_checked (attr_class, &error);
8240                 if (mono_error_set_pending_exception (&error))
8241                         return NULL;
8242         }
8243
8244         res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8245         if (!mono_error_ok (&error)) {
8246                 mono_error_set_pending_exception (&error);
8247                 return NULL;
8248         }
8249
8250         return res;
8251 }
8252
8253 ICALL_EXPORT MonoArray*
8254 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8255 {
8256         MonoError error;
8257         MonoArray *result;
8258         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8259         mono_error_set_pending_exception (&error);
8260         return result;
8261 }
8262
8263
8264 ICALL_EXPORT MonoString*
8265 ves_icall_Mono_Runtime_GetDisplayName (void)
8266 {
8267         char *info;
8268         MonoString *display_name;
8269
8270         info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8271         display_name = mono_string_new (mono_domain_get (), info);
8272         g_free (info);
8273         return display_name;
8274 }
8275
8276 ICALL_EXPORT MonoString*
8277 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8278 {
8279         MonoError error;
8280         MonoString *message;
8281         guint32 ret;
8282         gunichar2 buf[256];
8283         
8284         ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8285                              FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8286                              buf, 255, NULL);
8287         if (ret == 0) {
8288                 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8289         } else {
8290                 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8291                 if (mono_error_set_pending_exception (&error))
8292                         return NULL;
8293         }
8294         
8295         return message;
8296 }
8297
8298 ICALL_EXPORT gpointer
8299 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8300 {
8301         return GetCurrentProcess ();
8302 }
8303
8304 ICALL_EXPORT MonoBoolean
8305 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8306 {
8307         return GetExitCodeProcess (handle, (guint32*) exitcode);
8308 }
8309
8310 ICALL_EXPORT MonoBoolean
8311 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8312 {
8313 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8314         return CloseHandle (handle);
8315 #else
8316         return CloseProcess (handle);
8317 #endif
8318 }
8319
8320 ICALL_EXPORT MonoBoolean
8321 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8322 {
8323         return TerminateProcess (handle, exitcode);
8324 }
8325
8326 ICALL_EXPORT gint32
8327 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8328 {
8329         return WaitForInputIdle (handle, milliseconds);
8330 }
8331
8332 ICALL_EXPORT MonoBoolean
8333 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8334 {
8335         return GetProcessWorkingSetSize (handle, min, max);
8336 }
8337
8338 ICALL_EXPORT MonoBoolean
8339 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8340 {
8341         return SetProcessWorkingSetSize (handle, min, max);
8342 }
8343
8344 ICALL_EXPORT MonoBoolean
8345 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8346 {
8347         return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8348 }
8349
8350 ICALL_EXPORT gint32
8351 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8352 {
8353         return mono_process_current_pid ();
8354 }
8355
8356 ICALL_EXPORT gint32
8357 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8358 {
8359         return GetPriorityClass (handle);
8360 }
8361
8362 ICALL_EXPORT MonoBoolean
8363 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8364 {
8365         return SetPriorityClass (handle, priorityClass);
8366 }
8367
8368 #ifndef DISABLE_ICALL_TABLES
8369
8370 #define ICALL_TYPE(id,name,first)
8371 #define ICALL(id,name,func) Icall_ ## id,
8372
8373 enum {
8374 #include "metadata/icall-def.h"
8375         Icall_last
8376 };
8377
8378 #undef ICALL_TYPE
8379 #undef ICALL
8380 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8381 #define ICALL(id,name,func)
8382 enum {
8383 #include "metadata/icall-def.h"
8384         Icall_type_num
8385 };
8386
8387 #undef ICALL_TYPE
8388 #undef ICALL
8389 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8390 #define ICALL(id,name,func)
8391 typedef struct {
8392         guint16 first_icall;
8393 } IcallTypeDesc;
8394
8395 static const IcallTypeDesc
8396 icall_type_descs [] = {
8397 #include "metadata/icall-def.h"
8398         {Icall_last}
8399 };
8400
8401 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8402
8403 #undef ICALL_TYPE
8404 #define ICALL_TYPE(id,name,first)
8405 #undef ICALL
8406
8407 #ifdef HAVE_ARRAY_ELEM_INIT
8408 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8409 #define MSGSTRFIELD1(line) str##line
8410
8411 static const struct msgstrtn_t {
8412 #define ICALL(id,name,func)
8413 #undef ICALL_TYPE
8414 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8415 #include "metadata/icall-def.h"
8416 #undef ICALL_TYPE
8417 } icall_type_names_str = {
8418 #define ICALL_TYPE(id,name,first) (name),
8419 #include "metadata/icall-def.h"
8420 #undef ICALL_TYPE
8421 };
8422 static const guint16 icall_type_names_idx [] = {
8423 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8424 #include "metadata/icall-def.h"
8425 #undef ICALL_TYPE
8426 };
8427 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8428
8429 static const struct msgstr_t {
8430 #undef ICALL
8431 #define ICALL_TYPE(id,name,first)
8432 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8433 #include "metadata/icall-def.h"
8434 #undef ICALL
8435 } icall_names_str = {
8436 #define ICALL(id,name,func) (name),
8437 #include "metadata/icall-def.h"
8438 #undef ICALL
8439 };
8440 static const guint16 icall_names_idx [] = {
8441 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8442 #include "metadata/icall-def.h"
8443 #undef ICALL
8444 };
8445 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8446
8447 #else
8448
8449 #undef ICALL_TYPE
8450 #undef ICALL
8451 #define ICALL_TYPE(id,name,first) name,
8452 #define ICALL(id,name,func)
8453 static const char* const
8454 icall_type_names [] = {
8455 #include "metadata/icall-def.h"
8456         NULL
8457 };
8458
8459 #define icall_type_name_get(id) (icall_type_names [(id)])
8460
8461 #undef ICALL_TYPE
8462 #undef ICALL
8463 #define ICALL_TYPE(id,name,first)
8464 #define ICALL(id,name,func) name,
8465 static const char* const
8466 icall_names [] = {
8467 #include "metadata/icall-def.h"
8468         NULL
8469 };
8470 #define icall_name_get(id) icall_names [(id)]
8471
8472 #endif /* !HAVE_ARRAY_ELEM_INIT */
8473
8474 #undef ICALL_TYPE
8475 #undef ICALL
8476 #define ICALL_TYPE(id,name,first)
8477 #define ICALL(id,name,func) func,
8478 static const gconstpointer
8479 icall_functions [] = {
8480 #include "metadata/icall-def.h"
8481         NULL
8482 };
8483
8484 #ifdef ENABLE_ICALL_SYMBOL_MAP
8485 #undef ICALL_TYPE
8486 #undef ICALL
8487 #define ICALL_TYPE(id,name,first)
8488 #define ICALL(id,name,func) #func,
8489 static const gconstpointer
8490 icall_symbols [] = {
8491 #include "metadata/icall-def.h"
8492         NULL
8493 };
8494 #endif
8495
8496 #endif /* DISABLE_ICALL_TABLES */
8497
8498 static mono_mutex_t icall_mutex;
8499 static GHashTable *icall_hash = NULL;
8500 static GHashTable *jit_icall_hash_name = NULL;
8501 static GHashTable *jit_icall_hash_addr = NULL;
8502
8503 void
8504 mono_icall_init (void)
8505 {
8506 #ifndef DISABLE_ICALL_TABLES
8507         int i = 0;
8508
8509         /* check that tables are sorted: disable in release */
8510         if (TRUE) {
8511                 int j;
8512                 const char *prev_class = NULL;
8513                 const char *prev_method;
8514                 
8515                 for (i = 0; i < Icall_type_num; ++i) {
8516                         const IcallTypeDesc *desc;
8517                         int num_icalls;
8518                         prev_method = NULL;
8519                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8520                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8521                         prev_class = icall_type_name_get (i);
8522                         desc = &icall_type_descs [i];
8523                         num_icalls = icall_desc_num_icalls (desc);
8524                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8525                         for (j = 0; j < num_icalls; ++j) {
8526                                 const char *methodn = icall_name_get (desc->first_icall + j);
8527                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
8528                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
8529                                 prev_method = methodn;
8530                         }
8531                 }
8532         }
8533 #endif
8534
8535         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8536         mono_os_mutex_init (&icall_mutex);
8537 }
8538
8539 static void
8540 mono_icall_lock (void)
8541 {
8542         mono_locks_os_acquire (&icall_mutex, IcallLock);
8543 }
8544
8545 static void
8546 mono_icall_unlock (void)
8547 {
8548         mono_locks_os_release (&icall_mutex, IcallLock);
8549 }
8550
8551 void
8552 mono_icall_cleanup (void)
8553 {
8554         g_hash_table_destroy (icall_hash);
8555         g_hash_table_destroy (jit_icall_hash_name);
8556         g_hash_table_destroy (jit_icall_hash_addr);
8557         mono_os_mutex_destroy (&icall_mutex);
8558 }
8559
8560 /**
8561  * mono_add_internal_call:
8562  * @name: method specification to surface to the managed world
8563  * @method: pointer to a C method to invoke when the method is called
8564  *
8565  * This method surfaces the C function pointed by @method as a method
8566  * that has been surfaced in managed code with the method specified in
8567  * @name as an internal call.
8568  *
8569  * Internal calls are surfaced to all app domains loaded and they are
8570  * accessibly by a type with the specified name.
8571  *
8572  * You must provide a fully qualified type name, that is namespaces
8573  * and type name, followed by a colon and the method name, with an
8574  * optional signature to bind.
8575  *
8576  * For example, the following are all valid declarations:
8577  *
8578  * "MyApp.Services.ScriptService:Accelerate"
8579  * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8580  *
8581  * You use method parameters in cases where there might be more than
8582  * one surface method to managed code.  That way you can register different
8583  * internal calls for different method overloads.
8584  *
8585  * The internal calls are invoked with no marshalling.   This means that .NET
8586  * types like System.String are exposed as `MonoString *` parameters.   This is
8587  * different than the way that strings are surfaced in P/Invoke.
8588  *
8589  * For more information on how the parameters are marshalled, see the
8590  * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8591  * page.
8592  *
8593  * See the <a  href="mono-api-methods.html#method-desc">Method Description</a>
8594  * reference for more information on the format of method descriptions.
8595  */
8596 void
8597 mono_add_internal_call (const char *name, gconstpointer method)
8598 {
8599         mono_icall_lock ();
8600
8601         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8602
8603         mono_icall_unlock ();
8604 }
8605
8606 #ifndef DISABLE_ICALL_TABLES
8607
8608 #ifdef HAVE_ARRAY_ELEM_INIT
8609 static int
8610 compare_method_imap (const void *key, const void *elem)
8611 {
8612         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8613         return strcmp (key, method_name);
8614 }
8615
8616 static gpointer
8617 find_method_icall (const IcallTypeDesc *imap, const char *name)
8618 {
8619         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);
8620         if (!nameslot)
8621                 return NULL;
8622         return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8623 }
8624
8625 static int
8626 compare_class_imap (const void *key, const void *elem)
8627 {
8628         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8629         return strcmp (key, class_name);
8630 }
8631
8632 static const IcallTypeDesc*
8633 find_class_icalls (const char *name)
8634 {
8635         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);
8636         if (!nameslot)
8637                 return NULL;
8638         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8639 }
8640
8641 #else /* HAVE_ARRAY_ELEM_INIT */
8642
8643 static int
8644 compare_method_imap (const void *key, const void *elem)
8645 {
8646         const char** method_name = (const char**)elem;
8647         return strcmp (key, *method_name);
8648 }
8649
8650 static gpointer
8651 find_method_icall (const IcallTypeDesc *imap, const char *name)
8652 {
8653         const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8654         if (!nameslot)
8655                 return NULL;
8656         return (gpointer)icall_functions [(nameslot - icall_names)];
8657 }
8658
8659 static int
8660 compare_class_imap (const void *key, const void *elem)
8661 {
8662         const char** class_name = (const char**)elem;
8663         return strcmp (key, *class_name);
8664 }
8665
8666 static const IcallTypeDesc*
8667 find_class_icalls (const char *name)
8668 {
8669         const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8670         if (!nameslot)
8671                 return NULL;
8672         return &icall_type_descs [nameslot - icall_type_names];
8673 }
8674
8675 #endif /* HAVE_ARRAY_ELEM_INIT */
8676
8677 #endif /* DISABLE_ICALL_TABLES */
8678
8679 /* 
8680  * we should probably export this as an helper (handle nested types).
8681  * Returns the number of chars written in buf.
8682  */
8683 static int
8684 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8685 {
8686         int nspacelen, cnamelen;
8687         nspacelen = strlen (klass->name_space);
8688         cnamelen = strlen (klass->name);
8689         if (nspacelen + cnamelen + 2 > bufsize)
8690                 return 0;
8691         if (nspacelen) {
8692                 memcpy (buf, klass->name_space, nspacelen);
8693                 buf [nspacelen ++] = '.';
8694         }
8695         memcpy (buf + nspacelen, klass->name, cnamelen);
8696         buf [nspacelen + cnamelen] = 0;
8697         return nspacelen + cnamelen;
8698 }
8699
8700 #ifdef DISABLE_ICALL_TABLES
8701 static void
8702 no_icall_table (void)
8703 {
8704         g_assert_not_reached ();
8705 }
8706 #endif
8707
8708 gpointer
8709 mono_lookup_internal_call (MonoMethod *method)
8710 {
8711         char *sigstart;
8712         char *tmpsig;
8713         char mname [2048];
8714         int typelen = 0, mlen, siglen;
8715         gpointer res;
8716 #ifndef DISABLE_ICALL_TABLES
8717         const IcallTypeDesc *imap = NULL;
8718 #endif
8719
8720         g_assert (method != NULL);
8721
8722         if (method->is_inflated)
8723                 method = ((MonoMethodInflated *) method)->declaring;
8724
8725         if (method->klass->nested_in) {
8726                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8727                 if (!pos)
8728                         return NULL;
8729
8730                 mname [pos++] = '/';
8731                 mname [pos] = 0;
8732
8733                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8734                 if (!typelen)
8735                         return NULL;
8736
8737                 typelen += pos;
8738         } else {
8739                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8740                 if (!typelen)
8741                         return NULL;
8742         }
8743
8744 #ifndef DISABLE_ICALL_TABLES
8745         imap = find_class_icalls (mname);
8746 #endif
8747
8748         mname [typelen] = ':';
8749         mname [typelen + 1] = ':';
8750
8751         mlen = strlen (method->name);
8752         memcpy (mname + typelen + 2, method->name, mlen);
8753         sigstart = mname + typelen + 2 + mlen;
8754         *sigstart = 0;
8755
8756         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8757         siglen = strlen (tmpsig);
8758         if (typelen + mlen + siglen + 6 > sizeof (mname))
8759                 return NULL;
8760         sigstart [0] = '(';
8761         memcpy (sigstart + 1, tmpsig, siglen);
8762         sigstart [siglen + 1] = ')';
8763         sigstart [siglen + 2] = 0;
8764         g_free (tmpsig);
8765         
8766         mono_icall_lock ();
8767
8768         res = g_hash_table_lookup (icall_hash, mname);
8769         if (res) {
8770                 mono_icall_unlock ();;
8771                 return res;
8772         }
8773         /* try without signature */
8774         *sigstart = 0;
8775         res = g_hash_table_lookup (icall_hash, mname);
8776         if (res) {
8777                 mono_icall_unlock ();
8778                 return res;
8779         }
8780
8781 #ifdef DISABLE_ICALL_TABLES
8782         mono_icall_unlock ();
8783         /* Fail only when the result is actually used */
8784         /* mono_marshal_get_native_wrapper () depends on this */
8785         if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8786                 return ves_icall_System_String_ctor_RedirectToCreateString;
8787         else
8788                 return no_icall_table;
8789 #else
8790         /* it wasn't found in the static call tables */
8791         if (!imap) {
8792                 mono_icall_unlock ();
8793                 return NULL;
8794         }
8795         res = find_method_icall (imap, sigstart - mlen);
8796         if (res) {
8797                 mono_icall_unlock ();
8798                 return res;
8799         }
8800         /* try _with_ signature */
8801         *sigstart = '(';
8802         res = find_method_icall (imap, sigstart - mlen);
8803         if (res) {
8804                 mono_icall_unlock ();
8805                 return res;
8806         }
8807
8808         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8809         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8810         g_print ("The out of sync library is: %s\n", method->klass->image->name);
8811         g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8812         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");
8813         g_print ("If you see other errors or faults after this message they are probably related\n");
8814         g_print ("and you need to fix your mono install first.\n");
8815
8816         mono_icall_unlock ();
8817
8818         return NULL;
8819 #endif
8820 }
8821
8822 #ifdef ENABLE_ICALL_SYMBOL_MAP
8823 static int
8824 func_cmp (gconstpointer key, gconstpointer p)
8825 {
8826         return (gsize)key - (gsize)*(gsize*)p;
8827 }
8828 #endif
8829
8830 /*
8831  * mono_lookup_icall_symbol:
8832  *
8833  *   Given the icall METHOD, returns its C symbol.
8834  */
8835 const char*
8836 mono_lookup_icall_symbol (MonoMethod *m)
8837 {
8838 #ifdef DISABLE_ICALL_TABLES
8839         g_assert_not_reached ();
8840         return NULL;
8841 #else
8842 #ifdef ENABLE_ICALL_SYMBOL_MAP
8843         gpointer func;
8844         int i;
8845         gpointer slot;
8846         static gconstpointer *functions_sorted;
8847         static const char**symbols_sorted;
8848         static gboolean inited;
8849
8850         if (!inited) {
8851                 gboolean changed;
8852
8853                 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8854                 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8855                 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8856                 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8857                 /* Bubble sort the two arrays */
8858                 changed = TRUE;
8859                 while (changed) {
8860                         changed = FALSE;
8861                         for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8862                                 if (functions_sorted [i] > functions_sorted [i + 1]) {
8863                                         gconstpointer tmp;
8864
8865                                         tmp = functions_sorted [i];
8866                                         functions_sorted [i] = functions_sorted [i + 1];
8867                                         functions_sorted [i + 1] = tmp;
8868                                         tmp = symbols_sorted [i];
8869                                         symbols_sorted [i] = symbols_sorted [i + 1];
8870                                         symbols_sorted [i + 1] = tmp;
8871                                         changed = TRUE;
8872                                 }
8873                         }
8874                 }
8875         }
8876
8877         func = mono_lookup_internal_call (m);
8878         if (!func)
8879                 return NULL;
8880         slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8881         if (!slot)
8882                 return NULL;
8883         g_assert (slot);
8884         return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8885 #else
8886         fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8887         g_assert_not_reached ();
8888         return 0;
8889 #endif
8890 #endif
8891 }
8892
8893 static MonoType*
8894 type_from_typename (char *type_name)
8895 {
8896         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
8897
8898         if (!strcmp (type_name, "int"))
8899                 klass = mono_defaults.int_class;
8900         else if (!strcmp (type_name, "ptr"))
8901                 klass = mono_defaults.int_class;
8902         else if (!strcmp (type_name, "void"))
8903                 klass = mono_defaults.void_class;
8904         else if (!strcmp (type_name, "int32"))
8905                 klass = mono_defaults.int32_class;
8906         else if (!strcmp (type_name, "uint32"))
8907                 klass = mono_defaults.uint32_class;
8908         else if (!strcmp (type_name, "int8"))
8909                 klass = mono_defaults.sbyte_class;
8910         else if (!strcmp (type_name, "uint8"))
8911                 klass = mono_defaults.byte_class;
8912         else if (!strcmp (type_name, "int16"))
8913                 klass = mono_defaults.int16_class;
8914         else if (!strcmp (type_name, "uint16"))
8915                 klass = mono_defaults.uint16_class;
8916         else if (!strcmp (type_name, "long"))
8917                 klass = mono_defaults.int64_class;
8918         else if (!strcmp (type_name, "ulong"))
8919                 klass = mono_defaults.uint64_class;
8920         else if (!strcmp (type_name, "float"))
8921                 klass = mono_defaults.single_class;
8922         else if (!strcmp (type_name, "double"))
8923                 klass = mono_defaults.double_class;
8924         else if (!strcmp (type_name, "object"))
8925                 klass = mono_defaults.object_class;
8926         else if (!strcmp (type_name, "obj"))
8927                 klass = mono_defaults.object_class;
8928         else if (!strcmp (type_name, "string"))
8929                 klass = mono_defaults.string_class;
8930         else if (!strcmp (type_name, "bool"))
8931                 klass = mono_defaults.boolean_class;
8932         else if (!strcmp (type_name, "boolean"))
8933                 klass = mono_defaults.boolean_class;
8934         else {
8935                 g_error ("%s", type_name);
8936                 g_assert_not_reached ();
8937         }
8938         return &klass->byval_arg;
8939 }
8940
8941 /**
8942  * LOCKING: Take the corlib image lock.
8943  */
8944 MonoMethodSignature*
8945 mono_create_icall_signature (const char *sigstr)
8946 {
8947         gchar **parts;
8948         int i, len;
8949         gchar **tmp;
8950         MonoMethodSignature *res, *res2;
8951         MonoImage *corlib = mono_defaults.corlib;
8952
8953         mono_image_lock (corlib);
8954         res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8955         mono_image_unlock (corlib);
8956
8957         if (res)
8958                 return res;
8959
8960         parts = g_strsplit (sigstr, " ", 256);
8961
8962         tmp = parts;
8963         len = 0;
8964         while (*tmp) {
8965                 len ++;
8966                 tmp ++;
8967         }
8968
8969         res = mono_metadata_signature_alloc (corlib, len - 1);
8970         res->pinvoke = 1;
8971
8972 #ifdef HOST_WIN32
8973         /* 
8974          * Under windows, the default pinvoke calling convention is STDCALL but
8975          * we need CDECL.
8976          */
8977         res->call_convention = MONO_CALL_C;
8978 #endif
8979
8980         res->ret = type_from_typename (parts [0]);
8981         for (i = 1; i < len; ++i) {
8982                 res->params [i - 1] = type_from_typename (parts [i]);
8983         }
8984
8985         g_strfreev (parts);
8986
8987         mono_image_lock (corlib);
8988         res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8989         if (res2)
8990                 res = res2; /*Value is allocated in the image pool*/
8991         else
8992                 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8993         mono_image_unlock (corlib);
8994
8995         return res;
8996 }
8997
8998 MonoJitICallInfo *
8999 mono_find_jit_icall_by_name (const char *name)
9000 {
9001         MonoJitICallInfo *info;
9002         g_assert (jit_icall_hash_name);
9003
9004         mono_icall_lock ();
9005         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9006         mono_icall_unlock ();
9007         return info;
9008 }
9009
9010 MonoJitICallInfo *
9011 mono_find_jit_icall_by_addr (gconstpointer addr)
9012 {
9013         MonoJitICallInfo *info;
9014         g_assert (jit_icall_hash_addr);
9015
9016         mono_icall_lock ();
9017         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
9018         mono_icall_unlock ();
9019
9020         return info;
9021 }
9022
9023 /*
9024  * mono_get_jit_icall_info:
9025  *
9026  *   Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
9027  * caller should access it while holding the icall lock.
9028  */
9029 GHashTable*
9030 mono_get_jit_icall_info (void)
9031 {
9032         return jit_icall_hash_name;
9033 }
9034
9035 /*
9036  * mono_lookup_jit_icall_symbol:
9037  *
9038  *   Given the jit icall NAME, returns its C symbol if possible, or NULL.
9039  */
9040 const char*
9041 mono_lookup_jit_icall_symbol (const char *name)
9042 {
9043         MonoJitICallInfo *info;
9044         const char *res = NULL;
9045
9046         mono_icall_lock ();
9047         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9048         if (info)
9049                 res = info->c_symbol;
9050         mono_icall_unlock ();
9051         return res;
9052 }
9053
9054 void
9055 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
9056 {
9057         mono_icall_lock ();
9058         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
9059         mono_icall_unlock ();
9060 }
9061
9062 /*
9063  * 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
9064  * icalls without wrappers in some cases.
9065  */
9066 MonoJitICallInfo *
9067 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
9068 {
9069         MonoJitICallInfo *info;
9070         
9071         g_assert (func);
9072         g_assert (name);
9073
9074         mono_icall_lock ();
9075
9076         if (!jit_icall_hash_name) {
9077                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
9078                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
9079         }
9080
9081         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
9082                 g_warning ("jit icall already defined \"%s\"\n", name);
9083                 g_assert_not_reached ();
9084         }
9085
9086         info = g_new0 (MonoJitICallInfo, 1);
9087         
9088         info->name = name;
9089         info->func = func;
9090         info->sig = sig;
9091         info->c_symbol = c_symbol;
9092         info->no_raise = no_raise;
9093
9094         if (is_save) {
9095                 info->wrapper = func;
9096         } else {
9097                 info->wrapper = NULL;
9098         }
9099
9100         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
9101         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
9102
9103         mono_icall_unlock ();
9104         return info;
9105 }
9106
9107 MonoJitICallInfo *
9108 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
9109 {
9110         return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);
9111 }
9112