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