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