[io-layer] Extract socket (#4241)
[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/file-io.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/io-layer/io-layer.h>
89 #include <mono/utils/monobitset.h>
90 #include <mono/utils/mono-time.h>
91 #include <mono/utils/mono-proclib.h>
92 #include <mono/utils/mono-string.h>
93 #include <mono/utils/mono-error-internals.h>
94 #include <mono/utils/mono-mmap.h>
95 #include <mono/utils/mono-io-portability.h>
96 #include <mono/utils/mono-digest.h>
97 #include <mono/utils/bsearch.h>
98 #include <mono/utils/mono-os-mutex.h>
99 #include <mono/utils/mono-threads.h>
100
101 #include "decimal-ms.h"
102 #include "number-ms.h"
103
104 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
105 #include <sys/utsname.h>
106 #endif
107
108 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
109
110 ICALL_EXPORT MonoReflectionAssemblyHandle ves_icall_System_Reflection_Assembly_GetCallingAssembly (MonoError *error);
111
112 /* Lazy class loading functions */
113 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
114 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
115 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
116 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
119
120 static MonoArrayHandle
121 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
122
123 static inline MonoBoolean
124 is_generic_parameter (MonoType *type)
125 {
126         return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
127 }
128
129 static void
130 mono_class_init_checked (MonoClass *klass, MonoError *error)
131 {
132         mono_error_init (error);
133
134         if (!mono_class_init (klass))
135                 mono_error_set_for_class_failure (error, klass);
136 }
137
138 #ifndef HOST_WIN32
139 static inline void
140 mono_icall_make_platform_path (gchar *path)
141 {
142         return;
143 }
144
145 static inline const gchar *
146 mono_icall_get_file_path_prefix (const gchar *path)
147 {
148         return "file://";
149 }
150 #endif /* HOST_WIN32 */
151
152 ICALL_EXPORT MonoObject *
153 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
154 {
155         MonoError error;
156         MonoClass *ac;
157         gint32 esize;
158         gpointer *ea;
159         MonoObject *result = NULL;
160
161         ac = (MonoClass *)arr->obj.vtable->klass;
162
163         esize = mono_array_element_size (ac);
164         ea = (gpointer*)((char*)arr->vector + (pos * esize));
165
166         if (ac->element_class->valuetype) {
167                 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
168                 mono_error_set_pending_exception (&error);
169         } else
170                 result = (MonoObject *)*ea;
171         return result;
172 }
173
174 ICALL_EXPORT MonoObject *
175 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
176 {
177         MonoClass *ac, *ic;
178         MonoArray *io;
179         gint32 i, pos, *ind;
180
181         MONO_CHECK_ARG_NULL (idxs, NULL);
182
183         io = idxs;
184         ic = (MonoClass *)io->obj.vtable->klass;
185         
186         ac = (MonoClass *)arr->obj.vtable->klass;
187
188         g_assert (ic->rank == 1);
189         if (io->bounds != NULL || io->max_length !=  ac->rank) {
190                 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
191                 return NULL;
192         }
193
194         ind = (gint32 *)io->vector;
195
196         if (arr->bounds == NULL) {
197                 if (*ind < 0 || *ind >= arr->max_length) {
198                         mono_set_pending_exception (mono_get_exception_index_out_of_range ());
199                         return NULL;
200                 }
201
202                 return ves_icall_System_Array_GetValueImpl (arr, *ind);
203         }
204         
205         for (i = 0; i < ac->rank; i++) {
206                 if ((ind [i] < arr->bounds [i].lower_bound) ||
207                     (ind [i] >=  (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
208                         mono_set_pending_exception (mono_get_exception_index_out_of_range ());
209                         return NULL;
210                 }
211         }
212
213         pos = ind [0] - arr->bounds [0].lower_bound;
214         for (i = 1; i < ac->rank; i++)
215                 pos = pos * arr->bounds [i].length + ind [i] - 
216                         arr->bounds [i].lower_bound;
217
218         return ves_icall_System_Array_GetValueImpl (arr, pos);
219 }
220
221 ICALL_EXPORT void
222 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
223 {
224         MonoError error;
225         MonoClass *ac, *vc, *ec;
226         gint32 esize, vsize;
227         gpointer *ea, *va;
228         int et, vt;
229
230         guint64 u64 = 0;
231         gint64 i64 = 0;
232         gdouble r64 = 0;
233
234         mono_error_init (&error);
235
236         if (value)
237                 vc = value->vtable->klass;
238         else
239                 vc = NULL;
240
241         ac = arr->obj.vtable->klass;
242         ec = ac->element_class;
243
244         esize = mono_array_element_size (ac);
245         ea = (gpointer*)((char*)arr->vector + (pos * esize));
246         va = (gpointer*)((char*)value + sizeof (MonoObject));
247
248         if (mono_class_is_nullable (ec)) {
249                 mono_nullable_init ((guint8*)ea, value, ec);
250                 return;
251         }
252
253         if (!value) {
254                 mono_gc_bzero_atomic (ea, esize);
255                 return;
256         }
257
258 #define NO_WIDENING_CONVERSION G_STMT_START{\
259         mono_set_pending_exception (mono_get_exception_argument ( \
260                 "value", "not a widening conversion")); \
261         return; \
262 }G_STMT_END
263
264 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
265                 if (esize < vsize + (extra)) {                                                    \
266                         mono_set_pending_exception (mono_get_exception_argument (       \
267                         "value", "not a widening conversion")); \
268                         return;                                                                 \
269                 } \
270 }G_STMT_END
271
272 #define INVALID_CAST G_STMT_START{ \
273                 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
274         mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
275         return; \
276 }G_STMT_END
277
278         /* Check element (destination) type. */
279         switch (ec->byval_arg.type) {
280         case MONO_TYPE_STRING:
281                 switch (vc->byval_arg.type) {
282                 case MONO_TYPE_STRING:
283                         break;
284                 default:
285                         INVALID_CAST;
286                 }
287                 break;
288         case MONO_TYPE_BOOLEAN:
289                 switch (vc->byval_arg.type) {
290                 case MONO_TYPE_BOOLEAN:
291                         break;
292                 case MONO_TYPE_CHAR:
293                 case MONO_TYPE_U1:
294                 case MONO_TYPE_U2:
295                 case MONO_TYPE_U4:
296                 case MONO_TYPE_U8:
297                 case MONO_TYPE_I1:
298                 case MONO_TYPE_I2:
299                 case MONO_TYPE_I4:
300                 case MONO_TYPE_I8:
301                 case MONO_TYPE_R4:
302                 case MONO_TYPE_R8:
303                         NO_WIDENING_CONVERSION;
304                 default:
305                         INVALID_CAST;
306                 }
307                 break;
308         default:
309                 break;
310         }
311
312         if (!ec->valuetype) {
313                 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
314                 if (mono_error_set_pending_exception (&error))
315                         return;
316                 if (!castOk)
317                         INVALID_CAST;
318                 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
319                 return;
320         }
321
322         if (mono_object_isinst_checked (value, ec, &error)) {
323                 if (ec->has_references)
324                         mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
325                 else
326                         mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
327                 return;
328         }
329         if (mono_error_set_pending_exception (&error))
330                 return;
331
332         if (!vc->valuetype)
333                 INVALID_CAST;
334
335         vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
336
337         et = ec->byval_arg.type;
338         if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
339                 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
340
341         vt = vc->byval_arg.type;
342         if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
343                 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
344
345 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
346         switch (vt) { \
347         case MONO_TYPE_U1: \
348         case MONO_TYPE_U2: \
349         case MONO_TYPE_U4: \
350         case MONO_TYPE_U8: \
351         case MONO_TYPE_CHAR: \
352                 CHECK_WIDENING_CONVERSION(0); \
353                 *(etype *) ea = (etype) u64; \
354                 return; \
355         /* You can't assign a signed value to an unsigned array. */ \
356         case MONO_TYPE_I1: \
357         case MONO_TYPE_I2: \
358         case MONO_TYPE_I4: \
359         case MONO_TYPE_I8: \
360         /* You can't assign a floating point number to an integer array. */ \
361         case MONO_TYPE_R4: \
362         case MONO_TYPE_R8: \
363                 NO_WIDENING_CONVERSION; \
364         } \
365 }G_STMT_END
366
367 #define ASSIGN_SIGNED(etype) G_STMT_START{\
368         switch (vt) { \
369         case MONO_TYPE_I1: \
370         case MONO_TYPE_I2: \
371         case MONO_TYPE_I4: \
372         case MONO_TYPE_I8: \
373                 CHECK_WIDENING_CONVERSION(0); \
374                 *(etype *) ea = (etype) i64; \
375                 return; \
376         /* You can assign an unsigned value to a signed array if the array's */ \
377         /* element size is larger than the value size. */ \
378         case MONO_TYPE_U1: \
379         case MONO_TYPE_U2: \
380         case MONO_TYPE_U4: \
381         case MONO_TYPE_U8: \
382         case MONO_TYPE_CHAR: \
383                 CHECK_WIDENING_CONVERSION(1); \
384                 *(etype *) ea = (etype) u64; \
385                 return; \
386         /* You can't assign a floating point number to an integer array. */ \
387         case MONO_TYPE_R4: \
388         case MONO_TYPE_R8: \
389                 NO_WIDENING_CONVERSION; \
390         } \
391 }G_STMT_END
392
393 #define ASSIGN_REAL(etype) G_STMT_START{\
394         switch (vt) { \
395         case MONO_TYPE_R4: \
396         case MONO_TYPE_R8: \
397                 CHECK_WIDENING_CONVERSION(0); \
398                 *(etype *) ea = (etype) r64; \
399                 return; \
400         /* All integer values fit into a floating point array, so we don't */ \
401         /* need to CHECK_WIDENING_CONVERSION here. */ \
402         case MONO_TYPE_I1: \
403         case MONO_TYPE_I2: \
404         case MONO_TYPE_I4: \
405         case MONO_TYPE_I8: \
406                 *(etype *) ea = (etype) i64; \
407                 return; \
408         case MONO_TYPE_U1: \
409         case MONO_TYPE_U2: \
410         case MONO_TYPE_U4: \
411         case MONO_TYPE_U8: \
412         case MONO_TYPE_CHAR: \
413                 *(etype *) ea = (etype) u64; \
414                 return; \
415         } \
416 }G_STMT_END
417
418         switch (vt) {
419         case MONO_TYPE_U1:
420                 u64 = *(guint8 *) va;
421                 break;
422         case MONO_TYPE_U2:
423                 u64 = *(guint16 *) va;
424                 break;
425         case MONO_TYPE_U4:
426                 u64 = *(guint32 *) va;
427                 break;
428         case MONO_TYPE_U8:
429                 u64 = *(guint64 *) va;
430                 break;
431         case MONO_TYPE_I1:
432                 i64 = *(gint8 *) va;
433                 break;
434         case MONO_TYPE_I2:
435                 i64 = *(gint16 *) va;
436                 break;
437         case MONO_TYPE_I4:
438                 i64 = *(gint32 *) va;
439                 break;
440         case MONO_TYPE_I8:
441                 i64 = *(gint64 *) va;
442                 break;
443         case MONO_TYPE_R4:
444                 r64 = *(gfloat *) va;
445                 break;
446         case MONO_TYPE_R8:
447                 r64 = *(gdouble *) va;
448                 break;
449         case MONO_TYPE_CHAR:
450                 u64 = *(guint16 *) va;
451                 break;
452         case MONO_TYPE_BOOLEAN:
453                 /* Boolean is only compatible with itself. */
454                 switch (et) {
455                 case MONO_TYPE_CHAR:
456                 case MONO_TYPE_U1:
457                 case MONO_TYPE_U2:
458                 case MONO_TYPE_U4:
459                 case MONO_TYPE_U8:
460                 case MONO_TYPE_I1:
461                 case MONO_TYPE_I2:
462                 case MONO_TYPE_I4:
463                 case MONO_TYPE_I8:
464                 case MONO_TYPE_R4:
465                 case MONO_TYPE_R8:
466                         NO_WIDENING_CONVERSION;
467                 default:
468                         INVALID_CAST;
469                 }
470                 break;
471         }
472
473         /* If we can't do a direct copy, let's try a widening conversion. */
474         switch (et) {
475         case MONO_TYPE_CHAR:
476                 ASSIGN_UNSIGNED (guint16);
477         case MONO_TYPE_U1:
478                 ASSIGN_UNSIGNED (guint8);
479         case MONO_TYPE_U2:
480                 ASSIGN_UNSIGNED (guint16);
481         case MONO_TYPE_U4:
482                 ASSIGN_UNSIGNED (guint32);
483         case MONO_TYPE_U8:
484                 ASSIGN_UNSIGNED (guint64);
485         case MONO_TYPE_I1:
486                 ASSIGN_SIGNED (gint8);
487         case MONO_TYPE_I2:
488                 ASSIGN_SIGNED (gint16);
489         case MONO_TYPE_I4:
490                 ASSIGN_SIGNED (gint32);
491         case MONO_TYPE_I8:
492                 ASSIGN_SIGNED (gint64);
493         case MONO_TYPE_R4:
494                 ASSIGN_REAL (gfloat);
495         case MONO_TYPE_R8:
496                 ASSIGN_REAL (gdouble);
497         }
498
499         INVALID_CAST;
500         /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
501         return;
502
503 #undef INVALID_CAST
504 #undef NO_WIDENING_CONVERSION
505 #undef CHECK_WIDENING_CONVERSION
506 #undef ASSIGN_UNSIGNED
507 #undef ASSIGN_SIGNED
508 #undef ASSIGN_REAL
509 }
510
511 ICALL_EXPORT void 
512 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
513                                  MonoArray *idxs)
514 {
515         MonoClass *ac, *ic;
516         gint32 i, pos, *ind;
517
518         MONO_CHECK_ARG_NULL (idxs,);
519
520         ic = idxs->obj.vtable->klass;
521         ac = arr->obj.vtable->klass;
522
523         g_assert (ic->rank == 1);
524         if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
525                 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
526                 return;
527         }
528
529         ind = (gint32 *)idxs->vector;
530
531         if (arr->bounds == NULL) {
532                 if (*ind < 0 || *ind >= arr->max_length) {
533                         mono_set_pending_exception (mono_get_exception_index_out_of_range ());
534                         return;
535                 }
536
537                 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
538                 return;
539         }
540         
541         for (i = 0; i < ac->rank; i++)
542                 if ((ind [i] < arr->bounds [i].lower_bound) ||
543                     (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
544                         mono_set_pending_exception (mono_get_exception_index_out_of_range ());
545                         return;
546                 }
547
548         pos = ind [0] - arr->bounds [0].lower_bound;
549         for (i = 1; i < ac->rank; i++)
550                 pos = pos * arr->bounds [i].length + ind [i] - 
551                         arr->bounds [i].lower_bound;
552
553         ves_icall_System_Array_SetValueImpl (arr, value, pos);
554 }
555
556 ICALL_EXPORT MonoArray *
557 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
558 {
559         MonoError error;
560         MonoClass *aklass, *klass;
561         MonoArray *array;
562         uintptr_t *sizes, i;
563         gboolean bounded = FALSE;
564
565         MONO_CHECK_ARG_NULL (type, NULL);
566         MONO_CHECK_ARG_NULL (lengths, NULL);
567
568         MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
569         if (bounds)
570                 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
571
572         for (i = 0; i < mono_array_length (lengths); i++) {
573                 if (mono_array_get (lengths, gint32, i) < 0) {
574                         mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
575                         return NULL;
576                 }
577         }
578
579         klass = mono_class_from_mono_type (type->type);
580         mono_class_init_checked (klass, &error);
581         if (mono_error_set_pending_exception (&error))
582                 return NULL;
583
584         if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
585                 /* vectors are not the same as one dimensional arrays with no-zero bounds */
586                 bounded = TRUE;
587         else
588                 bounded = FALSE;
589
590         aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
591
592         sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
593         for (i = 0; i < aklass->rank; ++i) {
594                 sizes [i] = mono_array_get (lengths, guint32, i);
595                 if (bounds)
596                         sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
597                 else
598                         sizes [i + aklass->rank] = 0;
599         }
600
601         array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
602         mono_error_set_pending_exception (&error);
603
604         return array;
605 }
606
607 ICALL_EXPORT MonoArray *
608 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
609 {
610         MonoError error;
611         MonoClass *aklass, *klass;
612         MonoArray *array;
613         uintptr_t *sizes, i;
614         gboolean bounded = FALSE;
615
616         MONO_CHECK_ARG_NULL (type, NULL);
617         MONO_CHECK_ARG_NULL (lengths, NULL);
618
619         MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
620         if (bounds)
621                 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
622
623         for (i = 0; i < mono_array_length (lengths); i++) {
624                 if ((mono_array_get (lengths, gint64, i) < 0) ||
625                     (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
626                         mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
627                         return NULL;
628                 }
629         }
630
631         klass = mono_class_from_mono_type (type->type);
632         mono_class_init_checked (klass, &error);
633         if (mono_error_set_pending_exception (&error))
634                 return NULL;
635
636         if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
637                 /* vectors are not the same as one dimensional arrays with no-zero bounds */
638                 bounded = TRUE;
639         else
640                 bounded = FALSE;
641
642         aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
643
644         sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
645         for (i = 0; i < aklass->rank; ++i) {
646                 sizes [i] = mono_array_get (lengths, guint64, i);
647                 if (bounds)
648                         sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
649                 else
650                         sizes [i + aklass->rank] = 0;
651         }
652
653         array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
654         mono_error_set_pending_exception (&error);
655
656         return array;
657 }
658
659 ICALL_EXPORT gint32 
660 ves_icall_System_Array_GetRank (MonoObject *arr)
661 {
662         return arr->vtable->klass->rank;
663 }
664
665 ICALL_EXPORT gint32
666 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
667 {
668         gint32 rank = arr->obj.vtable->klass->rank;
669         uintptr_t length;
670
671         if ((dimension < 0) || (dimension >= rank)) {
672                 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
673                 return 0;
674         }
675         
676         if (arr->bounds == NULL)
677                 length = arr->max_length;
678         else
679                 length = arr->bounds [dimension].length;
680
681 #ifdef MONO_BIG_ARRAYS
682         if (length > G_MAXINT32) {
683                 mono_set_pending_exception (mono_get_exception_overflow ());
684                 return 0;
685         }
686 #endif
687         return length;
688 }
689
690 ICALL_EXPORT gint64
691 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
692 {
693         gint32 rank = arr->obj.vtable->klass->rank;
694
695         if ((dimension < 0) || (dimension >= rank)) {
696                 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
697                 return 0;
698         }
699         
700         if (arr->bounds == NULL)
701                 return arr->max_length;
702         
703         return arr->bounds [dimension].length;
704 }
705
706 ICALL_EXPORT gint32
707 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
708 {
709         gint32 rank = arr->obj.vtable->klass->rank;
710
711         if ((dimension < 0) || (dimension >= rank)) {
712                 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
713                 return 0;
714         }
715         
716         if (arr->bounds == NULL)
717                 return 0;
718         
719         return arr->bounds [dimension].lower_bound;
720 }
721
722 ICALL_EXPORT void
723 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
724 {
725         int sz = mono_array_element_size (mono_object_class (arr));
726         mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
727 }
728
729 ICALL_EXPORT MonoArray*
730 ves_icall_System_Array_Clone (MonoArray *arr)
731 {
732         MonoError error;
733         MonoArray *result = mono_array_clone_checked (arr, &error);
734         mono_error_set_pending_exception (&error);
735         return result;
736 }
737
738 ICALL_EXPORT gboolean
739 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
740 {
741         int element_size;
742         void * dest_addr;
743         void * source_addr;
744         MonoVTable *src_vtable;
745         MonoVTable *dest_vtable;
746         MonoClass *src_class;
747         MonoClass *dest_class;
748
749         src_vtable = source->obj.vtable;
750         dest_vtable = dest->obj.vtable;
751
752         if (src_vtable->rank != dest_vtable->rank)
753                 return FALSE;
754
755         if (source->bounds || dest->bounds)
756                 return FALSE;
757
758         /* there's no integer overflow since mono_array_length returns an unsigned integer */
759         if ((dest_idx + length > mono_array_length_fast (dest)) ||
760                 (source_idx + length > mono_array_length_fast (source)))
761                 return FALSE;
762
763         src_class = src_vtable->klass->element_class;
764         dest_class = dest_vtable->klass->element_class;
765
766         /*
767          * Handle common cases.
768          */
769
770         /* Case1: object[] -> valuetype[] (ArrayList::ToArray) 
771         We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
772         */
773         if (src_class == mono_defaults.object_class && dest_class->valuetype)
774                 return FALSE;
775
776         /* Check if we're copying a char[] <==> (u)short[] */
777         if (src_class != dest_class) {
778                 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
779                         return FALSE;
780
781                 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
782                 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
783                         return FALSE;
784         }
785
786         if (dest_class->valuetype) {
787                 element_size = mono_array_element_size (source->obj.vtable->klass);
788                 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
789                 if (dest_class->has_references) {
790                         mono_value_copy_array (dest, dest_idx, source_addr, length);
791                 } else {
792                         dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
793                         mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
794                 }
795         } else {
796                 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
797         }
798
799         return TRUE;
800 }
801
802 ICALL_EXPORT void
803 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
804 {
805         MonoClass *ac;
806         gint32 esize;
807         gpointer *ea;
808
809         ac = (MonoClass *)arr->obj.vtable->klass;
810
811         esize = mono_array_element_size (ac);
812         ea = (gpointer*)((char*)arr->vector + (pos * esize));
813
814         mono_gc_memmove_atomic (value, ea, esize);
815 }
816
817 ICALL_EXPORT void
818 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
819 {
820         MonoClass *ac, *ec;
821         gint32 esize;
822         gpointer *ea;
823
824         ac = (MonoClass *)arr->obj.vtable->klass;
825         ec = ac->element_class;
826
827         esize = mono_array_element_size (ac);
828         ea = (gpointer*)((char*)arr->vector + (pos * esize));
829
830         if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
831                 g_assert (esize == sizeof (gpointer));
832                 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
833         } else {
834                 g_assert (ec->inited);
835                 g_assert (esize == mono_class_value_size (ec, NULL));
836                 if (ec->has_references)
837                         mono_gc_wbarrier_value_copy (ea, value, 1, ec);
838                 else
839                         mono_gc_memmove_atomic (ea, value, esize);
840         }
841 }
842
843 ICALL_EXPORT void
844 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArrayHandle array, MonoClassField *field_handle, MonoError *error)
845 {
846         mono_error_init (error);
847
848         MonoClass *klass = mono_handle_class (array);
849         guint32 size = mono_array_element_size (klass);
850         MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
851         int align;
852         const char *field_data;
853
854         if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
855                 mono_error_set_argument (error, "array", "Cannot initialize array of non-primitive type");
856                 return;
857         }
858
859         if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
860                 mono_error_set_argument (error, "field_handle", "Field '%s' doesn't have an RVA", mono_field_get_name (field_handle));
861                 return;
862         }
863
864         size *= MONO_HANDLE_GETVAL(array, max_length);
865         field_data = mono_field_get_data (field_handle);
866
867         if (size > mono_type_size (field_handle->type, &align)) {
868                 mono_error_set_argument (error, "field_handle", "Field not large enough to fill array");
869                 return;
870         }
871
872 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
873 #define SWAP(n) {                                                               \
874         guint ## n *data = (guint ## n *) mono_array_addr (MONO_HANDLE_RAW(array), char, 0); \
875         guint ## n *src = (guint ## n *) field_data;                            \
876         int i,                                                                  \
877             nEnt = (size / sizeof(guint ## n));                                 \
878                                                                                 \
879         for (i = 0; i < nEnt; i++) {                                            \
880                 data[i] = read ## n (&src[i]);                                  \
881         }                                                                       \
882 }
883
884         /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
885
886         switch (type->type) {
887         case MONO_TYPE_CHAR:
888         case MONO_TYPE_I2:
889         case MONO_TYPE_U2:
890                 SWAP (16);
891                 break;
892         case MONO_TYPE_I4:
893         case MONO_TYPE_U4:
894         case MONO_TYPE_R4:
895                 SWAP (32);
896                 break;
897         case MONO_TYPE_I8:
898         case MONO_TYPE_U8:
899         case MONO_TYPE_R8:
900                 SWAP (64);
901                 break;
902         default:
903                 memcpy (mono_array_addr (MONO_HANDLE_RAW(array), char, 0), field_data, size);
904                 break;
905         }
906 #else
907         memcpy (mono_array_addr (MONO_HANDLE_RAW(array), char, 0), field_data, size);
908 #endif
909 }
910
911 ICALL_EXPORT gint
912 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
913 {
914         return offsetof (MonoString, chars);
915 }
916
917 ICALL_EXPORT MonoObject *
918 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
919 {
920         if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
921                 return obj;
922         else {
923                 MonoError error;
924                 MonoObject *ret = mono_object_clone_checked (obj, &error);
925                 mono_error_set_pending_exception (&error);
926
927                 return ret;
928         }
929 }
930
931 ICALL_EXPORT void
932 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
933 {
934         MonoError error;
935         MonoClass *klass;
936         MonoVTable *vtable;
937
938         MONO_CHECK_ARG_NULL (handle,);
939
940         klass = mono_class_from_mono_type (handle);
941         MONO_CHECK_ARG (handle, klass,);
942
943         if (mono_class_is_gtd (klass))
944                 return;
945
946         vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
947         if (!is_ok (&error)) {
948                 mono_error_set_pending_exception (&error);
949                 return;
950         }
951
952         /* This will call the type constructor */
953         if (!mono_runtime_class_init_full (vtable, &error))
954                 mono_error_set_pending_exception (&error);
955 }
956
957 ICALL_EXPORT void
958 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
959 {
960         MonoError error;
961
962         mono_image_check_for_module_cctor (image);
963         if (image->has_module_cctor) {
964                 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
965                 if (!mono_error_ok (&error)) {
966                         mono_error_set_pending_exception (&error);
967                         return;
968                 }
969                 /*It's fine to raise the exception here*/
970                 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
971                 if (!is_ok (&error)) {
972                         mono_error_set_pending_exception (&error);
973                         return;
974                 }
975                 if (!mono_runtime_class_init_full (vtable, &error))
976                         mono_error_set_pending_exception (&error);
977         }
978 }
979
980 ICALL_EXPORT MonoBoolean
981 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
982 {
983 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
984         // It does not work on win32
985 #else
986         guint8 *stack_addr;
987         guint8 *current;
988         size_t stack_size;
989         int min_size;
990         MonoInternalThread *thread;
991
992         mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
993         /* if we have no info we are optimistic and assume there is enough room */
994         if (!stack_addr)
995                 return TRUE;
996
997         thread = mono_thread_internal_current ();
998         // .net seems to check that at least 50% of stack is available
999         min_size = thread->stack_size / 2;
1000
1001         // TODO: It's not always set
1002         if (!min_size)
1003                 return TRUE;
1004
1005         current = (guint8 *)&stack_addr;
1006         if (current > stack_addr) {
1007                 if ((current - stack_addr) < min_size)
1008                         return FALSE;
1009         } else {
1010                 if (current - (stack_addr - stack_size) < min_size)
1011                         return FALSE;
1012         }
1013 #endif
1014         return TRUE;
1015 }
1016
1017 ICALL_EXPORT MonoObject *
1018 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1019 {
1020         MonoError error;
1021         MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1022         mono_error_set_pending_exception (&error);
1023
1024         return ret;
1025 }
1026
1027 ICALL_EXPORT gint32
1028 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1029 {
1030         MonoError error;
1031         MonoClass *klass;
1032         MonoObject **values = NULL;
1033         MonoObject *o;
1034         int count = 0;
1035         gint32 result = (int)(gsize)mono_defaults.int32_class;
1036         MonoClassField* field;
1037         gpointer iter;
1038
1039         klass = mono_object_class (this_obj);
1040
1041         if (mono_class_num_fields (klass) == 0)
1042                 return result;
1043
1044         /*
1045          * Compute the starting value of the hashcode for fields of primitive
1046          * types, and return the remaining fields in an array to the managed side.
1047          * This way, we can avoid costly reflection operations in managed code.
1048          */
1049         iter = NULL;
1050         while ((field = mono_class_get_fields (klass, &iter))) {
1051                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1052                         continue;
1053                 if (mono_field_is_deleted (field))
1054                         continue;
1055                 /* FIXME: Add more types */
1056                 switch (field->type->type) {
1057                 case MONO_TYPE_I4:
1058                         result ^= *(gint32*)((guint8*)this_obj + field->offset);
1059                         break;
1060                 case MONO_TYPE_STRING: {
1061                         MonoString *s;
1062                         s = *(MonoString**)((guint8*)this_obj + field->offset);
1063                         if (s != NULL)
1064                                 result ^= mono_string_hash (s);
1065                         break;
1066                 }
1067                 default:
1068                         if (!values)
1069                                 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1070                         o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1071                         if (!is_ok (&error)) {
1072                                 mono_error_set_pending_exception (&error);
1073                                 return 0;
1074                         }
1075                         values [count++] = o;
1076                 }
1077         }
1078
1079         if (values) {
1080                 int i;
1081                 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1082                 if (mono_error_set_pending_exception (&error))
1083                         return 0;
1084                 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1085                 for (i = 0; i < count; ++i)
1086                         mono_array_setref (*fields, i, values [i]);
1087         } else {
1088                 *fields = NULL;
1089         }
1090         return result;
1091 }
1092
1093 ICALL_EXPORT MonoBoolean
1094 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1095 {
1096         MonoError error;
1097         MonoClass *klass;
1098         MonoObject **values = NULL;
1099         MonoObject *o;
1100         MonoClassField* field;
1101         gpointer iter;
1102         int count = 0;
1103
1104         MONO_CHECK_ARG_NULL (that, FALSE);
1105
1106         if (this_obj->vtable != that->vtable)
1107                 return FALSE;
1108
1109         klass = mono_object_class (this_obj);
1110
1111         if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1112                 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1113
1114         /*
1115          * Do the comparison for fields of primitive type and return a result if
1116          * possible. Otherwise, return the remaining fields in an array to the 
1117          * managed side. This way, we can avoid costly reflection operations in 
1118          * managed code.
1119          */
1120         *fields = NULL;
1121         iter = NULL;
1122         while ((field = mono_class_get_fields (klass, &iter))) {
1123                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1124                         continue;
1125                 if (mono_field_is_deleted (field))
1126                         continue;
1127                 /* FIXME: Add more types */
1128                 switch (field->type->type) {
1129                 case MONO_TYPE_U1:
1130                 case MONO_TYPE_I1:
1131                 case MONO_TYPE_BOOLEAN:
1132                         if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1133                                 return FALSE;
1134                         break;
1135                 case MONO_TYPE_U2:
1136                 case MONO_TYPE_I2:
1137                 case MONO_TYPE_CHAR:
1138                         if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1139                                 return FALSE;
1140                         break;
1141                 case MONO_TYPE_U4:
1142                 case MONO_TYPE_I4:
1143                         if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1144                                 return FALSE;
1145                         break;
1146                 case MONO_TYPE_U8:
1147                 case MONO_TYPE_I8:
1148                         if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1149                                 return FALSE;
1150                         break;
1151                 case MONO_TYPE_R4:
1152                         if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1153                                 return FALSE;
1154                         break;
1155                 case MONO_TYPE_R8:
1156                         if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1157                                 return FALSE;
1158                         break;
1159
1160
1161                 case MONO_TYPE_STRING: {
1162                         MonoString *s1, *s2;
1163                         guint32 s1len, s2len;
1164                         s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1165                         s2 = *(MonoString**)((guint8*)that + field->offset);
1166                         if (s1 == s2)
1167                                 break;
1168                         if ((s1 == NULL) || (s2 == NULL))
1169                                 return FALSE;
1170                         s1len = mono_string_length (s1);
1171                         s2len = mono_string_length (s2);
1172                         if (s1len != s2len)
1173                                 return FALSE;
1174
1175                         if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1176                                 return FALSE;
1177                         break;
1178                 }
1179                 default:
1180                         if (!values)
1181                                 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1182                         o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1183                         if (!is_ok (&error)) {
1184                                 mono_error_set_pending_exception (&error);
1185                                 return FALSE;
1186                         }
1187                         values [count++] = o;
1188                         o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1189                         if (!is_ok (&error)) {
1190                                 mono_error_set_pending_exception (&error);
1191                                 return FALSE;
1192                         }
1193                         values [count++] = o;
1194                 }
1195
1196                 if (klass->enumtype)
1197                         /* enums only have one non-static field */
1198                         break;
1199         }
1200
1201         if (values) {
1202                 int i;
1203                 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1204                 if (mono_error_set_pending_exception (&error))
1205                         return FALSE;
1206                 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1207                 for (i = 0; i < count; ++i)
1208                         mono_array_setref_fast (*fields, i, values [i]);
1209                 return FALSE;
1210         } else {
1211                 return TRUE;
1212         }
1213 }
1214
1215 ICALL_EXPORT MonoReflectionTypeHandle
1216 ves_icall_System_Object_GetType (MonoObjectHandle obj, MonoError *error)
1217 {
1218         mono_error_init (error);
1219         MonoDomain *domain = MONO_HANDLE_DOMAIN (obj);
1220         MonoClass *klass = mono_handle_class (obj);
1221 #ifndef DISABLE_REMOTING
1222         if (mono_class_is_transparent_proxy (klass)) {
1223                 MonoTransparentProxyHandle proxy_obj = MONO_HANDLE_CAST (MonoTransparentProxy, obj);
1224                 MonoRemoteClass *remote_class = MONO_HANDLE_GETVAL (proxy_obj, remote_class);
1225                 MonoType *proxy_type = &remote_class->proxy_class->byval_arg;
1226                 return mono_type_get_object_handle (domain, proxy_type, error);
1227         } else
1228 #endif
1229                 return mono_type_get_object_handle (domain, &klass->byval_arg, error);
1230 }
1231
1232 static gboolean
1233 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1234 {
1235         MonoMethod **dest = (MonoMethod **)data;
1236
1237         /* skip unmanaged frames */
1238         if (!managed)
1239                 return FALSE;
1240
1241         if (!(*dest)) {
1242                 if (!strcmp (m->klass->name_space, "System.Reflection"))
1243                         return FALSE;
1244                 *dest = m;
1245                 return TRUE;
1246         }
1247         return FALSE;
1248 }
1249
1250 static gboolean
1251 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1252 {
1253         MonoMethod **dest = (MonoMethod **)data;
1254
1255         /* skip unmanaged frames */
1256         if (!managed)
1257                 return FALSE;
1258
1259         if (m->wrapper_type != MONO_WRAPPER_NONE)
1260                 return FALSE;
1261
1262         if (m == *dest) {
1263                 *dest = NULL;
1264                 return FALSE;
1265         }
1266
1267         if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1268                 return FALSE;
1269
1270         if (!(*dest)) {
1271                 *dest = m;
1272                 return TRUE;
1273         }
1274         return FALSE;
1275 }
1276
1277 static gboolean
1278 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1279 {
1280         MonoMethod **dest = (MonoMethod **)data;
1281
1282         /* skip unmanaged frames */
1283         if (!managed)
1284                 return FALSE;
1285
1286         if (m->wrapper_type != MONO_WRAPPER_NONE)
1287                 return FALSE;
1288
1289         if (m == *dest) {
1290                 *dest = NULL;
1291                 return FALSE;
1292         }
1293
1294         if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1295                                                                                                         || (!strcmp (m->klass->name_space, "System"))))
1296                 return FALSE;
1297
1298         if (!(*dest)) {
1299                 *dest = m;
1300                 return TRUE;
1301         }
1302         return FALSE;
1303 }
1304
1305 static MonoReflectionTypeHandle
1306 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoAssembly **caller_assembly, MonoError *error)
1307 {
1308         MonoMethod *m, *dest;
1309
1310         MonoType *type = NULL;
1311         MonoAssembly *assembly = NULL;
1312         gboolean type_resolve = FALSE;
1313         MonoImage *rootimage = NULL;
1314
1315         mono_error_init (error);
1316
1317         /*
1318          * We must compute the calling assembly as type loading must happen under a metadata context.
1319          * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1320          * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1321          */
1322         m = mono_method_get_last_managed ();
1323         dest = m;
1324         if (m && m->klass->image != mono_defaults.corlib) {
1325                 /* Happens with inlining */
1326         } else {
1327                 /* Ugly hack: type_from_parsed_name is called from
1328                  * System.Type.internal_from_name, which is called most
1329                  * directly from System.Type.GetType(string,bool,bool) but
1330                  * also indirectly from places such as
1331                  * System.Type.GetType(string,func,func) (via
1332                  * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1333                  * so we need to skip over all of those to find the true caller.
1334                  *
1335                  * It would be nice if we had stack marks.
1336                  */
1337                 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1338                 if (!dest)
1339                         dest = m;
1340         }
1341
1342         /*
1343          * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1344          *        causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1345          *        to crash.  This only seems to happen in some strange remoting
1346          *        scenarios and I was unable to figure out what's happening there.
1347          *        Dec 10, 2005 - Martin.
1348          */
1349
1350         if (dest) {
1351                 assembly = dest->klass->image->assembly;
1352                 type_resolve = TRUE;
1353                 rootimage = assembly->image;
1354         } else {
1355                 g_warning (G_STRLOC);
1356         }
1357         *caller_assembly = assembly;
1358
1359         if (info->assembly.name)
1360                 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1361
1362         if (assembly) {
1363                 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1364                 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1365                 if (!is_ok (error))
1366                         goto fail;
1367         }
1368
1369         // XXXX - aleksey -
1370         //  Say we're looking for System.Generic.Dict<int, Local>
1371         //  we FAIL the get type above, because S.G.Dict isn't in assembly->image.  So we drop down here.
1372         //  but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1373         //  is messed up when we go to construct the Local as the type arg...
1374         //
1375         // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1376         // as the root and then even the detour into generics would still not screw us when we went to load Local.
1377         if (!info->assembly.name && !type) {
1378                 /* try mscorlib */
1379                 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1380                 if (!is_ok (error))
1381                         goto fail;
1382         }
1383         if (assembly && !type && type_resolve) {
1384                 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1385                 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1386                 if (!is_ok (error))
1387                         goto fail;
1388         }
1389
1390         if (!type) 
1391                 goto fail;
1392
1393         return mono_type_get_object_handle (mono_domain_get (), type, error);
1394 fail:
1395         return MONO_HANDLE_NEW (MonoReflectionType, NULL);
1396 }
1397
1398 ICALL_EXPORT MonoReflectionTypeHandle
1399 ves_icall_System_Type_internal_from_name (MonoStringHandle name,
1400                                           MonoBoolean throwOnError,
1401                                           MonoBoolean ignoreCase,
1402                                           MonoError *error)
1403 {
1404         mono_error_init (error);
1405         MonoTypeNameParse info;
1406         gboolean parsedOk;
1407         MonoAssembly *caller_assembly;
1408         MonoReflectionTypeHandle type = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1409
1410         char *str = mono_string_handle_to_utf8 (name, error);
1411         if (!is_ok (error))
1412                 goto leave;
1413
1414         parsedOk = mono_reflection_parse_type (str, &info);
1415
1416         /* mono_reflection_parse_type() mangles the string */
1417         if (!parsedOk) {
1418                 mono_reflection_free_type_info (&info);
1419                 if (throwOnError)
1420                         mono_error_set_argument (error, "typeName", "failed parse: %s", str);
1421                 goto leave;
1422         }
1423
1424         MONO_HANDLE_ASSIGN (type, type_from_parsed_name (&info, ignoreCase, &caller_assembly, error));
1425
1426         if (!is_ok (error)) {
1427                 mono_reflection_free_type_info (&info);
1428                 goto leave;
1429         }
1430
1431         if (MONO_HANDLE_IS_NULL (type)) {
1432                 if (throwOnError) {
1433                         char *tname = info.name_space ? g_strdup_printf ("%s.%s", info.name_space, info.name) : g_strdup (info.name);
1434                         char *aname;
1435                         if (info.assembly.name)
1436                                 aname = mono_stringify_assembly_name (&info.assembly);
1437                         else if (caller_assembly)
1438                                 aname = mono_stringify_assembly_name (mono_assembly_get_name (caller_assembly));
1439                         else
1440                                 aname = g_strdup ("");
1441                         mono_error_set_type_load_name (error, tname, aname, "");
1442                 }
1443                 mono_reflection_free_type_info (&info);
1444                 goto leave;
1445         }
1446         
1447 leave:
1448         g_free (str);
1449         if (!is_ok (error)) {
1450                 if (!throwOnError)
1451                         mono_error_cleanup (error);
1452                 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
1453         }
1454
1455         return type;
1456 }
1457
1458
1459 ICALL_EXPORT MonoReflectionTypeHandle
1460 ves_icall_System_Type_internal_from_handle (MonoType *handle, MonoError *error)
1461 {
1462         mono_error_init (error);
1463         MonoDomain *domain = mono_domain_get (); 
1464
1465         return mono_type_get_object_handle (domain, handle, error);
1466 }
1467
1468 ICALL_EXPORT MonoType*
1469 ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
1470 {
1471         return mono_class_get_type (klass);
1472 }
1473
1474 ICALL_EXPORT void
1475 ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array)
1476 {
1477         g_ptr_array_free (ptr_array, TRUE);
1478 }
1479
1480 ICALL_EXPORT void
1481 ves_icall_Mono_SafeStringMarshal_GFree (void *c_str)
1482 {
1483         g_free (c_str);
1484 }
1485
1486 ICALL_EXPORT char*
1487 ves_icall_Mono_SafeStringMarshal_StringToUtf8 (MonoString *s)
1488 {
1489         MonoError error;
1490         char *res = mono_string_to_utf8_checked (s, &error);
1491         mono_error_set_pending_exception (&error);
1492         return res;
1493 }
1494
1495 /* System.TypeCode */
1496 typedef enum {
1497         TYPECODE_EMPTY,
1498         TYPECODE_OBJECT,
1499         TYPECODE_DBNULL,
1500         TYPECODE_BOOLEAN,
1501         TYPECODE_CHAR,
1502         TYPECODE_SBYTE,
1503         TYPECODE_BYTE,
1504         TYPECODE_INT16,
1505         TYPECODE_UINT16,
1506         TYPECODE_INT32,
1507         TYPECODE_UINT32,
1508         TYPECODE_INT64,
1509         TYPECODE_UINT64,
1510         TYPECODE_SINGLE,
1511         TYPECODE_DOUBLE,
1512         TYPECODE_DECIMAL,
1513         TYPECODE_DATETIME,
1514         TYPECODE_STRING = 18
1515 } TypeCode;
1516
1517 ICALL_EXPORT guint32
1518 ves_icall_type_GetTypeCodeInternal (MonoReflectionTypeHandle ref_type, MonoError *error)
1519 {
1520         mono_error_init (error);
1521         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
1522         int t = type->type;
1523
1524         if (type->byref)
1525                 return TYPECODE_OBJECT;
1526
1527 handle_enum:
1528         switch (t) {
1529         case MONO_TYPE_VOID:
1530                 return TYPECODE_OBJECT;
1531         case MONO_TYPE_BOOLEAN:
1532                 return TYPECODE_BOOLEAN;
1533         case MONO_TYPE_U1:
1534                 return TYPECODE_BYTE;
1535         case MONO_TYPE_I1:
1536                 return TYPECODE_SBYTE;
1537         case MONO_TYPE_U2:
1538                 return TYPECODE_UINT16;
1539         case MONO_TYPE_I2:
1540                 return TYPECODE_INT16;
1541         case MONO_TYPE_CHAR:
1542                 return TYPECODE_CHAR;
1543         case MONO_TYPE_PTR:
1544         case MONO_TYPE_U:
1545         case MONO_TYPE_I:
1546                 return TYPECODE_OBJECT;
1547         case MONO_TYPE_U4:
1548                 return TYPECODE_UINT32;
1549         case MONO_TYPE_I4:
1550                 return TYPECODE_INT32;
1551         case MONO_TYPE_U8:
1552                 return TYPECODE_UINT64;
1553         case MONO_TYPE_I8:
1554                 return TYPECODE_INT64;
1555         case MONO_TYPE_R4:
1556                 return TYPECODE_SINGLE;
1557         case MONO_TYPE_R8:
1558                 return TYPECODE_DOUBLE;
1559         case MONO_TYPE_VALUETYPE: {
1560                 MonoClass *klass = type->data.klass;
1561                 
1562                 if (klass->enumtype) {
1563                         t = mono_class_enum_basetype (klass)->type;
1564                         goto handle_enum;
1565                 } else if (mono_is_corlib_image (klass->image)) {
1566                         if (strcmp (klass->name_space, "System") == 0) {
1567                                 if (strcmp (klass->name, "Decimal") == 0)
1568                                         return TYPECODE_DECIMAL;
1569                                 else if (strcmp (klass->name, "DateTime") == 0)
1570                                         return TYPECODE_DATETIME;
1571                         }
1572                 }
1573                 return TYPECODE_OBJECT;
1574         }
1575         case MONO_TYPE_STRING:
1576                 return TYPECODE_STRING;
1577         case MONO_TYPE_SZARRAY:
1578         case MONO_TYPE_ARRAY:
1579         case MONO_TYPE_OBJECT:
1580         case MONO_TYPE_VAR:
1581         case MONO_TYPE_MVAR:
1582         case MONO_TYPE_TYPEDBYREF:
1583                 return TYPECODE_OBJECT;
1584         case MONO_TYPE_CLASS:
1585                 {
1586                         MonoClass *klass =  type->data.klass;
1587                         if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1588                                 if (strcmp (klass->name, "DBNull") == 0)
1589                                         return TYPECODE_DBNULL;
1590                         }
1591                 }
1592                 return TYPECODE_OBJECT;
1593         case MONO_TYPE_GENERICINST:
1594                 return TYPECODE_OBJECT;
1595         default:
1596                 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1597         }
1598         return 0;
1599 }
1600
1601 static MonoType*
1602 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1603 {
1604         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1605                 return mono_class_enum_basetype (type->data.klass);
1606         if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1607                 return mono_class_enum_basetype (type->data.generic_class->container_class);
1608         return type;
1609 }
1610
1611 ICALL_EXPORT guint32
1612 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionTypeHandle ref_type, MonoReflectionTypeHandle ref_c, MonoError *error)
1613 {
1614         mono_error_init (error);
1615
1616         g_assert (!MONO_HANDLE_IS_NULL (ref_type));
1617         
1618         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
1619         MonoClass *klass = mono_class_from_mono_type (type);
1620         MonoType *ctype = MONO_HANDLE_GETVAL (ref_c, type);
1621         MonoClass *klassc = mono_class_from_mono_type (ctype);
1622
1623         if (type->byref ^ ctype->byref)
1624                 return FALSE;
1625
1626         if (type->byref) {
1627                 MonoType *t = mono_type_get_underlying_type_ignore_byref (type);
1628                 MonoType *ot = mono_type_get_underlying_type_ignore_byref (ctype);
1629
1630                 klass = mono_class_from_mono_type (t);
1631                 klassc = mono_class_from_mono_type (ot);
1632
1633                 if (mono_type_is_primitive (t)) {
1634                         return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1635                 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1636                         return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1637                 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1638                         return t->type == ot->type;
1639                 } else {
1640                          if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1641                                  return FALSE;
1642
1643                          if (klass->valuetype)
1644                                 return klass == klassc;
1645                         return klass->valuetype == klassc->valuetype;
1646                 }
1647         }
1648         return mono_class_is_assignable_from (klass, klassc);
1649 }
1650
1651 ICALL_EXPORT guint32
1652 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionTypeHandle ref_type, MonoObjectHandle obj, MonoError *error)
1653 {
1654         mono_error_init (error);
1655         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
1656         MonoClass *klass = mono_class_from_mono_type (type);
1657         mono_class_init_checked (klass, error);
1658         return_val_if_nok (error, FALSE);
1659         MonoObjectHandle inst = mono_object_handle_isinst (obj, klass, error);
1660         return_val_if_nok (error, FALSE);
1661         return !MONO_HANDLE_IS_NULL (inst);
1662 }
1663
1664 ICALL_EXPORT guint32
1665 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionTypeHandle ref_type, MonoError *error)
1666 {
1667         mono_error_init (error);
1668         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
1669         MonoClass *klass = mono_class_from_mono_type (type);
1670         return mono_class_get_flags (klass);
1671 }
1672
1673 ICALL_EXPORT MonoReflectionMarshalAsAttributeHandle
1674 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionFieldHandle field_h, MonoError *error)
1675 {
1676         mono_error_init (error);
1677         MonoDomain *domain = MONO_HANDLE_DOMAIN (field_h);
1678         MonoClassField *field = MONO_HANDLE_GETVAL (field_h, field);
1679         MonoClass *klass = field->parent;
1680
1681         MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1682         if (mono_class_is_gtd (klass) ||
1683             (gklass && gklass->context.class_inst->is_open))
1684                 return MONO_HANDLE_CAST (MonoReflectionMarshalAsAttribute, NULL_HANDLE);
1685
1686         MonoType *ftype = mono_field_get_type (field);
1687         if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1688                 return MONO_HANDLE_CAST (MonoReflectionMarshalAsAttribute, NULL_HANDLE);
1689
1690         MonoMarshalType *info = mono_marshal_load_type_info (klass);
1691
1692         for (int i = 0; i < info->num_fields; ++i) {
1693                 if (info->fields [i].field == field) {
1694                         if (!info->fields [i].mspec)
1695                                 return MONO_HANDLE_CAST (MonoReflectionMarshalAsAttribute, NULL_HANDLE);
1696                         else {
1697                                 return mono_reflection_marshal_as_attribute_from_marshal_spec (domain, klass, info->fields [i].mspec, error);
1698                         }
1699                 }
1700         }
1701
1702         return MONO_HANDLE_CAST (MonoReflectionMarshalAsAttribute, NULL_HANDLE);
1703 }
1704
1705 ICALL_EXPORT MonoReflectionFieldHandle
1706 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type, MonoError *error)
1707 {
1708         MonoClass *klass;
1709
1710         g_assert (handle);
1711
1712         mono_error_init (error);
1713
1714         if (!type) {
1715                 klass = handle->parent;
1716         } else {
1717                 klass = mono_class_from_mono_type (type);
1718
1719                 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1720
1721                 if (!found)
1722                         /* The managed code will throw the exception */
1723                         return MONO_HANDLE_CAST (MonoReflectionField, NULL_HANDLE);
1724         }
1725
1726         return mono_field_get_object_handle (mono_domain_get (), klass, handle, error);
1727 }
1728
1729 ICALL_EXPORT MonoReflectionEventHandle
1730 ves_icall_System_Reflection_EventInfo_internal_from_handle_type (MonoEvent *handle, MonoType *type, MonoError *error)
1731 {
1732         MonoClass *klass;
1733
1734         g_assert (handle);
1735
1736         mono_error_init (error);
1737
1738         if (!type) {
1739                 klass = handle->parent;
1740         } else {
1741                 klass = mono_class_from_mono_type (type);
1742
1743                 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1744                 if (!found)
1745                         /* Managed code will throw an exception */
1746                         return MONO_HANDLE_CAST (MonoReflectionEvent, NULL_HANDLE);
1747         }
1748
1749         return mono_event_get_object_handle (mono_domain_get (), klass, handle, error);
1750 }
1751
1752
1753 ICALL_EXPORT MonoReflectionPropertyHandle
1754 ves_icall_System_Reflection_PropertyInfo_internal_from_handle_type (MonoProperty *handle, MonoType *type, MonoError *error)
1755 {
1756         mono_error_init (error);
1757         MonoClass *klass;
1758
1759         g_assert (handle);
1760
1761         if (!type) {
1762                 klass = handle->parent;
1763         } else {
1764                 klass = mono_class_from_mono_type (type);
1765
1766                 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1767                 if (!found)
1768                         /* Managed code will throw an exception */
1769                         return MONO_HANDLE_CAST (MonoReflectionProperty, NULL_HANDLE);
1770         }
1771
1772         return mono_property_get_object_handle (mono_domain_get (), klass, handle, error);
1773 }
1774
1775 ICALL_EXPORT MonoArrayHandle
1776 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionFieldHandle field_h, MonoBoolean optional, MonoError *error)
1777 {
1778         mono_error_init (error);
1779         MonoClassField *field = MONO_HANDLE_GETVAL (field_h, field);
1780
1781         MonoType *type = mono_field_get_type_checked (field, error);
1782         if (!is_ok (error))
1783                 return MONO_HANDLE_CAST (MonoArray, NULL_HANDLE);
1784
1785         return type_array_from_modifiers (field->parent->image, type, optional, error);
1786 }
1787
1788 ICALL_EXPORT int
1789 vell_icall_get_method_attributes (MonoMethod *method)
1790 {
1791         return method->flags;
1792 }
1793
1794 ICALL_EXPORT void
1795 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1796 {
1797         MonoError error;
1798         MonoReflectionType *rt;
1799         MonoDomain *domain = mono_domain_get ();
1800         MonoMethodSignature* sig;
1801
1802         sig = mono_method_signature_checked (method, &error);
1803         if (!mono_error_ok (&error)) {
1804                 mono_error_set_pending_exception (&error);
1805                 return;
1806         }
1807
1808         rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1809         if (!mono_error_ok (&error)) {
1810                 mono_error_set_pending_exception (&error);
1811                 return;
1812         }
1813
1814         MONO_STRUCT_SETREF (info, parent, rt);
1815
1816         rt = mono_type_get_object_checked (domain, sig->ret, &error);
1817         if (!mono_error_ok (&error)) {
1818                 mono_error_set_pending_exception (&error);
1819                 return;
1820         }
1821
1822         MONO_STRUCT_SETREF (info, ret, rt);
1823
1824         info->attrs = method->flags;
1825         info->implattrs = method->iflags;
1826         if (sig->call_convention == MONO_CALL_DEFAULT)
1827                 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1828         else {
1829                 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1830                         info->callconv = 2;
1831                 else
1832                         info->callconv = 1;
1833         }
1834         info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6); 
1835 }
1836
1837 ICALL_EXPORT MonoArrayHandle
1838 ves_icall_System_Reflection_MonoMethodInfo_get_parameter_info (MonoMethod *method, MonoReflectionMethodHandle member, MonoError *error)
1839 {
1840         mono_error_init (error);
1841         MonoDomain *domain = mono_domain_get (); 
1842
1843         MonoReflectionTypeHandle reftype = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1844         MONO_HANDLE_GET (reftype, member, reftype);
1845         MonoClass *klass = NULL;
1846         if (!MONO_HANDLE_IS_NULL (reftype))
1847                 klass = mono_class_from_mono_type (MONO_HANDLE_GETVAL (reftype, type));
1848         return mono_param_get_objects_internal (domain, method, klass, error);
1849 }
1850
1851 ICALL_EXPORT MonoReflectionMarshalAsAttributeHandle
1852 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method, MonoError *error)
1853 {
1854         mono_error_init (error);
1855         MonoDomain *domain = mono_domain_get (); 
1856         MonoReflectionMarshalAsAttributeHandle res = MONO_HANDLE_NEW (MonoReflectionMarshalAsAttribute, NULL);
1857
1858         MonoMarshalSpec **mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1859         mono_method_get_marshal_info (method, mspecs);
1860
1861         if (mspecs [0]) {
1862                 MONO_HANDLE_ASSIGN (res, mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], error));
1863                 if (!is_ok (error))
1864                         goto leave;
1865         }
1866                 
1867 leave:
1868         for (int i = mono_method_signature (method)->param_count; i >= 0; i--)
1869                 if (mspecs [i])
1870                         mono_metadata_free_marshal_spec (mspecs [i]);
1871         g_free (mspecs);
1872
1873         return res;
1874 }
1875
1876 ICALL_EXPORT gint32
1877 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1878 {
1879         MonoClass *parent = field->field->parent;
1880         mono_class_setup_fields (parent);
1881
1882         return field->field->offset - sizeof (MonoObject);
1883 }
1884
1885 ICALL_EXPORT MonoReflectionTypeHandle
1886 ves_icall_MonoField_GetParentType (MonoReflectionFieldHandle field, MonoBoolean declaring, MonoError *error)
1887 {
1888         mono_error_init (error);
1889         MonoDomain *domain = MONO_HANDLE_DOMAIN (field);
1890         MonoClass *parent;
1891
1892         if (declaring) {
1893                 MonoClassField *f = MONO_HANDLE_GETVAL (field, field);
1894                 parent = f->parent;
1895         } else {
1896                 parent = MONO_HANDLE_GETVAL (field, klass);
1897         }
1898
1899         return mono_type_get_object_handle (domain, &parent->byval_arg, error);
1900 }
1901
1902 ICALL_EXPORT MonoObject *
1903 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1904 {       
1905         MonoError error;
1906         MonoClass *fklass = field->klass;
1907         MonoClassField *cf = field->field;
1908         MonoDomain *domain = mono_object_domain (field);
1909
1910         if (fklass->image->assembly->ref_only) {
1911                 mono_set_pending_exception (mono_get_exception_invalid_operation (
1912                                         "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1913                 return NULL;
1914         }
1915
1916         if (mono_security_core_clr_enabled () &&
1917             !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1918                 mono_error_set_pending_exception (&error);
1919                 return NULL;
1920         }
1921
1922         MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1923         mono_error_set_pending_exception (&error);
1924         return result;
1925 }
1926
1927 ICALL_EXPORT void
1928 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1929 {
1930         MonoError error;
1931         MonoClassField *cf = field->field;
1932         MonoType *type;
1933         gchar *v;
1934
1935         if (field->klass->image->assembly->ref_only) {
1936                 mono_set_pending_exception (mono_get_exception_invalid_operation (
1937                                         "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1938                 return;
1939         }
1940
1941         if (mono_security_core_clr_enabled () &&
1942             !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1943                 mono_error_set_pending_exception (&error);
1944                 return;
1945         }
1946
1947         type = mono_field_get_type_checked (cf, &error);
1948         if (!mono_error_ok (&error)) {
1949                 mono_error_set_pending_exception (&error);
1950                 return;
1951         }
1952
1953         v = (gchar *) value;
1954         if (!type->byref) {
1955                 switch (type->type) {
1956                 case MONO_TYPE_U1:
1957                 case MONO_TYPE_I1:
1958                 case MONO_TYPE_BOOLEAN:
1959                 case MONO_TYPE_U2:
1960                 case MONO_TYPE_I2:
1961                 case MONO_TYPE_CHAR:
1962                 case MONO_TYPE_U:
1963                 case MONO_TYPE_I:
1964                 case MONO_TYPE_U4:
1965                 case MONO_TYPE_I4:
1966                 case MONO_TYPE_R4:
1967                 case MONO_TYPE_U8:
1968                 case MONO_TYPE_I8:
1969                 case MONO_TYPE_R8:
1970                 case MONO_TYPE_VALUETYPE:
1971                 case MONO_TYPE_PTR:
1972                         if (v != NULL)
1973                                 v += sizeof (MonoObject);
1974                         break;
1975                 case MONO_TYPE_STRING:
1976                 case MONO_TYPE_OBJECT:
1977                 case MONO_TYPE_CLASS:
1978                 case MONO_TYPE_ARRAY:
1979                 case MONO_TYPE_SZARRAY:
1980                         /* Do nothing */
1981                         break;
1982                 case MONO_TYPE_GENERICINST: {
1983                         MonoGenericClass *gclass = type->data.generic_class;
1984                         g_assert (!gclass->context.class_inst->is_open);
1985
1986                         if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1987                                 MonoClass *nklass = mono_class_from_mono_type (type);
1988                                 MonoObject *nullable;
1989
1990                                 /* 
1991                                  * Convert the boxed vtype into a Nullable structure.
1992                                  * This is complicated by the fact that Nullables have
1993                                  * a variable structure.
1994                                  */
1995                                 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1996                                 if (!mono_error_ok (&error)) {
1997                                         mono_error_set_pending_exception (&error);
1998                                         return;
1999                                 }
2000
2001                                 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2002
2003                                 v = (gchar *)mono_object_unbox (nullable);
2004                         }
2005                         else 
2006                                 if (gclass->container_class->valuetype && (v != NULL))
2007                                         v += sizeof (MonoObject);
2008                         break;
2009                 }
2010                 default:
2011                         g_error ("type 0x%x not handled in "
2012                                  "ves_icall_FieldInfo_SetValueInternal", type->type);
2013                         return;
2014                 }
2015         }
2016
2017         if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2018                 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2019                 if (!is_ok (&error)) {
2020                         mono_error_set_pending_exception (&error);
2021                         return;
2022                 }
2023                 if (!vtable->initialized) {
2024                         if (!mono_runtime_class_init_full (vtable, &error)) {
2025                                 mono_error_set_pending_exception (&error);
2026                                 return;
2027                         }
2028                 }
2029                 mono_field_static_set_value (vtable, cf, v);
2030         } else {
2031                 mono_field_set_value (obj, cf, v);
2032         }
2033 }
2034
2035 ICALL_EXPORT void
2036 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2037 {
2038         MonoClassField *f;
2039
2040         g_assert (field);
2041         g_assert (obj);
2042         g_assert (value);
2043
2044         f = field->field;
2045         if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2046                 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2047                 return;
2048         }
2049
2050         if (MONO_TYPE_IS_REFERENCE (f->type))
2051                 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2052         else
2053                 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2054 }
2055
2056 ICALL_EXPORT MonoObject *
2057 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2058 {       
2059         MonoObject *o = NULL;
2060         MonoClassField *field = rfield->field;
2061         MonoClass *klass;
2062         MonoDomain *domain = mono_object_domain (rfield);
2063         gchar *v;
2064         MonoTypeEnum def_type;
2065         const char *def_value;
2066         MonoType *t;
2067         MonoError error;
2068
2069         mono_class_init (field->parent);
2070
2071         t = mono_field_get_type_checked (field, &error);
2072         if (!mono_error_ok (&error)) {
2073                 mono_error_set_pending_exception (&error);
2074                 return NULL;
2075         }
2076
2077         if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2078                 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2079                 return NULL;
2080         }
2081
2082         if (image_is_dynamic (field->parent->image)) {
2083                 MonoClass *klass = field->parent;
2084                 int fidx = field - klass->fields;
2085                 MonoFieldDefaultValue *def_values = mono_class_get_field_def_values (klass);
2086
2087                 g_assert (def_values);
2088                 def_type = def_values [fidx].def_type;
2089                 def_value = def_values [fidx].data;
2090
2091                 if (def_type == MONO_TYPE_END) {
2092                         mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2093                         return NULL;
2094                 }
2095         } else {
2096                 def_value = mono_class_get_field_default_value (field, &def_type);
2097                 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2098                 if (!def_value) {
2099                         mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2100                         return NULL;
2101                 }
2102         }
2103
2104         /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2105         switch (def_type) {
2106         case MONO_TYPE_U1:
2107         case MONO_TYPE_I1:
2108         case MONO_TYPE_BOOLEAN:
2109         case MONO_TYPE_U2:
2110         case MONO_TYPE_I2:
2111         case MONO_TYPE_CHAR:
2112         case MONO_TYPE_U:
2113         case MONO_TYPE_I:
2114         case MONO_TYPE_U4:
2115         case MONO_TYPE_I4:
2116         case MONO_TYPE_R4:
2117         case MONO_TYPE_U8:
2118         case MONO_TYPE_I8:
2119         case MONO_TYPE_R8: {
2120                 MonoType *t;
2121
2122                 /* boxed value type */
2123                 t = g_new0 (MonoType, 1);
2124                 t->type = def_type;
2125                 klass = mono_class_from_mono_type (t);
2126                 g_free (t);
2127                 o = mono_object_new_checked (domain, klass, &error);
2128                 if (!mono_error_ok (&error)) {
2129                         mono_error_set_pending_exception (&error);
2130                         return NULL;
2131                 }
2132                 v = ((gchar *) o) + sizeof (MonoObject);
2133                 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2134                 if (mono_error_set_pending_exception (&error))
2135                         return NULL;
2136                 break;
2137         }
2138         case MONO_TYPE_STRING:
2139         case MONO_TYPE_CLASS:
2140                 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2141                 if (mono_error_set_pending_exception (&error))
2142                         return NULL;
2143                 break;
2144         default:
2145                 g_assert_not_reached ();
2146         }
2147
2148         return o;
2149 }
2150
2151 ICALL_EXPORT MonoReflectionTypeHandle
2152 ves_icall_MonoField_ResolveType (MonoReflectionFieldHandle ref_field, MonoError *error)
2153 {
2154         mono_error_init (error);
2155         MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_field);
2156         MonoClassField *field = MONO_HANDLE_GETVAL (ref_field, field);
2157         MonoType *type = mono_field_get_type_checked (field, error);
2158         if (!is_ok (error)) {
2159                 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
2160         }
2161         return mono_type_get_object_handle (domain, type, error);
2162 }
2163
2164 /* From MonoProperty.cs */
2165 typedef enum {
2166         PInfo_Attributes = 1,
2167         PInfo_GetMethod  = 1 << 1,
2168         PInfo_SetMethod  = 1 << 2,
2169         PInfo_ReflectedType = 1 << 3,
2170         PInfo_DeclaringType = 1 << 4,
2171         PInfo_Name = 1 << 5
2172 } PInfo;
2173
2174 ICALL_EXPORT void
2175 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2176 {
2177         MonoError error;
2178         MonoReflectionType *rt;
2179         MonoReflectionMethod *rm;
2180         MonoDomain *domain = mono_object_domain (property); 
2181         const MonoProperty *pproperty = property->property;
2182
2183         if ((req_info & PInfo_ReflectedType) != 0) {
2184                 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2185                 if (mono_error_set_pending_exception (&error))
2186                         return;
2187
2188                 MONO_STRUCT_SETREF (info, parent, rt);
2189         }
2190         if ((req_info & PInfo_DeclaringType) != 0) {
2191                 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2192                 if (mono_error_set_pending_exception (&error))
2193                         return;
2194
2195                 MONO_STRUCT_SETREF (info, declaring_type, rt);
2196         }
2197
2198         if ((req_info & PInfo_Name) != 0)
2199                 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2200
2201         if ((req_info & PInfo_Attributes) != 0)
2202                 info->attrs = pproperty->attrs;
2203
2204         if ((req_info & PInfo_GetMethod) != 0) {
2205                 if (pproperty->get &&
2206                     (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2207                      pproperty->get->klass == property->klass)) {
2208                         rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2209                         if (mono_error_set_pending_exception (&error))
2210                                 return;
2211                 } else {
2212                         rm = NULL;
2213                 }
2214
2215                 MONO_STRUCT_SETREF (info, get, rm);
2216         }
2217         if ((req_info & PInfo_SetMethod) != 0) {
2218                 if (pproperty->set &&
2219                     (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2220                      pproperty->set->klass == property->klass)) {
2221                         rm =  mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2222                         if (mono_error_set_pending_exception (&error))
2223                                 return;
2224                 } else {
2225                         rm = NULL;
2226                 }
2227
2228                 MONO_STRUCT_SETREF (info, set, rm);
2229         }
2230         /* 
2231          * There may be other methods defined for properties, though, it seems they are not exposed 
2232          * in the reflection API 
2233          */
2234 }
2235
2236 ICALL_EXPORT void
2237 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2238 {
2239         MonoError error;
2240         MonoReflectionType *rt;
2241         MonoReflectionMethod *rm;
2242         MonoDomain *domain = mono_object_domain (event); 
2243
2244         rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2245         if (mono_error_set_pending_exception (&error))
2246                 return;
2247
2248         MONO_STRUCT_SETREF (info, reflected_type, rt);
2249
2250         rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2251         if (mono_error_set_pending_exception (&error))
2252                 return;
2253
2254         MONO_STRUCT_SETREF (info, declaring_type, rt);
2255
2256         MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2257         info->attrs = event->event->attrs;
2258
2259         if (event->event->add) {
2260                 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2261                 if (mono_error_set_pending_exception (&error))
2262                         return;
2263         } else {
2264                 rm = NULL;
2265         }
2266
2267         MONO_STRUCT_SETREF (info, add_method, rm);
2268
2269         if (event->event->remove) {
2270                 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2271                 if (mono_error_set_pending_exception (&error))
2272                         return;
2273         } else {
2274                 rm = NULL;
2275         }
2276
2277         MONO_STRUCT_SETREF (info, remove_method, rm);
2278
2279         if (event->event->raise) {
2280                 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2281                 if (mono_error_set_pending_exception (&error))
2282                         return;
2283         } else {
2284                 rm = NULL;
2285         }
2286
2287         MONO_STRUCT_SETREF (info, raise_method, rm);
2288
2289 #ifndef MONO_SMALL_CONFIG
2290         if (event->event->other) {
2291                 int i, n = 0;
2292                 while (event->event->other [n])
2293                         n++;
2294                 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2295                 if (mono_error_set_pending_exception (&error))
2296                         return;
2297                 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2298
2299                 for (i = 0; i < n; i++) {
2300                         rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2301                         if (mono_error_set_pending_exception (&error))
2302                                 return;
2303                         mono_array_setref (info->other_methods, i, rm);
2304                 }
2305         }               
2306 #endif
2307 }
2308
2309 static void
2310 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2311 {
2312         int i;
2313         MonoClass *ic;
2314
2315         mono_class_setup_interfaces (klass, error);
2316         if (!mono_error_ok (error))
2317                 return;
2318
2319         for (i = 0; i < klass->interface_count; i++) {
2320                 ic = klass->interfaces [i];
2321                 g_hash_table_insert (ifaces, ic, ic);
2322
2323                 collect_interfaces (ic, ifaces, error);
2324                 if (!mono_error_ok (error))
2325                         return;
2326         }
2327 }
2328
2329 typedef struct {
2330         MonoArrayHandle iface_array;
2331         MonoGenericContext *context;
2332         MonoError *error;
2333         MonoDomain *domain;
2334         int next_idx;
2335 } FillIfaceArrayData;
2336
2337 static void
2338 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2339 {
2340         HANDLE_FUNCTION_ENTER ();
2341         FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2342         MonoClass *ic = (MonoClass *)key;
2343         MonoType *ret = &ic->byval_arg, *inflated = NULL;
2344         MonoError *error = data->error;
2345
2346         if (!is_ok (error))
2347                 goto leave;
2348
2349         if (data->context && mono_class_is_ginst (ic) && mono_class_get_generic_class (ic)->context.class_inst->is_open) {
2350                 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, error);
2351                 if (!is_ok (error))
2352                         goto leave;
2353         }
2354
2355         MonoReflectionTypeHandle rt = mono_type_get_object_handle (data->domain, ret, error);
2356         if (!is_ok (error))
2357                 goto leave;
2358
2359         MONO_HANDLE_ARRAY_SETREF (data->iface_array, data->next_idx, rt);
2360         data->next_idx++;
2361
2362         if (inflated)
2363                 mono_metadata_free_type (inflated);
2364 leave:
2365         HANDLE_FUNCTION_RETURN ();
2366 }
2367
2368 static guint
2369 get_interfaces_hash (gconstpointer v1)
2370 {
2371         MonoClass *k = (MonoClass*)v1;
2372
2373         return k->type_token;
2374 }
2375
2376 ICALL_EXPORT MonoArrayHandle
2377 ves_icall_RuntimeType_GetInterfaces (MonoReflectionTypeHandle ref_type, MonoError *error)
2378 {
2379         mono_error_init (error);
2380         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2381         MonoClass *klass = mono_class_from_mono_type (type);
2382
2383         GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2384
2385         MonoGenericContext *context = NULL;
2386         if (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst->is_open) {
2387                 context = mono_class_get_context (klass);
2388                 klass = mono_class_get_generic_class (klass)->container_class;
2389         }
2390
2391         for (MonoClass *parent = klass; parent; parent = parent->parent) {
2392                 mono_class_setup_interfaces (parent, error);
2393                 if (!is_ok (error))
2394                         goto fail;
2395                 collect_interfaces (parent, iface_hash, error);
2396                 if (!is_ok (error))
2397                         goto fail;
2398         }
2399
2400         MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
2401
2402         int len = g_hash_table_size (iface_hash);
2403         if (len == 0) {
2404                 g_hash_table_destroy (iface_hash);
2405                 if (!domain->empty_types) {
2406                         domain->empty_types = mono_array_new_cached (domain, mono_defaults.runtimetype_class, 0, error);
2407                         if (!is_ok (error))
2408                                 goto fail;
2409                 }
2410                 return MONO_HANDLE_NEW (MonoArray, domain->empty_types);
2411         }
2412
2413         FillIfaceArrayData data;
2414         data.iface_array = MONO_HANDLE_NEW (MonoArray, mono_array_new_cached (domain, mono_defaults.runtimetype_class, len, error));
2415         if (!is_ok (error))
2416                 goto fail;
2417         data.context = context;
2418         data.error = error;
2419         data.domain = domain;
2420         data.next_idx = 0;
2421
2422         g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2423
2424         if (!is_ok (error))
2425                 goto fail;
2426
2427         g_hash_table_destroy (iface_hash);
2428         return data.iface_array;
2429
2430 fail:
2431         g_hash_table_destroy (iface_hash);
2432         return MONO_HANDLE_CAST (MonoArray, NULL_HANDLE);
2433 }
2434
2435 static gboolean
2436 set_interface_map_data_method_object (MonoDomain *domain, MonoMethod *method, MonoClass *iclass, int ioffset, MonoClass *klass, MonoArrayHandle targets, MonoArrayHandle methods, int i, MonoError *error)
2437 {
2438         HANDLE_FUNCTION_ENTER ();
2439         mono_error_init (error);
2440         MonoReflectionMethodHandle member = mono_method_get_object_handle (domain, method, iclass, error);
2441         if (!is_ok (error))
2442                 goto leave;
2443
2444         MONO_HANDLE_ARRAY_SETREF (methods, i, member);
2445
2446         MONO_HANDLE_ASSIGN (member, mono_method_get_object_handle (domain, klass->vtable [i + ioffset], klass, error));
2447         if (!is_ok (error))
2448                 goto leave;
2449
2450         MONO_HANDLE_ARRAY_SETREF (targets, i, member);
2451                 
2452 leave:
2453         HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
2454 }
2455
2456 ICALL_EXPORT void
2457 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionTypeHandle ref_type, MonoReflectionTypeHandle ref_iface, MonoArrayHandleOut targets, MonoArrayHandleOut methods, MonoError *error)
2458 {
2459         mono_error_init (error);
2460         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2461         MonoClass *klass = mono_class_from_mono_type (type);
2462         MonoType *iface = MONO_HANDLE_GETVAL (ref_iface, type);
2463         MonoClass *iclass = mono_class_from_mono_type (iface);
2464
2465         mono_class_init_checked (klass, error);
2466         return_if_nok (error);
2467         mono_class_init_checked (iclass, error);
2468         return_if_nok (error);
2469
2470         mono_class_setup_vtable (klass);
2471
2472         gboolean variance_used;
2473         int ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2474         if (ioffset == -1)
2475                 return;
2476
2477         int len = mono_class_num_methods (iclass);
2478         MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
2479         MonoArrayHandle targets_arr = mono_array_new_handle (domain, mono_defaults.method_info_class, len, error);
2480         return_if_nok (error);
2481         MONO_HANDLE_ASSIGN (targets, targets_arr);
2482
2483         MonoArrayHandle methods_arr = mono_array_new_handle (domain, mono_defaults.method_info_class, len, error);
2484         return_if_nok (error);
2485         MONO_HANDLE_ASSIGN (methods, methods_arr);
2486
2487         MonoMethod* method;
2488         int i = 0;
2489         gpointer iter = NULL;
2490         while ((method = mono_class_get_methods (iclass, &iter))) {
2491                 if (!set_interface_map_data_method_object (domain, method, iclass, ioffset, klass, targets, methods, i, error))
2492                         return;
2493                 i ++;
2494         }
2495 }
2496
2497 ICALL_EXPORT void
2498 ves_icall_RuntimeType_GetPacking (MonoReflectionTypeHandle ref_type, guint32 *packing, guint32 *size, MonoError *error)
2499 {
2500         mono_error_init (error);
2501         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2502         MonoClass *klass = mono_class_from_mono_type (type);
2503
2504         mono_class_init_checked (klass, error);
2505         if (!is_ok (error))
2506                 return;
2507
2508         if (image_is_dynamic (klass->image)) {
2509                 MonoReflectionTypeBuilderHandle tb = MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref_type);
2510                 *packing = MONO_HANDLE_GETVAL (tb, packing_size);
2511                 *size = MONO_HANDLE_GETVAL (tb, class_size);
2512         } else {
2513                 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2514         }
2515 }
2516
2517 ICALL_EXPORT MonoReflectionTypeHandle
2518 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionTypeHandle ref_type, MonoError *error)
2519 {
2520         mono_error_init (error);
2521
2522         MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
2523         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2524
2525         if (!type->byref && type->type == MONO_TYPE_SZARRAY) {
2526                 return mono_type_get_object_handle (domain, &type->data.klass->byval_arg, error);
2527         }
2528
2529         MonoClass *klass = mono_class_from_mono_type (type);
2530         mono_class_init_checked (klass, error);
2531         if (!is_ok (error))
2532                 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
2533
2534         // GetElementType should only return a type for:
2535         // Array Pointer PassedByRef
2536         if (type->byref)
2537                 return mono_type_get_object_handle (domain, &klass->byval_arg, error);
2538         else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2539                 return mono_type_get_object_handle (domain, &klass->element_class->byval_arg, error);
2540         else if (klass->element_class && type->type == MONO_TYPE_PTR)
2541                 return mono_type_get_object_handle (domain, &klass->element_class->byval_arg, error);
2542         else
2543                 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
2544 }
2545
2546 ICALL_EXPORT MonoReflectionTypeHandle
2547 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionTypeHandle ref_type, MonoError *error)
2548 {
2549         mono_error_init (error);
2550
2551         MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
2552         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2553
2554         if (type->byref)
2555                 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
2556
2557         MonoClass *klass = mono_class_from_mono_type (type);
2558         if (!klass->parent)
2559                 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
2560
2561         return mono_type_get_object_handle (domain, &klass->parent->byval_arg, error);
2562 }
2563
2564 ICALL_EXPORT MonoBoolean
2565 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionTypeHandle ref_type, MonoError *error)
2566 {
2567         mono_error_init (error);
2568         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2569         return type->type == MONO_TYPE_PTR;
2570 }
2571
2572 ICALL_EXPORT MonoBoolean
2573 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionTypeHandle ref_type, MonoError *error)
2574 {
2575         mono_error_init (error);
2576         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2577         return (!type->byref && (((type->type >= MONO_TYPE_BOOLEAN) && (type->type <= MONO_TYPE_R8)) || (type->type == MONO_TYPE_I) || (type->type == MONO_TYPE_U)));
2578 }
2579
2580 ICALL_EXPORT MonoBoolean
2581 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionTypeHandle ref_type, MonoError *error)
2582 {
2583         mono_error_init (error);
2584         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2585         return type->byref;
2586 }
2587
2588 ICALL_EXPORT MonoBoolean
2589 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionTypeHandle ref_type, MonoError *error)
2590 {
2591         mono_error_init (error);
2592         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2593         MonoClass *klass = mono_class_from_mono_type (type);
2594         mono_class_init_checked (klass, error);
2595         if (!is_ok (error))
2596                 return FALSE;
2597
2598         return mono_class_is_com_object (klass);
2599 }
2600
2601 ICALL_EXPORT guint32
2602 ves_icall_reflection_get_token (MonoObjectHandle obj, MonoError *error)
2603 {
2604         mono_error_init (error);
2605         return mono_reflection_get_token_checked (obj, error);
2606 }
2607
2608 ICALL_EXPORT MonoReflectionModuleHandle
2609 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionTypeHandle type, MonoError *error)
2610 {
2611         mono_error_init (error);
2612         MonoDomain *domain = MONO_HANDLE_DOMAIN (type);
2613         MonoType *t = MONO_HANDLE_GETVAL (type, type);
2614         MonoClass *klass = mono_class_from_mono_type (t);
2615         return mono_module_get_object_handle (domain, klass->image, error);
2616 }
2617
2618 ICALL_EXPORT MonoReflectionAssemblyHandle
2619 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionTypeHandle type, MonoError *error)
2620 {
2621         mono_error_init (error);
2622         MonoDomain *domain = mono_domain_get (); 
2623         MonoType *t = MONO_HANDLE_GETVAL (type, type);
2624         MonoClass *klass = mono_class_from_mono_type (t);
2625         return mono_assembly_get_object_handle (domain, klass->image->assembly, error);
2626 }
2627
2628 ICALL_EXPORT MonoReflectionTypeHandle
2629 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionTypeHandle ref_type, MonoError *error)
2630 {
2631         mono_error_init (error);
2632         MonoDomain *domain = mono_domain_get ();
2633         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2634         MonoClass *klass;
2635
2636         if (type->byref)
2637                 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
2638         if (type->type == MONO_TYPE_VAR) {
2639                 MonoGenericContainer *param = mono_type_get_generic_param_owner (type);
2640                 klass = param ? param->owner.klass : NULL;
2641         } else if (type->type == MONO_TYPE_MVAR) {
2642                 MonoGenericContainer *param = mono_type_get_generic_param_owner (type);
2643                 klass = param ? param->owner.method->klass : NULL;
2644         } else {
2645                 klass = mono_class_from_mono_type (type)->nested_in;
2646         }
2647
2648         if (!klass)
2649                 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
2650
2651         return mono_type_get_object_handle (domain, &klass->byval_arg, error);
2652 }
2653
2654 ICALL_EXPORT MonoStringHandle
2655 ves_icall_RuntimeType_get_Name (MonoReflectionTypeHandle reftype, MonoError *error)
2656 {
2657         MonoDomain *domain = mono_domain_get ();
2658         MonoType *type = MONO_HANDLE_RAW(reftype)->type; 
2659         MonoClass *klass = mono_class_from_mono_type (type);
2660
2661         if (type->byref) {
2662                 char *n = g_strdup_printf ("%s&", klass->name);
2663                 MonoStringHandle res = mono_string_new_handle (domain, n, error);
2664
2665                 g_free (n);
2666
2667                 return res;
2668         } else {
2669                 return mono_string_new_handle (domain, klass->name, error);
2670         }
2671 }
2672
2673 ICALL_EXPORT MonoStringHandle
2674 ves_icall_RuntimeType_get_Namespace (MonoReflectionTypeHandle type, MonoError *error)
2675 {
2676         MonoDomain *domain = mono_domain_get (); 
2677         MonoClass *klass = mono_class_from_mono_type_handle (type);
2678
2679         while (klass->nested_in)
2680                 klass = klass->nested_in;
2681
2682         if (klass->name_space [0] == '\0')
2683                 return NULL_HANDLE_STRING;
2684         else
2685                 return mono_string_new_handle (domain, klass->name_space, error);
2686 }
2687
2688 ICALL_EXPORT gint32
2689 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionTypeHandle ref_type, MonoError *error)
2690 {
2691         mono_error_init (error);
2692         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2693
2694         if (type->type != MONO_TYPE_ARRAY && type->type != MONO_TYPE_SZARRAY) {
2695                 mono_error_set_argument (error, "type", "Type must be an array type");
2696                 return 0;
2697         }
2698
2699         MonoClass *klass = mono_class_from_mono_type (type);
2700
2701         return klass->rank;
2702 }
2703
2704 static MonoArrayHandle
2705 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2706 {
2707         return mono_array_new_handle (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2708 }
2709
2710 static gboolean
2711 set_type_object_in_array (MonoDomain *domain, MonoType *type, MonoArrayHandle dest, int i, MonoError *error)
2712 {
2713         HANDLE_FUNCTION_ENTER();
2714         mono_error_init (error);
2715         MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, type, error);
2716         if (!is_ok (error))
2717                 goto leave;
2718
2719         MONO_HANDLE_ARRAY_SETREF (dest, i, rt);
2720
2721 leave:
2722         HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
2723 }
2724
2725 ICALL_EXPORT MonoArrayHandle
2726 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionTypeHandle ref_type, MonoBoolean runtimeTypeArray, MonoError *error)
2727 {
2728         mono_error_init (error);
2729         MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
2730
2731         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2732         MonoClass *klass = mono_class_from_mono_type (type);
2733
2734         MonoArrayHandle res = MONO_HANDLE_NEW (MonoArray, NULL);
2735         if (mono_class_is_gtd (klass)) {
2736                 MonoGenericContainer *container = mono_class_get_generic_container (klass);
2737                 MONO_HANDLE_ASSIGN (res, create_type_array (domain, runtimeTypeArray, container->type_argc, error));
2738                 if (!is_ok (error))
2739                         goto leave;
2740                 for (int i = 0; i < container->type_argc; ++i) {
2741                         MonoClass *pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2742
2743                         if (!set_type_object_in_array (domain, &pklass->byval_arg, res, i, error))
2744                                 goto leave;
2745                 }
2746                 
2747         } else if (mono_class_is_ginst (klass)) {
2748                 MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
2749                 MONO_HANDLE_ASSIGN (res, create_type_array (domain, runtimeTypeArray, inst->type_argc, error));
2750                 if (!is_ok (error))
2751                         goto leave;
2752                 for (int i = 0; i < inst->type_argc; ++i) {
2753                         if (!set_type_object_in_array (domain, inst->type_argv [i], res, i, error))
2754                                 goto leave;
2755                 }
2756         }
2757
2758 leave:
2759         return res;
2760 }
2761
2762 ICALL_EXPORT gboolean
2763 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionTypeHandle ref_type, MonoError *error)
2764 {
2765         mono_error_init (error);
2766
2767         if (!IS_MONOTYPE (MONO_HANDLE_RAW(ref_type)))
2768                 return FALSE;
2769
2770         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2771         if (type->byref)
2772                 return FALSE;
2773
2774         MonoClass *klass = mono_class_from_mono_type (type);
2775         return mono_class_is_gtd (klass);
2776 }
2777
2778 ICALL_EXPORT MonoReflectionTypeHandle
2779 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionTypeHandle ref_type, MonoError *error)
2780 {
2781         mono_error_init (error);
2782         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2783
2784         MonoReflectionTypeHandle ret = MONO_HANDLE_NEW (MonoReflectionType, NULL);
2785
2786         if (type->byref)
2787                 goto leave;
2788
2789         MonoClass *klass = mono_class_from_mono_type (type);
2790
2791         if (mono_class_is_gtd (klass)) {
2792                 /* check this one */
2793                 MONO_HANDLE_ASSIGN (ret, ref_type);
2794                 goto leave;
2795         }
2796         if (mono_class_is_ginst (klass)) {
2797                 MonoClass *generic_class = mono_class_get_generic_class (klass)->container_class;
2798
2799                 guint32 ref_info_handle = mono_class_get_ref_info_handle (generic_class);
2800                 
2801                 if (generic_class->wastypebuilder && ref_info_handle) {
2802                         MonoObjectHandle tb = mono_gchandle_get_target_handle (ref_info_handle);
2803                         g_assert (!MONO_HANDLE_IS_NULL (tb));
2804                         MONO_HANDLE_ASSIGN (ret, tb);
2805                 } else {
2806                         MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
2807                         MONO_HANDLE_ASSIGN (ret, mono_type_get_object_handle (domain, &generic_class->byval_arg, error));
2808                 }
2809         }
2810 leave:
2811         return ret;
2812 }
2813
2814 ICALL_EXPORT MonoReflectionType*
2815 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2816 {
2817         MonoError error;
2818         MonoReflectionType *ret;
2819         MonoClass *klass;
2820         MonoType *geninst, **types;
2821         int i, count;
2822
2823         g_assert (IS_MONOTYPE (type));
2824         mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2825         if (mono_error_set_pending_exception (&error))
2826                 return NULL;
2827
2828         count = mono_array_length (type_array);
2829         types = g_new0 (MonoType *, count);
2830
2831         for (i = 0; i < count; i++) {
2832                 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2833                 types [i] = t->type;
2834         }
2835
2836         geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2837         g_free (types);
2838         if (!geninst) {
2839                 mono_error_set_pending_exception (&error);
2840                 return NULL;
2841         }
2842
2843         klass = mono_class_from_mono_type (geninst);
2844
2845         /*we might inflate to the GTD*/
2846         if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2847                 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2848                 return NULL;
2849         }
2850
2851         ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2852         mono_error_set_pending_exception (&error);
2853
2854         return ret;
2855 }
2856
2857 ICALL_EXPORT gboolean
2858 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionTypeHandle ref_type, MonoError *error)
2859 {
2860         mono_error_init (error);
2861         MonoClass *klass;
2862
2863         if (!IS_MONOTYPE (MONO_HANDLE_RAW (ref_type)))
2864                 return FALSE;
2865
2866         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2867         if (type->byref)
2868                 return FALSE;
2869
2870         klass = mono_class_from_mono_type (type);
2871         return mono_class_is_ginst (klass) || mono_class_is_gtd (klass);
2872 }
2873
2874 ICALL_EXPORT gint32
2875 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionTypeHandle ref_type, MonoError *error)
2876 {
2877         mono_error_init (error);
2878         if (!IS_MONOTYPE_HANDLE (ref_type))
2879                 return -1;
2880         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2881
2882         if (is_generic_parameter (type))
2883                 return mono_type_get_generic_param_num (type);
2884         return -1;
2885 }
2886
2887 ICALL_EXPORT MonoGenericParamInfo *
2888 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionTypeHandle ref_type, MonoError *error)
2889 {
2890         mono_error_init (error);
2891         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2892         return mono_generic_param_info (type->data.generic_param);
2893 }
2894
2895 ICALL_EXPORT MonoBoolean
2896 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionTypeHandle ref_type, MonoError *error)
2897 {
2898         MonoType *type = MONO_HANDLE_GETVAL(ref_type, type);
2899         return is_generic_parameter (type);
2900 }
2901
2902 ICALL_EXPORT MonoReflectionMethodHandle
2903 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionTypeHandle ref_type, 
2904                                                       MonoReflectionMethodHandle generic,
2905                                                       MonoError *error)
2906 {
2907         mono_error_init (error);
2908         MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
2909         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2910         MonoClass *klass = mono_class_from_mono_type (type);
2911                 
2912         mono_class_init_checked (klass, error);
2913         if (!is_ok (error))
2914                 return MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
2915
2916         MonoMethod *generic_method = MONO_HANDLE_GETVAL (generic, method);
2917         
2918         MonoReflectionMethodHandle ret = MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
2919         MonoMethod *method;
2920         gpointer iter = NULL;
2921         while ((method = mono_class_get_methods (klass, &iter))) {
2922                 if (method->token == generic_method->token) {
2923                         ret = mono_method_get_object_handle (domain, method, klass, error);
2924                         if (!is_ok (error))
2925                                 return MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
2926                 }
2927         }
2928
2929         return ret;
2930 }
2931
2932 ICALL_EXPORT MonoReflectionMethodHandle
2933 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionTypeHandle ref_type, MonoError *error)
2934 {
2935         mono_error_init (error);
2936         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2937         MonoReflectionMethodHandle ret = MONO_HANDLE_NEW (MonoReflectionMethod, NULL);
2938
2939         if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2940                 mono_error_set_invalid_operation (error, "DeclaringMethod can only be used on generic arguments");
2941                 goto leave;
2942         }
2943         if (type->type == MONO_TYPE_VAR)
2944                 goto leave;
2945
2946         MonoMethod *method = mono_type_get_generic_param_owner (type)->owner.method;
2947         g_assert (method);
2948
2949         MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
2950
2951         MONO_HANDLE_ASSIGN (ret, mono_method_get_object_handle (domain, method, method->klass, error));
2952 leave:
2953         return ret;
2954 }
2955
2956 ICALL_EXPORT MonoBoolean
2957 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (MonoError *error)
2958 {
2959         mono_error_init (error);
2960         mono_error_set_not_implemented (error, "%s", "");
2961         return FALSE;
2962 }
2963
2964 ICALL_EXPORT MonoBoolean
2965 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (MonoError *error)
2966 {
2967         mono_error_init (error);
2968         mono_error_set_not_implemented (error, "%s", "");
2969         return FALSE;
2970 }
2971
2972 ICALL_EXPORT void
2973 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2974 {
2975         MonoDomain *domain = mono_domain_get ();
2976         MonoImage *image = method->method->klass->image;
2977         MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2978         MonoTableInfo *tables = image->tables;
2979         MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2980         MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2981         guint32 im_cols [MONO_IMPLMAP_SIZE];
2982         guint32 scope_token;
2983         const char *import = NULL;
2984         const char *scope = NULL;
2985
2986         if (image_is_dynamic (image)) {
2987                 MonoReflectionMethodAux *method_aux = 
2988                         (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2989                 if (method_aux) {
2990                         import = method_aux->dllentry;
2991                         scope = method_aux->dll;
2992                 }
2993
2994                 if (!import || !scope) {
2995                         mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2996                         return;
2997                 }
2998         }
2999         else {
3000                 if (piinfo->implmap_idx) {
3001                         mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
3002                         
3003                         piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3004                         import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3005                         scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3006                         scope = mono_metadata_string_heap (image, scope_token);
3007                 }
3008         }
3009         
3010         *flags = piinfo->piflags;
3011         *entry_point = mono_string_new (domain, import);
3012         *dll_name = mono_string_new (domain, scope);
3013 }
3014
3015 ICALL_EXPORT MonoReflectionMethod *
3016 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3017 {
3018         MonoMethodInflated *imethod;
3019         MonoMethod *result;
3020         MonoReflectionMethod *ret = NULL;
3021         MonoError error;
3022
3023         if (method->method->is_generic)
3024                 return method;
3025
3026         if (!method->method->is_inflated)
3027                 return NULL;
3028
3029         imethod = (MonoMethodInflated *) method->method;
3030
3031         result = imethod->declaring;
3032         /* Not a generic method.  */
3033         if (!result->is_generic)
3034                 return NULL;
3035
3036         if (image_is_dynamic (method->method->klass->image)) {
3037                 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3038                 MonoReflectionMethod *res;
3039
3040                 /*
3041                  * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3042                  * the dynamic case as well ?
3043                  */
3044                 mono_image_lock ((MonoImage*)image);
3045                 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3046                 mono_image_unlock ((MonoImage*)image);
3047
3048                 if (res)
3049                         return res;
3050         }
3051
3052         if (imethod->context.class_inst) {
3053                 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3054                 /*Generic methods gets the context of the GTD.*/
3055                 if (mono_class_get_context (klass)) {
3056                         result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3057                         if (!mono_error_ok (&error))
3058                                 goto leave;
3059                 }
3060         }
3061
3062         ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3063 leave:
3064         if (!mono_error_ok (&error))
3065                 mono_error_set_pending_exception (&error);
3066         return ret;
3067 }
3068
3069 ICALL_EXPORT gboolean
3070 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3071 {
3072         return mono_method_signature (method->method)->generic_param_count != 0;
3073 }
3074
3075 ICALL_EXPORT gboolean
3076 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3077 {
3078         return method->method->is_generic;
3079 }
3080
3081 ICALL_EXPORT MonoArray*
3082 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3083 {
3084         MonoError error;
3085         MonoReflectionType *rt;
3086         MonoArray *res;
3087         MonoDomain *domain;
3088         int count, i;
3089
3090         domain = mono_object_domain (method);
3091
3092         if (method->method->is_inflated) {
3093                 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3094
3095                 if (inst) {
3096                         count = inst->type_argc;
3097                         res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3098                         if (mono_error_set_pending_exception (&error))
3099                                 return NULL;
3100
3101                         for (i = 0; i < count; i++) {
3102                                 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3103                                 if (mono_error_set_pending_exception (&error))
3104                                         return NULL;
3105
3106                                 mono_array_setref (res, i, rt);
3107                         }
3108
3109                         return res;
3110                 }
3111         }
3112
3113         count = mono_method_signature (method->method)->generic_param_count;
3114         res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3115         if (mono_error_set_pending_exception (&error))
3116                 return NULL;
3117
3118         for (i = 0; i < count; i++) {
3119                 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3120                 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3121                 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3122
3123                 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3124                 if (mono_error_set_pending_exception (&error))
3125                         return NULL;
3126
3127                 mono_array_setref (res, i, rt);
3128         }
3129
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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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         mono_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 (MonoReflectionMethod *rfield)
5245 {
5246         MonoMethod *method = rfield->method;
5247         return mono_security_core_clr_method_level (method, TRUE);
5248 }
5249
5250 ICALL_EXPORT MonoStringHandle
5251 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssemblyHandle assembly, MonoError *error)
5252 {
5253         mono_error_init (error);
5254         MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly);
5255         MonoAssembly *mass = MONO_HANDLE_GETVAL (assembly, assembly);
5256         gchar *name;
5257
5258         name = mono_stringify_assembly_name (&mass->aname);
5259         MonoStringHandle res = mono_string_new_handle (domain, name, error);
5260         g_free (name);
5261         return res;
5262 }
5263
5264 ICALL_EXPORT MonoAssemblyName *
5265 ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
5266 {
5267         return &mass->aname;
5268 }
5269
5270 ICALL_EXPORT void
5271 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoStringHandle fname, MonoAssemblyName *name, MonoStringHandleOut normalized_codebase, MonoError *error)
5272 {
5273         char *filename;
5274         MonoImageOpenStatus status = MONO_IMAGE_OK;
5275         char *codebase = NULL;
5276         gboolean res;
5277         MonoImage *image;
5278         char *dirname;
5279
5280         mono_error_init (error);
5281
5282         filename = mono_string_handle_to_utf8 (fname, error);
5283         return_if_nok (error);
5284
5285         dirname = g_path_get_dirname (filename);
5286         replace_shadow_path (mono_domain_get (), dirname, &filename);
5287         g_free (dirname);
5288
5289         image = mono_image_open (filename, &status);
5290
5291         if (!image){
5292                 if (status == MONO_IMAGE_IMAGE_INVALID)
5293                         mono_error_set_bad_image_name (error, g_strdup (filename), "%s", "");
5294                 else
5295                         mono_error_set_assembly_load (error, g_strdup (filename), "%s", "");
5296                 g_free (filename);
5297                 return;
5298         }
5299
5300         res = mono_assembly_fill_assembly_name_full (image, name, TRUE);
5301         if (!res) {
5302                 mono_image_close (image);
5303                 g_free (filename);
5304                 mono_error_set_argument (error, "assemblyFile", "The file does not contain a manifest");
5305                 return;
5306         }
5307
5308         if (filename != NULL && *filename != '\0') {
5309                 gchar *result;
5310
5311                 codebase = g_strdup (filename);
5312
5313                 mono_icall_make_platform_path (codebase);
5314
5315                 const gchar *prepend = mono_icall_get_file_path_prefix (codebase);
5316
5317                 result = g_strconcat (prepend, codebase, NULL);
5318                 g_free (codebase);
5319                 codebase = result;
5320         }
5321         MONO_HANDLE_ASSIGN (normalized_codebase, mono_string_new_handle (mono_domain_get (), codebase, error));
5322         g_free (codebase);
5323
5324         mono_image_close (image);
5325         g_free (filename);
5326 }
5327
5328 ICALL_EXPORT MonoBoolean
5329 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssemblyHandle assembly_h,
5330                                                       char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength, MonoError *error)
5331 {
5332         mono_error_init (error);
5333         MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
5334         MonoBoolean result = FALSE;
5335         MonoDeclSecurityEntry entry;
5336
5337         /* SecurityAction.RequestMinimum */
5338         if (mono_declsec_get_assembly_action (assembly, SECURITY_ACTION_REQMIN, &entry)) {
5339                 *minimum = entry.blob;
5340                 *minLength = entry.size;
5341                 result = TRUE;
5342         }
5343         /* SecurityAction.RequestOptional */
5344         if (mono_declsec_get_assembly_action (assembly, SECURITY_ACTION_REQOPT, &entry)) {
5345                 *optional = entry.blob;
5346                 *optLength = entry.size;
5347                 result = TRUE;
5348         }
5349         /* SecurityAction.RequestRefuse */
5350         if (mono_declsec_get_assembly_action (assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5351                 *refused = entry.blob;
5352                 *refLength = entry.size;
5353                 result = TRUE;
5354         }
5355
5356         return result;  
5357 }
5358
5359 static gboolean
5360 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5361 {
5362         guint32 attrs, visibility;
5363         do {
5364                 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5365                 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5366                 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5367                         return FALSE;
5368
5369         } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5370
5371         return TRUE;
5372 }
5373
5374 static void
5375 image_get_type (MonoDomain *domain, MonoImage *image, MonoTableInfo *tdef, int table_idx, int count, MonoArrayHandle res, MonoArrayHandle exceptions, MonoBoolean exportedOnly, MonoError *error)
5376 {
5377         mono_error_init (error);
5378         HANDLE_FUNCTION_ENTER ();
5379         MonoError klass_error;
5380         MonoClass *klass = mono_class_get_checked (image, table_idx | MONO_TOKEN_TYPE_DEF, &klass_error);
5381
5382         if (klass) {
5383                 MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, &klass->byval_arg, error);
5384                 return_if_nok (error);
5385
5386                 MONO_HANDLE_ARRAY_SETREF (res, count, rt);
5387         } else {
5388                 MonoException *ex = mono_error_convert_to_exception (error);
5389                 MONO_HANDLE_ARRAY_SETRAW (exceptions, count, ex);
5390         }
5391         HANDLE_FUNCTION_RETURN ();
5392 }
5393
5394 static MonoArrayHandle
5395 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArrayHandleOut exceptions, MonoBoolean exportedOnly, MonoError *error)
5396 {
5397         MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5398         int i, count;
5399
5400         mono_error_init (error);
5401
5402         /* we start the count from 1 because we skip the special type <Module> */
5403         if (exportedOnly) {
5404                 count = 0;
5405                 for (i = 1; i < tdef->rows; ++i) {
5406                         if (mono_module_type_is_visible (tdef, image, i + 1))
5407                                 count++;
5408                 }
5409         } else {
5410                 count = tdef->rows - 1;
5411         }
5412         MonoArrayHandle res = mono_array_new_handle (domain, mono_defaults.runtimetype_class, count, error);
5413         return_val_if_nok (error, MONO_HANDLE_CAST (MonoArray, NULL_HANDLE));
5414         MONO_HANDLE_ASSIGN (exceptions,  mono_array_new_handle (domain, mono_defaults.exception_class, count, error));
5415         return_val_if_nok (error, MONO_HANDLE_CAST (MonoArray, NULL_HANDLE));
5416         count = 0;
5417         for (i = 1; i < tdef->rows; ++i) {
5418                 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i+1)) {
5419                         image_get_type (domain, image, tdef, i + 1, count, res, exceptions, exportedOnly, error);
5420                         return_val_if_nok (error, MONO_HANDLE_CAST (MonoArray, NULL_HANDLE));
5421                         count++;
5422                 }
5423         }
5424         
5425         return res;
5426 }
5427
5428 static void
5429 append_module_types (MonoDomain *domain, MonoArrayHandleOut res, MonoArrayHandleOut exceptions, MonoImage *image, MonoBoolean exportedOnly, MonoError *error)
5430 {
5431         HANDLE_FUNCTION_ENTER ();
5432         mono_error_init (error);
5433         MonoArrayHandle ex2 = MONO_HANDLE_NEW (MonoArray, NULL);
5434         MonoArrayHandle res2 = mono_module_get_types (domain, image, ex2, exportedOnly, error);
5435         if (!is_ok (error))
5436                 goto leave;
5437
5438         /* Append the new types to the end of the array */
5439         if (mono_array_handle_length (res2) > 0) {
5440                 guint32 len1, len2;
5441
5442                 len1 = mono_array_handle_length (res);
5443                 len2 = mono_array_handle_length (res2);
5444
5445                 MonoArrayHandle res3 = mono_array_new_handle (domain, mono_defaults.runtimetype_class, len1 + len2, error);
5446                 if (!is_ok (error))
5447                         goto leave;
5448
5449                 mono_array_handle_memcpy_refs (res3, 0, res, 0, len1);
5450                 mono_array_handle_memcpy_refs (res3, len1, res2, 0, len2);
5451                 MONO_HANDLE_ASSIGN (res, res3);
5452
5453                 MonoArrayHandle ex3 = mono_array_new_handle (domain, mono_defaults.runtimetype_class, len1 + len2, error);
5454                 if (!is_ok (error))
5455                         goto leave;
5456
5457                 mono_array_handle_memcpy_refs (ex3, 0, exceptions, 0, len1);
5458                 mono_array_handle_memcpy_refs (ex3, len1, ex2, 0, len2);
5459                 MONO_HANDLE_ASSIGN (exceptions, ex3);
5460         }
5461 leave:
5462         HANDLE_FUNCTION_RETURN ();
5463 }
5464
5465 static void
5466 set_class_failure_in_array (MonoArrayHandle exl, int i, MonoClass *klass)
5467 {
5468         HANDLE_FUNCTION_ENTER ();
5469         MonoError unboxed_error;
5470         mono_error_init (&unboxed_error);
5471         mono_error_set_for_class_failure (&unboxed_error, klass);
5472
5473         MonoExceptionHandle exc = MONO_HANDLE_NEW (MonoException, mono_error_convert_to_exception (&unboxed_error));
5474         MONO_HANDLE_ARRAY_SETREF (exl, i, exc);
5475         HANDLE_FUNCTION_RETURN ();
5476 }
5477
5478 ICALL_EXPORT MonoArrayHandle
5479 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssemblyHandle assembly_handle, MonoBoolean exportedOnly, MonoError *error)
5480 {
5481         MonoArrayHandle exceptions = MONO_HANDLE_NEW(MonoArray, NULL);
5482         int i;
5483
5484         MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly_handle);
5485         MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_handle, assembly);
5486
5487         g_assert (!assembly_is_dynamic (assembly));
5488         MonoImage *image = assembly->image;
5489         MonoTableInfo *table = &image->tables [MONO_TABLE_FILE];
5490         MonoArrayHandle res = mono_module_get_types (domain, image, exceptions, exportedOnly, error);
5491         return_val_if_nok (error, MONO_HANDLE_CAST (MonoArray, NULL_HANDLE));
5492
5493         /* Append data from all modules in the assembly */
5494         for (i = 0; i < table->rows; ++i) {
5495                 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5496                         MonoImage *loaded_image = mono_assembly_load_module_checked (image->assembly, i + 1, error);
5497                         return_val_if_nok (error, MONO_HANDLE_CAST (MonoArray, NULL_HANDLE));
5498
5499                         if (loaded_image) {
5500                                 append_module_types (domain, res, exceptions, loaded_image, exportedOnly, error);
5501                                 return_val_if_nok (error, MONO_HANDLE_CAST (MonoArray, NULL_HANDLE));
5502                         }
5503                 }
5504         }
5505
5506         /* the ReflectionTypeLoadException must have all the types (Types property), 
5507          * NULL replacing types which throws an exception. The LoaderException must
5508          * contain all exceptions for NULL items.
5509          */
5510
5511         int len = mono_array_handle_length (res);
5512
5513         int ex_count = 0;
5514         GList *list = NULL;
5515         MonoReflectionTypeHandle t = MONO_HANDLE_NEW (MonoReflectionType, NULL);
5516         for (i = 0; i < len; i++) {
5517                 MONO_HANDLE_ARRAY_GETREF (t, res, i);
5518
5519                 if (!MONO_HANDLE_IS_NULL (t)) {
5520                         MonoClass *klass = mono_type_get_class (MONO_HANDLE_GETVAL (t, type));
5521                         if ((klass != NULL) && mono_class_has_failure (klass)) {
5522                                 /* keep the class in the list */
5523                                 list = g_list_append (list, klass);
5524                                 /* and replace Type with NULL */
5525                                 MONO_HANDLE_ARRAY_SETRAW (res, i, NULL);
5526                         }
5527                 } else {
5528                         ex_count ++;
5529                 }
5530         }
5531
5532         if (list || ex_count) {
5533                 GList *tmp = NULL;
5534                 int j, length = g_list_length (list) + ex_count;
5535
5536                 MonoArrayHandle exl = mono_array_new_handle (domain, mono_defaults.exception_class, length, error);
5537                 if (!is_ok (error)) {
5538                         g_list_free (list);
5539                         return MONO_HANDLE_CAST (MonoArray, NULL_HANDLE);
5540                 }
5541                 /* Types for which mono_class_get_checked () succeeded */
5542                 MonoExceptionHandle exc = MONO_HANDLE_NEW (MonoException, NULL);
5543                 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5544                         set_class_failure_in_array (exl, i, (MonoClass*)tmp->data);
5545                 }
5546                 /* Types for which it don't */
5547                 for (j = 0; j < mono_array_handle_length (exceptions); ++j) {
5548                         MONO_HANDLE_ARRAY_GETREF (exc, exceptions, j);
5549                         if (!MONO_HANDLE_IS_NULL (exc)) {
5550                                 g_assert (i < length);
5551                                 MONO_HANDLE_ARRAY_SETREF (exl, i, exc);
5552                                 i ++;
5553                         }
5554                 }
5555                 g_list_free (list);
5556                 list = NULL;
5557
5558                 MONO_HANDLE_ASSIGN (exc, mono_get_exception_reflection_type_load_checked (res, exl, error));
5559                 if (!is_ok (error)) {
5560                         return MONO_HANDLE_CAST (MonoArray, NULL_HANDLE);
5561                 }
5562                 mono_error_set_exception_handle (error, exc);
5563                 return MONO_HANDLE_CAST (MonoArray, NULL_HANDLE);
5564         }
5565                 
5566         return res;
5567 }
5568
5569 ICALL_EXPORT void
5570 ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname, gboolean free_struct)
5571 {
5572         mono_assembly_name_free (aname);
5573         if (free_struct)
5574                 g_free (aname);
5575 }
5576
5577 ICALL_EXPORT gboolean
5578 ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined)
5579 {
5580         *is_version_definited = *is_token_defined = FALSE;
5581
5582         return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined);
5583 }
5584
5585 ICALL_EXPORT MonoReflectionTypeHandle
5586 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModuleHandle module, MonoError *error)
5587 {
5588         MonoDomain *domain = MONO_HANDLE_DOMAIN (module);
5589         MonoImage *image = MONO_HANDLE_GETVAL (module, image);
5590         MonoClass *klass;
5591
5592         g_assert (image);
5593
5594         MonoReflectionTypeHandle ret = MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
5595
5596         if (image_is_dynamic (image) && ((MonoDynamicImage*)image)->initial_image)
5597                 /* These images do not have a global type */
5598                 goto leave;
5599
5600         klass = mono_class_get_checked (image, 1 | MONO_TOKEN_TYPE_DEF, error);
5601         if (!is_ok (error))
5602                 goto leave;
5603
5604         ret = mono_type_get_object_handle (domain, &klass->byval_arg, error);
5605 leave:
5606         return ret;
5607 }
5608
5609 ICALL_EXPORT void
5610 ves_icall_System_Reflection_Module_Close (MonoReflectionModuleHandle module, MonoError *error)
5611 {
5612         /*if (module->image)
5613                 mono_image_close (module->image);*/
5614 }
5615
5616 ICALL_EXPORT MonoStringHandle
5617 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModuleHandle refmodule, MonoError *error)
5618 {
5619         MonoDomain *domain = MONO_HANDLE_DOMAIN (refmodule);
5620         MonoImage *image = MONO_HANDLE_GETVAL (refmodule, image);
5621
5622         g_assert (image);
5623         return mono_string_new_handle (domain, image->guid, error);
5624 }
5625
5626 #ifndef HOST_WIN32
5627 static inline gpointer
5628 mono_icall_module_get_hinstance (MonoReflectionModuleHandle module)
5629 {
5630         return (gpointer) (-1);
5631 }
5632 #endif /* HOST_WIN32 */
5633
5634 ICALL_EXPORT gpointer
5635 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModuleHandle module, MonoError *error)
5636 {
5637         return mono_icall_module_get_hinstance (module);
5638 }
5639
5640 ICALL_EXPORT void
5641 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine, MonoError *error)
5642 {
5643         if (image_is_dynamic (image)) {
5644                 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5645                 *pe_kind = dyn->pe_kind;
5646                 *machine = dyn->machine;
5647         }
5648         else {
5649                 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5650                 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5651         }
5652 }
5653
5654 ICALL_EXPORT gint32
5655 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image, MonoError *error)
5656 {
5657         return (image->md_version_major << 16) | (image->md_version_minor);
5658 }
5659
5660 ICALL_EXPORT MonoArrayHandle
5661 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModuleHandle module, MonoError *error)
5662 {
5663         mono_error_init (error);
5664
5665         MonoImage *image = MONO_HANDLE_GETVAL (module, image);
5666         MonoDomain *domain = MONO_HANDLE_DOMAIN (module);
5667
5668         if (!image) {
5669                 MonoArrayHandle arr = mono_array_new_handle (domain, mono_defaults.runtimetype_class, 0, error);
5670                 return arr;
5671         } else {
5672                 MonoArrayHandle exceptions = MONO_HANDLE_NEW (MonoArray, NULL);
5673                 MonoArrayHandle res = mono_module_get_types (domain, image, exceptions, FALSE, error);
5674                 return_val_if_nok (error, MONO_HANDLE_CAST(MonoArray, NULL_HANDLE));
5675
5676                 int n = mono_array_handle_length (exceptions);
5677                 MonoExceptionHandle ex = MONO_HANDLE_NEW (MonoException, NULL);
5678                 for (int i = 0; i < n; ++i) {
5679                         MONO_HANDLE_ARRAY_GETREF(ex, exceptions, i);
5680                         if (!MONO_HANDLE_IS_NULL (ex)) {
5681                                 mono_error_set_exception_handle (error, ex);
5682                                 return MONO_HANDLE_CAST(MonoArray, NULL_HANDLE);
5683                         }
5684                 }
5685                 return res;
5686         }
5687 }
5688
5689 static gboolean
5690 mono_memberref_is_method (MonoImage *image, guint32 token)
5691 {
5692         if (!image_is_dynamic (image)) {
5693                 guint32 cols [MONO_MEMBERREF_SIZE];
5694                 const char *sig;
5695                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5696                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5697                 mono_metadata_decode_blob_size (sig, &sig);
5698                 return (*sig != 0x6);
5699         } else {
5700                 MonoError error;
5701                 MonoClass *handle_class;
5702
5703                 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5704                         mono_error_cleanup (&error); /* just probing, ignore error */
5705                         return FALSE;
5706                 }
5707
5708                 return mono_defaults.methodhandle_class == handle_class;
5709         }
5710 }
5711
5712 static MonoGenericInst *
5713 get_generic_inst_from_array_handle (MonoArrayHandle type_args)
5714 {
5715         int type_argc = mono_array_handle_length (type_args);
5716         int size = MONO_SIZEOF_GENERIC_INST + type_argc * sizeof (MonoType *);
5717
5718         MonoGenericInst *ginst = (MonoGenericInst *)g_alloca (size);
5719         memset (ginst, 0, sizeof (MonoGenericInst));
5720         ginst->type_argc = type_argc;
5721         for (int i = 0; i < type_argc; i++) {
5722                 MONO_HANDLE_ARRAY_GETVAL (ginst->type_argv[i], type_args, MonoType*, i);
5723         }
5724         ginst->is_open = FALSE;
5725         for (int i = 0; i < type_argc; i++) {
5726                 if (mono_class_is_open_constructed_type (ginst->type_argv[i])) {
5727                         ginst->is_open = TRUE;
5728                         break;
5729                 }
5730         }
5731
5732         return mono_metadata_get_canonical_generic_inst (ginst);
5733 }
5734
5735 static void
5736 init_generic_context_from_args_handles (MonoGenericContext *context, MonoArrayHandle type_args, MonoArrayHandle method_args)
5737 {
5738         if (!MONO_HANDLE_IS_NULL (type_args)) {
5739                 context->class_inst = get_generic_inst_from_array_handle (type_args);
5740         } else {
5741                 context->class_inst = NULL;
5742         }
5743         if (!MONO_HANDLE_IS_NULL  (method_args)) {
5744                 context->method_inst = get_generic_inst_from_array_handle (method_args);
5745         } else {
5746                 context->method_inst = NULL;
5747         }
5748 }
5749
5750
5751 static MonoType*
5752 module_resolve_type_token (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *resolve_error, MonoError *error)
5753 {
5754         HANDLE_FUNCTION_ENTER ();
5755         mono_error_init (error);
5756         MonoType *result = NULL;
5757         MonoClass *klass;
5758         int table = mono_metadata_token_table (token);
5759         int index = mono_metadata_token_index (token);
5760         MonoGenericContext context;
5761
5762         *resolve_error = ResolveTokenError_Other;
5763
5764         /* Validate token */
5765         if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) && 
5766                 (table != MONO_TABLE_TYPESPEC)) {
5767                 *resolve_error = ResolveTokenError_BadTable;
5768                 goto leave;
5769         }
5770
5771         if (image_is_dynamic (image)) {
5772                 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5773                         MonoError inner_error;
5774                         klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &inner_error);
5775                         mono_error_cleanup (&inner_error);
5776                         result = klass ? &klass->byval_arg : NULL;
5777                         goto leave;
5778                 }
5779
5780                 init_generic_context_from_args_handles (&context, type_args, method_args);
5781                 MonoError inner_error;
5782                 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &inner_error);
5783                 mono_error_cleanup (&inner_error);
5784                 result = klass ? &klass->byval_arg : NULL;
5785                 goto leave;
5786         }
5787
5788         if ((index <= 0) || (index > image->tables [table].rows)) {
5789                 *resolve_error = ResolveTokenError_OutOfRange;
5790                 goto leave;
5791         }
5792
5793         init_generic_context_from_args_handles (&context, type_args, method_args);
5794         klass = mono_class_get_checked (image, token, error);
5795         if (klass)
5796                 klass = mono_class_inflate_generic_class_checked (klass, &context, error);
5797         if (!is_ok (error))
5798                 goto leave;
5799
5800         if (klass)
5801                 result = &klass->byval_arg;
5802 leave:
5803         HANDLE_FUNCTION_RETURN_VAL (result);
5804
5805 }
5806 ICALL_EXPORT MonoType*
5807 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *resolve_error, MonoError *error)
5808 {
5809         return module_resolve_type_token (image, token, type_args, method_args, resolve_error, error);
5810 }
5811
5812 static MonoMethod*
5813 module_resolve_method_token (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *resolve_error, MonoError *error)
5814 {
5815         HANDLE_FUNCTION_ENTER ();
5816         mono_error_init (error);
5817         MonoMethod *method = NULL;
5818         int table = mono_metadata_token_table (token);
5819         int index = mono_metadata_token_index (token);
5820         MonoGenericContext context;
5821
5822         *resolve_error = ResolveTokenError_Other;
5823
5824         /* Validate token */
5825         if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) && 
5826                 (table != MONO_TABLE_MEMBERREF)) {
5827                 *resolve_error = ResolveTokenError_BadTable;
5828                 goto leave;
5829         }
5830
5831         if (image_is_dynamic (image)) {
5832                 if (table == MONO_TABLE_METHOD) {
5833                         MonoError inner_error;
5834                         method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &inner_error);
5835                         mono_error_cleanup (&inner_error);
5836                         goto leave;
5837                 }
5838
5839                 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5840                         *resolve_error = ResolveTokenError_BadTable;
5841                         goto leave;
5842                 }
5843
5844                 init_generic_context_from_args_handles (&context, type_args, method_args);
5845                 MonoError inner_error;
5846                 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &inner_error);
5847                 mono_error_cleanup (&inner_error);
5848                 goto leave;
5849         }
5850
5851         if ((index <= 0) || (index > image->tables [table].rows)) {
5852                 *resolve_error = ResolveTokenError_OutOfRange;
5853                 goto leave;
5854         }
5855         if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5856                 *resolve_error = ResolveTokenError_BadTable;
5857                 goto leave;
5858         }
5859
5860         init_generic_context_from_args_handles (&context, type_args, method_args);
5861         method = mono_get_method_checked (image, token, NULL, &context, error);
5862
5863 leave:
5864         HANDLE_FUNCTION_RETURN_VAL (method);
5865 }
5866
5867 ICALL_EXPORT MonoMethod*
5868 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *resolve_error, MonoError *error)
5869 {
5870         return module_resolve_method_token (image, token, type_args, method_args, resolve_error, error);
5871 }
5872
5873 ICALL_EXPORT MonoString*
5874 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5875 {
5876         MonoError error;
5877         int index = mono_metadata_token_index (token);
5878
5879         *resolve_error = ResolveTokenError_Other;
5880
5881         /* Validate token */
5882         if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5883                 *resolve_error = ResolveTokenError_BadTable;
5884                 return NULL;
5885         }
5886
5887         if (image_is_dynamic (image)) {
5888                 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5889                 mono_error_cleanup (&error);
5890                 return result;
5891         }
5892
5893         if ((index <= 0) || (index >= image->heap_us.size)) {
5894                 *resolve_error = ResolveTokenError_OutOfRange;
5895                 return NULL;
5896         }
5897
5898         /* FIXME: What to do if the index points into the middle of a string ? */
5899
5900         MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
5901         mono_error_set_pending_exception (&error);
5902         return result;
5903 }
5904
5905 static MonoClassField*
5906 module_resolve_field_token (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *resolve_error, MonoError *error)
5907 {
5908         HANDLE_FUNCTION_ENTER ();
5909         MonoClass *klass;
5910         int table = mono_metadata_token_table (token);
5911         int index = mono_metadata_token_index (token);
5912         MonoGenericContext context;
5913         MonoClassField *field = NULL;
5914
5915         mono_error_init (error);
5916         *resolve_error = ResolveTokenError_Other;
5917
5918         /* Validate token */
5919         if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5920                 *resolve_error = ResolveTokenError_BadTable;
5921                 goto leave;
5922         }
5923
5924         if (image_is_dynamic (image)) {
5925                 if (table == MONO_TABLE_FIELD) {
5926                         MonoError inner_error;
5927                         field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &inner_error);
5928                         mono_error_cleanup (&inner_error);
5929                         goto leave;
5930                 }
5931
5932                 if (mono_memberref_is_method (image, token)) {
5933                         *resolve_error = ResolveTokenError_BadTable;
5934                         goto leave;
5935                 }
5936
5937                 init_generic_context_from_args_handles (&context, type_args, method_args);
5938                 MonoError inner_error;
5939                 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &inner_error);
5940                 mono_error_cleanup (&inner_error);
5941                 goto leave;
5942         }
5943
5944         if ((index <= 0) || (index > image->tables [table].rows)) {
5945                 *resolve_error = ResolveTokenError_OutOfRange;
5946                 goto leave;
5947         }
5948         if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5949                 *resolve_error = ResolveTokenError_BadTable;
5950                 goto leave;
5951         }
5952
5953         init_generic_context_from_args_handles (&context, type_args, method_args);
5954         field = mono_field_from_token_checked (image, token, &klass, &context, error);
5955         
5956 leave:
5957         HANDLE_FUNCTION_RETURN_VAL (field);
5958 }
5959
5960 ICALL_EXPORT MonoClassField*
5961 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *resolve_error, MonoError *error)
5962 {
5963         return module_resolve_field_token (image, token, type_args, method_args, resolve_error, error);
5964 }
5965
5966 ICALL_EXPORT MonoObjectHandle
5967 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *error, MonoError *merror)
5968 {
5969         int table = mono_metadata_token_table (token);
5970
5971         mono_error_init (merror);
5972         *error = ResolveTokenError_Other;
5973
5974         switch (table) {
5975         case MONO_TABLE_TYPEDEF:
5976         case MONO_TABLE_TYPEREF:
5977         case MONO_TABLE_TYPESPEC: {
5978                 MonoType *t = module_resolve_type_token (image, token, type_args, method_args, error, merror);
5979                 if (t) {
5980                         return MONO_HANDLE_CAST (MonoObject, mono_type_get_object_handle (mono_domain_get (), t, merror));
5981                 }
5982                 else
5983                         return NULL_HANDLE;
5984         }
5985         case MONO_TABLE_METHOD:
5986         case MONO_TABLE_METHODSPEC: {
5987                 MonoMethod *m = module_resolve_method_token (image, token, type_args, method_args, error, merror);
5988                 if (m) {
5989                         return MONO_HANDLE_CAST (MonoObject, mono_method_get_object_handle (mono_domain_get (), m, m->klass, merror));
5990                 } else
5991                         return NULL_HANDLE;
5992         }               
5993         case MONO_TABLE_FIELD: {
5994                 MonoClassField *f = module_resolve_field_token (image, token, type_args, method_args, error, merror);
5995                 if (f) {
5996                         return MONO_HANDLE_CAST (MonoObject, mono_field_get_object_handle (mono_domain_get (), f->parent, f, merror));
5997                 }
5998                 else
5999                         return NULL_HANDLE;
6000         }
6001         case MONO_TABLE_MEMBERREF:
6002                 if (mono_memberref_is_method (image, token)) {
6003                         MonoMethod *m = module_resolve_method_token (image, token, type_args, method_args, error, merror);
6004                         if (m) {
6005                                 return MONO_HANDLE_CAST (MonoObject, mono_method_get_object_handle (mono_domain_get (), m, m->klass, merror));
6006                         } else
6007                                 return NULL_HANDLE;
6008                 }
6009                 else {
6010                         MonoClassField *f = module_resolve_field_token (image, token, type_args, method_args, error, merror);
6011                         if (f) {
6012                                 return MONO_HANDLE_CAST (MonoObject, mono_field_get_object_handle (mono_domain_get (), f->parent, f, merror));
6013                         }
6014                         else
6015                                 return NULL_HANDLE;
6016                 }
6017                 break;
6018
6019         default:
6020                 *error = ResolveTokenError_BadTable;
6021         }
6022
6023         return NULL_HANDLE;
6024 }
6025
6026 ICALL_EXPORT MonoArrayHandle
6027 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error, MonoError *error)
6028 {
6029         mono_error_init (error);
6030         int table = mono_metadata_token_table (token);
6031         int idx = mono_metadata_token_index (token);
6032         MonoTableInfo *tables = image->tables;
6033         guint32 sig, len;
6034         const char *ptr;
6035
6036         *resolve_error = ResolveTokenError_OutOfRange;
6037
6038         /* FIXME: Support other tables ? */
6039         if (table != MONO_TABLE_STANDALONESIG)
6040                 return MONO_HANDLE_CAST (MonoArray, NULL);
6041
6042         if (image_is_dynamic (image))
6043                 return MONO_HANDLE_CAST (MonoArray, NULL);
6044
6045         if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6046                 return MONO_HANDLE_CAST (MonoArray, NULL);
6047
6048         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6049
6050         ptr = mono_metadata_blob_heap (image, sig);
6051         len = mono_metadata_decode_blob_size (ptr, &ptr);
6052
6053         MonoArrayHandle res = mono_array_new_handle (mono_domain_get (), mono_defaults.byte_class, len, error);
6054         if (!is_ok (error))
6055                 return MONO_HANDLE_CAST (MonoArray, NULL);
6056         uint32_t h;
6057         gpointer array_base = MONO_ARRAY_HANDLE_PIN (res, guint8, 0, &h);
6058         memcpy (array_base, ptr, len);
6059         mono_gchandle_free (h);
6060         return res;
6061 }
6062
6063 ICALL_EXPORT MonoBoolean
6064 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionTypeHandle ref_type, MonoError *error)
6065 {
6066         mono_error_init (error);
6067         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
6068
6069         MonoBoolean res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6070
6071         return res;
6072 }
6073
6074 static void
6075 check_for_invalid_type (MonoClass *klass, MonoError *error)
6076 {
6077         char *name;
6078
6079         mono_error_init (error);
6080
6081         if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6082                 return;
6083
6084         name = mono_type_get_full_name (klass);
6085         mono_error_set_type_load_name (error, name, g_strdup (""), "");
6086 }
6087 ICALL_EXPORT MonoReflectionTypeHandle
6088 ves_icall_RuntimeType_make_array_type (MonoReflectionTypeHandle ref_type, int rank, MonoError *error)
6089 {
6090         mono_error_init (error);
6091         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
6092
6093         MonoClass *klass = mono_class_from_mono_type (type);
6094         check_for_invalid_type (klass, error);
6095         if (!is_ok (error))
6096                 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
6097
6098         MonoClass *aklass;
6099         if (rank == 0) //single dimentional array
6100                 aklass = mono_array_class_get (klass, 1);
6101         else
6102                 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6103
6104         MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
6105         return mono_type_get_object_handle (domain, &aklass->byval_arg, error);
6106 }
6107
6108 ICALL_EXPORT MonoReflectionTypeHandle
6109 ves_icall_RuntimeType_make_byref_type (MonoReflectionTypeHandle ref_type, MonoError *error)
6110 {
6111         mono_error_init (error);
6112         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
6113
6114         MonoClass *klass = mono_class_from_mono_type (type);
6115         mono_class_init_checked (klass, error);
6116         if (!is_ok (error))
6117                 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
6118
6119         check_for_invalid_type (klass, error);
6120         if (!is_ok (error))
6121                 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
6122
6123         MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
6124         return mono_type_get_object_handle (domain, &klass->this_arg, error);
6125 }
6126
6127 ICALL_EXPORT MonoReflectionTypeHandle
6128 ves_icall_RuntimeType_MakePointerType (MonoReflectionTypeHandle ref_type, MonoError *error)
6129 {
6130         mono_error_init (error);
6131         MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
6132         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
6133         MonoClass *klass = mono_class_from_mono_type (type);
6134         mono_class_init_checked (klass, error);
6135         if (!is_ok (error))
6136                 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
6137
6138         check_for_invalid_type (klass, error);
6139         if (!is_ok (error))
6140                 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
6141
6142         MonoClass *pklass = mono_ptr_class_get (type);
6143
6144         return mono_type_get_object_handle (domain, &pklass->byval_arg, error);
6145 }
6146
6147 ICALL_EXPORT MonoObject *
6148 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6149                                                    MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6150 {
6151         MonoError error;
6152         MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6153         MonoObject *delegate;
6154         gpointer func;
6155         MonoMethod *method = info->method;
6156         MonoMethodSignature *sig = mono_method_signature(method);
6157
6158         mono_class_init_checked (delegate_class, &error);
6159         if (mono_error_set_pending_exception (&error))
6160                 return NULL;
6161
6162         if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6163                 /* FIXME improve this exception message */
6164                 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6165                                                  __func__,
6166                                                  "delegate_class->parent == mono_defaults.multicastdelegate_class");
6167                 mono_error_set_pending_exception (&error);
6168                 return NULL;
6169         }
6170
6171         if (mono_security_core_clr_enabled ()) {
6172                 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6173                         if (throwOnBindFailure)
6174                                 mono_error_set_pending_exception (&error);
6175                         else
6176                                 mono_error_cleanup (&error);
6177                         return NULL;
6178                 }
6179         }
6180
6181         if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
6182                 if (!method->is_inflated) {
6183                         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"));
6184                         return NULL;
6185                 }
6186         }
6187
6188         delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6189         if (mono_error_set_pending_exception (&error))
6190                 return NULL;
6191
6192         if (method_is_dynamic (method)) {
6193                 /* Creating a trampoline would leak memory */
6194                 func = mono_compile_method_checked (method, &error);
6195                 if (mono_error_set_pending_exception (&error))
6196                         return NULL;
6197         } else {
6198                 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6199                         method = mono_object_get_virtual_method (target, method);
6200                 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6201                 if (mono_error_set_pending_exception (&error))
6202                         return NULL;
6203                 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6204         }
6205
6206         mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6207         if (mono_error_set_pending_exception (&error))
6208                 return NULL;
6209         return delegate;
6210 }
6211
6212 ICALL_EXPORT MonoMulticastDelegate *
6213 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6214 {
6215         MonoError error;
6216         MonoMulticastDelegate *ret;
6217
6218         g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6219
6220         ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6221         if (mono_error_set_pending_exception (&error))
6222                 return NULL;
6223
6224         ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6225
6226         return ret;
6227 }
6228
6229 ICALL_EXPORT MonoReflectionMethod*
6230 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6231 {
6232         MonoReflectionMethod *ret = NULL;
6233         MonoError error;
6234         ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6235         mono_error_set_pending_exception (&error);
6236         return ret;
6237 }
6238
6239 /* System.Buffer */
6240
6241 static inline gint32 
6242 mono_array_get_byte_length (MonoArray *array)
6243 {
6244         MonoClass *klass;
6245         int length;
6246         int i;
6247
6248         klass = array->obj.vtable->klass;
6249
6250         if (array->bounds == NULL)
6251                 length = array->max_length;
6252         else {
6253                 length = 1;
6254                 for (i = 0; i < klass->rank; ++ i)
6255                         length *= array->bounds [i].length;
6256         }
6257
6258         switch (klass->element_class->byval_arg.type) {
6259         case MONO_TYPE_I1:
6260         case MONO_TYPE_U1:
6261         case MONO_TYPE_BOOLEAN:
6262                 return length;
6263         case MONO_TYPE_I2:
6264         case MONO_TYPE_U2:
6265         case MONO_TYPE_CHAR:
6266                 return length << 1;
6267         case MONO_TYPE_I4:
6268         case MONO_TYPE_U4:
6269         case MONO_TYPE_R4:
6270                 return length << 2;
6271         case MONO_TYPE_I:
6272         case MONO_TYPE_U:
6273                 return length * sizeof (gpointer);
6274         case MONO_TYPE_I8:
6275         case MONO_TYPE_U8:
6276         case MONO_TYPE_R8:
6277                 return length << 3;
6278         default:
6279                 return -1;
6280         }
6281 }
6282
6283 ICALL_EXPORT gint32 
6284 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array) 
6285 {
6286         return mono_array_get_byte_length (array);
6287 }
6288
6289 ICALL_EXPORT gint8 
6290 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx) 
6291 {
6292         return mono_array_get (array, gint8, idx);
6293 }
6294
6295 ICALL_EXPORT void 
6296 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value) 
6297 {
6298         mono_array_set (array, gint8, idx, value);
6299 }
6300
6301 ICALL_EXPORT MonoBoolean
6302 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count) 
6303 {
6304         guint8 *src_buf, *dest_buf;
6305
6306         if (count < 0) {
6307                 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6308                 return FALSE;
6309         }
6310
6311         g_assert (count >= 0);
6312
6313         /* This is called directly from the class libraries without going through the managed wrapper */
6314         MONO_CHECK_ARG_NULL (src, FALSE);
6315         MONO_CHECK_ARG_NULL (dest, FALSE);
6316
6317         /* watch out for integer overflow */
6318         if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6319                 return FALSE;
6320
6321         src_buf = (guint8 *)src->vector + src_offset;
6322         dest_buf = (guint8 *)dest->vector + dest_offset;
6323
6324         if (src != dest)
6325                 memcpy (dest_buf, src_buf, count);
6326         else
6327                 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6328
6329         return TRUE;
6330 }
6331
6332 #ifndef DISABLE_REMOTING
6333 ICALL_EXPORT MonoObjectHandle
6334 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObjectHandle this_obj, MonoStringHandle class_name, MonoError *error)
6335 {
6336         mono_error_init (error);
6337         MonoDomain *domain = MONO_HANDLE_DOMAIN (this_obj);
6338         MonoRealProxyHandle rp = MONO_HANDLE_CAST (MonoRealProxy, this_obj);
6339
6340         MonoObjectHandle res = MONO_HANDLE_NEW (MonoObject, mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, error));
6341         if (!is_ok (error))
6342                 return NULL_HANDLE;
6343
6344         MonoTransparentProxyHandle tp = MONO_HANDLE_CAST (MonoTransparentProxy, res);
6345         
6346         MONO_HANDLE_SET (tp, rp, rp);
6347
6348         MonoReflectionTypeHandle reftype = MONO_HANDLE_NEW (MonoReflectionType, NULL);
6349         MONO_HANDLE_GET (reftype, rp, class_to_proxy);
6350         MonoType *type = MONO_HANDLE_GETVAL (reftype, type);
6351         MonoClass *klass = mono_class_from_mono_type (type);
6352
6353         // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6354         mono_class_setup_vtable (klass);
6355         if (mono_class_has_failure (klass)) {
6356                 mono_error_set_for_class_failure (error, klass);
6357                 return NULL_HANDLE;
6358         }
6359
6360         MonoObjectHandle remoting_obj = mono_object_handle_isinst (this_obj, mono_defaults.iremotingtypeinfo_class, error);
6361         if (!is_ok (error))
6362                 return NULL_HANDLE;
6363         MONO_HANDLE_SETVAL (tp, custom_type_info, MonoBoolean, !MONO_HANDLE_IS_NULL (remoting_obj));
6364
6365         MonoRemoteClass *remote_class = mono_remote_class (domain, class_name, klass, error);
6366         if (!is_ok (error))
6367                 return NULL_HANDLE;
6368         MONO_HANDLE_SETVAL (tp, remote_class, MonoRemoteClass*, remote_class);
6369
6370         MONO_HANDLE_SETVAL (res, vtable, MonoVTable*, mono_remote_class_vtable (domain, remote_class, rp, error));
6371         if (!is_ok (error))
6372                 return NULL_HANDLE;
6373         return res;
6374 }
6375
6376 ICALL_EXPORT MonoReflectionType *
6377 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6378 {
6379         MonoError error;
6380         MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6381         mono_error_set_pending_exception (&error);
6382
6383         return ret;
6384 }
6385 #endif
6386
6387 /* System.Environment */
6388
6389 MonoString*
6390 ves_icall_System_Environment_get_UserName (void)
6391 {
6392         /* using glib is more portable */
6393         return mono_string_new (mono_domain_get (), g_get_user_name ());
6394 }
6395
6396 #ifndef HOST_WIN32
6397 static MonoString *
6398 mono_icall_get_machine_name (void)
6399 {
6400 #if !defined(DISABLE_SOCKETS)
6401         MonoString *result;
6402         char *buf;
6403         int n;
6404 #if defined _SC_HOST_NAME_MAX
6405         n = sysconf (_SC_HOST_NAME_MAX);
6406         if (n == -1)
6407 #endif
6408         n = 512;
6409         buf = g_malloc (n+1);
6410         
6411         if (gethostname (buf, n) == 0){
6412                 buf [n] = 0;
6413                 result = mono_string_new (mono_domain_get (), buf);
6414         } else
6415                 result = NULL;
6416         g_free (buf);
6417         
6418         return result;
6419 #else
6420         return mono_string_new (mono_domain_get (), "mono");
6421 #endif
6422 }
6423 #endif /* !HOST_WIN32 */
6424
6425 ICALL_EXPORT MonoString *
6426 ves_icall_System_Environment_get_MachineName (void)
6427 {
6428         return mono_icall_get_machine_name ();
6429 }
6430
6431 #ifndef HOST_WIN32
6432 static inline int
6433 mono_icall_get_platform (void)
6434 {
6435 #if defined(__MACH__)
6436         /* OSX */
6437         //
6438         // Notice that the value is hidden from user code, and only exposed
6439         // to mscorlib.   This is due to Mono's Unix/MacOS code predating the
6440         // define and making assumptions based on Unix/128/4 values before there
6441         // was a MacOS define.    Lots of code would assume that not-Unix meant
6442         // Windows, but in this case, it would be OSX. 
6443         //
6444         return 6;
6445 #else
6446         /* Unix */
6447         return 4;
6448 #endif
6449 }
6450 #endif /* !HOST_WIN32 */
6451
6452 ICALL_EXPORT int
6453 ves_icall_System_Environment_get_Platform (void)
6454 {
6455         return mono_icall_get_platform ();
6456 }
6457
6458 #ifndef HOST_WIN32
6459 static inline MonoString *
6460 mono_icall_get_new_line (void)
6461 {
6462         return mono_string_new (mono_domain_get (), "\n");
6463 }
6464 #endif /* !HOST_WIN32 */
6465
6466 ICALL_EXPORT MonoString *
6467 ves_icall_System_Environment_get_NewLine (void)
6468 {
6469         return mono_icall_get_new_line ();
6470 }
6471
6472 #ifndef HOST_WIN32
6473 static inline MonoBoolean
6474 mono_icall_is_64bit_os (void)
6475 {
6476 #if SIZEOF_VOID_P == 8
6477         return TRUE;
6478 #else
6479 #if defined(HAVE_SYS_UTSNAME_H)
6480         struct utsname name;
6481
6482         if (uname (&name) >= 0) {
6483                 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6484         }
6485 #endif
6486         return FALSE;
6487 #endif
6488 }
6489 #endif /* !HOST_WIN32 */
6490
6491 ICALL_EXPORT MonoBoolean
6492 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6493 {
6494         return mono_icall_is_64bit_os ();
6495 }
6496
6497 ICALL_EXPORT MonoStringHandle
6498 ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
6499 {
6500         const gchar *value;
6501
6502         if (utf8_name == NULL)
6503                 return NULL_HANDLE_STRING;
6504
6505         value = g_getenv (utf8_name);
6506
6507         if (value == 0)
6508                 return NULL_HANDLE_STRING;
6509         
6510         return mono_string_new_handle (mono_domain_get (), value, error);
6511 }
6512
6513 /*
6514  * There is no standard way to get at environ.
6515  */
6516 #ifndef _MSC_VER
6517 #ifndef __MINGW32_VERSION
6518 #if defined(__APPLE__)
6519 #if defined (TARGET_OSX)
6520 /* Apple defines this in crt_externs.h but doesn't provide that header for 
6521  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
6522  * in fact exist on all implementations (so far) 
6523  */
6524 gchar ***_NSGetEnviron(void);
6525 #define environ (*_NSGetEnviron())
6526 #else
6527 static char *mono_environ[1] = { NULL };
6528 #define environ mono_environ
6529 #endif /* defined (TARGET_OSX) */
6530 #else
6531 extern
6532 char **environ;
6533 #endif
6534 #endif
6535 #endif
6536
6537 ICALL_EXPORT MonoArray *
6538 ves_icall_System_Environment_GetCoomandLineArgs (void)
6539 {
6540         MonoError error;
6541         MonoArray *result = mono_runtime_get_main_args_checked (&error);
6542         mono_error_set_pending_exception (&error);
6543         return result;
6544 }
6545
6546 #ifndef HOST_WIN32
6547 static MonoArray *
6548 mono_icall_get_environment_variable_names (void)
6549 {
6550         MonoError error;
6551         MonoArray *names;
6552         MonoDomain *domain;
6553         MonoString *str;
6554         gchar **e, **parts;
6555         int n;
6556
6557         n = 0;
6558         for (e = environ; *e != 0; ++ e)
6559                 ++ n;
6560
6561         domain = mono_domain_get ();
6562         names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6563         if (mono_error_set_pending_exception (&error))
6564                 return NULL;
6565
6566         n = 0;
6567         for (e = environ; *e != 0; ++ e) {
6568                 parts = g_strsplit (*e, "=", 2);
6569                 if (*parts != 0) {
6570                         str = mono_string_new (domain, *parts);
6571                         mono_array_setref (names, n, str);
6572                 }
6573
6574                 g_strfreev (parts);
6575
6576                 ++ n;
6577         }
6578
6579         return names;
6580 }
6581 #endif /* !HOST_WIN32 */
6582
6583 ICALL_EXPORT MonoArray *
6584 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6585 {
6586         return mono_icall_get_environment_variable_names ();
6587 }
6588
6589 #ifndef HOST_WIN32
6590 static void
6591 mono_icall_set_environment_variable (MonoString *name, MonoString *value)
6592 {
6593         gchar *utf8_name, *utf8_value;
6594         MonoError error;
6595
6596         utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6597         if (mono_error_set_pending_exception (&error))
6598                 return;
6599
6600         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6601                 g_unsetenv (utf8_name);
6602                 g_free (utf8_name);
6603                 return;
6604         }
6605
6606         utf8_value = mono_string_to_utf8_checked (value, &error);
6607         if (!mono_error_ok (&error)) {
6608                 g_free (utf8_name);
6609                 mono_error_set_pending_exception (&error);
6610                 return;
6611         }
6612         g_setenv (utf8_name, utf8_value, TRUE);
6613
6614         g_free (utf8_name);
6615         g_free (utf8_value);
6616 }
6617 #endif /* !HOST_WIN32 */
6618
6619 ICALL_EXPORT void
6620 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6621 {
6622         mono_icall_set_environment_variable (name, value);
6623 }
6624
6625 ICALL_EXPORT void
6626 ves_icall_System_Environment_Exit (int result)
6627 {
6628         mono_environment_exitcode_set (result);
6629
6630 /* FIXME: There are some cleanup hangs that should be worked out, but
6631  * if the program is going to exit, everything will be cleaned up when
6632  * NaCl exits anyway.
6633  */
6634 #ifndef __native_client__
6635         if (!mono_runtime_try_shutdown ())
6636                 mono_thread_exit ();
6637
6638         /* Suspend all managed threads since the runtime is going away */
6639         mono_thread_suspend_all_other_threads ();
6640
6641         mono_runtime_quit ();
6642 #endif
6643
6644         /* we may need to do some cleanup here... */
6645         exit (result);
6646 }
6647
6648 ICALL_EXPORT MonoStringHandle
6649 ves_icall_System_Environment_GetGacPath (MonoError *error)
6650 {
6651         return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error);
6652 }
6653
6654 #ifndef HOST_WIN32
6655 static inline MonoString *
6656 mono_icall_get_windows_folder_path (int folder)
6657 {
6658         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6659         return mono_string_new (mono_domain_get (), "");
6660 }
6661 #endif /* !HOST_WIN32 */
6662
6663 ICALL_EXPORT MonoString*
6664 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6665 {
6666         return mono_icall_get_windows_folder_path (folder);
6667 }
6668
6669 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
6670 static MonoArray *
6671 mono_icall_get_logical_drives (void)
6672 {
6673         MonoError error;
6674         gunichar2 buf [256], *ptr, *dname;
6675         gunichar2 *u16;
6676         guint initial_size = 127, size = 128;
6677         gint ndrives;
6678         MonoArray *result;
6679         MonoString *drivestr;
6680         MonoDomain *domain = mono_domain_get ();
6681         gint len;
6682
6683         buf [0] = '\0';
6684         ptr = buf;
6685
6686         while (size > initial_size) {
6687                 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6688                 if (size > initial_size) {
6689                         if (ptr != buf)
6690                                 g_free (ptr);
6691                         ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6692                         initial_size = size;
6693                         size++;
6694                 }
6695         }
6696
6697         /* Count strings */
6698         dname = ptr;
6699         ndrives = 0;
6700         do {
6701                 while (*dname++);
6702                 ndrives++;
6703         } while (*dname);
6704
6705         dname = ptr;
6706         result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
6707         if (mono_error_set_pending_exception (&error))
6708                 goto leave;
6709
6710         ndrives = 0;
6711         do {
6712                 len = 0;
6713                 u16 = dname;
6714                 while (*u16) { u16++; len ++; }
6715                 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6716                 if (mono_error_set_pending_exception (&error))
6717                         goto leave;
6718
6719                 mono_array_setref (result, ndrives++, drivestr);
6720                 while (*dname++);
6721         } while (*dname);
6722
6723 leave:
6724         if (ptr != buf)
6725                 g_free (ptr);
6726
6727         return result;
6728 }
6729 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
6730
6731 ICALL_EXPORT MonoArray *
6732 ves_icall_System_Environment_GetLogicalDrives (void)
6733 {
6734         return mono_icall_get_logical_drives ();
6735 }
6736
6737 ICALL_EXPORT MonoString *
6738 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6739 {
6740         MonoError error;
6741         gunichar2 volume_name [MAX_PATH + 1];
6742         
6743         if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6744                 return NULL;
6745         MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
6746         mono_error_set_pending_exception (&error);
6747         return result;
6748 }
6749
6750 ICALL_EXPORT MonoStringHandle
6751 ves_icall_System_Environment_InternalGetHome (MonoError *error)
6752 {
6753         return mono_string_new_handle (mono_domain_get (), g_get_home_dir (), error);
6754 }
6755
6756 static const char *encodings [] = {
6757         (char *) 1,
6758                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6759                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6760                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6761         (char *) 2,
6762                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6763                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6764                 "x_unicode_2_0_utf_7",
6765         (char *) 3,
6766                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6767                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6768         (char *) 4,
6769                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6770                 "iso_10646_ucs2",
6771         (char *) 5,
6772                 "unicodefffe", "utf_16be",
6773         (char *) 6,
6774                 "iso_8859_1",
6775         (char *) 0
6776 };
6777
6778 /*
6779  * Returns the internal codepage, if the value of "int_code_page" is
6780  * 1 at entry, and we can not compute a suitable code page number,
6781  * returns the code page as a string
6782  */
6783 ICALL_EXPORT MonoString*
6784 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page) 
6785 {
6786         const char *cset;
6787         const char *p;
6788         char *c;
6789         char *codepage = NULL;
6790         int code;
6791         int want_name = *int_code_page;
6792         int i;
6793         
6794         *int_code_page = -1;
6795
6796         g_get_charset (&cset);
6797         c = codepage = g_strdup (cset);
6798         for (c = codepage; *c; c++){
6799                 if (isascii (*c) && isalpha (*c))
6800                         *c = tolower (*c);
6801                 if (*c == '-')
6802                         *c = '_';
6803         }
6804         /* g_print ("charset: %s\n", cset); */
6805         
6806         /* handle some common aliases */
6807         p = encodings [0];
6808         code = 0;
6809         for (i = 0; p != 0; ){
6810                 if ((gsize) p < 7){
6811                         code = (gssize) p;
6812                         p = encodings [++i];
6813                         continue;
6814                 }
6815                 if (strcmp (p, codepage) == 0){
6816                         *int_code_page = code;
6817                         break;
6818                 }
6819                 p = encodings [++i];
6820         }
6821         
6822         if (strstr (codepage, "utf_8") != NULL)
6823                 *int_code_page |= 0x10000000;
6824         g_free (codepage);
6825         
6826         if (want_name && *int_code_page == -1)
6827                 return mono_string_new (mono_domain_get (), cset);
6828         else
6829                 return NULL;
6830 }
6831
6832 ICALL_EXPORT MonoBoolean
6833 ves_icall_System_Environment_get_HasShutdownStarted (void)
6834 {
6835         if (mono_runtime_is_shutting_down ())
6836                 return TRUE;
6837
6838         if (mono_domain_is_unloading (mono_domain_get ()))
6839                 return TRUE;
6840
6841         return FALSE;
6842 }
6843
6844 #ifndef HOST_WIN32
6845 static inline void
6846 mono_icall_broadcast_setting_change (void)
6847 {
6848         return;
6849 }
6850 #endif /* !HOST_WIN32 */
6851
6852 ICALL_EXPORT void
6853 ves_icall_System_Environment_BroadcastSettingChange (void)
6854 {
6855         mono_icall_broadcast_setting_change ();
6856 }
6857
6858 ICALL_EXPORT
6859 gint32
6860 ves_icall_System_Environment_get_TickCount (void)
6861 {
6862         /* this will overflow after ~24 days */
6863         return (gint32) (mono_msec_boottime () & 0xffffffff);
6864 }
6865
6866 ICALL_EXPORT gint32
6867 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6868 {
6869         return 9;
6870 }
6871
6872 #ifndef DISABLE_REMOTING
6873 ICALL_EXPORT MonoBoolean
6874 ves_icall_IsTransparentProxy (MonoObject *proxy)
6875 {
6876         if (!proxy)
6877                 return 0;
6878
6879         if (mono_object_is_transparent_proxy (proxy))
6880                 return 1;
6881
6882         return 0;
6883 }
6884
6885 ICALL_EXPORT MonoReflectionMethod *
6886 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6887         MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6888 {
6889         MonoReflectionMethod *ret = NULL;
6890         MonoError error;
6891
6892         MonoClass *klass;
6893         MonoMethod *method;
6894         MonoMethod **vtable;
6895         MonoMethod *res = NULL;
6896
6897         MONO_CHECK_ARG_NULL (rtype, NULL);
6898         MONO_CHECK_ARG_NULL (rmethod, NULL);
6899
6900         method = rmethod->method;
6901         klass = mono_class_from_mono_type (rtype->type);
6902         mono_class_init_checked (klass, &error);
6903         if (mono_error_set_pending_exception (&error))
6904                 return NULL;
6905
6906         if (MONO_CLASS_IS_INTERFACE (klass))
6907                 return NULL;
6908
6909         if (method->flags & METHOD_ATTRIBUTE_STATIC)
6910                 return NULL;
6911
6912         if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6913                 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6914                         return rmethod;
6915                 else
6916                         return NULL;
6917         }
6918
6919         mono_class_setup_vtable (klass);
6920         vtable = klass->vtable;
6921
6922         if (mono_class_is_interface (method->klass)) {
6923                 gboolean variance_used = FALSE;
6924                 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6925                 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6926                 if (offs >= 0)
6927                         res = vtable [offs + method->slot];
6928         } else {
6929                 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6930                         return NULL;
6931
6932                 if (method->slot != -1)
6933                         res = vtable [method->slot];
6934         }
6935
6936         if (!res)
6937                 return NULL;
6938
6939         ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
6940         mono_error_set_pending_exception (&error);
6941         return ret;
6942 }
6943
6944 ICALL_EXPORT void
6945 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6946 {
6947         MonoError error;
6948         MonoClass *klass;
6949         MonoVTable* vtable;
6950
6951         klass = mono_class_from_mono_type (type->type);
6952         vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
6953         if (!is_ok (&error)) {
6954                 mono_error_set_pending_exception (&error);
6955                 return;
6956         }
6957
6958         mono_vtable_set_is_remote (vtable, enable);
6959 }
6960
6961 #else /* DISABLE_REMOTING */
6962
6963 ICALL_EXPORT void
6964 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6965 {
6966         g_assert_not_reached ();
6967 }
6968
6969 #endif
6970
6971 ICALL_EXPORT MonoObject *
6972 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6973 {
6974         MonoError error;
6975         MonoClass *klass;
6976         MonoDomain *domain;
6977         MonoObject *ret;
6978         
6979         domain = mono_object_domain (type);
6980         klass = mono_class_from_mono_type (type->type);
6981         mono_class_init_checked (klass, &error);
6982         if (mono_error_set_pending_exception (&error))
6983                 return NULL;
6984
6985         if (MONO_CLASS_IS_INTERFACE (klass) || mono_class_is_abstract (klass)) {
6986                 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6987                 return NULL;
6988         }
6989
6990         if (klass->rank >= 1) {
6991                 g_assert (klass->rank == 1);
6992                 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
6993                 mono_error_set_pending_exception (&error);
6994                 return ret;
6995         } else {
6996                 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
6997                 if (!is_ok (&error)) {
6998                         mono_error_set_pending_exception (&error);
6999                         return NULL;
7000                 }
7001                 /* Bypass remoting object creation check */
7002                 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7003                 mono_error_set_pending_exception (&error);
7004
7005                 return ret;
7006         }
7007 }
7008
7009 ICALL_EXPORT MonoStringHandle
7010 ves_icall_System_IO_get_temp_path (MonoError *error)
7011 {
7012         return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error);
7013 }
7014
7015 #ifndef PLATFORM_NO_DRIVEINFO
7016 ICALL_EXPORT MonoBoolean
7017 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7018                                                 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7019                                                 gint32 *error)
7020 {
7021         gboolean result;
7022         ULARGE_INTEGER wapi_free_bytes_avail;
7023         ULARGE_INTEGER wapi_total_number_of_bytes;
7024         ULARGE_INTEGER wapi_total_number_of_free_bytes;
7025
7026         *error = ERROR_SUCCESS;
7027         result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7028                                      &wapi_total_number_of_free_bytes);
7029
7030         if (result) {
7031                 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7032                 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7033                 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7034         } else {
7035                 *free_bytes_avail = 0;
7036                 *total_number_of_bytes = 0;
7037                 *total_number_of_free_bytes = 0;
7038                 *error = GetLastError ();
7039         }
7040
7041         return result;
7042 }
7043
7044 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
7045 static inline guint32
7046 mono_icall_drive_info_get_drive_type (MonoString *root_path_name)
7047 {
7048         return GetDriveType (mono_string_chars (root_path_name));
7049 }
7050 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
7051
7052 ICALL_EXPORT guint32
7053 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7054 {
7055         return mono_icall_drive_info_get_drive_type (root_path_name);
7056 }
7057
7058 #endif /* PLATFORM_NO_DRIVEINFO */
7059
7060 ICALL_EXPORT gpointer
7061 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7062 {
7063         MonoError error;
7064         gpointer result = mono_compile_method_checked (method, &error);
7065         mono_error_set_pending_exception (&error);
7066         return result;
7067 }
7068
7069 ICALL_EXPORT MonoString *
7070 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7071 {
7072         MonoString *mcpath;
7073         gchar *path;
7074
7075         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7076
7077         mono_icall_make_platform_path (path);
7078
7079         mcpath = mono_string_new (mono_domain_get (), path);
7080         g_free (path);
7081
7082         return mcpath;
7083 }
7084
7085 /* this is an icall */
7086 static MonoString *
7087 get_bundled_app_config (void)
7088 {
7089         MonoError error;
7090         const gchar *app_config;
7091         MonoDomain *domain;
7092         MonoString *file;
7093         gchar *config_file_name, *config_file_path;
7094         gsize len, config_file_path_length, config_ext_length;
7095         gchar *module;
7096
7097         domain = mono_domain_get ();
7098         file = domain->setup->configuration_file;
7099         if (!file || file->length == 0)
7100                 return NULL;
7101
7102         // Retrieve config file and remove the extension
7103         config_file_name = mono_string_to_utf8_checked (file, &error);
7104         if (mono_error_set_pending_exception (&error))
7105                 return NULL;
7106         config_file_path = mono_portability_find_file (config_file_name, TRUE);
7107         if (!config_file_path)
7108                 config_file_path = config_file_name;
7109
7110         config_file_path_length = strlen (config_file_path);
7111         config_ext_length = strlen (".config");
7112         if (config_file_path_length <= config_ext_length)
7113                 return NULL;
7114
7115         len = config_file_path_length - config_ext_length;
7116         module = (gchar *)g_malloc0 (len + 1);
7117         memcpy (module, config_file_path, len);
7118         // Get the config file from the module name
7119         app_config = mono_config_string_for_assembly_file (module);
7120         // Clean-up
7121         g_free (module);
7122         if (config_file_name != config_file_path)
7123                 g_free (config_file_name);
7124         g_free (config_file_path);
7125
7126         if (!app_config)
7127                 return NULL;
7128
7129         return mono_string_new (mono_domain_get (), app_config);
7130 }
7131
7132 static MonoStringHandle
7133 get_bundled_machine_config (MonoError *error)
7134 {
7135         const gchar *machine_config;
7136
7137         machine_config = mono_get_machine_config ();
7138
7139         if (!machine_config)
7140                 return NULL_HANDLE_STRING;
7141
7142         return mono_string_new_handle (mono_domain_get (), machine_config, error);
7143 }
7144
7145 ICALL_EXPORT MonoStringHandle
7146 ves_icall_System_Environment_get_bundled_machine_config (MonoError *error)
7147 {
7148         return get_bundled_machine_config (error);
7149 }
7150
7151
7152 ICALL_EXPORT MonoStringHandle
7153 ves_icall_System_Configuration_DefaultConfig_get_bundled_machine_config (MonoError *error)
7154 {
7155         return get_bundled_machine_config (error);
7156 }
7157
7158 ICALL_EXPORT MonoStringHandle
7159 ves_icall_System_Configuration_InternalConfigurationHost_get_bundled_machine_config (MonoError *error)
7160 {
7161         return get_bundled_machine_config (error);
7162 }
7163
7164
7165 ICALL_EXPORT MonoString *
7166 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7167 {
7168         MonoString *ipath;
7169         gchar *path;
7170
7171         path = g_path_get_dirname (mono_get_config_dir ());
7172
7173         mono_icall_make_platform_path (path);
7174
7175         ipath = mono_string_new (mono_domain_get (), path);
7176         g_free (path);
7177
7178         return ipath;
7179 }
7180
7181 ICALL_EXPORT gboolean
7182 ves_icall_get_resources_ptr (MonoReflectionAssemblyHandle assembly, gpointer *result, gint32 *size, MonoError *error)
7183 {
7184         mono_error_init (error);
7185         MonoPEResourceDataEntry *entry;
7186         MonoImage *image;
7187
7188         if (!assembly || !result || !size)
7189                 return FALSE;
7190
7191         *result = NULL;
7192         *size = 0;
7193         MonoAssembly *assm = MONO_HANDLE_GETVAL (assembly, assembly);
7194         image = assm->image;
7195         entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7196         if (!entry)
7197                 return FALSE;
7198
7199         *result = mono_image_rva_map (image, entry->rde_data_offset);
7200         if (!(*result)) {
7201                 g_free (entry);
7202                 return FALSE;
7203         }
7204         *size = entry->rde_size;
7205         g_free (entry);
7206         return TRUE;
7207 }
7208
7209 ICALL_EXPORT MonoBoolean
7210 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7211 {
7212         return mono_is_debugger_attached ();
7213 }
7214
7215 ICALL_EXPORT MonoBoolean
7216 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7217 {
7218         if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7219                 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7220         else
7221                 return FALSE;
7222 }
7223
7224 ICALL_EXPORT void
7225 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7226 {
7227         if (mono_get_runtime_callbacks ()->debug_log)
7228                 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7229 }
7230
7231 #ifndef HOST_WIN32
7232 static inline void
7233 mono_icall_write_windows_debug_string (MonoString *message)
7234 {
7235         g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7236 }
7237 #endif /* !HOST_WIN32 */
7238
7239 ICALL_EXPORT void
7240 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7241 {
7242         mono_icall_write_windows_debug_string (message);
7243 }
7244
7245 /* Only used for value types */
7246 ICALL_EXPORT MonoObjectHandle
7247 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionTypeHandle ref_type, MonoError *error)
7248 {
7249         mono_error_init (error);
7250         MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
7251         MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
7252         MonoClass *klass = mono_class_from_mono_type (type);
7253
7254         mono_class_init_checked (klass, error);
7255         if (!is_ok (error))
7256                 return NULL_HANDLE;
7257
7258         if (mono_class_is_nullable (klass))
7259                 /* No arguments -> null */
7260                 return NULL_HANDLE;
7261
7262         return MONO_HANDLE_NEW (MonoObject, mono_object_new_checked (domain, klass, error));
7263 }
7264
7265 ICALL_EXPORT MonoReflectionMethod *
7266 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7267 {
7268         MonoReflectionMethod *ret = NULL;
7269         MonoError error;
7270
7271         MonoClass *klass, *parent;
7272         MonoGenericContext *generic_inst = NULL;
7273         MonoMethod *method = m->method;
7274         MonoMethod *result = NULL;
7275         int slot;
7276
7277         if (method->klass == NULL)
7278                 return m;
7279
7280         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7281             MONO_CLASS_IS_INTERFACE (method->klass) ||
7282             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7283                 return m;
7284
7285         slot = mono_method_get_vtable_slot (method);
7286         if (slot == -1)
7287                 return m;
7288
7289         klass = method->klass;
7290         if (mono_class_is_ginst (klass)) {
7291                 generic_inst = mono_class_get_context (klass);
7292                 klass = mono_class_get_generic_class (klass)->container_class;
7293         }
7294
7295 retry:
7296         if (definition) {
7297                 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7298                 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7299                         /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7300                            or klass is the generic container class and generic_inst is the instantiation.
7301
7302                            when we go to the parent, if the parent is an open constructed type, we need to
7303                            replace the type parameters by the definitions from the generic_inst, and then take it
7304                            apart again into the klass and the generic_inst.
7305
7306                            For cases like this:
7307                            class C<T> : B<T, int> {
7308                                public override void Foo () { ... }
7309                            }
7310                            class B<U,V> : A<HashMap<U,V>> {
7311                                public override void Foo () { ... }
7312                            }
7313                            class A<X> {
7314                                public virtual void Foo () { ... }
7315                            }
7316
7317                            if at each iteration the parent isn't open, we can skip inflating it.  if at some
7318                            iteration the parent isn't generic (after possible inflation), we set generic_inst to
7319                            NULL;
7320                         */
7321                         MonoGenericContext *parent_inst = NULL;
7322                         if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7323                                 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7324                                 if (!mono_error_ok (&error)) {
7325                                         mono_error_set_pending_exception (&error);
7326                                         return NULL;
7327                                 }
7328                         }
7329                         if (mono_class_is_ginst (parent)) {
7330                                 parent_inst = mono_class_get_context (parent);
7331                                 parent = mono_class_get_generic_class (parent)->container_class;
7332                         }
7333
7334                         mono_class_setup_vtable (parent);
7335                         if (parent->vtable_size <= slot)
7336                                 break;
7337                         klass = parent;
7338                         generic_inst = parent_inst;
7339                 }
7340         } else {
7341                 klass = klass->parent;
7342                 if (!klass)
7343                         return m;
7344                 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7345                         klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7346                         if (!mono_error_ok (&error)) {
7347                                 mono_error_set_pending_exception (&error);
7348                                 return NULL;
7349                         }
7350
7351                         generic_inst = NULL;
7352                 }
7353                 if (mono_class_is_ginst (klass)) {
7354                         generic_inst = mono_class_get_context (klass);
7355                         klass = mono_class_get_generic_class (klass)->container_class;
7356                 }
7357
7358         }
7359
7360         if (generic_inst) {
7361                 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7362                 if (!mono_error_ok (&error)) {
7363                         mono_error_set_pending_exception (&error);
7364                         return NULL;
7365                 }
7366         }
7367
7368         if (klass == method->klass)
7369                 return m;
7370
7371         /*This is possible if definition == FALSE.
7372          * Do it here to be really sure we don't read invalid memory.
7373          */
7374         if (slot >= klass->vtable_size)
7375                 return m;
7376
7377         mono_class_setup_vtable (klass);
7378
7379         result = klass->vtable [slot];
7380         if (result == NULL) {
7381                 /* It is an abstract method */
7382                 gboolean found = FALSE;
7383                 gpointer iter = NULL;
7384                 while ((result = mono_class_get_methods (klass, &iter))) {
7385                         if (result->slot == slot) {
7386                                 found = TRUE;
7387                                 break;
7388                         }
7389                 }
7390                 /* found might be FALSE if we looked in an abstract class
7391                  * that doesn't override an abstract method of its
7392                  * parent: 
7393                  *   abstract class Base {
7394                  *     public abstract void Foo ();
7395                  *   }
7396                  *   abstract class Derived : Base { }
7397                  *   class Child : Derived {
7398                  *     public override void Foo () { }
7399                  *  }
7400                  *
7401                  *  if m was Child.Foo and we ask for the base method,
7402                  *  then we get here with klass == Derived and found == FALSE
7403                  */
7404                 /* but it shouldn't be the case that if we're looking
7405                  * for the definition and didn't find a result; the
7406                  * loop above should've taken us as far as we could
7407                  * go! */
7408                 g_assert (!(definition && !found));
7409                 if (!found)
7410                         goto retry;
7411         }
7412
7413         g_assert (result != NULL);
7414
7415         ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7416         mono_error_set_pending_exception (&error);
7417         return ret;
7418 }
7419
7420 ICALL_EXPORT MonoString*
7421 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7422 {
7423         MonoMethod *method = m->method;
7424
7425         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7426         return m->name;
7427 }
7428
7429 ICALL_EXPORT void
7430 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7431 {
7432         iter->sig = *(MonoMethodSignature**)argsp;
7433         
7434         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7435         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7436
7437         iter->next_arg = 0;
7438         /* FIXME: it's not documented what start is exactly... */
7439         if (start) {
7440                 iter->args = start;
7441         } else {
7442                 iter->args = argsp + sizeof (gpointer);
7443         }
7444         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7445
7446         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7447 }
7448
7449 ICALL_EXPORT MonoTypedRef
7450 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7451 {
7452         guint32 i, arg_size;
7453         gint32 align;
7454         MonoTypedRef res;
7455
7456         i = iter->sig->sentinelpos + iter->next_arg;
7457
7458         g_assert (i < iter->sig->param_count);
7459
7460         res.type = iter->sig->params [i];
7461         res.klass = mono_class_from_mono_type (res.type);
7462         arg_size = mono_type_stack_size (res.type, &align);
7463 #if defined(__arm__) || defined(__mips__)
7464         iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7465 #endif
7466         res.value = iter->args;
7467 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7468         /* Values are stored as 8 byte register sized objects, but 'value'
7469          * is dereferenced as a pointer in other routines.
7470          */
7471         res.value = (char*)res.value + 4;
7472 #endif
7473 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7474         if (arg_size <= sizeof (gpointer)) {
7475                 int dummy;
7476                 int padding = arg_size - mono_type_size (res.type, &dummy);
7477                 res.value = (guint8*)res.value + padding;
7478         }
7479 #endif
7480         iter->args = (char*)iter->args + arg_size;
7481         iter->next_arg++;
7482
7483         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7484
7485         return res;
7486 }
7487
7488 ICALL_EXPORT MonoTypedRef
7489 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7490 {
7491         guint32 i, arg_size;
7492         gint32 align;
7493         MonoTypedRef res;
7494
7495         i = iter->sig->sentinelpos + iter->next_arg;
7496
7497         g_assert (i < iter->sig->param_count);
7498
7499         while (i < iter->sig->param_count) {
7500                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7501                         continue;
7502                 res.type = iter->sig->params [i];
7503                 res.klass = mono_class_from_mono_type (res.type);
7504                 /* FIXME: endianess issue... */
7505                 arg_size = mono_type_stack_size (res.type, &align);
7506 #if defined(__arm__) || defined(__mips__)
7507                 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7508 #endif
7509                 res.value = iter->args;
7510                 iter->args = (char*)iter->args + arg_size;
7511                 iter->next_arg++;
7512                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7513                 return res;
7514         }
7515         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7516
7517         res.type = NULL;
7518         res.value = NULL;
7519         res.klass = NULL;
7520         return res;
7521 }
7522
7523 ICALL_EXPORT MonoType*
7524 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7525 {
7526         gint i;
7527         
7528         i = iter->sig->sentinelpos + iter->next_arg;
7529
7530         g_assert (i < iter->sig->param_count);
7531
7532         return iter->sig->params [i];
7533 }
7534
7535 ICALL_EXPORT MonoObject*
7536 mono_TypedReference_ToObject (MonoTypedRef* tref)
7537 {
7538         MonoError error;
7539         MonoObject *result = NULL;
7540         if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7541                 MonoObject** objp = (MonoObject **)tref->value;
7542                 return *objp;
7543         }
7544
7545         result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7546         mono_error_set_pending_exception (&error);
7547         return result;
7548 }
7549
7550 ICALL_EXPORT MonoTypedRef
7551 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7552 {
7553         MonoTypedRef res;
7554         MonoReflectionField *f;
7555         MonoClass *klass;
7556         MonoType *ftype = NULL;
7557         guint8 *p = NULL;
7558         int i;
7559
7560         memset (&res, 0, sizeof (res));
7561
7562         g_assert (fields);
7563         g_assert (mono_array_length (fields) > 0);
7564
7565         klass = target->vtable->klass;
7566
7567         for (i = 0; i < mono_array_length (fields); ++i) {
7568                 f = mono_array_get (fields, MonoReflectionField*, i);
7569                 if (f == NULL) {
7570                         mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7571                         return res;
7572                 }
7573                 if (f->field->parent != klass) {
7574                         mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7575                         return res;
7576                 }
7577                 if (i == 0)
7578                         p = (guint8*)target + f->field->offset;
7579                 else
7580                         p += f->field->offset - sizeof (MonoObject);
7581                 klass = mono_class_from_mono_type (f->field->type);
7582                 ftype = f->field->type;
7583         }
7584
7585         res.type = ftype;
7586         res.klass = mono_class_from_mono_type (ftype);
7587         res.value = p;
7588
7589         return res;
7590 }
7591
7592 static void
7593 prelink_method (MonoMethod *method, MonoError *error)
7594 {
7595         const char *exc_class, *exc_arg;
7596
7597         mono_error_init (error);
7598         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7599                 return;
7600         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7601         if (exc_class) {
7602                 mono_error_set_exception_instance (error,
7603                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7604                 return;
7605         }
7606         /* create the wrapper, too? */
7607 }
7608
7609 ICALL_EXPORT void
7610 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7611 {
7612         MonoError error;
7613
7614         prelink_method (method->method, &error);
7615         mono_error_set_pending_exception (&error);
7616 }
7617
7618 ICALL_EXPORT void
7619 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7620 {
7621         MonoError error;
7622         MonoClass *klass = mono_class_from_mono_type (type->type);
7623         MonoMethod* m;
7624         gpointer iter = NULL;
7625
7626         mono_class_init_checked (klass, &error);
7627         if (mono_error_set_pending_exception (&error))
7628                 return;
7629
7630         while ((m = mono_class_get_methods (klass, &iter))) {
7631                 prelink_method (m, &error);
7632                 if (mono_error_set_pending_exception (&error))
7633                         return;
7634         }
7635 }
7636
7637 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7638 ICALL_EXPORT void
7639 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7640                                             gint32 const **exponents,
7641                                             gunichar2 const **digitLowerTable,
7642                                             gunichar2 const **digitUpperTable,
7643                                             gint64 const **tenPowersList,
7644                                             gint32 const **decHexDigits)
7645 {
7646         *mantissas = Formatter_MantissaBitsTable;
7647         *exponents = Formatter_TensExponentTable;
7648         *digitLowerTable = Formatter_DigitLowerTable;
7649         *digitUpperTable = Formatter_DigitUpperTable;
7650         *tenPowersList = Formatter_TenPowersList;
7651         *decHexDigits = Formatter_DecHexDigits;
7652 }
7653
7654 static gboolean
7655 add_modifier_to_array (MonoDomain *domain, MonoImage *image, MonoCustomMod *modifier, MonoArrayHandle dest, int dest_idx, MonoError *error)
7656 {
7657         HANDLE_FUNCTION_ENTER ();
7658         mono_error_init (error);
7659         MonoClass *klass = mono_class_get_checked (image, modifier->token, error);
7660         if (!is_ok (error))
7661                 goto leave;
7662
7663         MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, &klass->byval_arg, error);
7664         if (!is_ok (error))
7665                 goto leave;
7666
7667         MONO_HANDLE_ARRAY_SETREF (dest, dest_idx, rt);
7668 leave:
7669         HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
7670 }
7671
7672 /*
7673  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7674  * and avoid useless allocations.
7675  */
7676 static MonoArrayHandle
7677 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7678 {
7679         int i, count = 0;
7680         MonoDomain *domain = mono_domain_get ();
7681
7682         mono_error_init (error);
7683         for (i = 0; i < type->num_mods; ++i) {
7684                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7685                         count++;
7686         }
7687         if (!count)
7688                 return MONO_HANDLE_NEW (MonoArray, NULL);
7689
7690         MonoArrayHandle res = mono_array_new_handle (domain, mono_defaults.systemtype_class, count, error);
7691         if (!is_ok (error))
7692                 goto fail;
7693         count = 0;
7694         for (i = 0; i < type->num_mods; ++i) {
7695                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7696                         if (!add_modifier_to_array (domain, image, &type->modifiers[i], res, count , error))
7697                                 goto fail;
7698                         count++;
7699                 }
7700         }
7701         return res;
7702 fail:
7703         return MONO_HANDLE_NEW (MonoArray, NULL);
7704 }
7705
7706 ICALL_EXPORT MonoArrayHandle
7707 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameterHandle param, MonoBoolean optional, MonoError *error)
7708 {
7709         mono_error_init (error);
7710         MonoReflectionTypeHandle rt = MONO_HANDLE_NEW (MonoReflectionType, NULL);
7711         MONO_HANDLE_GET (rt, param, ClassImpl);
7712         MonoType *type = MONO_HANDLE_GETVAL (rt, type);
7713         MonoObjectHandle member = MONO_HANDLE_NEW (MonoObject, NULL);
7714         MONO_HANDLE_GET (member, param, MemberImpl);
7715         MonoClass *member_class = mono_handle_class (member);
7716         MonoMethod *method = NULL;
7717         MonoImage *image;
7718         int pos;
7719         MonoMethodSignature *sig;
7720
7721         if (mono_class_is_reflection_method_or_constructor (member_class)) {
7722                 method = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionMethod, member), method);
7723         } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7724                 MonoProperty *prop = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionProperty, member), property);
7725                 if (!(method = prop->get))
7726                         method = prop->set;
7727                 g_assert (method);      
7728         } else {
7729                 char *type_name = mono_type_get_full_name (member_class);
7730                 mono_error_set_not_supported (error, "Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7731                 g_free (type_name);
7732                 return MONO_HANDLE_CAST (MonoArray, NULL_HANDLE);
7733         }
7734
7735         image = method->klass->image;
7736         pos = MONO_HANDLE_GETVAL (param, PositionImpl);
7737         sig = mono_method_signature (method);
7738         if (pos == -1)
7739                 type = sig->ret;
7740         else
7741                 type = sig->params [pos];
7742
7743         return type_array_from_modifiers (image, type, optional, error);
7744 }
7745
7746 static MonoType*
7747 get_property_type (MonoProperty *prop)
7748 {
7749         MonoMethodSignature *sig;
7750         if (prop->get) {
7751                 sig = mono_method_signature (prop->get);
7752                 return sig->ret;
7753         } else if (prop->set) {
7754                 sig = mono_method_signature (prop->set);
7755                 return sig->params [sig->param_count - 1];
7756         }
7757         return NULL;
7758 }
7759
7760 ICALL_EXPORT MonoArrayHandle
7761 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionPropertyHandle property, MonoBoolean optional, MonoError *error)
7762 {
7763         mono_error_init (error);
7764         MonoProperty *prop = MONO_HANDLE_GETVAL (property, property);
7765         MonoClass *klass = MONO_HANDLE_GETVAL (property, klass);
7766         MonoType *type = get_property_type (prop);
7767         MonoImage *image = klass->image;
7768
7769         if (!type)
7770                 return MONO_HANDLE_CAST (MonoArray, NULL_HANDLE);
7771         return type_array_from_modifiers (image, type, optional, error);
7772 }
7773
7774 /*
7775  *Construct a MonoType suited to be used to decode a constant blob object.
7776  *
7777  * @type is the target type which will be constructed
7778  * @blob_type is the blob type, for example, that comes from the constant table
7779  * @real_type is the expected constructed type.
7780  */
7781 static void
7782 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7783 {
7784         type->type = blob_type;
7785         type->data.klass = NULL;
7786         if (blob_type == MONO_TYPE_CLASS)
7787                 type->data.klass = mono_defaults.object_class;
7788         else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7789                 /* For enums, we need to use the base type */
7790                 type->type = MONO_TYPE_VALUETYPE;
7791                 type->data.klass = mono_class_from_mono_type (real_type);
7792         } else
7793                 type->data.klass = mono_class_from_mono_type (real_type);
7794 }
7795
7796 ICALL_EXPORT MonoObject*
7797 property_info_get_default_value (MonoReflectionProperty *property)
7798 {
7799         MonoError error;
7800         MonoType blob_type;
7801         MonoProperty *prop = property->property;
7802         MonoType *type = get_property_type (prop);
7803         MonoDomain *domain = mono_object_domain (property); 
7804         MonoTypeEnum def_type;
7805         const char *def_value;
7806         MonoObject *o;
7807
7808         mono_class_init (prop->parent);
7809
7810         if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7811                 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7812                 return NULL;
7813         }
7814
7815         def_value = mono_class_get_property_default_value (prop, &def_type);
7816
7817         mono_type_from_blob_type (&blob_type, def_type, type);
7818         o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7819
7820         mono_error_set_pending_exception (&error);
7821         return o;
7822 }
7823
7824 ICALL_EXPORT MonoBoolean
7825 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7826 {
7827         MonoError error;
7828         MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7829         MonoCustomAttrInfo *cinfo;
7830         gboolean found;
7831
7832         mono_class_init_checked (attr_class, &error);
7833         if (mono_error_set_pending_exception (&error))
7834                 return FALSE;
7835
7836         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7837         if (!is_ok (&error)) {
7838                 mono_error_set_pending_exception (&error);
7839                 return FALSE;
7840         }
7841         if (!cinfo)
7842                 return FALSE;
7843         found = mono_custom_attrs_has_attr (cinfo, attr_class);
7844         if (!cinfo->cached)
7845                 mono_custom_attrs_free (cinfo);
7846         return found;
7847 }
7848
7849 ICALL_EXPORT MonoArray*
7850 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7851 {
7852         MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7853         MonoArray *res;
7854         MonoError error;
7855
7856         if (attr_class) {
7857                 mono_class_init_checked (attr_class, &error);
7858                 if (mono_error_set_pending_exception (&error))
7859                         return NULL;
7860         }
7861
7862         res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7863         if (!mono_error_ok (&error)) {
7864                 mono_error_set_pending_exception (&error);
7865                 return NULL;
7866         }
7867
7868         return res;
7869 }
7870
7871 ICALL_EXPORT MonoArray*
7872 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7873 {
7874         MonoError error;
7875         MonoArray *result;
7876         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7877         mono_error_set_pending_exception (&error);
7878         return result;
7879 }
7880
7881
7882 ICALL_EXPORT MonoStringHandle
7883 ves_icall_Mono_Runtime_GetDisplayName (MonoError *error)
7884 {
7885         char *info;
7886         MonoStringHandle display_name;
7887
7888         mono_error_init (error);
7889         info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7890         display_name = mono_string_new_handle (mono_domain_get (), info, error);
7891         g_free (info);
7892         return display_name;
7893 }
7894
7895 #ifndef HOST_WIN32
7896 static inline gint32
7897 mono_icall_wait_for_input_idle (gpointer handle, gint32 milliseconds)
7898 {
7899         return WAIT_TIMEOUT;
7900 }
7901 #endif /* !HOST_WIN32 */
7902
7903 ICALL_EXPORT gint32
7904 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
7905 {
7906         return mono_icall_wait_for_input_idle (handle, milliseconds);
7907 }
7908
7909 ICALL_EXPORT gint32
7910 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
7911 {
7912         return mono_process_current_pid ();
7913 }
7914
7915 ICALL_EXPORT MonoBoolean
7916 ves_icall_Mono_TlsProviderFactory_IsBtlsSupported (void)
7917 {
7918 #if HAVE_BTLS
7919         return TRUE;
7920 #else
7921         return FALSE;
7922 #endif
7923 }
7924
7925 #ifndef DISABLE_COM
7926
7927 ICALL_EXPORT int
7928 ves_icall_System_Runtime_InteropServices_Marshal_GetHRForException_WinRT(MonoException* ex)
7929 {
7930         mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetHRForException_WinRT internal call is not implemented."));
7931         return 0;
7932 }
7933
7934 ICALL_EXPORT MonoObject*
7935 ves_icall_System_Runtime_InteropServices_Marshal_GetNativeActivationFactory(MonoObject* type)
7936 {
7937         mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetNativeActivationFactory internal call is not implemented."));
7938         return NULL;
7939 }
7940
7941 ICALL_EXPORT void*
7942 ves_icall_System_Runtime_InteropServices_Marshal_GetRawIUnknownForComObjectNoAddRef(MonoObject* obj)
7943 {
7944         mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetRawIUnknownForComObjectNoAddRef internal call is not implemented."));
7945         return NULL;
7946 }
7947
7948 ICALL_EXPORT MonoObject*
7949 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_GetRestrictedErrorInfo()
7950 {
7951         mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.GetRestrictedErrorInfo internal call is not implemented."));
7952         return NULL;
7953 }
7954
7955 ICALL_EXPORT MonoBoolean
7956 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoOriginateLanguageException(int error, MonoString* message, void* languageException)
7957 {
7958         mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoOriginateLanguageException internal call is not implemented."));
7959         return FALSE;
7960 }
7961
7962 ICALL_EXPORT void
7963 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoReportUnhandledError(MonoObject* error)
7964 {
7965         mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoReportUnhandledError internal call is not implemented."));
7966 }
7967
7968 ICALL_EXPORT int
7969 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsCreateString(MonoString* sourceString, int length, void** hstring)
7970 {
7971         mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateString internal call is not implemented."));
7972         return 0;
7973 }
7974
7975 ICALL_EXPORT int
7976 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsDeleteString(void* hstring)
7977 {
7978         mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsDeleteString internal call is not implemented."));
7979         return 0;
7980 }
7981
7982 ICALL_EXPORT mono_unichar2*
7983 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsGetStringRawBuffer(void* hstring, unsigned* length)
7984 {
7985         mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsGetStringRawBuffer internal call is not implemented."));
7986         return NULL;
7987 }
7988
7989 #endif
7990
7991
7992 #ifndef DISABLE_ICALL_TABLES
7993
7994 #define ICALL_TYPE(id,name,first)
7995 #define ICALL(id,name,func) Icall_ ## id,
7996 #define HANDLES(inner) inner
7997
7998 enum {
7999 #include "metadata/icall-def.h"
8000         Icall_last
8001 };
8002
8003 #undef ICALL_TYPE
8004 #undef ICALL
8005 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8006 #define ICALL(id,name,func)
8007 #undef HANDLES
8008 #define HANDLES(inner) inner
8009 enum {
8010 #include "metadata/icall-def.h"
8011         Icall_type_num
8012 };
8013
8014 #undef ICALL_TYPE
8015 #undef ICALL
8016 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8017 #define ICALL(id,name,func)
8018 #undef HANDLES
8019 #define HANDLES(inner) inner
8020 typedef struct {
8021         guint16 first_icall;
8022 } IcallTypeDesc;
8023
8024 static const IcallTypeDesc
8025 icall_type_descs [] = {
8026 #include "metadata/icall-def.h"
8027         {Icall_last}
8028 };
8029
8030 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8031
8032 #undef HANDLES
8033 #define HANDLES(inner) inner
8034 #undef ICALL_TYPE
8035 #define ICALL_TYPE(id,name,first)
8036 #undef ICALL
8037
8038 #ifdef HAVE_ARRAY_ELEM_INIT
8039 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8040 #define MSGSTRFIELD1(line) str##line
8041
8042 static const struct msgstrtn_t {
8043 #define ICALL(id,name,func)
8044 #undef ICALL_TYPE
8045 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8046 #include "metadata/icall-def.h"
8047 #undef ICALL_TYPE
8048 } icall_type_names_str = {
8049 #define ICALL_TYPE(id,name,first) (name),
8050 #include "metadata/icall-def.h"
8051 #undef ICALL_TYPE
8052 };
8053 static const guint16 icall_type_names_idx [] = {
8054 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8055 #include "metadata/icall-def.h"
8056 #undef ICALL_TYPE
8057 };
8058 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8059
8060 static const struct msgstr_t {
8061 #undef ICALL
8062 #define ICALL_TYPE(id,name,first)
8063 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8064 #include "metadata/icall-def.h"
8065 #undef ICALL
8066 } icall_names_str = {
8067 #define ICALL(id,name,func) (name),
8068 #include "metadata/icall-def.h"
8069 #undef ICALL
8070 };
8071 static const guint16 icall_names_idx [] = {
8072 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8073 #include "metadata/icall-def.h"
8074 #undef ICALL
8075 };
8076 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8077
8078 #else
8079
8080 #undef ICALL_TYPE
8081 #undef ICALL
8082 #define ICALL_TYPE(id,name,first) name,
8083 #define ICALL(id,name,func)
8084 static const char* const
8085 icall_type_names [] = {
8086 #include "metadata/icall-def.h"
8087         NULL
8088 };
8089
8090 #define icall_type_name_get(id) (icall_type_names [(id)])
8091
8092 #undef ICALL_TYPE
8093 #undef ICALL
8094 #define ICALL_TYPE(id,name,first)
8095 #define ICALL(id,name,func) name,
8096 static const char* const
8097 icall_names [] = {
8098 #include "metadata/icall-def.h"
8099         NULL
8100 };
8101 #define icall_name_get(id) icall_names [(id)]
8102
8103 #endif /* !HAVE_ARRAY_ELEM_INIT */
8104
8105 #undef HANDLES
8106 #define HANDLES(inner) inner
8107 #undef ICALL_TYPE
8108 #undef ICALL
8109 #define ICALL_TYPE(id,name,first)
8110 #define ICALL(id,name,func) func,
8111 static const gconstpointer
8112 icall_functions [] = {
8113 #include "metadata/icall-def.h"
8114         NULL
8115 };
8116
8117 #ifdef ENABLE_ICALL_SYMBOL_MAP
8118 #undef HANDLES
8119 #define HANDLES(inner) inner
8120 #undef ICALL_TYPE
8121 #undef ICALL
8122 #define ICALL_TYPE(id,name,first)
8123 #define ICALL(id,name,func) #func,
8124 static const gconstpointer
8125 icall_symbols [] = {
8126 #include "metadata/icall-def.h"
8127         NULL
8128 };
8129 #endif
8130
8131 #undef ICALL_TYPE
8132 #undef ICALL
8133 #define ICALL_TYPE(id,name,first)
8134 #define ICALL(id,name,func) 0,
8135 #undef HANDLES
8136 #define HANDLES(inner) 1,
8137 static const guchar
8138 icall_uses_handles [] = {
8139 #include "metadata/icall-def.h"
8140 #undef ICALL
8141 #undef HANDLES
8142 };
8143
8144 #endif /* DISABLE_ICALL_TABLES */
8145
8146 static mono_mutex_t icall_mutex;
8147 static GHashTable *icall_hash = NULL;
8148 static GHashTable *jit_icall_hash_name = NULL;
8149 static GHashTable *jit_icall_hash_addr = NULL;
8150
8151 void
8152 mono_icall_init (void)
8153 {
8154 #ifndef DISABLE_ICALL_TABLES
8155         int i = 0;
8156
8157         /* check that tables are sorted: disable in release */
8158         if (TRUE) {
8159                 int j;
8160                 const char *prev_class = NULL;
8161                 const char *prev_method;
8162                 
8163                 for (i = 0; i < Icall_type_num; ++i) {
8164                         const IcallTypeDesc *desc;
8165                         int num_icalls;
8166                         prev_method = NULL;
8167                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8168                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8169                         prev_class = icall_type_name_get (i);
8170                         desc = &icall_type_descs [i];
8171                         num_icalls = icall_desc_num_icalls (desc);
8172                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8173                         for (j = 0; j < num_icalls; ++j) {
8174                                 const char *methodn = icall_name_get (desc->first_icall + j);
8175                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
8176                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
8177                                 prev_method = methodn;
8178                         }
8179                 }
8180         }
8181 #endif
8182
8183         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8184         mono_os_mutex_init (&icall_mutex);
8185 }
8186
8187 static void
8188 mono_icall_lock (void)
8189 {
8190         mono_locks_os_acquire (&icall_mutex, IcallLock);
8191 }
8192
8193 static void
8194 mono_icall_unlock (void)
8195 {
8196         mono_locks_os_release (&icall_mutex, IcallLock);
8197 }
8198
8199 void
8200 mono_icall_cleanup (void)
8201 {
8202         g_hash_table_destroy (icall_hash);
8203         g_hash_table_destroy (jit_icall_hash_name);
8204         g_hash_table_destroy (jit_icall_hash_addr);
8205         mono_os_mutex_destroy (&icall_mutex);
8206 }
8207
8208 /**
8209  * mono_add_internal_call:
8210  * @name: method specification to surface to the managed world
8211  * @method: pointer to a C method to invoke when the method is called
8212  *
8213  * This method surfaces the C function pointed by @method as a method
8214  * that has been surfaced in managed code with the method specified in
8215  * @name as an internal call.
8216  *
8217  * Internal calls are surfaced to all app domains loaded and they are
8218  * accessibly by a type with the specified name.
8219  *
8220  * You must provide a fully qualified type name, that is namespaces
8221  * and type name, followed by a colon and the method name, with an
8222  * optional signature to bind.
8223  *
8224  * For example, the following are all valid declarations:
8225  *
8226  * "MyApp.Services.ScriptService:Accelerate"
8227  * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8228  *
8229  * You use method parameters in cases where there might be more than
8230  * one surface method to managed code.  That way you can register different
8231  * internal calls for different method overloads.
8232  *
8233  * The internal calls are invoked with no marshalling.   This means that .NET
8234  * types like System.String are exposed as `MonoString *` parameters.   This is
8235  * different than the way that strings are surfaced in P/Invoke.
8236  *
8237  * For more information on how the parameters are marshalled, see the
8238  * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8239  * page.
8240  *
8241  * See the <a  href="mono-api-methods.html#method-desc">Method Description</a>
8242  * reference for more information on the format of method descriptions.
8243  */
8244 void
8245 mono_add_internal_call (const char *name, gconstpointer method)
8246 {
8247         mono_icall_lock ();
8248
8249         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8250
8251         mono_icall_unlock ();
8252 }
8253
8254 #ifndef DISABLE_ICALL_TABLES
8255
8256 #ifdef HAVE_ARRAY_ELEM_INIT
8257 static int
8258 compare_method_imap (const void *key, const void *elem)
8259 {
8260         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8261         return strcmp (key, method_name);
8262 }
8263
8264 static gsize
8265 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8266 {
8267         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);
8268         if (!nameslot)
8269                 return -1;
8270         return (nameslot - &icall_names_idx [0]);
8271 }
8272
8273 static gboolean
8274 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8275 {
8276         gsize slotnum = find_slot_icall (imap, name);
8277         if (slotnum == -1)
8278                 return FALSE;
8279         return (gboolean)icall_uses_handles [slotnum];
8280 }
8281
8282 static gpointer
8283 find_method_icall (const IcallTypeDesc *imap, const char *name)
8284 {
8285         gsize slotnum = find_slot_icall (imap, name);
8286         if (slotnum == -1)
8287                 return NULL;
8288         return (gpointer)icall_functions [slotnum];
8289 }
8290
8291 static int
8292 compare_class_imap (const void *key, const void *elem)
8293 {
8294         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8295         return strcmp (key, class_name);
8296 }
8297
8298 static const IcallTypeDesc*
8299 find_class_icalls (const char *name)
8300 {
8301         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);
8302         if (!nameslot)
8303                 return NULL;
8304         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8305 }
8306
8307 #else /* HAVE_ARRAY_ELEM_INIT */
8308
8309 static int
8310 compare_method_imap (const void *key, const void *elem)
8311 {
8312         const char** method_name = (const char**)elem;
8313         return strcmp (key, *method_name);
8314 }
8315
8316 static gsize
8317 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8318 {
8319         const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8320         if (!nameslot)
8321                 return -1;
8322         return nameslot - icall_names;
8323 }
8324
8325 static gpointer
8326 find_method_icall (const IcallTypeDesc *imap, const char *name)
8327 {
8328         gsize slotnum = find_slot_icall (imap, name);
8329         if (slotnum == -1)
8330                 return NULL;
8331         return (gpointer)icall_functions [slotnum];
8332 }
8333
8334 static gboolean
8335 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8336 {
8337         gsize slotnum = find_slot_icall (imap, name);
8338         if (slotnum == -1)
8339                 return FALSE;
8340         return (gboolean)icall_uses_handles [slotnum];
8341 }
8342
8343 static int
8344 compare_class_imap (const void *key, const void *elem)
8345 {
8346         const char** class_name = (const char**)elem;
8347         return strcmp (key, *class_name);
8348 }
8349
8350 static const IcallTypeDesc*
8351 find_class_icalls (const char *name)
8352 {
8353         const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8354         if (!nameslot)
8355                 return NULL;
8356         return &icall_type_descs [nameslot - icall_type_names];
8357 }
8358
8359 #endif /* HAVE_ARRAY_ELEM_INIT */
8360
8361 #endif /* DISABLE_ICALL_TABLES */
8362
8363 /* 
8364  * we should probably export this as an helper (handle nested types).
8365  * Returns the number of chars written in buf.
8366  */
8367 static int
8368 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8369 {
8370         int nspacelen, cnamelen;
8371         nspacelen = strlen (klass->name_space);
8372         cnamelen = strlen (klass->name);
8373         if (nspacelen + cnamelen + 2 > bufsize)
8374                 return 0;
8375         if (nspacelen) {
8376                 memcpy (buf, klass->name_space, nspacelen);
8377                 buf [nspacelen ++] = '.';
8378         }
8379         memcpy (buf + nspacelen, klass->name, cnamelen);
8380         buf [nspacelen + cnamelen] = 0;
8381         return nspacelen + cnamelen;
8382 }
8383
8384 #ifdef DISABLE_ICALL_TABLES
8385 static void
8386 no_icall_table (void)
8387 {
8388         g_assert_not_reached ();
8389 }
8390 #endif
8391
8392 /**
8393  * mono_lookup_internal_call_full:
8394  * @method: the method to look up
8395  * @uses_handles: out argument if method needs handles around managed objects.
8396  *
8397  * Returns a pointer to the icall code for the given method.  If
8398  * uses_handles is not NULL, it will be set to TRUE if the method
8399  * needs managed objects wrapped using the infrastructure in handle.h
8400  *
8401  * If the method is not found, warns and returns NULL.
8402  */
8403 gpointer
8404 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8405 {
8406         char *sigstart;
8407         char *tmpsig;
8408         char mname [2048];
8409         int typelen = 0, mlen, siglen;
8410         gpointer res;
8411 #ifndef DISABLE_ICALL_TABLES
8412         const IcallTypeDesc *imap = NULL;
8413 #endif
8414
8415         g_assert (method != NULL);
8416
8417         if (method->is_inflated)
8418                 method = ((MonoMethodInflated *) method)->declaring;
8419
8420         if (method->klass->nested_in) {
8421                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8422                 if (!pos)
8423                         return NULL;
8424
8425                 mname [pos++] = '/';
8426                 mname [pos] = 0;
8427
8428                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8429                 if (!typelen)
8430                         return NULL;
8431
8432                 typelen += pos;
8433         } else {
8434                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8435                 if (!typelen)
8436                         return NULL;
8437         }
8438
8439 #ifndef DISABLE_ICALL_TABLES
8440         imap = find_class_icalls (mname);
8441 #endif
8442
8443         mname [typelen] = ':';
8444         mname [typelen + 1] = ':';
8445
8446         mlen = strlen (method->name);
8447         memcpy (mname + typelen + 2, method->name, mlen);
8448         sigstart = mname + typelen + 2 + mlen;
8449         *sigstart = 0;
8450
8451         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8452         siglen = strlen (tmpsig);
8453         if (typelen + mlen + siglen + 6 > sizeof (mname))
8454                 return NULL;
8455         sigstart [0] = '(';
8456         memcpy (sigstart + 1, tmpsig, siglen);
8457         sigstart [siglen + 1] = ')';
8458         sigstart [siglen + 2] = 0;
8459         g_free (tmpsig);
8460         
8461         mono_icall_lock ();
8462
8463         res = g_hash_table_lookup (icall_hash, mname);
8464         if (res) {
8465                 if (uses_handles)
8466                         *uses_handles = FALSE;
8467                 mono_icall_unlock ();;
8468                 return res;
8469         }
8470         /* try without signature */
8471         *sigstart = 0;
8472         res = g_hash_table_lookup (icall_hash, mname);
8473         if (res) {
8474                 if (uses_handles)
8475                         *uses_handles = FALSE;
8476                 mono_icall_unlock ();
8477                 return res;
8478         }
8479
8480 #ifdef DISABLE_ICALL_TABLES
8481         mono_icall_unlock ();
8482         /* Fail only when the result is actually used */
8483         /* mono_marshal_get_native_wrapper () depends on this */
8484         if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8485                 return ves_icall_System_String_ctor_RedirectToCreateString;
8486         else
8487                 return no_icall_table;
8488 #else
8489         /* it wasn't found in the static call tables */
8490         if (!imap) {
8491                 if (uses_handles)
8492                         *uses_handles = FALSE;
8493                 mono_icall_unlock ();
8494                 return NULL;
8495         }
8496         res = find_method_icall (imap, sigstart - mlen);
8497         if (res) {
8498                 if (uses_handles)
8499                         *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8500                 mono_icall_unlock ();
8501                 return res;
8502         }
8503         /* try _with_ signature */
8504         *sigstart = '(';
8505         res = find_method_icall (imap, sigstart - mlen);
8506         if (res) {
8507                 if (uses_handles)
8508                         *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8509                 mono_icall_unlock ();
8510                 return res;
8511         }
8512
8513         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8514         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8515         g_print ("The out of sync library is: %s\n", method->klass->image->name);
8516         g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8517         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");
8518         g_print ("If you see other errors or faults after this message they are probably related\n");
8519         g_print ("and you need to fix your mono install first.\n");
8520
8521         mono_icall_unlock ();
8522
8523         return NULL;
8524 #endif
8525 }
8526
8527 gpointer
8528 mono_lookup_internal_call (MonoMethod *method)
8529 {
8530         return mono_lookup_internal_call_full (method, NULL);
8531 }
8532
8533 #ifdef ENABLE_ICALL_SYMBOL_MAP
8534 static int
8535 func_cmp (gconstpointer key, gconstpointer p)
8536 {
8537         return (gsize)key - (gsize)*(gsize*)p;
8538 }
8539 #endif
8540
8541 /*
8542  * mono_lookup_icall_symbol:
8543  *
8544  *   Given the icall METHOD, returns its C symbol.
8545  */
8546 const char*
8547 mono_lookup_icall_symbol (MonoMethod *m)
8548 {
8549 #ifdef DISABLE_ICALL_TABLES
8550         g_assert_not_reached ();
8551         return NULL;
8552 #else
8553 #ifdef ENABLE_ICALL_SYMBOL_MAP
8554         gpointer func;
8555         int i;
8556         gpointer slot;
8557         static gconstpointer *functions_sorted;
8558         static const char**symbols_sorted;
8559         static gboolean inited;
8560
8561         if (!inited) {
8562                 gboolean changed;
8563
8564                 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8565                 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8566                 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8567                 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8568                 /* Bubble sort the two arrays */
8569                 changed = TRUE;
8570                 while (changed) {
8571                         changed = FALSE;
8572                         for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8573                                 if (functions_sorted [i] > functions_sorted [i + 1]) {
8574                                         gconstpointer tmp;
8575
8576                                         tmp = functions_sorted [i];
8577                                         functions_sorted [i] = functions_sorted [i + 1];
8578                                         functions_sorted [i + 1] = tmp;
8579                                         tmp = symbols_sorted [i];
8580                                         symbols_sorted [i] = symbols_sorted [i + 1];
8581                                         symbols_sorted [i + 1] = tmp;
8582                                         changed = TRUE;
8583                                 }
8584                         }
8585                 }
8586         }
8587
8588         func = mono_lookup_internal_call (m);
8589         if (!func)
8590                 return NULL;
8591         slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8592         if (!slot)
8593                 return NULL;
8594         g_assert (slot);
8595         return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8596 #else
8597         fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8598         g_assert_not_reached ();
8599         return 0;
8600 #endif
8601 #endif
8602 }
8603
8604 static MonoType*
8605 type_from_typename (char *type_name)
8606 {
8607         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
8608
8609         if (!strcmp (type_name, "int"))
8610                 klass = mono_defaults.int_class;
8611         else if (!strcmp (type_name, "ptr"))
8612                 klass = mono_defaults.int_class;
8613         else if (!strcmp (type_name, "void"))
8614                 klass = mono_defaults.void_class;
8615         else if (!strcmp (type_name, "int32"))
8616                 klass = mono_defaults.int32_class;
8617         else if (!strcmp (type_name, "uint32"))
8618                 klass = mono_defaults.uint32_class;
8619         else if (!strcmp (type_name, "int8"))
8620                 klass = mono_defaults.sbyte_class;
8621         else if (!strcmp (type_name, "uint8"))
8622                 klass = mono_defaults.byte_class;
8623         else if (!strcmp (type_name, "int16"))
8624                 klass = mono_defaults.int16_class;
8625         else if (!strcmp (type_name, "uint16"))
8626                 klass = mono_defaults.uint16_class;
8627         else if (!strcmp (type_name, "long"))
8628                 klass = mono_defaults.int64_class;
8629         else if (!strcmp (type_name, "ulong"))
8630                 klass = mono_defaults.uint64_class;
8631         else if (!strcmp (type_name, "float"))
8632                 klass = mono_defaults.single_class;
8633         else if (!strcmp (type_name, "double"))
8634                 klass = mono_defaults.double_class;
8635         else if (!strcmp (type_name, "object"))
8636                 klass = mono_defaults.object_class;
8637         else if (!strcmp (type_name, "obj"))
8638                 klass = mono_defaults.object_class;
8639         else if (!strcmp (type_name, "string"))
8640                 klass = mono_defaults.string_class;
8641         else if (!strcmp (type_name, "bool"))
8642                 klass = mono_defaults.boolean_class;
8643         else if (!strcmp (type_name, "boolean"))
8644                 klass = mono_defaults.boolean_class;
8645         else {
8646                 g_error ("%s", type_name);
8647                 g_assert_not_reached ();
8648         }
8649         return &klass->byval_arg;
8650 }
8651
8652 /**
8653  * LOCKING: Take the corlib image lock.
8654  */
8655 MonoMethodSignature*
8656 mono_create_icall_signature (const char *sigstr)
8657 {
8658         gchar **parts;
8659         int i, len;
8660         gchar **tmp;
8661         MonoMethodSignature *res, *res2;
8662         MonoImage *corlib = mono_defaults.corlib;
8663
8664         mono_image_lock (corlib);
8665         res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8666         mono_image_unlock (corlib);
8667
8668         if (res)
8669                 return res;
8670
8671         parts = g_strsplit (sigstr, " ", 256);
8672
8673         tmp = parts;
8674         len = 0;
8675         while (*tmp) {
8676                 len ++;
8677                 tmp ++;
8678         }
8679
8680         res = mono_metadata_signature_alloc (corlib, len - 1);
8681         res->pinvoke = 1;
8682
8683 #ifdef HOST_WIN32
8684         /* 
8685          * Under windows, the default pinvoke calling convention is STDCALL but
8686          * we need CDECL.
8687          */
8688         res->call_convention = MONO_CALL_C;
8689 #endif
8690
8691         res->ret = type_from_typename (parts [0]);
8692         for (i = 1; i < len; ++i) {
8693                 res->params [i - 1] = type_from_typename (parts [i]);
8694         }
8695
8696         g_strfreev (parts);
8697
8698         mono_image_lock (corlib);
8699         res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8700         if (res2)
8701                 res = res2; /*Value is allocated in the image pool*/
8702         else
8703                 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8704         mono_image_unlock (corlib);
8705
8706         return res;
8707 }
8708
8709 MonoJitICallInfo *
8710 mono_find_jit_icall_by_name (const char *name)
8711 {
8712         MonoJitICallInfo *info;
8713         g_assert (jit_icall_hash_name);
8714
8715         mono_icall_lock ();
8716         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8717         mono_icall_unlock ();
8718         return info;
8719 }
8720
8721 MonoJitICallInfo *
8722 mono_find_jit_icall_by_addr (gconstpointer addr)
8723 {
8724         MonoJitICallInfo *info;
8725         g_assert (jit_icall_hash_addr);
8726
8727         mono_icall_lock ();
8728         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8729         mono_icall_unlock ();
8730
8731         return info;
8732 }
8733
8734 /*
8735  * mono_get_jit_icall_info:
8736  *
8737  *   Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8738  * caller should access it while holding the icall lock.
8739  */
8740 GHashTable*
8741 mono_get_jit_icall_info (void)
8742 {
8743         return jit_icall_hash_name;
8744 }
8745
8746 /*
8747  * mono_lookup_jit_icall_symbol:
8748  *
8749  *   Given the jit icall NAME, returns its C symbol if possible, or NULL.
8750  */
8751 const char*
8752 mono_lookup_jit_icall_symbol (const char *name)
8753 {
8754         MonoJitICallInfo *info;
8755         const char *res = NULL;
8756
8757         mono_icall_lock ();
8758         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8759         if (info)
8760                 res = info->c_symbol;
8761         mono_icall_unlock ();
8762         return res;
8763 }
8764
8765 void
8766 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8767 {
8768         mono_icall_lock ();
8769         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8770         mono_icall_unlock ();
8771 }
8772
8773 /*
8774  * 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
8775  * icalls without wrappers in some cases.
8776  */
8777 MonoJitICallInfo *
8778 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8779 {
8780         MonoJitICallInfo *info;
8781         
8782         g_assert (func);
8783         g_assert (name);
8784
8785         mono_icall_lock ();
8786
8787         if (!jit_icall_hash_name) {
8788                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8789                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8790         }
8791
8792         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8793                 g_warning ("jit icall already defined \"%s\"\n", name);
8794                 g_assert_not_reached ();
8795         }
8796
8797         info = g_new0 (MonoJitICallInfo, 1);
8798         
8799         info->name = name;
8800         info->func = func;
8801         info->sig = sig;
8802         info->c_symbol = c_symbol;
8803         info->no_raise = no_raise;
8804
8805         if (is_save) {
8806                 info->wrapper = func;
8807         } else {
8808                 info->wrapper = NULL;
8809         }
8810
8811         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8812         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8813
8814         mono_icall_unlock ();
8815         return info;
8816 }
8817
8818 MonoJitICallInfo *
8819 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8820 {
8821         return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);
8822 }
8823