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