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