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