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