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