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