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