Merge pull request #3044 from lambdageek/dev/monoerror-llvm
[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 ICALL_EXPORT void
7015 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
7016 {
7017 #ifdef HOST_WIN32
7018         gunichar2 *utf16_name, *utf16_value;
7019 #else
7020         gchar *utf8_name, *utf8_value;
7021         MonoError error;
7022 #endif
7023
7024 #ifdef HOST_WIN32
7025         utf16_name = mono_string_to_utf16 (name);
7026         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7027                 SetEnvironmentVariable (utf16_name, NULL);
7028                 g_free (utf16_name);
7029                 return;
7030         }
7031
7032         utf16_value = mono_string_to_utf16 (value);
7033
7034         SetEnvironmentVariable (utf16_name, utf16_value);
7035
7036         g_free (utf16_name);
7037         g_free (utf16_value);
7038 #else
7039         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
7040
7041         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7042                 g_unsetenv (utf8_name);
7043                 g_free (utf8_name);
7044                 return;
7045         }
7046
7047         utf8_value = mono_string_to_utf8_checked (value, &error);
7048         if (!mono_error_ok (&error)) {
7049                 g_free (utf8_name);
7050                 mono_error_set_pending_exception (&error);
7051                 return;
7052         }
7053         g_setenv (utf8_name, utf8_value, TRUE);
7054
7055         g_free (utf8_name);
7056         g_free (utf8_value);
7057 #endif
7058 }
7059
7060 ICALL_EXPORT void
7061 ves_icall_System_Environment_Exit (int result)
7062 {
7063         mono_environment_exitcode_set (result);
7064
7065 /* FIXME: There are some cleanup hangs that should be worked out, but
7066  * if the program is going to exit, everything will be cleaned up when
7067  * NaCl exits anyway.
7068  */
7069 #ifndef __native_client__
7070         if (!mono_runtime_try_shutdown ())
7071                 mono_thread_exit ();
7072
7073         /* Suspend all managed threads since the runtime is going away */
7074         mono_thread_suspend_all_other_threads ();
7075
7076         mono_runtime_quit ();
7077 #endif
7078
7079         /* we may need to do some cleanup here... */
7080         exit (result);
7081 }
7082
7083 ICALL_EXPORT MonoString*
7084 ves_icall_System_Environment_GetGacPath (void)
7085 {
7086         return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
7087 }
7088
7089 ICALL_EXPORT MonoString*
7090 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
7091 {
7092 #if defined (HOST_WIN32)
7093         #ifndef CSIDL_FLAG_CREATE
7094                 #define CSIDL_FLAG_CREATE       0x8000
7095         #endif
7096
7097         WCHAR path [MAX_PATH];
7098         /* Create directory if no existing */
7099         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
7100                 int len = 0;
7101                 while (path [len])
7102                         ++ len;
7103                 MonoError error;
7104                 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
7105                 mono_error_set_pending_exception (&error);
7106                 return res;
7107         }
7108 #else
7109         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7110 #endif
7111         return mono_string_new (mono_domain_get (), "");
7112 }
7113
7114 ICALL_EXPORT MonoArray *
7115 ves_icall_System_Environment_GetLogicalDrives (void)
7116 {
7117         MonoError error;
7118         gunichar2 buf [256], *ptr, *dname;
7119         gunichar2 *u16;
7120         guint initial_size = 127, size = 128;
7121         gint ndrives;
7122         MonoArray *result;
7123         MonoString *drivestr;
7124         MonoDomain *domain = mono_domain_get ();
7125         gint len;
7126
7127         buf [0] = '\0';
7128         ptr = buf;
7129
7130         while (size > initial_size) {
7131                 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7132                 if (size > initial_size) {
7133                         if (ptr != buf)
7134                                 g_free (ptr);
7135                         ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7136                         initial_size = size;
7137                         size++;
7138                 }
7139         }
7140
7141         /* Count strings */
7142         dname = ptr;
7143         ndrives = 0;
7144         do {
7145                 while (*dname++);
7146                 ndrives++;
7147         } while (*dname);
7148
7149         dname = ptr;
7150         result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7151         if (mono_error_set_pending_exception (&error))
7152                 goto leave;
7153
7154         ndrives = 0;
7155         do {
7156                 len = 0;
7157                 u16 = dname;
7158                 while (*u16) { u16++; len ++; }
7159                 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7160                 if (mono_error_set_pending_exception (&error))
7161                         goto leave;
7162
7163                 mono_array_setref (result, ndrives++, drivestr);
7164                 while (*dname++);
7165         } while (*dname);
7166
7167 leave:
7168         if (ptr != buf)
7169                 g_free (ptr);
7170
7171         return result;
7172 }
7173
7174 ICALL_EXPORT MonoString *
7175 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7176 {
7177         MonoError error;
7178         gunichar2 volume_name [MAX_PATH + 1];
7179         
7180         if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7181                 return NULL;
7182         MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
7183         mono_error_set_pending_exception (&error);
7184         return result;
7185 }
7186
7187 ICALL_EXPORT MonoString *
7188 ves_icall_System_Environment_InternalGetHome (void)
7189 {
7190         return mono_string_new (mono_domain_get (), g_get_home_dir ());
7191 }
7192
7193 static const char *encodings [] = {
7194         (char *) 1,
7195                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7196                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7197                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7198         (char *) 2,
7199                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7200                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7201                 "x_unicode_2_0_utf_7",
7202         (char *) 3,
7203                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7204                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7205         (char *) 4,
7206                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7207                 "iso_10646_ucs2",
7208         (char *) 5,
7209                 "unicodefffe", "utf_16be",
7210         (char *) 6,
7211                 "iso_8859_1",
7212         (char *) 0
7213 };
7214
7215 /*
7216  * Returns the internal codepage, if the value of "int_code_page" is
7217  * 1 at entry, and we can not compute a suitable code page number,
7218  * returns the code page as a string
7219  */
7220 ICALL_EXPORT MonoString*
7221 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page) 
7222 {
7223         const char *cset;
7224         const char *p;
7225         char *c;
7226         char *codepage = NULL;
7227         int code;
7228         int want_name = *int_code_page;
7229         int i;
7230         
7231         *int_code_page = -1;
7232
7233         g_get_charset (&cset);
7234         c = codepage = strdup (cset);
7235         for (c = codepage; *c; c++){
7236                 if (isascii (*c) && isalpha (*c))
7237                         *c = tolower (*c);
7238                 if (*c == '-')
7239                         *c = '_';
7240         }
7241         /* g_print ("charset: %s\n", cset); */
7242         
7243         /* handle some common aliases */
7244         p = encodings [0];
7245         code = 0;
7246         for (i = 0; p != 0; ){
7247                 if ((gsize) p < 7){
7248                         code = (gssize) p;
7249                         p = encodings [++i];
7250                         continue;
7251                 }
7252                 if (strcmp (p, codepage) == 0){
7253                         *int_code_page = code;
7254                         break;
7255                 }
7256                 p = encodings [++i];
7257         }
7258         
7259         if (strstr (codepage, "utf_8") != NULL)
7260                 *int_code_page |= 0x10000000;
7261         free (codepage);
7262         
7263         if (want_name && *int_code_page == -1)
7264                 return mono_string_new (mono_domain_get (), cset);
7265         else
7266                 return NULL;
7267 }
7268
7269 ICALL_EXPORT MonoBoolean
7270 ves_icall_System_Environment_get_HasShutdownStarted (void)
7271 {
7272         if (mono_runtime_is_shutting_down ())
7273                 return TRUE;
7274
7275         if (mono_domain_is_unloading (mono_domain_get ()))
7276                 return TRUE;
7277
7278         return FALSE;
7279 }
7280
7281 ICALL_EXPORT void
7282 ves_icall_System_Environment_BroadcastSettingChange (void)
7283 {
7284 #ifdef HOST_WIN32
7285         SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7286 #endif
7287 }
7288
7289 ICALL_EXPORT
7290 gint32
7291 ves_icall_System_Environment_get_TickCount (void)
7292 {
7293         /* this will overflow after ~24 days */
7294         return (gint32) (mono_msec_boottime () & 0xffffffff);
7295 }
7296
7297 ICALL_EXPORT gint32
7298 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7299 {
7300         return 9;
7301 }
7302
7303 ICALL_EXPORT void
7304 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj, 
7305                                          MonoReflectionMethod *method,
7306                                          MonoArray *out_args)
7307 {
7308         MonoError error;
7309         mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args, &error);
7310         mono_error_set_pending_exception (&error);
7311 }
7312
7313 #ifndef DISABLE_REMOTING
7314 ICALL_EXPORT MonoBoolean
7315 ves_icall_IsTransparentProxy (MonoObject *proxy)
7316 {
7317         if (!proxy)
7318                 return 0;
7319
7320         if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7321                 return 1;
7322
7323         return 0;
7324 }
7325
7326 ICALL_EXPORT MonoReflectionMethod *
7327 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7328         MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7329 {
7330         MonoReflectionMethod *ret = NULL;
7331         MonoError error;
7332
7333         MonoClass *klass;
7334         MonoMethod *method;
7335         MonoMethod **vtable;
7336         MonoMethod *res = NULL;
7337
7338         MONO_CHECK_ARG_NULL (rtype, NULL);
7339         MONO_CHECK_ARG_NULL (rmethod, NULL);
7340
7341         method = rmethod->method;
7342         klass = mono_class_from_mono_type (rtype->type);
7343         mono_class_init_checked (klass, &error);
7344         if (mono_error_set_pending_exception (&error))
7345                 return NULL;
7346
7347         if (MONO_CLASS_IS_INTERFACE (klass))
7348                 return NULL;
7349
7350         if (method->flags & METHOD_ATTRIBUTE_STATIC)
7351                 return NULL;
7352
7353         if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7354                 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7355                         return rmethod;
7356                 else
7357                         return NULL;
7358         }
7359
7360         mono_class_setup_vtable (klass);
7361         vtable = klass->vtable;
7362
7363         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7364                 gboolean variance_used = FALSE;
7365                 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7366                 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7367                 if (offs >= 0)
7368                         res = vtable [offs + method->slot];
7369         } else {
7370                 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7371                         return NULL;
7372
7373                 if (method->slot != -1)
7374                         res = vtable [method->slot];
7375         }
7376
7377         if (!res)
7378                 return NULL;
7379
7380         ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7381         mono_error_set_pending_exception (&error);
7382         return ret;
7383 }
7384
7385 ICALL_EXPORT void
7386 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7387 {
7388         MonoError error;
7389         MonoClass *klass;
7390         MonoVTable* vtable;
7391
7392         klass = mono_class_from_mono_type (type->type);
7393         vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7394         if (!is_ok (&error)) {
7395                 mono_error_set_pending_exception (&error);
7396                 return;
7397         }
7398
7399         mono_vtable_set_is_remote (vtable, enable);
7400 }
7401
7402 #else /* DISABLE_REMOTING */
7403
7404 ICALL_EXPORT void
7405 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7406 {
7407         g_assert_not_reached ();
7408 }
7409
7410 #endif
7411
7412 ICALL_EXPORT MonoObject *
7413 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7414 {
7415         MonoError error;
7416         MonoClass *klass;
7417         MonoDomain *domain;
7418         MonoObject *ret;
7419         
7420         domain = mono_object_domain (type);
7421         klass = mono_class_from_mono_type (type->type);
7422         mono_class_init_checked (klass, &error);
7423         if (mono_error_set_pending_exception (&error))
7424                 return NULL;
7425
7426         if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7427                 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7428                 return NULL;
7429         }
7430
7431         if (klass->rank >= 1) {
7432                 g_assert (klass->rank == 1);
7433                 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7434                 mono_error_set_pending_exception (&error);
7435                 return ret;
7436         } else {
7437                 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7438                 if (!is_ok (&error)) {
7439                         mono_error_set_pending_exception (&error);
7440                         return NULL;
7441                 }
7442                 /* Bypass remoting object creation check */
7443                 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7444                 mono_error_set_pending_exception (&error);
7445
7446                 return ret;
7447         }
7448 }
7449
7450 ICALL_EXPORT MonoString *
7451 ves_icall_System_IO_get_temp_path (void)
7452 {
7453         return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7454 }
7455
7456 #ifndef PLATFORM_NO_DRIVEINFO
7457 ICALL_EXPORT MonoBoolean
7458 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7459                                                 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7460                                                 gint32 *error)
7461 {
7462         gboolean result;
7463         ULARGE_INTEGER wapi_free_bytes_avail;
7464         ULARGE_INTEGER wapi_total_number_of_bytes;
7465         ULARGE_INTEGER wapi_total_number_of_free_bytes;
7466
7467         *error = ERROR_SUCCESS;
7468         result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7469                                      &wapi_total_number_of_free_bytes);
7470
7471         if (result) {
7472                 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7473                 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7474                 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7475         } else {
7476                 *free_bytes_avail = 0;
7477                 *total_number_of_bytes = 0;
7478                 *total_number_of_free_bytes = 0;
7479                 *error = GetLastError ();
7480         }
7481
7482         return result;
7483 }
7484
7485 ICALL_EXPORT guint32
7486 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7487 {
7488         return GetDriveType (mono_string_chars (root_path_name));
7489 }
7490 #endif
7491
7492 ICALL_EXPORT gpointer
7493 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7494 {
7495         MonoError error;
7496         gpointer result = mono_compile_method_checked (method, &error);
7497         mono_error_set_pending_exception (&error);
7498         return result;
7499 }
7500
7501 ICALL_EXPORT MonoString *
7502 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7503 {
7504         MonoString *mcpath;
7505         gchar *path;
7506
7507         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7508
7509 #if defined (HOST_WIN32)
7510         /* Avoid mixing '/' and '\\' */
7511         {
7512                 gint i;
7513                 for (i = strlen (path) - 1; i >= 0; i--)
7514                         if (path [i] == '/')
7515                                 path [i] = '\\';
7516         }
7517 #endif
7518         mcpath = mono_string_new (mono_domain_get (), path);
7519         g_free (path);
7520
7521         return mcpath;
7522 }
7523
7524 static MonoString *
7525 get_bundled_app_config (void)
7526 {
7527         const gchar *app_config;
7528         MonoDomain *domain;
7529         MonoString *file;
7530         gchar *config_file_name, *config_file_path;
7531         gsize len, config_file_path_length, config_ext_length;
7532         gchar *module;
7533
7534         domain = mono_domain_get ();
7535         file = domain->setup->configuration_file;
7536         if (!file || file->length == 0)
7537                 return NULL;
7538
7539         // Retrieve config file and remove the extension
7540         config_file_name = mono_string_to_utf8 (file);
7541         config_file_path = mono_portability_find_file (config_file_name, TRUE);
7542         if (!config_file_path)
7543                 config_file_path = config_file_name;
7544
7545         config_file_path_length = strlen (config_file_path);
7546         config_ext_length = strlen (".config");
7547         if (config_file_path_length <= config_ext_length)
7548                 return NULL;
7549
7550         len = config_file_path_length - config_ext_length;
7551         module = (gchar *)g_malloc0 (len + 1);
7552         memcpy (module, config_file_path, len);
7553         // Get the config file from the module name
7554         app_config = mono_config_string_for_assembly_file (module);
7555         // Clean-up
7556         g_free (module);
7557         if (config_file_name != config_file_path)
7558                 g_free (config_file_name);
7559         g_free (config_file_path);
7560
7561         if (!app_config)
7562                 return NULL;
7563
7564         return mono_string_new (mono_domain_get (), app_config);
7565 }
7566
7567 static MonoString *
7568 get_bundled_machine_config (void)
7569 {
7570         const gchar *machine_config;
7571
7572         machine_config = mono_get_machine_config ();
7573
7574         if (!machine_config)
7575                 return NULL;
7576
7577         return mono_string_new (mono_domain_get (), machine_config);
7578 }
7579
7580 ICALL_EXPORT MonoString *
7581 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7582 {
7583         MonoString *ipath;
7584         gchar *path;
7585
7586         path = g_path_get_dirname (mono_get_config_dir ());
7587
7588 #if defined (HOST_WIN32)
7589         /* Avoid mixing '/' and '\\' */
7590         {
7591                 gint i;
7592                 for (i = strlen (path) - 1; i >= 0; i--)
7593                         if (path [i] == '/')
7594                                 path [i] = '\\';
7595         }
7596 #endif
7597         ipath = mono_string_new (mono_domain_get (), path);
7598         g_free (path);
7599
7600         return ipath;
7601 }
7602
7603 ICALL_EXPORT gboolean
7604 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7605 {
7606         MonoPEResourceDataEntry *entry;
7607         MonoImage *image;
7608
7609         if (!assembly || !result || !size)
7610                 return FALSE;
7611
7612         *result = NULL;
7613         *size = 0;
7614         image = assembly->assembly->image;
7615         entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7616         if (!entry)
7617                 return FALSE;
7618
7619         *result = mono_image_rva_map (image, entry->rde_data_offset);
7620         if (!(*result)) {
7621                 g_free (entry);
7622                 return FALSE;
7623         }
7624         *size = entry->rde_size;
7625         g_free (entry);
7626         return TRUE;
7627 }
7628
7629 ICALL_EXPORT MonoBoolean
7630 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7631 {
7632         return mono_is_debugger_attached ();
7633 }
7634
7635 ICALL_EXPORT MonoBoolean
7636 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7637 {
7638         if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7639                 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7640         else
7641                 return FALSE;
7642 }
7643
7644 ICALL_EXPORT void
7645 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7646 {
7647         if (mono_get_runtime_callbacks ()->debug_log)
7648                 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7649 }
7650
7651 ICALL_EXPORT void
7652 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7653 {
7654 #if defined (HOST_WIN32)
7655         OutputDebugString (mono_string_chars (message));
7656 #else
7657         g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7658 #endif
7659 }
7660
7661 /* Only used for value types */
7662 ICALL_EXPORT MonoObject *
7663 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7664 {
7665         MonoError error;
7666         MonoObject *result;
7667         MonoClass *klass;
7668         MonoDomain *domain;
7669         
7670         domain = mono_object_domain (type);
7671         klass = mono_class_from_mono_type (type->type);
7672         mono_class_init_checked (klass, &error);
7673         if (mono_error_set_pending_exception (&error))
7674                 return NULL;
7675
7676         if (mono_class_is_nullable (klass))
7677                 /* No arguments -> null */
7678                 return NULL;
7679
7680         result = mono_object_new_checked (domain, klass, &error);
7681         mono_error_set_pending_exception (&error);
7682         return result;
7683 }
7684
7685 ICALL_EXPORT MonoReflectionMethod *
7686 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7687 {
7688         MonoReflectionMethod *ret = NULL;
7689         MonoError error;
7690
7691         MonoClass *klass, *parent;
7692         MonoGenericContext *generic_inst = NULL;
7693         MonoMethod *method = m->method;
7694         MonoMethod *result = NULL;
7695         int slot;
7696
7697         if (method->klass == NULL)
7698                 return m;
7699
7700         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7701             MONO_CLASS_IS_INTERFACE (method->klass) ||
7702             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7703                 return m;
7704
7705         slot = mono_method_get_vtable_slot (method);
7706         if (slot == -1)
7707                 return m;
7708
7709         klass = method->klass;
7710         if (klass->generic_class) {
7711                 generic_inst = mono_class_get_context (klass);
7712                 klass = klass->generic_class->container_class;
7713         }
7714
7715         if (definition) {
7716                 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7717                 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7718                         /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7719                            or klass is the generic container class and generic_inst is the instantiation.
7720
7721                            when we go to the parent, if the parent is an open constructed type, we need to
7722                            replace the type parameters by the definitions from the generic_inst, and then take it
7723                            apart again into the klass and the generic_inst.
7724
7725                            For cases like this:
7726                            class C<T> : B<T, int> {
7727                                public override void Foo () { ... }
7728                            }
7729                            class B<U,V> : A<HashMap<U,V>> {
7730                                public override void Foo () { ... }
7731                            }
7732                            class A<X> {
7733                                public virtual void Foo () { ... }
7734                            }
7735
7736                            if at each iteration the parent isn't open, we can skip inflating it.  if at some
7737                            iteration the parent isn't generic (after possible inflation), we set generic_inst to
7738                            NULL;
7739                         */
7740                         MonoGenericContext *parent_inst = NULL;
7741                         if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7742                                 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7743                                 if (!mono_error_ok (&error)) {
7744                                         mono_error_set_pending_exception (&error);
7745                                         return NULL;
7746                                 }
7747                         }
7748                         if (parent->generic_class) {
7749                                 parent_inst = mono_class_get_context (parent);
7750                                 parent = parent->generic_class->container_class;
7751                         }
7752
7753                         mono_class_setup_vtable (parent);
7754                         if (parent->vtable_size <= slot)
7755                                 break;
7756                         klass = parent;
7757                         generic_inst = parent_inst;
7758                 }
7759         } else {
7760                 klass = klass->parent;
7761                 if (!klass)
7762                         return m;
7763                 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7764                         klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7765                         if (!mono_error_ok (&error)) {
7766                                 mono_error_set_pending_exception (&error);
7767                                 return NULL;
7768                         }
7769
7770                         generic_inst = NULL;
7771                 }
7772                 if (klass->generic_class) {
7773                         generic_inst = mono_class_get_context (klass);
7774                         klass = klass->generic_class->container_class;
7775                 }
7776
7777         }
7778
7779         if (generic_inst) {
7780                 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7781                 if (!mono_error_ok (&error)) {
7782                         mono_error_set_pending_exception (&error);
7783                         return NULL;
7784                 }
7785         }
7786
7787         if (klass == method->klass)
7788                 return m;
7789
7790         /*This is possible if definition == FALSE.
7791          * Do it here to be really sure we don't read invalid memory.
7792          */
7793         if (slot >= klass->vtable_size)
7794                 return m;
7795
7796         mono_class_setup_vtable (klass);
7797
7798         result = klass->vtable [slot];
7799         if (result == NULL) {
7800                 /* It is an abstract method */
7801                 gpointer iter = NULL;
7802                 while ((result = mono_class_get_methods (klass, &iter)))
7803                         if (result->slot == slot)
7804                                 break;
7805         }
7806
7807         if (result == NULL)
7808                 return m;
7809
7810         ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7811         mono_error_set_pending_exception (&error);
7812         return ret;
7813 }
7814
7815 ICALL_EXPORT MonoString*
7816 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7817 {
7818         MonoMethod *method = m->method;
7819
7820         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7821         return m->name;
7822 }
7823
7824 ICALL_EXPORT void
7825 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7826 {
7827         iter->sig = *(MonoMethodSignature**)argsp;
7828         
7829         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7830         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7831
7832         iter->next_arg = 0;
7833         /* FIXME: it's not documented what start is exactly... */
7834         if (start) {
7835                 iter->args = start;
7836         } else {
7837                 iter->args = argsp + sizeof (gpointer);
7838         }
7839         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7840
7841         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7842 }
7843
7844 ICALL_EXPORT MonoTypedRef
7845 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7846 {
7847         guint32 i, arg_size;
7848         gint32 align;
7849         MonoTypedRef res;
7850
7851         i = iter->sig->sentinelpos + iter->next_arg;
7852
7853         g_assert (i < iter->sig->param_count);
7854
7855         res.type = iter->sig->params [i];
7856         res.klass = mono_class_from_mono_type (res.type);
7857         arg_size = mono_type_stack_size (res.type, &align);
7858 #if defined(__arm__) || defined(__mips__)
7859         iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7860 #endif
7861         res.value = iter->args;
7862 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7863         /* Values are stored as 8 byte register sized objects, but 'value'
7864          * is dereferenced as a pointer in other routines.
7865          */
7866         res.value = (char*)res.value + 4;
7867 #endif
7868 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7869         if (arg_size <= sizeof (gpointer)) {
7870                 int dummy;
7871                 int padding = arg_size - mono_type_size (res.type, &dummy);
7872                 res.value = (guint8*)res.value + padding;
7873         }
7874 #endif
7875         iter->args = (char*)iter->args + arg_size;
7876         iter->next_arg++;
7877
7878         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7879
7880         return res;
7881 }
7882
7883 ICALL_EXPORT MonoTypedRef
7884 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7885 {
7886         guint32 i, arg_size;
7887         gint32 align;
7888         MonoTypedRef res;
7889
7890         i = iter->sig->sentinelpos + iter->next_arg;
7891
7892         g_assert (i < iter->sig->param_count);
7893
7894         while (i < iter->sig->param_count) {
7895                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7896                         continue;
7897                 res.type = iter->sig->params [i];
7898                 res.klass = mono_class_from_mono_type (res.type);
7899                 /* FIXME: endianess issue... */
7900                 arg_size = mono_type_stack_size (res.type, &align);
7901 #if defined(__arm__) || defined(__mips__)
7902                 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7903 #endif
7904                 res.value = iter->args;
7905                 iter->args = (char*)iter->args + arg_size;
7906                 iter->next_arg++;
7907                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7908                 return res;
7909         }
7910         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7911
7912         res.type = NULL;
7913         res.value = NULL;
7914         res.klass = NULL;
7915         return res;
7916 }
7917
7918 ICALL_EXPORT MonoType*
7919 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7920 {
7921         gint i;
7922         
7923         i = iter->sig->sentinelpos + iter->next_arg;
7924
7925         g_assert (i < iter->sig->param_count);
7926
7927         return iter->sig->params [i];
7928 }
7929
7930 ICALL_EXPORT MonoObject*
7931 mono_TypedReference_ToObject (MonoTypedRef* tref)
7932 {
7933         MonoError error;
7934         MonoObject *result = NULL;
7935         if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7936                 MonoObject** objp = (MonoObject **)tref->value;
7937                 return *objp;
7938         }
7939
7940         result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7941         mono_error_set_pending_exception (&error);
7942         return result;
7943 }
7944
7945 ICALL_EXPORT MonoTypedRef
7946 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7947 {
7948         MonoTypedRef res;
7949         MonoReflectionField *f;
7950         MonoClass *klass;
7951         MonoType *ftype = NULL;
7952         guint8 *p = NULL;
7953         int i;
7954
7955         memset (&res, 0, sizeof (res));
7956
7957         g_assert (fields);
7958         g_assert (mono_array_length (fields) > 0);
7959
7960         klass = target->vtable->klass;
7961
7962         for (i = 0; i < mono_array_length (fields); ++i) {
7963                 f = mono_array_get (fields, MonoReflectionField*, i);
7964                 if (f == NULL) {
7965                         mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7966                         return res;
7967                 }
7968                 if (f->field->parent != klass) {
7969                         mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7970                         return res;
7971                 }
7972                 if (i == 0)
7973                         p = (guint8*)target + f->field->offset;
7974                 else
7975                         p += f->field->offset - sizeof (MonoObject);
7976                 klass = mono_class_from_mono_type (f->field->type);
7977                 ftype = f->field->type;
7978         }
7979
7980         res.type = ftype;
7981         res.klass = mono_class_from_mono_type (ftype);
7982         res.value = p;
7983
7984         return res;
7985 }
7986
7987 static void
7988 prelink_method (MonoMethod *method, MonoError *error)
7989 {
7990         const char *exc_class, *exc_arg;
7991
7992         mono_error_init (error);
7993         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7994                 return;
7995         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7996         if (exc_class) {
7997                 mono_error_set_exception_instance (error,
7998                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7999                 return;
8000         }
8001         /* create the wrapper, too? */
8002 }
8003
8004 ICALL_EXPORT void
8005 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
8006 {
8007         MonoError error;
8008
8009         prelink_method (method->method, &error);
8010         mono_error_set_pending_exception (&error);
8011 }
8012
8013 ICALL_EXPORT void
8014 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
8015 {
8016         MonoError error;
8017         MonoClass *klass = mono_class_from_mono_type (type->type);
8018         MonoMethod* m;
8019         gpointer iter = NULL;
8020
8021         mono_class_init_checked (klass, &error);
8022         if (mono_error_set_pending_exception (&error))
8023                 return;
8024
8025         while ((m = mono_class_get_methods (klass, &iter))) {
8026                 prelink_method (m, &error);
8027                 if (mono_error_set_pending_exception (&error))
8028                         return;
8029         }
8030 }
8031
8032 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
8033 ICALL_EXPORT void
8034 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
8035                                             gint32 const **exponents,
8036                                             gunichar2 const **digitLowerTable,
8037                                             gunichar2 const **digitUpperTable,
8038                                             gint64 const **tenPowersList,
8039                                             gint32 const **decHexDigits)
8040 {
8041         *mantissas = Formatter_MantissaBitsTable;
8042         *exponents = Formatter_TensExponentTable;
8043         *digitLowerTable = Formatter_DigitLowerTable;
8044         *digitUpperTable = Formatter_DigitUpperTable;
8045         *tenPowersList = Formatter_TenPowersList;
8046         *decHexDigits = Formatter_DecHexDigits;
8047 }
8048
8049 /*
8050  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
8051  * and avoid useless allocations.
8052  */
8053 static MonoArray*
8054 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
8055 {
8056         MonoReflectionType *rt;
8057         MonoArray *res;
8058         int i, count = 0;
8059
8060         mono_error_init (error);
8061         for (i = 0; i < type->num_mods; ++i) {
8062                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
8063                         count++;
8064         }
8065         if (!count)
8066                 return NULL;
8067         res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
8068         return_val_if_nok (error, NULL);
8069         count = 0;
8070         for (i = 0; i < type->num_mods; ++i) {
8071                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
8072                         MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
8073                         return_val_if_nok (error, NULL);
8074
8075                         rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8076                         return_val_if_nok (error, NULL);
8077
8078                         mono_array_setref (res, count, rt);
8079                         count++;
8080                 }
8081         }
8082         return res;
8083 }
8084
8085 ICALL_EXPORT MonoArray*
8086 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
8087 {
8088         MonoError error;
8089         MonoType *type = param->ClassImpl->type;
8090         MonoClass *member_class = mono_object_class (param->MemberImpl);
8091         MonoMethod *method = NULL;
8092         MonoImage *image;
8093         int pos;
8094         MonoMethodSignature *sig;
8095         MonoArray *res;
8096
8097         if (mono_class_is_reflection_method_or_constructor (member_class)) {
8098                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8099                 method = rmethod->method;
8100         } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
8101                 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8102                 if (!(method = prop->property->get))
8103                         method = prop->property->set;
8104                 g_assert (method);      
8105         } else {
8106                 char *type_name = mono_type_get_full_name (member_class);
8107                 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
8108                 MonoException *ex = mono_get_exception_not_supported  (msg);
8109                 g_free (type_name);
8110                 g_free (msg);
8111                 mono_set_pending_exception (ex);
8112                 return NULL;
8113         }
8114
8115         image = method->klass->image;
8116         pos = param->PositionImpl;
8117         sig = mono_method_signature (method);
8118         if (pos == -1)
8119                 type = sig->ret;
8120         else
8121                 type = sig->params [pos];
8122
8123         res = type_array_from_modifiers (image, type, optional, &error);
8124         mono_error_set_pending_exception (&error);
8125         return res;
8126 }
8127
8128 static MonoType*
8129 get_property_type (MonoProperty *prop)
8130 {
8131         MonoMethodSignature *sig;
8132         if (prop->get) {
8133                 sig = mono_method_signature (prop->get);
8134                 return sig->ret;
8135         } else if (prop->set) {
8136                 sig = mono_method_signature (prop->set);
8137                 return sig->params [sig->param_count - 1];
8138         }
8139         return NULL;
8140 }
8141
8142 ICALL_EXPORT MonoArray*
8143 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8144 {
8145         MonoError error;
8146         MonoType *type = get_property_type (property->property);
8147         MonoImage *image = property->klass->image;
8148         MonoArray *res;
8149
8150         if (!type)
8151                 return NULL;
8152         res = type_array_from_modifiers (image, type, optional, &error);
8153         mono_error_set_pending_exception (&error);
8154         return res;
8155 }
8156
8157 /*
8158  *Construct a MonoType suited to be used to decode a constant blob object.
8159  *
8160  * @type is the target type which will be constructed
8161  * @blob_type is the blob type, for example, that comes from the constant table
8162  * @real_type is the expected constructed type.
8163  */
8164 static void
8165 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8166 {
8167         type->type = blob_type;
8168         type->data.klass = NULL;
8169         if (blob_type == MONO_TYPE_CLASS)
8170                 type->data.klass = mono_defaults.object_class;
8171         else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8172                 /* For enums, we need to use the base type */
8173                 type->type = MONO_TYPE_VALUETYPE;
8174                 type->data.klass = mono_class_from_mono_type (real_type);
8175         } else
8176                 type->data.klass = mono_class_from_mono_type (real_type);
8177 }
8178
8179 ICALL_EXPORT MonoObject*
8180 property_info_get_default_value (MonoReflectionProperty *property)
8181 {
8182         MonoError error;
8183         MonoType blob_type;
8184         MonoProperty *prop = property->property;
8185         MonoType *type = get_property_type (prop);
8186         MonoDomain *domain = mono_object_domain (property); 
8187         MonoTypeEnum def_type;
8188         const char *def_value;
8189         MonoObject *o;
8190
8191         mono_class_init (prop->parent);
8192
8193         if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8194                 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8195                 return NULL;
8196         }
8197
8198         def_value = mono_class_get_property_default_value (prop, &def_type);
8199
8200         mono_type_from_blob_type (&blob_type, def_type, type);
8201         o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8202
8203         mono_error_set_pending_exception (&error);
8204         return o;
8205 }
8206
8207 ICALL_EXPORT MonoBoolean
8208 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8209 {
8210         MonoError error;
8211         MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8212         MonoCustomAttrInfo *cinfo;
8213         gboolean found;
8214
8215         mono_class_init_checked (attr_class, &error);
8216         if (mono_error_set_pending_exception (&error))
8217                 return FALSE;
8218
8219         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8220         if (!is_ok (&error)) {
8221                 mono_error_set_pending_exception (&error);
8222                 return FALSE;
8223         }
8224         if (!cinfo)
8225                 return FALSE;
8226         found = mono_custom_attrs_has_attr (cinfo, attr_class);
8227         if (!cinfo->cached)
8228                 mono_custom_attrs_free (cinfo);
8229         return found;
8230 }
8231
8232 ICALL_EXPORT MonoArray*
8233 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8234 {
8235         MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8236         MonoArray *res;
8237         MonoError error;
8238
8239         if (attr_class) {
8240                 mono_class_init_checked (attr_class, &error);
8241                 if (mono_error_set_pending_exception (&error))
8242                         return NULL;
8243         }
8244
8245         res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8246         if (!mono_error_ok (&error)) {
8247                 mono_error_set_pending_exception (&error);
8248                 return NULL;
8249         }
8250
8251         return res;
8252 }
8253
8254 ICALL_EXPORT MonoArray*
8255 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8256 {
8257         MonoError error;
8258         MonoArray *result;
8259         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8260         mono_error_set_pending_exception (&error);
8261         return result;
8262 }
8263
8264
8265 ICALL_EXPORT MonoString*
8266 ves_icall_Mono_Runtime_GetDisplayName (void)
8267 {
8268         char *info;
8269         MonoString *display_name;
8270
8271         info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8272         display_name = mono_string_new (mono_domain_get (), info);
8273         g_free (info);
8274         return display_name;
8275 }
8276
8277 ICALL_EXPORT MonoString*
8278 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8279 {
8280         MonoError error;
8281         MonoString *message;
8282         guint32 ret;
8283         gunichar2 buf[256];
8284         
8285         ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8286                              FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8287                              buf, 255, NULL);
8288         if (ret == 0) {
8289                 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8290         } else {
8291                 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8292                 if (mono_error_set_pending_exception (&error))
8293                         return NULL;
8294         }
8295         
8296         return message;
8297 }
8298
8299 ICALL_EXPORT gpointer
8300 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8301 {
8302         return GetCurrentProcess ();
8303 }
8304
8305 ICALL_EXPORT MonoBoolean
8306 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8307 {
8308         return GetExitCodeProcess (handle, (guint32*) exitcode);
8309 }
8310
8311 ICALL_EXPORT MonoBoolean
8312 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8313 {
8314 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8315         return CloseHandle (handle);
8316 #else
8317         return CloseProcess (handle);
8318 #endif
8319 }
8320
8321 ICALL_EXPORT MonoBoolean
8322 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8323 {
8324         return TerminateProcess (handle, exitcode);
8325 }
8326
8327 ICALL_EXPORT gint32
8328 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8329 {
8330         return WaitForInputIdle (handle, milliseconds);
8331 }
8332
8333 ICALL_EXPORT MonoBoolean
8334 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8335 {
8336         return GetProcessWorkingSetSize (handle, min, max);
8337 }
8338
8339 ICALL_EXPORT MonoBoolean
8340 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8341 {
8342         return SetProcessWorkingSetSize (handle, min, max);
8343 }
8344
8345 ICALL_EXPORT MonoBoolean
8346 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8347 {
8348         return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8349 }
8350
8351 ICALL_EXPORT gint32
8352 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8353 {
8354         return mono_process_current_pid ();
8355 }
8356
8357 ICALL_EXPORT gint32
8358 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8359 {
8360         return GetPriorityClass (handle);
8361 }
8362
8363 ICALL_EXPORT MonoBoolean
8364 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8365 {
8366         return SetPriorityClass (handle, priorityClass);
8367 }
8368
8369 #ifndef DISABLE_ICALL_TABLES
8370
8371 #define ICALL_TYPE(id,name,first)
8372 #define ICALL(id,name,func) Icall_ ## id,
8373
8374 enum {
8375 #include "metadata/icall-def.h"
8376         Icall_last
8377 };
8378
8379 #undef ICALL_TYPE
8380 #undef ICALL
8381 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8382 #define ICALL(id,name,func)
8383 enum {
8384 #include "metadata/icall-def.h"
8385         Icall_type_num
8386 };
8387
8388 #undef ICALL_TYPE
8389 #undef ICALL
8390 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8391 #define ICALL(id,name,func)
8392 typedef struct {
8393         guint16 first_icall;
8394 } IcallTypeDesc;
8395
8396 static const IcallTypeDesc
8397 icall_type_descs [] = {
8398 #include "metadata/icall-def.h"
8399         {Icall_last}
8400 };
8401
8402 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8403
8404 #undef ICALL_TYPE
8405 #define ICALL_TYPE(id,name,first)
8406 #undef ICALL
8407
8408 #ifdef HAVE_ARRAY_ELEM_INIT
8409 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8410 #define MSGSTRFIELD1(line) str##line
8411
8412 static const struct msgstrtn_t {
8413 #define ICALL(id,name,func)
8414 #undef ICALL_TYPE
8415 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8416 #include "metadata/icall-def.h"
8417 #undef ICALL_TYPE
8418 } icall_type_names_str = {
8419 #define ICALL_TYPE(id,name,first) (name),
8420 #include "metadata/icall-def.h"
8421 #undef ICALL_TYPE
8422 };
8423 static const guint16 icall_type_names_idx [] = {
8424 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8425 #include "metadata/icall-def.h"
8426 #undef ICALL_TYPE
8427 };
8428 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8429
8430 static const struct msgstr_t {
8431 #undef ICALL
8432 #define ICALL_TYPE(id,name,first)
8433 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8434 #include "metadata/icall-def.h"
8435 #undef ICALL
8436 } icall_names_str = {
8437 #define ICALL(id,name,func) (name),
8438 #include "metadata/icall-def.h"
8439 #undef ICALL
8440 };
8441 static const guint16 icall_names_idx [] = {
8442 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8443 #include "metadata/icall-def.h"
8444 #undef ICALL
8445 };
8446 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8447
8448 #else
8449
8450 #undef ICALL_TYPE
8451 #undef ICALL
8452 #define ICALL_TYPE(id,name,first) name,
8453 #define ICALL(id,name,func)
8454 static const char* const
8455 icall_type_names [] = {
8456 #include "metadata/icall-def.h"
8457         NULL
8458 };
8459
8460 #define icall_type_name_get(id) (icall_type_names [(id)])
8461
8462 #undef ICALL_TYPE
8463 #undef ICALL
8464 #define ICALL_TYPE(id,name,first)
8465 #define ICALL(id,name,func) name,
8466 static const char* const
8467 icall_names [] = {
8468 #include "metadata/icall-def.h"
8469         NULL
8470 };
8471 #define icall_name_get(id) icall_names [(id)]
8472
8473 #endif /* !HAVE_ARRAY_ELEM_INIT */
8474
8475 #undef ICALL_TYPE
8476 #undef ICALL
8477 #define ICALL_TYPE(id,name,first)
8478 #define ICALL(id,name,func) func,
8479 static const gconstpointer
8480 icall_functions [] = {
8481 #include "metadata/icall-def.h"
8482         NULL
8483 };
8484
8485 #ifdef ENABLE_ICALL_SYMBOL_MAP
8486 #undef ICALL_TYPE
8487 #undef ICALL
8488 #define ICALL_TYPE(id,name,first)
8489 #define ICALL(id,name,func) #func,
8490 static const gconstpointer
8491 icall_symbols [] = {
8492 #include "metadata/icall-def.h"
8493         NULL
8494 };
8495 #endif
8496
8497 #endif /* DISABLE_ICALL_TABLES */
8498
8499 static mono_mutex_t icall_mutex;
8500 static GHashTable *icall_hash = NULL;
8501 static GHashTable *jit_icall_hash_name = NULL;
8502 static GHashTable *jit_icall_hash_addr = NULL;
8503
8504 void
8505 mono_icall_init (void)
8506 {
8507 #ifndef DISABLE_ICALL_TABLES
8508         int i = 0;
8509
8510         /* check that tables are sorted: disable in release */
8511         if (TRUE) {
8512                 int j;
8513                 const char *prev_class = NULL;
8514                 const char *prev_method;
8515                 
8516                 for (i = 0; i < Icall_type_num; ++i) {
8517                         const IcallTypeDesc *desc;
8518                         int num_icalls;
8519                         prev_method = NULL;
8520                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8521                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8522                         prev_class = icall_type_name_get (i);
8523                         desc = &icall_type_descs [i];
8524                         num_icalls = icall_desc_num_icalls (desc);
8525                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8526                         for (j = 0; j < num_icalls; ++j) {
8527                                 const char *methodn = icall_name_get (desc->first_icall + j);
8528                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
8529                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
8530                                 prev_method = methodn;
8531                         }
8532                 }
8533         }
8534 #endif
8535
8536         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8537         mono_os_mutex_init (&icall_mutex);
8538 }
8539
8540 static void
8541 mono_icall_lock (void)
8542 {
8543         mono_locks_os_acquire (&icall_mutex, IcallLock);
8544 }
8545
8546 static void
8547 mono_icall_unlock (void)
8548 {
8549         mono_locks_os_release (&icall_mutex, IcallLock);
8550 }
8551
8552 void
8553 mono_icall_cleanup (void)
8554 {
8555         g_hash_table_destroy (icall_hash);
8556         g_hash_table_destroy (jit_icall_hash_name);
8557         g_hash_table_destroy (jit_icall_hash_addr);
8558         mono_os_mutex_destroy (&icall_mutex);
8559 }
8560
8561 /**
8562  * mono_add_internal_call:
8563  * @name: method specification to surface to the managed world
8564  * @method: pointer to a C method to invoke when the method is called
8565  *
8566  * This method surfaces the C function pointed by @method as a method
8567  * that has been surfaced in managed code with the method specified in
8568  * @name as an internal call.
8569  *
8570  * Internal calls are surfaced to all app domains loaded and they are
8571  * accessibly by a type with the specified name.
8572  *
8573  * You must provide a fully qualified type name, that is namespaces
8574  * and type name, followed by a colon and the method name, with an
8575  * optional signature to bind.
8576  *
8577  * For example, the following are all valid declarations:
8578  *
8579  * "MyApp.Services.ScriptService:Accelerate"
8580  * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8581  *
8582  * You use method parameters in cases where there might be more than
8583  * one surface method to managed code.  That way you can register different
8584  * internal calls for different method overloads.
8585  *
8586  * The internal calls are invoked with no marshalling.   This means that .NET
8587  * types like System.String are exposed as `MonoString *` parameters.   This is
8588  * different than the way that strings are surfaced in P/Invoke.
8589  *
8590  * For more information on how the parameters are marshalled, see the
8591  * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8592  * page.
8593  *
8594  * See the <a  href="mono-api-methods.html#method-desc">Method Description</a>
8595  * reference for more information on the format of method descriptions.
8596  */
8597 void
8598 mono_add_internal_call (const char *name, gconstpointer method)
8599 {
8600         mono_icall_lock ();
8601
8602         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8603
8604         mono_icall_unlock ();
8605 }
8606
8607 #ifndef DISABLE_ICALL_TABLES
8608
8609 #ifdef HAVE_ARRAY_ELEM_INIT
8610 static int
8611 compare_method_imap (const void *key, const void *elem)
8612 {
8613         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8614         return strcmp (key, method_name);
8615 }
8616
8617 static gpointer
8618 find_method_icall (const IcallTypeDesc *imap, const char *name)
8619 {
8620         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);
8621         if (!nameslot)
8622                 return NULL;
8623         return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8624 }
8625
8626 static int
8627 compare_class_imap (const void *key, const void *elem)
8628 {
8629         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8630         return strcmp (key, class_name);
8631 }
8632
8633 static const IcallTypeDesc*
8634 find_class_icalls (const char *name)
8635 {
8636         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);
8637         if (!nameslot)
8638                 return NULL;
8639         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8640 }
8641
8642 #else /* HAVE_ARRAY_ELEM_INIT */
8643
8644 static int
8645 compare_method_imap (const void *key, const void *elem)
8646 {
8647         const char** method_name = (const char**)elem;
8648         return strcmp (key, *method_name);
8649 }
8650
8651 static gpointer
8652 find_method_icall (const IcallTypeDesc *imap, const char *name)
8653 {
8654         const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8655         if (!nameslot)
8656                 return NULL;
8657         return (gpointer)icall_functions [(nameslot - icall_names)];
8658 }
8659
8660 static int
8661 compare_class_imap (const void *key, const void *elem)
8662 {
8663         const char** class_name = (const char**)elem;
8664         return strcmp (key, *class_name);
8665 }
8666
8667 static const IcallTypeDesc*
8668 find_class_icalls (const char *name)
8669 {
8670         const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8671         if (!nameslot)
8672                 return NULL;
8673         return &icall_type_descs [nameslot - icall_type_names];
8674 }
8675
8676 #endif /* HAVE_ARRAY_ELEM_INIT */
8677
8678 #endif /* DISABLE_ICALL_TABLES */
8679
8680 /* 
8681  * we should probably export this as an helper (handle nested types).
8682  * Returns the number of chars written in buf.
8683  */
8684 static int
8685 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8686 {
8687         int nspacelen, cnamelen;
8688         nspacelen = strlen (klass->name_space);
8689         cnamelen = strlen (klass->name);
8690         if (nspacelen + cnamelen + 2 > bufsize)
8691                 return 0;
8692         if (nspacelen) {
8693                 memcpy (buf, klass->name_space, nspacelen);
8694                 buf [nspacelen ++] = '.';
8695         }
8696         memcpy (buf + nspacelen, klass->name, cnamelen);
8697         buf [nspacelen + cnamelen] = 0;
8698         return nspacelen + cnamelen;
8699 }
8700
8701 #ifdef DISABLE_ICALL_TABLES
8702 static void
8703 no_icall_table (void)
8704 {
8705         g_assert_not_reached ();
8706 }
8707 #endif
8708
8709 gpointer
8710 mono_lookup_internal_call (MonoMethod *method)
8711 {
8712         char *sigstart;
8713         char *tmpsig;
8714         char mname [2048];
8715         int typelen = 0, mlen, siglen;
8716         gpointer res;
8717 #ifndef DISABLE_ICALL_TABLES
8718         const IcallTypeDesc *imap = NULL;
8719 #endif
8720
8721         g_assert (method != NULL);
8722
8723         if (method->is_inflated)
8724                 method = ((MonoMethodInflated *) method)->declaring;
8725
8726         if (method->klass->nested_in) {
8727                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8728                 if (!pos)
8729                         return NULL;
8730
8731                 mname [pos++] = '/';
8732                 mname [pos] = 0;
8733
8734                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8735                 if (!typelen)
8736                         return NULL;
8737
8738                 typelen += pos;
8739         } else {
8740                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8741                 if (!typelen)
8742                         return NULL;
8743         }
8744
8745 #ifndef DISABLE_ICALL_TABLES
8746         imap = find_class_icalls (mname);
8747 #endif
8748
8749         mname [typelen] = ':';
8750         mname [typelen + 1] = ':';
8751
8752         mlen = strlen (method->name);
8753         memcpy (mname + typelen + 2, method->name, mlen);
8754         sigstart = mname + typelen + 2 + mlen;
8755         *sigstart = 0;
8756
8757         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8758         siglen = strlen (tmpsig);
8759         if (typelen + mlen + siglen + 6 > sizeof (mname))
8760                 return NULL;
8761         sigstart [0] = '(';
8762         memcpy (sigstart + 1, tmpsig, siglen);
8763         sigstart [siglen + 1] = ')';
8764         sigstart [siglen + 2] = 0;
8765         g_free (tmpsig);
8766         
8767         mono_icall_lock ();
8768
8769         res = g_hash_table_lookup (icall_hash, mname);
8770         if (res) {
8771                 mono_icall_unlock ();;
8772                 return res;
8773         }
8774         /* try without signature */
8775         *sigstart = 0;
8776         res = g_hash_table_lookup (icall_hash, mname);
8777         if (res) {
8778                 mono_icall_unlock ();
8779                 return res;
8780         }
8781
8782 #ifdef DISABLE_ICALL_TABLES
8783         mono_icall_unlock ();
8784         /* Fail only when the result is actually used */
8785         /* mono_marshal_get_native_wrapper () depends on this */
8786         if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8787                 return ves_icall_System_String_ctor_RedirectToCreateString;
8788         else
8789                 return no_icall_table;
8790 #else
8791         /* it wasn't found in the static call tables */
8792         if (!imap) {
8793                 mono_icall_unlock ();
8794                 return NULL;
8795         }
8796         res = find_method_icall (imap, sigstart - mlen);
8797         if (res) {
8798                 mono_icall_unlock ();
8799                 return res;
8800         }
8801         /* try _with_ signature */
8802         *sigstart = '(';
8803         res = find_method_icall (imap, sigstart - mlen);
8804         if (res) {
8805                 mono_icall_unlock ();
8806                 return res;
8807         }
8808
8809         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8810         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8811         g_print ("The out of sync library is: %s\n", method->klass->image->name);
8812         g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8813         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");
8814         g_print ("If you see other errors or faults after this message they are probably related\n");
8815         g_print ("and you need to fix your mono install first.\n");
8816
8817         mono_icall_unlock ();
8818
8819         return NULL;
8820 #endif
8821 }
8822
8823 #ifdef ENABLE_ICALL_SYMBOL_MAP
8824 static int
8825 func_cmp (gconstpointer key, gconstpointer p)
8826 {
8827         return (gsize)key - (gsize)*(gsize*)p;
8828 }
8829 #endif
8830
8831 /*
8832  * mono_lookup_icall_symbol:
8833  *
8834  *   Given the icall METHOD, returns its C symbol.
8835  */
8836 const char*
8837 mono_lookup_icall_symbol (MonoMethod *m)
8838 {
8839 #ifdef DISABLE_ICALL_TABLES
8840         g_assert_not_reached ();
8841         return NULL;
8842 #else
8843 #ifdef ENABLE_ICALL_SYMBOL_MAP
8844         gpointer func;
8845         int i;
8846         gpointer slot;
8847         static gconstpointer *functions_sorted;
8848         static const char**symbols_sorted;
8849         static gboolean inited;
8850
8851         if (!inited) {
8852                 gboolean changed;
8853
8854                 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8855                 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8856                 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8857                 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8858                 /* Bubble sort the two arrays */
8859                 changed = TRUE;
8860                 while (changed) {
8861                         changed = FALSE;
8862                         for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8863                                 if (functions_sorted [i] > functions_sorted [i + 1]) {
8864                                         gconstpointer tmp;
8865
8866                                         tmp = functions_sorted [i];
8867                                         functions_sorted [i] = functions_sorted [i + 1];
8868                                         functions_sorted [i + 1] = tmp;
8869                                         tmp = symbols_sorted [i];
8870                                         symbols_sorted [i] = symbols_sorted [i + 1];
8871                                         symbols_sorted [i + 1] = tmp;
8872                                         changed = TRUE;
8873                                 }
8874                         }
8875                 }
8876         }
8877
8878         func = mono_lookup_internal_call (m);
8879         if (!func)
8880                 return NULL;
8881         slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8882         if (!slot)
8883                 return NULL;
8884         g_assert (slot);
8885         return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8886 #else
8887         fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8888         g_assert_not_reached ();
8889         return 0;
8890 #endif
8891 #endif
8892 }
8893
8894 static MonoType*
8895 type_from_typename (char *type_name)
8896 {
8897         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
8898
8899         if (!strcmp (type_name, "int"))
8900                 klass = mono_defaults.int_class;
8901         else if (!strcmp (type_name, "ptr"))
8902                 klass = mono_defaults.int_class;
8903         else if (!strcmp (type_name, "void"))
8904                 klass = mono_defaults.void_class;
8905         else if (!strcmp (type_name, "int32"))
8906                 klass = mono_defaults.int32_class;
8907         else if (!strcmp (type_name, "uint32"))
8908                 klass = mono_defaults.uint32_class;
8909         else if (!strcmp (type_name, "int8"))
8910                 klass = mono_defaults.sbyte_class;
8911         else if (!strcmp (type_name, "uint8"))
8912                 klass = mono_defaults.byte_class;
8913         else if (!strcmp (type_name, "int16"))
8914                 klass = mono_defaults.int16_class;
8915         else if (!strcmp (type_name, "uint16"))
8916                 klass = mono_defaults.uint16_class;
8917         else if (!strcmp (type_name, "long"))
8918                 klass = mono_defaults.int64_class;
8919         else if (!strcmp (type_name, "ulong"))
8920                 klass = mono_defaults.uint64_class;
8921         else if (!strcmp (type_name, "float"))
8922                 klass = mono_defaults.single_class;
8923         else if (!strcmp (type_name, "double"))
8924                 klass = mono_defaults.double_class;
8925         else if (!strcmp (type_name, "object"))
8926                 klass = mono_defaults.object_class;
8927         else if (!strcmp (type_name, "obj"))
8928                 klass = mono_defaults.object_class;
8929         else if (!strcmp (type_name, "string"))
8930                 klass = mono_defaults.string_class;
8931         else if (!strcmp (type_name, "bool"))
8932                 klass = mono_defaults.boolean_class;
8933         else if (!strcmp (type_name, "boolean"))
8934                 klass = mono_defaults.boolean_class;
8935         else {
8936                 g_error ("%s", type_name);
8937                 g_assert_not_reached ();
8938         }
8939         return &klass->byval_arg;
8940 }
8941
8942 /**
8943  * LOCKING: Take the corlib image lock.
8944  */
8945 MonoMethodSignature*
8946 mono_create_icall_signature (const char *sigstr)
8947 {
8948         gchar **parts;
8949         int i, len;
8950         gchar **tmp;
8951         MonoMethodSignature *res, *res2;
8952         MonoImage *corlib = mono_defaults.corlib;
8953
8954         mono_image_lock (corlib);
8955         res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8956         mono_image_unlock (corlib);
8957
8958         if (res)
8959                 return res;
8960
8961         parts = g_strsplit (sigstr, " ", 256);
8962
8963         tmp = parts;
8964         len = 0;
8965         while (*tmp) {
8966                 len ++;
8967                 tmp ++;
8968         }
8969
8970         res = mono_metadata_signature_alloc (corlib, len - 1);
8971         res->pinvoke = 1;
8972
8973 #ifdef HOST_WIN32
8974         /* 
8975          * Under windows, the default pinvoke calling convention is STDCALL but
8976          * we need CDECL.
8977          */
8978         res->call_convention = MONO_CALL_C;
8979 #endif
8980
8981         res->ret = type_from_typename (parts [0]);
8982         for (i = 1; i < len; ++i) {
8983                 res->params [i - 1] = type_from_typename (parts [i]);
8984         }
8985
8986         g_strfreev (parts);
8987
8988         mono_image_lock (corlib);
8989         res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8990         if (res2)
8991                 res = res2; /*Value is allocated in the image pool*/
8992         else
8993                 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8994         mono_image_unlock (corlib);
8995
8996         return res;
8997 }
8998
8999 MonoJitICallInfo *
9000 mono_find_jit_icall_by_name (const char *name)
9001 {
9002         MonoJitICallInfo *info;
9003         g_assert (jit_icall_hash_name);
9004
9005         mono_icall_lock ();
9006         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9007         mono_icall_unlock ();
9008         return info;
9009 }
9010
9011 MonoJitICallInfo *
9012 mono_find_jit_icall_by_addr (gconstpointer addr)
9013 {
9014         MonoJitICallInfo *info;
9015         g_assert (jit_icall_hash_addr);
9016
9017         mono_icall_lock ();
9018         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
9019         mono_icall_unlock ();
9020
9021         return info;
9022 }
9023
9024 /*
9025  * mono_get_jit_icall_info:
9026  *
9027  *   Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
9028  * caller should access it while holding the icall lock.
9029  */
9030 GHashTable*
9031 mono_get_jit_icall_info (void)
9032 {
9033         return jit_icall_hash_name;
9034 }
9035
9036 /*
9037  * mono_lookup_jit_icall_symbol:
9038  *
9039  *   Given the jit icall NAME, returns its C symbol if possible, or NULL.
9040  */
9041 const char*
9042 mono_lookup_jit_icall_symbol (const char *name)
9043 {
9044         MonoJitICallInfo *info;
9045         const char *res = NULL;
9046
9047         mono_icall_lock ();
9048         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9049         if (info)
9050                 res = info->c_symbol;
9051         mono_icall_unlock ();
9052         return res;
9053 }
9054
9055 void
9056 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
9057 {
9058         mono_icall_lock ();
9059         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
9060         mono_icall_unlock ();
9061 }
9062
9063 /*
9064  * 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
9065  * icalls without wrappers in some cases.
9066  */
9067 MonoJitICallInfo *
9068 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
9069 {
9070         MonoJitICallInfo *info;
9071         
9072         g_assert (func);
9073         g_assert (name);
9074
9075         mono_icall_lock ();
9076
9077         if (!jit_icall_hash_name) {
9078                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
9079                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
9080         }
9081
9082         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
9083                 g_warning ("jit icall already defined \"%s\"\n", name);
9084                 g_assert_not_reached ();
9085         }
9086
9087         info = g_new0 (MonoJitICallInfo, 1);
9088         
9089         info->name = name;
9090         info->func = func;
9091         info->sig = sig;
9092         info->c_symbol = c_symbol;
9093         info->no_raise = no_raise;
9094
9095         if (is_save) {
9096                 info->wrapper = func;
9097         } else {
9098                 info->wrapper = NULL;
9099         }
9100
9101         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
9102         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
9103
9104         mono_icall_unlock ();
9105         return info;
9106 }
9107
9108 MonoJitICallInfo *
9109 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
9110 {
9111         return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);
9112 }
9113