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