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