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