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