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