Merge pull request #3320 from lambdageek/dev/reflection-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, char *str, guint32 bflags)
4358 {
4359         MonoClass *klass;
4360         int match;
4361         MonoClass *nested;
4362         gpointer iter;
4363         GPtrArray *res_array;
4364
4365         if (type->type->byref) {
4366                 return g_ptr_array_new ();
4367         }
4368
4369         klass = mono_class_from_mono_type (type->type);
4370
4371         /*
4372          * If a nested type is generic, return its generic type definition.
4373          * Note that this means that the return value is essentially the set
4374          * of nested types of the generic type definition of @klass.
4375          *
4376          * A note in MSDN claims that a generic type definition can have
4377          * nested types that aren't generic.  In any case, the container of that
4378          * nested type would be the generic type definition.
4379          */
4380         if (klass->generic_class)
4381                 klass = klass->generic_class->container_class;
4382
4383         res_array = g_ptr_array_new ();
4384         
4385         iter = NULL;
4386         while ((nested = mono_class_get_nested_types (klass, &iter))) {
4387                 match = 0;
4388                 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4389                         if (bflags & BFLAGS_Public)
4390                                 match++;
4391                 } else {
4392                         if (bflags & BFLAGS_NonPublic)
4393                                 match++;
4394                 }
4395                 if (!match)
4396                         continue;
4397
4398                 if (str != NULL && strcmp (nested->name, str))
4399                                 continue;
4400
4401                 g_ptr_array_add (res_array, &nested->byval_arg);
4402         }
4403
4404         return res_array;
4405 }
4406
4407 ICALL_EXPORT MonoReflectionType*
4408 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4409 {
4410         MonoError error;
4411         MonoReflectionType *ret;
4412         gchar *str;
4413         MonoType *type = NULL;
4414         MonoTypeNameParse info;
4415         gboolean type_resolve;
4416
4417         /* On MS.NET, this does not fire a TypeResolve event */
4418         type_resolve = TRUE;
4419         str = mono_string_to_utf8_checked (name, &error);
4420         if (mono_error_set_pending_exception (&error))
4421                 return NULL;
4422         /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4423         if (!mono_reflection_parse_type (str, &info)) {
4424                 g_free (str);
4425                 mono_reflection_free_type_info (&info);
4426                 if (throwOnError) {
4427                         mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4428                         return NULL;
4429                 }
4430                 /*g_print ("failed parse\n");*/
4431                 return NULL;
4432         }
4433
4434         if (info.assembly.name) {
4435                 g_free (str);
4436                 mono_reflection_free_type_info (&info);
4437                 if (throwOnError) {
4438                         /* 1.0 and 2.0 throw different exceptions */
4439                         if (mono_defaults.generic_ilist_class)
4440                                 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4441                         else
4442                                 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4443                         return NULL;
4444                 }
4445                 return NULL;
4446         }
4447
4448         if (module != NULL) {
4449                 if (module->image) {
4450                         type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4451                         if (!is_ok (&error)) {
4452                                 g_free (str);
4453                                 mono_reflection_free_type_info (&info);
4454                                 mono_error_set_pending_exception (&error);
4455                                 return NULL;
4456                         }
4457                 } else
4458                         type = NULL;
4459         }
4460         else
4461                 if (assembly_is_dynamic (assembly->assembly)) {
4462                         /* Enumerate all modules */
4463                         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4464                         int i;
4465
4466                         type = NULL;
4467                         if (abuilder->modules) {
4468                                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4469                                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4470                                         type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4471                                         if (!is_ok (&error)) {
4472                                                 g_free (str);
4473                                                 mono_reflection_free_type_info (&info);
4474                                                 mono_error_set_pending_exception (&error);
4475                                                 return NULL;
4476                                         }
4477                                         if (type)
4478                                                 break;
4479                                 }
4480                         }
4481
4482                         if (!type && abuilder->loaded_modules) {
4483                                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4484                                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4485                                         type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4486                                         if (!is_ok (&error)) {
4487                                                 g_free (str);
4488                                                 mono_reflection_free_type_info (&info);
4489                                                 mono_error_set_pending_exception (&error);
4490                                                 return NULL;
4491                                         }
4492                                         if (type)
4493                                                 break;
4494                                 }
4495                         }
4496                 }
4497                 else {
4498                         type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4499                         if (!is_ok (&error)) {
4500                                 g_free (str);
4501                                 mono_reflection_free_type_info (&info);
4502                                 mono_error_set_pending_exception (&error);
4503                                 return NULL;
4504                         }
4505                 }
4506         g_free (str);
4507         mono_reflection_free_type_info (&info);
4508         if (!type) {
4509                 MonoException *e = NULL;
4510                 
4511                 if (throwOnError)
4512                         e = mono_get_exception_type_load (name, NULL);
4513
4514                 if (e != NULL)
4515                         mono_set_pending_exception (e);
4516                 return NULL;
4517         }
4518
4519         if (type->type == MONO_TYPE_CLASS) {
4520                 MonoClass *klass = mono_type_get_class (type);
4521
4522                 /* need to report exceptions ? */
4523                 if (throwOnError && mono_class_has_failure (klass)) {
4524                         /* report SecurityException (or others) that occured when loading the assembly */
4525                         MonoException *exc = mono_class_get_exception_for_failure (klass);
4526                         mono_set_pending_exception (exc);
4527                         return NULL;
4528                 }
4529         }
4530
4531         /* g_print ("got it\n"); */
4532         ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4533         mono_error_set_pending_exception (&error);
4534
4535         return ret;
4536 }
4537
4538 static gboolean
4539 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4540 {
4541         gchar *content;
4542         gchar *shadow_ini_file;
4543         gsize len;
4544
4545         /* Check for shadow-copied assembly */
4546         if (mono_is_shadow_copy_enabled (domain, dirname)) {
4547                 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4548                 content = NULL;
4549                 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4550                         !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4551                         if (content) {
4552                                 g_free (content);
4553                                 content = NULL;
4554                         }
4555                 }
4556                 g_free (shadow_ini_file);
4557                 if (content != NULL) {
4558                         if (*filename)
4559                                 g_free (*filename);
4560                         *filename = content;
4561                         return TRUE;
4562                 }
4563         }
4564         return FALSE;
4565 }
4566
4567 ICALL_EXPORT MonoString *
4568 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4569 {
4570         MonoDomain *domain = mono_object_domain (assembly); 
4571         MonoAssembly *mass = assembly->assembly;
4572         MonoString *res = NULL;
4573         gchar *uri;
4574         gchar *absolute;
4575         gchar *dirname;
4576         
4577         if (g_path_is_absolute (mass->image->name)) {
4578                 absolute = g_strdup (mass->image->name);
4579                 dirname = g_path_get_dirname (absolute);
4580         } else {
4581                 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4582                 dirname = g_strdup (mass->basedir);
4583         }
4584
4585         replace_shadow_path (domain, dirname, &absolute);
4586         g_free (dirname);
4587 #if HOST_WIN32
4588         {
4589                 gint i;
4590                 for (i = strlen (absolute) - 1; i >= 0; i--)
4591                         if (absolute [i] == '\\')
4592                                 absolute [i] = '/';
4593         }
4594 #endif
4595         if (escaped) {
4596                 uri = g_filename_to_uri (absolute, NULL, NULL);
4597         } else {
4598                 const char *prepend = "file://";
4599 #if HOST_WIN32
4600                 if (*absolute == '/' && *(absolute + 1) == '/') {
4601                         prepend = "file:";
4602                 } else {
4603                         prepend = "file:///";
4604                 }
4605 #endif
4606                 uri = g_strconcat (prepend, absolute, NULL);
4607         }
4608
4609         if (uri) {
4610                 res = mono_string_new (domain, uri);
4611                 g_free (uri);
4612         }
4613         g_free (absolute);
4614         return res;
4615 }
4616
4617 ICALL_EXPORT MonoBoolean
4618 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4619 {
4620         MonoAssembly *mass = assembly->assembly;
4621
4622         return mass->in_gac;
4623 }
4624
4625 ICALL_EXPORT MonoReflectionAssembly*
4626 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4627 {
4628         MonoError error;
4629         gchar *name;
4630         MonoAssembly *res;
4631         MonoImageOpenStatus status;
4632         MonoReflectionAssembly* result = NULL;
4633         
4634         name = mono_string_to_utf8_checked (mname, &error);
4635         if (mono_error_set_pending_exception (&error))
4636                 return NULL;
4637         res = mono_assembly_load_with_partial_name (name, &status);
4638
4639         g_free (name);
4640
4641         if (res == NULL)
4642                 return NULL;
4643         result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4644         if (!result)
4645                 mono_error_set_pending_exception (&error);
4646         return result;
4647 }
4648
4649 ICALL_EXPORT MonoString *
4650 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4651 {
4652         MonoDomain *domain = mono_object_domain (assembly); 
4653         MonoString *res;
4654
4655         res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4656
4657         return res;
4658 }
4659
4660 ICALL_EXPORT MonoBoolean
4661 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4662 {
4663         return assembly->assembly->ref_only;
4664 }
4665
4666 ICALL_EXPORT MonoString *
4667 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4668 {
4669         MonoDomain *domain = mono_object_domain (assembly); 
4670
4671         return mono_string_new (domain, assembly->assembly->image->version);
4672 }
4673
4674 ICALL_EXPORT MonoReflectionMethod*
4675 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly) 
4676 {
4677         MonoError error;
4678         MonoReflectionMethod *res = NULL;
4679         MonoMethod *method;
4680
4681         guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4682
4683         if (!token)
4684                 return NULL;
4685         method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4686         if (!mono_error_ok (&error))
4687                 goto leave;
4688
4689         res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4690
4691 leave:
4692         if (!mono_error_ok (&error))
4693                 mono_error_set_pending_exception (&error);
4694         return res;
4695 }
4696
4697 ICALL_EXPORT MonoReflectionModule*
4698 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly) 
4699 {
4700         MonoError error;
4701         MonoReflectionModule *result = NULL;
4702         result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4703         if (!mono_error_ok (&error))
4704                 mono_error_set_pending_exception (&error);
4705         return result;
4706 }
4707
4708 ICALL_EXPORT MonoArray*
4709 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly) 
4710 {
4711         MonoError error;
4712         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4713         MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4714         if (mono_error_set_pending_exception (&error))
4715                 return NULL;
4716         int i;
4717         const char *val;
4718
4719         for (i = 0; i < table->rows; ++i) {
4720                 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4721                 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4722         }
4723         return result;
4724 }
4725
4726 ICALL_EXPORT MonoString*
4727 ves_icall_System_Reflection_Assembly_GetAotId ()
4728 {
4729         int i;
4730         guint8 aotid_sum = 0;
4731         MonoDomain* domain = mono_domain_get ();
4732
4733         if (!domain->entry_assembly || !domain->entry_assembly->image)
4734                 return NULL;
4735
4736         guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
4737
4738         for (i = 0; i < 16; ++i)
4739                 aotid_sum |= (*aotid)[i];
4740
4741         if (aotid_sum == 0)
4742                 return NULL;
4743         
4744         return mono_string_new (domain, mono_guid_to_string((guint8*) aotid));
4745 }
4746
4747 static MonoObject*
4748 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4749 {
4750         static MonoMethod *create_version = NULL;
4751         MonoObject *result;
4752         gpointer args [4];
4753
4754         mono_error_init (error);
4755         
4756
4757         if (!create_version) {
4758                 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4759                 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4760                 g_assert (create_version);
4761                 mono_method_desc_free (desc);
4762         }
4763
4764         args [0] = &major;
4765         args [1] = &minor;
4766         args [2] = &build;
4767         args [3] = &revision;
4768         result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4769         return_val_if_nok (error, NULL);
4770
4771         mono_runtime_invoke_checked (create_version, result, args, error);
4772         return_val_if_nok (error, NULL);
4773
4774         return result;
4775 }
4776
4777 ICALL_EXPORT MonoArray*
4778 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly) 
4779 {
4780         MonoError error;
4781         MonoArray *result;
4782         MonoDomain *domain = mono_object_domain (assembly);
4783         int i, count = 0;
4784         static MonoMethod *create_culture = NULL;
4785         MonoImage *image = assembly->assembly->image;
4786         MonoTableInfo *t;
4787         MonoObject *o;
4788
4789         t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4790         count = t->rows;
4791
4792         result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4793         if (mono_error_set_pending_exception (&error))
4794                 return NULL;
4795
4796
4797         if (count > 0 && !create_culture) {
4798                 MonoMethodDesc *desc = mono_method_desc_new (
4799                         "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4800                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4801                 g_assert (create_culture);
4802                 mono_method_desc_free (desc);
4803         }
4804
4805         for (i = 0; i < count; i++) {
4806                 MonoObject *version;
4807                 MonoReflectionAssemblyName *aname;
4808                 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4809
4810                 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4811
4812                 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4813                         domain, mono_class_get_assembly_name_class (), &error);
4814                 if (mono_error_set_pending_exception (&error))
4815                         return NULL;
4816
4817                 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4818
4819                 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4820                 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4821                 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4822                 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4823                 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4824                 aname->versioncompat = 1; /* SameMachine (default) */
4825                 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4826
4827                 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4828                 if (mono_error_set_pending_exception (&error))
4829                         return NULL;
4830
4831                 MONO_OBJECT_SETREF (aname, version, version);
4832
4833                 if (create_culture) {
4834                         gpointer args [2];
4835                         MonoBoolean assembly_ref = 1;
4836                         args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4837                         args [1] = &assembly_ref;
4838
4839                         o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4840                         if (mono_error_set_pending_exception (&error))
4841                                 return NULL;
4842
4843                         MONO_OBJECT_SETREF (aname, cultureInfo, o);
4844                 }
4845                 
4846                 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4847                         const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4848                         guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4849
4850                         if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4851                                 /* public key token isn't copied - the class library will 
4852                                 automatically generate it from the public key if required */
4853                                 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4854                                 if (mono_error_set_pending_exception (&error))
4855                                         return NULL;
4856
4857                                 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4858                                 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4859                         } else {
4860                                 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4861                                 if (mono_error_set_pending_exception (&error))
4862                                         return NULL;
4863
4864                                 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4865                                 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
4866                         }
4867                 } else {
4868                         MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
4869                         if (mono_error_set_pending_exception (&error))
4870                                 return NULL;
4871
4872                         MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4873                 }
4874                 
4875                 /* note: this function doesn't return the codebase on purpose (i.e. it can
4876                          be used under partial trust as path information isn't present). */
4877
4878                 mono_array_setref (result, i, aname);
4879         }
4880         return result;
4881 }
4882
4883 /* move this in some file in mono/util/ */
4884 static char *
4885 g_concat_dir_and_file (const char *dir, const char *file)
4886 {
4887         g_return_val_if_fail (dir != NULL, NULL);
4888         g_return_val_if_fail (file != NULL, NULL);
4889
4890         /*
4891          * If the directory name doesn't have a / on the end, we need
4892          * to add one so we get a proper path to the file
4893          */
4894         if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4895                 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4896         else
4897                 return g_strconcat (dir, file, NULL);
4898 }
4899
4900 ICALL_EXPORT void *
4901 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module) 
4902 {
4903         MonoError error;
4904         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4905         guint32 i;
4906         guint32 cols [MONO_MANIFEST_SIZE];
4907         guint32 impl, file_idx;
4908         const char *val;
4909         MonoImage *module;
4910
4911         char *n = mono_string_to_utf8_checked (name, &error);
4912         if (mono_error_set_pending_exception (&error))
4913                 return NULL;
4914
4915         for (i = 0; i < table->rows; ++i) {
4916                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4917                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4918                 if (strcmp (val, n) == 0)
4919                         break;
4920         }
4921         g_free (n);
4922         if (i == table->rows)
4923                 return NULL;
4924         /* FIXME */
4925         impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4926         if (impl) {
4927                 /*
4928                  * this code should only be called after obtaining the 
4929                  * ResourceInfo and handling the other cases.
4930                  */
4931                 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4932                 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4933
4934                 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4935                 if (!module)
4936                         return NULL;
4937         }
4938         else
4939                 module = assembly->assembly->image;
4940
4941         
4942         MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4943         if (mono_error_set_pending_exception (&error))
4944                 return NULL;
4945         mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4946
4947         return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4948 }
4949
4950 ICALL_EXPORT gboolean
4951 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4952 {
4953         MonoError error;
4954         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4955         int i;
4956         guint32 cols [MONO_MANIFEST_SIZE];
4957         guint32 file_cols [MONO_FILE_SIZE];
4958         const char *val;
4959         char *n;
4960
4961         n = mono_string_to_utf8_checked (name, &error);
4962         if (mono_error_set_pending_exception (&error))
4963                 return FALSE;
4964         for (i = 0; i < table->rows; ++i) {
4965                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4966                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4967                 if (strcmp (val, n) == 0)
4968                         break;
4969         }
4970         g_free (n);
4971         if (i == table->rows)
4972                 return FALSE;
4973
4974         if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4975                 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4976         }
4977         else {
4978                 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4979                 case MONO_IMPLEMENTATION_FILE:
4980                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4981                         table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4982                         mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4983                         val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4984                         MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4985                         if (file_cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA)
4986                                 info->location = 0;
4987                         else
4988                                 info->location = RESOURCE_LOCATION_EMBEDDED;
4989                         break;
4990
4991                 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4992                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4993                         mono_assembly_load_reference (assembly->assembly->image, i - 1);
4994                         if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4995                                 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4996                                 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4997                                 g_free (msg);
4998                                 mono_set_pending_exception (ex);
4999                                 return FALSE;
5000                         }
5001                         MonoReflectionAssembly *assm_obj;
5002                         assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5003                         if (!assm_obj) {
5004                                 mono_error_set_pending_exception (&error);
5005                                 return FALSE;
5006                         }
5007                         MONO_OBJECT_SETREF (info, assembly, assm_obj);
5008
5009                         /* Obtain info recursively */
5010                         ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5011                         info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5012                         break;
5013
5014                 case MONO_IMPLEMENTATION_EXP_TYPE:
5015                         g_assert_not_reached ();
5016                         break;
5017                 }
5018         }
5019
5020         return TRUE;
5021 }
5022
5023 ICALL_EXPORT MonoObject*
5024 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules) 
5025 {
5026         MonoError error;
5027         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5028         MonoArray *result = NULL;
5029         int i, count;
5030         const char *val;
5031         char *n;
5032
5033         /* check hash if needed */
5034         if (name) {
5035                 n = mono_string_to_utf8_checked (name, &error);
5036                 if (mono_error_set_pending_exception (&error))
5037                         return NULL;
5038
5039                 for (i = 0; i < table->rows; ++i) {
5040                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5041                         if (strcmp (val, n) == 0) {
5042                                 MonoString *fn;
5043                                 g_free (n);
5044                                 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5045                                 fn = mono_string_new (mono_object_domain (assembly), n);
5046                                 g_free (n);
5047                                 return (MonoObject*)fn;
5048                         }
5049                 }
5050                 g_free (n);
5051                 return NULL;
5052         }
5053
5054         count = 0;
5055         for (i = 0; i < table->rows; ++i) {
5056                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5057                         count ++;
5058         }
5059
5060         result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
5061         if (mono_error_set_pending_exception (&error))
5062                 return NULL;
5063
5064
5065         count = 0;
5066         for (i = 0; i < table->rows; ++i) {
5067                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5068                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5069                         n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5070                         mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5071                         g_free (n);
5072                         count ++;
5073                 }
5074         }
5075         return (MonoObject*)result;
5076 }
5077
5078 ICALL_EXPORT MonoArray*
5079 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5080 {
5081         MonoError error;
5082         MonoDomain *domain = mono_domain_get();
5083         MonoArray *res;
5084         MonoClass *klass;
5085         int i, j, file_count = 0;
5086         MonoImage **modules;
5087         guint32 module_count, real_module_count;
5088         MonoTableInfo *table;
5089         guint32 cols [MONO_FILE_SIZE];
5090         MonoImage *image = assembly->assembly->image;
5091
5092         g_assert (image != NULL);
5093         g_assert (!assembly_is_dynamic (assembly->assembly));
5094
5095         table = &image->tables [MONO_TABLE_FILE];
5096         file_count = table->rows;
5097
5098         modules = image->modules;
5099         module_count = image->module_count;
5100
5101         real_module_count = 0;
5102         for (i = 0; i < module_count; ++i)
5103                 if (modules [i])
5104                         real_module_count ++;
5105
5106         klass = mono_class_get_module_class ();
5107         res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5108         if (mono_error_set_pending_exception (&error))
5109                 return NULL;
5110
5111         MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5112         if (mono_error_set_pending_exception (&error))
5113                 return NULL;
5114
5115         mono_array_setref (res, 0, image_obj);
5116         j = 1;
5117         for (i = 0; i < module_count; ++i)
5118                 if (modules [i]) {
5119                         MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5120                         if (mono_error_set_pending_exception (&error))
5121                                 return NULL;
5122                         mono_array_setref (res, j, rm);
5123                         ++j;
5124                 }
5125
5126         for (i = 0; i < file_count; ++i, ++j) {
5127                 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5128                 if (cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA) {
5129                         MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5130                         if (mono_error_set_pending_exception (&error))
5131                                 return NULL;
5132                         mono_array_setref (res, j, rm);
5133                 }
5134                 else {
5135                         MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5136                         if (!m) {
5137                                 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5138                                 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5139                                 return NULL;
5140                         }
5141                         MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5142                         if (mono_error_set_pending_exception (&error))
5143                                 return NULL;
5144                         mono_array_setref (res, j, rm);
5145                 }
5146         }
5147
5148         return res;
5149 }
5150
5151 ICALL_EXPORT MonoReflectionMethod*
5152 ves_icall_GetCurrentMethod (void) 
5153 {
5154         MonoReflectionMethod *res = NULL;
5155         MonoError error;
5156
5157         MonoMethod *m = mono_method_get_last_managed ();
5158
5159         if (!m) {
5160                 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5161                 return NULL;
5162         }
5163
5164         while (m->is_inflated)
5165                 m = ((MonoMethodInflated*)m)->declaring;
5166
5167         res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5168         mono_error_set_pending_exception (&error);
5169         return res;
5170 }
5171
5172
5173 static MonoMethod*
5174 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5175 {
5176         int offset = -1, i;
5177         if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5178                 MonoError error;
5179                 MonoMethod *result;
5180                 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5181                 //method is inflated, we should inflate it on the other class
5182                 MonoGenericContext ctx;
5183                 ctx.method_inst = inflated->context.method_inst;
5184                 ctx.class_inst = inflated->context.class_inst;
5185                 if (klass->generic_class)
5186                         ctx.class_inst = klass->generic_class->context.class_inst;
5187                 else if (klass->generic_container)
5188                         ctx.class_inst = klass->generic_container->context.class_inst;
5189                 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5190                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5191                 return result;
5192         }
5193
5194         mono_class_setup_methods (method->klass);
5195         if (mono_class_has_failure (method->klass))
5196                 return NULL;
5197         for (i = 0; i < method->klass->method.count; ++i) {
5198                 if (method->klass->methods [i] == method) {
5199                         offset = i;
5200                         break;
5201                 }       
5202         }
5203         mono_class_setup_methods (klass);
5204         if (mono_class_has_failure (klass))
5205                 return NULL;
5206         g_assert (offset >= 0 && offset < klass->method.count);
5207         return klass->methods [offset];
5208 }
5209
5210 ICALL_EXPORT MonoReflectionMethod*
5211 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check)
5212 {
5213         MonoReflectionMethod *res = NULL;
5214         MonoError error;
5215         MonoClass *klass;
5216         if (type && generic_check) {
5217                 klass = mono_class_from_mono_type (type);
5218                 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5219                         return NULL;
5220
5221                 if (method->klass != klass) {
5222                         method = mono_method_get_equivalent_method (method, klass);
5223                         if (!method)
5224                                 return NULL;
5225                 }
5226         } else if (type)
5227                 klass = mono_class_from_mono_type (type);
5228         else
5229                 klass = method->klass;
5230         res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5231         mono_error_set_pending_exception (&error);
5232         return res;
5233 }
5234
5235 ICALL_EXPORT MonoReflectionMethodBody*
5236 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5237 {
5238         MonoError error;
5239         MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5240         mono_error_set_pending_exception (&error);
5241         return result;
5242 }
5243
5244 ICALL_EXPORT MonoReflectionAssembly*
5245 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5246 {
5247         MonoError error;
5248         MonoReflectionAssembly *result;
5249         MonoMethod *dest = NULL;
5250
5251         mono_stack_walk_no_il (get_executing, &dest);
5252         g_assert (dest);
5253         result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5254         if (!result)
5255                 mono_error_set_pending_exception (&error);
5256         return result;
5257 }
5258
5259
5260 ICALL_EXPORT MonoReflectionAssembly*
5261 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5262 {
5263         MonoError error;
5264         MonoReflectionAssembly *result;
5265         MonoDomain* domain = mono_domain_get ();
5266
5267         if (!domain->entry_assembly)
5268                 return NULL;
5269
5270         result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5271         if (!result)
5272                 mono_error_set_pending_exception (&error);
5273         return result;
5274 }
5275
5276 ICALL_EXPORT MonoReflectionAssembly*
5277 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5278 {
5279         MonoError error;
5280         MonoMethod *m;
5281         MonoMethod *dest;
5282         MonoReflectionAssembly *result;
5283
5284         dest = NULL;
5285         mono_stack_walk_no_il (get_executing, &dest);
5286         m = dest;
5287         mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5288         if (!dest)
5289                 dest = m;
5290         if (!m) {
5291                 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5292                 return NULL;
5293         }
5294         result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5295         if (!result)
5296                 mono_error_set_pending_exception (&error);
5297         return result;
5298 }
5299
5300 ICALL_EXPORT MonoString *
5301 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5302                                        gboolean assembly_qualified)
5303 {
5304         MonoDomain *domain = mono_object_domain (object); 
5305         MonoTypeNameFormat format;
5306         MonoString *res;
5307         gchar *name;
5308
5309         if (full_name)
5310                 format = assembly_qualified ?
5311                         MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5312                         MONO_TYPE_NAME_FORMAT_FULL_NAME;
5313         else
5314                 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5315  
5316         name = mono_type_get_name_full (object->type, format);
5317         if (!name)
5318                 return NULL;
5319
5320         if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5321                 g_free (name);
5322                 return NULL;
5323         }
5324
5325         res = mono_string_new (domain, name);
5326         g_free (name);
5327
5328         return res;
5329 }
5330
5331 ICALL_EXPORT int
5332 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5333 {
5334         MonoError error;
5335         MonoClass *klass = mono_class_from_mono_type (rfield->type);
5336
5337         mono_class_init_checked (klass, &error);
5338         mono_error_set_pending_exception (&error);
5339         return mono_security_core_clr_class_level (klass);
5340 }
5341
5342 ICALL_EXPORT int
5343 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5344 {
5345         MonoClassField *field = rfield->field;
5346         return mono_security_core_clr_field_level (field, TRUE);
5347 }
5348
5349 ICALL_EXPORT int
5350 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5351 {
5352         MonoMethod *method = rfield->method;
5353         return mono_security_core_clr_method_level (method, TRUE);
5354 }
5355
5356 static void
5357 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)
5358 {
5359         static MonoMethod *create_culture = NULL;
5360         MonoObject *obj;
5361         gpointer args [2];
5362         guint32 pkey_len;
5363         const char *pkey_ptr;
5364         gchar *codebase;
5365         MonoBoolean assembly_ref = 0;
5366
5367         mono_error_init (error);
5368
5369         MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5370         aname->major = name->major;
5371         aname->minor = name->minor;
5372         aname->build = name->build;
5373         aname->flags = name->flags;
5374         aname->revision = name->revision;
5375         aname->hashalg = name->hash_alg;
5376         aname->versioncompat = 1; /* SameMachine (default) */
5377         aname->processor_architecture = name->arch;
5378
5379         if (by_default_version) {
5380                 MonoObject *version;
5381
5382                 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5383                 return_if_nok (error);
5384
5385                 MONO_OBJECT_SETREF (aname, version, version);
5386         }
5387
5388         codebase = NULL;
5389         if (absolute != NULL && *absolute != '\0') {
5390                 const gchar *prepend = "file://";
5391                 gchar *result;
5392
5393                 codebase = g_strdup (absolute);
5394
5395 #if HOST_WIN32
5396                 {
5397                         gint i;
5398                         for (i = strlen (codebase) - 1; i >= 0; i--)
5399                                 if (codebase [i] == '\\')
5400                                         codebase [i] = '/';
5401
5402                         if (*codebase == '/' && *(codebase + 1) == '/') {
5403                                 prepend = "file:";
5404                         } else {
5405                                 prepend = "file:///";
5406                         }
5407                 }
5408 #endif
5409                 result = g_strconcat (prepend, codebase, NULL);
5410                 g_free (codebase);
5411                 codebase = result;
5412         }
5413
5414         if (codebase) {
5415                 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5416                 g_free (codebase);
5417         }
5418
5419         if (!create_culture) {
5420                 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5421                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5422                 g_assert (create_culture);
5423                 mono_method_desc_free (desc);
5424         }
5425
5426         if (name->culture) {
5427                 args [0] = mono_string_new (domain, name->culture);
5428                 args [1] = &assembly_ref;
5429
5430                 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5431                 return_if_nok (error);
5432
5433                 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5434         }
5435
5436         if (name->public_key) {
5437                 pkey_ptr = (char*)name->public_key;
5438                 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5439
5440                 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5441                 return_if_nok (error);
5442                 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5443                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5444                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5445         } else if (default_publickey) {
5446                 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5447                 return_if_nok (error);
5448                 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5449                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5450         }
5451
5452         /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5453         if (name->public_key_token [0]) {
5454                 int i, j;
5455                 char *p;
5456
5457                 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5458                 return_if_nok (error);
5459                 
5460                 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5461                 p = mono_array_addr (keyToken, char, 0);
5462
5463                 for (i = 0, j = 0; i < 8; i++) {
5464                         *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5465                         *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5466                         p++;
5467                 }
5468         } else if (default_token) {
5469                 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5470                 return_if_nok (error);
5471                 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5472         }
5473 }
5474
5475 ICALL_EXPORT MonoString *
5476 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5477 {
5478         MonoDomain *domain = mono_object_domain (assembly); 
5479         MonoAssembly *mass = assembly->assembly;
5480         MonoString *res;
5481         gchar *name;
5482
5483         name = mono_stringify_assembly_name (&mass->aname);
5484         res = mono_string_new (domain, name);
5485         g_free (name);
5486
5487         return res;
5488 }
5489
5490 ICALL_EXPORT void
5491 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5492 {
5493         MonoError error;
5494         gchar *absolute, *dirname;
5495         MonoAssembly *mass = assembly->assembly;
5496
5497         /* XXX this is duplicated code to compute the codebase URI, unify it */
5498         if (g_path_is_absolute (mass->image->name)) {
5499                 absolute = g_strdup (mass->image->name);
5500                 dirname = g_path_get_dirname (absolute);
5501         } else {
5502                 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5503                 dirname = g_strdup (mass->basedir);
5504         }
5505
5506         replace_shadow_path (mono_object_domain (assembly), dirname, &absolute);
5507         g_free (dirname);
5508
5509         fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5510         mono_error_set_pending_exception (&error);
5511
5512         g_free (absolute);
5513 }
5514
5515 ICALL_EXPORT void
5516 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5517 {
5518         MonoError error;
5519         char *filename;
5520         MonoImageOpenStatus status = MONO_IMAGE_OK;
5521         gboolean res;
5522         MonoImage *image;
5523         MonoAssemblyName name;
5524         char *dirname;
5525
5526         filename = mono_string_to_utf8_checked (fname, &error);
5527         if (mono_error_set_pending_exception (&error))
5528                 return;
5529
5530         dirname = g_path_get_dirname (filename);
5531         replace_shadow_path (mono_domain_get (), dirname, &filename);
5532         g_free (dirname);
5533
5534         image = mono_image_open (filename, &status);
5535
5536         if (!image){
5537                 MonoException *exc;
5538
5539                 g_free (filename);
5540                 if (status == MONO_IMAGE_IMAGE_INVALID)
5541                         exc = mono_get_exception_bad_image_format2 (NULL, fname);
5542                 else
5543                         exc = mono_get_exception_file_not_found2 (NULL, fname);
5544                 mono_set_pending_exception (exc);
5545                 return;
5546         }
5547
5548         res = mono_assembly_fill_assembly_name (image, &name);
5549         if (!res) {
5550                 mono_image_close (image);
5551                 g_free (filename);
5552                 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5553                 return;
5554         }
5555
5556         fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5557         mono_error_set_pending_exception (&error);
5558
5559         mono_image_close (image);
5560         g_free (filename);
5561 }
5562
5563 ICALL_EXPORT MonoBoolean
5564 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5565         char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5566 {
5567         MonoBoolean result = FALSE;
5568         MonoDeclSecurityEntry entry;
5569
5570         /* SecurityAction.RequestMinimum */
5571         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5572                 *minimum = entry.blob;
5573                 *minLength = entry.size;
5574                 result = TRUE;
5575         }
5576         /* SecurityAction.RequestOptional */
5577         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5578                 *optional = entry.blob;
5579                 *optLength = entry.size;
5580                 result = TRUE;
5581         }
5582         /* SecurityAction.RequestRefuse */
5583         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5584                 *refused = entry.blob;
5585                 *refLength = entry.size;
5586                 result = TRUE;
5587         }
5588
5589         return result;  
5590 }
5591
5592 static gboolean
5593 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5594 {
5595         guint32 attrs, visibility;
5596         do {
5597                 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5598                 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5599                 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5600                         return FALSE;
5601
5602         } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5603
5604         return TRUE;
5605 }
5606
5607 static MonoArray*
5608 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5609 {
5610         MonoReflectionType *rt;
5611         MonoArray *res;
5612         MonoClass *klass;
5613         MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5614         int i, count;
5615
5616         mono_error_init (error);
5617
5618         /* we start the count from 1 because we skip the special type <Module> */
5619         if (exportedOnly) {
5620                 count = 0;
5621                 for (i = 1; i < tdef->rows; ++i) {
5622                         if (mono_module_type_is_visible (tdef, image, i + 1))
5623                                 count++;
5624                 }
5625         } else {
5626                 count = tdef->rows - 1;
5627         }
5628         res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5629         return_val_if_nok (error, NULL);
5630         *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5631         return_val_if_nok (error, NULL);
5632         count = 0;
5633         for (i = 1; i < tdef->rows; ++i) {
5634                 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5635                         klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5636                         
5637                         if (klass) {
5638                                 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5639                                 return_val_if_nok (error, NULL);
5640
5641                                 mono_array_setref (res, count, rt);
5642                         } else {
5643                                 MonoException *ex = mono_error_convert_to_exception (error);
5644                                 mono_array_setref (*exceptions, count, ex);
5645                         }
5646                         count++;
5647                 }
5648         }
5649         
5650         return res;
5651 }
5652
5653 ICALL_EXPORT MonoArray*
5654 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5655 {
5656         MonoError error;
5657         MonoArray *res = NULL;
5658         MonoArray *exceptions = NULL;
5659         MonoImage *image = NULL;
5660         MonoTableInfo *table = NULL;
5661         MonoDomain *domain;
5662         GList *list = NULL;
5663         int i, len, ex_count;
5664
5665         domain = mono_object_domain (assembly);
5666
5667         g_assert (!assembly_is_dynamic (assembly->assembly));
5668         image = assembly->assembly->image;
5669         table = &image->tables [MONO_TABLE_FILE];
5670         res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5671         if (mono_error_set_pending_exception (&error))
5672                 return NULL;
5673
5674         /* Append data from all modules in the assembly */
5675         for (i = 0; i < table->rows; ++i) {
5676                 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5677                         MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5678                         if (loaded_image) {
5679                                 MonoArray *ex2;
5680                                 MonoArray *res2;
5681
5682                                 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5683                                 if (mono_error_set_pending_exception (&error))
5684                                         return NULL;
5685
5686
5687                                 /* Append the new types to the end of the array */
5688                                 if (mono_array_length (res2) > 0) {
5689                                         guint32 len1, len2;
5690                                         MonoArray *res3, *ex3;
5691
5692                                         len1 = mono_array_length (res);
5693                                         len2 = mono_array_length (res2);
5694
5695                                         res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5696                                         if (mono_error_set_pending_exception (&error))
5697                                                 return NULL;
5698                                         mono_array_memcpy_refs (res3, 0, res, 0, len1);
5699                                         mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5700                                         res = res3;
5701
5702                                         ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5703                                         if (mono_error_set_pending_exception (&error))
5704                                                 return NULL;
5705                                         mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5706                                         mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5707                                         exceptions = ex3;
5708                                 }
5709                         }
5710                 }
5711         }
5712
5713         /* the ReflectionTypeLoadException must have all the types (Types property), 
5714          * NULL replacing types which throws an exception. The LoaderException must
5715          * contain all exceptions for NULL items.
5716          */
5717
5718         len = mono_array_length (res);
5719
5720         ex_count = 0;
5721         for (i = 0; i < len; i++) {
5722                 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5723                 MonoClass *klass;
5724
5725                 if (t) {
5726                         klass = mono_type_get_class (t->type);
5727                         if ((klass != NULL) && mono_class_has_failure (klass)) {
5728                                 /* keep the class in the list */
5729                                 list = g_list_append (list, klass);
5730                                 /* and replace Type with NULL */
5731                                 mono_array_setref (res, i, NULL);
5732                         }
5733                 } else {
5734                         ex_count ++;
5735                 }
5736         }
5737
5738         if (list || ex_count) {
5739                 GList *tmp = NULL;
5740                 MonoException *exc = NULL;
5741                 MonoArray *exl = NULL;
5742                 int j, length = g_list_length (list) + ex_count;
5743
5744                 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5745                 if (mono_error_set_pending_exception (&error)) {
5746                         g_list_free (list);
5747                         return NULL;
5748                 }
5749                 /* Types for which mono_class_get_checked () succeeded */
5750                 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5751                         MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5752                         mono_array_setref (exl, i, exc);
5753                 }
5754                 /* Types for which it don't */
5755                 for (j = 0; j < mono_array_length (exceptions); ++j) {
5756                         MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5757                         if (exc) {
5758                                 g_assert (i < length);
5759                                 mono_array_setref (exl, i, exc);
5760                                 i ++;
5761                         }
5762                 }
5763                 g_list_free (list);
5764                 list = NULL;
5765
5766                 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5767                 if (!is_ok (&error)) {
5768                         mono_error_set_pending_exception (&error);
5769                         return NULL;
5770                 }
5771                 mono_set_pending_exception (exc);
5772                 return NULL;
5773         }
5774                 
5775         return res;
5776 }
5777
5778 ICALL_EXPORT gboolean
5779 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5780 {
5781         MonoError error;
5782         MonoAssemblyName aname;
5783         MonoDomain *domain = mono_object_domain (name);
5784         char *val;
5785         gboolean is_version_defined;
5786         gboolean is_token_defined;
5787
5788         aname.public_key = NULL;
5789         val = mono_string_to_utf8_checked (assname, &error);
5790         if (mono_error_set_pending_exception (&error))
5791                 return FALSE;
5792
5793         if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5794                 g_free ((guint8*) aname.public_key);
5795                 g_free (val);
5796                 return FALSE;
5797         }
5798         
5799         fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5800         mono_error_set_pending_exception (&error);
5801
5802         mono_assembly_name_free (&aname);
5803         g_free ((guint8*) aname.public_key);
5804         g_free (val);
5805
5806         return TRUE;
5807 }
5808
5809 ICALL_EXPORT MonoReflectionType*
5810 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5811 {
5812         MonoError error;
5813         MonoReflectionType *ret;
5814         MonoDomain *domain = mono_object_domain (module); 
5815         MonoClass *klass;
5816
5817         g_assert (module->image);
5818
5819         if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5820                 /* These images do not have a global type */
5821                 return NULL;
5822
5823         klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5824         if (!mono_error_ok (&error)) {
5825                 mono_error_set_pending_exception (&error);
5826                 return NULL;
5827         }
5828
5829         ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5830         if (!mono_error_ok (&error)) {
5831                 mono_error_set_pending_exception (&error);
5832                 return NULL;
5833         }
5834
5835         return ret;
5836 }
5837
5838 ICALL_EXPORT void
5839 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5840 {
5841         /*if (module->image)
5842                 mono_image_close (module->image);*/
5843 }
5844
5845 ICALL_EXPORT MonoString*
5846 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5847 {
5848         MonoDomain *domain = mono_object_domain (module); 
5849
5850         g_assert (module->image);
5851         return mono_string_new (domain, module->image->guid);
5852 }
5853
5854 ICALL_EXPORT gpointer
5855 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5856 {
5857 #ifdef HOST_WIN32
5858         if (module->image && module->image->is_module_handle)
5859                 return module->image->raw_data;
5860 #endif
5861
5862         return (gpointer) (-1);
5863 }
5864
5865 ICALL_EXPORT void
5866 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5867 {
5868         if (image_is_dynamic (image)) {
5869                 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5870                 *pe_kind = dyn->pe_kind;
5871                 *machine = dyn->machine;
5872         }
5873         else {
5874                 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5875                 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5876         }
5877 }
5878
5879 ICALL_EXPORT gint32
5880 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5881 {
5882         return (image->md_version_major << 16) | (image->md_version_minor);
5883 }
5884
5885 ICALL_EXPORT MonoArray*
5886 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5887 {
5888         MonoError error;
5889         MonoArray *exceptions;
5890         int i;
5891
5892         if (!module->image) {
5893                 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
5894                 mono_error_set_pending_exception (&error);
5895                 return arr;
5896         } else {
5897                 MonoArray *res;
5898
5899                 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5900                 if (mono_error_set_pending_exception (&error))
5901                         return NULL;
5902
5903                 for (i = 0; i < mono_array_length (exceptions); ++i) {
5904                         MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5905                         if (ex) {
5906                                 mono_set_pending_exception (ex);
5907                                 return NULL;
5908                         }
5909                 }
5910                 return res;
5911         }
5912 }
5913
5914 static gboolean
5915 mono_memberref_is_method (MonoImage *image, guint32 token)
5916 {
5917         if (!image_is_dynamic (image)) {
5918                 guint32 cols [MONO_MEMBERREF_SIZE];
5919                 const char *sig;
5920                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5921                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5922                 mono_metadata_decode_blob_size (sig, &sig);
5923                 return (*sig != 0x6);
5924         } else {
5925                 MonoError error;
5926                 MonoClass *handle_class;
5927
5928                 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5929                         mono_error_cleanup (&error); /* just probing, ignore error */
5930                         return FALSE;
5931                 }
5932
5933                 return mono_defaults.methodhandle_class == handle_class;
5934         }
5935 }
5936
5937 static void
5938 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5939 {
5940         if (type_args)
5941                 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5942                                                                       mono_array_addr (type_args, MonoType*, 0));
5943         else
5944                 context->class_inst = NULL;
5945         if (method_args)
5946                 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5947                                                                        mono_array_addr (method_args, MonoType*, 0));
5948         else
5949                 context->method_inst = NULL;
5950 }
5951
5952 ICALL_EXPORT MonoType*
5953 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5954 {
5955         MonoClass *klass;
5956         int table = mono_metadata_token_table (token);
5957         int index = mono_metadata_token_index (token);
5958         MonoGenericContext context;
5959         MonoError error;
5960
5961         *resolve_error = ResolveTokenError_Other;
5962
5963         /* Validate token */
5964         if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) && 
5965                 (table != MONO_TABLE_TYPESPEC)) {
5966                 *resolve_error = ResolveTokenError_BadTable;
5967                 return NULL;
5968         }
5969
5970         if (image_is_dynamic (image)) {
5971                 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5972                         klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5973                         mono_error_cleanup (&error);
5974                         return klass ? &klass->byval_arg : NULL;
5975                 }
5976
5977                 init_generic_context_from_args (&context, type_args, method_args);
5978                 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5979                 mono_error_cleanup (&error);
5980                 return klass ? &klass->byval_arg : NULL;
5981         }
5982
5983         if ((index <= 0) || (index > image->tables [table].rows)) {
5984                 *resolve_error = ResolveTokenError_OutOfRange;
5985                 return NULL;
5986         }
5987
5988         init_generic_context_from_args (&context, type_args, method_args);
5989         klass = mono_class_get_checked (image, token, &error);
5990         if (klass)
5991                 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5992         if (!mono_error_ok (&error)) {
5993                 mono_error_set_pending_exception (&error);
5994                 return NULL;
5995         }
5996
5997         if (klass)
5998                 return &klass->byval_arg;
5999         else
6000                 return NULL;
6001 }
6002
6003 ICALL_EXPORT MonoMethod*
6004 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6005 {
6006         MonoError error;
6007         int table = mono_metadata_token_table (token);
6008         int index = mono_metadata_token_index (token);
6009         MonoGenericContext context;
6010         MonoMethod *method;
6011
6012         *resolve_error = ResolveTokenError_Other;
6013
6014         /* Validate token */
6015         if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) && 
6016                 (table != MONO_TABLE_MEMBERREF)) {
6017                 *resolve_error = ResolveTokenError_BadTable;
6018                 return NULL;
6019         }
6020
6021         if (image_is_dynamic (image)) {
6022                 if (table == MONO_TABLE_METHOD) {
6023                         method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6024                         mono_error_cleanup (&error);
6025                         return method;
6026                 }
6027
6028                 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
6029                         *resolve_error = ResolveTokenError_BadTable;
6030                         return NULL;
6031                 }
6032
6033                 init_generic_context_from_args (&context, type_args, method_args);
6034                 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6035                 mono_error_cleanup (&error);
6036                 return method;
6037         }
6038
6039         if ((index <= 0) || (index > image->tables [table].rows)) {
6040                 *resolve_error = ResolveTokenError_OutOfRange;
6041                 return NULL;
6042         }
6043         if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6044                 *resolve_error = ResolveTokenError_BadTable;
6045                 return NULL;
6046         }
6047
6048         init_generic_context_from_args (&context, type_args, method_args);
6049         method = mono_get_method_checked (image, token, NULL, &context, &error);
6050         mono_error_set_pending_exception (&error);
6051
6052         return method;
6053 }
6054
6055 ICALL_EXPORT MonoString*
6056 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6057 {
6058         MonoError error;
6059         int index = mono_metadata_token_index (token);
6060
6061         *resolve_error = ResolveTokenError_Other;
6062
6063         /* Validate token */
6064         if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6065                 *resolve_error = ResolveTokenError_BadTable;
6066                 return NULL;
6067         }
6068
6069         if (image_is_dynamic (image)) {
6070                 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6071                 mono_error_cleanup (&error);
6072                 return result;
6073         }
6074
6075         if ((index <= 0) || (index >= image->heap_us.size)) {
6076                 *resolve_error = ResolveTokenError_OutOfRange;
6077                 return NULL;
6078         }
6079
6080         /* FIXME: What to do if the index points into the middle of a string ? */
6081
6082         MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
6083         mono_error_set_pending_exception (&error);
6084         return result;
6085 }
6086
6087 ICALL_EXPORT MonoClassField*
6088 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6089 {
6090         MonoError error;
6091         MonoClass *klass;
6092         int table = mono_metadata_token_table (token);
6093         int index = mono_metadata_token_index (token);
6094         MonoGenericContext context;
6095         MonoClassField *field;
6096
6097         *resolve_error = ResolveTokenError_Other;
6098
6099         /* Validate token */
6100         if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6101                 *resolve_error = ResolveTokenError_BadTable;
6102                 return NULL;
6103         }
6104
6105         if (image_is_dynamic (image)) {
6106                 if (table == MONO_TABLE_FIELD) {
6107                         field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6108                         mono_error_cleanup (&error);
6109                         return field;
6110                 }
6111
6112                 if (mono_memberref_is_method (image, token)) {
6113                         *resolve_error = ResolveTokenError_BadTable;
6114                         return NULL;
6115                 }
6116
6117                 init_generic_context_from_args (&context, type_args, method_args);
6118                 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6119                 mono_error_cleanup (&error);
6120                 return field;
6121         }
6122
6123         if ((index <= 0) || (index > image->tables [table].rows)) {
6124                 *resolve_error = ResolveTokenError_OutOfRange;
6125                 return NULL;
6126         }
6127         if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6128                 *resolve_error = ResolveTokenError_BadTable;
6129                 return NULL;
6130         }
6131
6132         init_generic_context_from_args (&context, type_args, method_args);
6133         field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6134         mono_error_set_pending_exception (&error);
6135         
6136         return field;
6137 }
6138
6139
6140 ICALL_EXPORT MonoObject*
6141 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6142 {
6143         MonoError merror;
6144         MonoObject *ret;
6145         int table = mono_metadata_token_table (token);
6146
6147         *error = ResolveTokenError_Other;
6148
6149         switch (table) {
6150         case MONO_TABLE_TYPEDEF:
6151         case MONO_TABLE_TYPEREF:
6152         case MONO_TABLE_TYPESPEC: {
6153                 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6154                 if (t) {
6155                         ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6156                         mono_error_set_pending_exception (&merror);
6157
6158                         return ret;
6159                 }
6160                 else
6161                         return NULL;
6162         }
6163         case MONO_TABLE_METHOD:
6164         case MONO_TABLE_METHODSPEC: {
6165                 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6166                 if (m) {
6167                         ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6168                         mono_error_set_pending_exception (&merror);
6169
6170                         return ret;
6171                 } else
6172                         return NULL;
6173         }               
6174         case MONO_TABLE_FIELD: {
6175                 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6176                 if (f) {
6177                         ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6178                         mono_error_set_pending_exception (&merror);
6179                         return ret;
6180                 }
6181                 else
6182                         return NULL;
6183         }
6184         case MONO_TABLE_MEMBERREF:
6185                 if (mono_memberref_is_method (image, token)) {
6186                         MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6187                         if (m) {
6188                                 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6189                                 mono_error_set_pending_exception (&merror);
6190
6191                                 return ret;
6192                         } else
6193                                 return NULL;
6194                 }
6195                 else {
6196                         MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6197                         if (f) {
6198                                 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6199                                 mono_error_set_pending_exception (&merror);
6200                                 return ret;
6201                         }
6202                         else
6203                                 return NULL;
6204                 }
6205                 break;
6206
6207         default:
6208                 *error = ResolveTokenError_BadTable;
6209         }
6210
6211         return NULL;
6212 }
6213
6214 ICALL_EXPORT MonoArray*
6215 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6216 {
6217         MonoError error;
6218         int table = mono_metadata_token_table (token);
6219         int idx = mono_metadata_token_index (token);
6220         MonoTableInfo *tables = image->tables;
6221         guint32 sig, len;
6222         const char *ptr;
6223         MonoArray *res;
6224
6225         *resolve_error = ResolveTokenError_OutOfRange;
6226
6227         /* FIXME: Support other tables ? */
6228         if (table != MONO_TABLE_STANDALONESIG)
6229                 return NULL;
6230
6231         if (image_is_dynamic (image))
6232                 return NULL;
6233
6234         if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6235                 return NULL;
6236
6237         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6238
6239         ptr = mono_metadata_blob_heap (image, sig);
6240         len = mono_metadata_decode_blob_size (ptr, &ptr);
6241
6242         res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6243         if (mono_error_set_pending_exception (&error))
6244                 return NULL;
6245         memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6246         return res;
6247 }
6248
6249 ICALL_EXPORT MonoReflectionType*
6250 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6251 {
6252         MonoError error;
6253         MonoReflectionType *ret;
6254         MonoClass *klass;
6255         int isbyref = 0, rank;
6256         char *p;
6257         char *str = mono_string_to_utf8_checked (smodifiers, &error);
6258         if (mono_error_set_pending_exception (&error))
6259                 return NULL;
6260
6261         klass = mono_class_from_mono_type (tb->type.type);
6262         p = str;
6263         /* logic taken from mono_reflection_parse_type(): keep in sync */
6264         while (*p) {
6265                 switch (*p) {
6266                 case '&':
6267                         if (isbyref) { /* only one level allowed by the spec */
6268                                 g_free (str);
6269                                 return NULL;
6270                         }
6271                         isbyref = 1;
6272                         p++;
6273
6274                         g_free (str);
6275
6276                         ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6277                         mono_error_set_pending_exception (&error);
6278
6279                         return ret;
6280                 case '*':
6281                         klass = mono_ptr_class_get (&klass->byval_arg);
6282                         mono_class_init (klass);
6283                         p++;
6284                         break;
6285                 case '[':
6286                         rank = 1;
6287                         p++;
6288                         while (*p) {
6289                                 if (*p == ']')
6290                                         break;
6291                                 if (*p == ',')
6292                                         rank++;
6293                                 else if (*p != '*') { /* '*' means unknown lower bound */
6294                                         g_free (str);
6295                                         return NULL;
6296                                 }
6297                                 ++p;
6298                         }
6299                         if (*p != ']') {
6300                                 g_free (str);
6301                                 return NULL;
6302                         }
6303                         p++;
6304                         klass = mono_array_class_get (klass, rank);
6305                         mono_class_init (klass);
6306                         break;
6307                 default:
6308                         break;
6309                 }
6310         }
6311
6312         g_free (str);
6313
6314         ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6315         mono_error_set_pending_exception (&error);
6316
6317         return ret;
6318 }
6319
6320 ICALL_EXPORT MonoBoolean
6321 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6322 {
6323         MonoType *type;
6324         MonoBoolean res;
6325
6326         type = t->type;
6327         res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6328
6329         return res;
6330 }
6331
6332 static void
6333 check_for_invalid_type (MonoClass *klass, MonoError *error)
6334 {
6335         char *name;
6336         MonoString *str;
6337
6338         mono_error_init (error);
6339
6340         if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6341                 return;
6342
6343         name = mono_type_get_full_name (klass);
6344         str =  mono_string_new (mono_domain_get (), name);
6345         g_free (name);
6346         mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6347
6348 }
6349 ICALL_EXPORT MonoReflectionType *
6350 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6351 {
6352         MonoError error;
6353         MonoReflectionType *ret;
6354         MonoClass *klass, *aklass;
6355
6356         klass = mono_class_from_mono_type (type->type);
6357         check_for_invalid_type (klass, &error);
6358         mono_error_set_pending_exception (&error);
6359
6360         if (rank == 0) //single dimentional array
6361                 aklass = mono_array_class_get (klass, 1);
6362         else
6363                 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6364
6365         ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6366         mono_error_set_pending_exception (&error);
6367
6368         return ret;
6369 }
6370
6371 ICALL_EXPORT MonoReflectionType *
6372 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6373 {
6374         MonoError error;
6375         MonoReflectionType *ret;
6376         MonoClass *klass;
6377
6378         klass = mono_class_from_mono_type (type->type);
6379         mono_class_init_checked (klass, &error);
6380         if (mono_error_set_pending_exception (&error))
6381                 return NULL;
6382
6383         check_for_invalid_type (klass, &error);
6384         if (mono_error_set_pending_exception (&error))
6385                 return NULL;
6386
6387         ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6388         mono_error_set_pending_exception (&error);
6389
6390         return ret;
6391 }
6392
6393 ICALL_EXPORT MonoReflectionType *
6394 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6395 {
6396         MonoError error;
6397         MonoReflectionType *ret;
6398         MonoClass *klass, *pklass;
6399
6400         klass = mono_class_from_mono_type (type->type);
6401         mono_class_init_checked (klass, &error);
6402         if (mono_error_set_pending_exception (&error))
6403                 return NULL;
6404         check_for_invalid_type (klass, &error);
6405         if (mono_error_set_pending_exception (&error))
6406                 return NULL;
6407
6408         pklass = mono_ptr_class_get (type->type);
6409
6410         ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6411         mono_error_set_pending_exception (&error);
6412
6413         return ret;
6414 }
6415
6416 ICALL_EXPORT MonoObject *
6417 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6418                                                    MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6419 {
6420         MonoError error;
6421         MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6422         MonoObject *delegate;
6423         gpointer func;
6424         MonoMethod *method = info->method;
6425
6426         mono_class_init_checked (delegate_class, &error);
6427         if (mono_error_set_pending_exception (&error))
6428                 return NULL;
6429
6430         if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6431                 /* FIXME improve this exception message */
6432                 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6433                                                  __func__,
6434                                                  "delegate_class->parent == mono_defaults.multicastdelegate_class");
6435                 mono_error_set_pending_exception (&error);
6436                 return NULL;
6437         }
6438
6439         if (mono_security_core_clr_enabled ()) {
6440                 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6441                         if (throwOnBindFailure)
6442                                 mono_error_set_pending_exception (&error);
6443                         else
6444                                 mono_error_cleanup (&error);
6445                         return NULL;
6446                 }
6447         }
6448
6449         delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6450         if (mono_error_set_pending_exception (&error))
6451                 return NULL;
6452
6453         if (method_is_dynamic (method)) {
6454                 /* Creating a trampoline would leak memory */
6455                 func = mono_compile_method_checked (method, &error);
6456                 if (mono_error_set_pending_exception (&error))
6457                         return NULL;
6458         } else {
6459                 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6460                         method = mono_object_get_virtual_method (target, method);
6461                 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6462                 if (mono_error_set_pending_exception (&error))
6463                         return NULL;
6464                 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6465         }
6466
6467         mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6468         if (mono_error_set_pending_exception (&error))
6469                 return NULL;
6470         return delegate;
6471 }
6472
6473 ICALL_EXPORT MonoMulticastDelegate *
6474 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6475 {
6476         MonoError error;
6477         MonoMulticastDelegate *ret;
6478
6479         g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6480
6481         ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6482         if (mono_error_set_pending_exception (&error))
6483                 return NULL;
6484
6485         ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6486
6487         return ret;
6488 }
6489
6490 ICALL_EXPORT MonoReflectionMethod*
6491 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6492 {
6493         MonoReflectionMethod *ret = NULL;
6494         MonoError error;
6495         ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6496         mono_error_set_pending_exception (&error);
6497         return ret;
6498 }
6499
6500 /* System.Buffer */
6501
6502 static inline gint32 
6503 mono_array_get_byte_length (MonoArray *array)
6504 {
6505         MonoClass *klass;
6506         int length;
6507         int i;
6508
6509         klass = array->obj.vtable->klass;
6510
6511         if (array->bounds == NULL)
6512                 length = array->max_length;
6513         else {
6514                 length = 1;
6515                 for (i = 0; i < klass->rank; ++ i)
6516                         length *= array->bounds [i].length;
6517         }
6518
6519         switch (klass->element_class->byval_arg.type) {
6520         case MONO_TYPE_I1:
6521         case MONO_TYPE_U1:
6522         case MONO_TYPE_BOOLEAN:
6523                 return length;
6524         case MONO_TYPE_I2:
6525         case MONO_TYPE_U2:
6526         case MONO_TYPE_CHAR:
6527                 return length << 1;
6528         case MONO_TYPE_I4:
6529         case MONO_TYPE_U4:
6530         case MONO_TYPE_R4:
6531                 return length << 2;
6532         case MONO_TYPE_I:
6533         case MONO_TYPE_U:
6534                 return length * sizeof (gpointer);
6535         case MONO_TYPE_I8:
6536         case MONO_TYPE_U8:
6537         case MONO_TYPE_R8:
6538                 return length << 3;
6539         default:
6540                 return -1;
6541         }
6542 }
6543
6544 ICALL_EXPORT gint32 
6545 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array) 
6546 {
6547         return mono_array_get_byte_length (array);
6548 }
6549
6550 ICALL_EXPORT gint8 
6551 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx) 
6552 {
6553         return mono_array_get (array, gint8, idx);
6554 }
6555
6556 ICALL_EXPORT void 
6557 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value) 
6558 {
6559         mono_array_set (array, gint8, idx, value);
6560 }
6561
6562 ICALL_EXPORT MonoBoolean
6563 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count) 
6564 {
6565         guint8 *src_buf, *dest_buf;
6566
6567         if (count < 0) {
6568                 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6569                 return FALSE;
6570         }
6571
6572         g_assert (count >= 0);
6573
6574         /* This is called directly from the class libraries without going through the managed wrapper */
6575         MONO_CHECK_ARG_NULL (src, FALSE);
6576         MONO_CHECK_ARG_NULL (dest, FALSE);
6577
6578         /* watch out for integer overflow */
6579         if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6580                 return FALSE;
6581
6582         src_buf = (guint8 *)src->vector + src_offset;
6583         dest_buf = (guint8 *)dest->vector + dest_offset;
6584
6585         if (src != dest)
6586                 memcpy (dest_buf, src_buf, count);
6587         else
6588                 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6589
6590         return TRUE;
6591 }
6592
6593 #ifndef DISABLE_REMOTING
6594 ICALL_EXPORT MonoObject *
6595 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6596 {
6597         MonoError error;
6598         MonoDomain *domain = mono_object_domain (this_obj); 
6599         MonoObject *res;
6600         MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6601         MonoTransparentProxy *tp;
6602         MonoType *type;
6603         MonoClass *klass;
6604
6605         res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6606         if (mono_error_set_pending_exception (&error))
6607                 return NULL;
6608
6609         tp = (MonoTransparentProxy*) res;
6610         
6611         MONO_OBJECT_SETREF (tp, rp, rp);
6612         type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6613         klass = mono_class_from_mono_type (type);
6614
6615         // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6616         mono_class_setup_vtable (klass);
6617         if (mono_class_has_failure (klass)) {
6618                 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6619                 return NULL;
6620         }
6621
6622         tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6623         if (mono_error_set_pending_exception (&error))
6624                 return NULL;
6625         tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6626         if (mono_error_set_pending_exception (&error))
6627                 return NULL;
6628
6629         res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6630         if (mono_error_set_pending_exception (&error))
6631                 return NULL;
6632         return res;
6633 }
6634
6635 ICALL_EXPORT MonoReflectionType *
6636 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6637 {
6638         MonoError error;
6639         MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6640         mono_error_set_pending_exception (&error);
6641
6642         return ret;
6643 }
6644 #endif
6645
6646 /* System.Environment */
6647
6648 MonoString*
6649 ves_icall_System_Environment_get_UserName (void)
6650 {
6651         /* using glib is more portable */
6652         return mono_string_new (mono_domain_get (), g_get_user_name ());
6653 }
6654
6655
6656 ICALL_EXPORT MonoString *
6657 ves_icall_System_Environment_get_MachineName (void)
6658 {
6659 #if defined (HOST_WIN32)
6660         gunichar2 *buf;
6661         guint32 len;
6662         MonoString *result;
6663
6664         len = MAX_COMPUTERNAME_LENGTH + 1;
6665         buf = g_new (gunichar2, len);
6666
6667         result = NULL;
6668         if (GetComputerName (buf, (PDWORD) &len)) {
6669                 MonoError error;
6670                 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6671                 mono_error_set_pending_exception (&error);
6672         }
6673
6674         g_free (buf);
6675         return result;
6676 #elif !defined(DISABLE_SOCKETS)
6677         MonoString *result;
6678         char *buf;
6679         int n;
6680 #if defined _SC_HOST_NAME_MAX
6681         n = sysconf (_SC_HOST_NAME_MAX);
6682         if (n == -1)
6683 #endif
6684         n = 512;
6685         buf = g_malloc (n+1);
6686         
6687         if (gethostname (buf, n) == 0){
6688                 buf [n] = 0;
6689                 result = mono_string_new (mono_domain_get (), buf);
6690         } else
6691                 result = NULL;
6692         g_free (buf);
6693         
6694         return result;
6695 #else
6696         return mono_string_new (mono_domain_get (), "mono");
6697 #endif
6698 }
6699
6700 ICALL_EXPORT int
6701 ves_icall_System_Environment_get_Platform (void)
6702 {
6703 #if defined (TARGET_WIN32)
6704         /* Win32NT */
6705         return 2;
6706 #elif defined(__MACH__)
6707         /* OSX */
6708         //
6709         // Notice that the value is hidden from user code, and only exposed
6710         // to mscorlib.   This is due to Mono's Unix/MacOS code predating the
6711         // define and making assumptions based on Unix/128/4 values before there
6712         // was a MacOS define.    Lots of code would assume that not-Unix meant
6713         // Windows, but in this case, it would be OSX. 
6714         //
6715         return 6;
6716 #else
6717         /* Unix */
6718         return 4;
6719 #endif
6720 }
6721
6722 ICALL_EXPORT MonoString *
6723 ves_icall_System_Environment_get_NewLine (void)
6724 {
6725 #if defined (HOST_WIN32)
6726         return mono_string_new (mono_domain_get (), "\r\n");
6727 #else
6728         return mono_string_new (mono_domain_get (), "\n");
6729 #endif
6730 }
6731
6732 ICALL_EXPORT MonoBoolean
6733 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6734 {
6735 #if SIZEOF_VOID_P == 8
6736         return TRUE;
6737 #else
6738 #ifdef HOST_WIN32
6739         gboolean isWow64Process = FALSE;
6740         if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6741                 return (MonoBoolean)isWow64Process;
6742         }
6743 #elif defined(HAVE_SYS_UTSNAME_H)
6744         struct utsname name;
6745
6746         if (uname (&name) >= 0) {
6747                 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6748         }
6749 #endif
6750         return FALSE;
6751 #endif
6752 }
6753
6754 ICALL_EXPORT MonoString *
6755 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6756 {
6757         MonoError error;
6758         const gchar *value;
6759         gchar *utf8_name;
6760
6761         if (name == NULL)
6762                 return NULL;
6763
6764         utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6765         if (mono_error_set_pending_exception (&error))
6766                 return NULL;
6767         value = g_getenv (utf8_name);
6768
6769         g_free (utf8_name);
6770
6771         if (value == 0)
6772                 return NULL;
6773         
6774         return mono_string_new (mono_domain_get (), value);
6775 }
6776
6777 /*
6778  * There is no standard way to get at environ.
6779  */
6780 #ifndef _MSC_VER
6781 #ifndef __MINGW32_VERSION
6782 #if defined(__APPLE__)
6783 #if defined (TARGET_OSX)
6784 /* Apple defines this in crt_externs.h but doesn't provide that header for 
6785  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
6786  * in fact exist on all implementations (so far) 
6787  */
6788 gchar ***_NSGetEnviron(void);
6789 #define environ (*_NSGetEnviron())
6790 #else
6791 static char *mono_environ[1] = { NULL };
6792 #define environ mono_environ
6793 #endif /* defined (TARGET_OSX) */
6794 #else
6795 extern
6796 char **environ;
6797 #endif
6798 #endif
6799 #endif
6800
6801 ICALL_EXPORT MonoArray *
6802 ves_icall_System_Environment_GetCoomandLineArgs (void)
6803 {
6804         MonoError error;
6805         MonoArray *result = mono_runtime_get_main_args_checked (&error);
6806         mono_error_set_pending_exception (&error);
6807         return result;
6808 }
6809
6810 ICALL_EXPORT MonoArray *
6811 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6812 {
6813 #ifdef HOST_WIN32
6814         MonoError error;
6815         MonoArray *names;
6816         MonoDomain *domain;
6817         MonoString *str;
6818         WCHAR* env_strings;
6819         WCHAR* env_string;
6820         WCHAR* equal_str;
6821         int n = 0;
6822
6823         env_strings = GetEnvironmentStrings();
6824
6825         if (env_strings) {
6826                 env_string = env_strings;
6827                 while (*env_string != '\0') {
6828                 /* weird case that MS seems to skip */
6829                         if (*env_string != '=')
6830                                 n++;
6831                         while (*env_string != '\0')
6832                                 env_string++;
6833                         env_string++;
6834                 }
6835         }
6836
6837         domain = mono_domain_get ();
6838         names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6839         if (mono_error_set_pending_exception (&error))
6840                 return NULL;
6841
6842         if (env_strings) {
6843                 n = 0;
6844                 env_string = env_strings;
6845                 while (*env_string != '\0') {
6846                         /* weird case that MS seems to skip */
6847                         if (*env_string != '=') {
6848                                 equal_str = wcschr(env_string, '=');
6849                                 g_assert(equal_str);
6850                                 MonoError error;
6851                                 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6852                                 if (mono_error_set_pending_exception (&error))
6853                                         return NULL;
6854
6855                                 mono_array_setref (names, n, str);
6856                                 n++;
6857                         }
6858                         while (*env_string != '\0')
6859                                 env_string++;
6860                         env_string++;
6861                 }
6862
6863                 FreeEnvironmentStrings (env_strings);
6864         }
6865
6866         return names;
6867
6868 #else
6869         MonoError error;
6870         MonoArray *names;
6871         MonoDomain *domain;
6872         MonoString *str;
6873         gchar **e, **parts;
6874         int n;
6875
6876         n = 0;
6877         for (e = environ; *e != 0; ++ e)
6878                 ++ n;
6879
6880         domain = mono_domain_get ();
6881         names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6882         if (mono_error_set_pending_exception (&error))
6883                 return NULL;
6884
6885         n = 0;
6886         for (e = environ; *e != 0; ++ e) {
6887                 parts = g_strsplit (*e, "=", 2);
6888                 if (*parts != 0) {
6889                         str = mono_string_new (domain, *parts);
6890                         mono_array_setref (names, n, str);
6891                 }
6892
6893                 g_strfreev (parts);
6894
6895                 ++ n;
6896         }
6897
6898         return names;
6899 #endif
6900 }
6901
6902 ICALL_EXPORT void
6903 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6904 {
6905 #ifdef HOST_WIN32
6906         gunichar2 *utf16_name, *utf16_value;
6907 #else
6908         gchar *utf8_name, *utf8_value;
6909         MonoError error;
6910 #endif
6911
6912 #ifdef HOST_WIN32
6913         utf16_name = mono_string_to_utf16 (name);
6914         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6915                 SetEnvironmentVariable (utf16_name, NULL);
6916                 g_free (utf16_name);
6917                 return;
6918         }
6919
6920         utf16_value = mono_string_to_utf16 (value);
6921
6922         SetEnvironmentVariable (utf16_name, utf16_value);
6923
6924         g_free (utf16_name);
6925         g_free (utf16_value);
6926 #else
6927         utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6928         if (mono_error_set_pending_exception (&error))
6929                 return;
6930
6931         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6932                 g_unsetenv (utf8_name);
6933                 g_free (utf8_name);
6934                 return;
6935         }
6936
6937         utf8_value = mono_string_to_utf8_checked (value, &error);
6938         if (!mono_error_ok (&error)) {
6939                 g_free (utf8_name);
6940                 mono_error_set_pending_exception (&error);
6941                 return;
6942         }
6943         g_setenv (utf8_name, utf8_value, TRUE);
6944
6945         g_free (utf8_name);
6946         g_free (utf8_value);
6947 #endif
6948 }
6949
6950 ICALL_EXPORT void
6951 ves_icall_System_Environment_Exit (int result)
6952 {
6953         mono_environment_exitcode_set (result);
6954
6955 /* FIXME: There are some cleanup hangs that should be worked out, but
6956  * if the program is going to exit, everything will be cleaned up when
6957  * NaCl exits anyway.
6958  */
6959 #ifndef __native_client__
6960         if (!mono_runtime_try_shutdown ())
6961                 mono_thread_exit ();
6962
6963         /* Suspend all managed threads since the runtime is going away */
6964         mono_thread_suspend_all_other_threads ();
6965
6966         mono_runtime_quit ();
6967 #endif
6968
6969         /* we may need to do some cleanup here... */
6970         exit (result);
6971 }
6972
6973 ICALL_EXPORT MonoString*
6974 ves_icall_System_Environment_GetGacPath (void)
6975 {
6976         return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6977 }
6978
6979 ICALL_EXPORT MonoString*
6980 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6981 {
6982 #if defined (HOST_WIN32)
6983         #ifndef CSIDL_FLAG_CREATE
6984                 #define CSIDL_FLAG_CREATE       0x8000
6985         #endif
6986
6987         WCHAR path [MAX_PATH];
6988         /* Create directory if no existing */
6989         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6990                 int len = 0;
6991                 while (path [len])
6992                         ++ len;
6993                 MonoError error;
6994                 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6995                 mono_error_set_pending_exception (&error);
6996                 return res;
6997         }
6998 #else
6999         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7000 #endif
7001         return mono_string_new (mono_domain_get (), "");
7002 }
7003
7004 ICALL_EXPORT MonoArray *
7005 ves_icall_System_Environment_GetLogicalDrives (void)
7006 {
7007         MonoError error;
7008         gunichar2 buf [256], *ptr, *dname;
7009         gunichar2 *u16;
7010         guint initial_size = 127, size = 128;
7011         gint ndrives;
7012         MonoArray *result;
7013         MonoString *drivestr;
7014         MonoDomain *domain = mono_domain_get ();
7015         gint len;
7016
7017         buf [0] = '\0';
7018         ptr = buf;
7019
7020         while (size > initial_size) {
7021                 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7022                 if (size > initial_size) {
7023                         if (ptr != buf)
7024                                 g_free (ptr);
7025                         ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7026                         initial_size = size;
7027                         size++;
7028                 }
7029         }
7030
7031         /* Count strings */
7032         dname = ptr;
7033         ndrives = 0;
7034         do {
7035                 while (*dname++);
7036                 ndrives++;
7037         } while (*dname);
7038
7039         dname = ptr;
7040         result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7041         if (mono_error_set_pending_exception (&error))
7042                 goto leave;
7043
7044         ndrives = 0;
7045         do {
7046                 len = 0;
7047                 u16 = dname;
7048                 while (*u16) { u16++; len ++; }
7049                 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7050                 if (mono_error_set_pending_exception (&error))
7051                         goto leave;
7052
7053                 mono_array_setref (result, ndrives++, drivestr);
7054                 while (*dname++);
7055         } while (*dname);
7056
7057 leave:
7058         if (ptr != buf)
7059                 g_free (ptr);
7060
7061         return result;
7062 }
7063
7064 ICALL_EXPORT MonoString *
7065 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7066 {
7067         MonoError error;
7068         gunichar2 volume_name [MAX_PATH + 1];
7069         
7070         if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7071                 return NULL;
7072         MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
7073         mono_error_set_pending_exception (&error);
7074         return result;
7075 }
7076
7077 ICALL_EXPORT MonoString *
7078 ves_icall_System_Environment_InternalGetHome (void)
7079 {
7080         return mono_string_new (mono_domain_get (), g_get_home_dir ());
7081 }
7082
7083 static const char *encodings [] = {
7084         (char *) 1,
7085                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7086                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7087                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7088         (char *) 2,
7089                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7090                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7091                 "x_unicode_2_0_utf_7",
7092         (char *) 3,
7093                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7094                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7095         (char *) 4,
7096                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7097                 "iso_10646_ucs2",
7098         (char *) 5,
7099                 "unicodefffe", "utf_16be",
7100         (char *) 6,
7101                 "iso_8859_1",
7102         (char *) 0
7103 };
7104
7105 /*
7106  * Returns the internal codepage, if the value of "int_code_page" is
7107  * 1 at entry, and we can not compute a suitable code page number,
7108  * returns the code page as a string
7109  */
7110 ICALL_EXPORT MonoString*
7111 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page) 
7112 {
7113         const char *cset;
7114         const char *p;
7115         char *c;
7116         char *codepage = NULL;
7117         int code;
7118         int want_name = *int_code_page;
7119         int i;
7120         
7121         *int_code_page = -1;
7122
7123         g_get_charset (&cset);
7124         c = codepage = strdup (cset);
7125         for (c = codepage; *c; c++){
7126                 if (isascii (*c) && isalpha (*c))
7127                         *c = tolower (*c);
7128                 if (*c == '-')
7129                         *c = '_';
7130         }
7131         /* g_print ("charset: %s\n", cset); */
7132         
7133         /* handle some common aliases */
7134         p = encodings [0];
7135         code = 0;
7136         for (i = 0; p != 0; ){
7137                 if ((gsize) p < 7){
7138                         code = (gssize) p;
7139                         p = encodings [++i];
7140                         continue;
7141                 }
7142                 if (strcmp (p, codepage) == 0){
7143                         *int_code_page = code;
7144                         break;
7145                 }
7146                 p = encodings [++i];
7147         }
7148         
7149         if (strstr (codepage, "utf_8") != NULL)
7150                 *int_code_page |= 0x10000000;
7151         free (codepage);
7152         
7153         if (want_name && *int_code_page == -1)
7154                 return mono_string_new (mono_domain_get (), cset);
7155         else
7156                 return NULL;
7157 }
7158
7159 ICALL_EXPORT MonoBoolean
7160 ves_icall_System_Environment_get_HasShutdownStarted (void)
7161 {
7162         if (mono_runtime_is_shutting_down ())
7163                 return TRUE;
7164
7165         if (mono_domain_is_unloading (mono_domain_get ()))
7166                 return TRUE;
7167
7168         return FALSE;
7169 }
7170
7171 ICALL_EXPORT void
7172 ves_icall_System_Environment_BroadcastSettingChange (void)
7173 {
7174 #ifdef HOST_WIN32
7175         SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7176 #endif
7177 }
7178
7179 ICALL_EXPORT
7180 gint32
7181 ves_icall_System_Environment_get_TickCount (void)
7182 {
7183         /* this will overflow after ~24 days */
7184         return (gint32) (mono_msec_boottime () & 0xffffffff);
7185 }
7186
7187 ICALL_EXPORT gint32
7188 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7189 {
7190         return 9;
7191 }
7192
7193 #ifndef DISABLE_REMOTING
7194 ICALL_EXPORT MonoBoolean
7195 ves_icall_IsTransparentProxy (MonoObject *proxy)
7196 {
7197         if (!proxy)
7198                 return 0;
7199
7200         if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7201                 return 1;
7202
7203         return 0;
7204 }
7205
7206 ICALL_EXPORT MonoReflectionMethod *
7207 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7208         MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7209 {
7210         MonoReflectionMethod *ret = NULL;
7211         MonoError error;
7212
7213         MonoClass *klass;
7214         MonoMethod *method;
7215         MonoMethod **vtable;
7216         MonoMethod *res = NULL;
7217
7218         MONO_CHECK_ARG_NULL (rtype, NULL);
7219         MONO_CHECK_ARG_NULL (rmethod, NULL);
7220
7221         method = rmethod->method;
7222         klass = mono_class_from_mono_type (rtype->type);
7223         mono_class_init_checked (klass, &error);
7224         if (mono_error_set_pending_exception (&error))
7225                 return NULL;
7226
7227         if (MONO_CLASS_IS_INTERFACE (klass))
7228                 return NULL;
7229
7230         if (method->flags & METHOD_ATTRIBUTE_STATIC)
7231                 return NULL;
7232
7233         if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7234                 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7235                         return rmethod;
7236                 else
7237                         return NULL;
7238         }
7239
7240         mono_class_setup_vtable (klass);
7241         vtable = klass->vtable;
7242
7243         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7244                 gboolean variance_used = FALSE;
7245                 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7246                 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7247                 if (offs >= 0)
7248                         res = vtable [offs + method->slot];
7249         } else {
7250                 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7251                         return NULL;
7252
7253                 if (method->slot != -1)
7254                         res = vtable [method->slot];
7255         }
7256
7257         if (!res)
7258                 return NULL;
7259
7260         ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7261         mono_error_set_pending_exception (&error);
7262         return ret;
7263 }
7264
7265 ICALL_EXPORT void
7266 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7267 {
7268         MonoError error;
7269         MonoClass *klass;
7270         MonoVTable* vtable;
7271
7272         klass = mono_class_from_mono_type (type->type);
7273         vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7274         if (!is_ok (&error)) {
7275                 mono_error_set_pending_exception (&error);
7276                 return;
7277         }
7278
7279         mono_vtable_set_is_remote (vtable, enable);
7280 }
7281
7282 #else /* DISABLE_REMOTING */
7283
7284 ICALL_EXPORT void
7285 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7286 {
7287         g_assert_not_reached ();
7288 }
7289
7290 #endif
7291
7292 ICALL_EXPORT MonoObject *
7293 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7294 {
7295         MonoError error;
7296         MonoClass *klass;
7297         MonoDomain *domain;
7298         MonoObject *ret;
7299         
7300         domain = mono_object_domain (type);
7301         klass = mono_class_from_mono_type (type->type);
7302         mono_class_init_checked (klass, &error);
7303         if (mono_error_set_pending_exception (&error))
7304                 return NULL;
7305
7306         if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7307                 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7308                 return NULL;
7309         }
7310
7311         if (klass->rank >= 1) {
7312                 g_assert (klass->rank == 1);
7313                 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7314                 mono_error_set_pending_exception (&error);
7315                 return ret;
7316         } else {
7317                 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7318                 if (!is_ok (&error)) {
7319                         mono_error_set_pending_exception (&error);
7320                         return NULL;
7321                 }
7322                 /* Bypass remoting object creation check */
7323                 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7324                 mono_error_set_pending_exception (&error);
7325
7326                 return ret;
7327         }
7328 }
7329
7330 ICALL_EXPORT MonoString *
7331 ves_icall_System_IO_get_temp_path (void)
7332 {
7333         return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7334 }
7335
7336 #ifndef PLATFORM_NO_DRIVEINFO
7337 ICALL_EXPORT MonoBoolean
7338 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7339                                                 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7340                                                 gint32 *error)
7341 {
7342         gboolean result;
7343         ULARGE_INTEGER wapi_free_bytes_avail;
7344         ULARGE_INTEGER wapi_total_number_of_bytes;
7345         ULARGE_INTEGER wapi_total_number_of_free_bytes;
7346
7347         *error = ERROR_SUCCESS;
7348         result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7349                                      &wapi_total_number_of_free_bytes);
7350
7351         if (result) {
7352                 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7353                 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7354                 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7355         } else {
7356                 *free_bytes_avail = 0;
7357                 *total_number_of_bytes = 0;
7358                 *total_number_of_free_bytes = 0;
7359                 *error = GetLastError ();
7360         }
7361
7362         return result;
7363 }
7364
7365 ICALL_EXPORT guint32
7366 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7367 {
7368         return GetDriveType (mono_string_chars (root_path_name));
7369 }
7370 #endif
7371
7372 ICALL_EXPORT gpointer
7373 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7374 {
7375         MonoError error;
7376         gpointer result = mono_compile_method_checked (method, &error);
7377         mono_error_set_pending_exception (&error);
7378         return result;
7379 }
7380
7381 ICALL_EXPORT MonoString *
7382 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7383 {
7384         MonoString *mcpath;
7385         gchar *path;
7386
7387         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7388
7389 #if defined (HOST_WIN32)
7390         /* Avoid mixing '/' and '\\' */
7391         {
7392                 gint i;
7393                 for (i = strlen (path) - 1; i >= 0; i--)
7394                         if (path [i] == '/')
7395                                 path [i] = '\\';
7396         }
7397 #endif
7398         mcpath = mono_string_new (mono_domain_get (), path);
7399         g_free (path);
7400
7401         return mcpath;
7402 }
7403
7404 /* this is an icall */
7405 static MonoString *
7406 get_bundled_app_config (void)
7407 {
7408         MonoError error;
7409         const gchar *app_config;
7410         MonoDomain *domain;
7411         MonoString *file;
7412         gchar *config_file_name, *config_file_path;
7413         gsize len, config_file_path_length, config_ext_length;
7414         gchar *module;
7415
7416         domain = mono_domain_get ();
7417         file = domain->setup->configuration_file;
7418         if (!file || file->length == 0)
7419                 return NULL;
7420
7421         // Retrieve config file and remove the extension
7422         config_file_name = mono_string_to_utf8_checked (file, &error);
7423         if (mono_error_set_pending_exception (&error))
7424                 return NULL;
7425         config_file_path = mono_portability_find_file (config_file_name, TRUE);
7426         if (!config_file_path)
7427                 config_file_path = config_file_name;
7428
7429         config_file_path_length = strlen (config_file_path);
7430         config_ext_length = strlen (".config");
7431         if (config_file_path_length <= config_ext_length)
7432                 return NULL;
7433
7434         len = config_file_path_length - config_ext_length;
7435         module = (gchar *)g_malloc0 (len + 1);
7436         memcpy (module, config_file_path, len);
7437         // Get the config file from the module name
7438         app_config = mono_config_string_for_assembly_file (module);
7439         // Clean-up
7440         g_free (module);
7441         if (config_file_name != config_file_path)
7442                 g_free (config_file_name);
7443         g_free (config_file_path);
7444
7445         if (!app_config)
7446                 return NULL;
7447
7448         return mono_string_new (mono_domain_get (), app_config);
7449 }
7450
7451 static MonoString *
7452 get_bundled_machine_config (void)
7453 {
7454         const gchar *machine_config;
7455
7456         machine_config = mono_get_machine_config ();
7457
7458         if (!machine_config)
7459                 return NULL;
7460
7461         return mono_string_new (mono_domain_get (), machine_config);
7462 }
7463
7464 ICALL_EXPORT MonoString *
7465 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7466 {
7467         MonoString *ipath;
7468         gchar *path;
7469
7470         path = g_path_get_dirname (mono_get_config_dir ());
7471
7472 #if defined (HOST_WIN32)
7473         /* Avoid mixing '/' and '\\' */
7474         {
7475                 gint i;
7476                 for (i = strlen (path) - 1; i >= 0; i--)
7477                         if (path [i] == '/')
7478                                 path [i] = '\\';
7479         }
7480 #endif
7481         ipath = mono_string_new (mono_domain_get (), path);
7482         g_free (path);
7483
7484         return ipath;
7485 }
7486
7487 ICALL_EXPORT gboolean
7488 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7489 {
7490         MonoPEResourceDataEntry *entry;
7491         MonoImage *image;
7492
7493         if (!assembly || !result || !size)
7494                 return FALSE;
7495
7496         *result = NULL;
7497         *size = 0;
7498         image = assembly->assembly->image;
7499         entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7500         if (!entry)
7501                 return FALSE;
7502
7503         *result = mono_image_rva_map (image, entry->rde_data_offset);
7504         if (!(*result)) {
7505                 g_free (entry);
7506                 return FALSE;
7507         }
7508         *size = entry->rde_size;
7509         g_free (entry);
7510         return TRUE;
7511 }
7512
7513 ICALL_EXPORT MonoBoolean
7514 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7515 {
7516         return mono_is_debugger_attached ();
7517 }
7518
7519 ICALL_EXPORT MonoBoolean
7520 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7521 {
7522         if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7523                 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7524         else
7525                 return FALSE;
7526 }
7527
7528 ICALL_EXPORT void
7529 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7530 {
7531         if (mono_get_runtime_callbacks ()->debug_log)
7532                 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7533 }
7534
7535 ICALL_EXPORT void
7536 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7537 {
7538 #if defined (HOST_WIN32)
7539         OutputDebugString (mono_string_chars (message));
7540 #else
7541         g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7542 #endif
7543 }
7544
7545 /* Only used for value types */
7546 ICALL_EXPORT MonoObject *
7547 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7548 {
7549         MonoError error;
7550         MonoObject *result;
7551         MonoClass *klass;
7552         MonoDomain *domain;
7553         
7554         domain = mono_object_domain (type);
7555         klass = mono_class_from_mono_type (type->type);
7556         mono_class_init_checked (klass, &error);
7557         if (mono_error_set_pending_exception (&error))
7558                 return NULL;
7559
7560         if (mono_class_is_nullable (klass))
7561                 /* No arguments -> null */
7562                 return NULL;
7563
7564         result = mono_object_new_checked (domain, klass, &error);
7565         mono_error_set_pending_exception (&error);
7566         return result;
7567 }
7568
7569 ICALL_EXPORT MonoReflectionMethod *
7570 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7571 {
7572         MonoReflectionMethod *ret = NULL;
7573         MonoError error;
7574
7575         MonoClass *klass, *parent;
7576         MonoGenericContext *generic_inst = NULL;
7577         MonoMethod *method = m->method;
7578         MonoMethod *result = NULL;
7579         int slot;
7580
7581         if (method->klass == NULL)
7582                 return m;
7583
7584         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7585             MONO_CLASS_IS_INTERFACE (method->klass) ||
7586             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7587                 return m;
7588
7589         slot = mono_method_get_vtable_slot (method);
7590         if (slot == -1)
7591                 return m;
7592
7593         klass = method->klass;
7594         if (klass->generic_class) {
7595                 generic_inst = mono_class_get_context (klass);
7596                 klass = klass->generic_class->container_class;
7597         }
7598
7599         if (definition) {
7600                 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7601                 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7602                         /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7603                            or klass is the generic container class and generic_inst is the instantiation.
7604
7605                            when we go to the parent, if the parent is an open constructed type, we need to
7606                            replace the type parameters by the definitions from the generic_inst, and then take it
7607                            apart again into the klass and the generic_inst.
7608
7609                            For cases like this:
7610                            class C<T> : B<T, int> {
7611                                public override void Foo () { ... }
7612                            }
7613                            class B<U,V> : A<HashMap<U,V>> {
7614                                public override void Foo () { ... }
7615                            }
7616                            class A<X> {
7617                                public virtual void Foo () { ... }
7618                            }
7619
7620                            if at each iteration the parent isn't open, we can skip inflating it.  if at some
7621                            iteration the parent isn't generic (after possible inflation), we set generic_inst to
7622                            NULL;
7623                         */
7624                         MonoGenericContext *parent_inst = NULL;
7625                         if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7626                                 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7627                                 if (!mono_error_ok (&error)) {
7628                                         mono_error_set_pending_exception (&error);
7629                                         return NULL;
7630                                 }
7631                         }
7632                         if (parent->generic_class) {
7633                                 parent_inst = mono_class_get_context (parent);
7634                                 parent = parent->generic_class->container_class;
7635                         }
7636
7637                         mono_class_setup_vtable (parent);
7638                         if (parent->vtable_size <= slot)
7639                                 break;
7640                         klass = parent;
7641                         generic_inst = parent_inst;
7642                 }
7643         } else {
7644                 klass = klass->parent;
7645                 if (!klass)
7646                         return m;
7647                 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7648                         klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7649                         if (!mono_error_ok (&error)) {
7650                                 mono_error_set_pending_exception (&error);
7651                                 return NULL;
7652                         }
7653
7654                         generic_inst = NULL;
7655                 }
7656                 if (klass->generic_class) {
7657                         generic_inst = mono_class_get_context (klass);
7658                         klass = klass->generic_class->container_class;
7659                 }
7660
7661         }
7662
7663         if (generic_inst) {
7664                 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7665                 if (!mono_error_ok (&error)) {
7666                         mono_error_set_pending_exception (&error);
7667                         return NULL;
7668                 }
7669         }
7670
7671         if (klass == method->klass)
7672                 return m;
7673
7674         /*This is possible if definition == FALSE.
7675          * Do it here to be really sure we don't read invalid memory.
7676          */
7677         if (slot >= klass->vtable_size)
7678                 return m;
7679
7680         mono_class_setup_vtable (klass);
7681
7682         result = klass->vtable [slot];
7683         if (result == NULL) {
7684                 /* It is an abstract method */
7685                 gpointer iter = NULL;
7686                 while ((result = mono_class_get_methods (klass, &iter)))
7687                         if (result->slot == slot)
7688                                 break;
7689         }
7690
7691         if (result == NULL)
7692                 return m;
7693
7694         ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7695         mono_error_set_pending_exception (&error);
7696         return ret;
7697 }
7698
7699 ICALL_EXPORT MonoString*
7700 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7701 {
7702         MonoMethod *method = m->method;
7703
7704         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7705         return m->name;
7706 }
7707
7708 ICALL_EXPORT void
7709 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7710 {
7711         iter->sig = *(MonoMethodSignature**)argsp;
7712         
7713         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7714         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7715
7716         iter->next_arg = 0;
7717         /* FIXME: it's not documented what start is exactly... */
7718         if (start) {
7719                 iter->args = start;
7720         } else {
7721                 iter->args = argsp + sizeof (gpointer);
7722         }
7723         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7724
7725         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7726 }
7727
7728 ICALL_EXPORT MonoTypedRef
7729 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7730 {
7731         guint32 i, arg_size;
7732         gint32 align;
7733         MonoTypedRef res;
7734
7735         i = iter->sig->sentinelpos + iter->next_arg;
7736
7737         g_assert (i < iter->sig->param_count);
7738
7739         res.type = iter->sig->params [i];
7740         res.klass = mono_class_from_mono_type (res.type);
7741         arg_size = mono_type_stack_size (res.type, &align);
7742 #if defined(__arm__) || defined(__mips__)
7743         iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7744 #endif
7745         res.value = iter->args;
7746 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7747         /* Values are stored as 8 byte register sized objects, but 'value'
7748          * is dereferenced as a pointer in other routines.
7749          */
7750         res.value = (char*)res.value + 4;
7751 #endif
7752 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7753         if (arg_size <= sizeof (gpointer)) {
7754                 int dummy;
7755                 int padding = arg_size - mono_type_size (res.type, &dummy);
7756                 res.value = (guint8*)res.value + padding;
7757         }
7758 #endif
7759         iter->args = (char*)iter->args + arg_size;
7760         iter->next_arg++;
7761
7762         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7763
7764         return res;
7765 }
7766
7767 ICALL_EXPORT MonoTypedRef
7768 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7769 {
7770         guint32 i, arg_size;
7771         gint32 align;
7772         MonoTypedRef res;
7773
7774         i = iter->sig->sentinelpos + iter->next_arg;
7775
7776         g_assert (i < iter->sig->param_count);
7777
7778         while (i < iter->sig->param_count) {
7779                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7780                         continue;
7781                 res.type = iter->sig->params [i];
7782                 res.klass = mono_class_from_mono_type (res.type);
7783                 /* FIXME: endianess issue... */
7784                 arg_size = mono_type_stack_size (res.type, &align);
7785 #if defined(__arm__) || defined(__mips__)
7786                 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7787 #endif
7788                 res.value = iter->args;
7789                 iter->args = (char*)iter->args + arg_size;
7790                 iter->next_arg++;
7791                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7792                 return res;
7793         }
7794         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7795
7796         res.type = NULL;
7797         res.value = NULL;
7798         res.klass = NULL;
7799         return res;
7800 }
7801
7802 ICALL_EXPORT MonoType*
7803 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7804 {
7805         gint i;
7806         
7807         i = iter->sig->sentinelpos + iter->next_arg;
7808
7809         g_assert (i < iter->sig->param_count);
7810
7811         return iter->sig->params [i];
7812 }
7813
7814 ICALL_EXPORT MonoObject*
7815 mono_TypedReference_ToObject (MonoTypedRef* tref)
7816 {
7817         MonoError error;
7818         MonoObject *result = NULL;
7819         if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7820                 MonoObject** objp = (MonoObject **)tref->value;
7821                 return *objp;
7822         }
7823
7824         result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7825         mono_error_set_pending_exception (&error);
7826         return result;
7827 }
7828
7829 ICALL_EXPORT MonoTypedRef
7830 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7831 {
7832         MonoTypedRef res;
7833         MonoReflectionField *f;
7834         MonoClass *klass;
7835         MonoType *ftype = NULL;
7836         guint8 *p = NULL;
7837         int i;
7838
7839         memset (&res, 0, sizeof (res));
7840
7841         g_assert (fields);
7842         g_assert (mono_array_length (fields) > 0);
7843
7844         klass = target->vtable->klass;
7845
7846         for (i = 0; i < mono_array_length (fields); ++i) {
7847                 f = mono_array_get (fields, MonoReflectionField*, i);
7848                 if (f == NULL) {
7849                         mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7850                         return res;
7851                 }
7852                 if (f->field->parent != klass) {
7853                         mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7854                         return res;
7855                 }
7856                 if (i == 0)
7857                         p = (guint8*)target + f->field->offset;
7858                 else
7859                         p += f->field->offset - sizeof (MonoObject);
7860                 klass = mono_class_from_mono_type (f->field->type);
7861                 ftype = f->field->type;
7862         }
7863
7864         res.type = ftype;
7865         res.klass = mono_class_from_mono_type (ftype);
7866         res.value = p;
7867
7868         return res;
7869 }
7870
7871 static void
7872 prelink_method (MonoMethod *method, MonoError *error)
7873 {
7874         const char *exc_class, *exc_arg;
7875
7876         mono_error_init (error);
7877         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7878                 return;
7879         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7880         if (exc_class) {
7881                 mono_error_set_exception_instance (error,
7882                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7883                 return;
7884         }
7885         /* create the wrapper, too? */
7886 }
7887
7888 ICALL_EXPORT void
7889 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7890 {
7891         MonoError error;
7892
7893         prelink_method (method->method, &error);
7894         mono_error_set_pending_exception (&error);
7895 }
7896
7897 ICALL_EXPORT void
7898 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7899 {
7900         MonoError error;
7901         MonoClass *klass = mono_class_from_mono_type (type->type);
7902         MonoMethod* m;
7903         gpointer iter = NULL;
7904
7905         mono_class_init_checked (klass, &error);
7906         if (mono_error_set_pending_exception (&error))
7907                 return;
7908
7909         while ((m = mono_class_get_methods (klass, &iter))) {
7910                 prelink_method (m, &error);
7911                 if (mono_error_set_pending_exception (&error))
7912                         return;
7913         }
7914 }
7915
7916 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7917 ICALL_EXPORT void
7918 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7919                                             gint32 const **exponents,
7920                                             gunichar2 const **digitLowerTable,
7921                                             gunichar2 const **digitUpperTable,
7922                                             gint64 const **tenPowersList,
7923                                             gint32 const **decHexDigits)
7924 {
7925         *mantissas = Formatter_MantissaBitsTable;
7926         *exponents = Formatter_TensExponentTable;
7927         *digitLowerTable = Formatter_DigitLowerTable;
7928         *digitUpperTable = Formatter_DigitUpperTable;
7929         *tenPowersList = Formatter_TenPowersList;
7930         *decHexDigits = Formatter_DecHexDigits;
7931 }
7932
7933 /*
7934  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7935  * and avoid useless allocations.
7936  */
7937 static MonoArray*
7938 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7939 {
7940         MonoReflectionType *rt;
7941         MonoArray *res;
7942         int i, count = 0;
7943
7944         mono_error_init (error);
7945         for (i = 0; i < type->num_mods; ++i) {
7946                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7947                         count++;
7948         }
7949         if (!count)
7950                 return NULL;
7951         res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7952         return_val_if_nok (error, NULL);
7953         count = 0;
7954         for (i = 0; i < type->num_mods; ++i) {
7955                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7956                         MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7957                         return_val_if_nok (error, NULL);
7958
7959                         rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7960                         return_val_if_nok (error, NULL);
7961
7962                         mono_array_setref (res, count, rt);
7963                         count++;
7964                 }
7965         }
7966         return res;
7967 }
7968
7969 ICALL_EXPORT MonoArray*
7970 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7971 {
7972         MonoError error;
7973         MonoType *type = param->ClassImpl->type;
7974         MonoClass *member_class = mono_object_class (param->MemberImpl);
7975         MonoMethod *method = NULL;
7976         MonoImage *image;
7977         int pos;
7978         MonoMethodSignature *sig;
7979         MonoArray *res;
7980
7981         if (mono_class_is_reflection_method_or_constructor (member_class)) {
7982                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7983                 method = rmethod->method;
7984         } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7985                 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7986                 if (!(method = prop->property->get))
7987                         method = prop->property->set;
7988                 g_assert (method);      
7989         } else {
7990                 char *type_name = mono_type_get_full_name (member_class);
7991                 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7992                 MonoException *ex = mono_get_exception_not_supported  (msg);
7993                 g_free (type_name);
7994                 g_free (msg);
7995                 mono_set_pending_exception (ex);
7996                 return NULL;
7997         }
7998
7999         image = method->klass->image;
8000         pos = param->PositionImpl;
8001         sig = mono_method_signature (method);
8002         if (pos == -1)
8003                 type = sig->ret;
8004         else
8005                 type = sig->params [pos];
8006
8007         res = type_array_from_modifiers (image, type, optional, &error);
8008         mono_error_set_pending_exception (&error);
8009         return res;
8010 }
8011
8012 static MonoType*
8013 get_property_type (MonoProperty *prop)
8014 {
8015         MonoMethodSignature *sig;
8016         if (prop->get) {
8017                 sig = mono_method_signature (prop->get);
8018                 return sig->ret;
8019         } else if (prop->set) {
8020                 sig = mono_method_signature (prop->set);
8021                 return sig->params [sig->param_count - 1];
8022         }
8023         return NULL;
8024 }
8025
8026 ICALL_EXPORT MonoArray*
8027 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8028 {
8029         MonoError error;
8030         MonoType *type = get_property_type (property->property);
8031         MonoImage *image = property->klass->image;
8032         MonoArray *res;
8033
8034         if (!type)
8035                 return NULL;
8036         res = type_array_from_modifiers (image, type, optional, &error);
8037         mono_error_set_pending_exception (&error);
8038         return res;
8039 }
8040
8041 /*
8042  *Construct a MonoType suited to be used to decode a constant blob object.
8043  *
8044  * @type is the target type which will be constructed
8045  * @blob_type is the blob type, for example, that comes from the constant table
8046  * @real_type is the expected constructed type.
8047  */
8048 static void
8049 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8050 {
8051         type->type = blob_type;
8052         type->data.klass = NULL;
8053         if (blob_type == MONO_TYPE_CLASS)
8054                 type->data.klass = mono_defaults.object_class;
8055         else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8056                 /* For enums, we need to use the base type */
8057                 type->type = MONO_TYPE_VALUETYPE;
8058                 type->data.klass = mono_class_from_mono_type (real_type);
8059         } else
8060                 type->data.klass = mono_class_from_mono_type (real_type);
8061 }
8062
8063 ICALL_EXPORT MonoObject*
8064 property_info_get_default_value (MonoReflectionProperty *property)
8065 {
8066         MonoError error;
8067         MonoType blob_type;
8068         MonoProperty *prop = property->property;
8069         MonoType *type = get_property_type (prop);
8070         MonoDomain *domain = mono_object_domain (property); 
8071         MonoTypeEnum def_type;
8072         const char *def_value;
8073         MonoObject *o;
8074
8075         mono_class_init (prop->parent);
8076
8077         if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8078                 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8079                 return NULL;
8080         }
8081
8082         def_value = mono_class_get_property_default_value (prop, &def_type);
8083
8084         mono_type_from_blob_type (&blob_type, def_type, type);
8085         o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8086
8087         mono_error_set_pending_exception (&error);
8088         return o;
8089 }
8090
8091 ICALL_EXPORT MonoBoolean
8092 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8093 {
8094         MonoError error;
8095         MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8096         MonoCustomAttrInfo *cinfo;
8097         gboolean found;
8098
8099         mono_class_init_checked (attr_class, &error);
8100         if (mono_error_set_pending_exception (&error))
8101                 return FALSE;
8102
8103         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8104         if (!is_ok (&error)) {
8105                 mono_error_set_pending_exception (&error);
8106                 return FALSE;
8107         }
8108         if (!cinfo)
8109                 return FALSE;
8110         found = mono_custom_attrs_has_attr (cinfo, attr_class);
8111         if (!cinfo->cached)
8112                 mono_custom_attrs_free (cinfo);
8113         return found;
8114 }
8115
8116 ICALL_EXPORT MonoArray*
8117 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8118 {
8119         MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8120         MonoArray *res;
8121         MonoError error;
8122
8123         if (attr_class) {
8124                 mono_class_init_checked (attr_class, &error);
8125                 if (mono_error_set_pending_exception (&error))
8126                         return NULL;
8127         }
8128
8129         res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8130         if (!mono_error_ok (&error)) {
8131                 mono_error_set_pending_exception (&error);
8132                 return NULL;
8133         }
8134
8135         return res;
8136 }
8137
8138 ICALL_EXPORT MonoArray*
8139 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8140 {
8141         MonoError error;
8142         MonoArray *result;
8143         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8144         mono_error_set_pending_exception (&error);
8145         return result;
8146 }
8147
8148
8149 ICALL_EXPORT MonoString*
8150 ves_icall_Mono_Runtime_GetDisplayName (void)
8151 {
8152         char *info;
8153         MonoString *display_name;
8154
8155         info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8156         display_name = mono_string_new (mono_domain_get (), info);
8157         g_free (info);
8158         return display_name;
8159 }
8160
8161 ICALL_EXPORT MonoString*
8162 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8163 {
8164         MonoError error;
8165         MonoString *message;
8166         guint32 ret;
8167         gunichar2 buf[256];
8168         
8169         ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8170                              FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8171                              buf, 255, NULL);
8172         if (ret == 0) {
8173                 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8174         } else {
8175                 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8176                 if (mono_error_set_pending_exception (&error))
8177                         return NULL;
8178         }
8179         
8180         return message;
8181 }
8182
8183 ICALL_EXPORT gpointer
8184 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8185 {
8186         return GetCurrentProcess ();
8187 }
8188
8189 ICALL_EXPORT MonoBoolean
8190 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8191 {
8192         return GetExitCodeProcess (handle, (guint32*) exitcode);
8193 }
8194
8195 ICALL_EXPORT MonoBoolean
8196 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8197 {
8198 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8199         return CloseHandle (handle);
8200 #else
8201         return CloseProcess (handle);
8202 #endif
8203 }
8204
8205 ICALL_EXPORT MonoBoolean
8206 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8207 {
8208         return TerminateProcess (handle, exitcode);
8209 }
8210
8211 ICALL_EXPORT gint32
8212 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8213 {
8214         return WaitForInputIdle (handle, milliseconds);
8215 }
8216
8217 ICALL_EXPORT MonoBoolean
8218 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8219 {
8220         return GetProcessWorkingSetSize (handle, min, max);
8221 }
8222
8223 ICALL_EXPORT MonoBoolean
8224 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8225 {
8226         return SetProcessWorkingSetSize (handle, min, max);
8227 }
8228
8229 ICALL_EXPORT MonoBoolean
8230 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8231 {
8232         return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8233 }
8234
8235 ICALL_EXPORT gint32
8236 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8237 {
8238         return mono_process_current_pid ();
8239 }
8240
8241 ICALL_EXPORT gint32
8242 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8243 {
8244         return GetPriorityClass (handle);
8245 }
8246
8247 ICALL_EXPORT MonoBoolean
8248 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8249 {
8250         return SetPriorityClass (handle, priorityClass);
8251 }
8252
8253 #ifndef DISABLE_ICALL_TABLES
8254
8255 #define ICALL_TYPE(id,name,first)
8256 #define ICALL(id,name,func) Icall_ ## id,
8257
8258 enum {
8259 #include "metadata/icall-def.h"
8260         Icall_last
8261 };
8262
8263 #undef ICALL_TYPE
8264 #undef ICALL
8265 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8266 #define ICALL(id,name,func)
8267 enum {
8268 #include "metadata/icall-def.h"
8269         Icall_type_num
8270 };
8271
8272 #undef ICALL_TYPE
8273 #undef ICALL
8274 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8275 #define ICALL(id,name,func)
8276 typedef struct {
8277         guint16 first_icall;
8278 } IcallTypeDesc;
8279
8280 static const IcallTypeDesc
8281 icall_type_descs [] = {
8282 #include "metadata/icall-def.h"
8283         {Icall_last}
8284 };
8285
8286 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8287
8288 #undef ICALL_TYPE
8289 #define ICALL_TYPE(id,name,first)
8290 #undef ICALL
8291
8292 #ifdef HAVE_ARRAY_ELEM_INIT
8293 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8294 #define MSGSTRFIELD1(line) str##line
8295
8296 static const struct msgstrtn_t {
8297 #define ICALL(id,name,func)
8298 #undef ICALL_TYPE
8299 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8300 #include "metadata/icall-def.h"
8301 #undef ICALL_TYPE
8302 } icall_type_names_str = {
8303 #define ICALL_TYPE(id,name,first) (name),
8304 #include "metadata/icall-def.h"
8305 #undef ICALL_TYPE
8306 };
8307 static const guint16 icall_type_names_idx [] = {
8308 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8309 #include "metadata/icall-def.h"
8310 #undef ICALL_TYPE
8311 };
8312 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8313
8314 static const struct msgstr_t {
8315 #undef ICALL
8316 #define ICALL_TYPE(id,name,first)
8317 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8318 #include "metadata/icall-def.h"
8319 #undef ICALL
8320 } icall_names_str = {
8321 #define ICALL(id,name,func) (name),
8322 #include "metadata/icall-def.h"
8323 #undef ICALL
8324 };
8325 static const guint16 icall_names_idx [] = {
8326 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8327 #include "metadata/icall-def.h"
8328 #undef ICALL
8329 };
8330 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8331
8332 #else
8333
8334 #undef ICALL_TYPE
8335 #undef ICALL
8336 #define ICALL_TYPE(id,name,first) name,
8337 #define ICALL(id,name,func)
8338 static const char* const
8339 icall_type_names [] = {
8340 #include "metadata/icall-def.h"
8341         NULL
8342 };
8343
8344 #define icall_type_name_get(id) (icall_type_names [(id)])
8345
8346 #undef ICALL_TYPE
8347 #undef ICALL
8348 #define ICALL_TYPE(id,name,first)
8349 #define ICALL(id,name,func) name,
8350 static const char* const
8351 icall_names [] = {
8352 #include "metadata/icall-def.h"
8353         NULL
8354 };
8355 #define icall_name_get(id) icall_names [(id)]
8356
8357 #endif /* !HAVE_ARRAY_ELEM_INIT */
8358
8359 #undef ICALL_TYPE
8360 #undef ICALL
8361 #define ICALL_TYPE(id,name,first)
8362 #define ICALL(id,name,func) func,
8363 static const gconstpointer
8364 icall_functions [] = {
8365 #include "metadata/icall-def.h"
8366         NULL
8367 };
8368
8369 #ifdef ENABLE_ICALL_SYMBOL_MAP
8370 #undef ICALL_TYPE
8371 #undef ICALL
8372 #define ICALL_TYPE(id,name,first)
8373 #define ICALL(id,name,func) #func,
8374 static const gconstpointer
8375 icall_symbols [] = {
8376 #include "metadata/icall-def.h"
8377         NULL
8378 };
8379 #endif
8380
8381 #endif /* DISABLE_ICALL_TABLES */
8382
8383 static mono_mutex_t icall_mutex;
8384 static GHashTable *icall_hash = NULL;
8385 static GHashTable *jit_icall_hash_name = NULL;
8386 static GHashTable *jit_icall_hash_addr = NULL;
8387
8388 void
8389 mono_icall_init (void)
8390 {
8391 #ifndef DISABLE_ICALL_TABLES
8392         int i = 0;
8393
8394         /* check that tables are sorted: disable in release */
8395         if (TRUE) {
8396                 int j;
8397                 const char *prev_class = NULL;
8398                 const char *prev_method;
8399                 
8400                 for (i = 0; i < Icall_type_num; ++i) {
8401                         const IcallTypeDesc *desc;
8402                         int num_icalls;
8403                         prev_method = NULL;
8404                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8405                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8406                         prev_class = icall_type_name_get (i);
8407                         desc = &icall_type_descs [i];
8408                         num_icalls = icall_desc_num_icalls (desc);
8409                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8410                         for (j = 0; j < num_icalls; ++j) {
8411                                 const char *methodn = icall_name_get (desc->first_icall + j);
8412                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
8413                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
8414                                 prev_method = methodn;
8415                         }
8416                 }
8417         }
8418 #endif
8419
8420         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8421         mono_os_mutex_init (&icall_mutex);
8422 }
8423
8424 static void
8425 mono_icall_lock (void)
8426 {
8427         mono_locks_os_acquire (&icall_mutex, IcallLock);
8428 }
8429
8430 static void
8431 mono_icall_unlock (void)
8432 {
8433         mono_locks_os_release (&icall_mutex, IcallLock);
8434 }
8435
8436 void
8437 mono_icall_cleanup (void)
8438 {
8439         g_hash_table_destroy (icall_hash);
8440         g_hash_table_destroy (jit_icall_hash_name);
8441         g_hash_table_destroy (jit_icall_hash_addr);
8442         mono_os_mutex_destroy (&icall_mutex);
8443 }
8444
8445 /**
8446  * mono_add_internal_call:
8447  * @name: method specification to surface to the managed world
8448  * @method: pointer to a C method to invoke when the method is called
8449  *
8450  * This method surfaces the C function pointed by @method as a method
8451  * that has been surfaced in managed code with the method specified in
8452  * @name as an internal call.
8453  *
8454  * Internal calls are surfaced to all app domains loaded and they are
8455  * accessibly by a type with the specified name.
8456  *
8457  * You must provide a fully qualified type name, that is namespaces
8458  * and type name, followed by a colon and the method name, with an
8459  * optional signature to bind.
8460  *
8461  * For example, the following are all valid declarations:
8462  *
8463  * "MyApp.Services.ScriptService:Accelerate"
8464  * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8465  *
8466  * You use method parameters in cases where there might be more than
8467  * one surface method to managed code.  That way you can register different
8468  * internal calls for different method overloads.
8469  *
8470  * The internal calls are invoked with no marshalling.   This means that .NET
8471  * types like System.String are exposed as `MonoString *` parameters.   This is
8472  * different than the way that strings are surfaced in P/Invoke.
8473  *
8474  * For more information on how the parameters are marshalled, see the
8475  * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8476  * page.
8477  *
8478  * See the <a  href="mono-api-methods.html#method-desc">Method Description</a>
8479  * reference for more information on the format of method descriptions.
8480  */
8481 void
8482 mono_add_internal_call (const char *name, gconstpointer method)
8483 {
8484         mono_icall_lock ();
8485
8486         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8487
8488         mono_icall_unlock ();
8489 }
8490
8491 #ifndef DISABLE_ICALL_TABLES
8492
8493 #ifdef HAVE_ARRAY_ELEM_INIT
8494 static int
8495 compare_method_imap (const void *key, const void *elem)
8496 {
8497         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8498         return strcmp (key, method_name);
8499 }
8500
8501 static gpointer
8502 find_method_icall (const IcallTypeDesc *imap, const char *name)
8503 {
8504         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);
8505         if (!nameslot)
8506                 return NULL;
8507         return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8508 }
8509
8510 static int
8511 compare_class_imap (const void *key, const void *elem)
8512 {
8513         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8514         return strcmp (key, class_name);
8515 }
8516
8517 static const IcallTypeDesc*
8518 find_class_icalls (const char *name)
8519 {
8520         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);
8521         if (!nameslot)
8522                 return NULL;
8523         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8524 }
8525
8526 #else /* HAVE_ARRAY_ELEM_INIT */
8527
8528 static int
8529 compare_method_imap (const void *key, const void *elem)
8530 {
8531         const char** method_name = (const char**)elem;
8532         return strcmp (key, *method_name);
8533 }
8534
8535 static gpointer
8536 find_method_icall (const IcallTypeDesc *imap, const char *name)
8537 {
8538         const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8539         if (!nameslot)
8540                 return NULL;
8541         return (gpointer)icall_functions [(nameslot - icall_names)];
8542 }
8543
8544 static int
8545 compare_class_imap (const void *key, const void *elem)
8546 {
8547         const char** class_name = (const char**)elem;
8548         return strcmp (key, *class_name);
8549 }
8550
8551 static const IcallTypeDesc*
8552 find_class_icalls (const char *name)
8553 {
8554         const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8555         if (!nameslot)
8556                 return NULL;
8557         return &icall_type_descs [nameslot - icall_type_names];
8558 }
8559
8560 #endif /* HAVE_ARRAY_ELEM_INIT */
8561
8562 #endif /* DISABLE_ICALL_TABLES */
8563
8564 /* 
8565  * we should probably export this as an helper (handle nested types).
8566  * Returns the number of chars written in buf.
8567  */
8568 static int
8569 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8570 {
8571         int nspacelen, cnamelen;
8572         nspacelen = strlen (klass->name_space);
8573         cnamelen = strlen (klass->name);
8574         if (nspacelen + cnamelen + 2 > bufsize)
8575                 return 0;
8576         if (nspacelen) {
8577                 memcpy (buf, klass->name_space, nspacelen);
8578                 buf [nspacelen ++] = '.';
8579         }
8580         memcpy (buf + nspacelen, klass->name, cnamelen);
8581         buf [nspacelen + cnamelen] = 0;
8582         return nspacelen + cnamelen;
8583 }
8584
8585 #ifdef DISABLE_ICALL_TABLES
8586 static void
8587 no_icall_table (void)
8588 {
8589         g_assert_not_reached ();
8590 }
8591 #endif
8592
8593 gpointer
8594 mono_lookup_internal_call (MonoMethod *method)
8595 {
8596         char *sigstart;
8597         char *tmpsig;
8598         char mname [2048];
8599         int typelen = 0, mlen, siglen;
8600         gpointer res;
8601 #ifndef DISABLE_ICALL_TABLES
8602         const IcallTypeDesc *imap = NULL;
8603 #endif
8604
8605         g_assert (method != NULL);
8606
8607         if (method->is_inflated)
8608                 method = ((MonoMethodInflated *) method)->declaring;
8609
8610         if (method->klass->nested_in) {
8611                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8612                 if (!pos)
8613                         return NULL;
8614
8615                 mname [pos++] = '/';
8616                 mname [pos] = 0;
8617
8618                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8619                 if (!typelen)
8620                         return NULL;
8621
8622                 typelen += pos;
8623         } else {
8624                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8625                 if (!typelen)
8626                         return NULL;
8627         }
8628
8629 #ifndef DISABLE_ICALL_TABLES
8630         imap = find_class_icalls (mname);
8631 #endif
8632
8633         mname [typelen] = ':';
8634         mname [typelen + 1] = ':';
8635
8636         mlen = strlen (method->name);
8637         memcpy (mname + typelen + 2, method->name, mlen);
8638         sigstart = mname + typelen + 2 + mlen;
8639         *sigstart = 0;
8640
8641         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8642         siglen = strlen (tmpsig);
8643         if (typelen + mlen + siglen + 6 > sizeof (mname))
8644                 return NULL;
8645         sigstart [0] = '(';
8646         memcpy (sigstart + 1, tmpsig, siglen);
8647         sigstart [siglen + 1] = ')';
8648         sigstart [siglen + 2] = 0;
8649         g_free (tmpsig);
8650         
8651         mono_icall_lock ();
8652
8653         res = g_hash_table_lookup (icall_hash, mname);
8654         if (res) {
8655                 mono_icall_unlock ();;
8656                 return res;
8657         }
8658         /* try without signature */
8659         *sigstart = 0;
8660         res = g_hash_table_lookup (icall_hash, mname);
8661         if (res) {
8662                 mono_icall_unlock ();
8663                 return res;
8664         }
8665
8666 #ifdef DISABLE_ICALL_TABLES
8667         mono_icall_unlock ();
8668         /* Fail only when the result is actually used */
8669         /* mono_marshal_get_native_wrapper () depends on this */
8670         if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8671                 return ves_icall_System_String_ctor_RedirectToCreateString;
8672         else
8673                 return no_icall_table;
8674 #else
8675         /* it wasn't found in the static call tables */
8676         if (!imap) {
8677                 mono_icall_unlock ();
8678                 return NULL;
8679         }
8680         res = find_method_icall (imap, sigstart - mlen);
8681         if (res) {
8682                 mono_icall_unlock ();
8683                 return res;
8684         }
8685         /* try _with_ signature */
8686         *sigstart = '(';
8687         res = find_method_icall (imap, sigstart - mlen);
8688         if (res) {
8689                 mono_icall_unlock ();
8690                 return res;
8691         }
8692
8693         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8694         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8695         g_print ("The out of sync library is: %s\n", method->klass->image->name);
8696         g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8697         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");
8698         g_print ("If you see other errors or faults after this message they are probably related\n");
8699         g_print ("and you need to fix your mono install first.\n");
8700
8701         mono_icall_unlock ();
8702
8703         return NULL;
8704 #endif
8705 }
8706
8707 #ifdef ENABLE_ICALL_SYMBOL_MAP
8708 static int
8709 func_cmp (gconstpointer key, gconstpointer p)
8710 {
8711         return (gsize)key - (gsize)*(gsize*)p;
8712 }
8713 #endif
8714
8715 /*
8716  * mono_lookup_icall_symbol:
8717  *
8718  *   Given the icall METHOD, returns its C symbol.
8719  */
8720 const char*
8721 mono_lookup_icall_symbol (MonoMethod *m)
8722 {
8723 #ifdef DISABLE_ICALL_TABLES
8724         g_assert_not_reached ();
8725         return NULL;
8726 #else
8727 #ifdef ENABLE_ICALL_SYMBOL_MAP
8728         gpointer func;
8729         int i;
8730         gpointer slot;
8731         static gconstpointer *functions_sorted;
8732         static const char**symbols_sorted;
8733         static gboolean inited;
8734
8735         if (!inited) {
8736                 gboolean changed;
8737
8738                 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8739                 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8740                 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8741                 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8742                 /* Bubble sort the two arrays */
8743                 changed = TRUE;
8744                 while (changed) {
8745                         changed = FALSE;
8746                         for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8747                                 if (functions_sorted [i] > functions_sorted [i + 1]) {
8748                                         gconstpointer tmp;
8749
8750                                         tmp = functions_sorted [i];
8751                                         functions_sorted [i] = functions_sorted [i + 1];
8752                                         functions_sorted [i + 1] = tmp;
8753                                         tmp = symbols_sorted [i];
8754                                         symbols_sorted [i] = symbols_sorted [i + 1];
8755                                         symbols_sorted [i + 1] = tmp;
8756                                         changed = TRUE;
8757                                 }
8758                         }
8759                 }
8760         }
8761
8762         func = mono_lookup_internal_call (m);
8763         if (!func)
8764                 return NULL;
8765         slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8766         if (!slot)
8767                 return NULL;
8768         g_assert (slot);
8769         return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8770 #else
8771         fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8772         g_assert_not_reached ();
8773         return 0;
8774 #endif
8775 #endif
8776 }
8777
8778 static MonoType*
8779 type_from_typename (char *type_name)
8780 {
8781         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
8782
8783         if (!strcmp (type_name, "int"))
8784                 klass = mono_defaults.int_class;
8785         else if (!strcmp (type_name, "ptr"))
8786                 klass = mono_defaults.int_class;
8787         else if (!strcmp (type_name, "void"))
8788                 klass = mono_defaults.void_class;
8789         else if (!strcmp (type_name, "int32"))
8790                 klass = mono_defaults.int32_class;
8791         else if (!strcmp (type_name, "uint32"))
8792                 klass = mono_defaults.uint32_class;
8793         else if (!strcmp (type_name, "int8"))
8794                 klass = mono_defaults.sbyte_class;
8795         else if (!strcmp (type_name, "uint8"))
8796                 klass = mono_defaults.byte_class;
8797         else if (!strcmp (type_name, "int16"))
8798                 klass = mono_defaults.int16_class;
8799         else if (!strcmp (type_name, "uint16"))
8800                 klass = mono_defaults.uint16_class;
8801         else if (!strcmp (type_name, "long"))
8802                 klass = mono_defaults.int64_class;
8803         else if (!strcmp (type_name, "ulong"))
8804                 klass = mono_defaults.uint64_class;
8805         else if (!strcmp (type_name, "float"))
8806                 klass = mono_defaults.single_class;
8807         else if (!strcmp (type_name, "double"))
8808                 klass = mono_defaults.double_class;
8809         else if (!strcmp (type_name, "object"))
8810                 klass = mono_defaults.object_class;
8811         else if (!strcmp (type_name, "obj"))
8812                 klass = mono_defaults.object_class;
8813         else if (!strcmp (type_name, "string"))
8814                 klass = mono_defaults.string_class;
8815         else if (!strcmp (type_name, "bool"))
8816                 klass = mono_defaults.boolean_class;
8817         else if (!strcmp (type_name, "boolean"))
8818                 klass = mono_defaults.boolean_class;
8819         else {
8820                 g_error ("%s", type_name);
8821                 g_assert_not_reached ();
8822         }
8823         return &klass->byval_arg;
8824 }
8825
8826 /**
8827  * LOCKING: Take the corlib image lock.
8828  */
8829 MonoMethodSignature*
8830 mono_create_icall_signature (const char *sigstr)
8831 {
8832         gchar **parts;
8833         int i, len;
8834         gchar **tmp;
8835         MonoMethodSignature *res, *res2;
8836         MonoImage *corlib = mono_defaults.corlib;
8837
8838         mono_image_lock (corlib);
8839         res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8840         mono_image_unlock (corlib);
8841
8842         if (res)
8843                 return res;
8844
8845         parts = g_strsplit (sigstr, " ", 256);
8846
8847         tmp = parts;
8848         len = 0;
8849         while (*tmp) {
8850                 len ++;
8851                 tmp ++;
8852         }
8853
8854         res = mono_metadata_signature_alloc (corlib, len - 1);
8855         res->pinvoke = 1;
8856
8857 #ifdef HOST_WIN32
8858         /* 
8859          * Under windows, the default pinvoke calling convention is STDCALL but
8860          * we need CDECL.
8861          */
8862         res->call_convention = MONO_CALL_C;
8863 #endif
8864
8865         res->ret = type_from_typename (parts [0]);
8866         for (i = 1; i < len; ++i) {
8867                 res->params [i - 1] = type_from_typename (parts [i]);
8868         }
8869
8870         g_strfreev (parts);
8871
8872         mono_image_lock (corlib);
8873         res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8874         if (res2)
8875                 res = res2; /*Value is allocated in the image pool*/
8876         else
8877                 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8878         mono_image_unlock (corlib);
8879
8880         return res;
8881 }
8882
8883 MonoJitICallInfo *
8884 mono_find_jit_icall_by_name (const char *name)
8885 {
8886         MonoJitICallInfo *info;
8887         g_assert (jit_icall_hash_name);
8888
8889         mono_icall_lock ();
8890         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8891         mono_icall_unlock ();
8892         return info;
8893 }
8894
8895 MonoJitICallInfo *
8896 mono_find_jit_icall_by_addr (gconstpointer addr)
8897 {
8898         MonoJitICallInfo *info;
8899         g_assert (jit_icall_hash_addr);
8900
8901         mono_icall_lock ();
8902         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8903         mono_icall_unlock ();
8904
8905         return info;
8906 }
8907
8908 /*
8909  * mono_get_jit_icall_info:
8910  *
8911  *   Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8912  * caller should access it while holding the icall lock.
8913  */
8914 GHashTable*
8915 mono_get_jit_icall_info (void)
8916 {
8917         return jit_icall_hash_name;
8918 }
8919
8920 /*
8921  * mono_lookup_jit_icall_symbol:
8922  *
8923  *   Given the jit icall NAME, returns its C symbol if possible, or NULL.
8924  */
8925 const char*
8926 mono_lookup_jit_icall_symbol (const char *name)
8927 {
8928         MonoJitICallInfo *info;
8929         const char *res = NULL;
8930
8931         mono_icall_lock ();
8932         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8933         if (info)
8934                 res = info->c_symbol;
8935         mono_icall_unlock ();
8936         return res;
8937 }
8938
8939 void
8940 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8941 {
8942         mono_icall_lock ();
8943         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8944         mono_icall_unlock ();
8945 }
8946
8947 /*
8948  * 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
8949  * icalls without wrappers in some cases.
8950  */
8951 MonoJitICallInfo *
8952 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8953 {
8954         MonoJitICallInfo *info;
8955         
8956         g_assert (func);
8957         g_assert (name);
8958
8959         mono_icall_lock ();
8960
8961         if (!jit_icall_hash_name) {
8962                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8963                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8964         }
8965
8966         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8967                 g_warning ("jit icall already defined \"%s\"\n", name);
8968                 g_assert_not_reached ();
8969         }
8970
8971         info = g_new0 (MonoJitICallInfo, 1);
8972         
8973         info->name = name;
8974         info->func = func;
8975         info->sig = sig;
8976         info->c_symbol = c_symbol;
8977         info->no_raise = no_raise;
8978
8979         if (is_save) {
8980                 info->wrapper = func;
8981         } else {
8982                 info->wrapper = NULL;
8983         }
8984
8985         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8986         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8987
8988         mono_icall_unlock ();
8989         return info;
8990 }
8991
8992 MonoJitICallInfo *
8993 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8994 {
8995         return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);
8996 }
8997