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