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