e60d9b3b27e47902c30d162e3c08e9c429dfdaca
[mono.git] / mono / metadata / icall.c
1 /*
2  * icall.c:
3  *
4  * Authors:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *   Paolo Molaro (lupus@ximian.com)
7  *       Patrik Torstensson (patrik.torstensson@labs2.com)
8  *   Marek Safar (marek.safar@gmail.com)
9  *   Aleksey Kliger (aleksey@xamarin.com)
10  *
11  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13  * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
14  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
15  */
16
17 #include <config.h>
18 #include <glib.h>
19 #include <stdarg.h>
20 #include <string.h>
21 #include <ctype.h>
22 #ifdef HAVE_ALLOCA_H
23 #include <alloca.h>
24 #endif
25 #ifdef HAVE_SYS_TIME_H
26 #include <sys/time.h>
27 #endif
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31 #if defined (HOST_WIN32)
32 #include <stdlib.h>
33 #endif
34 #if defined (HAVE_WCHAR_H)
35 #include <wchar.h>
36 #endif
37
38 #include "mono/utils/mono-membar.h"
39 #include <mono/metadata/object.h>
40 #include <mono/metadata/threads.h>
41 #include <mono/metadata/threads-types.h>
42 #include <mono/metadata/threadpool-ms.h>
43 #include <mono/metadata/threadpool-ms-io.h>
44 #include <mono/metadata/monitor.h>
45 #include <mono/metadata/reflection.h>
46 #include <mono/metadata/assembly.h>
47 #include <mono/metadata/tabledefs.h>
48 #include <mono/metadata/exception.h>
49 #include <mono/metadata/exception-internals.h>
50 #include <mono/metadata/file-io.h>
51 #include <mono/metadata/console-io.h>
52 #include <mono/metadata/mono-route.h>
53 #include <mono/metadata/socket-io.h>
54 #include <mono/metadata/mono-endian.h>
55 #include <mono/metadata/tokentype.h>
56 #include <mono/metadata/domain-internals.h>
57 #include <mono/metadata/metadata-internals.h>
58 #include <mono/metadata/class-internals.h>
59 #include <mono/metadata/reflection-internals.h>
60 #include <mono/metadata/marshal.h>
61 #include <mono/metadata/gc-internals.h>
62 #include <mono/metadata/mono-gc.h>
63 #include <mono/metadata/rand.h>
64 #include <mono/metadata/sysmath.h>
65 #include <mono/metadata/string-icalls.h>
66 #include <mono/metadata/debug-helpers.h>
67 #include <mono/metadata/process.h>
68 #include <mono/metadata/environment.h>
69 #include <mono/metadata/profiler-private.h>
70 #include <mono/metadata/locales.h>
71 #include <mono/metadata/filewatcher.h>
72 #include <mono/metadata/security.h>
73 #include <mono/metadata/mono-config.h>
74 #include <mono/metadata/cil-coff.h>
75 #include <mono/metadata/number-formatter.h>
76 #include <mono/metadata/security-manager.h>
77 #include <mono/metadata/security-core-clr.h>
78 #include <mono/metadata/mono-perfcounters.h>
79 #include <mono/metadata/mono-debug.h>
80 #include <mono/metadata/mono-ptr-array.h>
81 #include <mono/metadata/verify-internals.h>
82 #include <mono/metadata/runtime.h>
83 #include <mono/metadata/file-mmap.h>
84 #include <mono/metadata/seq-points-data.h>
85 #include <mono/io-layer/io-layer.h>
86 #include <mono/utils/monobitset.h>
87 #include <mono/utils/mono-time.h>
88 #include <mono/utils/mono-proclib.h>
89 #include <mono/utils/mono-string.h>
90 #include <mono/utils/mono-error-internals.h>
91 #include <mono/utils/mono-mmap.h>
92 #include <mono/utils/mono-io-portability.h>
93 #include <mono/utils/mono-digest.h>
94 #include <mono/utils/bsearch.h>
95 #include <mono/utils/mono-os-mutex.h>
96 #include <mono/utils/mono-threads.h>
97
98 #if defined (HOST_WIN32)
99 #include <windows.h>
100 #include <shlobj.h>
101 #endif
102 #include "decimal-ms.h"
103 #include "number-ms.h"
104
105 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
106 #include <sys/utsname.h>
107 #endif
108
109 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
110
111 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
112
113 /* Lazy class loading functions */
114 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
115 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
116 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
119 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
120
121 static MonoArray*
122 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
123
124 static inline MonoBoolean
125 is_generic_parameter (MonoType *type)
126 {
127         return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
128 }
129
130 static void
131 mono_class_init_checked (MonoClass *klass, MonoError *error)
132 {
133         mono_error_init (error);
134
135         if (!mono_class_init (klass))
136                 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
137 }
138
139 ICALL_EXPORT MonoObject *
140 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
141 {
142         MonoError error;
143         MonoClass *ac;
144         gint32 esize;
145         gpointer *ea;
146         MonoObject *result = NULL;
147
148         ac = (MonoClass *)arr->obj.vtable->klass;
149
150         esize = mono_array_element_size (ac);
151         ea = (gpointer*)((char*)arr->vector + (pos * esize));
152
153         if (ac->element_class->valuetype) {
154                 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
155                 mono_error_set_pending_exception (&error);
156         } else
157                 result = (MonoObject *)*ea;
158         return result;
159 }
160
161 ICALL_EXPORT MonoObject *
162 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
163 {
164         MonoClass *ac, *ic;
165         MonoArray *io;
166         gint32 i, pos, *ind;
167
168         MONO_CHECK_ARG_NULL (idxs, NULL);
169
170         io = idxs;
171         ic = (MonoClass *)io->obj.vtable->klass;
172         
173         ac = (MonoClass *)arr->obj.vtable->klass;
174
175         g_assert (ic->rank == 1);
176         if (io->bounds != NULL || io->max_length !=  ac->rank) {
177                 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
178                 return NULL;
179         }
180
181         ind = (gint32 *)io->vector;
182
183         if (arr->bounds == NULL) {
184                 if (*ind < 0 || *ind >= arr->max_length) {
185                         mono_set_pending_exception (mono_get_exception_index_out_of_range ());
186                         return NULL;
187                 }
188
189                 return ves_icall_System_Array_GetValueImpl (arr, *ind);
190         }
191         
192         for (i = 0; i < ac->rank; i++) {
193                 if ((ind [i] < arr->bounds [i].lower_bound) ||
194                     (ind [i] >=  (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
195                         mono_set_pending_exception (mono_get_exception_index_out_of_range ());
196                         return NULL;
197                 }
198         }
199
200         pos = ind [0] - arr->bounds [0].lower_bound;
201         for (i = 1; i < ac->rank; i++)
202                 pos = pos * arr->bounds [i].length + ind [i] - 
203                         arr->bounds [i].lower_bound;
204
205         return ves_icall_System_Array_GetValueImpl (arr, pos);
206 }
207
208 ICALL_EXPORT void
209 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
210 {
211         MonoError error;
212         MonoClass *ac, *vc, *ec;
213         gint32 esize, vsize;
214         gpointer *ea, *va;
215         int et, vt;
216
217         guint64 u64 = 0;
218         gint64 i64 = 0;
219         gdouble r64 = 0;
220
221         mono_error_init (&error);
222
223         if (value)
224                 vc = value->vtable->klass;
225         else
226                 vc = NULL;
227
228         ac = arr->obj.vtable->klass;
229         ec = ac->element_class;
230
231         esize = mono_array_element_size (ac);
232         ea = (gpointer*)((char*)arr->vector + (pos * esize));
233         va = (gpointer*)((char*)value + sizeof (MonoObject));
234
235         if (mono_class_is_nullable (ec)) {
236                 mono_nullable_init ((guint8*)ea, value, ec);
237                 return;
238         }
239
240         if (!value) {
241                 mono_gc_bzero_atomic (ea, esize);
242                 return;
243         }
244
245 #define NO_WIDENING_CONVERSION G_STMT_START{\
246         mono_set_pending_exception (mono_get_exception_argument ( \
247                 "value", "not a widening conversion")); \
248         return; \
249 }G_STMT_END
250
251 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
252                 if (esize < vsize + (extra)) {                                                    \
253                         mono_set_pending_exception (mono_get_exception_argument (       \
254                         "value", "not a widening conversion")); \
255                         return;                                                                 \
256                 } \
257 }G_STMT_END
258
259 #define INVALID_CAST G_STMT_START{ \
260                 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
261         mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
262         return; \
263 }G_STMT_END
264
265         /* Check element (destination) type. */
266         switch (ec->byval_arg.type) {
267         case MONO_TYPE_STRING:
268                 switch (vc->byval_arg.type) {
269                 case MONO_TYPE_STRING:
270                         break;
271                 default:
272                         INVALID_CAST;
273                 }
274                 break;
275         case MONO_TYPE_BOOLEAN:
276                 switch (vc->byval_arg.type) {
277                 case MONO_TYPE_BOOLEAN:
278                         break;
279                 case MONO_TYPE_CHAR:
280                 case MONO_TYPE_U1:
281                 case MONO_TYPE_U2:
282                 case MONO_TYPE_U4:
283                 case MONO_TYPE_U8:
284                 case MONO_TYPE_I1:
285                 case MONO_TYPE_I2:
286                 case MONO_TYPE_I4:
287                 case MONO_TYPE_I8:
288                 case MONO_TYPE_R4:
289                 case MONO_TYPE_R8:
290                         NO_WIDENING_CONVERSION;
291                 default:
292                         INVALID_CAST;
293                 }
294                 break;
295         default:
296                 break;
297         }
298
299         if (!ec->valuetype) {
300                 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
301                 if (mono_error_set_pending_exception (&error))
302                         return;
303                 if (!castOk)
304                         INVALID_CAST;
305                 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
306                 return;
307         }
308
309         if (mono_object_isinst_checked (value, ec, &error)) {
310                 if (ec->has_references)
311                         mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
312                 else
313                         mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
314                 return;
315         }
316         if (mono_error_set_pending_exception (&error))
317                 return;
318
319         if (!vc->valuetype)
320                 INVALID_CAST;
321
322         vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
323
324         et = ec->byval_arg.type;
325         if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
326                 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
327
328         vt = vc->byval_arg.type;
329         if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
330                 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
331
332 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
333         switch (vt) { \
334         case MONO_TYPE_U1: \
335         case MONO_TYPE_U2: \
336         case MONO_TYPE_U4: \
337         case MONO_TYPE_U8: \
338         case MONO_TYPE_CHAR: \
339                 CHECK_WIDENING_CONVERSION(0); \
340                 *(etype *) ea = (etype) u64; \
341                 return; \
342         /* You can't assign a signed value to an unsigned array. */ \
343         case MONO_TYPE_I1: \
344         case MONO_TYPE_I2: \
345         case MONO_TYPE_I4: \
346         case MONO_TYPE_I8: \
347         /* You can't assign a floating point number to an integer array. */ \
348         case MONO_TYPE_R4: \
349         case MONO_TYPE_R8: \
350                 NO_WIDENING_CONVERSION; \
351         } \
352 }G_STMT_END
353
354 #define ASSIGN_SIGNED(etype) G_STMT_START{\
355         switch (vt) { \
356         case MONO_TYPE_I1: \
357         case MONO_TYPE_I2: \
358         case MONO_TYPE_I4: \
359         case MONO_TYPE_I8: \
360                 CHECK_WIDENING_CONVERSION(0); \
361                 *(etype *) ea = (etype) i64; \
362                 return; \
363         /* You can assign an unsigned value to a signed array if the array's */ \
364         /* element size is larger than the value size. */ \
365         case MONO_TYPE_U1: \
366         case MONO_TYPE_U2: \
367         case MONO_TYPE_U4: \
368         case MONO_TYPE_U8: \
369         case MONO_TYPE_CHAR: \
370                 CHECK_WIDENING_CONVERSION(1); \
371                 *(etype *) ea = (etype) u64; \
372                 return; \
373         /* You can't assign a floating point number to an integer array. */ \
374         case MONO_TYPE_R4: \
375         case MONO_TYPE_R8: \
376                 NO_WIDENING_CONVERSION; \
377         } \
378 }G_STMT_END
379
380 #define ASSIGN_REAL(etype) G_STMT_START{\
381         switch (vt) { \
382         case MONO_TYPE_R4: \
383         case MONO_TYPE_R8: \
384                 CHECK_WIDENING_CONVERSION(0); \
385                 *(etype *) ea = (etype) r64; \
386                 return; \
387         /* All integer values fit into a floating point array, so we don't */ \
388         /* need to CHECK_WIDENING_CONVERSION here. */ \
389         case MONO_TYPE_I1: \
390         case MONO_TYPE_I2: \
391         case MONO_TYPE_I4: \
392         case MONO_TYPE_I8: \
393                 *(etype *) ea = (etype) i64; \
394                 return; \
395         case MONO_TYPE_U1: \
396         case MONO_TYPE_U2: \
397         case MONO_TYPE_U4: \
398         case MONO_TYPE_U8: \
399         case MONO_TYPE_CHAR: \
400                 *(etype *) ea = (etype) u64; \
401                 return; \
402         } \
403 }G_STMT_END
404
405         switch (vt) {
406         case MONO_TYPE_U1:
407                 u64 = *(guint8 *) va;
408                 break;
409         case MONO_TYPE_U2:
410                 u64 = *(guint16 *) va;
411                 break;
412         case MONO_TYPE_U4:
413                 u64 = *(guint32 *) va;
414                 break;
415         case MONO_TYPE_U8:
416                 u64 = *(guint64 *) va;
417                 break;
418         case MONO_TYPE_I1:
419                 i64 = *(gint8 *) va;
420                 break;
421         case MONO_TYPE_I2:
422                 i64 = *(gint16 *) va;
423                 break;
424         case MONO_TYPE_I4:
425                 i64 = *(gint32 *) va;
426                 break;
427         case MONO_TYPE_I8:
428                 i64 = *(gint64 *) va;
429                 break;
430         case MONO_TYPE_R4:
431                 r64 = *(gfloat *) va;
432                 break;
433         case MONO_TYPE_R8:
434                 r64 = *(gdouble *) va;
435                 break;
436         case MONO_TYPE_CHAR:
437                 u64 = *(guint16 *) va;
438                 break;
439         case MONO_TYPE_BOOLEAN:
440                 /* Boolean is only compatible with itself. */
441                 switch (et) {
442                 case MONO_TYPE_CHAR:
443                 case MONO_TYPE_U1:
444                 case MONO_TYPE_U2:
445                 case MONO_TYPE_U4:
446                 case MONO_TYPE_U8:
447                 case MONO_TYPE_I1:
448                 case MONO_TYPE_I2:
449                 case MONO_TYPE_I4:
450                 case MONO_TYPE_I8:
451                 case MONO_TYPE_R4:
452                 case MONO_TYPE_R8:
453                         NO_WIDENING_CONVERSION;
454                 default:
455                         INVALID_CAST;
456                 }
457                 break;
458         }
459
460         /* If we can't do a direct copy, let's try a widening conversion. */
461         switch (et) {
462         case MONO_TYPE_CHAR:
463                 ASSIGN_UNSIGNED (guint16);
464         case MONO_TYPE_U1:
465                 ASSIGN_UNSIGNED (guint8);
466         case MONO_TYPE_U2:
467                 ASSIGN_UNSIGNED (guint16);
468         case MONO_TYPE_U4:
469                 ASSIGN_UNSIGNED (guint32);
470         case MONO_TYPE_U8:
471                 ASSIGN_UNSIGNED (guint64);
472         case MONO_TYPE_I1:
473                 ASSIGN_SIGNED (gint8);
474         case MONO_TYPE_I2:
475                 ASSIGN_SIGNED (gint16);
476         case MONO_TYPE_I4:
477                 ASSIGN_SIGNED (gint32);
478         case MONO_TYPE_I8:
479                 ASSIGN_SIGNED (gint64);
480         case MONO_TYPE_R4:
481                 ASSIGN_REAL (gfloat);
482         case MONO_TYPE_R8:
483                 ASSIGN_REAL (gdouble);
484         }
485
486         INVALID_CAST;
487         /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
488         return;
489
490 #undef INVALID_CAST
491 #undef NO_WIDENING_CONVERSION
492 #undef CHECK_WIDENING_CONVERSION
493 #undef ASSIGN_UNSIGNED
494 #undef ASSIGN_SIGNED
495 #undef ASSIGN_REAL
496 }
497
498 ICALL_EXPORT void 
499 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
500                                  MonoArray *idxs)
501 {
502         MonoClass *ac, *ic;
503         gint32 i, pos, *ind;
504
505         MONO_CHECK_ARG_NULL (idxs,);
506
507         ic = idxs->obj.vtable->klass;
508         ac = arr->obj.vtable->klass;
509
510         g_assert (ic->rank == 1);
511         if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
512                 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
513                 return;
514         }
515
516         ind = (gint32 *)idxs->vector;
517
518         if (arr->bounds == NULL) {
519                 if (*ind < 0 || *ind >= arr->max_length) {
520                         mono_set_pending_exception (mono_get_exception_index_out_of_range ());
521                         return;
522                 }
523
524                 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
525                 return;
526         }
527         
528         for (i = 0; i < ac->rank; i++)
529                 if ((ind [i] < arr->bounds [i].lower_bound) ||
530                     (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
531                         mono_set_pending_exception (mono_get_exception_index_out_of_range ());
532                         return;
533                 }
534
535         pos = ind [0] - arr->bounds [0].lower_bound;
536         for (i = 1; i < ac->rank; i++)
537                 pos = pos * arr->bounds [i].length + ind [i] - 
538                         arr->bounds [i].lower_bound;
539
540         ves_icall_System_Array_SetValueImpl (arr, value, pos);
541 }
542
543 ICALL_EXPORT MonoArray *
544 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
545 {
546         MonoError error;
547         MonoClass *aklass, *klass;
548         MonoArray *array;
549         uintptr_t *sizes, i;
550         gboolean bounded = FALSE;
551
552         MONO_CHECK_ARG_NULL (type, NULL);
553         MONO_CHECK_ARG_NULL (lengths, NULL);
554
555         MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
556         if (bounds)
557                 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
558
559         for (i = 0; i < mono_array_length (lengths); i++) {
560                 if (mono_array_get (lengths, gint32, i) < 0) {
561                         mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
562                         return NULL;
563                 }
564         }
565
566         klass = mono_class_from_mono_type (type->type);
567         mono_class_init_checked (klass, &error);
568         if (mono_error_set_pending_exception (&error))
569                 return NULL;
570
571         if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
572                 /* vectors are not the same as one dimensional arrays with no-zero bounds */
573                 bounded = TRUE;
574         else
575                 bounded = FALSE;
576
577         aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
578
579         sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
580         for (i = 0; i < aklass->rank; ++i) {
581                 sizes [i] = mono_array_get (lengths, guint32, i);
582                 if (bounds)
583                         sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
584                 else
585                         sizes [i + aklass->rank] = 0;
586         }
587
588         array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
589         mono_error_set_pending_exception (&error);
590
591         return array;
592 }
593
594 ICALL_EXPORT MonoArray *
595 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
596 {
597         MonoError error;
598         MonoClass *aklass, *klass;
599         MonoArray *array;
600         uintptr_t *sizes, i;
601         gboolean bounded = FALSE;
602
603         MONO_CHECK_ARG_NULL (type, NULL);
604         MONO_CHECK_ARG_NULL (lengths, NULL);
605
606         MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
607         if (bounds)
608                 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
609
610         for (i = 0; i < mono_array_length (lengths); i++) {
611                 if ((mono_array_get (lengths, gint64, i) < 0) ||
612                     (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
613                         mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
614                         return NULL;
615                 }
616         }
617
618         klass = mono_class_from_mono_type (type->type);
619         mono_class_init_checked (klass, &error);
620         if (mono_error_set_pending_exception (&error))
621                 return NULL;
622
623         if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
624                 /* vectors are not the same as one dimensional arrays with no-zero bounds */
625                 bounded = TRUE;
626         else
627                 bounded = FALSE;
628
629         aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
630
631         sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
632         for (i = 0; i < aklass->rank; ++i) {
633                 sizes [i] = mono_array_get (lengths, guint64, i);
634                 if (bounds)
635                         sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
636                 else
637                         sizes [i + aklass->rank] = 0;
638         }
639
640         array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
641         mono_error_set_pending_exception (&error);
642
643         return array;
644 }
645
646 ICALL_EXPORT gint32 
647 ves_icall_System_Array_GetRank (MonoObject *arr)
648 {
649         return arr->vtable->klass->rank;
650 }
651
652 ICALL_EXPORT gint32
653 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
654 {
655         gint32 rank = arr->obj.vtable->klass->rank;
656         uintptr_t length;
657
658         if ((dimension < 0) || (dimension >= rank)) {
659                 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
660                 return 0;
661         }
662         
663         if (arr->bounds == NULL)
664                 length = arr->max_length;
665         else
666                 length = arr->bounds [dimension].length;
667
668 #ifdef MONO_BIG_ARRAYS
669         if (length > G_MAXINT32) {
670                 mono_set_pending_exception (mono_get_exception_overflow ());
671                 return 0;
672         }
673 #endif
674         return length;
675 }
676
677 ICALL_EXPORT gint64
678 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
679 {
680         gint32 rank = arr->obj.vtable->klass->rank;
681
682         if ((dimension < 0) || (dimension >= rank)) {
683                 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
684                 return 0;
685         }
686         
687         if (arr->bounds == NULL)
688                 return arr->max_length;
689         
690         return arr->bounds [dimension].length;
691 }
692
693 ICALL_EXPORT gint32
694 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
695 {
696         gint32 rank = arr->obj.vtable->klass->rank;
697
698         if ((dimension < 0) || (dimension >= rank)) {
699                 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
700                 return 0;
701         }
702         
703         if (arr->bounds == NULL)
704                 return 0;
705         
706         return arr->bounds [dimension].lower_bound;
707 }
708
709 ICALL_EXPORT void
710 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
711 {
712         int sz = mono_array_element_size (mono_object_class (arr));
713         mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
714 }
715
716 ICALL_EXPORT MonoArray*
717 ves_icall_System_Array_Clone (MonoArray *arr)
718 {
719         MonoError error;
720         MonoArray *result = mono_array_clone_checked (arr, &error);
721         mono_error_set_pending_exception (&error);
722         return result;
723 }
724
725 ICALL_EXPORT gboolean
726 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
727 {
728         int element_size;
729         void * dest_addr;
730         void * source_addr;
731         MonoVTable *src_vtable;
732         MonoVTable *dest_vtable;
733         MonoClass *src_class;
734         MonoClass *dest_class;
735
736         src_vtable = source->obj.vtable;
737         dest_vtable = dest->obj.vtable;
738
739         if (src_vtable->rank != dest_vtable->rank)
740                 return FALSE;
741
742         if (source->bounds || dest->bounds)
743                 return FALSE;
744
745         /* there's no integer overflow since mono_array_length returns an unsigned integer */
746         if ((dest_idx + length > mono_array_length_fast (dest)) ||
747                 (source_idx + length > mono_array_length_fast (source)))
748                 return FALSE;
749
750         src_class = src_vtable->klass->element_class;
751         dest_class = dest_vtable->klass->element_class;
752
753         /*
754          * Handle common cases.
755          */
756
757         /* Case1: object[] -> valuetype[] (ArrayList::ToArray) 
758         We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
759         */
760         if (src_class == mono_defaults.object_class && dest_class->valuetype)
761                 return FALSE;
762
763         /* Check if we're copying a char[] <==> (u)short[] */
764         if (src_class != dest_class) {
765                 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
766                         return FALSE;
767
768                 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
769                 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
770                         return FALSE;
771         }
772
773         if (dest_class->valuetype) {
774                 element_size = mono_array_element_size (source->obj.vtable->klass);
775                 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
776                 if (dest_class->has_references) {
777                         mono_value_copy_array (dest, dest_idx, source_addr, length);
778                 } else {
779                         dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
780                         mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
781                 }
782         } else {
783                 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
784         }
785
786         return TRUE;
787 }
788
789 ICALL_EXPORT void
790 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
791 {
792         MonoClass *ac;
793         gint32 esize;
794         gpointer *ea;
795
796         ac = (MonoClass *)arr->obj.vtable->klass;
797
798         esize = mono_array_element_size (ac);
799         ea = (gpointer*)((char*)arr->vector + (pos * esize));
800
801         mono_gc_memmove_atomic (value, ea, esize);
802 }
803
804 ICALL_EXPORT void
805 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
806 {
807         MonoClass *ac, *ec;
808         gint32 esize;
809         gpointer *ea;
810
811         ac = (MonoClass *)arr->obj.vtable->klass;
812         ec = ac->element_class;
813
814         esize = mono_array_element_size (ac);
815         ea = (gpointer*)((char*)arr->vector + (pos * esize));
816
817         if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
818                 g_assert (esize == sizeof (gpointer));
819                 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
820         } else {
821                 g_assert (ec->inited);
822                 g_assert (esize == mono_class_value_size (ec, NULL));
823                 if (ec->has_references)
824                         mono_gc_wbarrier_value_copy (ea, value, 1, ec);
825                 else
826                         mono_gc_memmove_atomic (ea, value, esize);
827         }
828 }
829
830 ICALL_EXPORT void
831 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
832 {
833         MonoClass *klass = array->obj.vtable->klass;
834         guint32 size = mono_array_element_size (klass);
835         MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
836         int align;
837         const char *field_data;
838
839         if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
840                 MonoException *exc = mono_get_exception_argument("array",
841                         "Cannot initialize array of non-primitive type.");
842                 mono_set_pending_exception (exc);
843                 return;
844         }
845
846         if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
847                 MonoException *exc = mono_get_exception_argument("field_handle",
848                         "Field doesn't have an RVA");
849                 mono_set_pending_exception (exc);
850                 return;
851         }
852
853         size *= array->max_length;
854         field_data = mono_field_get_data (field_handle);
855
856         if (size > mono_type_size (field_handle->type, &align)) {
857                 MonoException *exc = mono_get_exception_argument("field_handle",
858                         "Field not large enough to fill array");
859                 mono_set_pending_exception (exc);
860                 return;
861         }
862
863 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
864 #define SWAP(n) {                                                               \
865         guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0);     \
866         guint ## n *src = (guint ## n *) field_data;                            \
867         int i,                                                                  \
868             nEnt = (size / sizeof(guint ## n));                                 \
869                                                                                 \
870         for (i = 0; i < nEnt; i++) {                                            \
871                 data[i] = read ## n (&src[i]);                                  \
872         }                                                                       \
873 }
874
875         /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
876
877         switch (type->type) {
878         case MONO_TYPE_CHAR:
879         case MONO_TYPE_I2:
880         case MONO_TYPE_U2:
881                 SWAP (16);
882                 break;
883         case MONO_TYPE_I4:
884         case MONO_TYPE_U4:
885         case MONO_TYPE_R4:
886                 SWAP (32);
887                 break;
888         case MONO_TYPE_I8:
889         case MONO_TYPE_U8:
890         case MONO_TYPE_R8:
891                 SWAP (64);
892                 break;
893         default:
894                 memcpy (mono_array_addr (array, char, 0), field_data, size);
895                 break;
896         }
897 #else
898         memcpy (mono_array_addr (array, char, 0), field_data, size);
899 #endif
900 }
901
902 ICALL_EXPORT gint
903 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
904 {
905         return offsetof (MonoString, chars);
906 }
907
908 ICALL_EXPORT MonoObject *
909 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
910 {
911         if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
912                 return obj;
913         else {
914                 MonoError error;
915                 MonoObject *ret = mono_object_clone_checked (obj, &error);
916                 mono_error_set_pending_exception (&error);
917
918                 return ret;
919         }
920 }
921
922 ICALL_EXPORT void
923 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
924 {
925         MonoError error;
926         MonoClass *klass;
927         MonoVTable *vtable;
928
929         MONO_CHECK_ARG_NULL (handle,);
930
931         klass = mono_class_from_mono_type (handle);
932         MONO_CHECK_ARG (handle, klass,);
933
934         if (klass->generic_container)
935                 return;
936
937         vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
938         if (!is_ok (&error)) {
939                 mono_error_set_pending_exception (&error);
940                 return;
941         }
942
943         /* This will call the type constructor */
944         if (!mono_runtime_class_init_full (vtable, &error))
945                 mono_error_set_pending_exception (&error);
946 }
947
948 ICALL_EXPORT void
949 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
950 {
951         MonoError error;
952
953         mono_image_check_for_module_cctor (image);
954         if (image->has_module_cctor) {
955                 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
956                 if (!mono_error_ok (&error)) {
957                         mono_error_set_pending_exception (&error);
958                         return;
959                 }
960                 /*It's fine to raise the exception here*/
961                 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
962                 if (!is_ok (&error)) {
963                         mono_error_set_pending_exception (&error);
964                         return;
965                 }
966                 if (!mono_runtime_class_init_full (vtable, &error))
967                         mono_error_set_pending_exception (&error);
968         }
969 }
970
971 ICALL_EXPORT MonoBoolean
972 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
973 {
974         guint8 *stack_addr;
975         guint8 *current;
976         size_t stack_size;
977         /* later make this configurable and per-arch */
978         int min_size = 4096 * 4 * sizeof (void*);
979         mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
980         /* if we have no info we are optimistic and assume there is enough room */
981         if (!stack_addr)
982                 return TRUE;
983 #ifdef HOST_WIN32
984         // FIXME: Windows dynamically extends the stack, so stack_addr might be close
985         // to the current sp
986         return TRUE;
987 #endif
988         current = (guint8 *)&stack_addr;
989         if (current > stack_addr) {
990                 if ((current - stack_addr) < min_size)
991                         return FALSE;
992         } else {
993                 if (current - (stack_addr - stack_size) < min_size)
994                         return FALSE;
995         }
996         return TRUE;
997 }
998
999 ICALL_EXPORT MonoObject *
1000 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1001 {
1002         MonoError error;
1003         MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1004         mono_error_set_pending_exception (&error);
1005
1006         return ret;
1007 }
1008
1009 ICALL_EXPORT gint32
1010 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1011 {
1012         MonoError error;
1013         MonoClass *klass;
1014         MonoObject **values = NULL;
1015         MonoObject *o;
1016         int count = 0;
1017         gint32 result = (int)(gsize)mono_defaults.int32_class;
1018         MonoClassField* field;
1019         gpointer iter;
1020
1021         klass = mono_object_class (this_obj);
1022
1023         if (mono_class_num_fields (klass) == 0)
1024                 return result;
1025
1026         /*
1027          * Compute the starting value of the hashcode for fields of primitive
1028          * types, and return the remaining fields in an array to the managed side.
1029          * This way, we can avoid costly reflection operations in managed code.
1030          */
1031         iter = NULL;
1032         while ((field = mono_class_get_fields (klass, &iter))) {
1033                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1034                         continue;
1035                 if (mono_field_is_deleted (field))
1036                         continue;
1037                 /* FIXME: Add more types */
1038                 switch (field->type->type) {
1039                 case MONO_TYPE_I4:
1040                         result ^= *(gint32*)((guint8*)this_obj + field->offset);
1041                         break;
1042                 case MONO_TYPE_STRING: {
1043                         MonoString *s;
1044                         s = *(MonoString**)((guint8*)this_obj + field->offset);
1045                         if (s != NULL)
1046                                 result ^= mono_string_hash (s);
1047                         break;
1048                 }
1049                 default:
1050                         if (!values)
1051                                 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1052                         o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1053                         if (!is_ok (&error)) {
1054                                 mono_error_set_pending_exception (&error);
1055                                 return 0;
1056                         }
1057                         values [count++] = o;
1058                 }
1059         }
1060
1061         if (values) {
1062                 int i;
1063                 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1064                 if (mono_error_set_pending_exception (&error))
1065                         return 0;
1066                 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1067                 for (i = 0; i < count; ++i)
1068                         mono_array_setref (*fields, i, values [i]);
1069         } else {
1070                 *fields = NULL;
1071         }
1072         return result;
1073 }
1074
1075 ICALL_EXPORT MonoBoolean
1076 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1077 {
1078         MonoError error;
1079         MonoClass *klass;
1080         MonoObject **values = NULL;
1081         MonoObject *o;
1082         MonoClassField* field;
1083         gpointer iter;
1084         int count = 0;
1085
1086         MONO_CHECK_ARG_NULL (that, FALSE);
1087
1088         if (this_obj->vtable != that->vtable)
1089                 return FALSE;
1090
1091         klass = mono_object_class (this_obj);
1092
1093         if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1094                 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1095
1096         /*
1097          * Do the comparison for fields of primitive type and return a result if
1098          * possible. Otherwise, return the remaining fields in an array to the 
1099          * managed side. This way, we can avoid costly reflection operations in 
1100          * managed code.
1101          */
1102         *fields = NULL;
1103         iter = NULL;
1104         while ((field = mono_class_get_fields (klass, &iter))) {
1105                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1106                         continue;
1107                 if (mono_field_is_deleted (field))
1108                         continue;
1109                 /* FIXME: Add more types */
1110                 switch (field->type->type) {
1111                 case MONO_TYPE_U1:
1112                 case MONO_TYPE_I1:
1113                 case MONO_TYPE_BOOLEAN:
1114                         if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1115                                 return FALSE;
1116                         break;
1117                 case MONO_TYPE_U2:
1118                 case MONO_TYPE_I2:
1119                 case MONO_TYPE_CHAR:
1120                         if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1121                                 return FALSE;
1122                         break;
1123                 case MONO_TYPE_U4:
1124                 case MONO_TYPE_I4:
1125                         if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1126                                 return FALSE;
1127                         break;
1128                 case MONO_TYPE_U8:
1129                 case MONO_TYPE_I8:
1130                         if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1131                                 return FALSE;
1132                         break;
1133                 case MONO_TYPE_R4:
1134                         if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1135                                 return FALSE;
1136                         break;
1137                 case MONO_TYPE_R8:
1138                         if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1139                                 return FALSE;
1140                         break;
1141
1142
1143                 case MONO_TYPE_STRING: {
1144                         MonoString *s1, *s2;
1145                         guint32 s1len, s2len;
1146                         s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1147                         s2 = *(MonoString**)((guint8*)that + field->offset);
1148                         if (s1 == s2)
1149                                 break;
1150                         if ((s1 == NULL) || (s2 == NULL))
1151                                 return FALSE;
1152                         s1len = mono_string_length (s1);
1153                         s2len = mono_string_length (s2);
1154                         if (s1len != s2len)
1155                                 return FALSE;
1156
1157                         if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1158                                 return FALSE;
1159                         break;
1160                 }
1161                 default:
1162                         if (!values)
1163                                 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1164                         o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1165                         if (!is_ok (&error)) {
1166                                 mono_error_set_pending_exception (&error);
1167                                 return FALSE;
1168                         }
1169                         values [count++] = o;
1170                         o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1171                         if (!is_ok (&error)) {
1172                                 mono_error_set_pending_exception (&error);
1173                                 return FALSE;
1174                         }
1175                         values [count++] = o;
1176                 }
1177
1178                 if (klass->enumtype)
1179                         /* enums only have one non-static field */
1180                         break;
1181         }
1182
1183         if (values) {
1184                 int i;
1185                 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1186                 if (mono_error_set_pending_exception (&error))
1187                         return FALSE;
1188                 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1189                 for (i = 0; i < count; ++i)
1190                         mono_array_setref_fast (*fields, i, values [i]);
1191                 return FALSE;
1192         } else {
1193                 return TRUE;
1194         }
1195 }
1196
1197 ICALL_EXPORT MonoReflectionType *
1198 ves_icall_System_Object_GetType (MonoObject *obj)
1199 {
1200         MonoError error;
1201         MonoReflectionType *ret;
1202 #ifndef DISABLE_REMOTING
1203         if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1204                 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1205         else
1206 #endif
1207                 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1208
1209         mono_error_set_pending_exception (&error);
1210         return ret;
1211 }
1212
1213 ICALL_EXPORT void
1214 ves_icall_MonoType_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1215 {
1216         mtype->type = &obj->vtable->klass->byval_arg;
1217         g_assert (mtype->type->type);
1218 }
1219
1220 ICALL_EXPORT gint32
1221 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1222 {
1223         MONO_CHECK_ARG_NULL (obj, 0);
1224         
1225         MonoError error;
1226         gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1227         mono_error_set_pending_exception (&error);
1228         return result;
1229 }
1230
1231 ICALL_EXPORT gint32
1232 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1233                                         MonoReflectionMethod *method,
1234                                         MonoArray *opt_param_types)
1235 {
1236         MONO_CHECK_ARG_NULL (method, 0);
1237         
1238         MonoError error;
1239         gint32 result = mono_image_create_method_token (
1240                 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1241         mono_error_set_pending_exception (&error);
1242         return result;
1243 }
1244
1245 ICALL_EXPORT void
1246 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1247 {
1248         MonoError error;
1249         mono_image_create_pefile (mb, file, &error);
1250         mono_error_set_pending_exception (&error);
1251 }
1252
1253 ICALL_EXPORT void
1254 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1255 {
1256         MonoError error;
1257         mono_image_build_metadata (mb, &error);
1258         mono_error_set_pending_exception (&error);
1259 }
1260
1261 ICALL_EXPORT void
1262 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1263 {
1264         mono_image_register_token (mb->dynamic_image, token, obj);
1265 }
1266
1267 ICALL_EXPORT MonoObject*
1268 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1269 {
1270         MonoObject *obj;
1271
1272         mono_loader_lock ();
1273         obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1274         mono_loader_unlock ();
1275
1276         return obj;
1277 }
1278
1279 ICALL_EXPORT MonoReflectionModule*
1280 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1281 {
1282         MonoError error;
1283         MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1284         mono_error_set_pending_exception (&error);
1285         return result;
1286 }
1287
1288 /**
1289  * ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class:
1290  * @tb: a TypeBuilder object
1291  *
1292  * (icall)
1293  * Creates the generic class after all generic parameters have been added.
1294  */
1295 ICALL_EXPORT void
1296 ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class (MonoReflectionTypeBuilder *tb)
1297 {
1298         MonoError error;
1299         (void) mono_reflection_create_generic_class (tb, &error);
1300         mono_error_set_pending_exception (&error);
1301 }
1302
1303 #ifndef DISABLE_REFLECTION_EMIT
1304 ICALL_EXPORT MonoArray*
1305 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1306 {
1307         MonoError error;
1308         MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1309         mono_error_set_pending_exception (&error);
1310         return result;
1311 }
1312 #endif
1313
1314 static gboolean
1315 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1316 {
1317         MonoMethod **dest = (MonoMethod **)data;
1318
1319         /* skip unmanaged frames */
1320         if (!managed)
1321                 return FALSE;
1322
1323         if (!(*dest)) {
1324                 if (!strcmp (m->klass->name_space, "System.Reflection"))
1325                         return FALSE;
1326                 *dest = m;
1327                 return TRUE;
1328         }
1329         return FALSE;
1330 }
1331
1332 static gboolean
1333 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1334 {
1335         MonoMethod **dest = (MonoMethod **)data;
1336
1337         /* skip unmanaged frames */
1338         if (!managed)
1339                 return FALSE;
1340
1341         if (m->wrapper_type != MONO_WRAPPER_NONE)
1342                 return FALSE;
1343
1344         if (m == *dest) {
1345                 *dest = NULL;
1346                 return FALSE;
1347         }
1348
1349         if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1350                 return FALSE;
1351
1352         if (!(*dest)) {
1353                 *dest = m;
1354                 return TRUE;
1355         }
1356         return FALSE;
1357 }
1358
1359 static gboolean
1360 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1361 {
1362         MonoMethod **dest = (MonoMethod **)data;
1363
1364         /* skip unmanaged frames */
1365         if (!managed)
1366                 return FALSE;
1367
1368         if (m->wrapper_type != MONO_WRAPPER_NONE)
1369                 return FALSE;
1370
1371         if (m == *dest) {
1372                 *dest = NULL;
1373                 return FALSE;
1374         }
1375
1376         if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1377                                                                                                         || (!strcmp (m->klass->name_space, "System"))))
1378                 return FALSE;
1379
1380         if (!(*dest)) {
1381                 *dest = m;
1382                 return TRUE;
1383         }
1384         return FALSE;
1385 }
1386
1387 static MonoReflectionType *
1388 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1389 {
1390         MonoMethod *m, *dest;
1391
1392         MonoType *type = NULL;
1393         MonoAssembly *assembly = NULL;
1394         gboolean type_resolve = FALSE;
1395         MonoImage *rootimage = NULL;
1396
1397         mono_error_init (error);
1398
1399         /*
1400          * We must compute the calling assembly as type loading must happen under a metadata context.
1401          * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1402          * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1403          */
1404         m = mono_method_get_last_managed ();
1405         dest = m;
1406         if (m && m->klass->image != mono_defaults.corlib) {
1407                 /* Happens with inlining */
1408         } else {
1409                 /* Ugly hack: type_from_parsed_name is called from
1410                  * System.Type.internal_from_name, which is called most
1411                  * directly from System.Type.GetType(string,bool,bool) but
1412                  * also indirectly from places such as
1413                  * System.Type.GetType(string,func,func) (via
1414                  * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1415                  * so we need to skip over all of those to find the true caller.
1416                  *
1417                  * It would be nice if we had stack marks.
1418                  */
1419                 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1420                 if (!dest)
1421                         dest = m;
1422         }
1423
1424         /*
1425          * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1426          *        causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1427          *        to crash.  This only seems to happen in some strange remoting
1428          *        scenarios and I was unable to figure out what's happening there.
1429          *        Dec 10, 2005 - Martin.
1430          */
1431
1432         if (dest) {
1433                 assembly = dest->klass->image->assembly;
1434                 type_resolve = TRUE;
1435                 rootimage = assembly->image;
1436         } else {
1437                 g_warning (G_STRLOC);
1438         }
1439
1440         if (info->assembly.name)
1441                 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1442
1443         if (assembly) {
1444                 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1445                 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1446                 return_val_if_nok (error, NULL);
1447         }
1448
1449         // XXXX - aleksey -
1450         //  Say we're looking for System.Generic.Dict<int, Local>
1451         //  we FAIL the get type above, because S.G.Dict isn't in assembly->image.  So we drop down here.
1452         //  but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1453         //  is messed up when we go to construct the Local as the type arg...
1454         //
1455         // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1456         // as the root and then even the detour into generics would still not screw us when we went to load Local.
1457         if (!info->assembly.name && !type) {
1458                 /* try mscorlib */
1459                 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1460                 return_val_if_nok (error, NULL);
1461         }
1462         if (assembly && !type && type_resolve) {
1463                 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1464                 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1465                 return_val_if_nok (error, NULL);
1466         }
1467
1468         if (!type) 
1469                 return NULL;
1470
1471         return mono_type_get_object_checked (mono_domain_get (), type, error);
1472 }
1473
1474 ICALL_EXPORT MonoReflectionType*
1475 ves_icall_System_Type_internal_from_name (MonoString *name,
1476                                                                                   MonoBoolean throwOnError,
1477                                                                                   MonoBoolean ignoreCase)
1478 {
1479         MonoError error;
1480         char *str = mono_string_to_utf8 (name);
1481         MonoTypeNameParse info;
1482         MonoReflectionType *type;
1483         gboolean parsedOk;
1484
1485         parsedOk = mono_reflection_parse_type (str, &info);
1486
1487         /* mono_reflection_parse_type() mangles the string */
1488         if (!parsedOk) {
1489                 mono_reflection_free_type_info (&info);
1490                 if (throwOnError) {
1491                         mono_error_init (&error);
1492                         mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1493                         mono_error_set_pending_exception (&error);
1494                 }
1495                 g_free (str);
1496                 return NULL;
1497         }
1498
1499         type = type_from_parsed_name (&info, ignoreCase, &error);
1500
1501         mono_reflection_free_type_info (&info);
1502         g_free (str);
1503
1504         if (!mono_error_ok (&error)) {
1505                 if (throwOnError)
1506                         mono_error_set_pending_exception (&error);
1507                 else
1508                         mono_error_cleanup (&error);
1509                 return NULL;
1510         }
1511
1512         if (type == NULL){
1513                 MonoException *e = NULL;
1514                 
1515                 if (throwOnError)
1516                         e = mono_get_exception_type_load (name, NULL);
1517
1518                 if (e) {
1519                         mono_set_pending_exception (e);
1520                         return NULL;
1521                 }
1522         }
1523         
1524         return type;
1525 }
1526
1527
1528 ICALL_EXPORT MonoReflectionType*
1529 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1530 {
1531         MonoError error;
1532         MonoReflectionType *ret;
1533         MonoDomain *domain = mono_domain_get (); 
1534
1535         ret = mono_type_get_object_checked (domain, handle, &error);
1536         mono_error_set_pending_exception (&error);
1537
1538         return ret;
1539 }
1540
1541 /* System.TypeCode */
1542 typedef enum {
1543         TYPECODE_EMPTY,
1544         TYPECODE_OBJECT,
1545         TYPECODE_DBNULL,
1546         TYPECODE_BOOLEAN,
1547         TYPECODE_CHAR,
1548         TYPECODE_SBYTE,
1549         TYPECODE_BYTE,
1550         TYPECODE_INT16,
1551         TYPECODE_UINT16,
1552         TYPECODE_INT32,
1553         TYPECODE_UINT32,
1554         TYPECODE_INT64,
1555         TYPECODE_UINT64,
1556         TYPECODE_SINGLE,
1557         TYPECODE_DOUBLE,
1558         TYPECODE_DECIMAL,
1559         TYPECODE_DATETIME,
1560         TYPECODE_STRING = 18
1561 } TypeCode;
1562
1563 ICALL_EXPORT guint32
1564 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1565 {
1566         int t = type->type->type;
1567
1568         if (type->type->byref)
1569                 return TYPECODE_OBJECT;
1570
1571 handle_enum:
1572         switch (t) {
1573         case MONO_TYPE_VOID:
1574                 return TYPECODE_OBJECT;
1575         case MONO_TYPE_BOOLEAN:
1576                 return TYPECODE_BOOLEAN;
1577         case MONO_TYPE_U1:
1578                 return TYPECODE_BYTE;
1579         case MONO_TYPE_I1:
1580                 return TYPECODE_SBYTE;
1581         case MONO_TYPE_U2:
1582                 return TYPECODE_UINT16;
1583         case MONO_TYPE_I2:
1584                 return TYPECODE_INT16;
1585         case MONO_TYPE_CHAR:
1586                 return TYPECODE_CHAR;
1587         case MONO_TYPE_PTR:
1588         case MONO_TYPE_U:
1589         case MONO_TYPE_I:
1590                 return TYPECODE_OBJECT;
1591         case MONO_TYPE_U4:
1592                 return TYPECODE_UINT32;
1593         case MONO_TYPE_I4:
1594                 return TYPECODE_INT32;
1595         case MONO_TYPE_U8:
1596                 return TYPECODE_UINT64;
1597         case MONO_TYPE_I8:
1598                 return TYPECODE_INT64;
1599         case MONO_TYPE_R4:
1600                 return TYPECODE_SINGLE;
1601         case MONO_TYPE_R8:
1602                 return TYPECODE_DOUBLE;
1603         case MONO_TYPE_VALUETYPE: {
1604                 MonoClass *klass = type->type->data.klass;
1605                 
1606                 if (klass->enumtype) {
1607                         t = mono_class_enum_basetype (klass)->type;
1608                         goto handle_enum;
1609                 } else if (mono_is_corlib_image (klass->image)) {
1610                         if (strcmp (klass->name_space, "System") == 0) {
1611                                 if (strcmp (klass->name, "Decimal") == 0)
1612                                         return TYPECODE_DECIMAL;
1613                                 else if (strcmp (klass->name, "DateTime") == 0)
1614                                         return TYPECODE_DATETIME;
1615                         }
1616                 }
1617                 return TYPECODE_OBJECT;
1618         }
1619         case MONO_TYPE_STRING:
1620                 return TYPECODE_STRING;
1621         case MONO_TYPE_SZARRAY:
1622         case MONO_TYPE_ARRAY:
1623         case MONO_TYPE_OBJECT:
1624         case MONO_TYPE_VAR:
1625         case MONO_TYPE_MVAR:
1626         case MONO_TYPE_TYPEDBYREF:
1627                 return TYPECODE_OBJECT;
1628         case MONO_TYPE_CLASS:
1629                 {
1630                         MonoClass *klass =  type->type->data.klass;
1631                         if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1632                                 if (strcmp (klass->name, "DBNull") == 0)
1633                                         return TYPECODE_DBNULL;
1634                         }
1635                 }
1636                 return TYPECODE_OBJECT;
1637         case MONO_TYPE_GENERICINST:
1638                 return TYPECODE_OBJECT;
1639         default:
1640                 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1641         }
1642         return 0;
1643 }
1644
1645 static gboolean
1646 mono_type_is_primitive (MonoType *type)
1647 {
1648         return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1649                         type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1650 }
1651
1652 static MonoType*
1653 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1654 {
1655         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1656                 return mono_class_enum_basetype (type->data.klass);
1657         if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1658                 return mono_class_enum_basetype (type->data.generic_class->container_class);
1659         return type;
1660 }
1661
1662 ICALL_EXPORT guint32
1663 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1664 {
1665         MonoClass *klass;
1666         MonoClass *klassc;
1667
1668         g_assert (type != NULL);
1669         
1670         klass = mono_class_from_mono_type (type->type);
1671         klassc = mono_class_from_mono_type (c->type);
1672
1673         if (type->type->byref ^ c->type->byref)
1674                 return FALSE;
1675
1676         if (type->type->byref) {
1677                 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1678                 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1679
1680                 klass = mono_class_from_mono_type (t);
1681                 klassc = mono_class_from_mono_type (ot);
1682
1683                 if (mono_type_is_primitive (t)) {
1684                         return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1685                 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1686                         return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1687                 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1688                         return t->type == ot->type;
1689                 } else {
1690                          if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1691                                  return FALSE;
1692
1693                          if (klass->valuetype)
1694                                 return klass == klassc;
1695                         return klass->valuetype == klassc->valuetype;
1696                 }
1697         }
1698         return mono_class_is_assignable_from (klass, klassc);
1699 }
1700
1701 ICALL_EXPORT guint32
1702 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1703 {
1704         MonoError error;
1705         MonoClass *klass = mono_class_from_mono_type (type->type);
1706         mono_class_init_checked (klass, &error);
1707         if (!is_ok (&error)) {
1708                 mono_error_set_pending_exception (&error);
1709                 return FALSE;
1710         }
1711         guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1712         mono_error_set_pending_exception (&error);
1713         return result;
1714 }
1715
1716 ICALL_EXPORT guint32
1717 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1718 {
1719         MonoClass *klass = mono_class_from_mono_type (type->type);
1720         return klass->flags;
1721 }
1722
1723 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1724 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1725 {
1726         MonoError error;
1727         MonoClass *klass = field->field->parent;
1728         MonoMarshalType *info;
1729         MonoType *ftype;
1730         int i;
1731
1732         if (klass->generic_container ||
1733             (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1734                 return NULL;
1735
1736         ftype = mono_field_get_type (field->field);
1737         if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1738                 return NULL;
1739
1740         info = mono_marshal_load_type_info (klass);
1741
1742         for (i = 0; i < info->num_fields; ++i) {
1743                 if (info->fields [i].field == field->field) {
1744                         if (!info->fields [i].mspec)
1745                                 return NULL;
1746                         else {
1747                                 MonoReflectionMarshalAsAttribute* obj;
1748                                 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1749                                 if (!mono_error_ok (&error))
1750                                         mono_error_set_pending_exception (&error);
1751                                 return obj;
1752                         }
1753                 }
1754         }
1755
1756         return NULL;
1757 }
1758
1759 ICALL_EXPORT MonoReflectionField*
1760 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1761 {
1762         MonoError error;
1763         gboolean found = FALSE;
1764         MonoClass *klass;
1765         MonoClass *k;
1766
1767         g_assert (handle);
1768
1769         if (!type) {
1770                 klass = handle->parent;
1771         } else {
1772                 klass = mono_class_from_mono_type (type);
1773
1774                 /* Check that the field belongs to the class */
1775                 for (k = klass; k; k = k->parent) {
1776                         if (k == handle->parent) {
1777                                 found = TRUE;
1778                                 break;
1779                         }
1780                 }
1781
1782                 if (!found)
1783                         /* The managed code will throw the exception */
1784                         return NULL;
1785         }
1786
1787         MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1788         mono_error_set_pending_exception (&error);
1789         return result;
1790 }
1791
1792 ICALL_EXPORT MonoArray*
1793 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1794 {
1795         MonoError error;
1796         MonoType *type = mono_field_get_type_checked (field->field, &error);
1797         MonoArray *res;
1798
1799         if (!mono_error_ok (&error)) {
1800                 mono_error_set_pending_exception (&error);
1801                 return NULL;
1802         }
1803
1804         res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1805         mono_error_set_pending_exception (&error);
1806         return res;
1807 }
1808
1809 ICALL_EXPORT int
1810 vell_icall_get_method_attributes (MonoMethod *method)
1811 {
1812         return method->flags;
1813 }
1814
1815 ICALL_EXPORT void
1816 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1817 {
1818         MonoError error;
1819         MonoReflectionType *rt;
1820         MonoDomain *domain = mono_domain_get ();
1821         MonoMethodSignature* sig;
1822
1823         sig = mono_method_signature_checked (method, &error);
1824         if (!mono_error_ok (&error)) {
1825                 mono_error_set_pending_exception (&error);
1826                 return;
1827         }
1828
1829         rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1830         if (!mono_error_ok (&error)) {
1831                 mono_error_set_pending_exception (&error);
1832                 return;
1833         }
1834
1835         MONO_STRUCT_SETREF (info, parent, rt);
1836
1837         rt = mono_type_get_object_checked (domain, sig->ret, &error);
1838         if (!mono_error_ok (&error)) {
1839                 mono_error_set_pending_exception (&error);
1840                 return;
1841         }
1842
1843         MONO_STRUCT_SETREF (info, ret, rt);
1844
1845         info->attrs = method->flags;
1846         info->implattrs = method->iflags;
1847         if (sig->call_convention == MONO_CALL_DEFAULT)
1848                 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1849         else {
1850                 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1851                         info->callconv = 2;
1852                 else
1853                         info->callconv = 1;
1854         }
1855         info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6); 
1856 }
1857
1858 ICALL_EXPORT MonoArray*
1859 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1860 {
1861         MonoError error;
1862         MonoDomain *domain = mono_domain_get (); 
1863
1864         MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1865         mono_error_set_pending_exception (&error);
1866         return result;
1867 }
1868
1869 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1870 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1871 {
1872         MonoError error;
1873         MonoDomain *domain = mono_domain_get (); 
1874         MonoReflectionMarshalAsAttribute* res = NULL;
1875         MonoMarshalSpec **mspecs;
1876         int i;
1877
1878         mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1879         mono_method_get_marshal_info (method, mspecs);
1880
1881         if (mspecs [0]) {
1882                 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1883                 if (!mono_error_ok (&error)) {
1884                         mono_error_set_pending_exception (&error);
1885                         return NULL;
1886                 }
1887         }
1888                 
1889         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1890                 if (mspecs [i])
1891                         mono_metadata_free_marshal_spec (mspecs [i]);
1892         g_free (mspecs);
1893
1894         return res;
1895 }
1896
1897 ICALL_EXPORT gint32
1898 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1899 {
1900         MonoClass *parent = field->field->parent;
1901         if (!parent->size_inited)
1902                 mono_class_init (parent);
1903         mono_class_setup_fields_locking (parent);
1904
1905         return field->field->offset - sizeof (MonoObject);
1906 }
1907
1908 ICALL_EXPORT MonoReflectionType*
1909 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1910 {
1911         MonoError error;
1912         MonoReflectionType *ret;
1913         MonoClass *parent;
1914
1915         parent = declaring? field->field->parent: field->klass;
1916
1917         ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1918         mono_error_set_pending_exception (&error);
1919
1920         return ret;
1921
1922 }
1923
1924 ICALL_EXPORT MonoObject *
1925 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1926 {       
1927         MonoError error;
1928         MonoClass *fklass = field->klass;
1929         MonoClassField *cf = field->field;
1930         MonoDomain *domain = mono_object_domain (field);
1931
1932         if (fklass->image->assembly->ref_only) {
1933                 mono_set_pending_exception (mono_get_exception_invalid_operation (
1934                                         "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1935                 return NULL;
1936         }
1937
1938         if (mono_security_core_clr_enabled () &&
1939             !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1940                 mono_error_set_pending_exception (&error);
1941                 return NULL;
1942         }
1943
1944         MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1945         mono_error_set_pending_exception (&error);
1946         return result;
1947 }
1948
1949 ICALL_EXPORT void
1950 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1951 {
1952         MonoError error;
1953         MonoClassField *cf = field->field;
1954         MonoType *type;
1955         gchar *v;
1956
1957         if (field->klass->image->assembly->ref_only) {
1958                 mono_set_pending_exception (mono_get_exception_invalid_operation (
1959                                         "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1960                 return;
1961         }
1962
1963         if (mono_security_core_clr_enabled () &&
1964             !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1965                 mono_error_set_pending_exception (&error);
1966                 return;
1967         }
1968
1969         type = mono_field_get_type_checked (cf, &error);
1970         if (!mono_error_ok (&error)) {
1971                 mono_error_set_pending_exception (&error);
1972                 return;
1973         }
1974
1975         v = (gchar *) value;
1976         if (!type->byref) {
1977                 switch (type->type) {
1978                 case MONO_TYPE_U1:
1979                 case MONO_TYPE_I1:
1980                 case MONO_TYPE_BOOLEAN:
1981                 case MONO_TYPE_U2:
1982                 case MONO_TYPE_I2:
1983                 case MONO_TYPE_CHAR:
1984                 case MONO_TYPE_U:
1985                 case MONO_TYPE_I:
1986                 case MONO_TYPE_U4:
1987                 case MONO_TYPE_I4:
1988                 case MONO_TYPE_R4:
1989                 case MONO_TYPE_U8:
1990                 case MONO_TYPE_I8:
1991                 case MONO_TYPE_R8:
1992                 case MONO_TYPE_VALUETYPE:
1993                 case MONO_TYPE_PTR:
1994                         if (v != NULL)
1995                                 v += sizeof (MonoObject);
1996                         break;
1997                 case MONO_TYPE_STRING:
1998                 case MONO_TYPE_OBJECT:
1999                 case MONO_TYPE_CLASS:
2000                 case MONO_TYPE_ARRAY:
2001                 case MONO_TYPE_SZARRAY:
2002                         /* Do nothing */
2003                         break;
2004                 case MONO_TYPE_GENERICINST: {
2005                         MonoGenericClass *gclass = type->data.generic_class;
2006                         g_assert (!gclass->context.class_inst->is_open);
2007
2008                         if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
2009                                 MonoClass *nklass = mono_class_from_mono_type (type);
2010                                 MonoObject *nullable;
2011
2012                                 /* 
2013                                  * Convert the boxed vtype into a Nullable structure.
2014                                  * This is complicated by the fact that Nullables have
2015                                  * a variable structure.
2016                                  */
2017                                 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2018                                 if (!mono_error_ok (&error)) {
2019                                         mono_error_set_pending_exception (&error);
2020                                         return;
2021                                 }
2022
2023                                 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2024
2025                                 v = (gchar *)mono_object_unbox (nullable);
2026                         }
2027                         else 
2028                                 if (gclass->container_class->valuetype && (v != NULL))
2029                                         v += sizeof (MonoObject);
2030                         break;
2031                 }
2032                 default:
2033                         g_error ("type 0x%x not handled in "
2034                                  "ves_icall_FieldInfo_SetValueInternal", type->type);
2035                         return;
2036                 }
2037         }
2038
2039         if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2040                 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2041                 if (!is_ok (&error)) {
2042                         mono_error_set_pending_exception (&error);
2043                         return;
2044                 }
2045                 if (!vtable->initialized) {
2046                         if (!mono_runtime_class_init_full (vtable, &error)) {
2047                                 mono_error_set_pending_exception (&error);
2048                                 return;
2049                         }
2050                 }
2051                 mono_field_static_set_value (vtable, cf, v);
2052         } else {
2053                 mono_field_set_value (obj, cf, v);
2054         }
2055 }
2056
2057 ICALL_EXPORT void
2058 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2059 {
2060         MonoClassField *f;
2061
2062         g_assert (field);
2063         g_assert (obj);
2064         g_assert (value);
2065
2066         f = field->field;
2067         if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2068                 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2069                 return;
2070         }
2071
2072         if (MONO_TYPE_IS_REFERENCE (f->type))
2073                 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2074         else
2075                 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2076 }
2077
2078 ICALL_EXPORT MonoObject *
2079 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2080 {       
2081         MonoObject *o = NULL;
2082         MonoClassField *field = rfield->field;
2083         MonoClass *klass;
2084         MonoDomain *domain = mono_object_domain (rfield);
2085         gchar *v;
2086         MonoTypeEnum def_type;
2087         const char *def_value;
2088         MonoType *t;
2089         MonoError error;
2090
2091         mono_class_init (field->parent);
2092
2093         t = mono_field_get_type_checked (field, &error);
2094         if (!mono_error_ok (&error)) {
2095                 mono_error_set_pending_exception (&error);
2096                 return NULL;
2097         }
2098
2099         if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2100                 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2101                 return NULL;
2102         }
2103
2104         if (image_is_dynamic (field->parent->image)) {
2105                 MonoClass *klass = field->parent;
2106                 int fidx = field - klass->fields;
2107
2108                 g_assert (fidx >= 0 && fidx < klass->field.count);
2109                 g_assert (klass->ext);
2110                 g_assert (klass->ext->field_def_values);
2111                 def_type = klass->ext->field_def_values [fidx].def_type;
2112                 def_value = klass->ext->field_def_values [fidx].data;
2113                 if (def_type == MONO_TYPE_END) {
2114                         mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2115                         return NULL;
2116                 }
2117         } else {
2118                 def_value = mono_class_get_field_default_value (field, &def_type);
2119                 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2120                 if (!def_value) {
2121                         mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2122                         return NULL;
2123                 }
2124         }
2125
2126         /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2127         switch (def_type) {
2128         case MONO_TYPE_U1:
2129         case MONO_TYPE_I1:
2130         case MONO_TYPE_BOOLEAN:
2131         case MONO_TYPE_U2:
2132         case MONO_TYPE_I2:
2133         case MONO_TYPE_CHAR:
2134         case MONO_TYPE_U:
2135         case MONO_TYPE_I:
2136         case MONO_TYPE_U4:
2137         case MONO_TYPE_I4:
2138         case MONO_TYPE_R4:
2139         case MONO_TYPE_U8:
2140         case MONO_TYPE_I8:
2141         case MONO_TYPE_R8: {
2142                 MonoType *t;
2143
2144                 /* boxed value type */
2145                 t = g_new0 (MonoType, 1);
2146                 t->type = def_type;
2147                 klass = mono_class_from_mono_type (t);
2148                 g_free (t);
2149                 o = mono_object_new_checked (domain, klass, &error);
2150                 if (!mono_error_ok (&error)) {
2151                         mono_error_set_pending_exception (&error);
2152                         return NULL;
2153                 }
2154                 v = ((gchar *) o) + sizeof (MonoObject);
2155                 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &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_Type_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.monotype_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.monotype_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_Type_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_Type_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_MonoType_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_MonoType_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_MonoType_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_MonoType_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_Type_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_Type_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_Type_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_Type_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.monotype_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_MonoType_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_MonoType_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_Type_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_Type_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_Type_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_Type_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_Type_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_Type_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.monotype_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.monotype_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_MonoType_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.monotype_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.monotype_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.monotype_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.monotype_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_Type_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_Type_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_Type_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 (!is_ok (&error)) {
6737                 mono_error_set_pending_exception (&error);
6738                 return NULL;
6739         }
6740         tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6741         if (!is_ok (&error)) {
6742                 mono_error_set_pending_exception (&error);
6743                 return NULL;
6744         }
6745
6746         res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6747         return res;
6748 }
6749
6750 ICALL_EXPORT MonoReflectionType *
6751 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6752 {
6753         MonoError error;
6754         MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6755         mono_error_set_pending_exception (&error);
6756
6757         return ret;
6758 }
6759 #endif
6760
6761 /* System.Environment */
6762
6763 MonoString*
6764 ves_icall_System_Environment_get_UserName (void)
6765 {
6766         /* using glib is more portable */
6767         return mono_string_new (mono_domain_get (), g_get_user_name ());
6768 }
6769
6770
6771 ICALL_EXPORT MonoString *
6772 ves_icall_System_Environment_get_MachineName (void)
6773 {
6774 #if defined (HOST_WIN32)
6775         gunichar2 *buf;
6776         guint32 len;
6777         MonoString *result;
6778
6779         len = MAX_COMPUTERNAME_LENGTH + 1;
6780         buf = g_new (gunichar2, len);
6781
6782         result = NULL;
6783         if (GetComputerName (buf, (PDWORD) &len)) {
6784                 MonoError error;
6785                 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6786                 mono_error_set_pending_exception (&error);
6787         }
6788
6789         g_free (buf);
6790         return result;
6791 #elif !defined(DISABLE_SOCKETS)
6792         MonoString *result;
6793         char *buf;
6794         int n;
6795 #if defined _SC_HOST_NAME_MAX
6796         n = sysconf (_SC_HOST_NAME_MAX);
6797         if (n == -1)
6798 #endif
6799         n = 512;
6800         buf = g_malloc (n+1);
6801         
6802         if (gethostname (buf, n) == 0){
6803                 buf [n] = 0;
6804                 result = mono_string_new (mono_domain_get (), buf);
6805         } else
6806                 result = NULL;
6807         g_free (buf);
6808         
6809         return result;
6810 #else
6811         return mono_string_new (mono_domain_get (), "mono");
6812 #endif
6813 }
6814
6815 ICALL_EXPORT int
6816 ves_icall_System_Environment_get_Platform (void)
6817 {
6818 #if defined (TARGET_WIN32)
6819         /* Win32NT */
6820         return 2;
6821 #elif defined(__MACH__)
6822         /* OSX */
6823         //
6824         // Notice that the value is hidden from user code, and only exposed
6825         // to mscorlib.   This is due to Mono's Unix/MacOS code predating the
6826         // define and making assumptions based on Unix/128/4 values before there
6827         // was a MacOS define.    Lots of code would assume that not-Unix meant
6828         // Windows, but in this case, it would be OSX. 
6829         //
6830         return 6;
6831 #else
6832         /* Unix */
6833         return 4;
6834 #endif
6835 }
6836
6837 ICALL_EXPORT MonoString *
6838 ves_icall_System_Environment_get_NewLine (void)
6839 {
6840 #if defined (HOST_WIN32)
6841         return mono_string_new (mono_domain_get (), "\r\n");
6842 #else
6843         return mono_string_new (mono_domain_get (), "\n");
6844 #endif
6845 }
6846
6847 ICALL_EXPORT MonoBoolean
6848 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6849 {
6850 #if SIZEOF_VOID_P == 8
6851         return TRUE;
6852 #else
6853 #ifdef HOST_WIN32
6854         gboolean isWow64Process = FALSE;
6855         if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6856                 return (MonoBoolean)isWow64Process;
6857         }
6858 #elif defined(HAVE_SYS_UTSNAME_H)
6859         struct utsname name;
6860
6861         if (uname (&name) >= 0) {
6862                 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6863         }
6864 #endif
6865         return FALSE;
6866 #endif
6867 }
6868
6869 ICALL_EXPORT MonoString *
6870 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6871 {
6872         const gchar *value;
6873         gchar *utf8_name;
6874
6875         if (name == NULL)
6876                 return NULL;
6877
6878         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6879         value = g_getenv (utf8_name);
6880
6881         g_free (utf8_name);
6882
6883         if (value == 0)
6884                 return NULL;
6885         
6886         return mono_string_new (mono_domain_get (), value);
6887 }
6888
6889 /*
6890  * There is no standard way to get at environ.
6891  */
6892 #ifndef _MSC_VER
6893 #ifndef __MINGW32_VERSION
6894 #if defined(__APPLE__)
6895 #if defined (TARGET_OSX)
6896 /* Apple defines this in crt_externs.h but doesn't provide that header for 
6897  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
6898  * in fact exist on all implementations (so far) 
6899  */
6900 gchar ***_NSGetEnviron(void);
6901 #define environ (*_NSGetEnviron())
6902 #else
6903 static char *mono_environ[1] = { NULL };
6904 #define environ mono_environ
6905 #endif /* defined (TARGET_OSX) */
6906 #else
6907 extern
6908 char **environ;
6909 #endif
6910 #endif
6911 #endif
6912
6913 ICALL_EXPORT MonoArray *
6914 ves_icall_System_Environment_GetCoomandLineArgs (void)
6915 {
6916         MonoError error;
6917         MonoArray *result = mono_runtime_get_main_args_checked (&error);
6918         mono_error_set_pending_exception (&error);
6919         return result;
6920 }
6921
6922 ICALL_EXPORT MonoArray *
6923 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6924 {
6925 #ifdef HOST_WIN32
6926         MonoError error;
6927         MonoArray *names;
6928         MonoDomain *domain;
6929         MonoString *str;
6930         WCHAR* env_strings;
6931         WCHAR* env_string;
6932         WCHAR* equal_str;
6933         int n = 0;
6934
6935         env_strings = GetEnvironmentStrings();
6936
6937         if (env_strings) {
6938                 env_string = env_strings;
6939                 while (*env_string != '\0') {
6940                 /* weird case that MS seems to skip */
6941                         if (*env_string != '=')
6942                                 n++;
6943                         while (*env_string != '\0')
6944                                 env_string++;
6945                         env_string++;
6946                 }
6947         }
6948
6949         domain = mono_domain_get ();
6950         names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6951         if (mono_error_set_pending_exception (&error))
6952                 return NULL;
6953
6954         if (env_strings) {
6955                 n = 0;
6956                 env_string = env_strings;
6957                 while (*env_string != '\0') {
6958                         /* weird case that MS seems to skip */
6959                         if (*env_string != '=') {
6960                                 equal_str = wcschr(env_string, '=');
6961                                 g_assert(equal_str);
6962                                 MonoError error;
6963                                 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6964                                 if (mono_error_set_pending_exception (&error))
6965                                         return NULL;
6966
6967                                 mono_array_setref (names, n, str);
6968                                 n++;
6969                         }
6970                         while (*env_string != '\0')
6971                                 env_string++;
6972                         env_string++;
6973                 }
6974
6975                 FreeEnvironmentStrings (env_strings);
6976         }
6977
6978         return names;
6979
6980 #else
6981         MonoError error;
6982         MonoArray *names;
6983         MonoDomain *domain;
6984         MonoString *str;
6985         gchar **e, **parts;
6986         int n;
6987
6988         n = 0;
6989         for (e = environ; *e != 0; ++ e)
6990                 ++ n;
6991
6992         domain = mono_domain_get ();
6993         names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6994         if (mono_error_set_pending_exception (&error))
6995                 return NULL;
6996
6997         n = 0;
6998         for (e = environ; *e != 0; ++ e) {
6999                 parts = g_strsplit (*e, "=", 2);
7000                 if (*parts != 0) {
7001                         str = mono_string_new (domain, *parts);
7002                         mono_array_setref (names, n, str);
7003                 }
7004
7005                 g_strfreev (parts);
7006
7007                 ++ n;
7008         }
7009
7010         return names;
7011 #endif
7012 }
7013
7014 /*
7015  * If your platform lacks setenv/unsetenv, you must upgrade your glib.
7016  */
7017 #if !GLIB_CHECK_VERSION(2,4,0)
7018 #define g_setenv(a,b,c)   setenv(a,b,c)
7019 #define g_unsetenv(a) unsetenv(a)
7020 #endif
7021
7022 ICALL_EXPORT void
7023 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
7024 {
7025 #ifdef HOST_WIN32
7026         gunichar2 *utf16_name, *utf16_value;
7027 #else
7028         gchar *utf8_name, *utf8_value;
7029         MonoError error;
7030 #endif
7031
7032 #ifdef HOST_WIN32
7033         utf16_name = mono_string_to_utf16 (name);
7034         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7035                 SetEnvironmentVariable (utf16_name, NULL);
7036                 g_free (utf16_name);
7037                 return;
7038         }
7039
7040         utf16_value = mono_string_to_utf16 (value);
7041
7042         SetEnvironmentVariable (utf16_name, utf16_value);
7043
7044         g_free (utf16_name);
7045         g_free (utf16_value);
7046 #else
7047         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
7048
7049         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7050                 g_unsetenv (utf8_name);
7051                 g_free (utf8_name);
7052                 return;
7053         }
7054
7055         utf8_value = mono_string_to_utf8_checked (value, &error);
7056         if (!mono_error_ok (&error)) {
7057                 g_free (utf8_name);
7058                 mono_error_set_pending_exception (&error);
7059                 return;
7060         }
7061         g_setenv (utf8_name, utf8_value, TRUE);
7062
7063         g_free (utf8_name);
7064         g_free (utf8_value);
7065 #endif
7066 }
7067
7068 ICALL_EXPORT void
7069 ves_icall_System_Environment_Exit (int result)
7070 {
7071         mono_environment_exitcode_set (result);
7072
7073 /* FIXME: There are some cleanup hangs that should be worked out, but
7074  * if the program is going to exit, everything will be cleaned up when
7075  * NaCl exits anyway.
7076  */
7077 #ifndef __native_client__
7078         if (!mono_runtime_try_shutdown ())
7079                 mono_thread_exit ();
7080
7081         /* Suspend all managed threads since the runtime is going away */
7082         mono_thread_suspend_all_other_threads ();
7083
7084         mono_runtime_quit ();
7085 #endif
7086
7087         /* we may need to do some cleanup here... */
7088         exit (result);
7089 }
7090
7091 ICALL_EXPORT MonoString*
7092 ves_icall_System_Environment_GetGacPath (void)
7093 {
7094         return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
7095 }
7096
7097 ICALL_EXPORT MonoString*
7098 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
7099 {
7100 #if defined (HOST_WIN32)
7101         #ifndef CSIDL_FLAG_CREATE
7102                 #define CSIDL_FLAG_CREATE       0x8000
7103         #endif
7104
7105         WCHAR path [MAX_PATH];
7106         /* Create directory if no existing */
7107         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
7108                 int len = 0;
7109                 while (path [len])
7110                         ++ len;
7111                 MonoError error;
7112                 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
7113                 mono_error_set_pending_exception (&error);
7114                 return res;
7115         }
7116 #else
7117         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7118 #endif
7119         return mono_string_new (mono_domain_get (), "");
7120 }
7121
7122 ICALL_EXPORT MonoArray *
7123 ves_icall_System_Environment_GetLogicalDrives (void)
7124 {
7125         MonoError error;
7126         gunichar2 buf [256], *ptr, *dname;
7127         gunichar2 *u16;
7128         guint initial_size = 127, size = 128;
7129         gint ndrives;
7130         MonoArray *result;
7131         MonoString *drivestr;
7132         MonoDomain *domain = mono_domain_get ();
7133         gint len;
7134
7135         buf [0] = '\0';
7136         ptr = buf;
7137
7138         while (size > initial_size) {
7139                 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7140                 if (size > initial_size) {
7141                         if (ptr != buf)
7142                                 g_free (ptr);
7143                         ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7144                         initial_size = size;
7145                         size++;
7146                 }
7147         }
7148
7149         /* Count strings */
7150         dname = ptr;
7151         ndrives = 0;
7152         do {
7153                 while (*dname++);
7154                 ndrives++;
7155         } while (*dname);
7156
7157         dname = ptr;
7158         result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7159         if (mono_error_set_pending_exception (&error))
7160                 goto leave;
7161
7162         ndrives = 0;
7163         do {
7164                 len = 0;
7165                 u16 = dname;
7166                 while (*u16) { u16++; len ++; }
7167                 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7168                 if (mono_error_set_pending_exception (&error))
7169                         goto leave;
7170
7171                 mono_array_setref (result, ndrives++, drivestr);
7172                 while (*dname++);
7173         } while (*dname);
7174
7175 leave:
7176         if (ptr != buf)
7177                 g_free (ptr);
7178
7179         return result;
7180 }
7181
7182 ICALL_EXPORT MonoString *
7183 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7184 {
7185         MonoError error;
7186         gunichar2 volume_name [MAX_PATH + 1];
7187         
7188         if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7189                 return NULL;
7190         MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
7191         mono_error_set_pending_exception (&error);
7192         return result;
7193 }
7194
7195 ICALL_EXPORT MonoString *
7196 ves_icall_System_Environment_InternalGetHome (void)
7197 {
7198         return mono_string_new (mono_domain_get (), g_get_home_dir ());
7199 }
7200
7201 static const char *encodings [] = {
7202         (char *) 1,
7203                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7204                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7205                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7206         (char *) 2,
7207                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7208                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7209                 "x_unicode_2_0_utf_7",
7210         (char *) 3,
7211                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7212                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7213         (char *) 4,
7214                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7215                 "iso_10646_ucs2",
7216         (char *) 5,
7217                 "unicodefffe", "utf_16be",
7218         (char *) 6,
7219                 "iso_8859_1",
7220         (char *) 0
7221 };
7222
7223 /*
7224  * Returns the internal codepage, if the value of "int_code_page" is
7225  * 1 at entry, and we can not compute a suitable code page number,
7226  * returns the code page as a string
7227  */
7228 ICALL_EXPORT MonoString*
7229 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page) 
7230 {
7231         const char *cset;
7232         const char *p;
7233         char *c;
7234         char *codepage = NULL;
7235         int code;
7236         int want_name = *int_code_page;
7237         int i;
7238         
7239         *int_code_page = -1;
7240
7241         g_get_charset (&cset);
7242         c = codepage = strdup (cset);
7243         for (c = codepage; *c; c++){
7244                 if (isascii (*c) && isalpha (*c))
7245                         *c = tolower (*c);
7246                 if (*c == '-')
7247                         *c = '_';
7248         }
7249         /* g_print ("charset: %s\n", cset); */
7250         
7251         /* handle some common aliases */
7252         p = encodings [0];
7253         code = 0;
7254         for (i = 0; p != 0; ){
7255                 if ((gsize) p < 7){
7256                         code = (gssize) p;
7257                         p = encodings [++i];
7258                         continue;
7259                 }
7260                 if (strcmp (p, codepage) == 0){
7261                         *int_code_page = code;
7262                         break;
7263                 }
7264                 p = encodings [++i];
7265         }
7266         
7267         if (strstr (codepage, "utf_8") != NULL)
7268                 *int_code_page |= 0x10000000;
7269         free (codepage);
7270         
7271         if (want_name && *int_code_page == -1)
7272                 return mono_string_new (mono_domain_get (), cset);
7273         else
7274                 return NULL;
7275 }
7276
7277 ICALL_EXPORT MonoBoolean
7278 ves_icall_System_Environment_get_HasShutdownStarted (void)
7279 {
7280         if (mono_runtime_is_shutting_down ())
7281                 return TRUE;
7282
7283         if (mono_domain_is_unloading (mono_domain_get ()))
7284                 return TRUE;
7285
7286         return FALSE;
7287 }
7288
7289 ICALL_EXPORT void
7290 ves_icall_System_Environment_BroadcastSettingChange (void)
7291 {
7292 #ifdef HOST_WIN32
7293         SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7294 #endif
7295 }
7296
7297 ICALL_EXPORT
7298 gint32
7299 ves_icall_System_Environment_get_TickCount (void)
7300 {
7301         /* this will overflow after ~24 days */
7302         return (gint32) (mono_msec_boottime () & 0xffffffff);
7303 }
7304
7305 ICALL_EXPORT gint32
7306 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7307 {
7308         return 9;
7309 }
7310
7311 ICALL_EXPORT void
7312 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj, 
7313                                          MonoReflectionMethod *method,
7314                                          MonoArray *out_args)
7315 {
7316         MonoError error;
7317         mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args, &error);
7318         mono_error_set_pending_exception (&error);
7319 }
7320
7321 #ifndef DISABLE_REMOTING
7322 ICALL_EXPORT MonoBoolean
7323 ves_icall_IsTransparentProxy (MonoObject *proxy)
7324 {
7325         if (!proxy)
7326                 return 0;
7327
7328         if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7329                 return 1;
7330
7331         return 0;
7332 }
7333
7334 ICALL_EXPORT MonoReflectionMethod *
7335 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7336         MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7337 {
7338         MonoReflectionMethod *ret = NULL;
7339         MonoError error;
7340
7341         MonoClass *klass;
7342         MonoMethod *method;
7343         MonoMethod **vtable;
7344         MonoMethod *res = NULL;
7345
7346         MONO_CHECK_ARG_NULL (rtype, NULL);
7347         MONO_CHECK_ARG_NULL (rmethod, NULL);
7348
7349         method = rmethod->method;
7350         klass = mono_class_from_mono_type (rtype->type);
7351         mono_class_init_checked (klass, &error);
7352         if (mono_error_set_pending_exception (&error))
7353                 return NULL;
7354
7355         if (MONO_CLASS_IS_INTERFACE (klass))
7356                 return NULL;
7357
7358         if (method->flags & METHOD_ATTRIBUTE_STATIC)
7359                 return NULL;
7360
7361         if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7362                 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7363                         return rmethod;
7364                 else
7365                         return NULL;
7366         }
7367
7368         mono_class_setup_vtable (klass);
7369         vtable = klass->vtable;
7370
7371         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7372                 gboolean variance_used = FALSE;
7373                 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7374                 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7375                 if (offs >= 0)
7376                         res = vtable [offs + method->slot];
7377         } else {
7378                 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7379                         return NULL;
7380
7381                 if (method->slot != -1)
7382                         res = vtable [method->slot];
7383         }
7384
7385         if (!res)
7386                 return NULL;
7387
7388         ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7389         mono_error_set_pending_exception (&error);
7390         return ret;
7391 }
7392
7393 ICALL_EXPORT void
7394 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7395 {
7396         MonoError error;
7397         MonoClass *klass;
7398         MonoVTable* vtable;
7399
7400         klass = mono_class_from_mono_type (type->type);
7401         vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7402         if (!is_ok (&error)) {
7403                 mono_error_set_pending_exception (&error);
7404                 return;
7405         }
7406
7407         mono_vtable_set_is_remote (vtable, enable);
7408 }
7409
7410 #else /* DISABLE_REMOTING */
7411
7412 ICALL_EXPORT void
7413 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7414 {
7415         g_assert_not_reached ();
7416 }
7417
7418 #endif
7419
7420 ICALL_EXPORT MonoObject *
7421 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7422 {
7423         MonoError error;
7424         MonoClass *klass;
7425         MonoDomain *domain;
7426         MonoObject *ret;
7427         
7428         domain = mono_object_domain (type);
7429         klass = mono_class_from_mono_type (type->type);
7430         mono_class_init_checked (klass, &error);
7431         if (mono_error_set_pending_exception (&error))
7432                 return NULL;
7433
7434         if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7435                 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7436                 return NULL;
7437         }
7438
7439         if (klass->rank >= 1) {
7440                 g_assert (klass->rank == 1);
7441                 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7442                 mono_error_set_pending_exception (&error);
7443                 return ret;
7444         } else {
7445                 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7446                 if (!is_ok (&error)) {
7447                         mono_error_set_pending_exception (&error);
7448                         return NULL;
7449                 }
7450                 /* Bypass remoting object creation check */
7451                 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7452                 mono_error_set_pending_exception (&error);
7453
7454                 return ret;
7455         }
7456 }
7457
7458 ICALL_EXPORT MonoString *
7459 ves_icall_System_IO_get_temp_path (void)
7460 {
7461         return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7462 }
7463
7464 #ifndef PLATFORM_NO_DRIVEINFO
7465 ICALL_EXPORT MonoBoolean
7466 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7467                                                 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7468                                                 gint32 *error)
7469 {
7470         gboolean result;
7471         ULARGE_INTEGER wapi_free_bytes_avail;
7472         ULARGE_INTEGER wapi_total_number_of_bytes;
7473         ULARGE_INTEGER wapi_total_number_of_free_bytes;
7474
7475         *error = ERROR_SUCCESS;
7476         result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7477                                      &wapi_total_number_of_free_bytes);
7478
7479         if (result) {
7480                 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7481                 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7482                 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7483         } else {
7484                 *free_bytes_avail = 0;
7485                 *total_number_of_bytes = 0;
7486                 *total_number_of_free_bytes = 0;
7487                 *error = GetLastError ();
7488         }
7489
7490         return result;
7491 }
7492
7493 ICALL_EXPORT guint32
7494 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7495 {
7496         return GetDriveType (mono_string_chars (root_path_name));
7497 }
7498 #endif
7499
7500 ICALL_EXPORT gpointer
7501 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7502 {
7503         MonoError error;
7504         gpointer result = mono_compile_method_checked (method, &error);
7505         mono_error_set_pending_exception (&error);
7506         return result;
7507 }
7508
7509 ICALL_EXPORT MonoString *
7510 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7511 {
7512         MonoString *mcpath;
7513         gchar *path;
7514
7515         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7516
7517 #if defined (HOST_WIN32)
7518         /* Avoid mixing '/' and '\\' */
7519         {
7520                 gint i;
7521                 for (i = strlen (path) - 1; i >= 0; i--)
7522                         if (path [i] == '/')
7523                                 path [i] = '\\';
7524         }
7525 #endif
7526         mcpath = mono_string_new (mono_domain_get (), path);
7527         g_free (path);
7528
7529         return mcpath;
7530 }
7531
7532 static MonoString *
7533 get_bundled_app_config (void)
7534 {
7535         const gchar *app_config;
7536         MonoDomain *domain;
7537         MonoString *file;
7538         gchar *config_file_name, *config_file_path;
7539         gsize len, config_file_path_length, config_ext_length;
7540         gchar *module;
7541
7542         domain = mono_domain_get ();
7543         file = domain->setup->configuration_file;
7544         if (!file || file->length == 0)
7545                 return NULL;
7546
7547         // Retrieve config file and remove the extension
7548         config_file_name = mono_string_to_utf8 (file);
7549         config_file_path = mono_portability_find_file (config_file_name, TRUE);
7550         if (!config_file_path)
7551                 config_file_path = config_file_name;
7552
7553         config_file_path_length = strlen (config_file_path);
7554         config_ext_length = strlen (".config");
7555         if (config_file_path_length <= config_ext_length)
7556                 return NULL;
7557
7558         len = config_file_path_length - config_ext_length;
7559         module = (gchar *)g_malloc0 (len + 1);
7560         memcpy (module, config_file_path, len);
7561         // Get the config file from the module name
7562         app_config = mono_config_string_for_assembly_file (module);
7563         // Clean-up
7564         g_free (module);
7565         if (config_file_name != config_file_path)
7566                 g_free (config_file_name);
7567         g_free (config_file_path);
7568
7569         if (!app_config)
7570                 return NULL;
7571
7572         return mono_string_new (mono_domain_get (), app_config);
7573 }
7574
7575 static MonoString *
7576 get_bundled_machine_config (void)
7577 {
7578         const gchar *machine_config;
7579
7580         machine_config = mono_get_machine_config ();
7581
7582         if (!machine_config)
7583                 return NULL;
7584
7585         return mono_string_new (mono_domain_get (), machine_config);
7586 }
7587
7588 ICALL_EXPORT MonoString *
7589 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7590 {
7591         MonoString *ipath;
7592         gchar *path;
7593
7594         path = g_path_get_dirname (mono_get_config_dir ());
7595
7596 #if defined (HOST_WIN32)
7597         /* Avoid mixing '/' and '\\' */
7598         {
7599                 gint i;
7600                 for (i = strlen (path) - 1; i >= 0; i--)
7601                         if (path [i] == '/')
7602                                 path [i] = '\\';
7603         }
7604 #endif
7605         ipath = mono_string_new (mono_domain_get (), path);
7606         g_free (path);
7607
7608         return ipath;
7609 }
7610
7611 ICALL_EXPORT gboolean
7612 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7613 {
7614         MonoPEResourceDataEntry *entry;
7615         MonoImage *image;
7616
7617         if (!assembly || !result || !size)
7618                 return FALSE;
7619
7620         *result = NULL;
7621         *size = 0;
7622         image = assembly->assembly->image;
7623         entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7624         if (!entry)
7625                 return FALSE;
7626
7627         *result = mono_image_rva_map (image, entry->rde_data_offset);
7628         if (!(*result)) {
7629                 g_free (entry);
7630                 return FALSE;
7631         }
7632         *size = entry->rde_size;
7633         g_free (entry);
7634         return TRUE;
7635 }
7636
7637 ICALL_EXPORT MonoBoolean
7638 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7639 {
7640         return mono_is_debugger_attached ();
7641 }
7642
7643 ICALL_EXPORT MonoBoolean
7644 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7645 {
7646         if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7647                 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7648         else
7649                 return FALSE;
7650 }
7651
7652 ICALL_EXPORT void
7653 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7654 {
7655         if (mono_get_runtime_callbacks ()->debug_log)
7656                 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7657 }
7658
7659 ICALL_EXPORT void
7660 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7661 {
7662 #if defined (HOST_WIN32)
7663         OutputDebugString (mono_string_chars (message));
7664 #else
7665         g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7666 #endif
7667 }
7668
7669 /* Only used for value types */
7670 ICALL_EXPORT MonoObject *
7671 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7672 {
7673         MonoError error;
7674         MonoObject *result;
7675         MonoClass *klass;
7676         MonoDomain *domain;
7677         
7678         domain = mono_object_domain (type);
7679         klass = mono_class_from_mono_type (type->type);
7680         mono_class_init_checked (klass, &error);
7681         if (mono_error_set_pending_exception (&error))
7682                 return NULL;
7683
7684         if (mono_class_is_nullable (klass))
7685                 /* No arguments -> null */
7686                 return NULL;
7687
7688         result = mono_object_new_checked (domain, klass, &error);
7689         mono_error_set_pending_exception (&error);
7690         return result;
7691 }
7692
7693 ICALL_EXPORT MonoReflectionMethod *
7694 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7695 {
7696         MonoReflectionMethod *ret = NULL;
7697         MonoError error;
7698
7699         MonoClass *klass, *parent;
7700         MonoGenericContext *generic_inst = NULL;
7701         MonoMethod *method = m->method;
7702         MonoMethod *result = NULL;
7703         int slot;
7704
7705         if (method->klass == NULL)
7706                 return m;
7707
7708         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7709             MONO_CLASS_IS_INTERFACE (method->klass) ||
7710             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7711                 return m;
7712
7713         slot = mono_method_get_vtable_slot (method);
7714         if (slot == -1)
7715                 return m;
7716
7717         klass = method->klass;
7718         if (klass->generic_class) {
7719                 generic_inst = mono_class_get_context (klass);
7720                 klass = klass->generic_class->container_class;
7721         }
7722
7723         if (definition) {
7724                 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7725                 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7726                         /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7727                            or klass is the generic container class and generic_inst is the instantiation.
7728
7729                            when we go to the parent, if the parent is an open constructed type, we need to
7730                            replace the type parameters by the definitions from the generic_inst, and then take it
7731                            apart again into the klass and the generic_inst.
7732
7733                            For cases like this:
7734                            class C<T> : B<T, int> {
7735                                public override void Foo () { ... }
7736                            }
7737                            class B<U,V> : A<HashMap<U,V>> {
7738                                public override void Foo () { ... }
7739                            }
7740                            class A<X> {
7741                                public virtual void Foo () { ... }
7742                            }
7743
7744                            if at each iteration the parent isn't open, we can skip inflating it.  if at some
7745                            iteration the parent isn't generic (after possible inflation), we set generic_inst to
7746                            NULL;
7747                         */
7748                         MonoGenericContext *parent_inst = NULL;
7749                         if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7750                                 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7751                                 if (!mono_error_ok (&error)) {
7752                                         mono_error_set_pending_exception (&error);
7753                                         return NULL;
7754                                 }
7755                         }
7756                         if (parent->generic_class) {
7757                                 parent_inst = mono_class_get_context (parent);
7758                                 parent = parent->generic_class->container_class;
7759                         }
7760
7761                         mono_class_setup_vtable (parent);
7762                         if (parent->vtable_size <= slot)
7763                                 break;
7764                         klass = parent;
7765                         generic_inst = parent_inst;
7766                 }
7767         } else {
7768                 klass = klass->parent;
7769                 if (!klass)
7770                         return m;
7771                 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7772                         klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7773                         if (!mono_error_ok (&error)) {
7774                                 mono_error_set_pending_exception (&error);
7775                                 return NULL;
7776                         }
7777
7778                         generic_inst = NULL;
7779                 }
7780                 if (klass->generic_class) {
7781                         generic_inst = mono_class_get_context (klass);
7782                         klass = klass->generic_class->container_class;
7783                 }
7784
7785         }
7786
7787         if (generic_inst) {
7788                 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7789                 if (!mono_error_ok (&error)) {
7790                         mono_error_set_pending_exception (&error);
7791                         return NULL;
7792                 }
7793         }
7794
7795         if (klass == method->klass)
7796                 return m;
7797
7798         /*This is possible if definition == FALSE.
7799          * Do it here to be really sure we don't read invalid memory.
7800          */
7801         if (slot >= klass->vtable_size)
7802                 return m;
7803
7804         mono_class_setup_vtable (klass);
7805
7806         result = klass->vtable [slot];
7807         if (result == NULL) {
7808                 /* It is an abstract method */
7809                 gpointer iter = NULL;
7810                 while ((result = mono_class_get_methods (klass, &iter)))
7811                         if (result->slot == slot)
7812                                 break;
7813         }
7814
7815         if (result == NULL)
7816                 return m;
7817
7818         ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7819         mono_error_set_pending_exception (&error);
7820         return ret;
7821 }
7822
7823 ICALL_EXPORT MonoString*
7824 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7825 {
7826         MonoMethod *method = m->method;
7827
7828         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7829         return m->name;
7830 }
7831
7832 ICALL_EXPORT void
7833 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7834 {
7835         iter->sig = *(MonoMethodSignature**)argsp;
7836         
7837         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7838         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7839
7840         iter->next_arg = 0;
7841         /* FIXME: it's not documented what start is exactly... */
7842         if (start) {
7843                 iter->args = start;
7844         } else {
7845                 iter->args = argsp + sizeof (gpointer);
7846         }
7847         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7848
7849         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7850 }
7851
7852 ICALL_EXPORT MonoTypedRef
7853 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7854 {
7855         guint32 i, arg_size;
7856         gint32 align;
7857         MonoTypedRef res;
7858
7859         i = iter->sig->sentinelpos + iter->next_arg;
7860
7861         g_assert (i < iter->sig->param_count);
7862
7863         res.type = iter->sig->params [i];
7864         res.klass = mono_class_from_mono_type (res.type);
7865         arg_size = mono_type_stack_size (res.type, &align);
7866 #if defined(__arm__) || defined(__mips__)
7867         iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7868 #endif
7869         res.value = iter->args;
7870 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7871         /* Values are stored as 8 byte register sized objects, but 'value'
7872          * is dereferenced as a pointer in other routines.
7873          */
7874         res.value = (char*)res.value + 4;
7875 #endif
7876 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7877         if (arg_size <= sizeof (gpointer)) {
7878                 int dummy;
7879                 int padding = arg_size - mono_type_size (res.type, &dummy);
7880                 res.value = (guint8*)res.value + padding;
7881         }
7882 #endif
7883         iter->args = (char*)iter->args + arg_size;
7884         iter->next_arg++;
7885
7886         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7887
7888         return res;
7889 }
7890
7891 ICALL_EXPORT MonoTypedRef
7892 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7893 {
7894         guint32 i, arg_size;
7895         gint32 align;
7896         MonoTypedRef res;
7897
7898         i = iter->sig->sentinelpos + iter->next_arg;
7899
7900         g_assert (i < iter->sig->param_count);
7901
7902         while (i < iter->sig->param_count) {
7903                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7904                         continue;
7905                 res.type = iter->sig->params [i];
7906                 res.klass = mono_class_from_mono_type (res.type);
7907                 /* FIXME: endianess issue... */
7908                 arg_size = mono_type_stack_size (res.type, &align);
7909 #if defined(__arm__) || defined(__mips__)
7910                 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7911 #endif
7912                 res.value = iter->args;
7913                 iter->args = (char*)iter->args + arg_size;
7914                 iter->next_arg++;
7915                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7916                 return res;
7917         }
7918         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7919
7920         res.type = NULL;
7921         res.value = NULL;
7922         res.klass = NULL;
7923         return res;
7924 }
7925
7926 ICALL_EXPORT MonoType*
7927 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7928 {
7929         gint i;
7930         
7931         i = iter->sig->sentinelpos + iter->next_arg;
7932
7933         g_assert (i < iter->sig->param_count);
7934
7935         return iter->sig->params [i];
7936 }
7937
7938 ICALL_EXPORT MonoObject*
7939 mono_TypedReference_ToObject (MonoTypedRef* tref)
7940 {
7941         MonoError error;
7942         MonoObject *result = NULL;
7943         if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7944                 MonoObject** objp = (MonoObject **)tref->value;
7945                 return *objp;
7946         }
7947
7948         result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7949         mono_error_set_pending_exception (&error);
7950         return result;
7951 }
7952
7953 ICALL_EXPORT MonoTypedRef
7954 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7955 {
7956         MonoTypedRef res;
7957         MonoReflectionField *f;
7958         MonoClass *klass;
7959         MonoType *ftype = NULL;
7960         guint8 *p = NULL;
7961         int i;
7962
7963         memset (&res, 0, sizeof (res));
7964
7965         g_assert (fields);
7966         g_assert (mono_array_length (fields) > 0);
7967
7968         klass = target->vtable->klass;
7969
7970         for (i = 0; i < mono_array_length (fields); ++i) {
7971                 f = mono_array_get (fields, MonoReflectionField*, i);
7972                 if (f == NULL) {
7973                         mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7974                         return res;
7975                 }
7976                 if (f->field->parent != klass) {
7977                         mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7978                         return res;
7979                 }
7980                 if (i == 0)
7981                         p = (guint8*)target + f->field->offset;
7982                 else
7983                         p += f->field->offset - sizeof (MonoObject);
7984                 klass = mono_class_from_mono_type (f->field->type);
7985                 ftype = f->field->type;
7986         }
7987
7988         res.type = ftype;
7989         res.klass = mono_class_from_mono_type (ftype);
7990         res.value = p;
7991
7992         return res;
7993 }
7994
7995 static void
7996 prelink_method (MonoMethod *method, MonoError *error)
7997 {
7998         const char *exc_class, *exc_arg;
7999
8000         mono_error_init (error);
8001         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
8002                 return;
8003         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
8004         if (exc_class) {
8005                 mono_error_set_exception_instance (error,
8006                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
8007                 return;
8008         }
8009         /* create the wrapper, too? */
8010 }
8011
8012 ICALL_EXPORT void
8013 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
8014 {
8015         MonoError error;
8016
8017         prelink_method (method->method, &error);
8018         mono_error_set_pending_exception (&error);
8019 }
8020
8021 ICALL_EXPORT void
8022 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
8023 {
8024         MonoError error;
8025         MonoClass *klass = mono_class_from_mono_type (type->type);
8026         MonoMethod* m;
8027         gpointer iter = NULL;
8028
8029         mono_class_init_checked (klass, &error);
8030         if (mono_error_set_pending_exception (&error))
8031                 return;
8032
8033         while ((m = mono_class_get_methods (klass, &iter))) {
8034                 prelink_method (m, &error);
8035                 if (mono_error_set_pending_exception (&error))
8036                         return;
8037         }
8038 }
8039
8040 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
8041 ICALL_EXPORT void
8042 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
8043                                             gint32 const **exponents,
8044                                             gunichar2 const **digitLowerTable,
8045                                             gunichar2 const **digitUpperTable,
8046                                             gint64 const **tenPowersList,
8047                                             gint32 const **decHexDigits)
8048 {
8049         *mantissas = Formatter_MantissaBitsTable;
8050         *exponents = Formatter_TensExponentTable;
8051         *digitLowerTable = Formatter_DigitLowerTable;
8052         *digitUpperTable = Formatter_DigitUpperTable;
8053         *tenPowersList = Formatter_TenPowersList;
8054         *decHexDigits = Formatter_DecHexDigits;
8055 }
8056
8057 /*
8058  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
8059  * and avoid useless allocations.
8060  */
8061 static MonoArray*
8062 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
8063 {
8064         MonoReflectionType *rt;
8065         MonoArray *res;
8066         int i, count = 0;
8067
8068         mono_error_init (error);
8069         for (i = 0; i < type->num_mods; ++i) {
8070                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
8071                         count++;
8072         }
8073         if (!count)
8074                 return NULL;
8075         res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
8076         return_val_if_nok (error, NULL);
8077         count = 0;
8078         for (i = 0; i < type->num_mods; ++i) {
8079                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
8080                         MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
8081                         return_val_if_nok (error, NULL);
8082
8083                         rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8084                         return_val_if_nok (error, NULL);
8085
8086                         mono_array_setref (res, count, rt);
8087                         count++;
8088                 }
8089         }
8090         return res;
8091 }
8092
8093 ICALL_EXPORT MonoArray*
8094 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
8095 {
8096         MonoError error;
8097         MonoType *type = param->ClassImpl->type;
8098         MonoClass *member_class = mono_object_class (param->MemberImpl);
8099         MonoMethod *method = NULL;
8100         MonoImage *image;
8101         int pos;
8102         MonoMethodSignature *sig;
8103         MonoArray *res;
8104
8105         if (mono_class_is_reflection_method_or_constructor (member_class)) {
8106                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8107                 method = rmethod->method;
8108         } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
8109                 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8110                 if (!(method = prop->property->get))
8111                         method = prop->property->set;
8112                 g_assert (method);      
8113         } else {
8114                 char *type_name = mono_type_get_full_name (member_class);
8115                 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
8116                 MonoException *ex = mono_get_exception_not_supported  (msg);
8117                 g_free (type_name);
8118                 g_free (msg);
8119                 mono_set_pending_exception (ex);
8120                 return NULL;
8121         }
8122
8123         image = method->klass->image;
8124         pos = param->PositionImpl;
8125         sig = mono_method_signature (method);
8126         if (pos == -1)
8127                 type = sig->ret;
8128         else
8129                 type = sig->params [pos];
8130
8131         res = type_array_from_modifiers (image, type, optional, &error);
8132         mono_error_set_pending_exception (&error);
8133         return res;
8134 }
8135
8136 static MonoType*
8137 get_property_type (MonoProperty *prop)
8138 {
8139         MonoMethodSignature *sig;
8140         if (prop->get) {
8141                 sig = mono_method_signature (prop->get);
8142                 return sig->ret;
8143         } else if (prop->set) {
8144                 sig = mono_method_signature (prop->set);
8145                 return sig->params [sig->param_count - 1];
8146         }
8147         return NULL;
8148 }
8149
8150 ICALL_EXPORT MonoArray*
8151 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8152 {
8153         MonoError error;
8154         MonoType *type = get_property_type (property->property);
8155         MonoImage *image = property->klass->image;
8156         MonoArray *res;
8157
8158         if (!type)
8159                 return NULL;
8160         res = type_array_from_modifiers (image, type, optional, &error);
8161         mono_error_set_pending_exception (&error);
8162         return res;
8163 }
8164
8165 /*
8166  *Construct a MonoType suited to be used to decode a constant blob object.
8167  *
8168  * @type is the target type which will be constructed
8169  * @blob_type is the blob type, for example, that comes from the constant table
8170  * @real_type is the expected constructed type.
8171  */
8172 static void
8173 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8174 {
8175         type->type = blob_type;
8176         type->data.klass = NULL;
8177         if (blob_type == MONO_TYPE_CLASS)
8178                 type->data.klass = mono_defaults.object_class;
8179         else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8180                 /* For enums, we need to use the base type */
8181                 type->type = MONO_TYPE_VALUETYPE;
8182                 type->data.klass = mono_class_from_mono_type (real_type);
8183         } else
8184                 type->data.klass = mono_class_from_mono_type (real_type);
8185 }
8186
8187 ICALL_EXPORT MonoObject*
8188 property_info_get_default_value (MonoReflectionProperty *property)
8189 {
8190         MonoError error;
8191         MonoType blob_type;
8192         MonoProperty *prop = property->property;
8193         MonoType *type = get_property_type (prop);
8194         MonoDomain *domain = mono_object_domain (property); 
8195         MonoTypeEnum def_type;
8196         const char *def_value;
8197         MonoObject *o;
8198
8199         mono_class_init (prop->parent);
8200
8201         if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8202                 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8203                 return NULL;
8204         }
8205
8206         def_value = mono_class_get_property_default_value (prop, &def_type);
8207
8208         mono_type_from_blob_type (&blob_type, def_type, type);
8209         o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8210
8211         mono_error_set_pending_exception (&error);
8212         return o;
8213 }
8214
8215 ICALL_EXPORT MonoBoolean
8216 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8217 {
8218         MonoError error;
8219         MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8220         MonoCustomAttrInfo *cinfo;
8221         gboolean found;
8222
8223         mono_class_init_checked (attr_class, &error);
8224         if (mono_error_set_pending_exception (&error))
8225                 return FALSE;
8226
8227         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8228         if (!is_ok (&error)) {
8229                 mono_error_set_pending_exception (&error);
8230                 return FALSE;
8231         }
8232         if (!cinfo)
8233                 return FALSE;
8234         found = mono_custom_attrs_has_attr (cinfo, attr_class);
8235         if (!cinfo->cached)
8236                 mono_custom_attrs_free (cinfo);
8237         return found;
8238 }
8239
8240 ICALL_EXPORT MonoArray*
8241 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8242 {
8243         MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8244         MonoArray *res;
8245         MonoError error;
8246
8247         if (attr_class) {
8248                 mono_class_init_checked (attr_class, &error);
8249                 if (mono_error_set_pending_exception (&error))
8250                         return NULL;
8251         }
8252
8253         res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8254         if (!mono_error_ok (&error)) {
8255                 mono_error_set_pending_exception (&error);
8256                 return NULL;
8257         }
8258
8259         return res;
8260 }
8261
8262 ICALL_EXPORT MonoArray*
8263 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8264 {
8265         MonoError error;
8266         MonoArray *result;
8267         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8268         mono_error_set_pending_exception (&error);
8269         return result;
8270 }
8271
8272
8273 ICALL_EXPORT MonoString*
8274 ves_icall_Mono_Runtime_GetDisplayName (void)
8275 {
8276         char *info;
8277         MonoString *display_name;
8278
8279         info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8280         display_name = mono_string_new (mono_domain_get (), info);
8281         g_free (info);
8282         return display_name;
8283 }
8284
8285 ICALL_EXPORT MonoString*
8286 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8287 {
8288         MonoError error;
8289         MonoString *message;
8290         guint32 ret;
8291         gunichar2 buf[256];
8292         
8293         ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8294                              FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8295                              buf, 255, NULL);
8296         if (ret == 0) {
8297                 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8298         } else {
8299                 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8300                 if (mono_error_set_pending_exception (&error))
8301                         return NULL;
8302         }
8303         
8304         return message;
8305 }
8306
8307 ICALL_EXPORT gpointer
8308 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8309 {
8310         return GetCurrentProcess ();
8311 }
8312
8313 ICALL_EXPORT MonoBoolean
8314 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8315 {
8316         return GetExitCodeProcess (handle, (guint32*) exitcode);
8317 }
8318
8319 ICALL_EXPORT MonoBoolean
8320 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8321 {
8322 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8323         return CloseHandle (handle);
8324 #else
8325         return CloseProcess (handle);
8326 #endif
8327 }
8328
8329 ICALL_EXPORT MonoBoolean
8330 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8331 {
8332         return TerminateProcess (handle, exitcode);
8333 }
8334
8335 ICALL_EXPORT gint32
8336 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8337 {
8338         return WaitForInputIdle (handle, milliseconds);
8339 }
8340
8341 ICALL_EXPORT MonoBoolean
8342 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8343 {
8344         return GetProcessWorkingSetSize (handle, min, max);
8345 }
8346
8347 ICALL_EXPORT MonoBoolean
8348 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8349 {
8350         return SetProcessWorkingSetSize (handle, min, max);
8351 }
8352
8353 ICALL_EXPORT MonoBoolean
8354 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8355 {
8356         return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8357 }
8358
8359 ICALL_EXPORT gint32
8360 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8361 {
8362         return mono_process_current_pid ();
8363 }
8364
8365 ICALL_EXPORT gint32
8366 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8367 {
8368         return GetPriorityClass (handle);
8369 }
8370
8371 ICALL_EXPORT MonoBoolean
8372 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8373 {
8374         return SetPriorityClass (handle, priorityClass);
8375 }
8376
8377 #ifndef DISABLE_ICALL_TABLES
8378
8379 #define ICALL_TYPE(id,name,first)
8380 #define ICALL(id,name,func) Icall_ ## id,
8381
8382 enum {
8383 #include "metadata/icall-def.h"
8384         Icall_last
8385 };
8386
8387 #undef ICALL_TYPE
8388 #undef ICALL
8389 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8390 #define ICALL(id,name,func)
8391 enum {
8392 #include "metadata/icall-def.h"
8393         Icall_type_num
8394 };
8395
8396 #undef ICALL_TYPE
8397 #undef ICALL
8398 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8399 #define ICALL(id,name,func)
8400 typedef struct {
8401         guint16 first_icall;
8402 } IcallTypeDesc;
8403
8404 static const IcallTypeDesc
8405 icall_type_descs [] = {
8406 #include "metadata/icall-def.h"
8407         {Icall_last}
8408 };
8409
8410 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8411
8412 #undef ICALL_TYPE
8413 #define ICALL_TYPE(id,name,first)
8414 #undef ICALL
8415
8416 #ifdef HAVE_ARRAY_ELEM_INIT
8417 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8418 #define MSGSTRFIELD1(line) str##line
8419
8420 static const struct msgstrtn_t {
8421 #define ICALL(id,name,func)
8422 #undef ICALL_TYPE
8423 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8424 #include "metadata/icall-def.h"
8425 #undef ICALL_TYPE
8426 } icall_type_names_str = {
8427 #define ICALL_TYPE(id,name,first) (name),
8428 #include "metadata/icall-def.h"
8429 #undef ICALL_TYPE
8430 };
8431 static const guint16 icall_type_names_idx [] = {
8432 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8433 #include "metadata/icall-def.h"
8434 #undef ICALL_TYPE
8435 };
8436 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8437
8438 static const struct msgstr_t {
8439 #undef ICALL
8440 #define ICALL_TYPE(id,name,first)
8441 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8442 #include "metadata/icall-def.h"
8443 #undef ICALL
8444 } icall_names_str = {
8445 #define ICALL(id,name,func) (name),
8446 #include "metadata/icall-def.h"
8447 #undef ICALL
8448 };
8449 static const guint16 icall_names_idx [] = {
8450 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8451 #include "metadata/icall-def.h"
8452 #undef ICALL
8453 };
8454 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8455
8456 #else
8457
8458 #undef ICALL_TYPE
8459 #undef ICALL
8460 #define ICALL_TYPE(id,name,first) name,
8461 #define ICALL(id,name,func)
8462 static const char* const
8463 icall_type_names [] = {
8464 #include "metadata/icall-def.h"
8465         NULL
8466 };
8467
8468 #define icall_type_name_get(id) (icall_type_names [(id)])
8469
8470 #undef ICALL_TYPE
8471 #undef ICALL
8472 #define ICALL_TYPE(id,name,first)
8473 #define ICALL(id,name,func) name,
8474 static const char* const
8475 icall_names [] = {
8476 #include "metadata/icall-def.h"
8477         NULL
8478 };
8479 #define icall_name_get(id) icall_names [(id)]
8480
8481 #endif /* !HAVE_ARRAY_ELEM_INIT */
8482
8483 #undef ICALL_TYPE
8484 #undef ICALL
8485 #define ICALL_TYPE(id,name,first)
8486 #define ICALL(id,name,func) func,
8487 static const gconstpointer
8488 icall_functions [] = {
8489 #include "metadata/icall-def.h"
8490         NULL
8491 };
8492
8493 #ifdef ENABLE_ICALL_SYMBOL_MAP
8494 #undef ICALL_TYPE
8495 #undef ICALL
8496 #define ICALL_TYPE(id,name,first)
8497 #define ICALL(id,name,func) #func,
8498 static const gconstpointer
8499 icall_symbols [] = {
8500 #include "metadata/icall-def.h"
8501         NULL
8502 };
8503 #endif
8504
8505 #endif /* DISABLE_ICALL_TABLES */
8506
8507 static mono_mutex_t icall_mutex;
8508 static GHashTable *icall_hash = NULL;
8509 static GHashTable *jit_icall_hash_name = NULL;
8510 static GHashTable *jit_icall_hash_addr = NULL;
8511
8512 void
8513 mono_icall_init (void)
8514 {
8515 #ifndef DISABLE_ICALL_TABLES
8516         int i = 0;
8517
8518         /* check that tables are sorted: disable in release */
8519         if (TRUE) {
8520                 int j;
8521                 const char *prev_class = NULL;
8522                 const char *prev_method;
8523                 
8524                 for (i = 0; i < Icall_type_num; ++i) {
8525                         const IcallTypeDesc *desc;
8526                         int num_icalls;
8527                         prev_method = NULL;
8528                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8529                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8530                         prev_class = icall_type_name_get (i);
8531                         desc = &icall_type_descs [i];
8532                         num_icalls = icall_desc_num_icalls (desc);
8533                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8534                         for (j = 0; j < num_icalls; ++j) {
8535                                 const char *methodn = icall_name_get (desc->first_icall + j);
8536                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
8537                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
8538                                 prev_method = methodn;
8539                         }
8540                 }
8541         }
8542 #endif
8543
8544         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8545         mono_os_mutex_init (&icall_mutex);
8546 }
8547
8548 static void
8549 mono_icall_lock (void)
8550 {
8551         mono_locks_os_acquire (&icall_mutex, IcallLock);
8552 }
8553
8554 static void
8555 mono_icall_unlock (void)
8556 {
8557         mono_locks_os_release (&icall_mutex, IcallLock);
8558 }
8559
8560 void
8561 mono_icall_cleanup (void)
8562 {
8563         g_hash_table_destroy (icall_hash);
8564         g_hash_table_destroy (jit_icall_hash_name);
8565         g_hash_table_destroy (jit_icall_hash_addr);
8566         mono_os_mutex_destroy (&icall_mutex);
8567 }
8568
8569 /**
8570  * mono_add_internal_call:
8571  * @name: method specification to surface to the managed world
8572  * @method: pointer to a C method to invoke when the method is called
8573  *
8574  * This method surfaces the C function pointed by @method as a method
8575  * that has been surfaced in managed code with the method specified in
8576  * @name as an internal call.
8577  *
8578  * Internal calls are surfaced to all app domains loaded and they are
8579  * accessibly by a type with the specified name.
8580  *
8581  * You must provide a fully qualified type name, that is namespaces
8582  * and type name, followed by a colon and the method name, with an
8583  * optional signature to bind.
8584  *
8585  * For example, the following are all valid declarations:
8586  *
8587  * "MyApp.Services.ScriptService:Accelerate"
8588  * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8589  *
8590  * You use method parameters in cases where there might be more than
8591  * one surface method to managed code.  That way you can register different
8592  * internal calls for different method overloads.
8593  *
8594  * The internal calls are invoked with no marshalling.   This means that .NET
8595  * types like System.String are exposed as `MonoString *` parameters.   This is
8596  * different than the way that strings are surfaced in P/Invoke.
8597  *
8598  * For more information on how the parameters are marshalled, see the
8599  * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8600  * page.
8601  *
8602  * See the <a  href="mono-api-methods.html#method-desc">Method Description</a>
8603  * reference for more information on the format of method descriptions.
8604  */
8605 void
8606 mono_add_internal_call (const char *name, gconstpointer method)
8607 {
8608         mono_icall_lock ();
8609
8610         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8611
8612         mono_icall_unlock ();
8613 }
8614
8615 #ifndef DISABLE_ICALL_TABLES
8616
8617 #ifdef HAVE_ARRAY_ELEM_INIT
8618 static int
8619 compare_method_imap (const void *key, const void *elem)
8620 {
8621         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8622         return strcmp (key, method_name);
8623 }
8624
8625 static gpointer
8626 find_method_icall (const IcallTypeDesc *imap, const char *name)
8627 {
8628         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);
8629         if (!nameslot)
8630                 return NULL;
8631         return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8632 }
8633
8634 static int
8635 compare_class_imap (const void *key, const void *elem)
8636 {
8637         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8638         return strcmp (key, class_name);
8639 }
8640
8641 static const IcallTypeDesc*
8642 find_class_icalls (const char *name)
8643 {
8644         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);
8645         if (!nameslot)
8646                 return NULL;
8647         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8648 }
8649
8650 #else /* HAVE_ARRAY_ELEM_INIT */
8651
8652 static int
8653 compare_method_imap (const void *key, const void *elem)
8654 {
8655         const char** method_name = (const char**)elem;
8656         return strcmp (key, *method_name);
8657 }
8658
8659 static gpointer
8660 find_method_icall (const IcallTypeDesc *imap, const char *name)
8661 {
8662         const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8663         if (!nameslot)
8664                 return NULL;
8665         return (gpointer)icall_functions [(nameslot - icall_names)];
8666 }
8667
8668 static int
8669 compare_class_imap (const void *key, const void *elem)
8670 {
8671         const char** class_name = (const char**)elem;
8672         return strcmp (key, *class_name);
8673 }
8674
8675 static const IcallTypeDesc*
8676 find_class_icalls (const char *name)
8677 {
8678         const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8679         if (!nameslot)
8680                 return NULL;
8681         return &icall_type_descs [nameslot - icall_type_names];
8682 }
8683
8684 #endif /* HAVE_ARRAY_ELEM_INIT */
8685
8686 #endif /* DISABLE_ICALL_TABLES */
8687
8688 /* 
8689  * we should probably export this as an helper (handle nested types).
8690  * Returns the number of chars written in buf.
8691  */
8692 static int
8693 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8694 {
8695         int nspacelen, cnamelen;
8696         nspacelen = strlen (klass->name_space);
8697         cnamelen = strlen (klass->name);
8698         if (nspacelen + cnamelen + 2 > bufsize)
8699                 return 0;
8700         if (nspacelen) {
8701                 memcpy (buf, klass->name_space, nspacelen);
8702                 buf [nspacelen ++] = '.';
8703         }
8704         memcpy (buf + nspacelen, klass->name, cnamelen);
8705         buf [nspacelen + cnamelen] = 0;
8706         return nspacelen + cnamelen;
8707 }
8708
8709 #ifdef DISABLE_ICALL_TABLES
8710 static void
8711 no_icall_table (void)
8712 {
8713         g_assert_not_reached ();
8714 }
8715 #endif
8716
8717 gpointer
8718 mono_lookup_internal_call (MonoMethod *method)
8719 {
8720         char *sigstart;
8721         char *tmpsig;
8722         char mname [2048];
8723         int typelen = 0, mlen, siglen;
8724         gpointer res;
8725 #ifndef DISABLE_ICALL_TABLES
8726         const IcallTypeDesc *imap = NULL;
8727 #endif
8728
8729         g_assert (method != NULL);
8730
8731         if (method->is_inflated)
8732                 method = ((MonoMethodInflated *) method)->declaring;
8733
8734         if (method->klass->nested_in) {
8735                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8736                 if (!pos)
8737                         return NULL;
8738
8739                 mname [pos++] = '/';
8740                 mname [pos] = 0;
8741
8742                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8743                 if (!typelen)
8744                         return NULL;
8745
8746                 typelen += pos;
8747         } else {
8748                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8749                 if (!typelen)
8750                         return NULL;
8751         }
8752
8753 #ifndef DISABLE_ICALL_TABLES
8754         imap = find_class_icalls (mname);
8755 #endif
8756
8757         mname [typelen] = ':';
8758         mname [typelen + 1] = ':';
8759
8760         mlen = strlen (method->name);
8761         memcpy (mname + typelen + 2, method->name, mlen);
8762         sigstart = mname + typelen + 2 + mlen;
8763         *sigstart = 0;
8764
8765         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8766         siglen = strlen (tmpsig);
8767         if (typelen + mlen + siglen + 6 > sizeof (mname))
8768                 return NULL;
8769         sigstart [0] = '(';
8770         memcpy (sigstart + 1, tmpsig, siglen);
8771         sigstart [siglen + 1] = ')';
8772         sigstart [siglen + 2] = 0;
8773         g_free (tmpsig);
8774         
8775         mono_icall_lock ();
8776
8777         res = g_hash_table_lookup (icall_hash, mname);
8778         if (res) {
8779                 mono_icall_unlock ();;
8780                 return res;
8781         }
8782         /* try without signature */
8783         *sigstart = 0;
8784         res = g_hash_table_lookup (icall_hash, mname);
8785         if (res) {
8786                 mono_icall_unlock ();
8787                 return res;
8788         }
8789
8790 #ifdef DISABLE_ICALL_TABLES
8791         mono_icall_unlock ();
8792         /* Fail only when the result is actually used */
8793         /* mono_marshal_get_native_wrapper () depends on this */
8794         if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8795                 return ves_icall_System_String_ctor_RedirectToCreateString;
8796         else
8797                 return no_icall_table;
8798 #else
8799         /* it wasn't found in the static call tables */
8800         if (!imap) {
8801                 mono_icall_unlock ();
8802                 return NULL;
8803         }
8804         res = find_method_icall (imap, sigstart - mlen);
8805         if (res) {
8806                 mono_icall_unlock ();
8807                 return res;
8808         }
8809         /* try _with_ signature */
8810         *sigstart = '(';
8811         res = find_method_icall (imap, sigstart - mlen);
8812         if (res) {
8813                 mono_icall_unlock ();
8814                 return res;
8815         }
8816
8817         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8818         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8819         g_print ("The out of sync library is: %s\n", method->klass->image->name);
8820         g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8821         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");
8822         g_print ("If you see other errors or faults after this message they are probably related\n");
8823         g_print ("and you need to fix your mono install first.\n");
8824
8825         mono_icall_unlock ();
8826
8827         return NULL;
8828 #endif
8829 }
8830
8831 #ifdef ENABLE_ICALL_SYMBOL_MAP
8832 static int
8833 func_cmp (gconstpointer key, gconstpointer p)
8834 {
8835         return (gsize)key - (gsize)*(gsize*)p;
8836 }
8837 #endif
8838
8839 /*
8840  * mono_lookup_icall_symbol:
8841  *
8842  *   Given the icall METHOD, returns its C symbol.
8843  */
8844 const char*
8845 mono_lookup_icall_symbol (MonoMethod *m)
8846 {
8847 #ifdef DISABLE_ICALL_TABLES
8848         g_assert_not_reached ();
8849         return NULL;
8850 #else
8851 #ifdef ENABLE_ICALL_SYMBOL_MAP
8852         gpointer func;
8853         int i;
8854         gpointer slot;
8855         static gconstpointer *functions_sorted;
8856         static const char**symbols_sorted;
8857         static gboolean inited;
8858
8859         if (!inited) {
8860                 gboolean changed;
8861
8862                 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8863                 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8864                 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8865                 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8866                 /* Bubble sort the two arrays */
8867                 changed = TRUE;
8868                 while (changed) {
8869                         changed = FALSE;
8870                         for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8871                                 if (functions_sorted [i] > functions_sorted [i + 1]) {
8872                                         gconstpointer tmp;
8873
8874                                         tmp = functions_sorted [i];
8875                                         functions_sorted [i] = functions_sorted [i + 1];
8876                                         functions_sorted [i + 1] = tmp;
8877                                         tmp = symbols_sorted [i];
8878                                         symbols_sorted [i] = symbols_sorted [i + 1];
8879                                         symbols_sorted [i + 1] = tmp;
8880                                         changed = TRUE;
8881                                 }
8882                         }
8883                 }
8884         }
8885
8886         func = mono_lookup_internal_call (m);
8887         if (!func)
8888                 return NULL;
8889         slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8890         if (!slot)
8891                 return NULL;
8892         g_assert (slot);
8893         return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8894 #else
8895         fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8896         g_assert_not_reached ();
8897         return 0;
8898 #endif
8899 #endif
8900 }
8901
8902 static MonoType*
8903 type_from_typename (char *type_name)
8904 {
8905         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
8906
8907         if (!strcmp (type_name, "int"))
8908                 klass = mono_defaults.int_class;
8909         else if (!strcmp (type_name, "ptr"))
8910                 klass = mono_defaults.int_class;
8911         else if (!strcmp (type_name, "void"))
8912                 klass = mono_defaults.void_class;
8913         else if (!strcmp (type_name, "int32"))
8914                 klass = mono_defaults.int32_class;
8915         else if (!strcmp (type_name, "uint32"))
8916                 klass = mono_defaults.uint32_class;
8917         else if (!strcmp (type_name, "int8"))
8918                 klass = mono_defaults.sbyte_class;
8919         else if (!strcmp (type_name, "uint8"))
8920                 klass = mono_defaults.byte_class;
8921         else if (!strcmp (type_name, "int16"))
8922                 klass = mono_defaults.int16_class;
8923         else if (!strcmp (type_name, "uint16"))
8924                 klass = mono_defaults.uint16_class;
8925         else if (!strcmp (type_name, "long"))
8926                 klass = mono_defaults.int64_class;
8927         else if (!strcmp (type_name, "ulong"))
8928                 klass = mono_defaults.uint64_class;
8929         else if (!strcmp (type_name, "float"))
8930                 klass = mono_defaults.single_class;
8931         else if (!strcmp (type_name, "double"))
8932                 klass = mono_defaults.double_class;
8933         else if (!strcmp (type_name, "object"))
8934                 klass = mono_defaults.object_class;
8935         else if (!strcmp (type_name, "obj"))
8936                 klass = mono_defaults.object_class;
8937         else if (!strcmp (type_name, "string"))
8938                 klass = mono_defaults.string_class;
8939         else if (!strcmp (type_name, "bool"))
8940                 klass = mono_defaults.boolean_class;
8941         else if (!strcmp (type_name, "boolean"))
8942                 klass = mono_defaults.boolean_class;
8943         else {
8944                 g_error ("%s", type_name);
8945                 g_assert_not_reached ();
8946         }
8947         return &klass->byval_arg;
8948 }
8949
8950 /**
8951  * LOCKING: Take the corlib image lock.
8952  */
8953 MonoMethodSignature*
8954 mono_create_icall_signature (const char *sigstr)
8955 {
8956         gchar **parts;
8957         int i, len;
8958         gchar **tmp;
8959         MonoMethodSignature *res, *res2;
8960         MonoImage *corlib = mono_defaults.corlib;
8961
8962         mono_image_lock (corlib);
8963         res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8964         mono_image_unlock (corlib);
8965
8966         if (res)
8967                 return res;
8968
8969         parts = g_strsplit (sigstr, " ", 256);
8970
8971         tmp = parts;
8972         len = 0;
8973         while (*tmp) {
8974                 len ++;
8975                 tmp ++;
8976         }
8977
8978         res = mono_metadata_signature_alloc (corlib, len - 1);
8979         res->pinvoke = 1;
8980
8981 #ifdef HOST_WIN32
8982         /* 
8983          * Under windows, the default pinvoke calling convention is STDCALL but
8984          * we need CDECL.
8985          */
8986         res->call_convention = MONO_CALL_C;
8987 #endif
8988
8989         res->ret = type_from_typename (parts [0]);
8990         for (i = 1; i < len; ++i) {
8991                 res->params [i - 1] = type_from_typename (parts [i]);
8992         }
8993
8994         g_strfreev (parts);
8995
8996         mono_image_lock (corlib);
8997         res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8998         if (res2)
8999                 res = res2; /*Value is allocated in the image pool*/
9000         else
9001                 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
9002         mono_image_unlock (corlib);
9003
9004         return res;
9005 }
9006
9007 MonoJitICallInfo *
9008 mono_find_jit_icall_by_name (const char *name)
9009 {
9010         MonoJitICallInfo *info;
9011         g_assert (jit_icall_hash_name);
9012
9013         mono_icall_lock ();
9014         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9015         mono_icall_unlock ();
9016         return info;
9017 }
9018
9019 MonoJitICallInfo *
9020 mono_find_jit_icall_by_addr (gconstpointer addr)
9021 {
9022         MonoJitICallInfo *info;
9023         g_assert (jit_icall_hash_addr);
9024
9025         mono_icall_lock ();
9026         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
9027         mono_icall_unlock ();
9028
9029         return info;
9030 }
9031
9032 /*
9033  * mono_get_jit_icall_info:
9034  *
9035  *   Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
9036  * caller should access it while holding the icall lock.
9037  */
9038 GHashTable*
9039 mono_get_jit_icall_info (void)
9040 {
9041         return jit_icall_hash_name;
9042 }
9043
9044 /*
9045  * mono_lookup_jit_icall_symbol:
9046  *
9047  *   Given the jit icall NAME, returns its C symbol if possible, or NULL.
9048  */
9049 const char*
9050 mono_lookup_jit_icall_symbol (const char *name)
9051 {
9052         MonoJitICallInfo *info;
9053         const char *res = NULL;
9054
9055         mono_icall_lock ();
9056         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9057         if (info)
9058                 res = info->c_symbol;
9059         mono_icall_unlock ();
9060         return res;
9061 }
9062
9063 void
9064 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
9065 {
9066         mono_icall_lock ();
9067         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
9068         mono_icall_unlock ();
9069 }
9070
9071 /*
9072  * 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
9073  * icalls without wrappers in some cases.
9074  */
9075 MonoJitICallInfo *
9076 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
9077 {
9078         MonoJitICallInfo *info;
9079         
9080         g_assert (func);
9081         g_assert (name);
9082
9083         mono_icall_lock ();
9084
9085         if (!jit_icall_hash_name) {
9086                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
9087                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
9088         }
9089
9090         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
9091                 g_warning ("jit icall already defined \"%s\"\n", name);
9092                 g_assert_not_reached ();
9093         }
9094
9095         info = g_new0 (MonoJitICallInfo, 1);
9096         
9097         info->name = name;
9098         info->func = func;
9099         info->sig = sig;
9100         info->c_symbol = c_symbol;
9101         info->no_raise = no_raise;
9102
9103         if (is_save) {
9104                 info->wrapper = func;
9105         } else {
9106                 info->wrapper = NULL;
9107         }
9108
9109         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
9110         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
9111
9112         mono_icall_unlock ();
9113         return info;
9114 }
9115
9116 MonoJitICallInfo *
9117 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
9118 {
9119         return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);
9120 }
9121