4376addf3e091105345b82a2cc53daca0e94154f
[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_for_class_failure (error, 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_for_class_failure (&error, klass);
4325
4326 failure:
4327         if (properties)
4328                 g_hash_table_destroy (properties);
4329         if (name)
4330                 g_free (propname);
4331         mono_ptr_array_destroy (tmp_array);
4332
4333         mono_error_set_pending_exception (&error);
4334
4335         return NULL;
4336 }
4337
4338 static guint
4339 event_hash (gconstpointer data)
4340 {
4341         MonoEvent *event = (MonoEvent*)data;
4342
4343         return g_str_hash (event->name);
4344 }
4345
4346 static gboolean
4347 event_equal (MonoEvent *event1, MonoEvent *event2)
4348 {
4349         // Events are hide-by-name
4350         return g_str_equal (event1->name, event2->name);
4351 }
4352
4353 ICALL_EXPORT MonoArray*
4354 ves_icall_RuntimeType_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4355 {
4356         MonoError error;
4357         MonoDomain *domain; 
4358         MonoClass *startklass, *klass;
4359         MonoArray *res;
4360         MonoMethod *method;
4361         MonoEvent *event;
4362         int i, match;
4363         gpointer iter;
4364         char *utf8_name = NULL;
4365         int (*compare_func) (const char *s1, const char *s2) = NULL;    
4366         GHashTable *events = NULL;
4367         MonoPtrArray tmp_array;
4368
4369         mono_error_init (&error);
4370         
4371         domain = mono_object_domain (type);
4372         if (type->type->byref) {
4373                 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), 0, &error);
4374                 mono_error_set_pending_exception (&error);
4375                 return res;
4376         }
4377
4378         mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4379
4380         klass = startklass = mono_class_from_mono_type (type->type);
4381
4382         events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4383 handle_parent:
4384         mono_class_setup_methods (klass);
4385         mono_class_setup_vtable (klass);
4386         if (mono_class_has_failure (klass))
4387                 goto loader_error;
4388
4389         iter = NULL;
4390         while ((event = mono_class_get_events (klass, &iter))) {
4391                 match = 0;
4392                 method = event->add;
4393                 if (!method)
4394                         method = event->remove;
4395                 if (!method)
4396                         method = event->raise;
4397                 if (method) {
4398                         if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4399                                 if (bflags & BFLAGS_Public)
4400                                         match++;
4401                         } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4402                                 if (bflags & BFLAGS_NonPublic)
4403                                         match++;
4404                         }
4405                 }
4406                 else
4407                         if (bflags & BFLAGS_NonPublic)
4408                                 match ++;
4409                 if (!match)
4410                         continue;
4411                 match = 0;
4412                 if (method) {
4413                         if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4414                                 if (bflags & BFLAGS_Static)
4415                                         if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4416                                                 match++;
4417                         } else {
4418                                 if (bflags & BFLAGS_Instance)
4419                                         match++;
4420                         }
4421                 }
4422                 else
4423                         if (bflags & BFLAGS_Instance)
4424                                 match ++;
4425                 if (!match)
4426                         continue;
4427
4428                 if (name != NULL) {
4429                         if (utf8_name == NULL) {
4430                                 utf8_name = mono_string_to_utf8_checked (name, &error);
4431                                 if (!is_ok (&error))
4432                                         goto failure;
4433                                 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4434                         }
4435
4436                         if (compare_func (event->name, utf8_name))
4437                                 continue;
4438                 }               
4439
4440                 if (g_hash_table_lookup (events, event))
4441                         continue;
4442
4443                 MonoReflectionEvent *ev_obj;
4444                 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4445                 if (!ev_obj)
4446                         goto failure;
4447                 mono_ptr_array_append (tmp_array, ev_obj);
4448
4449                 g_hash_table_insert (events, event, event);
4450         }
4451         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4452                 goto handle_parent;
4453
4454         g_hash_table_destroy (events);
4455
4456         res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array), &error);
4457         if (!is_ok (&error))
4458                 goto failure;
4459
4460         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4461                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4462
4463         mono_ptr_array_destroy (tmp_array);
4464
4465         if (utf8_name != NULL)
4466                 g_free (utf8_name);
4467
4468         return res;
4469
4470 loader_error:
4471         if (mono_class_has_failure (klass))
4472                 mono_error_set_for_class_failure (&error, klass);
4473
4474 failure:
4475         
4476         if (events != NULL)
4477                 g_hash_table_destroy (events);
4478         if (utf8_name != NULL)
4479                 g_free (utf8_name);
4480
4481         mono_ptr_array_destroy (tmp_array);
4482
4483         mono_error_set_pending_exception (&error);
4484         return NULL;
4485 }
4486
4487 ICALL_EXPORT MonoArray*
4488 ves_icall_RuntimeType_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4489 {
4490         MonoError error;
4491         MonoReflectionType *rt;
4492         MonoDomain *domain; 
4493         MonoClass *klass;
4494         MonoArray *res = NULL;
4495         int i, match;
4496         MonoClass *nested;
4497         gpointer iter;
4498         char *str = NULL;
4499         MonoPtrArray tmp_array;
4500
4501         mono_error_init (&error);
4502
4503         domain = ((MonoObject *)type)->vtable->domain;
4504         if (type->type->byref) {
4505                 MonoArray *result = mono_array_new_cached (domain, mono_defaults.runtimetype_class, 0, &error);
4506                 mono_error_set_pending_exception (&error);
4507                 return result;
4508         }
4509         klass = mono_class_from_mono_type (type->type);
4510
4511         /*
4512          * If a nested type is generic, return its generic type definition.
4513          * Note that this means that the return value is essentially the set
4514          * of nested types of the generic type definition of @klass.
4515          *
4516          * A note in MSDN claims that a generic type definition can have
4517          * nested types that aren't generic.  In any case, the container of that
4518          * nested type would be the generic type definition.
4519          */
4520         if (klass->generic_class)
4521                 klass = klass->generic_class->container_class;
4522
4523         mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4524         iter = NULL;
4525         while ((nested = mono_class_get_nested_types (klass, &iter))) {
4526                 match = 0;
4527                 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4528                         if (bflags & BFLAGS_Public)
4529                                 match++;
4530                 } else {
4531                         if (bflags & BFLAGS_NonPublic)
4532                                 match++;
4533                 }
4534                 if (!match)
4535                         continue;
4536
4537                 if (name != NULL) {
4538                         if (str == NULL) {
4539                                 str = mono_string_to_utf8_checked (name, &error);
4540                                 if (!is_ok (&error))
4541                                         goto leave;
4542                                 mono_identifier_unescape_type_name_chars (str);
4543                         }
4544
4545                         if (strcmp (nested->name, str))
4546                                 continue;
4547                 }
4548
4549                 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4550                 if (!is_ok (&error))
4551                         goto leave;
4552
4553                 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4554         }
4555
4556         res = mono_array_new_cached (domain, mono_defaults.runtimetype_class, mono_ptr_array_size (tmp_array), &error);
4557         if (!is_ok (&error))
4558                 goto leave;
4559
4560         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4561                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4562
4563 leave:
4564         mono_ptr_array_destroy (tmp_array);
4565
4566         g_free (str);
4567
4568         mono_error_set_pending_exception (&error);
4569         return res;
4570 }
4571
4572 ICALL_EXPORT MonoReflectionType*
4573 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4574 {
4575         MonoError error;
4576         MonoReflectionType *ret;
4577         gchar *str;
4578         MonoType *type = NULL;
4579         MonoTypeNameParse info;
4580         gboolean type_resolve;
4581
4582         /* On MS.NET, this does not fire a TypeResolve event */
4583         type_resolve = TRUE;
4584         str = mono_string_to_utf8_checked (name, &error);
4585         if (mono_error_set_pending_exception (&error))
4586                 return NULL;
4587         /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4588         if (!mono_reflection_parse_type (str, &info)) {
4589                 g_free (str);
4590                 mono_reflection_free_type_info (&info);
4591                 if (throwOnError) {
4592                         mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4593                         return NULL;
4594                 }
4595                 /*g_print ("failed parse\n");*/
4596                 return NULL;
4597         }
4598
4599         if (info.assembly.name) {
4600                 g_free (str);
4601                 mono_reflection_free_type_info (&info);
4602                 if (throwOnError) {
4603                         /* 1.0 and 2.0 throw different exceptions */
4604                         if (mono_defaults.generic_ilist_class)
4605                                 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4606                         else
4607                                 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4608                         return NULL;
4609                 }
4610                 return NULL;
4611         }
4612
4613         if (module != NULL) {
4614                 if (module->image) {
4615                         type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4616                         if (!is_ok (&error)) {
4617                                 g_free (str);
4618                                 mono_reflection_free_type_info (&info);
4619                                 mono_error_set_pending_exception (&error);
4620                                 return NULL;
4621                         }
4622                 } else
4623                         type = NULL;
4624         }
4625         else
4626                 if (assembly_is_dynamic (assembly->assembly)) {
4627                         /* Enumerate all modules */
4628                         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4629                         int i;
4630
4631                         type = NULL;
4632                         if (abuilder->modules) {
4633                                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4634                                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4635                                         type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4636                                         if (!is_ok (&error)) {
4637                                                 g_free (str);
4638                                                 mono_reflection_free_type_info (&info);
4639                                                 mono_error_set_pending_exception (&error);
4640                                                 return NULL;
4641                                         }
4642                                         if (type)
4643                                                 break;
4644                                 }
4645                         }
4646
4647                         if (!type && abuilder->loaded_modules) {
4648                                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4649                                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4650                                         type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4651                                         if (!is_ok (&error)) {
4652                                                 g_free (str);
4653                                                 mono_reflection_free_type_info (&info);
4654                                                 mono_error_set_pending_exception (&error);
4655                                                 return NULL;
4656                                         }
4657                                         if (type)
4658                                                 break;
4659                                 }
4660                         }
4661                 }
4662                 else {
4663                         type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4664                         if (!is_ok (&error)) {
4665                                 g_free (str);
4666                                 mono_reflection_free_type_info (&info);
4667                                 mono_error_set_pending_exception (&error);
4668                                 return NULL;
4669                         }
4670                 }
4671         g_free (str);
4672         mono_reflection_free_type_info (&info);
4673         if (!type) {
4674                 MonoException *e = NULL;
4675                 
4676                 if (throwOnError)
4677                         e = mono_get_exception_type_load (name, NULL);
4678
4679                 if (e != NULL)
4680                         mono_set_pending_exception (e);
4681                 return NULL;
4682         }
4683
4684         if (type->type == MONO_TYPE_CLASS) {
4685                 MonoClass *klass = mono_type_get_class (type);
4686
4687                 /* need to report exceptions ? */
4688                 if (throwOnError && mono_class_has_failure (klass)) {
4689                         /* report SecurityException (or others) that occured when loading the assembly */
4690                         MonoException *exc = mono_class_get_exception_for_failure (klass);
4691                         mono_set_pending_exception (exc);
4692                         return NULL;
4693                 }
4694         }
4695
4696         /* g_print ("got it\n"); */
4697         ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4698         mono_error_set_pending_exception (&error);
4699
4700         return ret;
4701 }
4702
4703 static gboolean
4704 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4705 {
4706         gchar *content;
4707         gchar *shadow_ini_file;
4708         gsize len;
4709
4710         /* Check for shadow-copied assembly */
4711         if (mono_is_shadow_copy_enabled (domain, dirname)) {
4712                 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4713                 content = NULL;
4714                 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4715                         !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4716                         if (content) {
4717                                 g_free (content);
4718                                 content = NULL;
4719                         }
4720                 }
4721                 g_free (shadow_ini_file);
4722                 if (content != NULL) {
4723                         if (*filename)
4724                                 g_free (*filename);
4725                         *filename = content;
4726                         return TRUE;
4727                 }
4728         }
4729         return FALSE;
4730 }
4731
4732 ICALL_EXPORT MonoString *
4733 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4734 {
4735         MonoDomain *domain = mono_object_domain (assembly); 
4736         MonoAssembly *mass = assembly->assembly;
4737         MonoString *res = NULL;
4738         gchar *uri;
4739         gchar *absolute;
4740         gchar *dirname;
4741         
4742         if (g_path_is_absolute (mass->image->name)) {
4743                 absolute = g_strdup (mass->image->name);
4744                 dirname = g_path_get_dirname (absolute);
4745         } else {
4746                 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4747                 dirname = g_strdup (mass->basedir);
4748         }
4749
4750         replace_shadow_path (domain, dirname, &absolute);
4751         g_free (dirname);
4752 #if HOST_WIN32
4753         {
4754                 gint i;
4755                 for (i = strlen (absolute) - 1; i >= 0; i--)
4756                         if (absolute [i] == '\\')
4757                                 absolute [i] = '/';
4758         }
4759 #endif
4760         if (escaped) {
4761                 uri = g_filename_to_uri (absolute, NULL, NULL);
4762         } else {
4763                 const char *prepend = "file://";
4764 #if HOST_WIN32
4765                 if (*absolute == '/' && *(absolute + 1) == '/') {
4766                         prepend = "file:";
4767                 } else {
4768                         prepend = "file:///";
4769                 }
4770 #endif
4771                 uri = g_strconcat (prepend, absolute, NULL);
4772         }
4773
4774         if (uri) {
4775                 res = mono_string_new (domain, uri);
4776                 g_free (uri);
4777         }
4778         g_free (absolute);
4779         return res;
4780 }
4781
4782 ICALL_EXPORT MonoBoolean
4783 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4784 {
4785         MonoAssembly *mass = assembly->assembly;
4786
4787         return mass->in_gac;
4788 }
4789
4790 ICALL_EXPORT MonoReflectionAssembly*
4791 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4792 {
4793         MonoError error;
4794         gchar *name;
4795         MonoAssembly *res;
4796         MonoImageOpenStatus status;
4797         MonoReflectionAssembly* result = NULL;
4798         
4799         name = mono_string_to_utf8_checked (mname, &error);
4800         if (mono_error_set_pending_exception (&error))
4801                 return NULL;
4802         res = mono_assembly_load_with_partial_name (name, &status);
4803
4804         g_free (name);
4805
4806         if (res == NULL)
4807                 return NULL;
4808         result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4809         if (!result)
4810                 mono_error_set_pending_exception (&error);
4811         return result;
4812 }
4813
4814 ICALL_EXPORT MonoString *
4815 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4816 {
4817         MonoDomain *domain = mono_object_domain (assembly); 
4818         MonoString *res;
4819
4820         res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4821
4822         return res;
4823 }
4824
4825 ICALL_EXPORT MonoBoolean
4826 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4827 {
4828         return assembly->assembly->ref_only;
4829 }
4830
4831 ICALL_EXPORT MonoString *
4832 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4833 {
4834         MonoDomain *domain = mono_object_domain (assembly); 
4835
4836         return mono_string_new (domain, assembly->assembly->image->version);
4837 }
4838
4839 ICALL_EXPORT MonoReflectionMethod*
4840 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly) 
4841 {
4842         MonoError error;
4843         MonoReflectionMethod *res = NULL;
4844         MonoMethod *method;
4845
4846         guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4847
4848         if (!token)
4849                 return NULL;
4850         method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4851         if (!mono_error_ok (&error))
4852                 goto leave;
4853
4854         res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4855
4856 leave:
4857         if (!mono_error_ok (&error))
4858                 mono_error_set_pending_exception (&error);
4859         return res;
4860 }
4861
4862 ICALL_EXPORT MonoReflectionModule*
4863 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly) 
4864 {
4865         MonoError error;
4866         MonoReflectionModule *result = NULL;
4867         result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4868         if (!mono_error_ok (&error))
4869                 mono_error_set_pending_exception (&error);
4870         return result;
4871 }
4872
4873 ICALL_EXPORT MonoArray*
4874 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly) 
4875 {
4876         MonoError error;
4877         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4878         MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4879         if (mono_error_set_pending_exception (&error))
4880                 return NULL;
4881         int i;
4882         const char *val;
4883
4884         for (i = 0; i < table->rows; ++i) {
4885                 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4886                 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4887         }
4888         return result;
4889 }
4890
4891 static MonoObject*
4892 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4893 {
4894         static MonoMethod *create_version = NULL;
4895         MonoObject *result;
4896         gpointer args [4];
4897
4898         mono_error_init (error);
4899         
4900
4901         if (!create_version) {
4902                 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4903                 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4904                 g_assert (create_version);
4905                 mono_method_desc_free (desc);
4906         }
4907
4908         args [0] = &major;
4909         args [1] = &minor;
4910         args [2] = &build;
4911         args [3] = &revision;
4912         result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4913         return_val_if_nok (error, NULL);
4914
4915         mono_runtime_invoke_checked (create_version, result, args, error);
4916         return_val_if_nok (error, NULL);
4917
4918         return result;
4919 }
4920
4921 ICALL_EXPORT MonoArray*
4922 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly) 
4923 {
4924         MonoError error;
4925         MonoArray *result;
4926         MonoDomain *domain = mono_object_domain (assembly);
4927         int i, count = 0;
4928         static MonoMethod *create_culture = NULL;
4929         MonoImage *image = assembly->assembly->image;
4930         MonoTableInfo *t;
4931         MonoObject *o;
4932
4933         t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4934         count = t->rows;
4935
4936         result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4937         if (mono_error_set_pending_exception (&error))
4938                 return NULL;
4939
4940
4941         if (count > 0 && !create_culture) {
4942                 MonoMethodDesc *desc = mono_method_desc_new (
4943                         "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4944                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4945                 g_assert (create_culture);
4946                 mono_method_desc_free (desc);
4947         }
4948
4949         for (i = 0; i < count; i++) {
4950                 MonoObject *version;
4951                 MonoReflectionAssemblyName *aname;
4952                 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4953
4954                 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4955
4956                 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4957                         domain, mono_class_get_assembly_name_class (), &error);
4958                 if (mono_error_set_pending_exception (&error))
4959                         return NULL;
4960
4961                 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4962
4963                 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4964                 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4965                 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4966                 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4967                 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4968                 aname->versioncompat = 1; /* SameMachine (default) */
4969                 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4970
4971                 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4972                 if (mono_error_set_pending_exception (&error))
4973                         return NULL;
4974
4975                 MONO_OBJECT_SETREF (aname, version, version);
4976
4977                 if (create_culture) {
4978                         gpointer args [2];
4979                         MonoBoolean assembly_ref = 1;
4980                         args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4981                         args [1] = &assembly_ref;
4982
4983                         o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4984                         if (mono_error_set_pending_exception (&error))
4985                                 return NULL;
4986
4987                         MONO_OBJECT_SETREF (aname, cultureInfo, o);
4988                 }
4989                 
4990                 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4991                         const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4992                         guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4993
4994                         if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4995                                 /* public key token isn't copied - the class library will 
4996                                 automatically generate it from the public key if required */
4997                                 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4998                                 if (mono_error_set_pending_exception (&error))
4999                                         return NULL;
5000
5001                                 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5002                                 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
5003                         } else {
5004                                 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
5005                                 if (mono_error_set_pending_exception (&error))
5006                                         return NULL;
5007
5008                                 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5009                                 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
5010                         }
5011                 } else {
5012                         MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
5013                         if (mono_error_set_pending_exception (&error))
5014                                 return NULL;
5015
5016                         MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5017                 }
5018                 
5019                 /* note: this function doesn't return the codebase on purpose (i.e. it can
5020                          be used under partial trust as path information isn't present). */
5021
5022                 mono_array_setref (result, i, aname);
5023         }
5024         return result;
5025 }
5026
5027 /* move this in some file in mono/util/ */
5028 static char *
5029 g_concat_dir_and_file (const char *dir, const char *file)
5030 {
5031         g_return_val_if_fail (dir != NULL, NULL);
5032         g_return_val_if_fail (file != NULL, NULL);
5033
5034         /*
5035          * If the directory name doesn't have a / on the end, we need
5036          * to add one so we get a proper path to the file
5037          */
5038         if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
5039                 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
5040         else
5041                 return g_strconcat (dir, file, NULL);
5042 }
5043
5044 ICALL_EXPORT void *
5045 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module) 
5046 {
5047         MonoError error;
5048         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5049         guint32 i;
5050         guint32 cols [MONO_MANIFEST_SIZE];
5051         guint32 impl, file_idx;
5052         const char *val;
5053         MonoImage *module;
5054
5055         char *n = mono_string_to_utf8_checked (name, &error);
5056         if (mono_error_set_pending_exception (&error))
5057                 return NULL;
5058
5059         for (i = 0; i < table->rows; ++i) {
5060                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5061                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5062                 if (strcmp (val, n) == 0)
5063                         break;
5064         }
5065         g_free (n);
5066         if (i == table->rows)
5067                 return NULL;
5068         /* FIXME */
5069         impl = cols [MONO_MANIFEST_IMPLEMENTATION];
5070         if (impl) {
5071                 /*
5072                  * this code should only be called after obtaining the 
5073                  * ResourceInfo and handling the other cases.
5074                  */
5075                 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
5076                 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
5077
5078                 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
5079                 if (!module)
5080                         return NULL;
5081         }
5082         else
5083                 module = assembly->assembly->image;
5084
5085         
5086         MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
5087         if (mono_error_set_pending_exception (&error))
5088                 return NULL;
5089         mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
5090
5091         return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
5092 }
5093
5094 ICALL_EXPORT gboolean
5095 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
5096 {
5097         MonoError error;
5098         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5099         int i;
5100         guint32 cols [MONO_MANIFEST_SIZE];
5101         guint32 file_cols [MONO_FILE_SIZE];
5102         const char *val;
5103         char *n;
5104
5105         n = mono_string_to_utf8_checked (name, &error);
5106         if (mono_error_set_pending_exception (&error))
5107                 return FALSE;
5108         for (i = 0; i < table->rows; ++i) {
5109                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5110                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5111                 if (strcmp (val, n) == 0)
5112                         break;
5113         }
5114         g_free (n);
5115         if (i == table->rows)
5116                 return FALSE;
5117
5118         if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
5119                 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
5120         }
5121         else {
5122                 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
5123                 case MONO_IMPLEMENTATION_FILE:
5124                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5125                         table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5126                         mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
5127                         val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
5128                         MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
5129                         if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
5130                                 info->location = 0;
5131                         else
5132                                 info->location = RESOURCE_LOCATION_EMBEDDED;
5133                         break;
5134
5135                 case MONO_IMPLEMENTATION_ASSEMBLYREF:
5136                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5137                         mono_assembly_load_reference (assembly->assembly->image, i - 1);
5138                         if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
5139                                 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
5140                                 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
5141                                 g_free (msg);
5142                                 mono_set_pending_exception (ex);
5143                                 return FALSE;
5144                         }
5145                         MonoReflectionAssembly *assm_obj;
5146                         assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5147                         if (!assm_obj) {
5148                                 mono_error_set_pending_exception (&error);
5149                                 return FALSE;
5150                         }
5151                         MONO_OBJECT_SETREF (info, assembly, assm_obj);
5152
5153                         /* Obtain info recursively */
5154                         ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5155                         info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5156                         break;
5157
5158                 case MONO_IMPLEMENTATION_EXP_TYPE:
5159                         g_assert_not_reached ();
5160                         break;
5161                 }
5162         }
5163
5164         return TRUE;
5165 }
5166
5167 ICALL_EXPORT MonoObject*
5168 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules) 
5169 {
5170         MonoError error;
5171         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5172         MonoArray *result = NULL;
5173         int i, count;
5174         const char *val;
5175         char *n;
5176
5177         /* check hash if needed */
5178         if (name) {
5179                 n = mono_string_to_utf8_checked (name, &error);
5180                 if (mono_error_set_pending_exception (&error))
5181                         return NULL;
5182
5183                 for (i = 0; i < table->rows; ++i) {
5184                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5185                         if (strcmp (val, n) == 0) {
5186                                 MonoString *fn;
5187                                 g_free (n);
5188                                 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5189                                 fn = mono_string_new (mono_object_domain (assembly), n);
5190                                 g_free (n);
5191                                 return (MonoObject*)fn;
5192                         }
5193                 }
5194                 g_free (n);
5195                 return NULL;
5196         }
5197
5198         count = 0;
5199         for (i = 0; i < table->rows; ++i) {
5200                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5201                         count ++;
5202         }
5203
5204         result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
5205         if (mono_error_set_pending_exception (&error))
5206                 return NULL;
5207
5208
5209         count = 0;
5210         for (i = 0; i < table->rows; ++i) {
5211                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5212                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5213                         n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5214                         mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5215                         g_free (n);
5216                         count ++;
5217                 }
5218         }
5219         return (MonoObject*)result;
5220 }
5221
5222 ICALL_EXPORT MonoArray*
5223 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5224 {
5225         MonoError error;
5226         MonoDomain *domain = mono_domain_get();
5227         MonoArray *res;
5228         MonoClass *klass;
5229         int i, j, file_count = 0;
5230         MonoImage **modules;
5231         guint32 module_count, real_module_count;
5232         MonoTableInfo *table;
5233         guint32 cols [MONO_FILE_SIZE];
5234         MonoImage *image = assembly->assembly->image;
5235
5236         g_assert (image != NULL);
5237         g_assert (!assembly_is_dynamic (assembly->assembly));
5238
5239         table = &image->tables [MONO_TABLE_FILE];
5240         file_count = table->rows;
5241
5242         modules = image->modules;
5243         module_count = image->module_count;
5244
5245         real_module_count = 0;
5246         for (i = 0; i < module_count; ++i)
5247                 if (modules [i])
5248                         real_module_count ++;
5249
5250         klass = mono_class_get_module_class ();
5251         res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5252         if (mono_error_set_pending_exception (&error))
5253                 return NULL;
5254
5255         MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5256         if (mono_error_set_pending_exception (&error))
5257                 return NULL;
5258
5259         mono_array_setref (res, 0, image_obj);
5260         j = 1;
5261         for (i = 0; i < module_count; ++i)
5262                 if (modules [i]) {
5263                         MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5264                         if (mono_error_set_pending_exception (&error))
5265                                 return NULL;
5266                         mono_array_setref (res, j, rm);
5267                         ++j;
5268                 }
5269
5270         for (i = 0; i < file_count; ++i, ++j) {
5271                 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5272                 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5273                         MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5274                         if (mono_error_set_pending_exception (&error))
5275                                 return NULL;
5276                         mono_array_setref (res, j, rm);
5277                 }
5278                 else {
5279                         MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5280                         if (!m) {
5281                                 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5282                                 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5283                                 return NULL;
5284                         }
5285                         MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5286                         if (mono_error_set_pending_exception (&error))
5287                                 return NULL;
5288                         mono_array_setref (res, j, rm);
5289                 }
5290         }
5291
5292         return res;
5293 }
5294
5295 ICALL_EXPORT MonoReflectionMethod*
5296 ves_icall_GetCurrentMethod (void) 
5297 {
5298         MonoReflectionMethod *res = NULL;
5299         MonoError error;
5300
5301         MonoMethod *m = mono_method_get_last_managed ();
5302
5303         if (!m) {
5304                 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5305                 return NULL;
5306         }
5307
5308         while (m->is_inflated)
5309                 m = ((MonoMethodInflated*)m)->declaring;
5310
5311         res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5312         mono_error_set_pending_exception (&error);
5313         return res;
5314 }
5315
5316
5317 static MonoMethod*
5318 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5319 {
5320         int offset = -1, i;
5321         if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5322                 MonoError error;
5323                 MonoMethod *result;
5324                 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5325                 //method is inflated, we should inflate it on the other class
5326                 MonoGenericContext ctx;
5327                 ctx.method_inst = inflated->context.method_inst;
5328                 ctx.class_inst = inflated->context.class_inst;
5329                 if (klass->generic_class)
5330                         ctx.class_inst = klass->generic_class->context.class_inst;
5331                 else if (klass->generic_container)
5332                         ctx.class_inst = klass->generic_container->context.class_inst;
5333                 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5334                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5335                 return result;
5336         }
5337
5338         mono_class_setup_methods (method->klass);
5339         if (mono_class_has_failure (method->klass))
5340                 return NULL;
5341         for (i = 0; i < method->klass->method.count; ++i) {
5342                 if (method->klass->methods [i] == method) {
5343                         offset = i;
5344                         break;
5345                 }       
5346         }
5347         mono_class_setup_methods (klass);
5348         if (mono_class_has_failure (klass))
5349                 return NULL;
5350         g_assert (offset >= 0 && offset < klass->method.count);
5351         return klass->methods [offset];
5352 }
5353
5354 ICALL_EXPORT MonoReflectionMethod*
5355 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5356 {
5357         MonoReflectionMethod *res = NULL;
5358         MonoError error;
5359         MonoClass *klass;
5360         if (type) {
5361                 klass = mono_class_from_mono_type (type);
5362                 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass)) 
5363                         return NULL;
5364                 if (method->klass != klass) {
5365                         method = mono_method_get_equivalent_method (method, klass);
5366                         if (!method)
5367                                 return NULL;
5368                 }
5369         } else
5370                 klass = method->klass;
5371         res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5372         mono_error_set_pending_exception (&error);
5373         return res;
5374 }
5375
5376 ICALL_EXPORT MonoReflectionMethodBody*
5377 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5378 {
5379         MonoError error;
5380         MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5381         mono_error_set_pending_exception (&error);
5382         return result;
5383 }
5384
5385 ICALL_EXPORT MonoReflectionAssembly*
5386 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5387 {
5388         MonoError error;
5389         MonoReflectionAssembly *result;
5390         MonoMethod *dest = NULL;
5391
5392         mono_stack_walk_no_il (get_executing, &dest);
5393         g_assert (dest);
5394         result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5395         if (!result)
5396                 mono_error_set_pending_exception (&error);
5397         return result;
5398 }
5399
5400
5401 ICALL_EXPORT MonoReflectionAssembly*
5402 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5403 {
5404         MonoError error;
5405         MonoReflectionAssembly *result;
5406         MonoDomain* domain = mono_domain_get ();
5407
5408         if (!domain->entry_assembly)
5409                 return NULL;
5410
5411         result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5412         if (!result)
5413                 mono_error_set_pending_exception (&error);
5414         return result;
5415 }
5416
5417 ICALL_EXPORT MonoReflectionAssembly*
5418 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5419 {
5420         MonoError error;
5421         MonoMethod *m;
5422         MonoMethod *dest;
5423         MonoReflectionAssembly *result;
5424
5425         dest = NULL;
5426         mono_stack_walk_no_il (get_executing, &dest);
5427         m = dest;
5428         mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5429         if (!dest)
5430                 dest = m;
5431         if (!m) {
5432                 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5433                 return NULL;
5434         }
5435         result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5436         if (!result)
5437                 mono_error_set_pending_exception (&error);
5438         return result;
5439 }
5440
5441 ICALL_EXPORT MonoString *
5442 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5443                                        gboolean assembly_qualified)
5444 {
5445         MonoDomain *domain = mono_object_domain (object); 
5446         MonoTypeNameFormat format;
5447         MonoString *res;
5448         gchar *name;
5449
5450         if (full_name)
5451                 format = assembly_qualified ?
5452                         MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5453                         MONO_TYPE_NAME_FORMAT_FULL_NAME;
5454         else
5455                 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5456  
5457         name = mono_type_get_name_full (object->type, format);
5458         if (!name)
5459                 return NULL;
5460
5461         if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5462                 g_free (name);
5463                 return NULL;
5464         }
5465
5466         res = mono_string_new (domain, name);
5467         g_free (name);
5468
5469         return res;
5470 }
5471
5472 ICALL_EXPORT int
5473 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5474 {
5475         MonoError error;
5476         MonoClass *klass = mono_class_from_mono_type (rfield->type);
5477
5478         mono_class_init_checked (klass, &error);
5479         mono_error_set_pending_exception (&error);
5480         return mono_security_core_clr_class_level (klass);
5481 }
5482
5483 ICALL_EXPORT int
5484 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5485 {
5486         MonoClassField *field = rfield->field;
5487         return mono_security_core_clr_field_level (field, TRUE);
5488 }
5489
5490 ICALL_EXPORT int
5491 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5492 {
5493         MonoMethod *method = rfield->method;
5494         return mono_security_core_clr_method_level (method, TRUE);
5495 }
5496
5497 static void
5498 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)
5499 {
5500         static MonoMethod *create_culture = NULL;
5501         MonoObject *obj;
5502         gpointer args [2];
5503         guint32 pkey_len;
5504         const char *pkey_ptr;
5505         gchar *codebase;
5506         MonoBoolean assembly_ref = 0;
5507
5508         mono_error_init (error);
5509
5510         MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5511         aname->major = name->major;
5512         aname->minor = name->minor;
5513         aname->build = name->build;
5514         aname->flags = name->flags;
5515         aname->revision = name->revision;
5516         aname->hashalg = name->hash_alg;
5517         aname->versioncompat = 1; /* SameMachine (default) */
5518         aname->processor_architecture = name->arch;
5519
5520         if (by_default_version) {
5521                 MonoObject *version;
5522
5523                 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5524                 return_if_nok (error);
5525
5526                 MONO_OBJECT_SETREF (aname, version, version);
5527         }
5528
5529         codebase = NULL;
5530         if (absolute != NULL && *absolute != '\0') {
5531                 const gchar *prepend = "file://";
5532                 gchar *result;
5533
5534                 codebase = g_strdup (absolute);
5535
5536 #if HOST_WIN32
5537                 {
5538                         gint i;
5539                         for (i = strlen (codebase) - 1; i >= 0; i--)
5540                                 if (codebase [i] == '\\')
5541                                         codebase [i] = '/';
5542
5543                         if (*codebase == '/' && *(codebase + 1) == '/') {
5544                                 prepend = "file:";
5545                         } else {
5546                                 prepend = "file:///";
5547                         }
5548                 }
5549 #endif
5550                 result = g_strconcat (prepend, codebase, NULL);
5551                 g_free (codebase);
5552                 codebase = result;
5553         }
5554
5555         if (codebase) {
5556                 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5557                 g_free (codebase);
5558         }
5559
5560         if (!create_culture) {
5561                 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5562                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5563                 g_assert (create_culture);
5564                 mono_method_desc_free (desc);
5565         }
5566
5567         if (name->culture) {
5568                 args [0] = mono_string_new (domain, name->culture);
5569                 args [1] = &assembly_ref;
5570
5571                 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5572                 return_if_nok (error);
5573
5574                 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5575         }
5576
5577         if (name->public_key) {
5578                 pkey_ptr = (char*)name->public_key;
5579                 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5580
5581                 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5582                 return_if_nok (error);
5583                 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5584                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5585                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5586         } else if (default_publickey) {
5587                 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5588                 return_if_nok (error);
5589                 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5590                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5591         }
5592
5593         /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5594         if (name->public_key_token [0]) {
5595                 int i, j;
5596                 char *p;
5597
5598                 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5599                 return_if_nok (error);
5600                 
5601                 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5602                 p = mono_array_addr (keyToken, char, 0);
5603
5604                 for (i = 0, j = 0; i < 8; i++) {
5605                         *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5606                         *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5607                         p++;
5608                 }
5609         } else if (default_token) {
5610                 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5611                 return_if_nok (error);
5612                 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5613         }
5614 }
5615
5616 ICALL_EXPORT MonoString *
5617 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5618 {
5619         MonoDomain *domain = mono_object_domain (assembly); 
5620         MonoAssembly *mass = assembly->assembly;
5621         MonoString *res;
5622         gchar *name;
5623
5624         name = mono_stringify_assembly_name (&mass->aname);
5625         res = mono_string_new (domain, name);
5626         g_free (name);
5627
5628         return res;
5629 }
5630
5631 ICALL_EXPORT void
5632 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5633 {
5634         MonoError error;
5635         gchar *absolute;
5636         MonoAssembly *mass = assembly->assembly;
5637
5638         if (g_path_is_absolute (mass->image->name)) {
5639                 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5640                 mono_error_set_pending_exception (&error);
5641                 return;
5642         }
5643         absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5644
5645         fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5646         mono_error_set_pending_exception (&error);
5647
5648         g_free (absolute);
5649 }
5650
5651 ICALL_EXPORT void
5652 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5653 {
5654         MonoError error;
5655         char *filename;
5656         MonoImageOpenStatus status = MONO_IMAGE_OK;
5657         gboolean res;
5658         MonoImage *image;
5659         MonoAssemblyName name;
5660         char *dirname;
5661
5662         filename = mono_string_to_utf8_checked (fname, &error);
5663         if (mono_error_set_pending_exception (&error))
5664                 return;
5665
5666         dirname = g_path_get_dirname (filename);
5667         replace_shadow_path (mono_domain_get (), dirname, &filename);
5668         g_free (dirname);
5669
5670         image = mono_image_open (filename, &status);
5671
5672         if (!image){
5673                 MonoException *exc;
5674
5675                 g_free (filename);
5676                 if (status == MONO_IMAGE_IMAGE_INVALID)
5677                         exc = mono_get_exception_bad_image_format2 (NULL, fname);
5678                 else
5679                         exc = mono_get_exception_file_not_found2 (NULL, fname);
5680                 mono_set_pending_exception (exc);
5681                 return;
5682         }
5683
5684         res = mono_assembly_fill_assembly_name (image, &name);
5685         if (!res) {
5686                 mono_image_close (image);
5687                 g_free (filename);
5688                 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5689                 return;
5690         }
5691
5692         fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5693         mono_error_set_pending_exception (&error);
5694
5695         mono_image_close (image);
5696         g_free (filename);
5697 }
5698
5699 ICALL_EXPORT MonoBoolean
5700 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5701         char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5702 {
5703         MonoBoolean result = FALSE;
5704         MonoDeclSecurityEntry entry;
5705
5706         /* SecurityAction.RequestMinimum */
5707         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5708                 *minimum = entry.blob;
5709                 *minLength = entry.size;
5710                 result = TRUE;
5711         }
5712         /* SecurityAction.RequestOptional */
5713         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5714                 *optional = entry.blob;
5715                 *optLength = entry.size;
5716                 result = TRUE;
5717         }
5718         /* SecurityAction.RequestRefuse */
5719         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5720                 *refused = entry.blob;
5721                 *refLength = entry.size;
5722                 result = TRUE;
5723         }
5724
5725         return result;  
5726 }
5727
5728 static gboolean
5729 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5730 {
5731         guint32 attrs, visibility;
5732         do {
5733                 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5734                 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5735                 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5736                         return FALSE;
5737
5738         } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5739
5740         return TRUE;
5741 }
5742
5743 static MonoArray*
5744 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5745 {
5746         MonoReflectionType *rt;
5747         MonoArray *res;
5748         MonoClass *klass;
5749         MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5750         int i, count;
5751
5752         mono_error_init (error);
5753
5754         /* we start the count from 1 because we skip the special type <Module> */
5755         if (exportedOnly) {
5756                 count = 0;
5757                 for (i = 1; i < tdef->rows; ++i) {
5758                         if (mono_module_type_is_visible (tdef, image, i + 1))
5759                                 count++;
5760                 }
5761         } else {
5762                 count = tdef->rows - 1;
5763         }
5764         res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5765         return_val_if_nok (error, NULL);
5766         *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5767         return_val_if_nok (error, NULL);
5768         count = 0;
5769         for (i = 1; i < tdef->rows; ++i) {
5770                 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5771                         klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5772                         
5773                         if (klass) {
5774                                 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5775                                 return_val_if_nok (error, NULL);
5776
5777                                 mono_array_setref (res, count, rt);
5778                         } else {
5779                                 MonoException *ex = mono_error_convert_to_exception (error);
5780                                 mono_array_setref (*exceptions, count, ex);
5781                         }
5782                         count++;
5783                 }
5784         }
5785         
5786         return res;
5787 }
5788
5789 ICALL_EXPORT MonoArray*
5790 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5791 {
5792         MonoError error;
5793         MonoArray *res = NULL;
5794         MonoArray *exceptions = NULL;
5795         MonoImage *image = NULL;
5796         MonoTableInfo *table = NULL;
5797         MonoDomain *domain;
5798         GList *list = NULL;
5799         int i, len, ex_count;
5800
5801         domain = mono_object_domain (assembly);
5802
5803         g_assert (!assembly_is_dynamic (assembly->assembly));
5804         image = assembly->assembly->image;
5805         table = &image->tables [MONO_TABLE_FILE];
5806         res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5807         if (mono_error_set_pending_exception (&error))
5808                 return NULL;
5809
5810         /* Append data from all modules in the assembly */
5811         for (i = 0; i < table->rows; ++i) {
5812                 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5813                         MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5814                         if (loaded_image) {
5815                                 MonoArray *ex2;
5816                                 MonoArray *res2;
5817
5818                                 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5819                                 if (mono_error_set_pending_exception (&error))
5820                                         return NULL;
5821
5822
5823                                 /* Append the new types to the end of the array */
5824                                 if (mono_array_length (res2) > 0) {
5825                                         guint32 len1, len2;
5826                                         MonoArray *res3, *ex3;
5827
5828                                         len1 = mono_array_length (res);
5829                                         len2 = mono_array_length (res2);
5830
5831                                         res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5832                                         if (mono_error_set_pending_exception (&error))
5833                                                 return NULL;
5834                                         mono_array_memcpy_refs (res3, 0, res, 0, len1);
5835                                         mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5836                                         res = res3;
5837
5838                                         ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5839                                         if (mono_error_set_pending_exception (&error))
5840                                                 return NULL;
5841                                         mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5842                                         mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5843                                         exceptions = ex3;
5844                                 }
5845                         }
5846                 }
5847         }
5848
5849         /* the ReflectionTypeLoadException must have all the types (Types property), 
5850          * NULL replacing types which throws an exception. The LoaderException must
5851          * contain all exceptions for NULL items.
5852          */
5853
5854         len = mono_array_length (res);
5855
5856         ex_count = 0;
5857         for (i = 0; i < len; i++) {
5858                 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5859                 MonoClass *klass;
5860
5861                 if (t) {
5862                         klass = mono_type_get_class (t->type);
5863                         if ((klass != NULL) && mono_class_has_failure (klass)) {
5864                                 /* keep the class in the list */
5865                                 list = g_list_append (list, klass);
5866                                 /* and replace Type with NULL */
5867                                 mono_array_setref (res, i, NULL);
5868                         }
5869                 } else {
5870                         ex_count ++;
5871                 }
5872         }
5873
5874         if (list || ex_count) {
5875                 GList *tmp = NULL;
5876                 MonoException *exc = NULL;
5877                 MonoArray *exl = NULL;
5878                 int j, length = g_list_length (list) + ex_count;
5879
5880                 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5881                 if (mono_error_set_pending_exception (&error)) {
5882                         g_list_free (list);
5883                         return NULL;
5884                 }
5885                 /* Types for which mono_class_get_checked () succeeded */
5886                 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5887                         MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5888                         mono_array_setref (exl, i, exc);
5889                 }
5890                 /* Types for which it don't */
5891                 for (j = 0; j < mono_array_length (exceptions); ++j) {
5892                         MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5893                         if (exc) {
5894                                 g_assert (i < length);
5895                                 mono_array_setref (exl, i, exc);
5896                                 i ++;
5897                         }
5898                 }
5899                 g_list_free (list);
5900                 list = NULL;
5901
5902                 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5903                 if (!is_ok (&error)) {
5904                         mono_error_set_pending_exception (&error);
5905                         return NULL;
5906                 }
5907                 mono_set_pending_exception (exc);
5908                 return NULL;
5909         }
5910                 
5911         return res;
5912 }
5913
5914 ICALL_EXPORT gboolean
5915 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5916 {
5917         MonoError error;
5918         MonoAssemblyName aname;
5919         MonoDomain *domain = mono_object_domain (name);
5920         char *val;
5921         gboolean is_version_defined;
5922         gboolean is_token_defined;
5923
5924         aname.public_key = NULL;
5925         val = mono_string_to_utf8_checked (assname, &error);
5926         if (mono_error_set_pending_exception (&error))
5927                 return FALSE;
5928
5929         if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5930                 g_free ((guint8*) aname.public_key);
5931                 g_free (val);
5932                 return FALSE;
5933         }
5934         
5935         fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5936         mono_error_set_pending_exception (&error);
5937
5938         mono_assembly_name_free (&aname);
5939         g_free ((guint8*) aname.public_key);
5940         g_free (val);
5941
5942         return TRUE;
5943 }
5944
5945 ICALL_EXPORT MonoReflectionType*
5946 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5947 {
5948         MonoError error;
5949         MonoReflectionType *ret;
5950         MonoDomain *domain = mono_object_domain (module); 
5951         MonoClass *klass;
5952
5953         g_assert (module->image);
5954
5955         if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5956                 /* These images do not have a global type */
5957                 return NULL;
5958
5959         klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5960         if (!mono_error_ok (&error)) {
5961                 mono_error_set_pending_exception (&error);
5962                 return NULL;
5963         }
5964
5965         ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5966         if (!mono_error_ok (&error)) {
5967                 mono_error_set_pending_exception (&error);
5968                 return NULL;
5969         }
5970
5971         return ret;
5972 }
5973
5974 ICALL_EXPORT void
5975 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5976 {
5977         /*if (module->image)
5978                 mono_image_close (module->image);*/
5979 }
5980
5981 ICALL_EXPORT MonoString*
5982 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5983 {
5984         MonoDomain *domain = mono_object_domain (module); 
5985
5986         g_assert (module->image);
5987         return mono_string_new (domain, module->image->guid);
5988 }
5989
5990 ICALL_EXPORT gpointer
5991 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5992 {
5993 #ifdef HOST_WIN32
5994         if (module->image && module->image->is_module_handle)
5995                 return module->image->raw_data;
5996 #endif
5997
5998         return (gpointer) (-1);
5999 }
6000
6001 ICALL_EXPORT void
6002 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
6003 {
6004         if (image_is_dynamic (image)) {
6005                 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
6006                 *pe_kind = dyn->pe_kind;
6007                 *machine = dyn->machine;
6008         }
6009         else {
6010                 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
6011                 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
6012         }
6013 }
6014
6015 ICALL_EXPORT gint32
6016 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
6017 {
6018         return (image->md_version_major << 16) | (image->md_version_minor);
6019 }
6020
6021 ICALL_EXPORT MonoArray*
6022 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
6023 {
6024         MonoError error;
6025         MonoArray *exceptions;
6026         int i;
6027
6028         if (!module->image) {
6029                 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
6030                 mono_error_set_pending_exception (&error);
6031                 return arr;
6032         } else {
6033                 MonoArray *res;
6034
6035                 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
6036                 if (mono_error_set_pending_exception (&error))
6037                         return NULL;
6038
6039                 for (i = 0; i < mono_array_length (exceptions); ++i) {
6040                         MonoException *ex = mono_array_get (exceptions, MonoException *, i);
6041                         if (ex) {
6042                                 mono_set_pending_exception (ex);
6043                                 return NULL;
6044                         }
6045                 }
6046                 return res;
6047         }
6048 }
6049
6050 static gboolean
6051 mono_memberref_is_method (MonoImage *image, guint32 token)
6052 {
6053         if (!image_is_dynamic (image)) {
6054                 guint32 cols [MONO_MEMBERREF_SIZE];
6055                 const char *sig;
6056                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
6057                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
6058                 mono_metadata_decode_blob_size (sig, &sig);
6059                 return (*sig != 0x6);
6060         } else {
6061                 MonoError error;
6062                 MonoClass *handle_class;
6063
6064                 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
6065                         mono_error_cleanup (&error); /* just probing, ignore error */
6066                         return FALSE;
6067                 }
6068
6069                 return mono_defaults.methodhandle_class == handle_class;
6070         }
6071 }
6072
6073 static void
6074 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
6075 {
6076         if (type_args)
6077                 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
6078                                                                       mono_array_addr (type_args, MonoType*, 0));
6079         else
6080                 context->class_inst = NULL;
6081         if (method_args)
6082                 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
6083                                                                        mono_array_addr (method_args, MonoType*, 0));
6084         else
6085                 context->method_inst = NULL;
6086 }
6087
6088 ICALL_EXPORT MonoType*
6089 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6090 {
6091         MonoClass *klass;
6092         int table = mono_metadata_token_table (token);
6093         int index = mono_metadata_token_index (token);
6094         MonoGenericContext context;
6095         MonoError error;
6096
6097         *resolve_error = ResolveTokenError_Other;
6098
6099         /* Validate token */
6100         if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) && 
6101                 (table != MONO_TABLE_TYPESPEC)) {
6102                 *resolve_error = ResolveTokenError_BadTable;
6103                 return NULL;
6104         }
6105
6106         if (image_is_dynamic (image)) {
6107                 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
6108                         klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6109                         mono_error_cleanup (&error);
6110                         return klass ? &klass->byval_arg : NULL;
6111                 }
6112
6113                 init_generic_context_from_args (&context, type_args, method_args);
6114                 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6115                 mono_error_cleanup (&error);
6116                 return klass ? &klass->byval_arg : NULL;
6117         }
6118
6119         if ((index <= 0) || (index > image->tables [table].rows)) {
6120                 *resolve_error = ResolveTokenError_OutOfRange;
6121                 return NULL;
6122         }
6123
6124         init_generic_context_from_args (&context, type_args, method_args);
6125         klass = mono_class_get_checked (image, token, &error);
6126         if (klass)
6127                 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
6128         if (!mono_error_ok (&error)) {
6129                 mono_error_set_pending_exception (&error);
6130                 return NULL;
6131         }
6132
6133         if (klass)
6134                 return &klass->byval_arg;
6135         else
6136                 return NULL;
6137 }
6138
6139 ICALL_EXPORT MonoMethod*
6140 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6141 {
6142         MonoError error;
6143         int table = mono_metadata_token_table (token);
6144         int index = mono_metadata_token_index (token);
6145         MonoGenericContext context;
6146         MonoMethod *method;
6147
6148         *resolve_error = ResolveTokenError_Other;
6149
6150         /* Validate token */
6151         if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) && 
6152                 (table != MONO_TABLE_MEMBERREF)) {
6153                 *resolve_error = ResolveTokenError_BadTable;
6154                 return NULL;
6155         }
6156
6157         if (image_is_dynamic (image)) {
6158                 if (table == MONO_TABLE_METHOD) {
6159                         method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6160                         mono_error_cleanup (&error);
6161                         return method;
6162                 }
6163
6164                 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
6165                         *resolve_error = ResolveTokenError_BadTable;
6166                         return NULL;
6167                 }
6168
6169                 init_generic_context_from_args (&context, type_args, method_args);
6170                 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6171                 mono_error_cleanup (&error);
6172                 return method;
6173         }
6174
6175         if ((index <= 0) || (index > image->tables [table].rows)) {
6176                 *resolve_error = ResolveTokenError_OutOfRange;
6177                 return NULL;
6178         }
6179         if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6180                 *resolve_error = ResolveTokenError_BadTable;
6181                 return NULL;
6182         }
6183
6184         init_generic_context_from_args (&context, type_args, method_args);
6185         method = mono_get_method_checked (image, token, NULL, &context, &error);
6186         mono_error_set_pending_exception (&error);
6187
6188         return method;
6189 }
6190
6191 ICALL_EXPORT MonoString*
6192 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6193 {
6194         MonoError error;
6195         int index = mono_metadata_token_index (token);
6196
6197         *resolve_error = ResolveTokenError_Other;
6198
6199         /* Validate token */
6200         if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6201                 *resolve_error = ResolveTokenError_BadTable;
6202                 return NULL;
6203         }
6204
6205         if (image_is_dynamic (image)) {
6206                 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6207                 mono_error_cleanup (&error);
6208                 return result;
6209         }
6210
6211         if ((index <= 0) || (index >= image->heap_us.size)) {
6212                 *resolve_error = ResolveTokenError_OutOfRange;
6213                 return NULL;
6214         }
6215
6216         /* FIXME: What to do if the index points into the middle of a string ? */
6217
6218         MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
6219         mono_error_set_pending_exception (&error);
6220         return result;
6221 }
6222
6223 ICALL_EXPORT MonoClassField*
6224 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6225 {
6226         MonoError error;
6227         MonoClass *klass;
6228         int table = mono_metadata_token_table (token);
6229         int index = mono_metadata_token_index (token);
6230         MonoGenericContext context;
6231         MonoClassField *field;
6232
6233         *resolve_error = ResolveTokenError_Other;
6234
6235         /* Validate token */
6236         if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6237                 *resolve_error = ResolveTokenError_BadTable;
6238                 return NULL;
6239         }
6240
6241         if (image_is_dynamic (image)) {
6242                 if (table == MONO_TABLE_FIELD) {
6243                         field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6244                         mono_error_cleanup (&error);
6245                         return field;
6246                 }
6247
6248                 if (mono_memberref_is_method (image, token)) {
6249                         *resolve_error = ResolveTokenError_BadTable;
6250                         return NULL;
6251                 }
6252
6253                 init_generic_context_from_args (&context, type_args, method_args);
6254                 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6255                 mono_error_cleanup (&error);
6256                 return field;
6257         }
6258
6259         if ((index <= 0) || (index > image->tables [table].rows)) {
6260                 *resolve_error = ResolveTokenError_OutOfRange;
6261                 return NULL;
6262         }
6263         if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6264                 *resolve_error = ResolveTokenError_BadTable;
6265                 return NULL;
6266         }
6267
6268         init_generic_context_from_args (&context, type_args, method_args);
6269         field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6270         mono_error_set_pending_exception (&error);
6271         
6272         return field;
6273 }
6274
6275
6276 ICALL_EXPORT MonoObject*
6277 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6278 {
6279         MonoError merror;
6280         MonoObject *ret;
6281         int table = mono_metadata_token_table (token);
6282
6283         *error = ResolveTokenError_Other;
6284
6285         switch (table) {
6286         case MONO_TABLE_TYPEDEF:
6287         case MONO_TABLE_TYPEREF:
6288         case MONO_TABLE_TYPESPEC: {
6289                 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6290                 if (t) {
6291                         ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6292                         mono_error_set_pending_exception (&merror);
6293
6294                         return ret;
6295                 }
6296                 else
6297                         return NULL;
6298         }
6299         case MONO_TABLE_METHOD:
6300         case MONO_TABLE_METHODSPEC: {
6301                 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6302                 if (m) {
6303                         ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6304                         mono_error_set_pending_exception (&merror);
6305
6306                         return ret;
6307                 } else
6308                         return NULL;
6309         }               
6310         case MONO_TABLE_FIELD: {
6311                 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6312                 if (f) {
6313                         ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6314                         mono_error_set_pending_exception (&merror);
6315                         return ret;
6316                 }
6317                 else
6318                         return NULL;
6319         }
6320         case MONO_TABLE_MEMBERREF:
6321                 if (mono_memberref_is_method (image, token)) {
6322                         MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6323                         if (m) {
6324                                 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6325                                 mono_error_set_pending_exception (&merror);
6326
6327                                 return ret;
6328                         } else
6329                                 return NULL;
6330                 }
6331                 else {
6332                         MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6333                         if (f) {
6334                                 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6335                                 mono_error_set_pending_exception (&merror);
6336                                 return ret;
6337                         }
6338                         else
6339                                 return NULL;
6340                 }
6341                 break;
6342
6343         default:
6344                 *error = ResolveTokenError_BadTable;
6345         }
6346
6347         return NULL;
6348 }
6349
6350 ICALL_EXPORT MonoArray*
6351 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6352 {
6353         MonoError error;
6354         int table = mono_metadata_token_table (token);
6355         int idx = mono_metadata_token_index (token);
6356         MonoTableInfo *tables = image->tables;
6357         guint32 sig, len;
6358         const char *ptr;
6359         MonoArray *res;
6360
6361         *resolve_error = ResolveTokenError_OutOfRange;
6362
6363         /* FIXME: Support other tables ? */
6364         if (table != MONO_TABLE_STANDALONESIG)
6365                 return NULL;
6366
6367         if (image_is_dynamic (image))
6368                 return NULL;
6369
6370         if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6371                 return NULL;
6372
6373         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6374
6375         ptr = mono_metadata_blob_heap (image, sig);
6376         len = mono_metadata_decode_blob_size (ptr, &ptr);
6377
6378         res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6379         if (mono_error_set_pending_exception (&error))
6380                 return NULL;
6381         memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6382         return res;
6383 }
6384
6385 ICALL_EXPORT MonoReflectionType*
6386 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6387 {
6388         MonoError error;
6389         MonoReflectionType *ret;
6390         MonoClass *klass;
6391         int isbyref = 0, rank;
6392         char *p;
6393         char *str = mono_string_to_utf8_checked (smodifiers, &error);
6394         if (mono_error_set_pending_exception (&error))
6395                 return NULL;
6396
6397         klass = mono_class_from_mono_type (tb->type.type);
6398         p = str;
6399         /* logic taken from mono_reflection_parse_type(): keep in sync */
6400         while (*p) {
6401                 switch (*p) {
6402                 case '&':
6403                         if (isbyref) { /* only one level allowed by the spec */
6404                                 g_free (str);
6405                                 return NULL;
6406                         }
6407                         isbyref = 1;
6408                         p++;
6409
6410                         g_free (str);
6411
6412                         ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6413                         mono_error_set_pending_exception (&error);
6414
6415                         return ret;
6416                 case '*':
6417                         klass = mono_ptr_class_get (&klass->byval_arg);
6418                         mono_class_init (klass);
6419                         p++;
6420                         break;
6421                 case '[':
6422                         rank = 1;
6423                         p++;
6424                         while (*p) {
6425                                 if (*p == ']')
6426                                         break;
6427                                 if (*p == ',')
6428                                         rank++;
6429                                 else if (*p != '*') { /* '*' means unknown lower bound */
6430                                         g_free (str);
6431                                         return NULL;
6432                                 }
6433                                 ++p;
6434                         }
6435                         if (*p != ']') {
6436                                 g_free (str);
6437                                 return NULL;
6438                         }
6439                         p++;
6440                         klass = mono_array_class_get (klass, rank);
6441                         mono_class_init (klass);
6442                         break;
6443                 default:
6444                         break;
6445                 }
6446         }
6447
6448         g_free (str);
6449
6450         ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6451         mono_error_set_pending_exception (&error);
6452
6453         return ret;
6454 }
6455
6456 ICALL_EXPORT MonoBoolean
6457 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6458 {
6459         MonoType *type;
6460         MonoBoolean res;
6461
6462         type = t->type;
6463         res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6464
6465         return res;
6466 }
6467
6468 static void
6469 check_for_invalid_type (MonoClass *klass, MonoError *error)
6470 {
6471         char *name;
6472         MonoString *str;
6473
6474         mono_error_init (error);
6475
6476         if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6477                 return;
6478
6479         name = mono_type_get_full_name (klass);
6480         str =  mono_string_new (mono_domain_get (), name);
6481         g_free (name);
6482         mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6483
6484 }
6485 ICALL_EXPORT MonoReflectionType *
6486 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6487 {
6488         MonoError error;
6489         MonoReflectionType *ret;
6490         MonoClass *klass, *aklass;
6491
6492         klass = mono_class_from_mono_type (type->type);
6493         check_for_invalid_type (klass, &error);
6494         mono_error_set_pending_exception (&error);
6495
6496         if (rank == 0) //single dimentional array
6497                 aklass = mono_array_class_get (klass, 1);
6498         else
6499                 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6500
6501         ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6502         mono_error_set_pending_exception (&error);
6503
6504         return ret;
6505 }
6506
6507 ICALL_EXPORT MonoReflectionType *
6508 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6509 {
6510         MonoError error;
6511         MonoReflectionType *ret;
6512         MonoClass *klass;
6513
6514         klass = mono_class_from_mono_type (type->type);
6515         mono_class_init_checked (klass, &error);
6516         if (mono_error_set_pending_exception (&error))
6517                 return NULL;
6518
6519         check_for_invalid_type (klass, &error);
6520         if (mono_error_set_pending_exception (&error))
6521                 return NULL;
6522
6523         ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6524         mono_error_set_pending_exception (&error);
6525
6526         return ret;
6527 }
6528
6529 ICALL_EXPORT MonoReflectionType *
6530 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6531 {
6532         MonoError error;
6533         MonoReflectionType *ret;
6534         MonoClass *klass, *pklass;
6535
6536         klass = mono_class_from_mono_type (type->type);
6537         mono_class_init_checked (klass, &error);
6538         if (mono_error_set_pending_exception (&error))
6539                 return NULL;
6540         check_for_invalid_type (klass, &error);
6541         if (mono_error_set_pending_exception (&error))
6542                 return NULL;
6543
6544         pklass = mono_ptr_class_get (type->type);
6545
6546         ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6547         mono_error_set_pending_exception (&error);
6548
6549         return ret;
6550 }
6551
6552 ICALL_EXPORT MonoObject *
6553 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6554                                                    MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6555 {
6556         MonoError error;
6557         MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6558         MonoObject *delegate;
6559         gpointer func;
6560         MonoMethod *method = info->method;
6561
6562         mono_class_init_checked (delegate_class, &error);
6563         if (mono_error_set_pending_exception (&error))
6564                 return NULL;
6565
6566         if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6567                 /* FIXME improve this exception message */
6568                 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6569                                                  __func__,
6570                                                  "delegate_class->parent == mono_defaults.multicastdelegate_class");
6571                 mono_error_set_pending_exception (&error);
6572                 return NULL;
6573         }
6574
6575         if (mono_security_core_clr_enabled ()) {
6576                 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6577                         if (throwOnBindFailure)
6578                                 mono_error_set_pending_exception (&error);
6579                         else
6580                                 mono_error_cleanup (&error);
6581                         return NULL;
6582                 }
6583         }
6584
6585         delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6586         if (mono_error_set_pending_exception (&error))
6587                 return NULL;
6588
6589         if (method_is_dynamic (method)) {
6590                 /* Creating a trampoline would leak memory */
6591                 func = mono_compile_method_checked (method, &error);
6592                 if (mono_error_set_pending_exception (&error))
6593                         return NULL;
6594         } else {
6595                 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6596                         method = mono_object_get_virtual_method (target, method);
6597                 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6598                 if (mono_error_set_pending_exception (&error))
6599                         return NULL;
6600                 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6601         }
6602
6603         mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6604         if (mono_error_set_pending_exception (&error))
6605                 return NULL;
6606         return delegate;
6607 }
6608
6609 ICALL_EXPORT MonoMulticastDelegate *
6610 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6611 {
6612         MonoError error;
6613         MonoMulticastDelegate *ret;
6614
6615         g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6616
6617         ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6618         if (mono_error_set_pending_exception (&error))
6619                 return NULL;
6620
6621         ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6622
6623         return ret;
6624 }
6625
6626 ICALL_EXPORT MonoReflectionMethod*
6627 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6628 {
6629         MonoReflectionMethod *ret = NULL;
6630         MonoError error;
6631         ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6632         mono_error_set_pending_exception (&error);
6633         return ret;
6634 }
6635
6636 /* System.Buffer */
6637
6638 static inline gint32 
6639 mono_array_get_byte_length (MonoArray *array)
6640 {
6641         MonoClass *klass;
6642         int length;
6643         int i;
6644
6645         klass = array->obj.vtable->klass;
6646
6647         if (array->bounds == NULL)
6648                 length = array->max_length;
6649         else {
6650                 length = 1;
6651                 for (i = 0; i < klass->rank; ++ i)
6652                         length *= array->bounds [i].length;
6653         }
6654
6655         switch (klass->element_class->byval_arg.type) {
6656         case MONO_TYPE_I1:
6657         case MONO_TYPE_U1:
6658         case MONO_TYPE_BOOLEAN:
6659                 return length;
6660         case MONO_TYPE_I2:
6661         case MONO_TYPE_U2:
6662         case MONO_TYPE_CHAR:
6663                 return length << 1;
6664         case MONO_TYPE_I4:
6665         case MONO_TYPE_U4:
6666         case MONO_TYPE_R4:
6667                 return length << 2;
6668         case MONO_TYPE_I:
6669         case MONO_TYPE_U:
6670                 return length * sizeof (gpointer);
6671         case MONO_TYPE_I8:
6672         case MONO_TYPE_U8:
6673         case MONO_TYPE_R8:
6674                 return length << 3;
6675         default:
6676                 return -1;
6677         }
6678 }
6679
6680 ICALL_EXPORT gint32 
6681 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array) 
6682 {
6683         return mono_array_get_byte_length (array);
6684 }
6685
6686 ICALL_EXPORT gint8 
6687 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx) 
6688 {
6689         return mono_array_get (array, gint8, idx);
6690 }
6691
6692 ICALL_EXPORT void 
6693 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value) 
6694 {
6695         mono_array_set (array, gint8, idx, value);
6696 }
6697
6698 ICALL_EXPORT MonoBoolean
6699 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count) 
6700 {
6701         guint8 *src_buf, *dest_buf;
6702
6703         if (count < 0) {
6704                 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6705                 return FALSE;
6706         }
6707
6708         g_assert (count >= 0);
6709
6710         /* This is called directly from the class libraries without going through the managed wrapper */
6711         MONO_CHECK_ARG_NULL (src, FALSE);
6712         MONO_CHECK_ARG_NULL (dest, FALSE);
6713
6714         /* watch out for integer overflow */
6715         if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6716                 return FALSE;
6717
6718         src_buf = (guint8 *)src->vector + src_offset;
6719         dest_buf = (guint8 *)dest->vector + dest_offset;
6720
6721         if (src != dest)
6722                 memcpy (dest_buf, src_buf, count);
6723         else
6724                 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6725
6726         return TRUE;
6727 }
6728
6729 #ifndef DISABLE_REMOTING
6730 ICALL_EXPORT MonoObject *
6731 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6732 {
6733         MonoError error;
6734         MonoDomain *domain = mono_object_domain (this_obj); 
6735         MonoObject *res;
6736         MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6737         MonoTransparentProxy *tp;
6738         MonoType *type;
6739         MonoClass *klass;
6740
6741         res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6742         if (mono_error_set_pending_exception (&error))
6743                 return NULL;
6744
6745         tp = (MonoTransparentProxy*) res;
6746         
6747         MONO_OBJECT_SETREF (tp, rp, rp);
6748         type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6749         klass = mono_class_from_mono_type (type);
6750
6751         // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6752         mono_class_setup_vtable (klass);
6753         if (mono_class_has_failure (klass)) {
6754                 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6755                 return NULL;
6756         }
6757
6758         tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6759         if (mono_error_set_pending_exception (&error))
6760                 return NULL;
6761         tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6762         if (mono_error_set_pending_exception (&error))
6763                 return NULL;
6764
6765         res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6766         if (mono_error_set_pending_exception (&error))
6767                 return NULL;
6768         return res;
6769 }
6770
6771 ICALL_EXPORT MonoReflectionType *
6772 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6773 {
6774         MonoError error;
6775         MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6776         mono_error_set_pending_exception (&error);
6777
6778         return ret;
6779 }
6780 #endif
6781
6782 /* System.Environment */
6783
6784 MonoString*
6785 ves_icall_System_Environment_get_UserName (void)
6786 {
6787         /* using glib is more portable */
6788         return mono_string_new (mono_domain_get (), g_get_user_name ());
6789 }
6790
6791
6792 ICALL_EXPORT MonoString *
6793 ves_icall_System_Environment_get_MachineName (void)
6794 {
6795 #if defined (HOST_WIN32)
6796         gunichar2 *buf;
6797         guint32 len;
6798         MonoString *result;
6799
6800         len = MAX_COMPUTERNAME_LENGTH + 1;
6801         buf = g_new (gunichar2, len);
6802
6803         result = NULL;
6804         if (GetComputerName (buf, (PDWORD) &len)) {
6805                 MonoError error;
6806                 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6807                 mono_error_set_pending_exception (&error);
6808         }
6809
6810         g_free (buf);
6811         return result;
6812 #elif !defined(DISABLE_SOCKETS)
6813         MonoString *result;
6814         char *buf;
6815         int n;
6816 #if defined _SC_HOST_NAME_MAX
6817         n = sysconf (_SC_HOST_NAME_MAX);
6818         if (n == -1)
6819 #endif
6820         n = 512;
6821         buf = g_malloc (n+1);
6822         
6823         if (gethostname (buf, n) == 0){
6824                 buf [n] = 0;
6825                 result = mono_string_new (mono_domain_get (), buf);
6826         } else
6827                 result = NULL;
6828         g_free (buf);
6829         
6830         return result;
6831 #else
6832         return mono_string_new (mono_domain_get (), "mono");
6833 #endif
6834 }
6835
6836 ICALL_EXPORT int
6837 ves_icall_System_Environment_get_Platform (void)
6838 {
6839 #if defined (TARGET_WIN32)
6840         /* Win32NT */
6841         return 2;
6842 #elif defined(__MACH__)
6843         /* OSX */
6844         //
6845         // Notice that the value is hidden from user code, and only exposed
6846         // to mscorlib.   This is due to Mono's Unix/MacOS code predating the
6847         // define and making assumptions based on Unix/128/4 values before there
6848         // was a MacOS define.    Lots of code would assume that not-Unix meant
6849         // Windows, but in this case, it would be OSX. 
6850         //
6851         return 6;
6852 #else
6853         /* Unix */
6854         return 4;
6855 #endif
6856 }
6857
6858 ICALL_EXPORT MonoString *
6859 ves_icall_System_Environment_get_NewLine (void)
6860 {
6861 #if defined (HOST_WIN32)
6862         return mono_string_new (mono_domain_get (), "\r\n");
6863 #else
6864         return mono_string_new (mono_domain_get (), "\n");
6865 #endif
6866 }
6867
6868 ICALL_EXPORT MonoBoolean
6869 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6870 {
6871 #if SIZEOF_VOID_P == 8
6872         return TRUE;
6873 #else
6874 #ifdef HOST_WIN32
6875         gboolean isWow64Process = FALSE;
6876         if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6877                 return (MonoBoolean)isWow64Process;
6878         }
6879 #elif defined(HAVE_SYS_UTSNAME_H)
6880         struct utsname name;
6881
6882         if (uname (&name) >= 0) {
6883                 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6884         }
6885 #endif
6886         return FALSE;
6887 #endif
6888 }
6889
6890 ICALL_EXPORT MonoString *
6891 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6892 {
6893         MonoError error;
6894         const gchar *value;
6895         gchar *utf8_name;
6896
6897         if (name == NULL)
6898                 return NULL;
6899
6900         utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6901         if (mono_error_set_pending_exception (&error))
6902                 return NULL;
6903         value = g_getenv (utf8_name);
6904
6905         g_free (utf8_name);
6906
6907         if (value == 0)
6908                 return NULL;
6909         
6910         return mono_string_new (mono_domain_get (), value);
6911 }
6912
6913 /*
6914  * There is no standard way to get at environ.
6915  */
6916 #ifndef _MSC_VER
6917 #ifndef __MINGW32_VERSION
6918 #if defined(__APPLE__)
6919 #if defined (TARGET_OSX)
6920 /* Apple defines this in crt_externs.h but doesn't provide that header for 
6921  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
6922  * in fact exist on all implementations (so far) 
6923  */
6924 gchar ***_NSGetEnviron(void);
6925 #define environ (*_NSGetEnviron())
6926 #else
6927 static char *mono_environ[1] = { NULL };
6928 #define environ mono_environ
6929 #endif /* defined (TARGET_OSX) */
6930 #else
6931 extern
6932 char **environ;
6933 #endif
6934 #endif
6935 #endif
6936
6937 ICALL_EXPORT MonoArray *
6938 ves_icall_System_Environment_GetCoomandLineArgs (void)
6939 {
6940         MonoError error;
6941         MonoArray *result = mono_runtime_get_main_args_checked (&error);
6942         mono_error_set_pending_exception (&error);
6943         return result;
6944 }
6945
6946 ICALL_EXPORT MonoArray *
6947 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6948 {
6949 #ifdef HOST_WIN32
6950         MonoError error;
6951         MonoArray *names;
6952         MonoDomain *domain;
6953         MonoString *str;
6954         WCHAR* env_strings;
6955         WCHAR* env_string;
6956         WCHAR* equal_str;
6957         int n = 0;
6958
6959         env_strings = GetEnvironmentStrings();
6960
6961         if (env_strings) {
6962                 env_string = env_strings;
6963                 while (*env_string != '\0') {
6964                 /* weird case that MS seems to skip */
6965                         if (*env_string != '=')
6966                                 n++;
6967                         while (*env_string != '\0')
6968                                 env_string++;
6969                         env_string++;
6970                 }
6971         }
6972
6973         domain = mono_domain_get ();
6974         names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6975         if (mono_error_set_pending_exception (&error))
6976                 return NULL;
6977
6978         if (env_strings) {
6979                 n = 0;
6980                 env_string = env_strings;
6981                 while (*env_string != '\0') {
6982                         /* weird case that MS seems to skip */
6983                         if (*env_string != '=') {
6984                                 equal_str = wcschr(env_string, '=');
6985                                 g_assert(equal_str);
6986                                 MonoError error;
6987                                 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6988                                 if (mono_error_set_pending_exception (&error))
6989                                         return NULL;
6990
6991                                 mono_array_setref (names, n, str);
6992                                 n++;
6993                         }
6994                         while (*env_string != '\0')
6995                                 env_string++;
6996                         env_string++;
6997                 }
6998
6999                 FreeEnvironmentStrings (env_strings);
7000         }
7001
7002         return names;
7003
7004 #else
7005         MonoError error;
7006         MonoArray *names;
7007         MonoDomain *domain;
7008         MonoString *str;
7009         gchar **e, **parts;
7010         int n;
7011
7012         n = 0;
7013         for (e = environ; *e != 0; ++ e)
7014                 ++ n;
7015
7016         domain = mono_domain_get ();
7017         names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
7018         if (mono_error_set_pending_exception (&error))
7019                 return NULL;
7020
7021         n = 0;
7022         for (e = environ; *e != 0; ++ e) {
7023                 parts = g_strsplit (*e, "=", 2);
7024                 if (*parts != 0) {
7025                         str = mono_string_new (domain, *parts);
7026                         mono_array_setref (names, n, str);
7027                 }
7028
7029                 g_strfreev (parts);
7030
7031                 ++ n;
7032         }
7033
7034         return names;
7035 #endif
7036 }
7037
7038 ICALL_EXPORT void
7039 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
7040 {
7041 #ifdef HOST_WIN32
7042         gunichar2 *utf16_name, *utf16_value;
7043 #else
7044         gchar *utf8_name, *utf8_value;
7045         MonoError error;
7046 #endif
7047
7048 #ifdef HOST_WIN32
7049         utf16_name = mono_string_to_utf16 (name);
7050         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7051                 SetEnvironmentVariable (utf16_name, NULL);
7052                 g_free (utf16_name);
7053                 return;
7054         }
7055
7056         utf16_value = mono_string_to_utf16 (value);
7057
7058         SetEnvironmentVariable (utf16_name, utf16_value);
7059
7060         g_free (utf16_name);
7061         g_free (utf16_value);
7062 #else
7063         utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
7064         if (mono_error_set_pending_exception (&error))
7065                 return;
7066
7067         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7068                 g_unsetenv (utf8_name);
7069                 g_free (utf8_name);
7070                 return;
7071         }
7072
7073         utf8_value = mono_string_to_utf8_checked (value, &error);
7074         if (!mono_error_ok (&error)) {
7075                 g_free (utf8_name);
7076                 mono_error_set_pending_exception (&error);
7077                 return;
7078         }
7079         g_setenv (utf8_name, utf8_value, TRUE);
7080
7081         g_free (utf8_name);
7082         g_free (utf8_value);
7083 #endif
7084 }
7085
7086 ICALL_EXPORT void
7087 ves_icall_System_Environment_Exit (int result)
7088 {
7089         mono_environment_exitcode_set (result);
7090
7091 /* FIXME: There are some cleanup hangs that should be worked out, but
7092  * if the program is going to exit, everything will be cleaned up when
7093  * NaCl exits anyway.
7094  */
7095 #ifndef __native_client__
7096         if (!mono_runtime_try_shutdown ())
7097                 mono_thread_exit ();
7098
7099         /* Suspend all managed threads since the runtime is going away */
7100         mono_thread_suspend_all_other_threads ();
7101
7102         mono_runtime_quit ();
7103 #endif
7104
7105         /* we may need to do some cleanup here... */
7106         exit (result);
7107 }
7108
7109 ICALL_EXPORT MonoString*
7110 ves_icall_System_Environment_GetGacPath (void)
7111 {
7112         return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
7113 }
7114
7115 ICALL_EXPORT MonoString*
7116 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
7117 {
7118 #if defined (HOST_WIN32)
7119         #ifndef CSIDL_FLAG_CREATE
7120                 #define CSIDL_FLAG_CREATE       0x8000
7121         #endif
7122
7123         WCHAR path [MAX_PATH];
7124         /* Create directory if no existing */
7125         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
7126                 int len = 0;
7127                 while (path [len])
7128                         ++ len;
7129                 MonoError error;
7130                 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
7131                 mono_error_set_pending_exception (&error);
7132                 return res;
7133         }
7134 #else
7135         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7136 #endif
7137         return mono_string_new (mono_domain_get (), "");
7138 }
7139
7140 ICALL_EXPORT MonoArray *
7141 ves_icall_System_Environment_GetLogicalDrives (void)
7142 {
7143         MonoError error;
7144         gunichar2 buf [256], *ptr, *dname;
7145         gunichar2 *u16;
7146         guint initial_size = 127, size = 128;
7147         gint ndrives;
7148         MonoArray *result;
7149         MonoString *drivestr;
7150         MonoDomain *domain = mono_domain_get ();
7151         gint len;
7152
7153         buf [0] = '\0';
7154         ptr = buf;
7155
7156         while (size > initial_size) {
7157                 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7158                 if (size > initial_size) {
7159                         if (ptr != buf)
7160                                 g_free (ptr);
7161                         ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7162                         initial_size = size;
7163                         size++;
7164                 }
7165         }
7166
7167         /* Count strings */
7168         dname = ptr;
7169         ndrives = 0;
7170         do {
7171                 while (*dname++);
7172                 ndrives++;
7173         } while (*dname);
7174
7175         dname = ptr;
7176         result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7177         if (mono_error_set_pending_exception (&error))
7178                 goto leave;
7179
7180         ndrives = 0;
7181         do {
7182                 len = 0;
7183                 u16 = dname;
7184                 while (*u16) { u16++; len ++; }
7185                 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7186                 if (mono_error_set_pending_exception (&error))
7187                         goto leave;
7188
7189                 mono_array_setref (result, ndrives++, drivestr);
7190                 while (*dname++);
7191         } while (*dname);
7192
7193 leave:
7194         if (ptr != buf)
7195                 g_free (ptr);
7196
7197         return result;
7198 }
7199
7200 ICALL_EXPORT MonoString *
7201 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7202 {
7203         MonoError error;
7204         gunichar2 volume_name [MAX_PATH + 1];
7205         
7206         if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7207                 return NULL;
7208         MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
7209         mono_error_set_pending_exception (&error);
7210         return result;
7211 }
7212
7213 ICALL_EXPORT MonoString *
7214 ves_icall_System_Environment_InternalGetHome (void)
7215 {
7216         return mono_string_new (mono_domain_get (), g_get_home_dir ());
7217 }
7218
7219 static const char *encodings [] = {
7220         (char *) 1,
7221                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7222                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7223                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7224         (char *) 2,
7225                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7226                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7227                 "x_unicode_2_0_utf_7",
7228         (char *) 3,
7229                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7230                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7231         (char *) 4,
7232                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7233                 "iso_10646_ucs2",
7234         (char *) 5,
7235                 "unicodefffe", "utf_16be",
7236         (char *) 6,
7237                 "iso_8859_1",
7238         (char *) 0
7239 };
7240
7241 /*
7242  * Returns the internal codepage, if the value of "int_code_page" is
7243  * 1 at entry, and we can not compute a suitable code page number,
7244  * returns the code page as a string
7245  */
7246 ICALL_EXPORT MonoString*
7247 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page) 
7248 {
7249         const char *cset;
7250         const char *p;
7251         char *c;
7252         char *codepage = NULL;
7253         int code;
7254         int want_name = *int_code_page;
7255         int i;
7256         
7257         *int_code_page = -1;
7258
7259         g_get_charset (&cset);
7260         c = codepage = strdup (cset);
7261         for (c = codepage; *c; c++){
7262                 if (isascii (*c) && isalpha (*c))
7263                         *c = tolower (*c);
7264                 if (*c == '-')
7265                         *c = '_';
7266         }
7267         /* g_print ("charset: %s\n", cset); */
7268         
7269         /* handle some common aliases */
7270         p = encodings [0];
7271         code = 0;
7272         for (i = 0; p != 0; ){
7273                 if ((gsize) p < 7){
7274                         code = (gssize) p;
7275                         p = encodings [++i];
7276                         continue;
7277                 }
7278                 if (strcmp (p, codepage) == 0){
7279                         *int_code_page = code;
7280                         break;
7281                 }
7282                 p = encodings [++i];
7283         }
7284         
7285         if (strstr (codepage, "utf_8") != NULL)
7286                 *int_code_page |= 0x10000000;
7287         free (codepage);
7288         
7289         if (want_name && *int_code_page == -1)
7290                 return mono_string_new (mono_domain_get (), cset);
7291         else
7292                 return NULL;
7293 }
7294
7295 ICALL_EXPORT MonoBoolean
7296 ves_icall_System_Environment_get_HasShutdownStarted (void)
7297 {
7298         if (mono_runtime_is_shutting_down ())
7299                 return TRUE;
7300
7301         if (mono_domain_is_unloading (mono_domain_get ()))
7302                 return TRUE;
7303
7304         return FALSE;
7305 }
7306
7307 ICALL_EXPORT void
7308 ves_icall_System_Environment_BroadcastSettingChange (void)
7309 {
7310 #ifdef HOST_WIN32
7311         SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7312 #endif
7313 }
7314
7315 ICALL_EXPORT
7316 gint32
7317 ves_icall_System_Environment_get_TickCount (void)
7318 {
7319         /* this will overflow after ~24 days */
7320         return (gint32) (mono_msec_boottime () & 0xffffffff);
7321 }
7322
7323 ICALL_EXPORT gint32
7324 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7325 {
7326         return 9;
7327 }
7328
7329 ICALL_EXPORT void
7330 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj, 
7331                                          MonoReflectionMethod *method,
7332                                          MonoArray *out_args)
7333 {
7334         MonoError error;
7335         mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args, &error);
7336         mono_error_set_pending_exception (&error);
7337 }
7338
7339 #ifndef DISABLE_REMOTING
7340 ICALL_EXPORT MonoBoolean
7341 ves_icall_IsTransparentProxy (MonoObject *proxy)
7342 {
7343         if (!proxy)
7344                 return 0;
7345
7346         if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7347                 return 1;
7348
7349         return 0;
7350 }
7351
7352 ICALL_EXPORT MonoReflectionMethod *
7353 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7354         MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7355 {
7356         MonoReflectionMethod *ret = NULL;
7357         MonoError error;
7358
7359         MonoClass *klass;
7360         MonoMethod *method;
7361         MonoMethod **vtable;
7362         MonoMethod *res = NULL;
7363
7364         MONO_CHECK_ARG_NULL (rtype, NULL);
7365         MONO_CHECK_ARG_NULL (rmethod, NULL);
7366
7367         method = rmethod->method;
7368         klass = mono_class_from_mono_type (rtype->type);
7369         mono_class_init_checked (klass, &error);
7370         if (mono_error_set_pending_exception (&error))
7371                 return NULL;
7372
7373         if (MONO_CLASS_IS_INTERFACE (klass))
7374                 return NULL;
7375
7376         if (method->flags & METHOD_ATTRIBUTE_STATIC)
7377                 return NULL;
7378
7379         if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7380                 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7381                         return rmethod;
7382                 else
7383                         return NULL;
7384         }
7385
7386         mono_class_setup_vtable (klass);
7387         vtable = klass->vtable;
7388
7389         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7390                 gboolean variance_used = FALSE;
7391                 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7392                 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7393                 if (offs >= 0)
7394                         res = vtable [offs + method->slot];
7395         } else {
7396                 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7397                         return NULL;
7398
7399                 if (method->slot != -1)
7400                         res = vtable [method->slot];
7401         }
7402
7403         if (!res)
7404                 return NULL;
7405
7406         ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7407         mono_error_set_pending_exception (&error);
7408         return ret;
7409 }
7410
7411 ICALL_EXPORT void
7412 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7413 {
7414         MonoError error;
7415         MonoClass *klass;
7416         MonoVTable* vtable;
7417
7418         klass = mono_class_from_mono_type (type->type);
7419         vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7420         if (!is_ok (&error)) {
7421                 mono_error_set_pending_exception (&error);
7422                 return;
7423         }
7424
7425         mono_vtable_set_is_remote (vtable, enable);
7426 }
7427
7428 #else /* DISABLE_REMOTING */
7429
7430 ICALL_EXPORT void
7431 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7432 {
7433         g_assert_not_reached ();
7434 }
7435
7436 #endif
7437
7438 ICALL_EXPORT MonoObject *
7439 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7440 {
7441         MonoError error;
7442         MonoClass *klass;
7443         MonoDomain *domain;
7444         MonoObject *ret;
7445         
7446         domain = mono_object_domain (type);
7447         klass = mono_class_from_mono_type (type->type);
7448         mono_class_init_checked (klass, &error);
7449         if (mono_error_set_pending_exception (&error))
7450                 return NULL;
7451
7452         if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7453                 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7454                 return NULL;
7455         }
7456
7457         if (klass->rank >= 1) {
7458                 g_assert (klass->rank == 1);
7459                 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7460                 mono_error_set_pending_exception (&error);
7461                 return ret;
7462         } else {
7463                 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7464                 if (!is_ok (&error)) {
7465                         mono_error_set_pending_exception (&error);
7466                         return NULL;
7467                 }
7468                 /* Bypass remoting object creation check */
7469                 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7470                 mono_error_set_pending_exception (&error);
7471
7472                 return ret;
7473         }
7474 }
7475
7476 ICALL_EXPORT MonoString *
7477 ves_icall_System_IO_get_temp_path (void)
7478 {
7479         return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7480 }
7481
7482 #ifndef PLATFORM_NO_DRIVEINFO
7483 ICALL_EXPORT MonoBoolean
7484 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7485                                                 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7486                                                 gint32 *error)
7487 {
7488         gboolean result;
7489         ULARGE_INTEGER wapi_free_bytes_avail;
7490         ULARGE_INTEGER wapi_total_number_of_bytes;
7491         ULARGE_INTEGER wapi_total_number_of_free_bytes;
7492
7493         *error = ERROR_SUCCESS;
7494         result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7495                                      &wapi_total_number_of_free_bytes);
7496
7497         if (result) {
7498                 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7499                 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7500                 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7501         } else {
7502                 *free_bytes_avail = 0;
7503                 *total_number_of_bytes = 0;
7504                 *total_number_of_free_bytes = 0;
7505                 *error = GetLastError ();
7506         }
7507
7508         return result;
7509 }
7510
7511 ICALL_EXPORT guint32
7512 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7513 {
7514         return GetDriveType (mono_string_chars (root_path_name));
7515 }
7516 #endif
7517
7518 ICALL_EXPORT gpointer
7519 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7520 {
7521         MonoError error;
7522         gpointer result = mono_compile_method_checked (method, &error);
7523         mono_error_set_pending_exception (&error);
7524         return result;
7525 }
7526
7527 ICALL_EXPORT MonoString *
7528 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7529 {
7530         MonoString *mcpath;
7531         gchar *path;
7532
7533         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7534
7535 #if defined (HOST_WIN32)
7536         /* Avoid mixing '/' and '\\' */
7537         {
7538                 gint i;
7539                 for (i = strlen (path) - 1; i >= 0; i--)
7540                         if (path [i] == '/')
7541                                 path [i] = '\\';
7542         }
7543 #endif
7544         mcpath = mono_string_new (mono_domain_get (), path);
7545         g_free (path);
7546
7547         return mcpath;
7548 }
7549
7550 /* this is an icall */
7551 static MonoString *
7552 get_bundled_app_config (void)
7553 {
7554         MonoError error;
7555         const gchar *app_config;
7556         MonoDomain *domain;
7557         MonoString *file;
7558         gchar *config_file_name, *config_file_path;
7559         gsize len, config_file_path_length, config_ext_length;
7560         gchar *module;
7561
7562         domain = mono_domain_get ();
7563         file = domain->setup->configuration_file;
7564         if (!file || file->length == 0)
7565                 return NULL;
7566
7567         // Retrieve config file and remove the extension
7568         config_file_name = mono_string_to_utf8_checked (file, &error);
7569         if (mono_error_set_pending_exception (&error))
7570                 return NULL;
7571         config_file_path = mono_portability_find_file (config_file_name, TRUE);
7572         if (!config_file_path)
7573                 config_file_path = config_file_name;
7574
7575         config_file_path_length = strlen (config_file_path);
7576         config_ext_length = strlen (".config");
7577         if (config_file_path_length <= config_ext_length)
7578                 return NULL;
7579
7580         len = config_file_path_length - config_ext_length;
7581         module = (gchar *)g_malloc0 (len + 1);
7582         memcpy (module, config_file_path, len);
7583         // Get the config file from the module name
7584         app_config = mono_config_string_for_assembly_file (module);
7585         // Clean-up
7586         g_free (module);
7587         if (config_file_name != config_file_path)
7588                 g_free (config_file_name);
7589         g_free (config_file_path);
7590
7591         if (!app_config)
7592                 return NULL;
7593
7594         return mono_string_new (mono_domain_get (), app_config);
7595 }
7596
7597 static MonoString *
7598 get_bundled_machine_config (void)
7599 {
7600         const gchar *machine_config;
7601
7602         machine_config = mono_get_machine_config ();
7603
7604         if (!machine_config)
7605                 return NULL;
7606
7607         return mono_string_new (mono_domain_get (), machine_config);
7608 }
7609
7610 ICALL_EXPORT MonoString *
7611 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7612 {
7613         MonoString *ipath;
7614         gchar *path;
7615
7616         path = g_path_get_dirname (mono_get_config_dir ());
7617
7618 #if defined (HOST_WIN32)
7619         /* Avoid mixing '/' and '\\' */
7620         {
7621                 gint i;
7622                 for (i = strlen (path) - 1; i >= 0; i--)
7623                         if (path [i] == '/')
7624                                 path [i] = '\\';
7625         }
7626 #endif
7627         ipath = mono_string_new (mono_domain_get (), path);
7628         g_free (path);
7629
7630         return ipath;
7631 }
7632
7633 ICALL_EXPORT gboolean
7634 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7635 {
7636         MonoPEResourceDataEntry *entry;
7637         MonoImage *image;
7638
7639         if (!assembly || !result || !size)
7640                 return FALSE;
7641
7642         *result = NULL;
7643         *size = 0;
7644         image = assembly->assembly->image;
7645         entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7646         if (!entry)
7647                 return FALSE;
7648
7649         *result = mono_image_rva_map (image, entry->rde_data_offset);
7650         if (!(*result)) {
7651                 g_free (entry);
7652                 return FALSE;
7653         }
7654         *size = entry->rde_size;
7655         g_free (entry);
7656         return TRUE;
7657 }
7658
7659 ICALL_EXPORT MonoBoolean
7660 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7661 {
7662         return mono_is_debugger_attached ();
7663 }
7664
7665 ICALL_EXPORT MonoBoolean
7666 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7667 {
7668         if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7669                 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7670         else
7671                 return FALSE;
7672 }
7673
7674 ICALL_EXPORT void
7675 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7676 {
7677         if (mono_get_runtime_callbacks ()->debug_log)
7678                 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7679 }
7680
7681 ICALL_EXPORT void
7682 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7683 {
7684 #if defined (HOST_WIN32)
7685         OutputDebugString (mono_string_chars (message));
7686 #else
7687         g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7688 #endif
7689 }
7690
7691 /* Only used for value types */
7692 ICALL_EXPORT MonoObject *
7693 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7694 {
7695         MonoError error;
7696         MonoObject *result;
7697         MonoClass *klass;
7698         MonoDomain *domain;
7699         
7700         domain = mono_object_domain (type);
7701         klass = mono_class_from_mono_type (type->type);
7702         mono_class_init_checked (klass, &error);
7703         if (mono_error_set_pending_exception (&error))
7704                 return NULL;
7705
7706         if (mono_class_is_nullable (klass))
7707                 /* No arguments -> null */
7708                 return NULL;
7709
7710         result = mono_object_new_checked (domain, klass, &error);
7711         mono_error_set_pending_exception (&error);
7712         return result;
7713 }
7714
7715 ICALL_EXPORT MonoReflectionMethod *
7716 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7717 {
7718         MonoReflectionMethod *ret = NULL;
7719         MonoError error;
7720
7721         MonoClass *klass, *parent;
7722         MonoGenericContext *generic_inst = NULL;
7723         MonoMethod *method = m->method;
7724         MonoMethod *result = NULL;
7725         int slot;
7726
7727         if (method->klass == NULL)
7728                 return m;
7729
7730         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7731             MONO_CLASS_IS_INTERFACE (method->klass) ||
7732             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7733                 return m;
7734
7735         slot = mono_method_get_vtable_slot (method);
7736         if (slot == -1)
7737                 return m;
7738
7739         klass = method->klass;
7740         if (klass->generic_class) {
7741                 generic_inst = mono_class_get_context (klass);
7742                 klass = klass->generic_class->container_class;
7743         }
7744
7745         if (definition) {
7746                 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7747                 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7748                         /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7749                            or klass is the generic container class and generic_inst is the instantiation.
7750
7751                            when we go to the parent, if the parent is an open constructed type, we need to
7752                            replace the type parameters by the definitions from the generic_inst, and then take it
7753                            apart again into the klass and the generic_inst.
7754
7755                            For cases like this:
7756                            class C<T> : B<T, int> {
7757                                public override void Foo () { ... }
7758                            }
7759                            class B<U,V> : A<HashMap<U,V>> {
7760                                public override void Foo () { ... }
7761                            }
7762                            class A<X> {
7763                                public virtual void Foo () { ... }
7764                            }
7765
7766                            if at each iteration the parent isn't open, we can skip inflating it.  if at some
7767                            iteration the parent isn't generic (after possible inflation), we set generic_inst to
7768                            NULL;
7769                         */
7770                         MonoGenericContext *parent_inst = NULL;
7771                         if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7772                                 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7773                                 if (!mono_error_ok (&error)) {
7774                                         mono_error_set_pending_exception (&error);
7775                                         return NULL;
7776                                 }
7777                         }
7778                         if (parent->generic_class) {
7779                                 parent_inst = mono_class_get_context (parent);
7780                                 parent = parent->generic_class->container_class;
7781                         }
7782
7783                         mono_class_setup_vtable (parent);
7784                         if (parent->vtable_size <= slot)
7785                                 break;
7786                         klass = parent;
7787                         generic_inst = parent_inst;
7788                 }
7789         } else {
7790                 klass = klass->parent;
7791                 if (!klass)
7792                         return m;
7793                 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7794                         klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7795                         if (!mono_error_ok (&error)) {
7796                                 mono_error_set_pending_exception (&error);
7797                                 return NULL;
7798                         }
7799
7800                         generic_inst = NULL;
7801                 }
7802                 if (klass->generic_class) {
7803                         generic_inst = mono_class_get_context (klass);
7804                         klass = klass->generic_class->container_class;
7805                 }
7806
7807         }
7808
7809         if (generic_inst) {
7810                 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7811                 if (!mono_error_ok (&error)) {
7812                         mono_error_set_pending_exception (&error);
7813                         return NULL;
7814                 }
7815         }
7816
7817         if (klass == method->klass)
7818                 return m;
7819
7820         /*This is possible if definition == FALSE.
7821          * Do it here to be really sure we don't read invalid memory.
7822          */
7823         if (slot >= klass->vtable_size)
7824                 return m;
7825
7826         mono_class_setup_vtable (klass);
7827
7828         result = klass->vtable [slot];
7829         if (result == NULL) {
7830                 /* It is an abstract method */
7831                 gpointer iter = NULL;
7832                 while ((result = mono_class_get_methods (klass, &iter)))
7833                         if (result->slot == slot)
7834                                 break;
7835         }
7836
7837         if (result == NULL)
7838                 return m;
7839
7840         ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7841         mono_error_set_pending_exception (&error);
7842         return ret;
7843 }
7844
7845 ICALL_EXPORT MonoString*
7846 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7847 {
7848         MonoMethod *method = m->method;
7849
7850         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7851         return m->name;
7852 }
7853
7854 ICALL_EXPORT void
7855 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7856 {
7857         iter->sig = *(MonoMethodSignature**)argsp;
7858         
7859         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7860         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7861
7862         iter->next_arg = 0;
7863         /* FIXME: it's not documented what start is exactly... */
7864         if (start) {
7865                 iter->args = start;
7866         } else {
7867                 iter->args = argsp + sizeof (gpointer);
7868         }
7869         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7870
7871         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7872 }
7873
7874 ICALL_EXPORT MonoTypedRef
7875 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7876 {
7877         guint32 i, arg_size;
7878         gint32 align;
7879         MonoTypedRef res;
7880
7881         i = iter->sig->sentinelpos + iter->next_arg;
7882
7883         g_assert (i < iter->sig->param_count);
7884
7885         res.type = iter->sig->params [i];
7886         res.klass = mono_class_from_mono_type (res.type);
7887         arg_size = mono_type_stack_size (res.type, &align);
7888 #if defined(__arm__) || defined(__mips__)
7889         iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7890 #endif
7891         res.value = iter->args;
7892 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7893         /* Values are stored as 8 byte register sized objects, but 'value'
7894          * is dereferenced as a pointer in other routines.
7895          */
7896         res.value = (char*)res.value + 4;
7897 #endif
7898 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7899         if (arg_size <= sizeof (gpointer)) {
7900                 int dummy;
7901                 int padding = arg_size - mono_type_size (res.type, &dummy);
7902                 res.value = (guint8*)res.value + padding;
7903         }
7904 #endif
7905         iter->args = (char*)iter->args + arg_size;
7906         iter->next_arg++;
7907
7908         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7909
7910         return res;
7911 }
7912
7913 ICALL_EXPORT MonoTypedRef
7914 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7915 {
7916         guint32 i, arg_size;
7917         gint32 align;
7918         MonoTypedRef res;
7919
7920         i = iter->sig->sentinelpos + iter->next_arg;
7921
7922         g_assert (i < iter->sig->param_count);
7923
7924         while (i < iter->sig->param_count) {
7925                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7926                         continue;
7927                 res.type = iter->sig->params [i];
7928                 res.klass = mono_class_from_mono_type (res.type);
7929                 /* FIXME: endianess issue... */
7930                 arg_size = mono_type_stack_size (res.type, &align);
7931 #if defined(__arm__) || defined(__mips__)
7932                 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7933 #endif
7934                 res.value = iter->args;
7935                 iter->args = (char*)iter->args + arg_size;
7936                 iter->next_arg++;
7937                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7938                 return res;
7939         }
7940         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7941
7942         res.type = NULL;
7943         res.value = NULL;
7944         res.klass = NULL;
7945         return res;
7946 }
7947
7948 ICALL_EXPORT MonoType*
7949 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7950 {
7951         gint i;
7952         
7953         i = iter->sig->sentinelpos + iter->next_arg;
7954
7955         g_assert (i < iter->sig->param_count);
7956
7957         return iter->sig->params [i];
7958 }
7959
7960 ICALL_EXPORT MonoObject*
7961 mono_TypedReference_ToObject (MonoTypedRef* tref)
7962 {
7963         MonoError error;
7964         MonoObject *result = NULL;
7965         if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7966                 MonoObject** objp = (MonoObject **)tref->value;
7967                 return *objp;
7968         }
7969
7970         result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7971         mono_error_set_pending_exception (&error);
7972         return result;
7973 }
7974
7975 ICALL_EXPORT MonoTypedRef
7976 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7977 {
7978         MonoTypedRef res;
7979         MonoReflectionField *f;
7980         MonoClass *klass;
7981         MonoType *ftype = NULL;
7982         guint8 *p = NULL;
7983         int i;
7984
7985         memset (&res, 0, sizeof (res));
7986
7987         g_assert (fields);
7988         g_assert (mono_array_length (fields) > 0);
7989
7990         klass = target->vtable->klass;
7991
7992         for (i = 0; i < mono_array_length (fields); ++i) {
7993                 f = mono_array_get (fields, MonoReflectionField*, i);
7994                 if (f == NULL) {
7995                         mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7996                         return res;
7997                 }
7998                 if (f->field->parent != klass) {
7999                         mono_set_pending_exception (mono_get_exception_argument ("field", ""));
8000                         return res;
8001                 }
8002                 if (i == 0)
8003                         p = (guint8*)target + f->field->offset;
8004                 else
8005                         p += f->field->offset - sizeof (MonoObject);
8006                 klass = mono_class_from_mono_type (f->field->type);
8007                 ftype = f->field->type;
8008         }
8009
8010         res.type = ftype;
8011         res.klass = mono_class_from_mono_type (ftype);
8012         res.value = p;
8013
8014         return res;
8015 }
8016
8017 static void
8018 prelink_method (MonoMethod *method, MonoError *error)
8019 {
8020         const char *exc_class, *exc_arg;
8021
8022         mono_error_init (error);
8023         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
8024                 return;
8025         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
8026         if (exc_class) {
8027                 mono_error_set_exception_instance (error,
8028                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
8029                 return;
8030         }
8031         /* create the wrapper, too? */
8032 }
8033
8034 ICALL_EXPORT void
8035 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
8036 {
8037         MonoError error;
8038
8039         prelink_method (method->method, &error);
8040         mono_error_set_pending_exception (&error);
8041 }
8042
8043 ICALL_EXPORT void
8044 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
8045 {
8046         MonoError error;
8047         MonoClass *klass = mono_class_from_mono_type (type->type);
8048         MonoMethod* m;
8049         gpointer iter = NULL;
8050
8051         mono_class_init_checked (klass, &error);
8052         if (mono_error_set_pending_exception (&error))
8053                 return;
8054
8055         while ((m = mono_class_get_methods (klass, &iter))) {
8056                 prelink_method (m, &error);
8057                 if (mono_error_set_pending_exception (&error))
8058                         return;
8059         }
8060 }
8061
8062 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
8063 ICALL_EXPORT void
8064 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
8065                                             gint32 const **exponents,
8066                                             gunichar2 const **digitLowerTable,
8067                                             gunichar2 const **digitUpperTable,
8068                                             gint64 const **tenPowersList,
8069                                             gint32 const **decHexDigits)
8070 {
8071         *mantissas = Formatter_MantissaBitsTable;
8072         *exponents = Formatter_TensExponentTable;
8073         *digitLowerTable = Formatter_DigitLowerTable;
8074         *digitUpperTable = Formatter_DigitUpperTable;
8075         *tenPowersList = Formatter_TenPowersList;
8076         *decHexDigits = Formatter_DecHexDigits;
8077 }
8078
8079 /*
8080  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
8081  * and avoid useless allocations.
8082  */
8083 static MonoArray*
8084 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
8085 {
8086         MonoReflectionType *rt;
8087         MonoArray *res;
8088         int i, count = 0;
8089
8090         mono_error_init (error);
8091         for (i = 0; i < type->num_mods; ++i) {
8092                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
8093                         count++;
8094         }
8095         if (!count)
8096                 return NULL;
8097         res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
8098         return_val_if_nok (error, NULL);
8099         count = 0;
8100         for (i = 0; i < type->num_mods; ++i) {
8101                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
8102                         MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
8103                         return_val_if_nok (error, NULL);
8104
8105                         rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8106                         return_val_if_nok (error, NULL);
8107
8108                         mono_array_setref (res, count, rt);
8109                         count++;
8110                 }
8111         }
8112         return res;
8113 }
8114
8115 ICALL_EXPORT MonoArray*
8116 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
8117 {
8118         MonoError error;
8119         MonoType *type = param->ClassImpl->type;
8120         MonoClass *member_class = mono_object_class (param->MemberImpl);
8121         MonoMethod *method = NULL;
8122         MonoImage *image;
8123         int pos;
8124         MonoMethodSignature *sig;
8125         MonoArray *res;
8126
8127         if (mono_class_is_reflection_method_or_constructor (member_class)) {
8128                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8129                 method = rmethod->method;
8130         } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
8131                 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8132                 if (!(method = prop->property->get))
8133                         method = prop->property->set;
8134                 g_assert (method);      
8135         } else {
8136                 char *type_name = mono_type_get_full_name (member_class);
8137                 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
8138                 MonoException *ex = mono_get_exception_not_supported  (msg);
8139                 g_free (type_name);
8140                 g_free (msg);
8141                 mono_set_pending_exception (ex);
8142                 return NULL;
8143         }
8144
8145         image = method->klass->image;
8146         pos = param->PositionImpl;
8147         sig = mono_method_signature (method);
8148         if (pos == -1)
8149                 type = sig->ret;
8150         else
8151                 type = sig->params [pos];
8152
8153         res = type_array_from_modifiers (image, type, optional, &error);
8154         mono_error_set_pending_exception (&error);
8155         return res;
8156 }
8157
8158 static MonoType*
8159 get_property_type (MonoProperty *prop)
8160 {
8161         MonoMethodSignature *sig;
8162         if (prop->get) {
8163                 sig = mono_method_signature (prop->get);
8164                 return sig->ret;
8165         } else if (prop->set) {
8166                 sig = mono_method_signature (prop->set);
8167                 return sig->params [sig->param_count - 1];
8168         }
8169         return NULL;
8170 }
8171
8172 ICALL_EXPORT MonoArray*
8173 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8174 {
8175         MonoError error;
8176         MonoType *type = get_property_type (property->property);
8177         MonoImage *image = property->klass->image;
8178         MonoArray *res;
8179
8180         if (!type)
8181                 return NULL;
8182         res = type_array_from_modifiers (image, type, optional, &error);
8183         mono_error_set_pending_exception (&error);
8184         return res;
8185 }
8186
8187 /*
8188  *Construct a MonoType suited to be used to decode a constant blob object.
8189  *
8190  * @type is the target type which will be constructed
8191  * @blob_type is the blob type, for example, that comes from the constant table
8192  * @real_type is the expected constructed type.
8193  */
8194 static void
8195 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8196 {
8197         type->type = blob_type;
8198         type->data.klass = NULL;
8199         if (blob_type == MONO_TYPE_CLASS)
8200                 type->data.klass = mono_defaults.object_class;
8201         else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8202                 /* For enums, we need to use the base type */
8203                 type->type = MONO_TYPE_VALUETYPE;
8204                 type->data.klass = mono_class_from_mono_type (real_type);
8205         } else
8206                 type->data.klass = mono_class_from_mono_type (real_type);
8207 }
8208
8209 ICALL_EXPORT MonoObject*
8210 property_info_get_default_value (MonoReflectionProperty *property)
8211 {
8212         MonoError error;
8213         MonoType blob_type;
8214         MonoProperty *prop = property->property;
8215         MonoType *type = get_property_type (prop);
8216         MonoDomain *domain = mono_object_domain (property); 
8217         MonoTypeEnum def_type;
8218         const char *def_value;
8219         MonoObject *o;
8220
8221         mono_class_init (prop->parent);
8222
8223         if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8224                 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8225                 return NULL;
8226         }
8227
8228         def_value = mono_class_get_property_default_value (prop, &def_type);
8229
8230         mono_type_from_blob_type (&blob_type, def_type, type);
8231         o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8232
8233         mono_error_set_pending_exception (&error);
8234         return o;
8235 }
8236
8237 ICALL_EXPORT MonoBoolean
8238 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8239 {
8240         MonoError error;
8241         MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8242         MonoCustomAttrInfo *cinfo;
8243         gboolean found;
8244
8245         mono_class_init_checked (attr_class, &error);
8246         if (mono_error_set_pending_exception (&error))
8247                 return FALSE;
8248
8249         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8250         if (!is_ok (&error)) {
8251                 mono_error_set_pending_exception (&error);
8252                 return FALSE;
8253         }
8254         if (!cinfo)
8255                 return FALSE;
8256         found = mono_custom_attrs_has_attr (cinfo, attr_class);
8257         if (!cinfo->cached)
8258                 mono_custom_attrs_free (cinfo);
8259         return found;
8260 }
8261
8262 ICALL_EXPORT MonoArray*
8263 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8264 {
8265         MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8266         MonoArray *res;
8267         MonoError error;
8268
8269         if (attr_class) {
8270                 mono_class_init_checked (attr_class, &error);
8271                 if (mono_error_set_pending_exception (&error))
8272                         return NULL;
8273         }
8274
8275         res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8276         if (!mono_error_ok (&error)) {
8277                 mono_error_set_pending_exception (&error);
8278                 return NULL;
8279         }
8280
8281         return res;
8282 }
8283
8284 ICALL_EXPORT MonoArray*
8285 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8286 {
8287         MonoError error;
8288         MonoArray *result;
8289         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8290         mono_error_set_pending_exception (&error);
8291         return result;
8292 }
8293
8294
8295 ICALL_EXPORT MonoString*
8296 ves_icall_Mono_Runtime_GetDisplayName (void)
8297 {
8298         char *info;
8299         MonoString *display_name;
8300
8301         info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8302         display_name = mono_string_new (mono_domain_get (), info);
8303         g_free (info);
8304         return display_name;
8305 }
8306
8307 ICALL_EXPORT MonoString*
8308 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8309 {
8310         MonoError error;
8311         MonoString *message;
8312         guint32 ret;
8313         gunichar2 buf[256];
8314         
8315         ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8316                              FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8317                              buf, 255, NULL);
8318         if (ret == 0) {
8319                 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8320         } else {
8321                 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8322                 if (mono_error_set_pending_exception (&error))
8323                         return NULL;
8324         }
8325         
8326         return message;
8327 }
8328
8329 ICALL_EXPORT gpointer
8330 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8331 {
8332         return GetCurrentProcess ();
8333 }
8334
8335 ICALL_EXPORT MonoBoolean
8336 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8337 {
8338         return GetExitCodeProcess (handle, (guint32*) exitcode);
8339 }
8340
8341 ICALL_EXPORT MonoBoolean
8342 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8343 {
8344 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8345         return CloseHandle (handle);
8346 #else
8347         return CloseProcess (handle);
8348 #endif
8349 }
8350
8351 ICALL_EXPORT MonoBoolean
8352 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8353 {
8354         return TerminateProcess (handle, exitcode);
8355 }
8356
8357 ICALL_EXPORT gint32
8358 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8359 {
8360         return WaitForInputIdle (handle, milliseconds);
8361 }
8362
8363 ICALL_EXPORT MonoBoolean
8364 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8365 {
8366         return GetProcessWorkingSetSize (handle, min, max);
8367 }
8368
8369 ICALL_EXPORT MonoBoolean
8370 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8371 {
8372         return SetProcessWorkingSetSize (handle, min, max);
8373 }
8374
8375 ICALL_EXPORT MonoBoolean
8376 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8377 {
8378         return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8379 }
8380
8381 ICALL_EXPORT gint32
8382 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8383 {
8384         return mono_process_current_pid ();
8385 }
8386
8387 ICALL_EXPORT gint32
8388 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8389 {
8390         return GetPriorityClass (handle);
8391 }
8392
8393 ICALL_EXPORT MonoBoolean
8394 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8395 {
8396         return SetPriorityClass (handle, priorityClass);
8397 }
8398
8399 #ifndef DISABLE_ICALL_TABLES
8400
8401 #define ICALL_TYPE(id,name,first)
8402 #define ICALL(id,name,func) Icall_ ## id,
8403
8404 enum {
8405 #include "metadata/icall-def.h"
8406         Icall_last
8407 };
8408
8409 #undef ICALL_TYPE
8410 #undef ICALL
8411 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8412 #define ICALL(id,name,func)
8413 enum {
8414 #include "metadata/icall-def.h"
8415         Icall_type_num
8416 };
8417
8418 #undef ICALL_TYPE
8419 #undef ICALL
8420 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8421 #define ICALL(id,name,func)
8422 typedef struct {
8423         guint16 first_icall;
8424 } IcallTypeDesc;
8425
8426 static const IcallTypeDesc
8427 icall_type_descs [] = {
8428 #include "metadata/icall-def.h"
8429         {Icall_last}
8430 };
8431
8432 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8433
8434 #undef ICALL_TYPE
8435 #define ICALL_TYPE(id,name,first)
8436 #undef ICALL
8437
8438 #ifdef HAVE_ARRAY_ELEM_INIT
8439 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8440 #define MSGSTRFIELD1(line) str##line
8441
8442 static const struct msgstrtn_t {
8443 #define ICALL(id,name,func)
8444 #undef ICALL_TYPE
8445 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8446 #include "metadata/icall-def.h"
8447 #undef ICALL_TYPE
8448 } icall_type_names_str = {
8449 #define ICALL_TYPE(id,name,first) (name),
8450 #include "metadata/icall-def.h"
8451 #undef ICALL_TYPE
8452 };
8453 static const guint16 icall_type_names_idx [] = {
8454 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8455 #include "metadata/icall-def.h"
8456 #undef ICALL_TYPE
8457 };
8458 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8459
8460 static const struct msgstr_t {
8461 #undef ICALL
8462 #define ICALL_TYPE(id,name,first)
8463 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8464 #include "metadata/icall-def.h"
8465 #undef ICALL
8466 } icall_names_str = {
8467 #define ICALL(id,name,func) (name),
8468 #include "metadata/icall-def.h"
8469 #undef ICALL
8470 };
8471 static const guint16 icall_names_idx [] = {
8472 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8473 #include "metadata/icall-def.h"
8474 #undef ICALL
8475 };
8476 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8477
8478 #else
8479
8480 #undef ICALL_TYPE
8481 #undef ICALL
8482 #define ICALL_TYPE(id,name,first) name,
8483 #define ICALL(id,name,func)
8484 static const char* const
8485 icall_type_names [] = {
8486 #include "metadata/icall-def.h"
8487         NULL
8488 };
8489
8490 #define icall_type_name_get(id) (icall_type_names [(id)])
8491
8492 #undef ICALL_TYPE
8493 #undef ICALL
8494 #define ICALL_TYPE(id,name,first)
8495 #define ICALL(id,name,func) name,
8496 static const char* const
8497 icall_names [] = {
8498 #include "metadata/icall-def.h"
8499         NULL
8500 };
8501 #define icall_name_get(id) icall_names [(id)]
8502
8503 #endif /* !HAVE_ARRAY_ELEM_INIT */
8504
8505 #undef ICALL_TYPE
8506 #undef ICALL
8507 #define ICALL_TYPE(id,name,first)
8508 #define ICALL(id,name,func) func,
8509 static const gconstpointer
8510 icall_functions [] = {
8511 #include "metadata/icall-def.h"
8512         NULL
8513 };
8514
8515 #ifdef ENABLE_ICALL_SYMBOL_MAP
8516 #undef ICALL_TYPE
8517 #undef ICALL
8518 #define ICALL_TYPE(id,name,first)
8519 #define ICALL(id,name,func) #func,
8520 static const gconstpointer
8521 icall_symbols [] = {
8522 #include "metadata/icall-def.h"
8523         NULL
8524 };
8525 #endif
8526
8527 #endif /* DISABLE_ICALL_TABLES */
8528
8529 static mono_mutex_t icall_mutex;
8530 static GHashTable *icall_hash = NULL;
8531 static GHashTable *jit_icall_hash_name = NULL;
8532 static GHashTable *jit_icall_hash_addr = NULL;
8533
8534 void
8535 mono_icall_init (void)
8536 {
8537 #ifndef DISABLE_ICALL_TABLES
8538         int i = 0;
8539
8540         /* check that tables are sorted: disable in release */
8541         if (TRUE) {
8542                 int j;
8543                 const char *prev_class = NULL;
8544                 const char *prev_method;
8545                 
8546                 for (i = 0; i < Icall_type_num; ++i) {
8547                         const IcallTypeDesc *desc;
8548                         int num_icalls;
8549                         prev_method = NULL;
8550                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8551                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8552                         prev_class = icall_type_name_get (i);
8553                         desc = &icall_type_descs [i];
8554                         num_icalls = icall_desc_num_icalls (desc);
8555                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8556                         for (j = 0; j < num_icalls; ++j) {
8557                                 const char *methodn = icall_name_get (desc->first_icall + j);
8558                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
8559                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
8560                                 prev_method = methodn;
8561                         }
8562                 }
8563         }
8564 #endif
8565
8566         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8567         mono_os_mutex_init (&icall_mutex);
8568 }
8569
8570 static void
8571 mono_icall_lock (void)
8572 {
8573         mono_locks_os_acquire (&icall_mutex, IcallLock);
8574 }
8575
8576 static void
8577 mono_icall_unlock (void)
8578 {
8579         mono_locks_os_release (&icall_mutex, IcallLock);
8580 }
8581
8582 void
8583 mono_icall_cleanup (void)
8584 {
8585         g_hash_table_destroy (icall_hash);
8586         g_hash_table_destroy (jit_icall_hash_name);
8587         g_hash_table_destroy (jit_icall_hash_addr);
8588         mono_os_mutex_destroy (&icall_mutex);
8589 }
8590
8591 /**
8592  * mono_add_internal_call:
8593  * @name: method specification to surface to the managed world
8594  * @method: pointer to a C method to invoke when the method is called
8595  *
8596  * This method surfaces the C function pointed by @method as a method
8597  * that has been surfaced in managed code with the method specified in
8598  * @name as an internal call.
8599  *
8600  * Internal calls are surfaced to all app domains loaded and they are
8601  * accessibly by a type with the specified name.
8602  *
8603  * You must provide a fully qualified type name, that is namespaces
8604  * and type name, followed by a colon and the method name, with an
8605  * optional signature to bind.
8606  *
8607  * For example, the following are all valid declarations:
8608  *
8609  * "MyApp.Services.ScriptService:Accelerate"
8610  * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8611  *
8612  * You use method parameters in cases where there might be more than
8613  * one surface method to managed code.  That way you can register different
8614  * internal calls for different method overloads.
8615  *
8616  * The internal calls are invoked with no marshalling.   This means that .NET
8617  * types like System.String are exposed as `MonoString *` parameters.   This is
8618  * different than the way that strings are surfaced in P/Invoke.
8619  *
8620  * For more information on how the parameters are marshalled, see the
8621  * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8622  * page.
8623  *
8624  * See the <a  href="mono-api-methods.html#method-desc">Method Description</a>
8625  * reference for more information on the format of method descriptions.
8626  */
8627 void
8628 mono_add_internal_call (const char *name, gconstpointer method)
8629 {
8630         mono_icall_lock ();
8631
8632         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8633
8634         mono_icall_unlock ();
8635 }
8636
8637 #ifndef DISABLE_ICALL_TABLES
8638
8639 #ifdef HAVE_ARRAY_ELEM_INIT
8640 static int
8641 compare_method_imap (const void *key, const void *elem)
8642 {
8643         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8644         return strcmp (key, method_name);
8645 }
8646
8647 static gpointer
8648 find_method_icall (const IcallTypeDesc *imap, const char *name)
8649 {
8650         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);
8651         if (!nameslot)
8652                 return NULL;
8653         return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8654 }
8655
8656 static int
8657 compare_class_imap (const void *key, const void *elem)
8658 {
8659         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8660         return strcmp (key, class_name);
8661 }
8662
8663 static const IcallTypeDesc*
8664 find_class_icalls (const char *name)
8665 {
8666         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);
8667         if (!nameslot)
8668                 return NULL;
8669         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8670 }
8671
8672 #else /* HAVE_ARRAY_ELEM_INIT */
8673
8674 static int
8675 compare_method_imap (const void *key, const void *elem)
8676 {
8677         const char** method_name = (const char**)elem;
8678         return strcmp (key, *method_name);
8679 }
8680
8681 static gpointer
8682 find_method_icall (const IcallTypeDesc *imap, const char *name)
8683 {
8684         const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8685         if (!nameslot)
8686                 return NULL;
8687         return (gpointer)icall_functions [(nameslot - icall_names)];
8688 }
8689
8690 static int
8691 compare_class_imap (const void *key, const void *elem)
8692 {
8693         const char** class_name = (const char**)elem;
8694         return strcmp (key, *class_name);
8695 }
8696
8697 static const IcallTypeDesc*
8698 find_class_icalls (const char *name)
8699 {
8700         const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8701         if (!nameslot)
8702                 return NULL;
8703         return &icall_type_descs [nameslot - icall_type_names];
8704 }
8705
8706 #endif /* HAVE_ARRAY_ELEM_INIT */
8707
8708 #endif /* DISABLE_ICALL_TABLES */
8709
8710 /* 
8711  * we should probably export this as an helper (handle nested types).
8712  * Returns the number of chars written in buf.
8713  */
8714 static int
8715 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8716 {
8717         int nspacelen, cnamelen;
8718         nspacelen = strlen (klass->name_space);
8719         cnamelen = strlen (klass->name);
8720         if (nspacelen + cnamelen + 2 > bufsize)
8721                 return 0;
8722         if (nspacelen) {
8723                 memcpy (buf, klass->name_space, nspacelen);
8724                 buf [nspacelen ++] = '.';
8725         }
8726         memcpy (buf + nspacelen, klass->name, cnamelen);
8727         buf [nspacelen + cnamelen] = 0;
8728         return nspacelen + cnamelen;
8729 }
8730
8731 #ifdef DISABLE_ICALL_TABLES
8732 static void
8733 no_icall_table (void)
8734 {
8735         g_assert_not_reached ();
8736 }
8737 #endif
8738
8739 gpointer
8740 mono_lookup_internal_call (MonoMethod *method)
8741 {
8742         char *sigstart;
8743         char *tmpsig;
8744         char mname [2048];
8745         int typelen = 0, mlen, siglen;
8746         gpointer res;
8747 #ifndef DISABLE_ICALL_TABLES
8748         const IcallTypeDesc *imap = NULL;
8749 #endif
8750
8751         g_assert (method != NULL);
8752
8753         if (method->is_inflated)
8754                 method = ((MonoMethodInflated *) method)->declaring;
8755
8756         if (method->klass->nested_in) {
8757                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8758                 if (!pos)
8759                         return NULL;
8760
8761                 mname [pos++] = '/';
8762                 mname [pos] = 0;
8763
8764                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8765                 if (!typelen)
8766                         return NULL;
8767
8768                 typelen += pos;
8769         } else {
8770                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8771                 if (!typelen)
8772                         return NULL;
8773         }
8774
8775 #ifndef DISABLE_ICALL_TABLES
8776         imap = find_class_icalls (mname);
8777 #endif
8778
8779         mname [typelen] = ':';
8780         mname [typelen + 1] = ':';
8781
8782         mlen = strlen (method->name);
8783         memcpy (mname + typelen + 2, method->name, mlen);
8784         sigstart = mname + typelen + 2 + mlen;
8785         *sigstart = 0;
8786
8787         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8788         siglen = strlen (tmpsig);
8789         if (typelen + mlen + siglen + 6 > sizeof (mname))
8790                 return NULL;
8791         sigstart [0] = '(';
8792         memcpy (sigstart + 1, tmpsig, siglen);
8793         sigstart [siglen + 1] = ')';
8794         sigstart [siglen + 2] = 0;
8795         g_free (tmpsig);
8796         
8797         mono_icall_lock ();
8798
8799         res = g_hash_table_lookup (icall_hash, mname);
8800         if (res) {
8801                 mono_icall_unlock ();;
8802                 return res;
8803         }
8804         /* try without signature */
8805         *sigstart = 0;
8806         res = g_hash_table_lookup (icall_hash, mname);
8807         if (res) {
8808                 mono_icall_unlock ();
8809                 return res;
8810         }
8811
8812 #ifdef DISABLE_ICALL_TABLES
8813         mono_icall_unlock ();
8814         /* Fail only when the result is actually used */
8815         /* mono_marshal_get_native_wrapper () depends on this */
8816         if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8817                 return ves_icall_System_String_ctor_RedirectToCreateString;
8818         else
8819                 return no_icall_table;
8820 #else
8821         /* it wasn't found in the static call tables */
8822         if (!imap) {
8823                 mono_icall_unlock ();
8824                 return NULL;
8825         }
8826         res = find_method_icall (imap, sigstart - mlen);
8827         if (res) {
8828                 mono_icall_unlock ();
8829                 return res;
8830         }
8831         /* try _with_ signature */
8832         *sigstart = '(';
8833         res = find_method_icall (imap, sigstart - mlen);
8834         if (res) {
8835                 mono_icall_unlock ();
8836                 return res;
8837         }
8838
8839         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8840         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8841         g_print ("The out of sync library is: %s\n", method->klass->image->name);
8842         g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8843         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");
8844         g_print ("If you see other errors or faults after this message they are probably related\n");
8845         g_print ("and you need to fix your mono install first.\n");
8846
8847         mono_icall_unlock ();
8848
8849         return NULL;
8850 #endif
8851 }
8852
8853 #ifdef ENABLE_ICALL_SYMBOL_MAP
8854 static int
8855 func_cmp (gconstpointer key, gconstpointer p)
8856 {
8857         return (gsize)key - (gsize)*(gsize*)p;
8858 }
8859 #endif
8860
8861 /*
8862  * mono_lookup_icall_symbol:
8863  *
8864  *   Given the icall METHOD, returns its C symbol.
8865  */
8866 const char*
8867 mono_lookup_icall_symbol (MonoMethod *m)
8868 {
8869 #ifdef DISABLE_ICALL_TABLES
8870         g_assert_not_reached ();
8871         return NULL;
8872 #else
8873 #ifdef ENABLE_ICALL_SYMBOL_MAP
8874         gpointer func;
8875         int i;
8876         gpointer slot;
8877         static gconstpointer *functions_sorted;
8878         static const char**symbols_sorted;
8879         static gboolean inited;
8880
8881         if (!inited) {
8882                 gboolean changed;
8883
8884                 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8885                 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8886                 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8887                 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8888                 /* Bubble sort the two arrays */
8889                 changed = TRUE;
8890                 while (changed) {
8891                         changed = FALSE;
8892                         for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8893                                 if (functions_sorted [i] > functions_sorted [i + 1]) {
8894                                         gconstpointer tmp;
8895
8896                                         tmp = functions_sorted [i];
8897                                         functions_sorted [i] = functions_sorted [i + 1];
8898                                         functions_sorted [i + 1] = tmp;
8899                                         tmp = symbols_sorted [i];
8900                                         symbols_sorted [i] = symbols_sorted [i + 1];
8901                                         symbols_sorted [i + 1] = tmp;
8902                                         changed = TRUE;
8903                                 }
8904                         }
8905                 }
8906         }
8907
8908         func = mono_lookup_internal_call (m);
8909         if (!func)
8910                 return NULL;
8911         slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8912         if (!slot)
8913                 return NULL;
8914         g_assert (slot);
8915         return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8916 #else
8917         fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8918         g_assert_not_reached ();
8919         return 0;
8920 #endif
8921 #endif
8922 }
8923
8924 static MonoType*
8925 type_from_typename (char *type_name)
8926 {
8927         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
8928
8929         if (!strcmp (type_name, "int"))
8930                 klass = mono_defaults.int_class;
8931         else if (!strcmp (type_name, "ptr"))
8932                 klass = mono_defaults.int_class;
8933         else if (!strcmp (type_name, "void"))
8934                 klass = mono_defaults.void_class;
8935         else if (!strcmp (type_name, "int32"))
8936                 klass = mono_defaults.int32_class;
8937         else if (!strcmp (type_name, "uint32"))
8938                 klass = mono_defaults.uint32_class;
8939         else if (!strcmp (type_name, "int8"))
8940                 klass = mono_defaults.sbyte_class;
8941         else if (!strcmp (type_name, "uint8"))
8942                 klass = mono_defaults.byte_class;
8943         else if (!strcmp (type_name, "int16"))
8944                 klass = mono_defaults.int16_class;
8945         else if (!strcmp (type_name, "uint16"))
8946                 klass = mono_defaults.uint16_class;
8947         else if (!strcmp (type_name, "long"))
8948                 klass = mono_defaults.int64_class;
8949         else if (!strcmp (type_name, "ulong"))
8950                 klass = mono_defaults.uint64_class;
8951         else if (!strcmp (type_name, "float"))
8952                 klass = mono_defaults.single_class;
8953         else if (!strcmp (type_name, "double"))
8954                 klass = mono_defaults.double_class;
8955         else if (!strcmp (type_name, "object"))
8956                 klass = mono_defaults.object_class;
8957         else if (!strcmp (type_name, "obj"))
8958                 klass = mono_defaults.object_class;
8959         else if (!strcmp (type_name, "string"))
8960                 klass = mono_defaults.string_class;
8961         else if (!strcmp (type_name, "bool"))
8962                 klass = mono_defaults.boolean_class;
8963         else if (!strcmp (type_name, "boolean"))
8964                 klass = mono_defaults.boolean_class;
8965         else {
8966                 g_error ("%s", type_name);
8967                 g_assert_not_reached ();
8968         }
8969         return &klass->byval_arg;
8970 }
8971
8972 /**
8973  * LOCKING: Take the corlib image lock.
8974  */
8975 MonoMethodSignature*
8976 mono_create_icall_signature (const char *sigstr)
8977 {
8978         gchar **parts;
8979         int i, len;
8980         gchar **tmp;
8981         MonoMethodSignature *res, *res2;
8982         MonoImage *corlib = mono_defaults.corlib;
8983
8984         mono_image_lock (corlib);
8985         res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8986         mono_image_unlock (corlib);
8987
8988         if (res)
8989                 return res;
8990
8991         parts = g_strsplit (sigstr, " ", 256);
8992
8993         tmp = parts;
8994         len = 0;
8995         while (*tmp) {
8996                 len ++;
8997                 tmp ++;
8998         }
8999
9000         res = mono_metadata_signature_alloc (corlib, len - 1);
9001         res->pinvoke = 1;
9002
9003 #ifdef HOST_WIN32
9004         /* 
9005          * Under windows, the default pinvoke calling convention is STDCALL but
9006          * we need CDECL.
9007          */
9008         res->call_convention = MONO_CALL_C;
9009 #endif
9010
9011         res->ret = type_from_typename (parts [0]);
9012         for (i = 1; i < len; ++i) {
9013                 res->params [i - 1] = type_from_typename (parts [i]);
9014         }
9015
9016         g_strfreev (parts);
9017
9018         mono_image_lock (corlib);
9019         res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
9020         if (res2)
9021                 res = res2; /*Value is allocated in the image pool*/
9022         else
9023                 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
9024         mono_image_unlock (corlib);
9025
9026         return res;
9027 }
9028
9029 MonoJitICallInfo *
9030 mono_find_jit_icall_by_name (const char *name)
9031 {
9032         MonoJitICallInfo *info;
9033         g_assert (jit_icall_hash_name);
9034
9035         mono_icall_lock ();
9036         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9037         mono_icall_unlock ();
9038         return info;
9039 }
9040
9041 MonoJitICallInfo *
9042 mono_find_jit_icall_by_addr (gconstpointer addr)
9043 {
9044         MonoJitICallInfo *info;
9045         g_assert (jit_icall_hash_addr);
9046
9047         mono_icall_lock ();
9048         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
9049         mono_icall_unlock ();
9050
9051         return info;
9052 }
9053
9054 /*
9055  * mono_get_jit_icall_info:
9056  *
9057  *   Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
9058  * caller should access it while holding the icall lock.
9059  */
9060 GHashTable*
9061 mono_get_jit_icall_info (void)
9062 {
9063         return jit_icall_hash_name;
9064 }
9065
9066 /*
9067  * mono_lookup_jit_icall_symbol:
9068  *
9069  *   Given the jit icall NAME, returns its C symbol if possible, or NULL.
9070  */
9071 const char*
9072 mono_lookup_jit_icall_symbol (const char *name)
9073 {
9074         MonoJitICallInfo *info;
9075         const char *res = NULL;
9076
9077         mono_icall_lock ();
9078         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9079         if (info)
9080                 res = info->c_symbol;
9081         mono_icall_unlock ();
9082         return res;
9083 }
9084
9085 void
9086 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
9087 {
9088         mono_icall_lock ();
9089         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
9090         mono_icall_unlock ();
9091 }
9092
9093 /*
9094  * 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
9095  * icalls without wrappers in some cases.
9096  */
9097 MonoJitICallInfo *
9098 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
9099 {
9100         MonoJitICallInfo *info;
9101         
9102         g_assert (func);
9103         g_assert (name);
9104
9105         mono_icall_lock ();
9106
9107         if (!jit_icall_hash_name) {
9108                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
9109                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
9110         }
9111
9112         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
9113                 g_warning ("jit icall already defined \"%s\"\n", name);
9114                 g_assert_not_reached ();
9115         }
9116
9117         info = g_new0 (MonoJitICallInfo, 1);
9118         
9119         info->name = name;
9120         info->func = func;
9121         info->sig = sig;
9122         info->c_symbol = c_symbol;
9123         info->no_raise = no_raise;
9124
9125         if (is_save) {
9126                 info->wrapper = func;
9127         } else {
9128                 info->wrapper = NULL;
9129         }
9130
9131         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
9132         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
9133
9134         mono_icall_unlock ();
9135         return info;
9136 }
9137
9138 MonoJitICallInfo *
9139 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
9140 {
9141         return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);
9142 }
9143