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