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