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