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