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