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