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