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