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