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