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