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