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