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