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