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