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