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