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