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