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