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