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