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