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