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