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