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