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