Merge pull request #3773 from mono/bockbuild-integration
[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 < klass->field.count);
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         for (i = 0; i < method->klass->method.count; ++i) {
5111                 if (method->klass->methods [i] == method) {
5112                         offset = i;
5113                         break;
5114                 }       
5115         }
5116         mono_class_setup_methods (klass);
5117         if (mono_class_has_failure (klass))
5118                 return NULL;
5119         g_assert (offset >= 0 && offset < klass->method.count);
5120         return klass->methods [offset];
5121 }
5122
5123 ICALL_EXPORT MonoReflectionMethod*
5124 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check)
5125 {
5126         MonoReflectionMethod *res = NULL;
5127         MonoError error;
5128         MonoClass *klass;
5129         if (type && generic_check) {
5130                 klass = mono_class_from_mono_type (type);
5131                 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5132                         return NULL;
5133
5134                 if (method->klass != klass) {
5135                         method = mono_method_get_equivalent_method (method, klass);
5136                         if (!method)
5137                                 return NULL;
5138                 }
5139         } else if (type)
5140                 klass = mono_class_from_mono_type (type);
5141         else
5142                 klass = method->klass;
5143         res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5144         mono_error_set_pending_exception (&error);
5145         return res;
5146 }
5147
5148 ICALL_EXPORT MonoReflectionMethodBody*
5149 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5150 {
5151         MonoError error;
5152         MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5153         mono_error_set_pending_exception (&error);
5154         return result;
5155 }
5156
5157 ICALL_EXPORT MonoReflectionAssembly*
5158 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5159 {
5160         MonoError error;
5161         MonoReflectionAssembly *result;
5162         MonoMethod *dest = NULL;
5163
5164         mono_stack_walk_no_il (get_executing, &dest);
5165         g_assert (dest);
5166         result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5167         if (!result)
5168                 mono_error_set_pending_exception (&error);
5169         return result;
5170 }
5171
5172
5173 ICALL_EXPORT MonoReflectionAssembly*
5174 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5175 {
5176         MonoError error;
5177         MonoReflectionAssembly *result;
5178         MonoDomain* domain = mono_domain_get ();
5179
5180         if (!domain->entry_assembly)
5181                 return NULL;
5182
5183         result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5184         if (!result)
5185                 mono_error_set_pending_exception (&error);
5186         return result;
5187 }
5188
5189 ICALL_EXPORT MonoReflectionAssembly*
5190 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5191 {
5192         MonoError error;
5193         MonoMethod *m;
5194         MonoMethod *dest;
5195         MonoReflectionAssembly *result;
5196
5197         dest = NULL;
5198         mono_stack_walk_no_il (get_executing, &dest);
5199         m = dest;
5200         mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5201         if (!dest)
5202                 dest = m;
5203         if (!m) {
5204                 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5205                 return NULL;
5206         }
5207         result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5208         if (!result)
5209                 mono_error_set_pending_exception (&error);
5210         return result;
5211 }
5212
5213 ICALL_EXPORT MonoStringHandle
5214 ves_icall_System_RuntimeType_getFullName (MonoReflectionTypeHandle object, gboolean full_name,
5215                                                                                   gboolean assembly_qualified, MonoError *error)
5216 {
5217         MonoDomain *domain = mono_object_domain (MONO_HANDLE_RAW (object));
5218         MonoType *type = MONO_HANDLE_RAW (object)->type;
5219         MonoTypeNameFormat format;
5220         MonoStringHandle res;
5221         gchar *name;
5222
5223         if (full_name)
5224                 format = assembly_qualified ?
5225                         MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5226                         MONO_TYPE_NAME_FORMAT_FULL_NAME;
5227         else
5228                 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5229  
5230         name = mono_type_get_name_full (type, format);
5231         if (!name)
5232                 return NULL_HANDLE_STRING;
5233
5234         if (full_name && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
5235                 g_free (name);
5236                 return NULL_HANDLE_STRING;
5237         }
5238
5239         res = mono_string_new_handle (domain, name, error);
5240         g_free (name);
5241
5242         return res;
5243 }
5244
5245 ICALL_EXPORT int
5246 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5247 {
5248         MonoError error;
5249         MonoClass *klass = mono_class_from_mono_type (rfield->type);
5250
5251         mono_class_init_checked (klass, &error);
5252         mono_error_set_pending_exception (&error);
5253         return mono_security_core_clr_class_level (klass);
5254 }
5255
5256 ICALL_EXPORT int
5257 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5258 {
5259         MonoClassField *field = rfield->field;
5260         return mono_security_core_clr_field_level (field, TRUE);
5261 }
5262
5263 ICALL_EXPORT int
5264 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5265 {
5266         MonoMethod *method = rfield->method;
5267         return mono_security_core_clr_method_level (method, TRUE);
5268 }
5269
5270 static void
5271 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)
5272 {
5273         static MonoMethod *create_culture = NULL;
5274         MonoObject *obj;
5275         gpointer args [2];
5276         guint32 pkey_len;
5277         const char *pkey_ptr;
5278         gchar *codebase;
5279         MonoBoolean assembly_ref = 0;
5280
5281         mono_error_init (error);
5282
5283         MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5284         aname->major = name->major;
5285         aname->minor = name->minor;
5286         aname->build = name->build;
5287         aname->flags = name->flags;
5288         aname->revision = name->revision;
5289         aname->hashalg = name->hash_alg;
5290         aname->versioncompat = 1; /* SameMachine (default) */
5291         aname->processor_architecture = name->arch;
5292
5293         if (by_default_version) {
5294                 MonoObject *version;
5295
5296                 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5297                 return_if_nok (error);
5298
5299                 MONO_OBJECT_SETREF (aname, version, version);
5300         }
5301
5302         codebase = NULL;
5303         if (absolute != NULL && *absolute != '\0') {
5304                 gchar *result;
5305
5306                 codebase = g_strdup (absolute);
5307
5308                 mono_icall_make_platform_path (codebase);
5309
5310                 const gchar *prepend = mono_icall_get_file_path_prefix (codebase);
5311
5312                 result = g_strconcat (prepend, codebase, NULL);
5313                 g_free (codebase);
5314                 codebase = result;
5315         }
5316
5317         if (codebase) {
5318                 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5319                 g_free (codebase);
5320         }
5321
5322         if (!create_culture) {
5323                 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5324                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5325                 g_assert (create_culture);
5326                 mono_method_desc_free (desc);
5327         }
5328
5329         if (name->culture) {
5330                 args [0] = mono_string_new (domain, name->culture);
5331                 args [1] = &assembly_ref;
5332
5333                 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5334                 return_if_nok (error);
5335
5336                 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5337         }
5338
5339         if (name->public_key) {
5340                 pkey_ptr = (char*)name->public_key;
5341                 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5342
5343                 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5344                 return_if_nok (error);
5345                 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5346                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5347                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5348         } else if (default_publickey) {
5349                 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5350                 return_if_nok (error);
5351                 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5352                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5353         }
5354
5355         /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5356         if (name->public_key_token [0]) {
5357                 int i, j;
5358                 char *p;
5359
5360                 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5361                 return_if_nok (error);
5362                 
5363                 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5364                 p = mono_array_addr (keyToken, char, 0);
5365
5366                 for (i = 0, j = 0; i < 8; i++) {
5367                         *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5368                         *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5369                         p++;
5370                 }
5371         } else if (default_token) {
5372                 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5373                 return_if_nok (error);
5374                 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5375         }
5376 }
5377
5378 ICALL_EXPORT MonoString *
5379 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5380 {
5381         MonoDomain *domain = mono_object_domain (assembly); 
5382         MonoAssembly *mass = assembly->assembly;
5383         MonoString *res;
5384         gchar *name;
5385
5386         name = mono_stringify_assembly_name (&mass->aname);
5387         res = mono_string_new (domain, name);
5388         g_free (name);
5389
5390         return res;
5391 }
5392
5393 ICALL_EXPORT MonoAssemblyName *
5394 ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
5395 {
5396         return &mass->aname;
5397 }
5398
5399 ICALL_EXPORT void
5400 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5401 {
5402         MonoError error;
5403         char *filename;
5404         MonoImageOpenStatus status = MONO_IMAGE_OK;
5405         gboolean res;
5406         MonoImage *image;
5407         MonoAssemblyName name;
5408         char *dirname;
5409
5410         filename = mono_string_to_utf8_checked (fname, &error);
5411         if (mono_error_set_pending_exception (&error))
5412                 return;
5413
5414         dirname = g_path_get_dirname (filename);
5415         replace_shadow_path (mono_domain_get (), dirname, &filename);
5416         g_free (dirname);
5417
5418         image = mono_image_open (filename, &status);
5419
5420         if (!image){
5421                 MonoException *exc;
5422
5423                 g_free (filename);
5424                 if (status == MONO_IMAGE_IMAGE_INVALID)
5425                         exc = mono_get_exception_bad_image_format2 (NULL, fname);
5426                 else
5427                         exc = mono_get_exception_file_not_found2 (NULL, fname);
5428                 mono_set_pending_exception (exc);
5429                 return;
5430         }
5431
5432         res = mono_assembly_fill_assembly_name (image, &name);
5433         if (!res) {
5434                 mono_image_close (image);
5435                 g_free (filename);
5436                 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5437                 return;
5438         }
5439
5440         fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5441         mono_error_set_pending_exception (&error);
5442
5443         mono_image_close (image);
5444         g_free (filename);
5445 }
5446
5447 ICALL_EXPORT MonoBoolean
5448 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5449         char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5450 {
5451         MonoBoolean result = FALSE;
5452         MonoDeclSecurityEntry entry;
5453
5454         /* SecurityAction.RequestMinimum */
5455         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5456                 *minimum = entry.blob;
5457                 *minLength = entry.size;
5458                 result = TRUE;
5459         }
5460         /* SecurityAction.RequestOptional */
5461         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5462                 *optional = entry.blob;
5463                 *optLength = entry.size;
5464                 result = TRUE;
5465         }
5466         /* SecurityAction.RequestRefuse */
5467         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5468                 *refused = entry.blob;
5469                 *refLength = entry.size;
5470                 result = TRUE;
5471         }
5472
5473         return result;  
5474 }
5475
5476 static gboolean
5477 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5478 {
5479         guint32 attrs, visibility;
5480         do {
5481                 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5482                 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5483                 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5484                         return FALSE;
5485
5486         } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5487
5488         return TRUE;
5489 }
5490
5491 static MonoArray*
5492 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5493 {
5494         MonoReflectionType *rt;
5495         MonoArray *res;
5496         MonoClass *klass;
5497         MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5498         int i, count;
5499
5500         mono_error_init (error);
5501
5502         /* we start the count from 1 because we skip the special type <Module> */
5503         if (exportedOnly) {
5504                 count = 0;
5505                 for (i = 1; i < tdef->rows; ++i) {
5506                         if (mono_module_type_is_visible (tdef, image, i + 1))
5507                                 count++;
5508                 }
5509         } else {
5510                 count = tdef->rows - 1;
5511         }
5512         res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5513         return_val_if_nok (error, NULL);
5514         *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5515         return_val_if_nok (error, NULL);
5516         count = 0;
5517         for (i = 1; i < tdef->rows; ++i) {
5518                 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5519                         klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5520                         
5521                         if (klass) {
5522                                 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5523                                 return_val_if_nok (error, NULL);
5524
5525                                 mono_array_setref (res, count, rt);
5526                         } else {
5527                                 MonoException *ex = mono_error_convert_to_exception (error);
5528                                 mono_array_setref (*exceptions, count, ex);
5529                         }
5530                         count++;
5531                 }
5532         }
5533         
5534         return res;
5535 }
5536
5537 ICALL_EXPORT MonoArray*
5538 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5539 {
5540         MonoError error;
5541         MonoArray *res = NULL;
5542         MonoArray *exceptions = NULL;
5543         MonoImage *image = NULL;
5544         MonoTableInfo *table = NULL;
5545         MonoDomain *domain;
5546         GList *list = NULL;
5547         int i, len, ex_count;
5548
5549         domain = mono_object_domain (assembly);
5550
5551         g_assert (!assembly_is_dynamic (assembly->assembly));
5552         image = assembly->assembly->image;
5553         table = &image->tables [MONO_TABLE_FILE];
5554         res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5555         if (mono_error_set_pending_exception (&error))
5556                 return NULL;
5557
5558         /* Append data from all modules in the assembly */
5559         for (i = 0; i < table->rows; ++i) {
5560                 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5561                         MonoImage *loaded_image = mono_assembly_load_module_checked (image->assembly, i + 1, &error);
5562                         if (mono_error_set_pending_exception (&error))
5563                                 return NULL;
5564                         if (loaded_image) {
5565                                 MonoArray *ex2;
5566                                 MonoArray *res2;
5567
5568                                 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5569                                 if (mono_error_set_pending_exception (&error))
5570                                         return NULL;
5571
5572
5573                                 /* Append the new types to the end of the array */
5574                                 if (mono_array_length (res2) > 0) {
5575                                         guint32 len1, len2;
5576                                         MonoArray *res3, *ex3;
5577
5578                                         len1 = mono_array_length (res);
5579                                         len2 = mono_array_length (res2);
5580
5581                                         res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5582                                         if (mono_error_set_pending_exception (&error))
5583                                                 return NULL;
5584                                         mono_array_memcpy_refs (res3, 0, res, 0, len1);
5585                                         mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5586                                         res = res3;
5587
5588                                         ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5589                                         if (mono_error_set_pending_exception (&error))
5590                                                 return NULL;
5591                                         mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5592                                         mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5593                                         exceptions = ex3;
5594                                 }
5595                         }
5596                 }
5597         }
5598
5599         /* the ReflectionTypeLoadException must have all the types (Types property), 
5600          * NULL replacing types which throws an exception. The LoaderException must
5601          * contain all exceptions for NULL items.
5602          */
5603
5604         len = mono_array_length (res);
5605
5606         ex_count = 0;
5607         for (i = 0; i < len; i++) {
5608                 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5609                 MonoClass *klass;
5610
5611                 if (t) {
5612                         klass = mono_type_get_class (t->type);
5613                         if ((klass != NULL) && mono_class_has_failure (klass)) {
5614                                 /* keep the class in the list */
5615                                 list = g_list_append (list, klass);
5616                                 /* and replace Type with NULL */
5617                                 mono_array_setref (res, i, NULL);
5618                         }
5619                 } else {
5620                         ex_count ++;
5621                 }
5622         }
5623
5624         if (list || ex_count) {
5625                 GList *tmp = NULL;
5626                 MonoException *exc = NULL;
5627                 MonoArray *exl = NULL;
5628                 int j, length = g_list_length (list) + ex_count;
5629
5630                 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5631                 if (mono_error_set_pending_exception (&error)) {
5632                         g_list_free (list);
5633                         return NULL;
5634                 }
5635                 /* Types for which mono_class_get_checked () succeeded */
5636                 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5637                         MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5638                         mono_array_setref (exl, i, exc);
5639                 }
5640                 /* Types for which it don't */
5641                 for (j = 0; j < mono_array_length (exceptions); ++j) {
5642                         MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5643                         if (exc) {
5644                                 g_assert (i < length);
5645                                 mono_array_setref (exl, i, exc);
5646                                 i ++;
5647                         }
5648                 }
5649                 g_list_free (list);
5650                 list = NULL;
5651
5652                 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5653                 if (!is_ok (&error)) {
5654                         mono_error_set_pending_exception (&error);
5655                         return NULL;
5656                 }
5657                 mono_set_pending_exception (exc);
5658                 return NULL;
5659         }
5660                 
5661         return res;
5662 }
5663
5664 ICALL_EXPORT void
5665 ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname)
5666 {
5667         mono_assembly_name_free (aname);
5668 }
5669
5670 ICALL_EXPORT gboolean
5671 ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined)
5672 {
5673         *is_version_definited = *is_token_defined = FALSE;
5674
5675         return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined);
5676 }
5677
5678 ICALL_EXPORT MonoReflectionType*
5679 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5680 {
5681         MonoError error;
5682         MonoReflectionType *ret;
5683         MonoDomain *domain = mono_object_domain (module); 
5684         MonoClass *klass;
5685
5686         g_assert (module->image);
5687
5688         if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5689                 /* These images do not have a global type */
5690                 return NULL;
5691
5692         klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5693         if (!mono_error_ok (&error)) {
5694                 mono_error_set_pending_exception (&error);
5695                 return NULL;
5696         }
5697
5698         ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5699         if (!mono_error_ok (&error)) {
5700                 mono_error_set_pending_exception (&error);
5701                 return NULL;
5702         }
5703
5704         return ret;
5705 }
5706
5707 ICALL_EXPORT void
5708 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5709 {
5710         /*if (module->image)
5711                 mono_image_close (module->image);*/
5712 }
5713
5714 ICALL_EXPORT MonoStringHandle
5715 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModuleHandle refmodule, MonoError *error)
5716 {
5717         MonoDomain *domain = MONO_HANDLE_DOMAIN (refmodule);
5718         MonoImage *image = MONO_HANDLE_RAW (refmodule)->image;
5719
5720         g_assert (image);
5721         return mono_string_new_handle (domain, image->guid, error);
5722 }
5723
5724 #ifndef HOST_WIN32
5725 static inline gpointer
5726 mono_icall_module_get_hinstance (MonoReflectionModule *module)
5727 {
5728         return (gpointer) (-1);
5729 }
5730 #endif /* HOST_WIN32 */
5731
5732 ICALL_EXPORT gpointer
5733 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5734 {
5735         return mono_icall_module_get_hinstance (module);
5736 }
5737
5738 ICALL_EXPORT void
5739 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5740 {
5741         if (image_is_dynamic (image)) {
5742                 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5743                 *pe_kind = dyn->pe_kind;
5744                 *machine = dyn->machine;
5745         }
5746         else {
5747                 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5748                 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5749         }
5750 }
5751
5752 ICALL_EXPORT gint32
5753 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5754 {
5755         return (image->md_version_major << 16) | (image->md_version_minor);
5756 }
5757
5758 ICALL_EXPORT MonoArray*
5759 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5760 {
5761         MonoError error;
5762         MonoArray *exceptions;
5763         int i;
5764
5765         if (!module->image) {
5766                 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
5767                 mono_error_set_pending_exception (&error);
5768                 return arr;
5769         } else {
5770                 MonoArray *res;
5771
5772                 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5773                 if (mono_error_set_pending_exception (&error))
5774                         return NULL;
5775
5776                 for (i = 0; i < mono_array_length (exceptions); ++i) {
5777                         MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5778                         if (ex) {
5779                                 mono_set_pending_exception (ex);
5780                                 return NULL;
5781                         }
5782                 }
5783                 return res;
5784         }
5785 }
5786
5787 static gboolean
5788 mono_memberref_is_method (MonoImage *image, guint32 token)
5789 {
5790         if (!image_is_dynamic (image)) {
5791                 guint32 cols [MONO_MEMBERREF_SIZE];
5792                 const char *sig;
5793                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5794                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5795                 mono_metadata_decode_blob_size (sig, &sig);
5796                 return (*sig != 0x6);
5797         } else {
5798                 MonoError error;
5799                 MonoClass *handle_class;
5800
5801                 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5802                         mono_error_cleanup (&error); /* just probing, ignore error */
5803                         return FALSE;
5804                 }
5805
5806                 return mono_defaults.methodhandle_class == handle_class;
5807         }
5808 }
5809
5810 static void
5811 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5812 {
5813         if (type_args)
5814                 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5815                                                                       mono_array_addr (type_args, MonoType*, 0));
5816         else
5817                 context->class_inst = NULL;
5818         if (method_args)
5819                 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5820                                                                        mono_array_addr (method_args, MonoType*, 0));
5821         else
5822                 context->method_inst = NULL;
5823 }
5824
5825 ICALL_EXPORT MonoType*
5826 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5827 {
5828         MonoClass *klass;
5829         int table = mono_metadata_token_table (token);
5830         int index = mono_metadata_token_index (token);
5831         MonoGenericContext context;
5832         MonoError error;
5833
5834         *resolve_error = ResolveTokenError_Other;
5835
5836         /* Validate token */
5837         if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) && 
5838                 (table != MONO_TABLE_TYPESPEC)) {
5839                 *resolve_error = ResolveTokenError_BadTable;
5840                 return NULL;
5841         }
5842
5843         if (image_is_dynamic (image)) {
5844                 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5845                         klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5846                         mono_error_cleanup (&error);
5847                         return klass ? &klass->byval_arg : NULL;
5848                 }
5849
5850                 init_generic_context_from_args (&context, type_args, method_args);
5851                 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5852                 mono_error_cleanup (&error);
5853                 return klass ? &klass->byval_arg : NULL;
5854         }
5855
5856         if ((index <= 0) || (index > image->tables [table].rows)) {
5857                 *resolve_error = ResolveTokenError_OutOfRange;
5858                 return NULL;
5859         }
5860
5861         init_generic_context_from_args (&context, type_args, method_args);
5862         klass = mono_class_get_checked (image, token, &error);
5863         if (klass)
5864                 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5865         if (!mono_error_ok (&error)) {
5866                 mono_error_set_pending_exception (&error);
5867                 return NULL;
5868         }
5869
5870         if (klass)
5871                 return &klass->byval_arg;
5872         else
5873                 return NULL;
5874 }
5875
5876 ICALL_EXPORT MonoMethod*
5877 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5878 {
5879         MonoError error;
5880         int table = mono_metadata_token_table (token);
5881         int index = mono_metadata_token_index (token);
5882         MonoGenericContext context;
5883         MonoMethod *method;
5884
5885         *resolve_error = ResolveTokenError_Other;
5886
5887         /* Validate token */
5888         if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) && 
5889                 (table != MONO_TABLE_MEMBERREF)) {
5890                 *resolve_error = ResolveTokenError_BadTable;
5891                 return NULL;
5892         }
5893
5894         if (image_is_dynamic (image)) {
5895                 if (table == MONO_TABLE_METHOD) {
5896                         method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5897                         mono_error_cleanup (&error);
5898                         return method;
5899                 }
5900
5901                 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5902                         *resolve_error = ResolveTokenError_BadTable;
5903                         return NULL;
5904                 }
5905
5906                 init_generic_context_from_args (&context, type_args, method_args);
5907                 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5908                 mono_error_cleanup (&error);
5909                 return method;
5910         }
5911
5912         if ((index <= 0) || (index > image->tables [table].rows)) {
5913                 *resolve_error = ResolveTokenError_OutOfRange;
5914                 return NULL;
5915         }
5916         if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5917                 *resolve_error = ResolveTokenError_BadTable;
5918                 return NULL;
5919         }
5920
5921         init_generic_context_from_args (&context, type_args, method_args);
5922         method = mono_get_method_checked (image, token, NULL, &context, &error);
5923         mono_error_set_pending_exception (&error);
5924
5925         return method;
5926 }
5927
5928 ICALL_EXPORT MonoString*
5929 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5930 {
5931         MonoError error;
5932         int index = mono_metadata_token_index (token);
5933
5934         *resolve_error = ResolveTokenError_Other;
5935
5936         /* Validate token */
5937         if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5938                 *resolve_error = ResolveTokenError_BadTable;
5939                 return NULL;
5940         }
5941
5942         if (image_is_dynamic (image)) {
5943                 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5944                 mono_error_cleanup (&error);
5945                 return result;
5946         }
5947
5948         if ((index <= 0) || (index >= image->heap_us.size)) {
5949                 *resolve_error = ResolveTokenError_OutOfRange;
5950                 return NULL;
5951         }
5952
5953         /* FIXME: What to do if the index points into the middle of a string ? */
5954
5955         MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
5956         mono_error_set_pending_exception (&error);
5957         return result;
5958 }
5959
5960 ICALL_EXPORT MonoClassField*
5961 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5962 {
5963         MonoError error;
5964         MonoClass *klass;
5965         int table = mono_metadata_token_table (token);
5966         int index = mono_metadata_token_index (token);
5967         MonoGenericContext context;
5968         MonoClassField *field;
5969
5970         *resolve_error = ResolveTokenError_Other;
5971
5972         /* Validate token */
5973         if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5974                 *resolve_error = ResolveTokenError_BadTable;
5975                 return NULL;
5976         }
5977
5978         if (image_is_dynamic (image)) {
5979                 if (table == MONO_TABLE_FIELD) {
5980                         field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5981                         mono_error_cleanup (&error);
5982                         return field;
5983                 }
5984
5985                 if (mono_memberref_is_method (image, token)) {
5986                         *resolve_error = ResolveTokenError_BadTable;
5987                         return NULL;
5988                 }
5989
5990                 init_generic_context_from_args (&context, type_args, method_args);
5991                 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5992                 mono_error_cleanup (&error);
5993                 return field;
5994         }
5995
5996         if ((index <= 0) || (index > image->tables [table].rows)) {
5997                 *resolve_error = ResolveTokenError_OutOfRange;
5998                 return NULL;
5999         }
6000         if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6001                 *resolve_error = ResolveTokenError_BadTable;
6002                 return NULL;
6003         }
6004
6005         init_generic_context_from_args (&context, type_args, method_args);
6006         field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6007         mono_error_set_pending_exception (&error);
6008         
6009         return field;
6010 }
6011
6012
6013 ICALL_EXPORT MonoObject*
6014 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6015 {
6016         MonoError merror;
6017         MonoObject *ret;
6018         int table = mono_metadata_token_table (token);
6019
6020         *error = ResolveTokenError_Other;
6021
6022         switch (table) {
6023         case MONO_TABLE_TYPEDEF:
6024         case MONO_TABLE_TYPEREF:
6025         case MONO_TABLE_TYPESPEC: {
6026                 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6027                 if (t) {
6028                         ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6029                         mono_error_set_pending_exception (&merror);
6030
6031                         return ret;
6032                 }
6033                 else
6034                         return NULL;
6035         }
6036         case MONO_TABLE_METHOD:
6037         case MONO_TABLE_METHODSPEC: {
6038                 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6039                 if (m) {
6040                         ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6041                         mono_error_set_pending_exception (&merror);
6042
6043                         return ret;
6044                 } else
6045                         return NULL;
6046         }               
6047         case MONO_TABLE_FIELD: {
6048                 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6049                 if (f) {
6050                         ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6051                         mono_error_set_pending_exception (&merror);
6052                         return ret;
6053                 }
6054                 else
6055                         return NULL;
6056         }
6057         case MONO_TABLE_MEMBERREF:
6058                 if (mono_memberref_is_method (image, token)) {
6059                         MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6060                         if (m) {
6061                                 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6062                                 mono_error_set_pending_exception (&merror);
6063
6064                                 return ret;
6065                         } else
6066                                 return NULL;
6067                 }
6068                 else {
6069                         MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6070                         if (f) {
6071                                 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6072                                 mono_error_set_pending_exception (&merror);
6073                                 return ret;
6074                         }
6075                         else
6076                                 return NULL;
6077                 }
6078                 break;
6079
6080         default:
6081                 *error = ResolveTokenError_BadTable;
6082         }
6083
6084         return NULL;
6085 }
6086
6087 ICALL_EXPORT MonoArray*
6088 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6089 {
6090         MonoError error;
6091         int table = mono_metadata_token_table (token);
6092         int idx = mono_metadata_token_index (token);
6093         MonoTableInfo *tables = image->tables;
6094         guint32 sig, len;
6095         const char *ptr;
6096         MonoArray *res;
6097
6098         *resolve_error = ResolveTokenError_OutOfRange;
6099
6100         /* FIXME: Support other tables ? */
6101         if (table != MONO_TABLE_STANDALONESIG)
6102                 return NULL;
6103
6104         if (image_is_dynamic (image))
6105                 return NULL;
6106
6107         if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6108                 return NULL;
6109
6110         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6111
6112         ptr = mono_metadata_blob_heap (image, sig);
6113         len = mono_metadata_decode_blob_size (ptr, &ptr);
6114
6115         res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6116         if (mono_error_set_pending_exception (&error))
6117                 return NULL;
6118         memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6119         return res;
6120 }
6121
6122 ICALL_EXPORT MonoBoolean
6123 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6124 {
6125         MonoType *type;
6126         MonoBoolean res;
6127
6128         type = t->type;
6129         res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6130
6131         return res;
6132 }
6133
6134 static void
6135 check_for_invalid_type (MonoClass *klass, MonoError *error)
6136 {
6137         char *name;
6138
6139         mono_error_init (error);
6140
6141         if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6142                 return;
6143
6144         name = mono_type_get_full_name (klass);
6145         mono_error_set_type_load_name (error, name, g_strdup (""), "");
6146 }
6147 ICALL_EXPORT MonoReflectionType *
6148 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6149 {
6150         MonoError error;
6151         MonoReflectionType *ret;
6152         MonoClass *klass, *aklass;
6153
6154         klass = mono_class_from_mono_type (type->type);
6155         check_for_invalid_type (klass, &error);
6156         if (mono_error_set_pending_exception (&error))
6157                 return NULL;
6158
6159         if (rank == 0) //single dimentional array
6160                 aklass = mono_array_class_get (klass, 1);
6161         else
6162                 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6163
6164         ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6165         mono_error_set_pending_exception (&error);
6166
6167         return ret;
6168 }
6169
6170 ICALL_EXPORT MonoReflectionType *
6171 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6172 {
6173         MonoError error;
6174         MonoReflectionType *ret;
6175         MonoClass *klass;
6176
6177         klass = mono_class_from_mono_type (type->type);
6178         mono_class_init_checked (klass, &error);
6179         if (mono_error_set_pending_exception (&error))
6180                 return NULL;
6181
6182         check_for_invalid_type (klass, &error);
6183         if (mono_error_set_pending_exception (&error))
6184                 return NULL;
6185
6186         ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6187         mono_error_set_pending_exception (&error);
6188
6189         return ret;
6190 }
6191
6192 ICALL_EXPORT MonoReflectionType *
6193 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6194 {
6195         MonoError error;
6196         MonoReflectionType *ret;
6197         MonoClass *klass, *pklass;
6198
6199         klass = mono_class_from_mono_type (type->type);
6200         mono_class_init_checked (klass, &error);
6201         if (mono_error_set_pending_exception (&error))
6202                 return NULL;
6203         check_for_invalid_type (klass, &error);
6204         if (mono_error_set_pending_exception (&error))
6205                 return NULL;
6206
6207         pklass = mono_ptr_class_get (type->type);
6208
6209         ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6210         mono_error_set_pending_exception (&error);
6211
6212         return ret;
6213 }
6214
6215 ICALL_EXPORT MonoObject *
6216 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6217                                                    MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6218 {
6219         MonoError error;
6220         MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6221         MonoObject *delegate;
6222         gpointer func;
6223         MonoMethod *method = info->method;
6224         MonoMethodSignature *sig = mono_method_signature(method);
6225
6226         mono_class_init_checked (delegate_class, &error);
6227         if (mono_error_set_pending_exception (&error))
6228                 return NULL;
6229
6230         if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6231                 /* FIXME improve this exception message */
6232                 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6233                                                  __func__,
6234                                                  "delegate_class->parent == mono_defaults.multicastdelegate_class");
6235                 mono_error_set_pending_exception (&error);
6236                 return NULL;
6237         }
6238
6239         if (mono_security_core_clr_enabled ()) {
6240                 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6241                         if (throwOnBindFailure)
6242                                 mono_error_set_pending_exception (&error);
6243                         else
6244                                 mono_error_cleanup (&error);
6245                         return NULL;
6246                 }
6247         }
6248
6249         if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
6250                 if (!method->is_inflated) {
6251                         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"));
6252                         return NULL;
6253                 }
6254         }
6255
6256         delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6257         if (mono_error_set_pending_exception (&error))
6258                 return NULL;
6259
6260         if (method_is_dynamic (method)) {
6261                 /* Creating a trampoline would leak memory */
6262                 func = mono_compile_method_checked (method, &error);
6263                 if (mono_error_set_pending_exception (&error))
6264                         return NULL;
6265         } else {
6266                 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6267                         method = mono_object_get_virtual_method (target, method);
6268                 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6269                 if (mono_error_set_pending_exception (&error))
6270                         return NULL;
6271                 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6272         }
6273
6274         mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6275         if (mono_error_set_pending_exception (&error))
6276                 return NULL;
6277         return delegate;
6278 }
6279
6280 ICALL_EXPORT MonoMulticastDelegate *
6281 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6282 {
6283         MonoError error;
6284         MonoMulticastDelegate *ret;
6285
6286         g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6287
6288         ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6289         if (mono_error_set_pending_exception (&error))
6290                 return NULL;
6291
6292         ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6293
6294         return ret;
6295 }
6296
6297 ICALL_EXPORT MonoReflectionMethod*
6298 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6299 {
6300         MonoReflectionMethod *ret = NULL;
6301         MonoError error;
6302         ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6303         mono_error_set_pending_exception (&error);
6304         return ret;
6305 }
6306
6307 /* System.Buffer */
6308
6309 static inline gint32 
6310 mono_array_get_byte_length (MonoArray *array)
6311 {
6312         MonoClass *klass;
6313         int length;
6314         int i;
6315
6316         klass = array->obj.vtable->klass;
6317
6318         if (array->bounds == NULL)
6319                 length = array->max_length;
6320         else {
6321                 length = 1;
6322                 for (i = 0; i < klass->rank; ++ i)
6323                         length *= array->bounds [i].length;
6324         }
6325
6326         switch (klass->element_class->byval_arg.type) {
6327         case MONO_TYPE_I1:
6328         case MONO_TYPE_U1:
6329         case MONO_TYPE_BOOLEAN:
6330                 return length;
6331         case MONO_TYPE_I2:
6332         case MONO_TYPE_U2:
6333         case MONO_TYPE_CHAR:
6334                 return length << 1;
6335         case MONO_TYPE_I4:
6336         case MONO_TYPE_U4:
6337         case MONO_TYPE_R4:
6338                 return length << 2;
6339         case MONO_TYPE_I:
6340         case MONO_TYPE_U:
6341                 return length * sizeof (gpointer);
6342         case MONO_TYPE_I8:
6343         case MONO_TYPE_U8:
6344         case MONO_TYPE_R8:
6345                 return length << 3;
6346         default:
6347                 return -1;
6348         }
6349 }
6350
6351 ICALL_EXPORT gint32 
6352 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array) 
6353 {
6354         return mono_array_get_byte_length (array);
6355 }
6356
6357 ICALL_EXPORT gint8 
6358 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx) 
6359 {
6360         return mono_array_get (array, gint8, idx);
6361 }
6362
6363 ICALL_EXPORT void 
6364 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value) 
6365 {
6366         mono_array_set (array, gint8, idx, value);
6367 }
6368
6369 ICALL_EXPORT MonoBoolean
6370 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count) 
6371 {
6372         guint8 *src_buf, *dest_buf;
6373
6374         if (count < 0) {
6375                 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6376                 return FALSE;
6377         }
6378
6379         g_assert (count >= 0);
6380
6381         /* This is called directly from the class libraries without going through the managed wrapper */
6382         MONO_CHECK_ARG_NULL (src, FALSE);
6383         MONO_CHECK_ARG_NULL (dest, FALSE);
6384
6385         /* watch out for integer overflow */
6386         if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6387                 return FALSE;
6388
6389         src_buf = (guint8 *)src->vector + src_offset;
6390         dest_buf = (guint8 *)dest->vector + dest_offset;
6391
6392         if (src != dest)
6393                 memcpy (dest_buf, src_buf, count);
6394         else
6395                 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6396
6397         return TRUE;
6398 }
6399
6400 #ifndef DISABLE_REMOTING
6401 ICALL_EXPORT MonoObject *
6402 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6403 {
6404         MonoError error;
6405         MonoDomain *domain = mono_object_domain (this_obj); 
6406         MonoObject *res;
6407         MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6408         MonoTransparentProxy *tp;
6409         MonoType *type;
6410         MonoClass *klass;
6411
6412         res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6413         if (mono_error_set_pending_exception (&error))
6414                 return NULL;
6415
6416         tp = (MonoTransparentProxy*) res;
6417         
6418         MONO_OBJECT_SETREF (tp, rp, rp);
6419         type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6420         klass = mono_class_from_mono_type (type);
6421
6422         // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6423         mono_class_setup_vtable (klass);
6424         if (mono_class_has_failure (klass)) {
6425                 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6426                 return NULL;
6427         }
6428
6429         tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6430         if (mono_error_set_pending_exception (&error))
6431                 return NULL;
6432         tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6433         if (mono_error_set_pending_exception (&error))
6434                 return NULL;
6435
6436         res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6437         if (mono_error_set_pending_exception (&error))
6438                 return NULL;
6439         return res;
6440 }
6441
6442 ICALL_EXPORT MonoReflectionType *
6443 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6444 {
6445         MonoError error;
6446         MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6447         mono_error_set_pending_exception (&error);
6448
6449         return ret;
6450 }
6451 #endif
6452
6453 /* System.Environment */
6454
6455 MonoString*
6456 ves_icall_System_Environment_get_UserName (void)
6457 {
6458         /* using glib is more portable */
6459         return mono_string_new (mono_domain_get (), g_get_user_name ());
6460 }
6461
6462 #ifndef HOST_WIN32
6463 static MonoString *
6464 mono_icall_get_machine_name (void)
6465 {
6466 #if !defined(DISABLE_SOCKETS)
6467         MonoString *result;
6468         char *buf;
6469         int n;
6470 #if defined _SC_HOST_NAME_MAX
6471         n = sysconf (_SC_HOST_NAME_MAX);
6472         if (n == -1)
6473 #endif
6474         n = 512;
6475         buf = g_malloc (n+1);
6476         
6477         if (gethostname (buf, n) == 0){
6478                 buf [n] = 0;
6479                 result = mono_string_new (mono_domain_get (), buf);
6480         } else
6481                 result = NULL;
6482         g_free (buf);
6483         
6484         return result;
6485 #else
6486         return mono_string_new (mono_domain_get (), "mono");
6487 #endif
6488 }
6489 #endif /* !HOST_WIN32 */
6490
6491 ICALL_EXPORT MonoString *
6492 ves_icall_System_Environment_get_MachineName (void)
6493 {
6494         return mono_icall_get_machine_name ();
6495 }
6496
6497 #ifndef HOST_WIN32
6498 static inline int
6499 mono_icall_get_platform (void)
6500 {
6501 #if defined(__MACH__)
6502         /* OSX */
6503         //
6504         // Notice that the value is hidden from user code, and only exposed
6505         // to mscorlib.   This is due to Mono's Unix/MacOS code predating the
6506         // define and making assumptions based on Unix/128/4 values before there
6507         // was a MacOS define.    Lots of code would assume that not-Unix meant
6508         // Windows, but in this case, it would be OSX. 
6509         //
6510         return 6;
6511 #else
6512         /* Unix */
6513         return 4;
6514 #endif
6515 }
6516 #endif /* !HOST_WIN32 */
6517
6518 ICALL_EXPORT int
6519 ves_icall_System_Environment_get_Platform (void)
6520 {
6521         return mono_icall_get_platform ();
6522 }
6523
6524 #ifndef HOST_WIN32
6525 static inline MonoString *
6526 mono_icall_get_new_line (void)
6527 {
6528         return mono_string_new (mono_domain_get (), "\n");
6529 }
6530 #endif /* !HOST_WIN32 */
6531
6532 ICALL_EXPORT MonoString *
6533 ves_icall_System_Environment_get_NewLine (void)
6534 {
6535         return mono_icall_get_new_line ();
6536 }
6537
6538 #ifndef HOST_WIN32
6539 static inline MonoBoolean
6540 mono_icall_is_64bit_os (void)
6541 {
6542 #if SIZEOF_VOID_P == 8
6543         return TRUE;
6544 #else
6545 #if defined(HAVE_SYS_UTSNAME_H)
6546         struct utsname name;
6547
6548         if (uname (&name) >= 0) {
6549                 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6550         }
6551 #endif
6552         return FALSE;
6553 #endif
6554 }
6555 #endif /* !HOST_WIN32 */
6556
6557 ICALL_EXPORT MonoBoolean
6558 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6559 {
6560         return mono_icall_is_64bit_os ();
6561 }
6562
6563 ICALL_EXPORT MonoStringHandle
6564 ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
6565 {
6566         const gchar *value;
6567
6568         if (utf8_name == NULL)
6569                 return NULL_HANDLE_STRING;
6570
6571         value = g_getenv (utf8_name);
6572
6573         if (value == 0)
6574                 return NULL_HANDLE_STRING;
6575         
6576         return mono_string_new_handle (mono_domain_get (), value, error);
6577 }
6578
6579 /*
6580  * There is no standard way to get at environ.
6581  */
6582 #ifndef _MSC_VER
6583 #ifndef __MINGW32_VERSION
6584 #if defined(__APPLE__)
6585 #if defined (TARGET_OSX)
6586 /* Apple defines this in crt_externs.h but doesn't provide that header for 
6587  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
6588  * in fact exist on all implementations (so far) 
6589  */
6590 gchar ***_NSGetEnviron(void);
6591 #define environ (*_NSGetEnviron())
6592 #else
6593 static char *mono_environ[1] = { NULL };
6594 #define environ mono_environ
6595 #endif /* defined (TARGET_OSX) */
6596 #else
6597 extern
6598 char **environ;
6599 #endif
6600 #endif
6601 #endif
6602
6603 ICALL_EXPORT MonoArray *
6604 ves_icall_System_Environment_GetCoomandLineArgs (void)
6605 {
6606         MonoError error;
6607         MonoArray *result = mono_runtime_get_main_args_checked (&error);
6608         mono_error_set_pending_exception (&error);
6609         return result;
6610 }
6611
6612 #ifndef HOST_WIN32
6613 static MonoArray *
6614 mono_icall_get_environment_variable_names (void)
6615 {
6616         MonoError error;
6617         MonoArray *names;
6618         MonoDomain *domain;
6619         MonoString *str;
6620         gchar **e, **parts;
6621         int n;
6622
6623         n = 0;
6624         for (e = environ; *e != 0; ++ e)
6625                 ++ n;
6626
6627         domain = mono_domain_get ();
6628         names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6629         if (mono_error_set_pending_exception (&error))
6630                 return NULL;
6631
6632         n = 0;
6633         for (e = environ; *e != 0; ++ e) {
6634                 parts = g_strsplit (*e, "=", 2);
6635                 if (*parts != 0) {
6636                         str = mono_string_new (domain, *parts);
6637                         mono_array_setref (names, n, str);
6638                 }
6639
6640                 g_strfreev (parts);
6641
6642                 ++ n;
6643         }
6644
6645         return names;
6646 }
6647 #endif /* !HOST_WIN32 */
6648
6649 ICALL_EXPORT MonoArray *
6650 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6651 {
6652         return mono_icall_get_environment_variable_names ();
6653 }
6654
6655 #ifndef HOST_WIN32
6656 static void
6657 mono_icall_set_environment_variable (MonoString *name, MonoString *value)
6658 {
6659         gchar *utf8_name, *utf8_value;
6660         MonoError error;
6661
6662         utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6663         if (mono_error_set_pending_exception (&error))
6664                 return;
6665
6666         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6667                 g_unsetenv (utf8_name);
6668                 g_free (utf8_name);
6669                 return;
6670         }
6671
6672         utf8_value = mono_string_to_utf8_checked (value, &error);
6673         if (!mono_error_ok (&error)) {
6674                 g_free (utf8_name);
6675                 mono_error_set_pending_exception (&error);
6676                 return;
6677         }
6678         g_setenv (utf8_name, utf8_value, TRUE);
6679
6680         g_free (utf8_name);
6681         g_free (utf8_value);
6682 }
6683 #endif /* !HOST_WIN32 */
6684
6685 ICALL_EXPORT void
6686 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6687 {
6688         mono_icall_set_environment_variable (name, value);
6689 }
6690
6691 ICALL_EXPORT void
6692 ves_icall_System_Environment_Exit (int result)
6693 {
6694         mono_environment_exitcode_set (result);
6695
6696 /* FIXME: There are some cleanup hangs that should be worked out, but
6697  * if the program is going to exit, everything will be cleaned up when
6698  * NaCl exits anyway.
6699  */
6700 #ifndef __native_client__
6701         if (!mono_runtime_try_shutdown ())
6702                 mono_thread_exit ();
6703
6704         /* Suspend all managed threads since the runtime is going away */
6705         mono_thread_suspend_all_other_threads ();
6706
6707         mono_runtime_quit ();
6708 #endif
6709
6710         /* we may need to do some cleanup here... */
6711         exit (result);
6712 }
6713
6714 ICALL_EXPORT MonoStringHandle
6715 ves_icall_System_Environment_GetGacPath (MonoError *error)
6716 {
6717         return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error);
6718 }
6719
6720 #ifndef HOST_WIN32
6721 static inline MonoString *
6722 mono_icall_get_windows_folder_path (int folder)
6723 {
6724         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6725         return mono_string_new (mono_domain_get (), "");
6726 }
6727 #endif /* !HOST_WIN32 */
6728
6729 ICALL_EXPORT MonoString*
6730 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6731 {
6732         return mono_icall_get_windows_folder_path (folder);
6733 }
6734
6735 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
6736 static MonoArray *
6737 mono_icall_get_logical_drives (void)
6738 {
6739         MonoError error;
6740         gunichar2 buf [256], *ptr, *dname;
6741         gunichar2 *u16;
6742         guint initial_size = 127, size = 128;
6743         gint ndrives;
6744         MonoArray *result;
6745         MonoString *drivestr;
6746         MonoDomain *domain = mono_domain_get ();
6747         gint len;
6748
6749         buf [0] = '\0';
6750         ptr = buf;
6751
6752         while (size > initial_size) {
6753                 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6754                 if (size > initial_size) {
6755                         if (ptr != buf)
6756                                 g_free (ptr);
6757                         ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6758                         initial_size = size;
6759                         size++;
6760                 }
6761         }
6762
6763         /* Count strings */
6764         dname = ptr;
6765         ndrives = 0;
6766         do {
6767                 while (*dname++);
6768                 ndrives++;
6769         } while (*dname);
6770
6771         dname = ptr;
6772         result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
6773         if (mono_error_set_pending_exception (&error))
6774                 goto leave;
6775
6776         ndrives = 0;
6777         do {
6778                 len = 0;
6779                 u16 = dname;
6780                 while (*u16) { u16++; len ++; }
6781                 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6782                 if (mono_error_set_pending_exception (&error))
6783                         goto leave;
6784
6785                 mono_array_setref (result, ndrives++, drivestr);
6786                 while (*dname++);
6787         } while (*dname);
6788
6789 leave:
6790         if (ptr != buf)
6791                 g_free (ptr);
6792
6793         return result;
6794 }
6795 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
6796
6797 ICALL_EXPORT MonoArray *
6798 ves_icall_System_Environment_GetLogicalDrives (void)
6799 {
6800         return mono_icall_get_logical_drives ();
6801 }
6802
6803 ICALL_EXPORT MonoString *
6804 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6805 {
6806         MonoError error;
6807         gunichar2 volume_name [MAX_PATH + 1];
6808         
6809         if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6810                 return NULL;
6811         MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
6812         mono_error_set_pending_exception (&error);
6813         return result;
6814 }
6815
6816 ICALL_EXPORT MonoStringHandle
6817 ves_icall_System_Environment_InternalGetHome (MonoError *error)
6818 {
6819         return mono_string_new_handle (mono_domain_get (), g_get_home_dir (), error);
6820 }
6821
6822 static const char *encodings [] = {
6823         (char *) 1,
6824                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6825                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6826                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6827         (char *) 2,
6828                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6829                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6830                 "x_unicode_2_0_utf_7",
6831         (char *) 3,
6832                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6833                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6834         (char *) 4,
6835                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6836                 "iso_10646_ucs2",
6837         (char *) 5,
6838                 "unicodefffe", "utf_16be",
6839         (char *) 6,
6840                 "iso_8859_1",
6841         (char *) 0
6842 };
6843
6844 /*
6845  * Returns the internal codepage, if the value of "int_code_page" is
6846  * 1 at entry, and we can not compute a suitable code page number,
6847  * returns the code page as a string
6848  */
6849 ICALL_EXPORT MonoString*
6850 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page) 
6851 {
6852         const char *cset;
6853         const char *p;
6854         char *c;
6855         char *codepage = NULL;
6856         int code;
6857         int want_name = *int_code_page;
6858         int i;
6859         
6860         *int_code_page = -1;
6861
6862         g_get_charset (&cset);
6863         c = codepage = g_strdup (cset);
6864         for (c = codepage; *c; c++){
6865                 if (isascii (*c) && isalpha (*c))
6866                         *c = tolower (*c);
6867                 if (*c == '-')
6868                         *c = '_';
6869         }
6870         /* g_print ("charset: %s\n", cset); */
6871         
6872         /* handle some common aliases */
6873         p = encodings [0];
6874         code = 0;
6875         for (i = 0; p != 0; ){
6876                 if ((gsize) p < 7){
6877                         code = (gssize) p;
6878                         p = encodings [++i];
6879                         continue;
6880                 }
6881                 if (strcmp (p, codepage) == 0){
6882                         *int_code_page = code;
6883                         break;
6884                 }
6885                 p = encodings [++i];
6886         }
6887         
6888         if (strstr (codepage, "utf_8") != NULL)
6889                 *int_code_page |= 0x10000000;
6890         g_free (codepage);
6891         
6892         if (want_name && *int_code_page == -1)
6893                 return mono_string_new (mono_domain_get (), cset);
6894         else
6895                 return NULL;
6896 }
6897
6898 ICALL_EXPORT MonoBoolean
6899 ves_icall_System_Environment_get_HasShutdownStarted (void)
6900 {
6901         if (mono_runtime_is_shutting_down ())
6902                 return TRUE;
6903
6904         if (mono_domain_is_unloading (mono_domain_get ()))
6905                 return TRUE;
6906
6907         return FALSE;
6908 }
6909
6910 #ifndef HOST_WIN32
6911 static inline void
6912 mono_icall_broadcast_setting_change (void)
6913 {
6914         return;
6915 }
6916 #endif /* !HOST_WIN32 */
6917
6918 ICALL_EXPORT void
6919 ves_icall_System_Environment_BroadcastSettingChange (void)
6920 {
6921         mono_icall_broadcast_setting_change ();
6922 }
6923
6924 ICALL_EXPORT
6925 gint32
6926 ves_icall_System_Environment_get_TickCount (void)
6927 {
6928         /* this will overflow after ~24 days */
6929         return (gint32) (mono_msec_boottime () & 0xffffffff);
6930 }
6931
6932 ICALL_EXPORT gint32
6933 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6934 {
6935         return 9;
6936 }
6937
6938 #ifndef DISABLE_REMOTING
6939 ICALL_EXPORT MonoBoolean
6940 ves_icall_IsTransparentProxy (MonoObject *proxy)
6941 {
6942         if (!proxy)
6943                 return 0;
6944
6945         if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6946                 return 1;
6947
6948         return 0;
6949 }
6950
6951 ICALL_EXPORT MonoReflectionMethod *
6952 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6953         MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6954 {
6955         MonoReflectionMethod *ret = NULL;
6956         MonoError error;
6957
6958         MonoClass *klass;
6959         MonoMethod *method;
6960         MonoMethod **vtable;
6961         MonoMethod *res = NULL;
6962
6963         MONO_CHECK_ARG_NULL (rtype, NULL);
6964         MONO_CHECK_ARG_NULL (rmethod, NULL);
6965
6966         method = rmethod->method;
6967         klass = mono_class_from_mono_type (rtype->type);
6968         mono_class_init_checked (klass, &error);
6969         if (mono_error_set_pending_exception (&error))
6970                 return NULL;
6971
6972         if (MONO_CLASS_IS_INTERFACE (klass))
6973                 return NULL;
6974
6975         if (method->flags & METHOD_ATTRIBUTE_STATIC)
6976                 return NULL;
6977
6978         if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6979                 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6980                         return rmethod;
6981                 else
6982                         return NULL;
6983         }
6984
6985         mono_class_setup_vtable (klass);
6986         vtable = klass->vtable;
6987
6988         if (mono_class_is_interface (method->klass)) {
6989                 gboolean variance_used = FALSE;
6990                 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6991                 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6992                 if (offs >= 0)
6993                         res = vtable [offs + method->slot];
6994         } else {
6995                 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6996                         return NULL;
6997
6998                 if (method->slot != -1)
6999                         res = vtable [method->slot];
7000         }
7001
7002         if (!res)
7003                 return NULL;
7004
7005         ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7006         mono_error_set_pending_exception (&error);
7007         return ret;
7008 }
7009
7010 ICALL_EXPORT void
7011 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7012 {
7013         MonoError error;
7014         MonoClass *klass;
7015         MonoVTable* vtable;
7016
7017         klass = mono_class_from_mono_type (type->type);
7018         vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7019         if (!is_ok (&error)) {
7020                 mono_error_set_pending_exception (&error);
7021                 return;
7022         }
7023
7024         mono_vtable_set_is_remote (vtable, enable);
7025 }
7026
7027 #else /* DISABLE_REMOTING */
7028
7029 ICALL_EXPORT void
7030 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7031 {
7032         g_assert_not_reached ();
7033 }
7034
7035 #endif
7036
7037 ICALL_EXPORT MonoObject *
7038 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7039 {
7040         MonoError error;
7041         MonoClass *klass;
7042         MonoDomain *domain;
7043         MonoObject *ret;
7044         
7045         domain = mono_object_domain (type);
7046         klass = mono_class_from_mono_type (type->type);
7047         mono_class_init_checked (klass, &error);
7048         if (mono_error_set_pending_exception (&error))
7049                 return NULL;
7050
7051         if (MONO_CLASS_IS_INTERFACE (klass) || mono_class_is_abstract (klass)) {
7052                 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7053                 return NULL;
7054         }
7055
7056         if (klass->rank >= 1) {
7057                 g_assert (klass->rank == 1);
7058                 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7059                 mono_error_set_pending_exception (&error);
7060                 return ret;
7061         } else {
7062                 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7063                 if (!is_ok (&error)) {
7064                         mono_error_set_pending_exception (&error);
7065                         return NULL;
7066                 }
7067                 /* Bypass remoting object creation check */
7068                 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7069                 mono_error_set_pending_exception (&error);
7070
7071                 return ret;
7072         }
7073 }
7074
7075 ICALL_EXPORT MonoStringHandle
7076 ves_icall_System_IO_get_temp_path (MonoError *error)
7077 {
7078         return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error);
7079 }
7080
7081 #ifndef PLATFORM_NO_DRIVEINFO
7082 ICALL_EXPORT MonoBoolean
7083 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7084                                                 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7085                                                 gint32 *error)
7086 {
7087         gboolean result;
7088         ULARGE_INTEGER wapi_free_bytes_avail;
7089         ULARGE_INTEGER wapi_total_number_of_bytes;
7090         ULARGE_INTEGER wapi_total_number_of_free_bytes;
7091
7092         *error = ERROR_SUCCESS;
7093         result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7094                                      &wapi_total_number_of_free_bytes);
7095
7096         if (result) {
7097                 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7098                 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7099                 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7100         } else {
7101                 *free_bytes_avail = 0;
7102                 *total_number_of_bytes = 0;
7103                 *total_number_of_free_bytes = 0;
7104                 *error = GetLastError ();
7105         }
7106
7107         return result;
7108 }
7109
7110 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
7111 static inline guint32
7112 mono_icall_drive_info_get_drive_type (MonoString *root_path_name)
7113 {
7114         return GetDriveType (mono_string_chars (root_path_name));
7115 }
7116 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
7117
7118 ICALL_EXPORT guint32
7119 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7120 {
7121         return mono_icall_drive_info_get_drive_type (root_path_name);
7122 }
7123
7124 #endif /* PLATFORM_NO_DRIVEINFO */
7125
7126 ICALL_EXPORT gpointer
7127 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7128 {
7129         MonoError error;
7130         gpointer result = mono_compile_method_checked (method, &error);
7131         mono_error_set_pending_exception (&error);
7132         return result;
7133 }
7134
7135 ICALL_EXPORT MonoString *
7136 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7137 {
7138         MonoString *mcpath;
7139         gchar *path;
7140
7141         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7142
7143         mono_icall_make_platform_path (path);
7144
7145         mcpath = mono_string_new (mono_domain_get (), path);
7146         g_free (path);
7147
7148         return mcpath;
7149 }
7150
7151 /* this is an icall */
7152 static MonoString *
7153 get_bundled_app_config (void)
7154 {
7155         MonoError error;
7156         const gchar *app_config;
7157         MonoDomain *domain;
7158         MonoString *file;
7159         gchar *config_file_name, *config_file_path;
7160         gsize len, config_file_path_length, config_ext_length;
7161         gchar *module;
7162
7163         domain = mono_domain_get ();
7164         file = domain->setup->configuration_file;
7165         if (!file || file->length == 0)
7166                 return NULL;
7167
7168         // Retrieve config file and remove the extension
7169         config_file_name = mono_string_to_utf8_checked (file, &error);
7170         if (mono_error_set_pending_exception (&error))
7171                 return NULL;
7172         config_file_path = mono_portability_find_file (config_file_name, TRUE);
7173         if (!config_file_path)
7174                 config_file_path = config_file_name;
7175
7176         config_file_path_length = strlen (config_file_path);
7177         config_ext_length = strlen (".config");
7178         if (config_file_path_length <= config_ext_length)
7179                 return NULL;
7180
7181         len = config_file_path_length - config_ext_length;
7182         module = (gchar *)g_malloc0 (len + 1);
7183         memcpy (module, config_file_path, len);
7184         // Get the config file from the module name
7185         app_config = mono_config_string_for_assembly_file (module);
7186         // Clean-up
7187         g_free (module);
7188         if (config_file_name != config_file_path)
7189                 g_free (config_file_name);
7190         g_free (config_file_path);
7191
7192         if (!app_config)
7193                 return NULL;
7194
7195         return mono_string_new (mono_domain_get (), app_config);
7196 }
7197
7198 static MonoStringHandle
7199 get_bundled_machine_config (MonoError *error)
7200 {
7201         const gchar *machine_config;
7202
7203         machine_config = mono_get_machine_config ();
7204
7205         if (!machine_config)
7206                 return NULL_HANDLE_STRING;
7207
7208         return mono_string_new_handle (mono_domain_get (), machine_config, error);
7209 }
7210
7211 ICALL_EXPORT MonoStringHandle
7212 ves_icall_System_Environment_get_bundled_machine_config (MonoError *error)
7213 {
7214         return get_bundled_machine_config (error);
7215 }
7216
7217
7218 ICALL_EXPORT MonoStringHandle
7219 ves_icall_System_Configuration_DefaultConfig_get_bundled_machine_config (MonoError *error)
7220 {
7221         return get_bundled_machine_config (error);
7222 }
7223
7224 ICALL_EXPORT MonoStringHandle
7225 ves_icall_System_Configuration_InternalConfigurationHost_get_bundled_machine_config (MonoError *error)
7226 {
7227         return get_bundled_machine_config (error);
7228 }
7229
7230
7231 ICALL_EXPORT MonoString *
7232 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7233 {
7234         MonoString *ipath;
7235         gchar *path;
7236
7237         path = g_path_get_dirname (mono_get_config_dir ());
7238
7239         mono_icall_make_platform_path (path);
7240
7241         ipath = mono_string_new (mono_domain_get (), path);
7242         g_free (path);
7243
7244         return ipath;
7245 }
7246
7247 ICALL_EXPORT gboolean
7248 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7249 {
7250         MonoPEResourceDataEntry *entry;
7251         MonoImage *image;
7252
7253         if (!assembly || !result || !size)
7254                 return FALSE;
7255
7256         *result = NULL;
7257         *size = 0;
7258         image = assembly->assembly->image;
7259         entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7260         if (!entry)
7261                 return FALSE;
7262
7263         *result = mono_image_rva_map (image, entry->rde_data_offset);
7264         if (!(*result)) {
7265                 g_free (entry);
7266                 return FALSE;
7267         }
7268         *size = entry->rde_size;
7269         g_free (entry);
7270         return TRUE;
7271 }
7272
7273 ICALL_EXPORT MonoBoolean
7274 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7275 {
7276         return mono_is_debugger_attached ();
7277 }
7278
7279 ICALL_EXPORT MonoBoolean
7280 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7281 {
7282         if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7283                 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7284         else
7285                 return FALSE;
7286 }
7287
7288 ICALL_EXPORT void
7289 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7290 {
7291         if (mono_get_runtime_callbacks ()->debug_log)
7292                 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7293 }
7294
7295 #ifndef HOST_WIN32
7296 static inline void
7297 mono_icall_write_windows_debug_string (MonoString *message)
7298 {
7299         g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7300 }
7301 #endif /* !HOST_WIN32 */
7302
7303 ICALL_EXPORT void
7304 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7305 {
7306         mono_icall_write_windows_debug_string (message);
7307 }
7308
7309 /* Only used for value types */
7310 ICALL_EXPORT MonoObject *
7311 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7312 {
7313         MonoError error;
7314         MonoObject *result;
7315         MonoClass *klass;
7316         MonoDomain *domain;
7317         
7318         domain = mono_object_domain (type);
7319         klass = mono_class_from_mono_type (type->type);
7320         mono_class_init_checked (klass, &error);
7321         if (mono_error_set_pending_exception (&error))
7322                 return NULL;
7323
7324         if (mono_class_is_nullable (klass))
7325                 /* No arguments -> null */
7326                 return NULL;
7327
7328         result = mono_object_new_checked (domain, klass, &error);
7329         mono_error_set_pending_exception (&error);
7330         return result;
7331 }
7332
7333 ICALL_EXPORT MonoReflectionMethod *
7334 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7335 {
7336         MonoReflectionMethod *ret = NULL;
7337         MonoError error;
7338
7339         MonoClass *klass, *parent;
7340         MonoGenericContext *generic_inst = NULL;
7341         MonoMethod *method = m->method;
7342         MonoMethod *result = NULL;
7343         int slot;
7344
7345         if (method->klass == NULL)
7346                 return m;
7347
7348         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7349             MONO_CLASS_IS_INTERFACE (method->klass) ||
7350             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7351                 return m;
7352
7353         slot = mono_method_get_vtable_slot (method);
7354         if (slot == -1)
7355                 return m;
7356
7357         klass = method->klass;
7358         if (mono_class_is_ginst (klass)) {
7359                 generic_inst = mono_class_get_context (klass);
7360                 klass = mono_class_get_generic_class (klass)->container_class;
7361         }
7362
7363 retry:
7364         if (definition) {
7365                 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7366                 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7367                         /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7368                            or klass is the generic container class and generic_inst is the instantiation.
7369
7370                            when we go to the parent, if the parent is an open constructed type, we need to
7371                            replace the type parameters by the definitions from the generic_inst, and then take it
7372                            apart again into the klass and the generic_inst.
7373
7374                            For cases like this:
7375                            class C<T> : B<T, int> {
7376                                public override void Foo () { ... }
7377                            }
7378                            class B<U,V> : A<HashMap<U,V>> {
7379                                public override void Foo () { ... }
7380                            }
7381                            class A<X> {
7382                                public virtual void Foo () { ... }
7383                            }
7384
7385                            if at each iteration the parent isn't open, we can skip inflating it.  if at some
7386                            iteration the parent isn't generic (after possible inflation), we set generic_inst to
7387                            NULL;
7388                         */
7389                         MonoGenericContext *parent_inst = NULL;
7390                         if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7391                                 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7392                                 if (!mono_error_ok (&error)) {
7393                                         mono_error_set_pending_exception (&error);
7394                                         return NULL;
7395                                 }
7396                         }
7397                         if (mono_class_is_ginst (parent)) {
7398                                 parent_inst = mono_class_get_context (parent);
7399                                 parent = mono_class_get_generic_class (parent)->container_class;
7400                         }
7401
7402                         mono_class_setup_vtable (parent);
7403                         if (parent->vtable_size <= slot)
7404                                 break;
7405                         klass = parent;
7406                         generic_inst = parent_inst;
7407                 }
7408         } else {
7409                 klass = klass->parent;
7410                 if (!klass)
7411                         return m;
7412                 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7413                         klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7414                         if (!mono_error_ok (&error)) {
7415                                 mono_error_set_pending_exception (&error);
7416                                 return NULL;
7417                         }
7418
7419                         generic_inst = NULL;
7420                 }
7421                 if (mono_class_is_ginst (klass)) {
7422                         generic_inst = mono_class_get_context (klass);
7423                         klass = mono_class_get_generic_class (klass)->container_class;
7424                 }
7425
7426         }
7427
7428         if (generic_inst) {
7429                 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7430                 if (!mono_error_ok (&error)) {
7431                         mono_error_set_pending_exception (&error);
7432                         return NULL;
7433                 }
7434         }
7435
7436         if (klass == method->klass)
7437                 return m;
7438
7439         /*This is possible if definition == FALSE.
7440          * Do it here to be really sure we don't read invalid memory.
7441          */
7442         if (slot >= klass->vtable_size)
7443                 return m;
7444
7445         mono_class_setup_vtable (klass);
7446
7447         result = klass->vtable [slot];
7448         if (result == NULL) {
7449                 /* It is an abstract method */
7450                 gboolean found = FALSE;
7451                 gpointer iter = NULL;
7452                 while ((result = mono_class_get_methods (klass, &iter))) {
7453                         if (result->slot == slot) {
7454                                 found = TRUE;
7455                                 break;
7456                         }
7457                 }
7458                 /* found might be FALSE if we looked in an abstract class
7459                  * that doesn't override an abstract method of its
7460                  * parent: 
7461                  *   abstract class Base {
7462                  *     public abstract void Foo ();
7463                  *   }
7464                  *   abstract class Derived : Base { }
7465                  *   class Child : Derived {
7466                  *     public override void Foo () { }
7467                  *  }
7468                  *
7469                  *  if m was Child.Foo and we ask for the base method,
7470                  *  then we get here with klass == Derived and found == FALSE
7471                  */
7472                 /* but it shouldn't be the case that if we're looking
7473                  * for the definition and didn't find a result; the
7474                  * loop above should've taken us as far as we could
7475                  * go! */
7476                 g_assert (!(definition && !found));
7477                 if (!found)
7478                         goto retry;
7479         }
7480
7481         g_assert (result != NULL);
7482
7483         ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7484         mono_error_set_pending_exception (&error);
7485         return ret;
7486 }
7487
7488 ICALL_EXPORT MonoString*
7489 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7490 {
7491         MonoMethod *method = m->method;
7492
7493         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7494         return m->name;
7495 }
7496
7497 ICALL_EXPORT void
7498 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7499 {
7500         iter->sig = *(MonoMethodSignature**)argsp;
7501         
7502         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7503         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7504
7505         iter->next_arg = 0;
7506         /* FIXME: it's not documented what start is exactly... */
7507         if (start) {
7508                 iter->args = start;
7509         } else {
7510                 iter->args = argsp + sizeof (gpointer);
7511         }
7512         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7513
7514         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7515 }
7516
7517 ICALL_EXPORT MonoTypedRef
7518 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7519 {
7520         guint32 i, arg_size;
7521         gint32 align;
7522         MonoTypedRef res;
7523
7524         i = iter->sig->sentinelpos + iter->next_arg;
7525
7526         g_assert (i < iter->sig->param_count);
7527
7528         res.type = iter->sig->params [i];
7529         res.klass = mono_class_from_mono_type (res.type);
7530         arg_size = mono_type_stack_size (res.type, &align);
7531 #if defined(__arm__) || defined(__mips__)
7532         iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7533 #endif
7534         res.value = iter->args;
7535 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7536         /* Values are stored as 8 byte register sized objects, but 'value'
7537          * is dereferenced as a pointer in other routines.
7538          */
7539         res.value = (char*)res.value + 4;
7540 #endif
7541 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7542         if (arg_size <= sizeof (gpointer)) {
7543                 int dummy;
7544                 int padding = arg_size - mono_type_size (res.type, &dummy);
7545                 res.value = (guint8*)res.value + padding;
7546         }
7547 #endif
7548         iter->args = (char*)iter->args + arg_size;
7549         iter->next_arg++;
7550
7551         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7552
7553         return res;
7554 }
7555
7556 ICALL_EXPORT MonoTypedRef
7557 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7558 {
7559         guint32 i, arg_size;
7560         gint32 align;
7561         MonoTypedRef res;
7562
7563         i = iter->sig->sentinelpos + iter->next_arg;
7564
7565         g_assert (i < iter->sig->param_count);
7566
7567         while (i < iter->sig->param_count) {
7568                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7569                         continue;
7570                 res.type = iter->sig->params [i];
7571                 res.klass = mono_class_from_mono_type (res.type);
7572                 /* FIXME: endianess issue... */
7573                 arg_size = mono_type_stack_size (res.type, &align);
7574 #if defined(__arm__) || defined(__mips__)
7575                 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7576 #endif
7577                 res.value = iter->args;
7578                 iter->args = (char*)iter->args + arg_size;
7579                 iter->next_arg++;
7580                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7581                 return res;
7582         }
7583         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7584
7585         res.type = NULL;
7586         res.value = NULL;
7587         res.klass = NULL;
7588         return res;
7589 }
7590
7591 ICALL_EXPORT MonoType*
7592 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7593 {
7594         gint i;
7595         
7596         i = iter->sig->sentinelpos + iter->next_arg;
7597
7598         g_assert (i < iter->sig->param_count);
7599
7600         return iter->sig->params [i];
7601 }
7602
7603 ICALL_EXPORT MonoObject*
7604 mono_TypedReference_ToObject (MonoTypedRef* tref)
7605 {
7606         MonoError error;
7607         MonoObject *result = NULL;
7608         if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7609                 MonoObject** objp = (MonoObject **)tref->value;
7610                 return *objp;
7611         }
7612
7613         result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7614         mono_error_set_pending_exception (&error);
7615         return result;
7616 }
7617
7618 ICALL_EXPORT MonoTypedRef
7619 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7620 {
7621         MonoTypedRef res;
7622         MonoReflectionField *f;
7623         MonoClass *klass;
7624         MonoType *ftype = NULL;
7625         guint8 *p = NULL;
7626         int i;
7627
7628         memset (&res, 0, sizeof (res));
7629
7630         g_assert (fields);
7631         g_assert (mono_array_length (fields) > 0);
7632
7633         klass = target->vtable->klass;
7634
7635         for (i = 0; i < mono_array_length (fields); ++i) {
7636                 f = mono_array_get (fields, MonoReflectionField*, i);
7637                 if (f == NULL) {
7638                         mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7639                         return res;
7640                 }
7641                 if (f->field->parent != klass) {
7642                         mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7643                         return res;
7644                 }
7645                 if (i == 0)
7646                         p = (guint8*)target + f->field->offset;
7647                 else
7648                         p += f->field->offset - sizeof (MonoObject);
7649                 klass = mono_class_from_mono_type (f->field->type);
7650                 ftype = f->field->type;
7651         }
7652
7653         res.type = ftype;
7654         res.klass = mono_class_from_mono_type (ftype);
7655         res.value = p;
7656
7657         return res;
7658 }
7659
7660 static void
7661 prelink_method (MonoMethod *method, MonoError *error)
7662 {
7663         const char *exc_class, *exc_arg;
7664
7665         mono_error_init (error);
7666         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7667                 return;
7668         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7669         if (exc_class) {
7670                 mono_error_set_exception_instance (error,
7671                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7672                 return;
7673         }
7674         /* create the wrapper, too? */
7675 }
7676
7677 ICALL_EXPORT void
7678 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7679 {
7680         MonoError error;
7681
7682         prelink_method (method->method, &error);
7683         mono_error_set_pending_exception (&error);
7684 }
7685
7686 ICALL_EXPORT void
7687 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7688 {
7689         MonoError error;
7690         MonoClass *klass = mono_class_from_mono_type (type->type);
7691         MonoMethod* m;
7692         gpointer iter = NULL;
7693
7694         mono_class_init_checked (klass, &error);
7695         if (mono_error_set_pending_exception (&error))
7696                 return;
7697
7698         while ((m = mono_class_get_methods (klass, &iter))) {
7699                 prelink_method (m, &error);
7700                 if (mono_error_set_pending_exception (&error))
7701                         return;
7702         }
7703 }
7704
7705 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7706 ICALL_EXPORT void
7707 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7708                                             gint32 const **exponents,
7709                                             gunichar2 const **digitLowerTable,
7710                                             gunichar2 const **digitUpperTable,
7711                                             gint64 const **tenPowersList,
7712                                             gint32 const **decHexDigits)
7713 {
7714         *mantissas = Formatter_MantissaBitsTable;
7715         *exponents = Formatter_TensExponentTable;
7716         *digitLowerTable = Formatter_DigitLowerTable;
7717         *digitUpperTable = Formatter_DigitUpperTable;
7718         *tenPowersList = Formatter_TenPowersList;
7719         *decHexDigits = Formatter_DecHexDigits;
7720 }
7721
7722 /*
7723  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7724  * and avoid useless allocations.
7725  */
7726 static MonoArray*
7727 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7728 {
7729         MonoReflectionType *rt;
7730         MonoArray *res;
7731         int i, count = 0;
7732
7733         mono_error_init (error);
7734         for (i = 0; i < type->num_mods; ++i) {
7735                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7736                         count++;
7737         }
7738         if (!count)
7739                 return NULL;
7740         res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7741         return_val_if_nok (error, NULL);
7742         count = 0;
7743         for (i = 0; i < type->num_mods; ++i) {
7744                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7745                         MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7746                         return_val_if_nok (error, NULL);
7747
7748                         rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7749                         return_val_if_nok (error, NULL);
7750
7751                         mono_array_setref (res, count, rt);
7752                         count++;
7753                 }
7754         }
7755         return res;
7756 }
7757
7758 ICALL_EXPORT MonoArray*
7759 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7760 {
7761         MonoError error;
7762         MonoType *type = param->ClassImpl->type;
7763         MonoClass *member_class = mono_object_class (param->MemberImpl);
7764         MonoMethod *method = NULL;
7765         MonoImage *image;
7766         int pos;
7767         MonoMethodSignature *sig;
7768         MonoArray *res;
7769
7770         if (mono_class_is_reflection_method_or_constructor (member_class)) {
7771                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7772                 method = rmethod->method;
7773         } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7774                 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7775                 if (!(method = prop->property->get))
7776                         method = prop->property->set;
7777                 g_assert (method);      
7778         } else {
7779                 char *type_name = mono_type_get_full_name (member_class);
7780                 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7781                 MonoException *ex = mono_get_exception_not_supported  (msg);
7782                 g_free (type_name);
7783                 g_free (msg);
7784                 mono_set_pending_exception (ex);
7785                 return NULL;
7786         }
7787
7788         image = method->klass->image;
7789         pos = param->PositionImpl;
7790         sig = mono_method_signature (method);
7791         if (pos == -1)
7792                 type = sig->ret;
7793         else
7794                 type = sig->params [pos];
7795
7796         res = type_array_from_modifiers (image, type, optional, &error);
7797         mono_error_set_pending_exception (&error);
7798         return res;
7799 }
7800
7801 static MonoType*
7802 get_property_type (MonoProperty *prop)
7803 {
7804         MonoMethodSignature *sig;
7805         if (prop->get) {
7806                 sig = mono_method_signature (prop->get);
7807                 return sig->ret;
7808         } else if (prop->set) {
7809                 sig = mono_method_signature (prop->set);
7810                 return sig->params [sig->param_count - 1];
7811         }
7812         return NULL;
7813 }
7814
7815 ICALL_EXPORT MonoArray*
7816 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7817 {
7818         MonoError error;
7819         MonoType *type = get_property_type (property->property);
7820         MonoImage *image = property->klass->image;
7821         MonoArray *res;
7822
7823         if (!type)
7824                 return NULL;
7825         res = type_array_from_modifiers (image, type, optional, &error);
7826         mono_error_set_pending_exception (&error);
7827         return res;
7828 }
7829
7830 /*
7831  *Construct a MonoType suited to be used to decode a constant blob object.
7832  *
7833  * @type is the target type which will be constructed
7834  * @blob_type is the blob type, for example, that comes from the constant table
7835  * @real_type is the expected constructed type.
7836  */
7837 static void
7838 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7839 {
7840         type->type = blob_type;
7841         type->data.klass = NULL;
7842         if (blob_type == MONO_TYPE_CLASS)
7843                 type->data.klass = mono_defaults.object_class;
7844         else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7845                 /* For enums, we need to use the base type */
7846                 type->type = MONO_TYPE_VALUETYPE;
7847                 type->data.klass = mono_class_from_mono_type (real_type);
7848         } else
7849                 type->data.klass = mono_class_from_mono_type (real_type);
7850 }
7851
7852 ICALL_EXPORT MonoObject*
7853 property_info_get_default_value (MonoReflectionProperty *property)
7854 {
7855         MonoError error;
7856         MonoType blob_type;
7857         MonoProperty *prop = property->property;
7858         MonoType *type = get_property_type (prop);
7859         MonoDomain *domain = mono_object_domain (property); 
7860         MonoTypeEnum def_type;
7861         const char *def_value;
7862         MonoObject *o;
7863
7864         mono_class_init (prop->parent);
7865
7866         if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7867                 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7868                 return NULL;
7869         }
7870
7871         def_value = mono_class_get_property_default_value (prop, &def_type);
7872
7873         mono_type_from_blob_type (&blob_type, def_type, type);
7874         o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7875
7876         mono_error_set_pending_exception (&error);
7877         return o;
7878 }
7879
7880 ICALL_EXPORT MonoBoolean
7881 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7882 {
7883         MonoError error;
7884         MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7885         MonoCustomAttrInfo *cinfo;
7886         gboolean found;
7887
7888         mono_class_init_checked (attr_class, &error);
7889         if (mono_error_set_pending_exception (&error))
7890                 return FALSE;
7891
7892         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7893         if (!is_ok (&error)) {
7894                 mono_error_set_pending_exception (&error);
7895                 return FALSE;
7896         }
7897         if (!cinfo)
7898                 return FALSE;
7899         found = mono_custom_attrs_has_attr (cinfo, attr_class);
7900         if (!cinfo->cached)
7901                 mono_custom_attrs_free (cinfo);
7902         return found;
7903 }
7904
7905 ICALL_EXPORT MonoArray*
7906 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7907 {
7908         MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7909         MonoArray *res;
7910         MonoError error;
7911
7912         if (attr_class) {
7913                 mono_class_init_checked (attr_class, &error);
7914                 if (mono_error_set_pending_exception (&error))
7915                         return NULL;
7916         }
7917
7918         res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7919         if (!mono_error_ok (&error)) {
7920                 mono_error_set_pending_exception (&error);
7921                 return NULL;
7922         }
7923
7924         return res;
7925 }
7926
7927 ICALL_EXPORT MonoArray*
7928 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7929 {
7930         MonoError error;
7931         MonoArray *result;
7932         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7933         mono_error_set_pending_exception (&error);
7934         return result;
7935 }
7936
7937
7938 ICALL_EXPORT MonoString*
7939 ves_icall_Mono_Runtime_GetDisplayName (void)
7940 {
7941         char *info;
7942         MonoString *display_name;
7943
7944         info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7945         display_name = mono_string_new (mono_domain_get (), info);
7946         g_free (info);
7947         return display_name;
7948 }
7949
7950 ICALL_EXPORT MonoString*
7951 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7952 {
7953         MonoError error;
7954         MonoString *message;
7955         guint32 ret;
7956         gunichar2 buf[256];
7957         
7958         ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7959                              FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7960                              buf, 255, NULL);
7961         if (ret == 0) {
7962                 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7963         } else {
7964                 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7965                 if (mono_error_set_pending_exception (&error))
7966                         return NULL;
7967         }
7968         
7969         return message;
7970 }
7971
7972 #ifndef HOST_WIN32
7973 static inline gint32
7974 mono_icall_wait_for_input_idle (gpointer handle, gint32 milliseconds)
7975 {
7976         return WAIT_TIMEOUT;
7977 }
7978 #endif /* !HOST_WIN32 */
7979
7980 ICALL_EXPORT gint32
7981 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
7982 {
7983         return mono_icall_wait_for_input_idle (handle, milliseconds);
7984 }
7985
7986 ICALL_EXPORT gint32
7987 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
7988 {
7989         return mono_process_current_pid ();
7990 }
7991
7992 ICALL_EXPORT MonoBoolean
7993 ves_icall_Mono_TlsProviderFactory_IsBtlsSupported (void)
7994 {
7995 #if HAVE_BTLS
7996         return TRUE;
7997 #else
7998         return FALSE;
7999 #endif
8000 }
8001
8002 #ifndef DISABLE_COM
8003
8004 ICALL_EXPORT int
8005 ves_icall_System_Runtime_InteropServices_Marshal_GetHRForException_WinRT(MonoException* ex)
8006 {
8007         mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetHRForException_WinRT internal call is not implemented."));
8008         return 0;
8009 }
8010
8011 ICALL_EXPORT MonoObject*
8012 ves_icall_System_Runtime_InteropServices_Marshal_GetNativeActivationFactory(MonoObject* type)
8013 {
8014         mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetNativeActivationFactory internal call is not implemented."));
8015         return NULL;
8016 }
8017
8018 ICALL_EXPORT void*
8019 ves_icall_System_Runtime_InteropServices_Marshal_GetRawIUnknownForComObjectNoAddRef(MonoObject* obj)
8020 {
8021         mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetRawIUnknownForComObjectNoAddRef internal call is not implemented."));
8022         return NULL;
8023 }
8024
8025 ICALL_EXPORT MonoObject*
8026 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_GetRestrictedErrorInfo()
8027 {
8028         mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.GetRestrictedErrorInfo internal call is not implemented."));
8029         return NULL;
8030 }
8031
8032 ICALL_EXPORT MonoBoolean
8033 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoOriginateLanguageException(int error, MonoString* message, void* languageException)
8034 {
8035         mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoOriginateLanguageException internal call is not implemented."));
8036         return FALSE;
8037 }
8038
8039 ICALL_EXPORT void
8040 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoReportUnhandledError(MonoObject* error)
8041 {
8042         mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoReportUnhandledError internal call is not implemented."));
8043 }
8044
8045 ICALL_EXPORT int
8046 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsCreateString(MonoString* sourceString, int length, void** hstring)
8047 {
8048         mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateString internal call is not implemented."));
8049         return 0;
8050 }
8051
8052 ICALL_EXPORT int
8053 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsDeleteString(void* hstring)
8054 {
8055         mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsDeleteString internal call is not implemented."));
8056         return 0;
8057 }
8058
8059 ICALL_EXPORT mono_unichar2*
8060 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsGetStringRawBuffer(void* hstring, unsigned* length)
8061 {
8062         mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsGetStringRawBuffer internal call is not implemented."));
8063         return NULL;
8064 }
8065
8066 #endif
8067
8068
8069 #ifndef DISABLE_ICALL_TABLES
8070
8071 #define ICALL_TYPE(id,name,first)
8072 #define ICALL(id,name,func) Icall_ ## id,
8073 #define HANDLES(inner) inner
8074
8075 enum {
8076 #include "metadata/icall-def.h"
8077         Icall_last
8078 };
8079
8080 #undef ICALL_TYPE
8081 #undef ICALL
8082 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8083 #define ICALL(id,name,func)
8084 #undef HANDLES
8085 #define HANDLES(inner) inner
8086 enum {
8087 #include "metadata/icall-def.h"
8088         Icall_type_num
8089 };
8090
8091 #undef ICALL_TYPE
8092 #undef ICALL
8093 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8094 #define ICALL(id,name,func)
8095 #undef HANDLES
8096 #define HANDLES(inner) inner
8097 typedef struct {
8098         guint16 first_icall;
8099 } IcallTypeDesc;
8100
8101 static const IcallTypeDesc
8102 icall_type_descs [] = {
8103 #include "metadata/icall-def.h"
8104         {Icall_last}
8105 };
8106
8107 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8108
8109 #undef HANDLES
8110 #define HANDLES(inner) inner
8111 #undef ICALL_TYPE
8112 #define ICALL_TYPE(id,name,first)
8113 #undef ICALL
8114
8115 #ifdef HAVE_ARRAY_ELEM_INIT
8116 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8117 #define MSGSTRFIELD1(line) str##line
8118
8119 static const struct msgstrtn_t {
8120 #define ICALL(id,name,func)
8121 #undef ICALL_TYPE
8122 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8123 #include "metadata/icall-def.h"
8124 #undef ICALL_TYPE
8125 } icall_type_names_str = {
8126 #define ICALL_TYPE(id,name,first) (name),
8127 #include "metadata/icall-def.h"
8128 #undef ICALL_TYPE
8129 };
8130 static const guint16 icall_type_names_idx [] = {
8131 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8132 #include "metadata/icall-def.h"
8133 #undef ICALL_TYPE
8134 };
8135 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8136
8137 static const struct msgstr_t {
8138 #undef ICALL
8139 #define ICALL_TYPE(id,name,first)
8140 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8141 #include "metadata/icall-def.h"
8142 #undef ICALL
8143 } icall_names_str = {
8144 #define ICALL(id,name,func) (name),
8145 #include "metadata/icall-def.h"
8146 #undef ICALL
8147 };
8148 static const guint16 icall_names_idx [] = {
8149 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8150 #include "metadata/icall-def.h"
8151 #undef ICALL
8152 };
8153 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8154
8155 #else
8156
8157 #undef ICALL_TYPE
8158 #undef ICALL
8159 #define ICALL_TYPE(id,name,first) name,
8160 #define ICALL(id,name,func)
8161 static const char* const
8162 icall_type_names [] = {
8163 #include "metadata/icall-def.h"
8164         NULL
8165 };
8166
8167 #define icall_type_name_get(id) (icall_type_names [(id)])
8168
8169 #undef ICALL_TYPE
8170 #undef ICALL
8171 #define ICALL_TYPE(id,name,first)
8172 #define ICALL(id,name,func) name,
8173 static const char* const
8174 icall_names [] = {
8175 #include "metadata/icall-def.h"
8176         NULL
8177 };
8178 #define icall_name_get(id) icall_names [(id)]
8179
8180 #endif /* !HAVE_ARRAY_ELEM_INIT */
8181
8182 #undef HANDLES
8183 #define HANDLES(inner) inner
8184 #undef ICALL_TYPE
8185 #undef ICALL
8186 #define ICALL_TYPE(id,name,first)
8187 #define ICALL(id,name,func) func,
8188 static const gconstpointer
8189 icall_functions [] = {
8190 #include "metadata/icall-def.h"
8191         NULL
8192 };
8193
8194 #ifdef ENABLE_ICALL_SYMBOL_MAP
8195 #undef HANDLES
8196 #define HANDLES(inner) inner
8197 #undef ICALL_TYPE
8198 #undef ICALL
8199 #define ICALL_TYPE(id,name,first)
8200 #define ICALL(id,name,func) #func,
8201 static const gconstpointer
8202 icall_symbols [] = {
8203 #include "metadata/icall-def.h"
8204         NULL
8205 };
8206 #endif
8207
8208 #undef ICALL_TYPE
8209 #undef ICALL
8210 #define ICALL_TYPE(id,name,first)
8211 #define ICALL(id,name,func) 0,
8212 #undef HANDLES
8213 #define HANDLES(inner) 1,
8214 static const guchar
8215 icall_uses_handles [] = {
8216 #include "metadata/icall-def.h"
8217 #undef ICALL
8218 #undef HANDLES
8219 };
8220
8221 #endif /* DISABLE_ICALL_TABLES */
8222
8223 static mono_mutex_t icall_mutex;
8224 static GHashTable *icall_hash = NULL;
8225 static GHashTable *jit_icall_hash_name = NULL;
8226 static GHashTable *jit_icall_hash_addr = NULL;
8227
8228 void
8229 mono_icall_init (void)
8230 {
8231 #ifndef DISABLE_ICALL_TABLES
8232         int i = 0;
8233
8234         /* check that tables are sorted: disable in release */
8235         if (TRUE) {
8236                 int j;
8237                 const char *prev_class = NULL;
8238                 const char *prev_method;
8239                 
8240                 for (i = 0; i < Icall_type_num; ++i) {
8241                         const IcallTypeDesc *desc;
8242                         int num_icalls;
8243                         prev_method = NULL;
8244                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8245                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8246                         prev_class = icall_type_name_get (i);
8247                         desc = &icall_type_descs [i];
8248                         num_icalls = icall_desc_num_icalls (desc);
8249                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8250                         for (j = 0; j < num_icalls; ++j) {
8251                                 const char *methodn = icall_name_get (desc->first_icall + j);
8252                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
8253                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
8254                                 prev_method = methodn;
8255                         }
8256                 }
8257         }
8258 #endif
8259
8260         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8261         mono_os_mutex_init (&icall_mutex);
8262 }
8263
8264 static void
8265 mono_icall_lock (void)
8266 {
8267         mono_locks_os_acquire (&icall_mutex, IcallLock);
8268 }
8269
8270 static void
8271 mono_icall_unlock (void)
8272 {
8273         mono_locks_os_release (&icall_mutex, IcallLock);
8274 }
8275
8276 void
8277 mono_icall_cleanup (void)
8278 {
8279         g_hash_table_destroy (icall_hash);
8280         g_hash_table_destroy (jit_icall_hash_name);
8281         g_hash_table_destroy (jit_icall_hash_addr);
8282         mono_os_mutex_destroy (&icall_mutex);
8283 }
8284
8285 /**
8286  * mono_add_internal_call:
8287  * @name: method specification to surface to the managed world
8288  * @method: pointer to a C method to invoke when the method is called
8289  *
8290  * This method surfaces the C function pointed by @method as a method
8291  * that has been surfaced in managed code with the method specified in
8292  * @name as an internal call.
8293  *
8294  * Internal calls are surfaced to all app domains loaded and they are
8295  * accessibly by a type with the specified name.
8296  *
8297  * You must provide a fully qualified type name, that is namespaces
8298  * and type name, followed by a colon and the method name, with an
8299  * optional signature to bind.
8300  *
8301  * For example, the following are all valid declarations:
8302  *
8303  * "MyApp.Services.ScriptService:Accelerate"
8304  * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8305  *
8306  * You use method parameters in cases where there might be more than
8307  * one surface method to managed code.  That way you can register different
8308  * internal calls for different method overloads.
8309  *
8310  * The internal calls are invoked with no marshalling.   This means that .NET
8311  * types like System.String are exposed as `MonoString *` parameters.   This is
8312  * different than the way that strings are surfaced in P/Invoke.
8313  *
8314  * For more information on how the parameters are marshalled, see the
8315  * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8316  * page.
8317  *
8318  * See the <a  href="mono-api-methods.html#method-desc">Method Description</a>
8319  * reference for more information on the format of method descriptions.
8320  */
8321 void
8322 mono_add_internal_call (const char *name, gconstpointer method)
8323 {
8324         mono_icall_lock ();
8325
8326         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8327
8328         mono_icall_unlock ();
8329 }
8330
8331 #ifndef DISABLE_ICALL_TABLES
8332
8333 #ifdef HAVE_ARRAY_ELEM_INIT
8334 static int
8335 compare_method_imap (const void *key, const void *elem)
8336 {
8337         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8338         return strcmp (key, method_name);
8339 }
8340
8341 static gsize
8342 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8343 {
8344         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);
8345         if (!nameslot)
8346                 return -1;
8347         return (nameslot - &icall_names_idx [0]);
8348 }
8349
8350 static gboolean
8351 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8352 {
8353         gsize slotnum = find_slot_icall (imap, name);
8354         if (slotnum == -1)
8355                 return FALSE;
8356         return (gboolean)icall_uses_handles [slotnum];
8357 }
8358
8359 static gpointer
8360 find_method_icall (const IcallTypeDesc *imap, const char *name)
8361 {
8362         gsize slotnum = find_slot_icall (imap, name);
8363         if (slotnum == -1)
8364                 return NULL;
8365         return (gpointer)icall_functions [slotnum];
8366 }
8367
8368 static int
8369 compare_class_imap (const void *key, const void *elem)
8370 {
8371         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8372         return strcmp (key, class_name);
8373 }
8374
8375 static const IcallTypeDesc*
8376 find_class_icalls (const char *name)
8377 {
8378         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);
8379         if (!nameslot)
8380                 return NULL;
8381         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8382 }
8383
8384 #else /* HAVE_ARRAY_ELEM_INIT */
8385
8386 static int
8387 compare_method_imap (const void *key, const void *elem)
8388 {
8389         const char** method_name = (const char**)elem;
8390         return strcmp (key, *method_name);
8391 }
8392
8393 static gsize
8394 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8395 {
8396         const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8397         if (!nameslot)
8398                 return -1;
8399         return nameslot - icall_names;
8400 }
8401
8402 static gpointer
8403 find_method_icall (const IcallTypeDesc *imap, const char *name)
8404 {
8405         gsize slotnum = find_slot_icall (imap, name);
8406         if (slotnum == -1)
8407                 return NULL;
8408         return (gpointer)icall_functions [slotnum];
8409 }
8410
8411 static gboolean
8412 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8413 {
8414         gsize slotnum = find_slot_icall (imap, name);
8415         if (slotnum == -1)
8416                 return FALSE;
8417         return (gboolean)icall_uses_handles [slotnum];
8418 }
8419
8420 static int
8421 compare_class_imap (const void *key, const void *elem)
8422 {
8423         const char** class_name = (const char**)elem;
8424         return strcmp (key, *class_name);
8425 }
8426
8427 static const IcallTypeDesc*
8428 find_class_icalls (const char *name)
8429 {
8430         const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8431         if (!nameslot)
8432                 return NULL;
8433         return &icall_type_descs [nameslot - icall_type_names];
8434 }
8435
8436 #endif /* HAVE_ARRAY_ELEM_INIT */
8437
8438 #endif /* DISABLE_ICALL_TABLES */
8439
8440 /* 
8441  * we should probably export this as an helper (handle nested types).
8442  * Returns the number of chars written in buf.
8443  */
8444 static int
8445 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8446 {
8447         int nspacelen, cnamelen;
8448         nspacelen = strlen (klass->name_space);
8449         cnamelen = strlen (klass->name);
8450         if (nspacelen + cnamelen + 2 > bufsize)
8451                 return 0;
8452         if (nspacelen) {
8453                 memcpy (buf, klass->name_space, nspacelen);
8454                 buf [nspacelen ++] = '.';
8455         }
8456         memcpy (buf + nspacelen, klass->name, cnamelen);
8457         buf [nspacelen + cnamelen] = 0;
8458         return nspacelen + cnamelen;
8459 }
8460
8461 #ifdef DISABLE_ICALL_TABLES
8462 static void
8463 no_icall_table (void)
8464 {
8465         g_assert_not_reached ();
8466 }
8467 #endif
8468
8469 /**
8470  * mono_lookup_internal_call_full:
8471  * @method: the method to look up
8472  * @uses_handles: out argument if method needs handles around managed objects.
8473  *
8474  * Returns a pointer to the icall code for the given method.  If
8475  * uses_handles is not NULL, it will be set to TRUE if the method
8476  * needs managed objects wrapped using the infrastructure in handle.h
8477  *
8478  * If the method is not found, warns and returns NULL.
8479  */
8480 gpointer
8481 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8482 {
8483         char *sigstart;
8484         char *tmpsig;
8485         char mname [2048];
8486         int typelen = 0, mlen, siglen;
8487         gpointer res;
8488 #ifndef DISABLE_ICALL_TABLES
8489         const IcallTypeDesc *imap = NULL;
8490 #endif
8491
8492         g_assert (method != NULL);
8493
8494         if (method->is_inflated)
8495                 method = ((MonoMethodInflated *) method)->declaring;
8496
8497         if (method->klass->nested_in) {
8498                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8499                 if (!pos)
8500                         return NULL;
8501
8502                 mname [pos++] = '/';
8503                 mname [pos] = 0;
8504
8505                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8506                 if (!typelen)
8507                         return NULL;
8508
8509                 typelen += pos;
8510         } else {
8511                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8512                 if (!typelen)
8513                         return NULL;
8514         }
8515
8516 #ifndef DISABLE_ICALL_TABLES
8517         imap = find_class_icalls (mname);
8518 #endif
8519
8520         mname [typelen] = ':';
8521         mname [typelen + 1] = ':';
8522
8523         mlen = strlen (method->name);
8524         memcpy (mname + typelen + 2, method->name, mlen);
8525         sigstart = mname + typelen + 2 + mlen;
8526         *sigstart = 0;
8527
8528         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8529         siglen = strlen (tmpsig);
8530         if (typelen + mlen + siglen + 6 > sizeof (mname))
8531                 return NULL;
8532         sigstart [0] = '(';
8533         memcpy (sigstart + 1, tmpsig, siglen);
8534         sigstart [siglen + 1] = ')';
8535         sigstart [siglen + 2] = 0;
8536         g_free (tmpsig);
8537         
8538         mono_icall_lock ();
8539
8540         res = g_hash_table_lookup (icall_hash, mname);
8541         if (res) {
8542                 if (uses_handles)
8543                         *uses_handles = FALSE;
8544                 mono_icall_unlock ();;
8545                 return res;
8546         }
8547         /* try without signature */
8548         *sigstart = 0;
8549         res = g_hash_table_lookup (icall_hash, mname);
8550         if (res) {
8551                 if (uses_handles)
8552                         *uses_handles = FALSE;
8553                 mono_icall_unlock ();
8554                 return res;
8555         }
8556
8557 #ifdef DISABLE_ICALL_TABLES
8558         mono_icall_unlock ();
8559         /* Fail only when the result is actually used */
8560         /* mono_marshal_get_native_wrapper () depends on this */
8561         if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8562                 return ves_icall_System_String_ctor_RedirectToCreateString;
8563         else
8564                 return no_icall_table;
8565 #else
8566         /* it wasn't found in the static call tables */
8567         if (!imap) {
8568                 if (uses_handles)
8569                         *uses_handles = FALSE;
8570                 mono_icall_unlock ();
8571                 return NULL;
8572         }
8573         res = find_method_icall (imap, sigstart - mlen);
8574         if (res) {
8575                 if (uses_handles)
8576                         *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8577                 mono_icall_unlock ();
8578                 return res;
8579         }
8580         /* try _with_ signature */
8581         *sigstart = '(';
8582         res = find_method_icall (imap, sigstart - mlen);
8583         if (res) {
8584                 if (uses_handles)
8585                         *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8586                 mono_icall_unlock ();
8587                 return res;
8588         }
8589
8590         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8591         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8592         g_print ("The out of sync library is: %s\n", method->klass->image->name);
8593         g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8594         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");
8595         g_print ("If you see other errors or faults after this message they are probably related\n");
8596         g_print ("and you need to fix your mono install first.\n");
8597
8598         mono_icall_unlock ();
8599
8600         return NULL;
8601 #endif
8602 }
8603
8604 gpointer
8605 mono_lookup_internal_call (MonoMethod *method)
8606 {
8607         return mono_lookup_internal_call_full (method, NULL);
8608 }
8609
8610 #ifdef ENABLE_ICALL_SYMBOL_MAP
8611 static int
8612 func_cmp (gconstpointer key, gconstpointer p)
8613 {
8614         return (gsize)key - (gsize)*(gsize*)p;
8615 }
8616 #endif
8617
8618 /*
8619  * mono_lookup_icall_symbol:
8620  *
8621  *   Given the icall METHOD, returns its C symbol.
8622  */
8623 const char*
8624 mono_lookup_icall_symbol (MonoMethod *m)
8625 {
8626 #ifdef DISABLE_ICALL_TABLES
8627         g_assert_not_reached ();
8628         return NULL;
8629 #else
8630 #ifdef ENABLE_ICALL_SYMBOL_MAP
8631         gpointer func;
8632         int i;
8633         gpointer slot;
8634         static gconstpointer *functions_sorted;
8635         static const char**symbols_sorted;
8636         static gboolean inited;
8637
8638         if (!inited) {
8639                 gboolean changed;
8640
8641                 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8642                 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8643                 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8644                 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8645                 /* Bubble sort the two arrays */
8646                 changed = TRUE;
8647                 while (changed) {
8648                         changed = FALSE;
8649                         for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8650                                 if (functions_sorted [i] > functions_sorted [i + 1]) {
8651                                         gconstpointer tmp;
8652
8653                                         tmp = functions_sorted [i];
8654                                         functions_sorted [i] = functions_sorted [i + 1];
8655                                         functions_sorted [i + 1] = tmp;
8656                                         tmp = symbols_sorted [i];
8657                                         symbols_sorted [i] = symbols_sorted [i + 1];
8658                                         symbols_sorted [i + 1] = tmp;
8659                                         changed = TRUE;
8660                                 }
8661                         }
8662                 }
8663         }
8664
8665         func = mono_lookup_internal_call (m);
8666         if (!func)
8667                 return NULL;
8668         slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8669         if (!slot)
8670                 return NULL;
8671         g_assert (slot);
8672         return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8673 #else
8674         fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8675         g_assert_not_reached ();
8676         return 0;
8677 #endif
8678 #endif
8679 }
8680
8681 static MonoType*
8682 type_from_typename (char *type_name)
8683 {
8684         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
8685
8686         if (!strcmp (type_name, "int"))
8687                 klass = mono_defaults.int_class;
8688         else if (!strcmp (type_name, "ptr"))
8689                 klass = mono_defaults.int_class;
8690         else if (!strcmp (type_name, "void"))
8691                 klass = mono_defaults.void_class;
8692         else if (!strcmp (type_name, "int32"))
8693                 klass = mono_defaults.int32_class;
8694         else if (!strcmp (type_name, "uint32"))
8695                 klass = mono_defaults.uint32_class;
8696         else if (!strcmp (type_name, "int8"))
8697                 klass = mono_defaults.sbyte_class;
8698         else if (!strcmp (type_name, "uint8"))
8699                 klass = mono_defaults.byte_class;
8700         else if (!strcmp (type_name, "int16"))
8701                 klass = mono_defaults.int16_class;
8702         else if (!strcmp (type_name, "uint16"))
8703                 klass = mono_defaults.uint16_class;
8704         else if (!strcmp (type_name, "long"))
8705                 klass = mono_defaults.int64_class;
8706         else if (!strcmp (type_name, "ulong"))
8707                 klass = mono_defaults.uint64_class;
8708         else if (!strcmp (type_name, "float"))
8709                 klass = mono_defaults.single_class;
8710         else if (!strcmp (type_name, "double"))
8711                 klass = mono_defaults.double_class;
8712         else if (!strcmp (type_name, "object"))
8713                 klass = mono_defaults.object_class;
8714         else if (!strcmp (type_name, "obj"))
8715                 klass = mono_defaults.object_class;
8716         else if (!strcmp (type_name, "string"))
8717                 klass = mono_defaults.string_class;
8718         else if (!strcmp (type_name, "bool"))
8719                 klass = mono_defaults.boolean_class;
8720         else if (!strcmp (type_name, "boolean"))
8721                 klass = mono_defaults.boolean_class;
8722         else {
8723                 g_error ("%s", type_name);
8724                 g_assert_not_reached ();
8725         }
8726         return &klass->byval_arg;
8727 }
8728
8729 /**
8730  * LOCKING: Take the corlib image lock.
8731  */
8732 MonoMethodSignature*
8733 mono_create_icall_signature (const char *sigstr)
8734 {
8735         gchar **parts;
8736         int i, len;
8737         gchar **tmp;
8738         MonoMethodSignature *res, *res2;
8739         MonoImage *corlib = mono_defaults.corlib;
8740
8741         mono_image_lock (corlib);
8742         res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8743         mono_image_unlock (corlib);
8744
8745         if (res)
8746                 return res;
8747
8748         parts = g_strsplit (sigstr, " ", 256);
8749
8750         tmp = parts;
8751         len = 0;
8752         while (*tmp) {
8753                 len ++;
8754                 tmp ++;
8755         }
8756
8757         res = mono_metadata_signature_alloc (corlib, len - 1);
8758         res->pinvoke = 1;
8759
8760 #ifdef HOST_WIN32
8761         /* 
8762          * Under windows, the default pinvoke calling convention is STDCALL but
8763          * we need CDECL.
8764          */
8765         res->call_convention = MONO_CALL_C;
8766 #endif
8767
8768         res->ret = type_from_typename (parts [0]);
8769         for (i = 1; i < len; ++i) {
8770                 res->params [i - 1] = type_from_typename (parts [i]);
8771         }
8772
8773         g_strfreev (parts);
8774
8775         mono_image_lock (corlib);
8776         res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8777         if (res2)
8778                 res = res2; /*Value is allocated in the image pool*/
8779         else
8780                 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8781         mono_image_unlock (corlib);
8782
8783         return res;
8784 }
8785
8786 MonoJitICallInfo *
8787 mono_find_jit_icall_by_name (const char *name)
8788 {
8789         MonoJitICallInfo *info;
8790         g_assert (jit_icall_hash_name);
8791
8792         mono_icall_lock ();
8793         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8794         mono_icall_unlock ();
8795         return info;
8796 }
8797
8798 MonoJitICallInfo *
8799 mono_find_jit_icall_by_addr (gconstpointer addr)
8800 {
8801         MonoJitICallInfo *info;
8802         g_assert (jit_icall_hash_addr);
8803
8804         mono_icall_lock ();
8805         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8806         mono_icall_unlock ();
8807
8808         return info;
8809 }
8810
8811 /*
8812  * mono_get_jit_icall_info:
8813  *
8814  *   Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8815  * caller should access it while holding the icall lock.
8816  */
8817 GHashTable*
8818 mono_get_jit_icall_info (void)
8819 {
8820         return jit_icall_hash_name;
8821 }
8822
8823 /*
8824  * mono_lookup_jit_icall_symbol:
8825  *
8826  *   Given the jit icall NAME, returns its C symbol if possible, or NULL.
8827  */
8828 const char*
8829 mono_lookup_jit_icall_symbol (const char *name)
8830 {
8831         MonoJitICallInfo *info;
8832         const char *res = NULL;
8833
8834         mono_icall_lock ();
8835         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8836         if (info)
8837                 res = info->c_symbol;
8838         mono_icall_unlock ();
8839         return res;
8840 }
8841
8842 void
8843 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8844 {
8845         mono_icall_lock ();
8846         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8847         mono_icall_unlock ();
8848 }
8849
8850 /*
8851  * 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
8852  * icalls without wrappers in some cases.
8853  */
8854 MonoJitICallInfo *
8855 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8856 {
8857         MonoJitICallInfo *info;
8858         
8859         g_assert (func);
8860         g_assert (name);
8861
8862         mono_icall_lock ();
8863
8864         if (!jit_icall_hash_name) {
8865                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8866                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8867         }
8868
8869         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8870                 g_warning ("jit icall already defined \"%s\"\n", name);
8871                 g_assert_not_reached ();
8872         }
8873
8874         info = g_new0 (MonoJitICallInfo, 1);
8875         
8876         info->name = name;
8877         info->func = func;
8878         info->sig = sig;
8879         info->c_symbol = c_symbol;
8880         info->no_raise = no_raise;
8881
8882         if (is_save) {
8883                 info->wrapper = func;
8884         } else {
8885                 info->wrapper = NULL;
8886         }
8887
8888         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8889         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8890
8891         mono_icall_unlock ();
8892         return info;
8893 }
8894
8895 MonoJitICallInfo *
8896 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8897 {
8898         return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);
8899 }
8900