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