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