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