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