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