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