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