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