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