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