[corlib] Move Assembly::GetName to be implemented 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 MonoAssemblyName *
5491 ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
5492 {
5493         return &mass->aname;
5494 }
5495
5496 ICALL_EXPORT void
5497 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5498 {
5499         MonoError error;
5500         char *filename;
5501         MonoImageOpenStatus status = MONO_IMAGE_OK;
5502         gboolean res;
5503         MonoImage *image;
5504         MonoAssemblyName name;
5505         char *dirname;
5506
5507         filename = mono_string_to_utf8_checked (fname, &error);
5508         if (mono_error_set_pending_exception (&error))
5509                 return;
5510
5511         dirname = g_path_get_dirname (filename);
5512         replace_shadow_path (mono_domain_get (), dirname, &filename);
5513         g_free (dirname);
5514
5515         image = mono_image_open (filename, &status);
5516
5517         if (!image){
5518                 MonoException *exc;
5519
5520                 g_free (filename);
5521                 if (status == MONO_IMAGE_IMAGE_INVALID)
5522                         exc = mono_get_exception_bad_image_format2 (NULL, fname);
5523                 else
5524                         exc = mono_get_exception_file_not_found2 (NULL, fname);
5525                 mono_set_pending_exception (exc);
5526                 return;
5527         }
5528
5529         res = mono_assembly_fill_assembly_name (image, &name);
5530         if (!res) {
5531                 mono_image_close (image);
5532                 g_free (filename);
5533                 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5534                 return;
5535         }
5536
5537         fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5538         mono_error_set_pending_exception (&error);
5539
5540         mono_image_close (image);
5541         g_free (filename);
5542 }
5543
5544 ICALL_EXPORT MonoBoolean
5545 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5546         char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5547 {
5548         MonoBoolean result = FALSE;
5549         MonoDeclSecurityEntry entry;
5550
5551         /* SecurityAction.RequestMinimum */
5552         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5553                 *minimum = entry.blob;
5554                 *minLength = entry.size;
5555                 result = TRUE;
5556         }
5557         /* SecurityAction.RequestOptional */
5558         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5559                 *optional = entry.blob;
5560                 *optLength = entry.size;
5561                 result = TRUE;
5562         }
5563         /* SecurityAction.RequestRefuse */
5564         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5565                 *refused = entry.blob;
5566                 *refLength = entry.size;
5567                 result = TRUE;
5568         }
5569
5570         return result;  
5571 }
5572
5573 static gboolean
5574 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5575 {
5576         guint32 attrs, visibility;
5577         do {
5578                 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5579                 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5580                 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5581                         return FALSE;
5582
5583         } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5584
5585         return TRUE;
5586 }
5587
5588 static MonoArray*
5589 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5590 {
5591         MonoReflectionType *rt;
5592         MonoArray *res;
5593         MonoClass *klass;
5594         MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5595         int i, count;
5596
5597         mono_error_init (error);
5598
5599         /* we start the count from 1 because we skip the special type <Module> */
5600         if (exportedOnly) {
5601                 count = 0;
5602                 for (i = 1; i < tdef->rows; ++i) {
5603                         if (mono_module_type_is_visible (tdef, image, i + 1))
5604                                 count++;
5605                 }
5606         } else {
5607                 count = tdef->rows - 1;
5608         }
5609         res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5610         return_val_if_nok (error, NULL);
5611         *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5612         return_val_if_nok (error, NULL);
5613         count = 0;
5614         for (i = 1; i < tdef->rows; ++i) {
5615                 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5616                         klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5617                         
5618                         if (klass) {
5619                                 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5620                                 return_val_if_nok (error, NULL);
5621
5622                                 mono_array_setref (res, count, rt);
5623                         } else {
5624                                 MonoException *ex = mono_error_convert_to_exception (error);
5625                                 mono_array_setref (*exceptions, count, ex);
5626                         }
5627                         count++;
5628                 }
5629         }
5630         
5631         return res;
5632 }
5633
5634 ICALL_EXPORT MonoArray*
5635 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5636 {
5637         MonoError error;
5638         MonoArray *res = NULL;
5639         MonoArray *exceptions = NULL;
5640         MonoImage *image = NULL;
5641         MonoTableInfo *table = NULL;
5642         MonoDomain *domain;
5643         GList *list = NULL;
5644         int i, len, ex_count;
5645
5646         domain = mono_object_domain (assembly);
5647
5648         g_assert (!assembly_is_dynamic (assembly->assembly));
5649         image = assembly->assembly->image;
5650         table = &image->tables [MONO_TABLE_FILE];
5651         res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5652         if (mono_error_set_pending_exception (&error))
5653                 return NULL;
5654
5655         /* Append data from all modules in the assembly */
5656         for (i = 0; i < table->rows; ++i) {
5657                 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5658                         MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5659                         if (loaded_image) {
5660                                 MonoArray *ex2;
5661                                 MonoArray *res2;
5662
5663                                 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5664                                 if (mono_error_set_pending_exception (&error))
5665                                         return NULL;
5666
5667
5668                                 /* Append the new types to the end of the array */
5669                                 if (mono_array_length (res2) > 0) {
5670                                         guint32 len1, len2;
5671                                         MonoArray *res3, *ex3;
5672
5673                                         len1 = mono_array_length (res);
5674                                         len2 = mono_array_length (res2);
5675
5676                                         res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5677                                         if (mono_error_set_pending_exception (&error))
5678                                                 return NULL;
5679                                         mono_array_memcpy_refs (res3, 0, res, 0, len1);
5680                                         mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5681                                         res = res3;
5682
5683                                         ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5684                                         if (mono_error_set_pending_exception (&error))
5685                                                 return NULL;
5686                                         mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5687                                         mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5688                                         exceptions = ex3;
5689                                 }
5690                         }
5691                 }
5692         }
5693
5694         /* the ReflectionTypeLoadException must have all the types (Types property), 
5695          * NULL replacing types which throws an exception. The LoaderException must
5696          * contain all exceptions for NULL items.
5697          */
5698
5699         len = mono_array_length (res);
5700
5701         ex_count = 0;
5702         for (i = 0; i < len; i++) {
5703                 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5704                 MonoClass *klass;
5705
5706                 if (t) {
5707                         klass = mono_type_get_class (t->type);
5708                         if ((klass != NULL) && mono_class_has_failure (klass)) {
5709                                 /* keep the class in the list */
5710                                 list = g_list_append (list, klass);
5711                                 /* and replace Type with NULL */
5712                                 mono_array_setref (res, i, NULL);
5713                         }
5714                 } else {
5715                         ex_count ++;
5716                 }
5717         }
5718
5719         if (list || ex_count) {
5720                 GList *tmp = NULL;
5721                 MonoException *exc = NULL;
5722                 MonoArray *exl = NULL;
5723                 int j, length = g_list_length (list) + ex_count;
5724
5725                 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5726                 if (mono_error_set_pending_exception (&error)) {
5727                         g_list_free (list);
5728                         return NULL;
5729                 }
5730                 /* Types for which mono_class_get_checked () succeeded */
5731                 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5732                         MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5733                         mono_array_setref (exl, i, exc);
5734                 }
5735                 /* Types for which it don't */
5736                 for (j = 0; j < mono_array_length (exceptions); ++j) {
5737                         MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5738                         if (exc) {
5739                                 g_assert (i < length);
5740                                 mono_array_setref (exl, i, exc);
5741                                 i ++;
5742                         }
5743                 }
5744                 g_list_free (list);
5745                 list = NULL;
5746
5747                 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5748                 if (!is_ok (&error)) {
5749                         mono_error_set_pending_exception (&error);
5750                         return NULL;
5751                 }
5752                 mono_set_pending_exception (exc);
5753                 return NULL;
5754         }
5755                 
5756         return res;
5757 }
5758
5759 ICALL_EXPORT gboolean
5760 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5761 {
5762         MonoError error;
5763         MonoAssemblyName aname;
5764         MonoDomain *domain = mono_object_domain (name);
5765         char *val;
5766         gboolean is_version_defined;
5767         gboolean is_token_defined;
5768
5769         aname.public_key = NULL;
5770         val = mono_string_to_utf8_checked (assname, &error);
5771         if (mono_error_set_pending_exception (&error))
5772                 return FALSE;
5773
5774         if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5775                 g_free ((guint8*) aname.public_key);
5776                 g_free (val);
5777                 return FALSE;
5778         }
5779         
5780         fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5781         mono_error_set_pending_exception (&error);
5782
5783         mono_assembly_name_free (&aname);
5784         g_free ((guint8*) aname.public_key);
5785         g_free (val);
5786
5787         return TRUE;
5788 }
5789
5790 ICALL_EXPORT MonoReflectionType*
5791 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5792 {
5793         MonoError error;
5794         MonoReflectionType *ret;
5795         MonoDomain *domain = mono_object_domain (module); 
5796         MonoClass *klass;
5797
5798         g_assert (module->image);
5799
5800         if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5801                 /* These images do not have a global type */
5802                 return NULL;
5803
5804         klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5805         if (!mono_error_ok (&error)) {
5806                 mono_error_set_pending_exception (&error);
5807                 return NULL;
5808         }
5809
5810         ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5811         if (!mono_error_ok (&error)) {
5812                 mono_error_set_pending_exception (&error);
5813                 return NULL;
5814         }
5815
5816         return ret;
5817 }
5818
5819 ICALL_EXPORT void
5820 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5821 {
5822         /*if (module->image)
5823                 mono_image_close (module->image);*/
5824 }
5825
5826 ICALL_EXPORT MonoString*
5827 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5828 {
5829         MonoDomain *domain = mono_object_domain (module); 
5830
5831         g_assert (module->image);
5832         return mono_string_new (domain, module->image->guid);
5833 }
5834
5835 ICALL_EXPORT gpointer
5836 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5837 {
5838 #ifdef HOST_WIN32
5839         if (module->image && module->image->is_module_handle)
5840                 return module->image->raw_data;
5841 #endif
5842
5843         return (gpointer) (-1);
5844 }
5845
5846 ICALL_EXPORT void
5847 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5848 {
5849         if (image_is_dynamic (image)) {
5850                 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5851                 *pe_kind = dyn->pe_kind;
5852                 *machine = dyn->machine;
5853         }
5854         else {
5855                 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5856                 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5857         }
5858 }
5859
5860 ICALL_EXPORT gint32
5861 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5862 {
5863         return (image->md_version_major << 16) | (image->md_version_minor);
5864 }
5865
5866 ICALL_EXPORT MonoArray*
5867 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5868 {
5869         MonoError error;
5870         MonoArray *exceptions;
5871         int i;
5872
5873         if (!module->image) {
5874                 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
5875                 mono_error_set_pending_exception (&error);
5876                 return arr;
5877         } else {
5878                 MonoArray *res;
5879
5880                 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5881                 if (mono_error_set_pending_exception (&error))
5882                         return NULL;
5883
5884                 for (i = 0; i < mono_array_length (exceptions); ++i) {
5885                         MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5886                         if (ex) {
5887                                 mono_set_pending_exception (ex);
5888                                 return NULL;
5889                         }
5890                 }
5891                 return res;
5892         }
5893 }
5894
5895 static gboolean
5896 mono_memberref_is_method (MonoImage *image, guint32 token)
5897 {
5898         if (!image_is_dynamic (image)) {
5899                 guint32 cols [MONO_MEMBERREF_SIZE];
5900                 const char *sig;
5901                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5902                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5903                 mono_metadata_decode_blob_size (sig, &sig);
5904                 return (*sig != 0x6);
5905         } else {
5906                 MonoError error;
5907                 MonoClass *handle_class;
5908
5909                 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5910                         mono_error_cleanup (&error); /* just probing, ignore error */
5911                         return FALSE;
5912                 }
5913
5914                 return mono_defaults.methodhandle_class == handle_class;
5915         }
5916 }
5917
5918 static void
5919 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5920 {
5921         if (type_args)
5922                 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5923                                                                       mono_array_addr (type_args, MonoType*, 0));
5924         else
5925                 context->class_inst = NULL;
5926         if (method_args)
5927                 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5928                                                                        mono_array_addr (method_args, MonoType*, 0));
5929         else
5930                 context->method_inst = NULL;
5931 }
5932
5933 ICALL_EXPORT MonoType*
5934 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5935 {
5936         MonoClass *klass;
5937         int table = mono_metadata_token_table (token);
5938         int index = mono_metadata_token_index (token);
5939         MonoGenericContext context;
5940         MonoError error;
5941
5942         *resolve_error = ResolveTokenError_Other;
5943
5944         /* Validate token */
5945         if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) && 
5946                 (table != MONO_TABLE_TYPESPEC)) {
5947                 *resolve_error = ResolveTokenError_BadTable;
5948                 return NULL;
5949         }
5950
5951         if (image_is_dynamic (image)) {
5952                 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5953                         klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5954                         mono_error_cleanup (&error);
5955                         return klass ? &klass->byval_arg : NULL;
5956                 }
5957
5958                 init_generic_context_from_args (&context, type_args, method_args);
5959                 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5960                 mono_error_cleanup (&error);
5961                 return klass ? &klass->byval_arg : NULL;
5962         }
5963
5964         if ((index <= 0) || (index > image->tables [table].rows)) {
5965                 *resolve_error = ResolveTokenError_OutOfRange;
5966                 return NULL;
5967         }
5968
5969         init_generic_context_from_args (&context, type_args, method_args);
5970         klass = mono_class_get_checked (image, token, &error);
5971         if (klass)
5972                 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5973         if (!mono_error_ok (&error)) {
5974                 mono_error_set_pending_exception (&error);
5975                 return NULL;
5976         }
5977
5978         if (klass)
5979                 return &klass->byval_arg;
5980         else
5981                 return NULL;
5982 }
5983
5984 ICALL_EXPORT MonoMethod*
5985 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5986 {
5987         MonoError error;
5988         int table = mono_metadata_token_table (token);
5989         int index = mono_metadata_token_index (token);
5990         MonoGenericContext context;
5991         MonoMethod *method;
5992
5993         *resolve_error = ResolveTokenError_Other;
5994
5995         /* Validate token */
5996         if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) && 
5997                 (table != MONO_TABLE_MEMBERREF)) {
5998                 *resolve_error = ResolveTokenError_BadTable;
5999                 return NULL;
6000         }
6001
6002         if (image_is_dynamic (image)) {
6003                 if (table == MONO_TABLE_METHOD) {
6004                         method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6005                         mono_error_cleanup (&error);
6006                         return method;
6007                 }
6008
6009                 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
6010                         *resolve_error = ResolveTokenError_BadTable;
6011                         return NULL;
6012                 }
6013
6014                 init_generic_context_from_args (&context, type_args, method_args);
6015                 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6016                 mono_error_cleanup (&error);
6017                 return method;
6018         }
6019
6020         if ((index <= 0) || (index > image->tables [table].rows)) {
6021                 *resolve_error = ResolveTokenError_OutOfRange;
6022                 return NULL;
6023         }
6024         if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6025                 *resolve_error = ResolveTokenError_BadTable;
6026                 return NULL;
6027         }
6028
6029         init_generic_context_from_args (&context, type_args, method_args);
6030         method = mono_get_method_checked (image, token, NULL, &context, &error);
6031         mono_error_set_pending_exception (&error);
6032
6033         return method;
6034 }
6035
6036 ICALL_EXPORT MonoString*
6037 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6038 {
6039         MonoError error;
6040         int index = mono_metadata_token_index (token);
6041
6042         *resolve_error = ResolveTokenError_Other;
6043
6044         /* Validate token */
6045         if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6046                 *resolve_error = ResolveTokenError_BadTable;
6047                 return NULL;
6048         }
6049
6050         if (image_is_dynamic (image)) {
6051                 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6052                 mono_error_cleanup (&error);
6053                 return result;
6054         }
6055
6056         if ((index <= 0) || (index >= image->heap_us.size)) {
6057                 *resolve_error = ResolveTokenError_OutOfRange;
6058                 return NULL;
6059         }
6060
6061         /* FIXME: What to do if the index points into the middle of a string ? */
6062
6063         MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
6064         mono_error_set_pending_exception (&error);
6065         return result;
6066 }
6067
6068 ICALL_EXPORT MonoClassField*
6069 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6070 {
6071         MonoError error;
6072         MonoClass *klass;
6073         int table = mono_metadata_token_table (token);
6074         int index = mono_metadata_token_index (token);
6075         MonoGenericContext context;
6076         MonoClassField *field;
6077
6078         *resolve_error = ResolveTokenError_Other;
6079
6080         /* Validate token */
6081         if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6082                 *resolve_error = ResolveTokenError_BadTable;
6083                 return NULL;
6084         }
6085
6086         if (image_is_dynamic (image)) {
6087                 if (table == MONO_TABLE_FIELD) {
6088                         field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6089                         mono_error_cleanup (&error);
6090                         return field;
6091                 }
6092
6093                 if (mono_memberref_is_method (image, token)) {
6094                         *resolve_error = ResolveTokenError_BadTable;
6095                         return NULL;
6096                 }
6097
6098                 init_generic_context_from_args (&context, type_args, method_args);
6099                 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6100                 mono_error_cleanup (&error);
6101                 return field;
6102         }
6103
6104         if ((index <= 0) || (index > image->tables [table].rows)) {
6105                 *resolve_error = ResolveTokenError_OutOfRange;
6106                 return NULL;
6107         }
6108         if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6109                 *resolve_error = ResolveTokenError_BadTable;
6110                 return NULL;
6111         }
6112
6113         init_generic_context_from_args (&context, type_args, method_args);
6114         field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6115         mono_error_set_pending_exception (&error);
6116         
6117         return field;
6118 }
6119
6120
6121 ICALL_EXPORT MonoObject*
6122 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6123 {
6124         MonoError merror;
6125         MonoObject *ret;
6126         int table = mono_metadata_token_table (token);
6127
6128         *error = ResolveTokenError_Other;
6129
6130         switch (table) {
6131         case MONO_TABLE_TYPEDEF:
6132         case MONO_TABLE_TYPEREF:
6133         case MONO_TABLE_TYPESPEC: {
6134                 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6135                 if (t) {
6136                         ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6137                         mono_error_set_pending_exception (&merror);
6138
6139                         return ret;
6140                 }
6141                 else
6142                         return NULL;
6143         }
6144         case MONO_TABLE_METHOD:
6145         case MONO_TABLE_METHODSPEC: {
6146                 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6147                 if (m) {
6148                         ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6149                         mono_error_set_pending_exception (&merror);
6150
6151                         return ret;
6152                 } else
6153                         return NULL;
6154         }               
6155         case MONO_TABLE_FIELD: {
6156                 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6157                 if (f) {
6158                         ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6159                         mono_error_set_pending_exception (&merror);
6160                         return ret;
6161                 }
6162                 else
6163                         return NULL;
6164         }
6165         case MONO_TABLE_MEMBERREF:
6166                 if (mono_memberref_is_method (image, token)) {
6167                         MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6168                         if (m) {
6169                                 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6170                                 mono_error_set_pending_exception (&merror);
6171
6172                                 return ret;
6173                         } else
6174                                 return NULL;
6175                 }
6176                 else {
6177                         MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6178                         if (f) {
6179                                 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6180                                 mono_error_set_pending_exception (&merror);
6181                                 return ret;
6182                         }
6183                         else
6184                                 return NULL;
6185                 }
6186                 break;
6187
6188         default:
6189                 *error = ResolveTokenError_BadTable;
6190         }
6191
6192         return NULL;
6193 }
6194
6195 ICALL_EXPORT MonoArray*
6196 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6197 {
6198         MonoError error;
6199         int table = mono_metadata_token_table (token);
6200         int idx = mono_metadata_token_index (token);
6201         MonoTableInfo *tables = image->tables;
6202         guint32 sig, len;
6203         const char *ptr;
6204         MonoArray *res;
6205
6206         *resolve_error = ResolveTokenError_OutOfRange;
6207
6208         /* FIXME: Support other tables ? */
6209         if (table != MONO_TABLE_STANDALONESIG)
6210                 return NULL;
6211
6212         if (image_is_dynamic (image))
6213                 return NULL;
6214
6215         if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6216                 return NULL;
6217
6218         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6219
6220         ptr = mono_metadata_blob_heap (image, sig);
6221         len = mono_metadata_decode_blob_size (ptr, &ptr);
6222
6223         res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6224         if (mono_error_set_pending_exception (&error))
6225                 return NULL;
6226         memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6227         return res;
6228 }
6229
6230 ICALL_EXPORT MonoReflectionType*
6231 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6232 {
6233         MonoError error;
6234         MonoReflectionType *ret;
6235         MonoClass *klass;
6236         int isbyref = 0, rank;
6237         char *p;
6238         char *str = mono_string_to_utf8_checked (smodifiers, &error);
6239         if (mono_error_set_pending_exception (&error))
6240                 return NULL;
6241
6242         klass = mono_class_from_mono_type (tb->type.type);
6243         p = str;
6244         /* logic taken from mono_reflection_parse_type(): keep in sync */
6245         while (*p) {
6246                 switch (*p) {
6247                 case '&':
6248                         if (isbyref) { /* only one level allowed by the spec */
6249                                 g_free (str);
6250                                 return NULL;
6251                         }
6252                         isbyref = 1;
6253                         p++;
6254
6255                         g_free (str);
6256
6257                         ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6258                         mono_error_set_pending_exception (&error);
6259
6260                         return ret;
6261                 case '*':
6262                         klass = mono_ptr_class_get (&klass->byval_arg);
6263                         mono_class_init (klass);
6264                         p++;
6265                         break;
6266                 case '[':
6267                         rank = 1;
6268                         p++;
6269                         while (*p) {
6270                                 if (*p == ']')
6271                                         break;
6272                                 if (*p == ',')
6273                                         rank++;
6274                                 else if (*p != '*') { /* '*' means unknown lower bound */
6275                                         g_free (str);
6276                                         return NULL;
6277                                 }
6278                                 ++p;
6279                         }
6280                         if (*p != ']') {
6281                                 g_free (str);
6282                                 return NULL;
6283                         }
6284                         p++;
6285                         klass = mono_array_class_get (klass, rank);
6286                         mono_class_init (klass);
6287                         break;
6288                 default:
6289                         break;
6290                 }
6291         }
6292
6293         g_free (str);
6294
6295         ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6296         mono_error_set_pending_exception (&error);
6297
6298         return ret;
6299 }
6300
6301 ICALL_EXPORT MonoBoolean
6302 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6303 {
6304         MonoType *type;
6305         MonoBoolean res;
6306
6307         type = t->type;
6308         res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6309
6310         return res;
6311 }
6312
6313 static void
6314 check_for_invalid_type (MonoClass *klass, MonoError *error)
6315 {
6316         char *name;
6317         MonoString *str;
6318
6319         mono_error_init (error);
6320
6321         if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6322                 return;
6323
6324         name = mono_type_get_full_name (klass);
6325         str =  mono_string_new (mono_domain_get (), name);
6326         g_free (name);
6327         mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6328
6329 }
6330 ICALL_EXPORT MonoReflectionType *
6331 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6332 {
6333         MonoError error;
6334         MonoReflectionType *ret;
6335         MonoClass *klass, *aklass;
6336
6337         klass = mono_class_from_mono_type (type->type);
6338         check_for_invalid_type (klass, &error);
6339         mono_error_set_pending_exception (&error);
6340
6341         if (rank == 0) //single dimentional array
6342                 aklass = mono_array_class_get (klass, 1);
6343         else
6344                 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6345
6346         ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6347         mono_error_set_pending_exception (&error);
6348
6349         return ret;
6350 }
6351
6352 ICALL_EXPORT MonoReflectionType *
6353 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6354 {
6355         MonoError error;
6356         MonoReflectionType *ret;
6357         MonoClass *klass;
6358
6359         klass = mono_class_from_mono_type (type->type);
6360         mono_class_init_checked (klass, &error);
6361         if (mono_error_set_pending_exception (&error))
6362                 return NULL;
6363
6364         check_for_invalid_type (klass, &error);
6365         if (mono_error_set_pending_exception (&error))
6366                 return NULL;
6367
6368         ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6369         mono_error_set_pending_exception (&error);
6370
6371         return ret;
6372 }
6373
6374 ICALL_EXPORT MonoReflectionType *
6375 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6376 {
6377         MonoError error;
6378         MonoReflectionType *ret;
6379         MonoClass *klass, *pklass;
6380
6381         klass = mono_class_from_mono_type (type->type);
6382         mono_class_init_checked (klass, &error);
6383         if (mono_error_set_pending_exception (&error))
6384                 return NULL;
6385         check_for_invalid_type (klass, &error);
6386         if (mono_error_set_pending_exception (&error))
6387                 return NULL;
6388
6389         pklass = mono_ptr_class_get (type->type);
6390
6391         ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6392         mono_error_set_pending_exception (&error);
6393
6394         return ret;
6395 }
6396
6397 ICALL_EXPORT MonoObject *
6398 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6399                                                    MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6400 {
6401         MonoError error;
6402         MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6403         MonoObject *delegate;
6404         gpointer func;
6405         MonoMethod *method = info->method;
6406
6407         mono_class_init_checked (delegate_class, &error);
6408         if (mono_error_set_pending_exception (&error))
6409                 return NULL;
6410
6411         if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6412                 /* FIXME improve this exception message */
6413                 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6414                                                  __func__,
6415                                                  "delegate_class->parent == mono_defaults.multicastdelegate_class");
6416                 mono_error_set_pending_exception (&error);
6417                 return NULL;
6418         }
6419
6420         if (mono_security_core_clr_enabled ()) {
6421                 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6422                         if (throwOnBindFailure)
6423                                 mono_error_set_pending_exception (&error);
6424                         else
6425                                 mono_error_cleanup (&error);
6426                         return NULL;
6427                 }
6428         }
6429
6430         delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6431         if (mono_error_set_pending_exception (&error))
6432                 return NULL;
6433
6434         if (method_is_dynamic (method)) {
6435                 /* Creating a trampoline would leak memory */
6436                 func = mono_compile_method_checked (method, &error);
6437                 if (mono_error_set_pending_exception (&error))
6438                         return NULL;
6439         } else {
6440                 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6441                         method = mono_object_get_virtual_method (target, method);
6442                 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6443                 if (mono_error_set_pending_exception (&error))
6444                         return NULL;
6445                 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6446         }
6447
6448         mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6449         if (mono_error_set_pending_exception (&error))
6450                 return NULL;
6451         return delegate;
6452 }
6453
6454 ICALL_EXPORT MonoMulticastDelegate *
6455 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6456 {
6457         MonoError error;
6458         MonoMulticastDelegate *ret;
6459
6460         g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6461
6462         ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6463         if (mono_error_set_pending_exception (&error))
6464                 return NULL;
6465
6466         ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6467
6468         return ret;
6469 }
6470
6471 ICALL_EXPORT MonoReflectionMethod*
6472 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6473 {
6474         MonoReflectionMethod *ret = NULL;
6475         MonoError error;
6476         ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6477         mono_error_set_pending_exception (&error);
6478         return ret;
6479 }
6480
6481 /* System.Buffer */
6482
6483 static inline gint32 
6484 mono_array_get_byte_length (MonoArray *array)
6485 {
6486         MonoClass *klass;
6487         int length;
6488         int i;
6489
6490         klass = array->obj.vtable->klass;
6491
6492         if (array->bounds == NULL)
6493                 length = array->max_length;
6494         else {
6495                 length = 1;
6496                 for (i = 0; i < klass->rank; ++ i)
6497                         length *= array->bounds [i].length;
6498         }
6499
6500         switch (klass->element_class->byval_arg.type) {
6501         case MONO_TYPE_I1:
6502         case MONO_TYPE_U1:
6503         case MONO_TYPE_BOOLEAN:
6504                 return length;
6505         case MONO_TYPE_I2:
6506         case MONO_TYPE_U2:
6507         case MONO_TYPE_CHAR:
6508                 return length << 1;
6509         case MONO_TYPE_I4:
6510         case MONO_TYPE_U4:
6511         case MONO_TYPE_R4:
6512                 return length << 2;
6513         case MONO_TYPE_I:
6514         case MONO_TYPE_U:
6515                 return length * sizeof (gpointer);
6516         case MONO_TYPE_I8:
6517         case MONO_TYPE_U8:
6518         case MONO_TYPE_R8:
6519                 return length << 3;
6520         default:
6521                 return -1;
6522         }
6523 }
6524
6525 ICALL_EXPORT gint32 
6526 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array) 
6527 {
6528         return mono_array_get_byte_length (array);
6529 }
6530
6531 ICALL_EXPORT gint8 
6532 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx) 
6533 {
6534         return mono_array_get (array, gint8, idx);
6535 }
6536
6537 ICALL_EXPORT void 
6538 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value) 
6539 {
6540         mono_array_set (array, gint8, idx, value);
6541 }
6542
6543 ICALL_EXPORT MonoBoolean
6544 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count) 
6545 {
6546         guint8 *src_buf, *dest_buf;
6547
6548         if (count < 0) {
6549                 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6550                 return FALSE;
6551         }
6552
6553         g_assert (count >= 0);
6554
6555         /* This is called directly from the class libraries without going through the managed wrapper */
6556         MONO_CHECK_ARG_NULL (src, FALSE);
6557         MONO_CHECK_ARG_NULL (dest, FALSE);
6558
6559         /* watch out for integer overflow */
6560         if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6561                 return FALSE;
6562
6563         src_buf = (guint8 *)src->vector + src_offset;
6564         dest_buf = (guint8 *)dest->vector + dest_offset;
6565
6566         if (src != dest)
6567                 memcpy (dest_buf, src_buf, count);
6568         else
6569                 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6570
6571         return TRUE;
6572 }
6573
6574 #ifndef DISABLE_REMOTING
6575 ICALL_EXPORT MonoObject *
6576 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6577 {
6578         MonoError error;
6579         MonoDomain *domain = mono_object_domain (this_obj); 
6580         MonoObject *res;
6581         MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6582         MonoTransparentProxy *tp;
6583         MonoType *type;
6584         MonoClass *klass;
6585
6586         res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6587         if (mono_error_set_pending_exception (&error))
6588                 return NULL;
6589
6590         tp = (MonoTransparentProxy*) res;
6591         
6592         MONO_OBJECT_SETREF (tp, rp, rp);
6593         type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6594         klass = mono_class_from_mono_type (type);
6595
6596         // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6597         mono_class_setup_vtable (klass);
6598         if (mono_class_has_failure (klass)) {
6599                 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6600                 return NULL;
6601         }
6602
6603         tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6604         if (mono_error_set_pending_exception (&error))
6605                 return NULL;
6606         tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6607         if (mono_error_set_pending_exception (&error))
6608                 return NULL;
6609
6610         res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6611         if (mono_error_set_pending_exception (&error))
6612                 return NULL;
6613         return res;
6614 }
6615
6616 ICALL_EXPORT MonoReflectionType *
6617 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6618 {
6619         MonoError error;
6620         MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6621         mono_error_set_pending_exception (&error);
6622
6623         return ret;
6624 }
6625 #endif
6626
6627 /* System.Environment */
6628
6629 MonoString*
6630 ves_icall_System_Environment_get_UserName (void)
6631 {
6632         /* using glib is more portable */
6633         return mono_string_new (mono_domain_get (), g_get_user_name ());
6634 }
6635
6636
6637 ICALL_EXPORT MonoString *
6638 ves_icall_System_Environment_get_MachineName (void)
6639 {
6640 #if defined (HOST_WIN32)
6641         gunichar2 *buf;
6642         guint32 len;
6643         MonoString *result;
6644
6645         len = MAX_COMPUTERNAME_LENGTH + 1;
6646         buf = g_new (gunichar2, len);
6647
6648         result = NULL;
6649         if (GetComputerName (buf, (PDWORD) &len)) {
6650                 MonoError error;
6651                 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6652                 mono_error_set_pending_exception (&error);
6653         }
6654
6655         g_free (buf);
6656         return result;
6657 #elif !defined(DISABLE_SOCKETS)
6658         MonoString *result;
6659         char *buf;
6660         int n;
6661 #if defined _SC_HOST_NAME_MAX
6662         n = sysconf (_SC_HOST_NAME_MAX);
6663         if (n == -1)
6664 #endif
6665         n = 512;
6666         buf = g_malloc (n+1);
6667         
6668         if (gethostname (buf, n) == 0){
6669                 buf [n] = 0;
6670                 result = mono_string_new (mono_domain_get (), buf);
6671         } else
6672                 result = NULL;
6673         g_free (buf);
6674         
6675         return result;
6676 #else
6677         return mono_string_new (mono_domain_get (), "mono");
6678 #endif
6679 }
6680
6681 ICALL_EXPORT int
6682 ves_icall_System_Environment_get_Platform (void)
6683 {
6684 #if defined (TARGET_WIN32)
6685         /* Win32NT */
6686         return 2;
6687 #elif defined(__MACH__)
6688         /* OSX */
6689         //
6690         // Notice that the value is hidden from user code, and only exposed
6691         // to mscorlib.   This is due to Mono's Unix/MacOS code predating the
6692         // define and making assumptions based on Unix/128/4 values before there
6693         // was a MacOS define.    Lots of code would assume that not-Unix meant
6694         // Windows, but in this case, it would be OSX. 
6695         //
6696         return 6;
6697 #else
6698         /* Unix */
6699         return 4;
6700 #endif
6701 }
6702
6703 ICALL_EXPORT MonoString *
6704 ves_icall_System_Environment_get_NewLine (void)
6705 {
6706 #if defined (HOST_WIN32)
6707         return mono_string_new (mono_domain_get (), "\r\n");
6708 #else
6709         return mono_string_new (mono_domain_get (), "\n");
6710 #endif
6711 }
6712
6713 ICALL_EXPORT MonoBoolean
6714 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6715 {
6716 #if SIZEOF_VOID_P == 8
6717         return TRUE;
6718 #else
6719 #ifdef HOST_WIN32
6720         gboolean isWow64Process = FALSE;
6721         if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6722                 return (MonoBoolean)isWow64Process;
6723         }
6724 #elif defined(HAVE_SYS_UTSNAME_H)
6725         struct utsname name;
6726
6727         if (uname (&name) >= 0) {
6728                 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6729         }
6730 #endif
6731         return FALSE;
6732 #endif
6733 }
6734
6735 ICALL_EXPORT MonoString *
6736 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6737 {
6738         MonoError error;
6739         const gchar *value;
6740         gchar *utf8_name;
6741
6742         if (name == NULL)
6743                 return NULL;
6744
6745         utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6746         if (mono_error_set_pending_exception (&error))
6747                 return NULL;
6748         value = g_getenv (utf8_name);
6749
6750         g_free (utf8_name);
6751
6752         if (value == 0)
6753                 return NULL;
6754         
6755         return mono_string_new (mono_domain_get (), value);
6756 }
6757
6758 /*
6759  * There is no standard way to get at environ.
6760  */
6761 #ifndef _MSC_VER
6762 #ifndef __MINGW32_VERSION
6763 #if defined(__APPLE__)
6764 #if defined (TARGET_OSX)
6765 /* Apple defines this in crt_externs.h but doesn't provide that header for 
6766  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
6767  * in fact exist on all implementations (so far) 
6768  */
6769 gchar ***_NSGetEnviron(void);
6770 #define environ (*_NSGetEnviron())
6771 #else
6772 static char *mono_environ[1] = { NULL };
6773 #define environ mono_environ
6774 #endif /* defined (TARGET_OSX) */
6775 #else
6776 extern
6777 char **environ;
6778 #endif
6779 #endif
6780 #endif
6781
6782 ICALL_EXPORT MonoArray *
6783 ves_icall_System_Environment_GetCoomandLineArgs (void)
6784 {
6785         MonoError error;
6786         MonoArray *result = mono_runtime_get_main_args_checked (&error);
6787         mono_error_set_pending_exception (&error);
6788         return result;
6789 }
6790
6791 ICALL_EXPORT MonoArray *
6792 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6793 {
6794 #ifdef HOST_WIN32
6795         MonoError error;
6796         MonoArray *names;
6797         MonoDomain *domain;
6798         MonoString *str;
6799         WCHAR* env_strings;
6800         WCHAR* env_string;
6801         WCHAR* equal_str;
6802         int n = 0;
6803
6804         env_strings = GetEnvironmentStrings();
6805
6806         if (env_strings) {
6807                 env_string = env_strings;
6808                 while (*env_string != '\0') {
6809                 /* weird case that MS seems to skip */
6810                         if (*env_string != '=')
6811                                 n++;
6812                         while (*env_string != '\0')
6813                                 env_string++;
6814                         env_string++;
6815                 }
6816         }
6817
6818         domain = mono_domain_get ();
6819         names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6820         if (mono_error_set_pending_exception (&error))
6821                 return NULL;
6822
6823         if (env_strings) {
6824                 n = 0;
6825                 env_string = env_strings;
6826                 while (*env_string != '\0') {
6827                         /* weird case that MS seems to skip */
6828                         if (*env_string != '=') {
6829                                 equal_str = wcschr(env_string, '=');
6830                                 g_assert(equal_str);
6831                                 MonoError error;
6832                                 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6833                                 if (mono_error_set_pending_exception (&error))
6834                                         return NULL;
6835
6836                                 mono_array_setref (names, n, str);
6837                                 n++;
6838                         }
6839                         while (*env_string != '\0')
6840                                 env_string++;
6841                         env_string++;
6842                 }
6843
6844                 FreeEnvironmentStrings (env_strings);
6845         }
6846
6847         return names;
6848
6849 #else
6850         MonoError error;
6851         MonoArray *names;
6852         MonoDomain *domain;
6853         MonoString *str;
6854         gchar **e, **parts;
6855         int n;
6856
6857         n = 0;
6858         for (e = environ; *e != 0; ++ e)
6859                 ++ n;
6860
6861         domain = mono_domain_get ();
6862         names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6863         if (mono_error_set_pending_exception (&error))
6864                 return NULL;
6865
6866         n = 0;
6867         for (e = environ; *e != 0; ++ e) {
6868                 parts = g_strsplit (*e, "=", 2);
6869                 if (*parts != 0) {
6870                         str = mono_string_new (domain, *parts);
6871                         mono_array_setref (names, n, str);
6872                 }
6873
6874                 g_strfreev (parts);
6875
6876                 ++ n;
6877         }
6878
6879         return names;
6880 #endif
6881 }
6882
6883 ICALL_EXPORT void
6884 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6885 {
6886 #ifdef HOST_WIN32
6887         gunichar2 *utf16_name, *utf16_value;
6888 #else
6889         gchar *utf8_name, *utf8_value;
6890         MonoError error;
6891 #endif
6892
6893 #ifdef HOST_WIN32
6894         utf16_name = mono_string_to_utf16 (name);
6895         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6896                 SetEnvironmentVariable (utf16_name, NULL);
6897                 g_free (utf16_name);
6898                 return;
6899         }
6900
6901         utf16_value = mono_string_to_utf16 (value);
6902
6903         SetEnvironmentVariable (utf16_name, utf16_value);
6904
6905         g_free (utf16_name);
6906         g_free (utf16_value);
6907 #else
6908         utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6909         if (mono_error_set_pending_exception (&error))
6910                 return;
6911
6912         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6913                 g_unsetenv (utf8_name);
6914                 g_free (utf8_name);
6915                 return;
6916         }
6917
6918         utf8_value = mono_string_to_utf8_checked (value, &error);
6919         if (!mono_error_ok (&error)) {
6920                 g_free (utf8_name);
6921                 mono_error_set_pending_exception (&error);
6922                 return;
6923         }
6924         g_setenv (utf8_name, utf8_value, TRUE);
6925
6926         g_free (utf8_name);
6927         g_free (utf8_value);
6928 #endif
6929 }
6930
6931 ICALL_EXPORT void
6932 ves_icall_System_Environment_Exit (int result)
6933 {
6934         mono_environment_exitcode_set (result);
6935
6936 /* FIXME: There are some cleanup hangs that should be worked out, but
6937  * if the program is going to exit, everything will be cleaned up when
6938  * NaCl exits anyway.
6939  */
6940 #ifndef __native_client__
6941         if (!mono_runtime_try_shutdown ())
6942                 mono_thread_exit ();
6943
6944         /* Suspend all managed threads since the runtime is going away */
6945         mono_thread_suspend_all_other_threads ();
6946
6947         mono_runtime_quit ();
6948 #endif
6949
6950         /* we may need to do some cleanup here... */
6951         exit (result);
6952 }
6953
6954 ICALL_EXPORT MonoString*
6955 ves_icall_System_Environment_GetGacPath (void)
6956 {
6957         return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6958 }
6959
6960 ICALL_EXPORT MonoString*
6961 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6962 {
6963 #if defined (HOST_WIN32)
6964         #ifndef CSIDL_FLAG_CREATE
6965                 #define CSIDL_FLAG_CREATE       0x8000
6966         #endif
6967
6968         WCHAR path [MAX_PATH];
6969         /* Create directory if no existing */
6970         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6971                 int len = 0;
6972                 while (path [len])
6973                         ++ len;
6974                 MonoError error;
6975                 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6976                 mono_error_set_pending_exception (&error);
6977                 return res;
6978         }
6979 #else
6980         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6981 #endif
6982         return mono_string_new (mono_domain_get (), "");
6983 }
6984
6985 ICALL_EXPORT MonoArray *
6986 ves_icall_System_Environment_GetLogicalDrives (void)
6987 {
6988         MonoError error;
6989         gunichar2 buf [256], *ptr, *dname;
6990         gunichar2 *u16;
6991         guint initial_size = 127, size = 128;
6992         gint ndrives;
6993         MonoArray *result;
6994         MonoString *drivestr;
6995         MonoDomain *domain = mono_domain_get ();
6996         gint len;
6997
6998         buf [0] = '\0';
6999         ptr = buf;
7000
7001         while (size > initial_size) {
7002                 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7003                 if (size > initial_size) {
7004                         if (ptr != buf)
7005                                 g_free (ptr);
7006                         ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7007                         initial_size = size;
7008                         size++;
7009                 }
7010         }
7011
7012         /* Count strings */
7013         dname = ptr;
7014         ndrives = 0;
7015         do {
7016                 while (*dname++);
7017                 ndrives++;
7018         } while (*dname);
7019
7020         dname = ptr;
7021         result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7022         if (mono_error_set_pending_exception (&error))
7023                 goto leave;
7024
7025         ndrives = 0;
7026         do {
7027                 len = 0;
7028                 u16 = dname;
7029                 while (*u16) { u16++; len ++; }
7030                 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7031                 if (mono_error_set_pending_exception (&error))
7032                         goto leave;
7033
7034                 mono_array_setref (result, ndrives++, drivestr);
7035                 while (*dname++);
7036         } while (*dname);
7037
7038 leave:
7039         if (ptr != buf)
7040                 g_free (ptr);
7041
7042         return result;
7043 }
7044
7045 ICALL_EXPORT MonoString *
7046 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7047 {
7048         MonoError error;
7049         gunichar2 volume_name [MAX_PATH + 1];
7050         
7051         if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7052                 return NULL;
7053         MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
7054         mono_error_set_pending_exception (&error);
7055         return result;
7056 }
7057
7058 ICALL_EXPORT MonoString *
7059 ves_icall_System_Environment_InternalGetHome (void)
7060 {
7061         return mono_string_new (mono_domain_get (), g_get_home_dir ());
7062 }
7063
7064 static const char *encodings [] = {
7065         (char *) 1,
7066                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7067                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7068                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7069         (char *) 2,
7070                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7071                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7072                 "x_unicode_2_0_utf_7",
7073         (char *) 3,
7074                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7075                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7076         (char *) 4,
7077                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7078                 "iso_10646_ucs2",
7079         (char *) 5,
7080                 "unicodefffe", "utf_16be",
7081         (char *) 6,
7082                 "iso_8859_1",
7083         (char *) 0
7084 };
7085
7086 /*
7087  * Returns the internal codepage, if the value of "int_code_page" is
7088  * 1 at entry, and we can not compute a suitable code page number,
7089  * returns the code page as a string
7090  */
7091 ICALL_EXPORT MonoString*
7092 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page) 
7093 {
7094         const char *cset;
7095         const char *p;
7096         char *c;
7097         char *codepage = NULL;
7098         int code;
7099         int want_name = *int_code_page;
7100         int i;
7101         
7102         *int_code_page = -1;
7103
7104         g_get_charset (&cset);
7105         c = codepage = strdup (cset);
7106         for (c = codepage; *c; c++){
7107                 if (isascii (*c) && isalpha (*c))
7108                         *c = tolower (*c);
7109                 if (*c == '-')
7110                         *c = '_';
7111         }
7112         /* g_print ("charset: %s\n", cset); */
7113         
7114         /* handle some common aliases */
7115         p = encodings [0];
7116         code = 0;
7117         for (i = 0; p != 0; ){
7118                 if ((gsize) p < 7){
7119                         code = (gssize) p;
7120                         p = encodings [++i];
7121                         continue;
7122                 }
7123                 if (strcmp (p, codepage) == 0){
7124                         *int_code_page = code;
7125                         break;
7126                 }
7127                 p = encodings [++i];
7128         }
7129         
7130         if (strstr (codepage, "utf_8") != NULL)
7131                 *int_code_page |= 0x10000000;
7132         free (codepage);
7133         
7134         if (want_name && *int_code_page == -1)
7135                 return mono_string_new (mono_domain_get (), cset);
7136         else
7137                 return NULL;
7138 }
7139
7140 ICALL_EXPORT MonoBoolean
7141 ves_icall_System_Environment_get_HasShutdownStarted (void)
7142 {
7143         if (mono_runtime_is_shutting_down ())
7144                 return TRUE;
7145
7146         if (mono_domain_is_unloading (mono_domain_get ()))
7147                 return TRUE;
7148
7149         return FALSE;
7150 }
7151
7152 ICALL_EXPORT void
7153 ves_icall_System_Environment_BroadcastSettingChange (void)
7154 {
7155 #ifdef HOST_WIN32
7156         SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7157 #endif
7158 }
7159
7160 ICALL_EXPORT
7161 gint32
7162 ves_icall_System_Environment_get_TickCount (void)
7163 {
7164         /* this will overflow after ~24 days */
7165         return (gint32) (mono_msec_boottime () & 0xffffffff);
7166 }
7167
7168 ICALL_EXPORT gint32
7169 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7170 {
7171         return 9;
7172 }
7173
7174 #ifndef DISABLE_REMOTING
7175 ICALL_EXPORT MonoBoolean
7176 ves_icall_IsTransparentProxy (MonoObject *proxy)
7177 {
7178         if (!proxy)
7179                 return 0;
7180
7181         if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7182                 return 1;
7183
7184         return 0;
7185 }
7186
7187 ICALL_EXPORT MonoReflectionMethod *
7188 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7189         MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7190 {
7191         MonoReflectionMethod *ret = NULL;
7192         MonoError error;
7193
7194         MonoClass *klass;
7195         MonoMethod *method;
7196         MonoMethod **vtable;
7197         MonoMethod *res = NULL;
7198
7199         MONO_CHECK_ARG_NULL (rtype, NULL);
7200         MONO_CHECK_ARG_NULL (rmethod, NULL);
7201
7202         method = rmethod->method;
7203         klass = mono_class_from_mono_type (rtype->type);
7204         mono_class_init_checked (klass, &error);
7205         if (mono_error_set_pending_exception (&error))
7206                 return NULL;
7207
7208         if (MONO_CLASS_IS_INTERFACE (klass))
7209                 return NULL;
7210
7211         if (method->flags & METHOD_ATTRIBUTE_STATIC)
7212                 return NULL;
7213
7214         if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7215                 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7216                         return rmethod;
7217                 else
7218                         return NULL;
7219         }
7220
7221         mono_class_setup_vtable (klass);
7222         vtable = klass->vtable;
7223
7224         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7225                 gboolean variance_used = FALSE;
7226                 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7227                 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7228                 if (offs >= 0)
7229                         res = vtable [offs + method->slot];
7230         } else {
7231                 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7232                         return NULL;
7233
7234                 if (method->slot != -1)
7235                         res = vtable [method->slot];
7236         }
7237
7238         if (!res)
7239                 return NULL;
7240
7241         ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7242         mono_error_set_pending_exception (&error);
7243         return ret;
7244 }
7245
7246 ICALL_EXPORT void
7247 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7248 {
7249         MonoError error;
7250         MonoClass *klass;
7251         MonoVTable* vtable;
7252
7253         klass = mono_class_from_mono_type (type->type);
7254         vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7255         if (!is_ok (&error)) {
7256                 mono_error_set_pending_exception (&error);
7257                 return;
7258         }
7259
7260         mono_vtable_set_is_remote (vtable, enable);
7261 }
7262
7263 #else /* DISABLE_REMOTING */
7264
7265 ICALL_EXPORT void
7266 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7267 {
7268         g_assert_not_reached ();
7269 }
7270
7271 #endif
7272
7273 ICALL_EXPORT MonoObject *
7274 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7275 {
7276         MonoError error;
7277         MonoClass *klass;
7278         MonoDomain *domain;
7279         MonoObject *ret;
7280         
7281         domain = mono_object_domain (type);
7282         klass = mono_class_from_mono_type (type->type);
7283         mono_class_init_checked (klass, &error);
7284         if (mono_error_set_pending_exception (&error))
7285                 return NULL;
7286
7287         if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7288                 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7289                 return NULL;
7290         }
7291
7292         if (klass->rank >= 1) {
7293                 g_assert (klass->rank == 1);
7294                 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7295                 mono_error_set_pending_exception (&error);
7296                 return ret;
7297         } else {
7298                 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7299                 if (!is_ok (&error)) {
7300                         mono_error_set_pending_exception (&error);
7301                         return NULL;
7302                 }
7303                 /* Bypass remoting object creation check */
7304                 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7305                 mono_error_set_pending_exception (&error);
7306
7307                 return ret;
7308         }
7309 }
7310
7311 ICALL_EXPORT MonoString *
7312 ves_icall_System_IO_get_temp_path (void)
7313 {
7314         return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7315 }
7316
7317 #ifndef PLATFORM_NO_DRIVEINFO
7318 ICALL_EXPORT MonoBoolean
7319 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7320                                                 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7321                                                 gint32 *error)
7322 {
7323         gboolean result;
7324         ULARGE_INTEGER wapi_free_bytes_avail;
7325         ULARGE_INTEGER wapi_total_number_of_bytes;
7326         ULARGE_INTEGER wapi_total_number_of_free_bytes;
7327
7328         *error = ERROR_SUCCESS;
7329         result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7330                                      &wapi_total_number_of_free_bytes);
7331
7332         if (result) {
7333                 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7334                 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7335                 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7336         } else {
7337                 *free_bytes_avail = 0;
7338                 *total_number_of_bytes = 0;
7339                 *total_number_of_free_bytes = 0;
7340                 *error = GetLastError ();
7341         }
7342
7343         return result;
7344 }
7345
7346 ICALL_EXPORT guint32
7347 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7348 {
7349         return GetDriveType (mono_string_chars (root_path_name));
7350 }
7351 #endif
7352
7353 ICALL_EXPORT gpointer
7354 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7355 {
7356         MonoError error;
7357         gpointer result = mono_compile_method_checked (method, &error);
7358         mono_error_set_pending_exception (&error);
7359         return result;
7360 }
7361
7362 ICALL_EXPORT MonoString *
7363 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7364 {
7365         MonoString *mcpath;
7366         gchar *path;
7367
7368         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7369
7370 #if defined (HOST_WIN32)
7371         /* Avoid mixing '/' and '\\' */
7372         {
7373                 gint i;
7374                 for (i = strlen (path) - 1; i >= 0; i--)
7375                         if (path [i] == '/')
7376                                 path [i] = '\\';
7377         }
7378 #endif
7379         mcpath = mono_string_new (mono_domain_get (), path);
7380         g_free (path);
7381
7382         return mcpath;
7383 }
7384
7385 /* this is an icall */
7386 static MonoString *
7387 get_bundled_app_config (void)
7388 {
7389         MonoError error;
7390         const gchar *app_config;
7391         MonoDomain *domain;
7392         MonoString *file;
7393         gchar *config_file_name, *config_file_path;
7394         gsize len, config_file_path_length, config_ext_length;
7395         gchar *module;
7396
7397         domain = mono_domain_get ();
7398         file = domain->setup->configuration_file;
7399         if (!file || file->length == 0)
7400                 return NULL;
7401
7402         // Retrieve config file and remove the extension
7403         config_file_name = mono_string_to_utf8_checked (file, &error);
7404         if (mono_error_set_pending_exception (&error))
7405                 return NULL;
7406         config_file_path = mono_portability_find_file (config_file_name, TRUE);
7407         if (!config_file_path)
7408                 config_file_path = config_file_name;
7409
7410         config_file_path_length = strlen (config_file_path);
7411         config_ext_length = strlen (".config");
7412         if (config_file_path_length <= config_ext_length)
7413                 return NULL;
7414
7415         len = config_file_path_length - config_ext_length;
7416         module = (gchar *)g_malloc0 (len + 1);
7417         memcpy (module, config_file_path, len);
7418         // Get the config file from the module name
7419         app_config = mono_config_string_for_assembly_file (module);
7420         // Clean-up
7421         g_free (module);
7422         if (config_file_name != config_file_path)
7423                 g_free (config_file_name);
7424         g_free (config_file_path);
7425
7426         if (!app_config)
7427                 return NULL;
7428
7429         return mono_string_new (mono_domain_get (), app_config);
7430 }
7431
7432 static MonoString *
7433 get_bundled_machine_config (void)
7434 {
7435         const gchar *machine_config;
7436
7437         machine_config = mono_get_machine_config ();
7438
7439         if (!machine_config)
7440                 return NULL;
7441
7442         return mono_string_new (mono_domain_get (), machine_config);
7443 }
7444
7445 ICALL_EXPORT MonoString *
7446 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7447 {
7448         MonoString *ipath;
7449         gchar *path;
7450
7451         path = g_path_get_dirname (mono_get_config_dir ());
7452
7453 #if defined (HOST_WIN32)
7454         /* Avoid mixing '/' and '\\' */
7455         {
7456                 gint i;
7457                 for (i = strlen (path) - 1; i >= 0; i--)
7458                         if (path [i] == '/')
7459                                 path [i] = '\\';
7460         }
7461 #endif
7462         ipath = mono_string_new (mono_domain_get (), path);
7463         g_free (path);
7464
7465         return ipath;
7466 }
7467
7468 ICALL_EXPORT gboolean
7469 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7470 {
7471         MonoPEResourceDataEntry *entry;
7472         MonoImage *image;
7473
7474         if (!assembly || !result || !size)
7475                 return FALSE;
7476
7477         *result = NULL;
7478         *size = 0;
7479         image = assembly->assembly->image;
7480         entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7481         if (!entry)
7482                 return FALSE;
7483
7484         *result = mono_image_rva_map (image, entry->rde_data_offset);
7485         if (!(*result)) {
7486                 g_free (entry);
7487                 return FALSE;
7488         }
7489         *size = entry->rde_size;
7490         g_free (entry);
7491         return TRUE;
7492 }
7493
7494 ICALL_EXPORT MonoBoolean
7495 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7496 {
7497         return mono_is_debugger_attached ();
7498 }
7499
7500 ICALL_EXPORT MonoBoolean
7501 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7502 {
7503         if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7504                 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7505         else
7506                 return FALSE;
7507 }
7508
7509 ICALL_EXPORT void
7510 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7511 {
7512         if (mono_get_runtime_callbacks ()->debug_log)
7513                 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7514 }
7515
7516 ICALL_EXPORT void
7517 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7518 {
7519 #if defined (HOST_WIN32)
7520         OutputDebugString (mono_string_chars (message));
7521 #else
7522         g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7523 #endif
7524 }
7525
7526 /* Only used for value types */
7527 ICALL_EXPORT MonoObject *
7528 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7529 {
7530         MonoError error;
7531         MonoObject *result;
7532         MonoClass *klass;
7533         MonoDomain *domain;
7534         
7535         domain = mono_object_domain (type);
7536         klass = mono_class_from_mono_type (type->type);
7537         mono_class_init_checked (klass, &error);
7538         if (mono_error_set_pending_exception (&error))
7539                 return NULL;
7540
7541         if (mono_class_is_nullable (klass))
7542                 /* No arguments -> null */
7543                 return NULL;
7544
7545         result = mono_object_new_checked (domain, klass, &error);
7546         mono_error_set_pending_exception (&error);
7547         return result;
7548 }
7549
7550 ICALL_EXPORT MonoReflectionMethod *
7551 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7552 {
7553         MonoReflectionMethod *ret = NULL;
7554         MonoError error;
7555
7556         MonoClass *klass, *parent;
7557         MonoGenericContext *generic_inst = NULL;
7558         MonoMethod *method = m->method;
7559         MonoMethod *result = NULL;
7560         int slot;
7561
7562         if (method->klass == NULL)
7563                 return m;
7564
7565         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7566             MONO_CLASS_IS_INTERFACE (method->klass) ||
7567             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7568                 return m;
7569
7570         slot = mono_method_get_vtable_slot (method);
7571         if (slot == -1)
7572                 return m;
7573
7574         klass = method->klass;
7575         if (klass->generic_class) {
7576                 generic_inst = mono_class_get_context (klass);
7577                 klass = klass->generic_class->container_class;
7578         }
7579
7580         if (definition) {
7581                 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7582                 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7583                         /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7584                            or klass is the generic container class and generic_inst is the instantiation.
7585
7586                            when we go to the parent, if the parent is an open constructed type, we need to
7587                            replace the type parameters by the definitions from the generic_inst, and then take it
7588                            apart again into the klass and the generic_inst.
7589
7590                            For cases like this:
7591                            class C<T> : B<T, int> {
7592                                public override void Foo () { ... }
7593                            }
7594                            class B<U,V> : A<HashMap<U,V>> {
7595                                public override void Foo () { ... }
7596                            }
7597                            class A<X> {
7598                                public virtual void Foo () { ... }
7599                            }
7600
7601                            if at each iteration the parent isn't open, we can skip inflating it.  if at some
7602                            iteration the parent isn't generic (after possible inflation), we set generic_inst to
7603                            NULL;
7604                         */
7605                         MonoGenericContext *parent_inst = NULL;
7606                         if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7607                                 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7608                                 if (!mono_error_ok (&error)) {
7609                                         mono_error_set_pending_exception (&error);
7610                                         return NULL;
7611                                 }
7612                         }
7613                         if (parent->generic_class) {
7614                                 parent_inst = mono_class_get_context (parent);
7615                                 parent = parent->generic_class->container_class;
7616                         }
7617
7618                         mono_class_setup_vtable (parent);
7619                         if (parent->vtable_size <= slot)
7620                                 break;
7621                         klass = parent;
7622                         generic_inst = parent_inst;
7623                 }
7624         } else {
7625                 klass = klass->parent;
7626                 if (!klass)
7627                         return m;
7628                 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7629                         klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7630                         if (!mono_error_ok (&error)) {
7631                                 mono_error_set_pending_exception (&error);
7632                                 return NULL;
7633                         }
7634
7635                         generic_inst = NULL;
7636                 }
7637                 if (klass->generic_class) {
7638                         generic_inst = mono_class_get_context (klass);
7639                         klass = klass->generic_class->container_class;
7640                 }
7641
7642         }
7643
7644         if (generic_inst) {
7645                 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7646                 if (!mono_error_ok (&error)) {
7647                         mono_error_set_pending_exception (&error);
7648                         return NULL;
7649                 }
7650         }
7651
7652         if (klass == method->klass)
7653                 return m;
7654
7655         /*This is possible if definition == FALSE.
7656          * Do it here to be really sure we don't read invalid memory.
7657          */
7658         if (slot >= klass->vtable_size)
7659                 return m;
7660
7661         mono_class_setup_vtable (klass);
7662
7663         result = klass->vtable [slot];
7664         if (result == NULL) {
7665                 /* It is an abstract method */
7666                 gpointer iter = NULL;
7667                 while ((result = mono_class_get_methods (klass, &iter)))
7668                         if (result->slot == slot)
7669                                 break;
7670         }
7671
7672         if (result == NULL)
7673                 return m;
7674
7675         ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7676         mono_error_set_pending_exception (&error);
7677         return ret;
7678 }
7679
7680 ICALL_EXPORT MonoString*
7681 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7682 {
7683         MonoMethod *method = m->method;
7684
7685         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7686         return m->name;
7687 }
7688
7689 ICALL_EXPORT void
7690 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7691 {
7692         iter->sig = *(MonoMethodSignature**)argsp;
7693         
7694         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7695         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7696
7697         iter->next_arg = 0;
7698         /* FIXME: it's not documented what start is exactly... */
7699         if (start) {
7700                 iter->args = start;
7701         } else {
7702                 iter->args = argsp + sizeof (gpointer);
7703         }
7704         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7705
7706         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7707 }
7708
7709 ICALL_EXPORT MonoTypedRef
7710 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7711 {
7712         guint32 i, arg_size;
7713         gint32 align;
7714         MonoTypedRef res;
7715
7716         i = iter->sig->sentinelpos + iter->next_arg;
7717
7718         g_assert (i < iter->sig->param_count);
7719
7720         res.type = iter->sig->params [i];
7721         res.klass = mono_class_from_mono_type (res.type);
7722         arg_size = mono_type_stack_size (res.type, &align);
7723 #if defined(__arm__) || defined(__mips__)
7724         iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7725 #endif
7726         res.value = iter->args;
7727 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7728         /* Values are stored as 8 byte register sized objects, but 'value'
7729          * is dereferenced as a pointer in other routines.
7730          */
7731         res.value = (char*)res.value + 4;
7732 #endif
7733 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7734         if (arg_size <= sizeof (gpointer)) {
7735                 int dummy;
7736                 int padding = arg_size - mono_type_size (res.type, &dummy);
7737                 res.value = (guint8*)res.value + padding;
7738         }
7739 #endif
7740         iter->args = (char*)iter->args + arg_size;
7741         iter->next_arg++;
7742
7743         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7744
7745         return res;
7746 }
7747
7748 ICALL_EXPORT MonoTypedRef
7749 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7750 {
7751         guint32 i, arg_size;
7752         gint32 align;
7753         MonoTypedRef res;
7754
7755         i = iter->sig->sentinelpos + iter->next_arg;
7756
7757         g_assert (i < iter->sig->param_count);
7758
7759         while (i < iter->sig->param_count) {
7760                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7761                         continue;
7762                 res.type = iter->sig->params [i];
7763                 res.klass = mono_class_from_mono_type (res.type);
7764                 /* FIXME: endianess issue... */
7765                 arg_size = mono_type_stack_size (res.type, &align);
7766 #if defined(__arm__) || defined(__mips__)
7767                 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7768 #endif
7769                 res.value = iter->args;
7770                 iter->args = (char*)iter->args + arg_size;
7771                 iter->next_arg++;
7772                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7773                 return res;
7774         }
7775         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7776
7777         res.type = NULL;
7778         res.value = NULL;
7779         res.klass = NULL;
7780         return res;
7781 }
7782
7783 ICALL_EXPORT MonoType*
7784 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7785 {
7786         gint i;
7787         
7788         i = iter->sig->sentinelpos + iter->next_arg;
7789
7790         g_assert (i < iter->sig->param_count);
7791
7792         return iter->sig->params [i];
7793 }
7794
7795 ICALL_EXPORT MonoObject*
7796 mono_TypedReference_ToObject (MonoTypedRef* tref)
7797 {
7798         MonoError error;
7799         MonoObject *result = NULL;
7800         if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7801                 MonoObject** objp = (MonoObject **)tref->value;
7802                 return *objp;
7803         }
7804
7805         result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7806         mono_error_set_pending_exception (&error);
7807         return result;
7808 }
7809
7810 ICALL_EXPORT MonoTypedRef
7811 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7812 {
7813         MonoTypedRef res;
7814         MonoReflectionField *f;
7815         MonoClass *klass;
7816         MonoType *ftype = NULL;
7817         guint8 *p = NULL;
7818         int i;
7819
7820         memset (&res, 0, sizeof (res));
7821
7822         g_assert (fields);
7823         g_assert (mono_array_length (fields) > 0);
7824
7825         klass = target->vtable->klass;
7826
7827         for (i = 0; i < mono_array_length (fields); ++i) {
7828                 f = mono_array_get (fields, MonoReflectionField*, i);
7829                 if (f == NULL) {
7830                         mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7831                         return res;
7832                 }
7833                 if (f->field->parent != klass) {
7834                         mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7835                         return res;
7836                 }
7837                 if (i == 0)
7838                         p = (guint8*)target + f->field->offset;
7839                 else
7840                         p += f->field->offset - sizeof (MonoObject);
7841                 klass = mono_class_from_mono_type (f->field->type);
7842                 ftype = f->field->type;
7843         }
7844
7845         res.type = ftype;
7846         res.klass = mono_class_from_mono_type (ftype);
7847         res.value = p;
7848
7849         return res;
7850 }
7851
7852 static void
7853 prelink_method (MonoMethod *method, MonoError *error)
7854 {
7855         const char *exc_class, *exc_arg;
7856
7857         mono_error_init (error);
7858         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7859                 return;
7860         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7861         if (exc_class) {
7862                 mono_error_set_exception_instance (error,
7863                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7864                 return;
7865         }
7866         /* create the wrapper, too? */
7867 }
7868
7869 ICALL_EXPORT void
7870 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7871 {
7872         MonoError error;
7873
7874         prelink_method (method->method, &error);
7875         mono_error_set_pending_exception (&error);
7876 }
7877
7878 ICALL_EXPORT void
7879 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7880 {
7881         MonoError error;
7882         MonoClass *klass = mono_class_from_mono_type (type->type);
7883         MonoMethod* m;
7884         gpointer iter = NULL;
7885
7886         mono_class_init_checked (klass, &error);
7887         if (mono_error_set_pending_exception (&error))
7888                 return;
7889
7890         while ((m = mono_class_get_methods (klass, &iter))) {
7891                 prelink_method (m, &error);
7892                 if (mono_error_set_pending_exception (&error))
7893                         return;
7894         }
7895 }
7896
7897 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7898 ICALL_EXPORT void
7899 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7900                                             gint32 const **exponents,
7901                                             gunichar2 const **digitLowerTable,
7902                                             gunichar2 const **digitUpperTable,
7903                                             gint64 const **tenPowersList,
7904                                             gint32 const **decHexDigits)
7905 {
7906         *mantissas = Formatter_MantissaBitsTable;
7907         *exponents = Formatter_TensExponentTable;
7908         *digitLowerTable = Formatter_DigitLowerTable;
7909         *digitUpperTable = Formatter_DigitUpperTable;
7910         *tenPowersList = Formatter_TenPowersList;
7911         *decHexDigits = Formatter_DecHexDigits;
7912 }
7913
7914 /*
7915  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7916  * and avoid useless allocations.
7917  */
7918 static MonoArray*
7919 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7920 {
7921         MonoReflectionType *rt;
7922         MonoArray *res;
7923         int i, count = 0;
7924
7925         mono_error_init (error);
7926         for (i = 0; i < type->num_mods; ++i) {
7927                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7928                         count++;
7929         }
7930         if (!count)
7931                 return NULL;
7932         res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7933         return_val_if_nok (error, NULL);
7934         count = 0;
7935         for (i = 0; i < type->num_mods; ++i) {
7936                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7937                         MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7938                         return_val_if_nok (error, NULL);
7939
7940                         rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7941                         return_val_if_nok (error, NULL);
7942
7943                         mono_array_setref (res, count, rt);
7944                         count++;
7945                 }
7946         }
7947         return res;
7948 }
7949
7950 ICALL_EXPORT MonoArray*
7951 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7952 {
7953         MonoError error;
7954         MonoType *type = param->ClassImpl->type;
7955         MonoClass *member_class = mono_object_class (param->MemberImpl);
7956         MonoMethod *method = NULL;
7957         MonoImage *image;
7958         int pos;
7959         MonoMethodSignature *sig;
7960         MonoArray *res;
7961
7962         if (mono_class_is_reflection_method_or_constructor (member_class)) {
7963                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7964                 method = rmethod->method;
7965         } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7966                 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7967                 if (!(method = prop->property->get))
7968                         method = prop->property->set;
7969                 g_assert (method);      
7970         } else {
7971                 char *type_name = mono_type_get_full_name (member_class);
7972                 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7973                 MonoException *ex = mono_get_exception_not_supported  (msg);
7974                 g_free (type_name);
7975                 g_free (msg);
7976                 mono_set_pending_exception (ex);
7977                 return NULL;
7978         }
7979
7980         image = method->klass->image;
7981         pos = param->PositionImpl;
7982         sig = mono_method_signature (method);
7983         if (pos == -1)
7984                 type = sig->ret;
7985         else
7986                 type = sig->params [pos];
7987
7988         res = type_array_from_modifiers (image, type, optional, &error);
7989         mono_error_set_pending_exception (&error);
7990         return res;
7991 }
7992
7993 static MonoType*
7994 get_property_type (MonoProperty *prop)
7995 {
7996         MonoMethodSignature *sig;
7997         if (prop->get) {
7998                 sig = mono_method_signature (prop->get);
7999                 return sig->ret;
8000         } else if (prop->set) {
8001                 sig = mono_method_signature (prop->set);
8002                 return sig->params [sig->param_count - 1];
8003         }
8004         return NULL;
8005 }
8006
8007 ICALL_EXPORT MonoArray*
8008 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8009 {
8010         MonoError error;
8011         MonoType *type = get_property_type (property->property);
8012         MonoImage *image = property->klass->image;
8013         MonoArray *res;
8014
8015         if (!type)
8016                 return NULL;
8017         res = type_array_from_modifiers (image, type, optional, &error);
8018         mono_error_set_pending_exception (&error);
8019         return res;
8020 }
8021
8022 /*
8023  *Construct a MonoType suited to be used to decode a constant blob object.
8024  *
8025  * @type is the target type which will be constructed
8026  * @blob_type is the blob type, for example, that comes from the constant table
8027  * @real_type is the expected constructed type.
8028  */
8029 static void
8030 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8031 {
8032         type->type = blob_type;
8033         type->data.klass = NULL;
8034         if (blob_type == MONO_TYPE_CLASS)
8035                 type->data.klass = mono_defaults.object_class;
8036         else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8037                 /* For enums, we need to use the base type */
8038                 type->type = MONO_TYPE_VALUETYPE;
8039                 type->data.klass = mono_class_from_mono_type (real_type);
8040         } else
8041                 type->data.klass = mono_class_from_mono_type (real_type);
8042 }
8043
8044 ICALL_EXPORT MonoObject*
8045 property_info_get_default_value (MonoReflectionProperty *property)
8046 {
8047         MonoError error;
8048         MonoType blob_type;
8049         MonoProperty *prop = property->property;
8050         MonoType *type = get_property_type (prop);
8051         MonoDomain *domain = mono_object_domain (property); 
8052         MonoTypeEnum def_type;
8053         const char *def_value;
8054         MonoObject *o;
8055
8056         mono_class_init (prop->parent);
8057
8058         if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8059                 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8060                 return NULL;
8061         }
8062
8063         def_value = mono_class_get_property_default_value (prop, &def_type);
8064
8065         mono_type_from_blob_type (&blob_type, def_type, type);
8066         o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8067
8068         mono_error_set_pending_exception (&error);
8069         return o;
8070 }
8071
8072 ICALL_EXPORT MonoBoolean
8073 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8074 {
8075         MonoError error;
8076         MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8077         MonoCustomAttrInfo *cinfo;
8078         gboolean found;
8079
8080         mono_class_init_checked (attr_class, &error);
8081         if (mono_error_set_pending_exception (&error))
8082                 return FALSE;
8083
8084         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8085         if (!is_ok (&error)) {
8086                 mono_error_set_pending_exception (&error);
8087                 return FALSE;
8088         }
8089         if (!cinfo)
8090                 return FALSE;
8091         found = mono_custom_attrs_has_attr (cinfo, attr_class);
8092         if (!cinfo->cached)
8093                 mono_custom_attrs_free (cinfo);
8094         return found;
8095 }
8096
8097 ICALL_EXPORT MonoArray*
8098 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8099 {
8100         MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8101         MonoArray *res;
8102         MonoError error;
8103
8104         if (attr_class) {
8105                 mono_class_init_checked (attr_class, &error);
8106                 if (mono_error_set_pending_exception (&error))
8107                         return NULL;
8108         }
8109
8110         res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8111         if (!mono_error_ok (&error)) {
8112                 mono_error_set_pending_exception (&error);
8113                 return NULL;
8114         }
8115
8116         return res;
8117 }
8118
8119 ICALL_EXPORT MonoArray*
8120 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8121 {
8122         MonoError error;
8123         MonoArray *result;
8124         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8125         mono_error_set_pending_exception (&error);
8126         return result;
8127 }
8128
8129
8130 ICALL_EXPORT MonoString*
8131 ves_icall_Mono_Runtime_GetDisplayName (void)
8132 {
8133         char *info;
8134         MonoString *display_name;
8135
8136         info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8137         display_name = mono_string_new (mono_domain_get (), info);
8138         g_free (info);
8139         return display_name;
8140 }
8141
8142 ICALL_EXPORT MonoString*
8143 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8144 {
8145         MonoError error;
8146         MonoString *message;
8147         guint32 ret;
8148         gunichar2 buf[256];
8149         
8150         ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8151                              FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8152                              buf, 255, NULL);
8153         if (ret == 0) {
8154                 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8155         } else {
8156                 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8157                 if (mono_error_set_pending_exception (&error))
8158                         return NULL;
8159         }
8160         
8161         return message;
8162 }
8163
8164 ICALL_EXPORT gpointer
8165 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8166 {
8167         return GetCurrentProcess ();
8168 }
8169
8170 ICALL_EXPORT MonoBoolean
8171 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8172 {
8173         return GetExitCodeProcess (handle, (guint32*) exitcode);
8174 }
8175
8176 ICALL_EXPORT MonoBoolean
8177 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8178 {
8179 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8180         return CloseHandle (handle);
8181 #else
8182         return CloseProcess (handle);
8183 #endif
8184 }
8185
8186 ICALL_EXPORT MonoBoolean
8187 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8188 {
8189         return TerminateProcess (handle, exitcode);
8190 }
8191
8192 ICALL_EXPORT gint32
8193 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8194 {
8195         return WaitForInputIdle (handle, milliseconds);
8196 }
8197
8198 ICALL_EXPORT MonoBoolean
8199 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8200 {
8201         return GetProcessWorkingSetSize (handle, min, max);
8202 }
8203
8204 ICALL_EXPORT MonoBoolean
8205 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8206 {
8207         return SetProcessWorkingSetSize (handle, min, max);
8208 }
8209
8210 ICALL_EXPORT MonoBoolean
8211 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8212 {
8213         return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8214 }
8215
8216 ICALL_EXPORT gint32
8217 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8218 {
8219         return mono_process_current_pid ();
8220 }
8221
8222 ICALL_EXPORT gint32
8223 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8224 {
8225         return GetPriorityClass (handle);
8226 }
8227
8228 ICALL_EXPORT MonoBoolean
8229 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8230 {
8231         return SetPriorityClass (handle, priorityClass);
8232 }
8233
8234 #ifndef DISABLE_ICALL_TABLES
8235
8236 #define ICALL_TYPE(id,name,first)
8237 #define ICALL(id,name,func) Icall_ ## id,
8238
8239 enum {
8240 #include "metadata/icall-def.h"
8241         Icall_last
8242 };
8243
8244 #undef ICALL_TYPE
8245 #undef ICALL
8246 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8247 #define ICALL(id,name,func)
8248 enum {
8249 #include "metadata/icall-def.h"
8250         Icall_type_num
8251 };
8252
8253 #undef ICALL_TYPE
8254 #undef ICALL
8255 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8256 #define ICALL(id,name,func)
8257 typedef struct {
8258         guint16 first_icall;
8259 } IcallTypeDesc;
8260
8261 static const IcallTypeDesc
8262 icall_type_descs [] = {
8263 #include "metadata/icall-def.h"
8264         {Icall_last}
8265 };
8266
8267 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8268
8269 #undef ICALL_TYPE
8270 #define ICALL_TYPE(id,name,first)
8271 #undef ICALL
8272
8273 #ifdef HAVE_ARRAY_ELEM_INIT
8274 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8275 #define MSGSTRFIELD1(line) str##line
8276
8277 static const struct msgstrtn_t {
8278 #define ICALL(id,name,func)
8279 #undef ICALL_TYPE
8280 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8281 #include "metadata/icall-def.h"
8282 #undef ICALL_TYPE
8283 } icall_type_names_str = {
8284 #define ICALL_TYPE(id,name,first) (name),
8285 #include "metadata/icall-def.h"
8286 #undef ICALL_TYPE
8287 };
8288 static const guint16 icall_type_names_idx [] = {
8289 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8290 #include "metadata/icall-def.h"
8291 #undef ICALL_TYPE
8292 };
8293 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8294
8295 static const struct msgstr_t {
8296 #undef ICALL
8297 #define ICALL_TYPE(id,name,first)
8298 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8299 #include "metadata/icall-def.h"
8300 #undef ICALL
8301 } icall_names_str = {
8302 #define ICALL(id,name,func) (name),
8303 #include "metadata/icall-def.h"
8304 #undef ICALL
8305 };
8306 static const guint16 icall_names_idx [] = {
8307 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8308 #include "metadata/icall-def.h"
8309 #undef ICALL
8310 };
8311 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8312
8313 #else
8314
8315 #undef ICALL_TYPE
8316 #undef ICALL
8317 #define ICALL_TYPE(id,name,first) name,
8318 #define ICALL(id,name,func)
8319 static const char* const
8320 icall_type_names [] = {
8321 #include "metadata/icall-def.h"
8322         NULL
8323 };
8324
8325 #define icall_type_name_get(id) (icall_type_names [(id)])
8326
8327 #undef ICALL_TYPE
8328 #undef ICALL
8329 #define ICALL_TYPE(id,name,first)
8330 #define ICALL(id,name,func) name,
8331 static const char* const
8332 icall_names [] = {
8333 #include "metadata/icall-def.h"
8334         NULL
8335 };
8336 #define icall_name_get(id) icall_names [(id)]
8337
8338 #endif /* !HAVE_ARRAY_ELEM_INIT */
8339
8340 #undef ICALL_TYPE
8341 #undef ICALL
8342 #define ICALL_TYPE(id,name,first)
8343 #define ICALL(id,name,func) func,
8344 static const gconstpointer
8345 icall_functions [] = {
8346 #include "metadata/icall-def.h"
8347         NULL
8348 };
8349
8350 #ifdef ENABLE_ICALL_SYMBOL_MAP
8351 #undef ICALL_TYPE
8352 #undef ICALL
8353 #define ICALL_TYPE(id,name,first)
8354 #define ICALL(id,name,func) #func,
8355 static const gconstpointer
8356 icall_symbols [] = {
8357 #include "metadata/icall-def.h"
8358         NULL
8359 };
8360 #endif
8361
8362 #endif /* DISABLE_ICALL_TABLES */
8363
8364 static mono_mutex_t icall_mutex;
8365 static GHashTable *icall_hash = NULL;
8366 static GHashTable *jit_icall_hash_name = NULL;
8367 static GHashTable *jit_icall_hash_addr = NULL;
8368
8369 void
8370 mono_icall_init (void)
8371 {
8372 #ifndef DISABLE_ICALL_TABLES
8373         int i = 0;
8374
8375         /* check that tables are sorted: disable in release */
8376         if (TRUE) {
8377                 int j;
8378                 const char *prev_class = NULL;
8379                 const char *prev_method;
8380                 
8381                 for (i = 0; i < Icall_type_num; ++i) {
8382                         const IcallTypeDesc *desc;
8383                         int num_icalls;
8384                         prev_method = NULL;
8385                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8386                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8387                         prev_class = icall_type_name_get (i);
8388                         desc = &icall_type_descs [i];
8389                         num_icalls = icall_desc_num_icalls (desc);
8390                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8391                         for (j = 0; j < num_icalls; ++j) {
8392                                 const char *methodn = icall_name_get (desc->first_icall + j);
8393                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
8394                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
8395                                 prev_method = methodn;
8396                         }
8397                 }
8398         }
8399 #endif
8400
8401         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8402         mono_os_mutex_init (&icall_mutex);
8403 }
8404
8405 static void
8406 mono_icall_lock (void)
8407 {
8408         mono_locks_os_acquire (&icall_mutex, IcallLock);
8409 }
8410
8411 static void
8412 mono_icall_unlock (void)
8413 {
8414         mono_locks_os_release (&icall_mutex, IcallLock);
8415 }
8416
8417 void
8418 mono_icall_cleanup (void)
8419 {
8420         g_hash_table_destroy (icall_hash);
8421         g_hash_table_destroy (jit_icall_hash_name);
8422         g_hash_table_destroy (jit_icall_hash_addr);
8423         mono_os_mutex_destroy (&icall_mutex);
8424 }
8425
8426 /**
8427  * mono_add_internal_call:
8428  * @name: method specification to surface to the managed world
8429  * @method: pointer to a C method to invoke when the method is called
8430  *
8431  * This method surfaces the C function pointed by @method as a method
8432  * that has been surfaced in managed code with the method specified in
8433  * @name as an internal call.
8434  *
8435  * Internal calls are surfaced to all app domains loaded and they are
8436  * accessibly by a type with the specified name.
8437  *
8438  * You must provide a fully qualified type name, that is namespaces
8439  * and type name, followed by a colon and the method name, with an
8440  * optional signature to bind.
8441  *
8442  * For example, the following are all valid declarations:
8443  *
8444  * "MyApp.Services.ScriptService:Accelerate"
8445  * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8446  *
8447  * You use method parameters in cases where there might be more than
8448  * one surface method to managed code.  That way you can register different
8449  * internal calls for different method overloads.
8450  *
8451  * The internal calls are invoked with no marshalling.   This means that .NET
8452  * types like System.String are exposed as `MonoString *` parameters.   This is
8453  * different than the way that strings are surfaced in P/Invoke.
8454  *
8455  * For more information on how the parameters are marshalled, see the
8456  * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8457  * page.
8458  *
8459  * See the <a  href="mono-api-methods.html#method-desc">Method Description</a>
8460  * reference for more information on the format of method descriptions.
8461  */
8462 void
8463 mono_add_internal_call (const char *name, gconstpointer method)
8464 {
8465         mono_icall_lock ();
8466
8467         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8468
8469         mono_icall_unlock ();
8470 }
8471
8472 #ifndef DISABLE_ICALL_TABLES
8473
8474 #ifdef HAVE_ARRAY_ELEM_INIT
8475 static int
8476 compare_method_imap (const void *key, const void *elem)
8477 {
8478         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8479         return strcmp (key, method_name);
8480 }
8481
8482 static gpointer
8483 find_method_icall (const IcallTypeDesc *imap, const char *name)
8484 {
8485         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);
8486         if (!nameslot)
8487                 return NULL;
8488         return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8489 }
8490
8491 static int
8492 compare_class_imap (const void *key, const void *elem)
8493 {
8494         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8495         return strcmp (key, class_name);
8496 }
8497
8498 static const IcallTypeDesc*
8499 find_class_icalls (const char *name)
8500 {
8501         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);
8502         if (!nameslot)
8503                 return NULL;
8504         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8505 }
8506
8507 #else /* HAVE_ARRAY_ELEM_INIT */
8508
8509 static int
8510 compare_method_imap (const void *key, const void *elem)
8511 {
8512         const char** method_name = (const char**)elem;
8513         return strcmp (key, *method_name);
8514 }
8515
8516 static gpointer
8517 find_method_icall (const IcallTypeDesc *imap, const char *name)
8518 {
8519         const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8520         if (!nameslot)
8521                 return NULL;
8522         return (gpointer)icall_functions [(nameslot - icall_names)];
8523 }
8524
8525 static int
8526 compare_class_imap (const void *key, const void *elem)
8527 {
8528         const char** class_name = (const char**)elem;
8529         return strcmp (key, *class_name);
8530 }
8531
8532 static const IcallTypeDesc*
8533 find_class_icalls (const char *name)
8534 {
8535         const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8536         if (!nameslot)
8537                 return NULL;
8538         return &icall_type_descs [nameslot - icall_type_names];
8539 }
8540
8541 #endif /* HAVE_ARRAY_ELEM_INIT */
8542
8543 #endif /* DISABLE_ICALL_TABLES */
8544
8545 /* 
8546  * we should probably export this as an helper (handle nested types).
8547  * Returns the number of chars written in buf.
8548  */
8549 static int
8550 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8551 {
8552         int nspacelen, cnamelen;
8553         nspacelen = strlen (klass->name_space);
8554         cnamelen = strlen (klass->name);
8555         if (nspacelen + cnamelen + 2 > bufsize)
8556                 return 0;
8557         if (nspacelen) {
8558                 memcpy (buf, klass->name_space, nspacelen);
8559                 buf [nspacelen ++] = '.';
8560         }
8561         memcpy (buf + nspacelen, klass->name, cnamelen);
8562         buf [nspacelen + cnamelen] = 0;
8563         return nspacelen + cnamelen;
8564 }
8565
8566 #ifdef DISABLE_ICALL_TABLES
8567 static void
8568 no_icall_table (void)
8569 {
8570         g_assert_not_reached ();
8571 }
8572 #endif
8573
8574 gpointer
8575 mono_lookup_internal_call (MonoMethod *method)
8576 {
8577         char *sigstart;
8578         char *tmpsig;
8579         char mname [2048];
8580         int typelen = 0, mlen, siglen;
8581         gpointer res;
8582 #ifndef DISABLE_ICALL_TABLES
8583         const IcallTypeDesc *imap = NULL;
8584 #endif
8585
8586         g_assert (method != NULL);
8587
8588         if (method->is_inflated)
8589                 method = ((MonoMethodInflated *) method)->declaring;
8590
8591         if (method->klass->nested_in) {
8592                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8593                 if (!pos)
8594                         return NULL;
8595
8596                 mname [pos++] = '/';
8597                 mname [pos] = 0;
8598
8599                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8600                 if (!typelen)
8601                         return NULL;
8602
8603                 typelen += pos;
8604         } else {
8605                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8606                 if (!typelen)
8607                         return NULL;
8608         }
8609
8610 #ifndef DISABLE_ICALL_TABLES
8611         imap = find_class_icalls (mname);
8612 #endif
8613
8614         mname [typelen] = ':';
8615         mname [typelen + 1] = ':';
8616
8617         mlen = strlen (method->name);
8618         memcpy (mname + typelen + 2, method->name, mlen);
8619         sigstart = mname + typelen + 2 + mlen;
8620         *sigstart = 0;
8621
8622         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8623         siglen = strlen (tmpsig);
8624         if (typelen + mlen + siglen + 6 > sizeof (mname))
8625                 return NULL;
8626         sigstart [0] = '(';
8627         memcpy (sigstart + 1, tmpsig, siglen);
8628         sigstart [siglen + 1] = ')';
8629         sigstart [siglen + 2] = 0;
8630         g_free (tmpsig);
8631         
8632         mono_icall_lock ();
8633
8634         res = g_hash_table_lookup (icall_hash, mname);
8635         if (res) {
8636                 mono_icall_unlock ();;
8637                 return res;
8638         }
8639         /* try without signature */
8640         *sigstart = 0;
8641         res = g_hash_table_lookup (icall_hash, mname);
8642         if (res) {
8643                 mono_icall_unlock ();
8644                 return res;
8645         }
8646
8647 #ifdef DISABLE_ICALL_TABLES
8648         mono_icall_unlock ();
8649         /* Fail only when the result is actually used */
8650         /* mono_marshal_get_native_wrapper () depends on this */
8651         if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8652                 return ves_icall_System_String_ctor_RedirectToCreateString;
8653         else
8654                 return no_icall_table;
8655 #else
8656         /* it wasn't found in the static call tables */
8657         if (!imap) {
8658                 mono_icall_unlock ();
8659                 return NULL;
8660         }
8661         res = find_method_icall (imap, sigstart - mlen);
8662         if (res) {
8663                 mono_icall_unlock ();
8664                 return res;
8665         }
8666         /* try _with_ signature */
8667         *sigstart = '(';
8668         res = find_method_icall (imap, sigstart - mlen);
8669         if (res) {
8670                 mono_icall_unlock ();
8671                 return res;
8672         }
8673
8674         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8675         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8676         g_print ("The out of sync library is: %s\n", method->klass->image->name);
8677         g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8678         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");
8679         g_print ("If you see other errors or faults after this message they are probably related\n");
8680         g_print ("and you need to fix your mono install first.\n");
8681
8682         mono_icall_unlock ();
8683
8684         return NULL;
8685 #endif
8686 }
8687
8688 #ifdef ENABLE_ICALL_SYMBOL_MAP
8689 static int
8690 func_cmp (gconstpointer key, gconstpointer p)
8691 {
8692         return (gsize)key - (gsize)*(gsize*)p;
8693 }
8694 #endif
8695
8696 /*
8697  * mono_lookup_icall_symbol:
8698  *
8699  *   Given the icall METHOD, returns its C symbol.
8700  */
8701 const char*
8702 mono_lookup_icall_symbol (MonoMethod *m)
8703 {
8704 #ifdef DISABLE_ICALL_TABLES
8705         g_assert_not_reached ();
8706         return NULL;
8707 #else
8708 #ifdef ENABLE_ICALL_SYMBOL_MAP
8709         gpointer func;
8710         int i;
8711         gpointer slot;
8712         static gconstpointer *functions_sorted;
8713         static const char**symbols_sorted;
8714         static gboolean inited;
8715
8716         if (!inited) {
8717                 gboolean changed;
8718
8719                 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8720                 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8721                 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8722                 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8723                 /* Bubble sort the two arrays */
8724                 changed = TRUE;
8725                 while (changed) {
8726                         changed = FALSE;
8727                         for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8728                                 if (functions_sorted [i] > functions_sorted [i + 1]) {
8729                                         gconstpointer tmp;
8730
8731                                         tmp = functions_sorted [i];
8732                                         functions_sorted [i] = functions_sorted [i + 1];
8733                                         functions_sorted [i + 1] = tmp;
8734                                         tmp = symbols_sorted [i];
8735                                         symbols_sorted [i] = symbols_sorted [i + 1];
8736                                         symbols_sorted [i + 1] = tmp;
8737                                         changed = TRUE;
8738                                 }
8739                         }
8740                 }
8741         }
8742
8743         func = mono_lookup_internal_call (m);
8744         if (!func)
8745                 return NULL;
8746         slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8747         if (!slot)
8748                 return NULL;
8749         g_assert (slot);
8750         return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8751 #else
8752         fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8753         g_assert_not_reached ();
8754         return 0;
8755 #endif
8756 #endif
8757 }
8758
8759 static MonoType*
8760 type_from_typename (char *type_name)
8761 {
8762         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
8763
8764         if (!strcmp (type_name, "int"))
8765                 klass = mono_defaults.int_class;
8766         else if (!strcmp (type_name, "ptr"))
8767                 klass = mono_defaults.int_class;
8768         else if (!strcmp (type_name, "void"))
8769                 klass = mono_defaults.void_class;
8770         else if (!strcmp (type_name, "int32"))
8771                 klass = mono_defaults.int32_class;
8772         else if (!strcmp (type_name, "uint32"))
8773                 klass = mono_defaults.uint32_class;
8774         else if (!strcmp (type_name, "int8"))
8775                 klass = mono_defaults.sbyte_class;
8776         else if (!strcmp (type_name, "uint8"))
8777                 klass = mono_defaults.byte_class;
8778         else if (!strcmp (type_name, "int16"))
8779                 klass = mono_defaults.int16_class;
8780         else if (!strcmp (type_name, "uint16"))
8781                 klass = mono_defaults.uint16_class;
8782         else if (!strcmp (type_name, "long"))
8783                 klass = mono_defaults.int64_class;
8784         else if (!strcmp (type_name, "ulong"))
8785                 klass = mono_defaults.uint64_class;
8786         else if (!strcmp (type_name, "float"))
8787                 klass = mono_defaults.single_class;
8788         else if (!strcmp (type_name, "double"))
8789                 klass = mono_defaults.double_class;
8790         else if (!strcmp (type_name, "object"))
8791                 klass = mono_defaults.object_class;
8792         else if (!strcmp (type_name, "obj"))
8793                 klass = mono_defaults.object_class;
8794         else if (!strcmp (type_name, "string"))
8795                 klass = mono_defaults.string_class;
8796         else if (!strcmp (type_name, "bool"))
8797                 klass = mono_defaults.boolean_class;
8798         else if (!strcmp (type_name, "boolean"))
8799                 klass = mono_defaults.boolean_class;
8800         else {
8801                 g_error ("%s", type_name);
8802                 g_assert_not_reached ();
8803         }
8804         return &klass->byval_arg;
8805 }
8806
8807 /**
8808  * LOCKING: Take the corlib image lock.
8809  */
8810 MonoMethodSignature*
8811 mono_create_icall_signature (const char *sigstr)
8812 {
8813         gchar **parts;
8814         int i, len;
8815         gchar **tmp;
8816         MonoMethodSignature *res, *res2;
8817         MonoImage *corlib = mono_defaults.corlib;
8818
8819         mono_image_lock (corlib);
8820         res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8821         mono_image_unlock (corlib);
8822
8823         if (res)
8824                 return res;
8825
8826         parts = g_strsplit (sigstr, " ", 256);
8827
8828         tmp = parts;
8829         len = 0;
8830         while (*tmp) {
8831                 len ++;
8832                 tmp ++;
8833         }
8834
8835         res = mono_metadata_signature_alloc (corlib, len - 1);
8836         res->pinvoke = 1;
8837
8838 #ifdef HOST_WIN32
8839         /* 
8840          * Under windows, the default pinvoke calling convention is STDCALL but
8841          * we need CDECL.
8842          */
8843         res->call_convention = MONO_CALL_C;
8844 #endif
8845
8846         res->ret = type_from_typename (parts [0]);
8847         for (i = 1; i < len; ++i) {
8848                 res->params [i - 1] = type_from_typename (parts [i]);
8849         }
8850
8851         g_strfreev (parts);
8852
8853         mono_image_lock (corlib);
8854         res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8855         if (res2)
8856                 res = res2; /*Value is allocated in the image pool*/
8857         else
8858                 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8859         mono_image_unlock (corlib);
8860
8861         return res;
8862 }
8863
8864 MonoJitICallInfo *
8865 mono_find_jit_icall_by_name (const char *name)
8866 {
8867         MonoJitICallInfo *info;
8868         g_assert (jit_icall_hash_name);
8869
8870         mono_icall_lock ();
8871         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8872         mono_icall_unlock ();
8873         return info;
8874 }
8875
8876 MonoJitICallInfo *
8877 mono_find_jit_icall_by_addr (gconstpointer addr)
8878 {
8879         MonoJitICallInfo *info;
8880         g_assert (jit_icall_hash_addr);
8881
8882         mono_icall_lock ();
8883         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8884         mono_icall_unlock ();
8885
8886         return info;
8887 }
8888
8889 /*
8890  * mono_get_jit_icall_info:
8891  *
8892  *   Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8893  * caller should access it while holding the icall lock.
8894  */
8895 GHashTable*
8896 mono_get_jit_icall_info (void)
8897 {
8898         return jit_icall_hash_name;
8899 }
8900
8901 /*
8902  * mono_lookup_jit_icall_symbol:
8903  *
8904  *   Given the jit icall NAME, returns its C symbol if possible, or NULL.
8905  */
8906 const char*
8907 mono_lookup_jit_icall_symbol (const char *name)
8908 {
8909         MonoJitICallInfo *info;
8910         const char *res = NULL;
8911
8912         mono_icall_lock ();
8913         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8914         if (info)
8915                 res = info->c_symbol;
8916         mono_icall_unlock ();
8917         return res;
8918 }
8919
8920 void
8921 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8922 {
8923         mono_icall_lock ();
8924         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8925         mono_icall_unlock ();
8926 }
8927
8928 /*
8929  * 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
8930  * icalls without wrappers in some cases.
8931  */
8932 MonoJitICallInfo *
8933 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8934 {
8935         MonoJitICallInfo *info;
8936         
8937         g_assert (func);
8938         g_assert (name);
8939
8940         mono_icall_lock ();
8941
8942         if (!jit_icall_hash_name) {
8943                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8944                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8945         }
8946
8947         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8948                 g_warning ("jit icall already defined \"%s\"\n", name);
8949                 g_assert_not_reached ();
8950         }
8951
8952         info = g_new0 (MonoJitICallInfo, 1);
8953         
8954         info->name = name;
8955         info->func = func;
8956         info->sig = sig;
8957         info->c_symbol = c_symbol;
8958         info->no_raise = no_raise;
8959
8960         if (is_save) {
8961                 info->wrapper = func;
8962         } else {
8963                 info->wrapper = NULL;
8964         }
8965
8966         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8967         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8968
8969         mono_icall_unlock ();
8970         return info;
8971 }
8972
8973 MonoJitICallInfo *
8974 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8975 {
8976         return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);
8977 }
8978