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