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