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