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