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