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