[reflection] Use MonoError for mono_module_get_object
[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         MonoError error;
2410         MonoReflectionModule *result = NULL;
2411         MonoClass *klass = mono_class_from_mono_type (type->type);
2412         result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2413         if (!mono_error_ok (&error))
2414                 mono_error_set_pending_exception (&error);
2415         return result;
2416 }
2417
2418 ICALL_EXPORT MonoReflectionAssembly*
2419 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2420 {
2421         MonoDomain *domain = mono_domain_get (); 
2422         MonoClass *klass = mono_class_from_mono_type (type->type);
2423         return mono_assembly_get_object (domain, klass->image->assembly);
2424 }
2425
2426 ICALL_EXPORT MonoReflectionType*
2427 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2428 {
2429         MonoError error;
2430         MonoReflectionType *ret;
2431         MonoDomain *domain = mono_domain_get ();
2432         MonoClass *klass;
2433
2434         if (type->type->byref)
2435                 return NULL;
2436         if (type->type->type == MONO_TYPE_VAR) {
2437                 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2438                 klass = param ? param->owner.klass : NULL;
2439         } else if (type->type->type == MONO_TYPE_MVAR) {
2440                 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2441                 klass = param ? param->owner.method->klass : NULL;
2442         } else {
2443                 klass = mono_class_from_mono_type (type->type)->nested_in;
2444         }
2445
2446         if (!klass)
2447                 return NULL;
2448
2449         ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2450         mono_error_raise_exception (&error);
2451
2452         return ret;
2453 }
2454
2455 ICALL_EXPORT MonoString*
2456 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2457 {
2458         MonoDomain *domain = mono_domain_get (); 
2459         MonoClass *klass = mono_class_from_mono_type (type->type);
2460
2461         if (type->type->byref) {
2462                 char *n = g_strdup_printf ("%s&", klass->name);
2463                 MonoString *res = mono_string_new (domain, n);
2464
2465                 g_free (n);
2466
2467                 return res;
2468         } else {
2469                 return mono_string_new (domain, klass->name);
2470         }
2471 }
2472
2473 ICALL_EXPORT MonoString*
2474 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2475 {
2476         MonoDomain *domain = mono_domain_get (); 
2477         MonoClass *klass = mono_class_from_mono_type (type->type);
2478
2479         while (klass->nested_in)
2480                 klass = klass->nested_in;
2481
2482         if (klass->name_space [0] == '\0')
2483                 return NULL;
2484         else
2485                 return mono_string_new (domain, klass->name_space);
2486 }
2487
2488 ICALL_EXPORT gint32
2489 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2490 {
2491         MonoClass *klass;
2492
2493         if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2494                 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2495                 return 0;
2496         }
2497
2498         klass = mono_class_from_mono_type (type->type);
2499
2500         return klass->rank;
2501 }
2502
2503 static MonoArray*
2504 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2505 {
2506         MonoArray *res;
2507         res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2508         return res;
2509 }
2510
2511 ICALL_EXPORT MonoArray*
2512 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2513 {
2514         MonoError error;
2515         MonoReflectionType *rt;
2516         MonoArray *res;
2517         MonoClass *klass, *pklass;
2518         MonoDomain *domain = mono_object_domain (type);
2519         int i;
2520
2521         klass = mono_class_from_mono_type (type->type);
2522
2523         if (klass->generic_container) {
2524                 MonoGenericContainer *container = klass->generic_container;
2525                 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2526                 for (i = 0; i < container->type_argc; ++i) {
2527                         pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2528
2529                         rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2530                         mono_error_raise_exception (&error);
2531
2532                         mono_array_setref (res, i, rt);
2533                 }
2534         } else if (klass->generic_class) {
2535                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2536                 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2537                 for (i = 0; i < inst->type_argc; ++i) {
2538                         rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2539                         mono_error_raise_exception (&error);
2540
2541                         mono_array_setref (res, i, rt);
2542                 }
2543         } else {
2544                 res = NULL;
2545         }
2546         return res;
2547 }
2548
2549 ICALL_EXPORT gboolean
2550 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2551 {
2552         MonoClass *klass;
2553
2554         if (!IS_MONOTYPE (type))
2555                 return FALSE;
2556
2557         if (type->type->byref)
2558                 return FALSE;
2559
2560         klass = mono_class_from_mono_type (type->type);
2561         return klass->generic_container != NULL;
2562 }
2563
2564 ICALL_EXPORT MonoReflectionType*
2565 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2566 {
2567         MonoError error;
2568         MonoReflectionType *ret;
2569         MonoClass *klass;
2570
2571         if (type->type->byref)
2572                 return NULL;
2573
2574         klass = mono_class_from_mono_type (type->type);
2575
2576         if (klass->generic_container) {
2577                 return type; /* check this one */
2578         }
2579         if (klass->generic_class) {
2580                 MonoClass *generic_class = klass->generic_class->container_class;
2581                 gpointer tb;
2582
2583                 tb = mono_class_get_ref_info (generic_class);
2584
2585                 if (generic_class->wastypebuilder && tb)
2586                         return (MonoReflectionType *)tb;
2587                 else {
2588                         ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2589                         mono_error_raise_exception (&error);
2590
2591                         return ret;
2592                 }
2593         }
2594         return NULL;
2595 }
2596
2597 ICALL_EXPORT MonoReflectionType*
2598 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2599 {
2600         MonoError error;
2601         MonoReflectionType *ret;
2602         MonoClass *klass;
2603         MonoType *geninst, **types;
2604         int i, count;
2605
2606         g_assert (IS_MONOTYPE (type));
2607         mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2608
2609         count = mono_array_length (type_array);
2610         types = g_new0 (MonoType *, count);
2611
2612         for (i = 0; i < count; i++) {
2613                 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2614                 types [i] = t->type;
2615         }
2616
2617         geninst = mono_reflection_bind_generic_parameters (type, count, types);
2618         g_free (types);
2619         if (!geninst)
2620                 return NULL;
2621
2622         klass = mono_class_from_mono_type (geninst);
2623
2624         /*we might inflate to the GTD*/
2625         if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2626                 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2627                 return NULL;
2628         }
2629
2630         ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2631         mono_error_raise_exception (&error);
2632
2633         return ret;
2634 }
2635
2636 ICALL_EXPORT gboolean
2637 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2638 {
2639         MonoClass *klass;
2640
2641         if (!IS_MONOTYPE (type))
2642                 return FALSE;
2643
2644         if (type->type->byref)
2645                 return FALSE;
2646
2647         klass = mono_class_from_mono_type (type->type);
2648         return klass->generic_class != NULL || klass->generic_container != NULL;
2649 }
2650
2651 ICALL_EXPORT gint32
2652 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2653 {
2654         if (!IS_MONOTYPE (type))
2655                 return -1;
2656
2657         if (is_generic_parameter (type->type))
2658                 return mono_type_get_generic_param_num (type->type);
2659         return -1;
2660 }
2661
2662 ICALL_EXPORT GenericParameterAttributes
2663 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2664 {
2665         g_assert (IS_MONOTYPE (type));
2666         g_assert (is_generic_parameter (type->type));
2667         return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2668 }
2669
2670 ICALL_EXPORT MonoArray *
2671 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2672 {
2673         MonoError error;
2674         MonoReflectionType *rt;
2675         MonoGenericParamInfo *param_info;
2676         MonoDomain *domain;
2677         MonoClass **ptr;
2678         MonoArray *res;
2679         int i, count;
2680
2681         g_assert (IS_MONOTYPE (type));
2682
2683         domain = mono_object_domain (type);
2684         param_info = mono_generic_param_info (type->type->data.generic_param);
2685         for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2686                 ;
2687
2688         res = mono_array_new (domain, mono_defaults.monotype_class, count);
2689         for (i = 0; i < count; i++) {
2690                 rt = mono_type_get_object_checked (domain, &param_info->constraints [i]->byval_arg, &error);
2691                 mono_error_raise_exception (&error);
2692
2693                 mono_array_setref (res, i, rt);
2694         }
2695
2696
2697         return res;
2698 }
2699
2700 ICALL_EXPORT MonoBoolean
2701 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2702 {
2703         return is_generic_parameter (type->type);
2704 }
2705
2706 ICALL_EXPORT MonoBoolean
2707 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2708 {
2709         return is_generic_parameter (tb->type.type);
2710 }
2711
2712 ICALL_EXPORT void
2713 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2714                                                                            MonoReflectionType *t)
2715 {
2716         enumtype->type = t->type;
2717 }
2718
2719 ICALL_EXPORT MonoReflectionMethod*
2720 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type, 
2721                                                    MonoReflectionMethod* generic)
2722 {
2723         MonoDomain *domain; 
2724         MonoClass *klass;
2725         MonoMethod *method;
2726         gpointer iter;
2727         MonoError error;
2728         MonoReflectionMethod *ret = NULL;
2729                 
2730         domain = ((MonoObject *)type)->vtable->domain;
2731
2732         klass = mono_class_from_mono_type (type->type);
2733         mono_class_init_or_throw (klass);
2734
2735         iter = NULL;
2736         while ((method = mono_class_get_methods (klass, &iter))) {
2737                 if (method->token == generic->method->token) {
2738                         ret = mono_method_get_object_checked (domain, method, klass, &error);
2739                         mono_error_raise_exception (&error);
2740                 }
2741         }
2742
2743         return ret;
2744 }
2745
2746 ICALL_EXPORT MonoReflectionMethod *
2747 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2748 {
2749         MonoMethod *method;
2750         MonoType *type = ref_type->type;
2751         MonoError error;
2752         MonoReflectionMethod *ret = NULL;
2753
2754         if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2755                 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2756                 return NULL;
2757         }
2758         if (type->type == MONO_TYPE_VAR)
2759                 return NULL;
2760
2761         method = mono_type_get_generic_param_owner (type)->owner.method;
2762         g_assert (method);
2763
2764         ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2765         if (!mono_error_ok (&error))
2766                 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2767         return ret;
2768 }
2769
2770 ICALL_EXPORT MonoBoolean
2771 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2772 {
2773         mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2774         return FALSE;
2775 }
2776
2777 ICALL_EXPORT MonoBoolean
2778 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2779 {
2780         mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2781         return FALSE;
2782 }
2783
2784 ICALL_EXPORT void
2785 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2786 {
2787         MonoDomain *domain = mono_domain_get ();
2788         MonoImage *image = method->method->klass->image;
2789         MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2790         MonoTableInfo *tables = image->tables;
2791         MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2792         MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2793         guint32 im_cols [MONO_IMPLMAP_SIZE];
2794         guint32 scope_token;
2795         const char *import = NULL;
2796         const char *scope = NULL;
2797
2798         if (image_is_dynamic (image)) {
2799                 MonoReflectionMethodAux *method_aux = 
2800                         (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2801                 if (method_aux) {
2802                         import = method_aux->dllentry;
2803                         scope = method_aux->dll;
2804                 }
2805
2806                 if (!import || !scope) {
2807                         mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2808                         return;
2809                 }
2810         }
2811         else {
2812                 if (piinfo->implmap_idx) {
2813                         mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2814                         
2815                         piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2816                         import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2817                         scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2818                         scope = mono_metadata_string_heap (image, scope_token);
2819                 }
2820         }
2821         
2822         *flags = piinfo->piflags;
2823         *entry_point = mono_string_new (domain, import);
2824         *dll_name = mono_string_new (domain, scope);
2825 }
2826
2827 ICALL_EXPORT MonoReflectionMethod *
2828 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2829 {
2830         MonoMethodInflated *imethod;
2831         MonoMethod *result;
2832         MonoReflectionMethod *ret = NULL;
2833         MonoError error;
2834
2835         if (method->method->is_generic)
2836                 return method;
2837
2838         if (!method->method->is_inflated)
2839                 return NULL;
2840
2841         imethod = (MonoMethodInflated *) method->method;
2842
2843         result = imethod->declaring;
2844         /* Not a generic method.  */
2845         if (!result->is_generic)
2846                 return NULL;
2847
2848         if (image_is_dynamic (method->method->klass->image)) {
2849                 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2850                 MonoReflectionMethod *res;
2851
2852                 /*
2853                  * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2854                  * the dynamic case as well ?
2855                  */
2856                 mono_image_lock ((MonoImage*)image);
2857                 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2858                 mono_image_unlock ((MonoImage*)image);
2859
2860                 if (res)
2861                         return res;
2862         }
2863
2864         if (imethod->context.class_inst) {
2865                 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2866                 /*Generic methods gets the context of the GTD.*/
2867                 if (mono_class_get_context (klass)) {
2868                         result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2869                         if (!mono_error_ok (&error))
2870                                 goto leave;
2871                 }
2872         }
2873
2874         ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2875 leave:
2876         if (!mono_error_ok (&error))
2877                 mono_error_set_pending_exception (&error);
2878         return ret;
2879 }
2880
2881 ICALL_EXPORT gboolean
2882 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2883 {
2884         return mono_method_signature (method->method)->generic_param_count != 0;
2885 }
2886
2887 ICALL_EXPORT gboolean
2888 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2889 {
2890         return method->method->is_generic;
2891 }
2892
2893 ICALL_EXPORT MonoArray*
2894 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2895 {
2896         MonoError error;
2897         MonoReflectionType *rt;
2898         MonoArray *res;
2899         MonoDomain *domain;
2900         int count, i;
2901
2902         domain = mono_object_domain (method);
2903
2904         if (method->method->is_inflated) {
2905                 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2906
2907                 if (inst) {
2908                         count = inst->type_argc;
2909                         res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2910
2911                         for (i = 0; i < count; i++) {
2912                                 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2913                                 mono_error_raise_exception (&error);
2914
2915                                 mono_array_setref (res, i, rt);
2916                         }
2917
2918                         return res;
2919                 }
2920         }
2921
2922         count = mono_method_signature (method->method)->generic_param_count;
2923         res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2924
2925         for (i = 0; i < count; i++) {
2926                 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2927                 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2928                 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
2929
2930                 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2931                 mono_error_raise_exception (&error);
2932
2933                 mono_array_setref (res, i, rt);
2934         }
2935
2936         return res;
2937 }
2938
2939 ICALL_EXPORT MonoObject *
2940 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc) 
2941 {
2942         MonoError error;
2943         /* 
2944          * Invoke from reflection is supposed to always be a virtual call (the API
2945          * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2946          * greater flexibility.
2947          */
2948         MonoMethod *m = method->method;
2949         MonoMethodSignature *sig = mono_method_signature (m);
2950         MonoImage *image;
2951         int pcount;
2952         void *obj = this_arg;
2953
2954         *exc = NULL;
2955
2956         if (mono_security_core_clr_enabled ())
2957                 mono_security_core_clr_ensure_reflection_access_method (m);
2958
2959         if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2960                 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2961                         mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2962                         return NULL;
2963                 }
2964
2965                 if (this_arg) {
2966                         if (!mono_object_isinst (this_arg, m->klass)) {
2967                                 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
2968                                 char *target_name = mono_type_get_full_name (m->klass);
2969                                 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2970                                 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2971                                 g_free (msg);
2972                                 g_free (target_name);
2973                                 g_free (this_name);
2974                                 return NULL;
2975                         }
2976                         m = mono_object_get_virtual_method (this_arg, m);
2977                         /* must pass the pointer to the value for valuetype methods */
2978                         if (m->klass->valuetype)
2979                                 obj = mono_object_unbox (this_arg);
2980                 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2981                         mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2982                         return NULL;
2983                 }
2984         }
2985
2986         if (sig->ret->byref) {
2987                 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"));
2988                 return NULL;
2989         }
2990
2991         pcount = params? mono_array_length (params): 0;
2992         if (pcount != sig->param_count) {
2993                 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2994                 return NULL;
2995         }
2996
2997         if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
2998                 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."));
2999                 return NULL;
3000         }
3001
3002         image = m->klass->image;
3003         if (image->assembly->ref_only) {
3004                 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."));
3005                 return NULL;
3006         }
3007
3008         if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3009                 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3010                 return NULL;
3011         }
3012         
3013         if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3014                 MonoArray *arr;
3015                 int i;
3016                 uintptr_t *lengths;
3017                 intptr_t *lower_bounds;
3018                 pcount = mono_array_length (params);
3019                 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3020                 /* Note: the synthetized array .ctors have int32 as argument type */
3021                 for (i = 0; i < pcount; ++i)
3022                         lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3023
3024                 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3025                         /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3026                         arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3027                         if (!mono_error_ok (&error)) {
3028                                 mono_error_set_pending_exception (&error);
3029                                 return NULL;
3030                         }
3031
3032                         for (i = 0; i < mono_array_length (arr); ++i) {
3033                                 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3034                                 if (!mono_error_ok (&error)) {
3035                                         mono_error_set_pending_exception (&error);
3036                                         return NULL;
3037                                 }
3038                                 mono_array_setref_fast (arr, i, subarray);
3039                         }
3040                         return (MonoObject*)arr;
3041                 }
3042
3043                 if (m->klass->rank == pcount) {
3044                         /* Only lengths provided. */
3045                         arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3046                         if (!mono_error_ok (&error)) {
3047                                 mono_error_set_pending_exception (&error);
3048                                 return NULL;
3049                         }
3050
3051                         return (MonoObject*)arr;
3052                 } else {
3053                         g_assert (pcount == (m->klass->rank * 2));
3054                         /* The arguments are lower-bound-length pairs */
3055                         lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3056
3057                         for (i = 0; i < pcount / 2; ++i) {
3058                                 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3059                                 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3060                         }
3061
3062                         arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3063                         if (!mono_error_ok (&error)) {
3064                                 mono_error_set_pending_exception (&error);
3065                                 return NULL;
3066                         }
3067
3068                         return (MonoObject*)arr;
3069                 }
3070         }
3071         return mono_runtime_invoke_array (m, obj, params, NULL);
3072 }
3073
3074 #ifndef DISABLE_REMOTING
3075 ICALL_EXPORT MonoObject *
3076 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs) 
3077 {
3078         MonoDomain *domain = mono_object_domain (method); 
3079         MonoMethod *m = method->method;
3080         MonoMethodSignature *sig = mono_method_signature (m);
3081         MonoArray *out_args;
3082         MonoObject *result;
3083         int i, j, outarg_count = 0;
3084
3085         if (m->klass == mono_defaults.object_class) {
3086                 if (!strcmp (m->name, "FieldGetter")) {
3087                         MonoClass *k = this_arg->vtable->klass;
3088                         MonoString *name;
3089                         char *str;
3090                         
3091                         /* If this is a proxy, then it must be a CBO */
3092                         if (k == mono_defaults.transparent_proxy_class) {
3093                                 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3094                                 this_arg = tp->rp->unwrapped_server;
3095                                 g_assert (this_arg);
3096                                 k = this_arg->vtable->klass;
3097                         }
3098                         
3099                         name = mono_array_get (params, MonoString *, 1);
3100                         str = mono_string_to_utf8 (name);
3101                 
3102                         do {
3103                                 MonoClassField* field = mono_class_get_field_from_name (k, str);
3104                                 if (field) {
3105                                         MonoClass *field_klass =  mono_class_from_mono_type (field->type);
3106                                         if (field_klass->valuetype)
3107                                                 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
3108                                         else 
3109                                                 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3110                                 
3111                                         out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3112                                         mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3113                                         mono_array_setref (out_args, 0, result);
3114                                         g_free (str);
3115                                         return NULL;
3116                                 }
3117                                 k = k->parent;
3118                         } while (k);
3119
3120                         g_free (str);
3121                         g_assert_not_reached ();
3122
3123                 } else if (!strcmp (m->name, "FieldSetter")) {
3124                         MonoClass *k = this_arg->vtable->klass;
3125                         MonoString *name;
3126                         guint32 size;
3127                         gint32 align;
3128                         char *str;
3129                         
3130                         /* If this is a proxy, then it must be a CBO */
3131                         if (k == mono_defaults.transparent_proxy_class) {
3132                                 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3133                                 this_arg = tp->rp->unwrapped_server;
3134                                 g_assert (this_arg);
3135                                 k = this_arg->vtable->klass;
3136                         }
3137                         
3138                         name = mono_array_get (params, MonoString *, 1);
3139                         str = mono_string_to_utf8 (name);
3140                 
3141                         do {
3142                                 MonoClassField* field = mono_class_get_field_from_name (k, str);
3143                                 if (field) {
3144                                         MonoClass *field_klass =  mono_class_from_mono_type (field->type);
3145                                         MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3146
3147                                         if (field_klass->valuetype) {
3148                                                 size = mono_type_size (field->type, &align);
3149                                                 g_assert (size == mono_class_value_size (field_klass, NULL));
3150                                                 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3151                                         } else {
3152                                                 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3153                                         }
3154                                 
3155                                         out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3156                                         mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3157
3158                                         g_free (str);
3159                                         return NULL;
3160                                 }
3161                                 
3162                                 k = k->parent;
3163                         } while (k);
3164
3165                         g_free (str);
3166                         g_assert_not_reached ();
3167
3168                 }
3169         }
3170
3171         for (i = 0; i < mono_array_length (params); i++) {
3172                 if (sig->params [i]->byref) 
3173                         outarg_count++;
3174         }
3175
3176         out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3177         
3178         /* handle constructors only for objects already allocated */
3179         if (!strcmp (method->method->name, ".ctor"))
3180                 g_assert (this_arg);
3181
3182         /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3183         g_assert (!method->method->klass->valuetype);
3184         result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3185
3186         for (i = 0, j = 0; i < mono_array_length (params); i++) {
3187                 if (sig->params [i]->byref) {
3188                         gpointer arg;
3189                         arg = mono_array_get (params, gpointer, i);
3190                         mono_array_setref (out_args, j, arg);
3191                         j++;
3192                 }
3193         }
3194
3195         mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3196
3197         return result;
3198 }
3199 #endif
3200
3201 static guint64
3202 read_enum_value (const char *mem, int type)
3203 {
3204         switch (type) {
3205         case MONO_TYPE_BOOLEAN:
3206         case MONO_TYPE_U1:
3207                 return *(guint8*)mem;
3208         case MONO_TYPE_I1:
3209                 return *(gint8*)mem;
3210         case MONO_TYPE_CHAR:
3211         case MONO_TYPE_U2:
3212                 return read16 (mem);
3213         case MONO_TYPE_I2:
3214                 return (gint16) read16 (mem);
3215         case MONO_TYPE_U4:
3216                 return read32 (mem);
3217         case MONO_TYPE_I4:
3218                 return (gint32) read32 (mem);
3219         case MONO_TYPE_U8:
3220         case MONO_TYPE_I8:
3221                 return read64 (mem);
3222         default:
3223                 g_assert_not_reached ();
3224         }
3225         return 0;
3226 }
3227
3228 static void
3229 write_enum_value (char *mem, int type, guint64 value)
3230 {
3231         switch (type) {
3232         case MONO_TYPE_U1:
3233         case MONO_TYPE_I1: {
3234                 guint8 *p = (guint8*)mem;
3235                 *p = value;
3236                 break;
3237         }
3238         case MONO_TYPE_U2:
3239         case MONO_TYPE_I2: {
3240                 guint16 *p = (guint16 *)mem;
3241                 *p = value;
3242                 break;
3243         }
3244         case MONO_TYPE_U4:
3245         case MONO_TYPE_I4: {
3246                 guint32 *p = (guint32 *)mem;
3247                 *p = value;
3248                 break;
3249         }
3250         case MONO_TYPE_U8:
3251         case MONO_TYPE_I8: {
3252                 guint64 *p = (guint64 *)mem;
3253                 *p = value;
3254                 break;
3255         }
3256         default:
3257                 g_assert_not_reached ();
3258         }
3259         return;
3260 }
3261
3262 ICALL_EXPORT MonoObject *
3263 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3264 {
3265         MonoError error;
3266         MonoDomain *domain; 
3267         MonoClass *enumc;
3268         MonoObject *res;
3269         MonoType *etype;
3270
3271         domain = mono_object_domain (enumType); 
3272         enumc = mono_class_from_mono_type (enumType->type);
3273
3274         mono_class_init_or_throw (enumc);
3275
3276         etype = mono_class_enum_basetype (enumc);
3277
3278         res = mono_object_new_checked (domain, enumc, &error);
3279         mono_error_raise_exception (&error);
3280         write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3281
3282         return res;
3283 }
3284
3285 ICALL_EXPORT MonoBoolean
3286 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3287 {
3288         int size = mono_class_value_size (a->vtable->klass, NULL);
3289         guint64 a_val = 0, b_val = 0;
3290
3291         memcpy (&a_val, mono_object_unbox (a), size);
3292         memcpy (&b_val, mono_object_unbox (b), size);
3293
3294         return (a_val & b_val) == b_val;
3295 }
3296
3297 ICALL_EXPORT MonoObject *
3298 ves_icall_System_Enum_get_value (MonoObject *eobj)
3299 {
3300         MonoError error;
3301         MonoObject *res;
3302         MonoClass *enumc;
3303         gpointer dst;
3304         gpointer src;
3305         int size;
3306
3307         if (!eobj)
3308                 return NULL;
3309
3310         g_assert (eobj->vtable->klass->enumtype);
3311         
3312         enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3313         res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3314         mono_error_raise_exception (&error);
3315         dst = (char *)res + sizeof (MonoObject);
3316         src = (char *)eobj + sizeof (MonoObject);
3317         size = mono_class_value_size (enumc, NULL);
3318
3319         memcpy (dst, src, size);
3320
3321         return res;
3322 }
3323
3324 ICALL_EXPORT MonoReflectionType *
3325 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3326 {
3327         MonoError error;
3328         MonoReflectionType *ret;
3329         MonoType *etype;
3330         MonoClass *klass;
3331
3332         klass = mono_class_from_mono_type (type->type);
3333         mono_class_init_or_throw (klass);
3334
3335         etype = mono_class_enum_basetype (klass);
3336         if (!etype) {
3337                 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3338                 return NULL;
3339         }
3340
3341         ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3342         mono_error_raise_exception (&error);
3343
3344         return ret;
3345 }
3346
3347 ICALL_EXPORT int
3348 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3349 {
3350         gpointer tdata = (char *)eobj + sizeof (MonoObject);
3351         gpointer odata = (char *)other + sizeof (MonoObject);
3352         MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3353         g_assert (basetype);
3354
3355         if (other == NULL)
3356                 return 1;
3357
3358         if (eobj->vtable->klass != other->vtable->klass)
3359                 return 2;
3360
3361 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3362                 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3363                 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3364                 if (me == other) \
3365                         return 0; \
3366                 return me > other ? 1 : -1; \
3367         } while (0)
3368
3369         switch (basetype->type) {
3370                 case MONO_TYPE_U1:
3371                         COMPARE_ENUM_VALUES (guint8);
3372                 case MONO_TYPE_I1:
3373                         COMPARE_ENUM_VALUES (gint8);
3374                 case MONO_TYPE_CHAR:
3375                 case MONO_TYPE_U2:
3376                         COMPARE_ENUM_VALUES (guint16);
3377                 case MONO_TYPE_I2:
3378                         COMPARE_ENUM_VALUES (gint16);
3379                 case MONO_TYPE_U4:
3380                         COMPARE_ENUM_VALUES (guint32);
3381                 case MONO_TYPE_I4:
3382                         COMPARE_ENUM_VALUES (gint32);
3383                 case MONO_TYPE_U8:
3384                         COMPARE_ENUM_VALUES (guint64);
3385                 case MONO_TYPE_I8:
3386                         COMPARE_ENUM_VALUES (gint64);
3387                 default:
3388                         break;
3389         }
3390 #undef COMPARE_ENUM_VALUES
3391         /* indicates that the enum was of an unsupported unerlying type */
3392         return 3;
3393 }
3394
3395 ICALL_EXPORT int
3396 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3397 {
3398         gpointer data = (char *)eobj + sizeof (MonoObject);
3399         MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3400         g_assert (basetype);
3401
3402         switch (basetype->type) {
3403                 case MONO_TYPE_I1:       {
3404                         gint8 value = *((gint8*)data);
3405                         return ((int)value ^ (int)value << 8);
3406                 }
3407                 case MONO_TYPE_U1:
3408                         return *((guint8*)data);
3409                 case MONO_TYPE_CHAR:
3410                 case MONO_TYPE_U2:
3411                         return *((guint16*)data);
3412                 
3413                 case MONO_TYPE_I2: {
3414                         gint16 value = *((gint16*)data);
3415                         return ((int)(guint16)value | (((int)value) << 16));
3416                 }
3417                 case MONO_TYPE_U4:
3418                         return *((guint32*)data);
3419                 case MONO_TYPE_I4:
3420                         return *((gint32*)data);
3421                 case MONO_TYPE_U8:
3422                 case MONO_TYPE_I8: {
3423                         gint64 value = *((gint64*)data);
3424                         return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3425                 }
3426                 default:
3427                         g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3428         }
3429         return 0;
3430 }
3431
3432 ICALL_EXPORT MonoBoolean
3433 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3434 {
3435         MonoDomain *domain = mono_object_domain (type); 
3436         MonoClass *enumc = mono_class_from_mono_type (type->type);
3437         guint j = 0, nvalues;
3438         gpointer iter;
3439         MonoClassField *field;
3440         int base_type;
3441         guint64 field_value, previous_value = 0;
3442         gboolean sorted = TRUE;
3443
3444         mono_class_init_or_throw (enumc);
3445
3446         if (!enumc->enumtype) {
3447                 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3448                 return TRUE;
3449         }
3450
3451         base_type = mono_class_enum_basetype (enumc)->type;
3452
3453         nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3454         *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3455         *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3456
3457         iter = NULL;
3458         while ((field = mono_class_get_fields (enumc, &iter))) {
3459                 const char *p;
3460                 MonoTypeEnum def_type;
3461
3462                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3463                         continue;
3464                 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3465                         continue;
3466                 if (mono_field_is_deleted (field))
3467                         continue;
3468                 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3469
3470                 p = mono_class_get_field_default_value (field, &def_type);
3471                 /* len = */ mono_metadata_decode_blob_size (p, &p);
3472
3473                 field_value = read_enum_value (p, base_type);
3474                 mono_array_set (*values, guint64, j, field_value);
3475
3476                 if (previous_value > field_value)
3477                         sorted = FALSE;
3478
3479                 previous_value = field_value;
3480                 ++j;
3481         }
3482
3483         return sorted;
3484 }
3485
3486 enum {
3487         BFLAGS_IgnoreCase = 1,
3488         BFLAGS_DeclaredOnly = 2,
3489         BFLAGS_Instance = 4,
3490         BFLAGS_Static = 8,
3491         BFLAGS_Public = 0x10,
3492         BFLAGS_NonPublic = 0x20,
3493         BFLAGS_FlattenHierarchy = 0x40,
3494         BFLAGS_InvokeMethod = 0x100,
3495         BFLAGS_CreateInstance = 0x200,
3496         BFLAGS_GetField = 0x400,
3497         BFLAGS_SetField = 0x800,
3498         BFLAGS_GetProperty = 0x1000,
3499         BFLAGS_SetProperty = 0x2000,
3500         BFLAGS_ExactBinding = 0x10000,
3501         BFLAGS_SuppressChangeType = 0x20000,
3502         BFLAGS_OptionalParamBinding = 0x40000
3503 };
3504
3505 ICALL_EXPORT MonoArray*
3506 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3507 {
3508         MonoError error;
3509         MonoDomain *domain; 
3510         MonoClass *startklass, *klass, *refklass;
3511         MonoArray *res;
3512         MonoObject *member;
3513         int i, match;
3514         gpointer iter;
3515         char *utf8_name = NULL;
3516         int (*compare_func) (const char *s1, const char *s2) = NULL;    
3517         MonoClassField *field;
3518         MonoPtrArray tmp_array;
3519
3520         domain = ((MonoObject *)type)->vtable->domain;
3521         if (type->type->byref)
3522                 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3523
3524         klass = startklass = mono_class_from_mono_type (type->type);
3525         refklass = mono_class_from_mono_type (reftype->type);
3526
3527         mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3528         
3529 handle_parent:  
3530         if (klass->exception_type != MONO_EXCEPTION_NONE) {
3531                 mono_ptr_array_destroy (tmp_array);
3532                 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3533                 return NULL;
3534         }
3535
3536         iter = NULL;
3537         while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3538                 guint32 flags = mono_field_get_flags (field);
3539                 match = 0;
3540                 if (mono_field_is_deleted_with_flags (field, flags))
3541                         continue;
3542                 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3543                         if (bflags & BFLAGS_Public)
3544                                 match++;
3545                 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3546                         if (bflags & BFLAGS_NonPublic) {
3547                                 match++;
3548                         }
3549                 }
3550                 if (!match)
3551                         continue;
3552                 match = 0;
3553                 if (flags & FIELD_ATTRIBUTE_STATIC) {
3554                         if (bflags & BFLAGS_Static)
3555                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3556                                         match++;
3557                 } else {
3558                         if (bflags & BFLAGS_Instance)
3559                                 match++;
3560                 }
3561
3562                 if (!match)
3563                         continue;
3564
3565                 if (name != NULL) {
3566                         if (utf8_name == NULL) {
3567                                 utf8_name = mono_string_to_utf8 (name);
3568                                 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3569                         }
3570
3571                         if (compare_func (mono_field_get_name (field), utf8_name))
3572                                 continue;
3573                 }
3574
3575                 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3576                 if (!mono_error_ok (&error))
3577                     goto fail;
3578                 mono_ptr_array_append (tmp_array, member);
3579         }
3580         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3581                 goto handle_parent;
3582
3583         res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3584
3585         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3586                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3587
3588         mono_ptr_array_destroy (tmp_array);
3589
3590         if (utf8_name != NULL)
3591                 g_free (utf8_name);
3592
3593         return res;
3594 fail:
3595         mono_ptr_array_destroy (tmp_array);
3596         mono_error_raise_exception (&error);
3597         g_assert_not_reached ();
3598 }
3599
3600 static gboolean
3601 method_nonpublic (MonoMethod* method, gboolean start_klass)
3602 {
3603         switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3604                 case METHOD_ATTRIBUTE_ASSEM:
3605                         return (start_klass || mono_defaults.generic_ilist_class);
3606                 case METHOD_ATTRIBUTE_PRIVATE:
3607                         return start_klass;
3608                 case METHOD_ATTRIBUTE_PUBLIC:
3609                         return FALSE;
3610                 default:
3611                         return TRUE;
3612         }
3613 }
3614
3615 GPtrArray*
3616 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3617 {
3618         GPtrArray *array;
3619         MonoClass *startklass;
3620         MonoMethod *method;
3621         gpointer iter;
3622         int match, nslots;
3623         /*FIXME, use MonoBitSet*/
3624         guint32 method_slots_default [8];
3625         guint32 *method_slots = NULL;
3626         int (*compare_func) (const char *s1, const char *s2) = NULL;
3627
3628         array = g_ptr_array_new ();
3629         startklass = klass;
3630         *ex = NULL;
3631
3632         if (name != NULL)
3633                 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3634
3635         /* An optimization for calls made from Delegate:CreateDelegate () */
3636         if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3637                 method = mono_get_delegate_invoke (klass);
3638                 if (mono_loader_get_last_error ())
3639                         goto loader_error;
3640
3641                 g_ptr_array_add (array, method);
3642                 return array;
3643         }
3644
3645         mono_class_setup_methods (klass);
3646         mono_class_setup_vtable (klass);
3647         if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3648                 goto loader_error;
3649
3650         if (is_generic_parameter (&klass->byval_arg))
3651                 nslots = mono_class_get_vtable_size (klass->parent);
3652         else
3653                 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3654         if (nslots >= sizeof (method_slots_default) * 8) {
3655                 method_slots = g_new0 (guint32, nslots / 32 + 1);
3656         } else {
3657                 method_slots = method_slots_default;
3658                 memset (method_slots, 0, sizeof (method_slots_default));
3659         }
3660 handle_parent:
3661         mono_class_setup_methods (klass);
3662         mono_class_setup_vtable (klass);
3663         if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3664                 goto loader_error;              
3665
3666         iter = NULL;
3667         while ((method = mono_class_get_methods (klass, &iter))) {
3668                 match = 0;
3669                 if (method->slot != -1) {
3670                         g_assert (method->slot < nslots);
3671                         if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3672                                 continue;
3673                         if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3674                                 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3675                 }
3676
3677                 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3678                         continue;
3679                 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3680                         if (bflags & BFLAGS_Public)
3681                                 match++;
3682                 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3683                                 match++;
3684                 }
3685                 if (!match)
3686                         continue;
3687                 match = 0;
3688                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3689                         if (bflags & BFLAGS_Static)
3690                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3691                                         match++;
3692                 } else {
3693                         if (bflags & BFLAGS_Instance)
3694                                 match++;
3695                 }
3696
3697                 if (!match)
3698                         continue;
3699
3700                 if (name != NULL) {
3701                         if (compare_func (name, method->name))
3702                                 continue;
3703                 }
3704                 
3705                 match = 0;
3706                 g_ptr_array_add (array, method);
3707         }
3708         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3709                 goto handle_parent;
3710         if (method_slots != method_slots_default)
3711                 g_free (method_slots);
3712
3713         return array;
3714
3715 loader_error:
3716         if (method_slots != method_slots_default)
3717                 g_free (method_slots);
3718         g_ptr_array_free (array, TRUE);
3719
3720         if (klass->exception_type != MONO_EXCEPTION_NONE) {
3721                 *ex = mono_class_get_exception_for_failure (klass);
3722         } else {
3723                 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3724                 mono_loader_clear_error ();
3725         }
3726         return NULL;
3727 }
3728
3729 ICALL_EXPORT MonoArray*
3730 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3731 {
3732         static MonoClass *MethodInfo_array;
3733         MonoError error;
3734         MonoDomain *domain; 
3735         MonoArray *res;
3736         MonoVTable *array_vtable;
3737         MonoException *ex = NULL;
3738         const char *mname = NULL;
3739         GPtrArray *method_array;
3740         MonoClass *klass, *refklass;
3741         int i;
3742
3743         mono_error_init (&error);
3744
3745         if (!MethodInfo_array) {
3746                 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3747                 mono_memory_barrier ();
3748                 MethodInfo_array = klass;
3749         }
3750
3751         klass = mono_class_from_mono_type (type->type);
3752         refklass = mono_class_from_mono_type (reftype->type);
3753         domain = ((MonoObject *)type)->vtable->domain;
3754         array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3755         if (type->type->byref) {
3756                 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3757                 mono_error_set_pending_exception (&error);
3758
3759                 return res;
3760         }
3761
3762         if (name)
3763                 mname = mono_string_to_utf8 (name);
3764
3765         method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3766         g_free ((char*)mname);
3767         if (ex) {
3768                 mono_set_pending_exception (ex);
3769                 return NULL;
3770         }
3771
3772         res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3773         if (!mono_error_ok (&error)) {
3774                 mono_error_set_pending_exception (&error);
3775                 return NULL;
3776         }
3777
3778         for (i = 0; i < method_array->len; ++i) {
3779                 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3780                 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3781                 if (!mono_error_ok (&error))
3782                         goto failure;
3783                 mono_array_setref (res, i, rm);
3784         }
3785
3786 failure:
3787         g_ptr_array_free (method_array, TRUE);
3788         if (!mono_error_ok (&error))
3789                 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3790         return res;
3791 }
3792
3793 ICALL_EXPORT MonoArray*
3794 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3795 {
3796         MonoDomain *domain; 
3797         static MonoClass *System_Reflection_ConstructorInfo;
3798         MonoClass *startklass, *klass, *refklass;
3799         MonoArray *res;
3800         MonoMethod *method;
3801         MonoObject *member;
3802         int i, match;
3803         gpointer iter = NULL;
3804         MonoPtrArray tmp_array;
3805         MonoError error;
3806         
3807         mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3808
3809         domain = ((MonoObject *)type)->vtable->domain;
3810         if (type->type->byref)
3811                 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3812         klass = startklass = mono_class_from_mono_type (type->type);
3813         refklass = mono_class_from_mono_type (reftype->type);
3814
3815         if (!System_Reflection_ConstructorInfo)
3816                 System_Reflection_ConstructorInfo = mono_class_from_name (
3817                         mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3818
3819         mono_class_setup_methods (klass);
3820         if (klass->exception_type != MONO_EXCEPTION_NONE) {
3821                 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3822                 return NULL;
3823         }
3824
3825         iter = NULL;
3826         while ((method = mono_class_get_methods (klass, &iter))) {
3827                 match = 0;
3828                 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3829                         continue;
3830                 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3831                         if (bflags & BFLAGS_Public)
3832                                 match++;
3833                 } else {
3834                         if (bflags & BFLAGS_NonPublic)
3835                                 match++;
3836                 }
3837                 if (!match)
3838                         continue;
3839                 match = 0;
3840                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3841                         if (bflags & BFLAGS_Static)
3842                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3843                                         match++;
3844                 } else {
3845                         if (bflags & BFLAGS_Instance)
3846                                 match++;
3847                 }
3848
3849                 if (!match)
3850                         continue;
3851                 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3852                 if (!mono_error_ok (&error)) {
3853                         mono_error_set_pending_exception (&error);
3854                         return NULL;
3855                 }
3856
3857                 mono_ptr_array_append (tmp_array, member);
3858         }
3859
3860         res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3861
3862         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3863                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3864
3865         mono_ptr_array_destroy (tmp_array);
3866
3867         return res;
3868 }
3869
3870 static guint
3871 property_hash (gconstpointer data)
3872 {
3873         MonoProperty *prop = (MonoProperty*)data;
3874
3875         return g_str_hash (prop->name);
3876 }
3877
3878 static gboolean
3879 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3880 {
3881         if (method1->is_inflated)
3882                 method1 = ((MonoMethodInflated*) method1)->declaring;
3883         if (method2->is_inflated)
3884                 method2 = ((MonoMethodInflated*) method2)->declaring;
3885
3886         return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3887 }
3888
3889 static gboolean
3890 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3891 {
3892         // Properties are hide-by-name-and-signature
3893         if (!g_str_equal (prop1->name, prop2->name))
3894                 return FALSE;
3895
3896         /* If we see a property in a generic method, we want to
3897            compare the generic signatures, not the inflated signatures
3898            because we might conflate two properties that were
3899            distinct:
3900
3901            class Foo<T,U> {
3902              public T this[T t] { getter { return t; } } // method 1
3903              public U this[U u] { getter { return u; } } // method 2
3904            }
3905
3906            If we see int Foo<int,int>::Item[int] we need to know if
3907            the indexer came from method 1 or from method 2, and we
3908            shouldn't conflate them.   (Bugzilla 36283)
3909         */
3910         if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
3911                 return FALSE;
3912
3913         if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
3914                 return FALSE;
3915
3916         return TRUE;
3917 }
3918
3919 static gboolean
3920 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3921 {
3922         if (!accessor)
3923                 return FALSE;
3924
3925         return method_nonpublic (accessor, start_klass);
3926 }
3927
3928 ICALL_EXPORT MonoArray*
3929 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3930 {
3931         MonoException *ex;
3932         MonoDomain *domain; 
3933         static MonoClass *System_Reflection_PropertyInfo;
3934         MonoClass *startklass, *klass;
3935         MonoArray *res;
3936         MonoMethod *method;
3937         MonoProperty *prop;
3938         int i, match;
3939         guint32 flags;
3940         gchar *propname = NULL;
3941         int (*compare_func) (const char *s1, const char *s2) = NULL;
3942         gpointer iter;
3943         GHashTable *properties = NULL;
3944         MonoPtrArray tmp_array;
3945
3946         mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
3947
3948         if (!System_Reflection_PropertyInfo)
3949                 System_Reflection_PropertyInfo = mono_class_from_name (
3950                         mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3951
3952         domain = ((MonoObject *)type)->vtable->domain;
3953         if (type->type->byref)
3954                 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3955         klass = startklass = mono_class_from_mono_type (type->type);
3956
3957         if (name != NULL) {
3958                 propname = mono_string_to_utf8 (name);
3959                 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3960         }
3961
3962         properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3963 handle_parent:
3964         mono_class_setup_methods (klass);
3965         mono_class_setup_vtable (klass);
3966         if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3967                 goto loader_error;
3968
3969         iter = NULL;
3970         while ((prop = mono_class_get_properties (klass, &iter))) {
3971                 match = 0;
3972                 method = prop->get;
3973                 if (!method)
3974                         method = prop->set;
3975                 if (method)
3976                         flags = method->flags;
3977                 else
3978                         flags = 0;
3979                 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3980                         (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3981                         if (bflags & BFLAGS_Public)
3982                                 match++;
3983                 } else if (bflags & BFLAGS_NonPublic) {
3984                         if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3985                                 property_accessor_nonpublic(prop->set, startklass == klass)) {
3986                                 match++;
3987                         }
3988                 }
3989                 if (!match)
3990                         continue;
3991                 match = 0;
3992                 if (flags & METHOD_ATTRIBUTE_STATIC) {
3993                         if (bflags & BFLAGS_Static)
3994                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3995                                         match++;
3996                 } else {
3997                         if (bflags & BFLAGS_Instance)
3998                                 match++;
3999                 }
4000
4001                 if (!match)
4002                         continue;
4003                 match = 0;
4004
4005                 if (name != NULL) {
4006                         if (compare_func (propname, prop->name))
4007                                 continue;
4008                 }
4009                 
4010                 if (g_hash_table_lookup (properties, prop))
4011                         continue;
4012
4013                 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
4014                 
4015                 g_hash_table_insert (properties, prop, prop);
4016         }
4017         if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4018                 goto handle_parent;
4019
4020         g_hash_table_destroy (properties);
4021         g_free (propname);
4022
4023         res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
4024         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4025                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4026
4027         mono_ptr_array_destroy (tmp_array);
4028
4029         return res;
4030
4031 loader_error:
4032         if (properties)
4033                 g_hash_table_destroy (properties);
4034         if (name)
4035                 g_free (propname);
4036         mono_ptr_array_destroy (tmp_array);
4037
4038         if (klass->exception_type != MONO_EXCEPTION_NONE) {
4039                 ex = mono_class_get_exception_for_failure (klass);
4040         } else {
4041                 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4042                 mono_loader_clear_error ();
4043         }
4044         mono_set_pending_exception (ex);
4045         return NULL;
4046 }
4047
4048 static guint
4049 event_hash (gconstpointer data)
4050 {
4051         MonoEvent *event = (MonoEvent*)data;
4052
4053         return g_str_hash (event->name);
4054 }
4055
4056 static gboolean
4057 event_equal (MonoEvent *event1, MonoEvent *event2)
4058 {
4059         // Events are hide-by-name
4060         return g_str_equal (event1->name, event2->name);
4061 }
4062
4063 ICALL_EXPORT MonoArray*
4064 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4065 {
4066         MonoException *ex;
4067         MonoDomain *domain; 
4068         static MonoClass *System_Reflection_EventInfo;
4069         MonoClass *startklass, *klass;
4070         MonoArray *res;
4071         MonoMethod *method;
4072         MonoEvent *event;
4073         int i, match;
4074         gpointer iter;
4075         char *utf8_name = NULL;
4076         int (*compare_func) (const char *s1, const char *s2) = NULL;    
4077         GHashTable *events = NULL;
4078         MonoPtrArray tmp_array;
4079
4080         mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4081
4082         if (!System_Reflection_EventInfo)
4083                 System_Reflection_EventInfo = mono_class_from_name (
4084                         mono_defaults.corlib, "System.Reflection", "EventInfo");
4085
4086         domain = mono_object_domain (type);
4087         if (type->type->byref)
4088                 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
4089         klass = startklass = mono_class_from_mono_type (type->type);
4090
4091         events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4092 handle_parent:
4093         mono_class_setup_methods (klass);
4094         mono_class_setup_vtable (klass);
4095         if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
4096                 goto loader_error;
4097
4098         iter = NULL;
4099         while ((event = mono_class_get_events (klass, &iter))) {
4100                 match = 0;
4101                 method = event->add;
4102                 if (!method)
4103                         method = event->remove;
4104                 if (!method)
4105                         method = event->raise;
4106                 if (method) {
4107                         if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4108                                 if (bflags & BFLAGS_Public)
4109                                         match++;
4110                         } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4111                                 if (bflags & BFLAGS_NonPublic)
4112                                         match++;
4113                         }
4114                 }
4115                 else
4116                         if (bflags & BFLAGS_NonPublic)
4117                                 match ++;
4118                 if (!match)
4119                         continue;
4120                 match = 0;
4121                 if (method) {
4122                         if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4123                                 if (bflags & BFLAGS_Static)
4124                                         if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4125                                                 match++;
4126                         } else {
4127                                 if (bflags & BFLAGS_Instance)
4128                                         match++;
4129                         }
4130                 }
4131                 else
4132                         if (bflags & BFLAGS_Instance)
4133                                 match ++;
4134                 if (!match)
4135                         continue;
4136
4137                 if (name != NULL) {
4138                         if (utf8_name == NULL) {
4139                                 utf8_name = mono_string_to_utf8 (name);
4140                                 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4141                         }
4142
4143                         if (compare_func (event->name, utf8_name))
4144                                 continue;
4145                 }               
4146
4147                 if (g_hash_table_lookup (events, event))
4148                         continue;
4149
4150                 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
4151
4152                 g_hash_table_insert (events, event, event);
4153         }
4154         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4155                 goto handle_parent;
4156
4157         g_hash_table_destroy (events);
4158
4159         res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4160
4161         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4162                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4163
4164         mono_ptr_array_destroy (tmp_array);
4165
4166         if (utf8_name != NULL)
4167                 g_free (utf8_name);
4168
4169         return res;
4170
4171 loader_error:
4172         mono_ptr_array_destroy (tmp_array);
4173         if (klass->exception_type != MONO_EXCEPTION_NONE) {
4174                 ex = mono_class_get_exception_for_failure (klass);
4175         } else {
4176                 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4177                 mono_loader_clear_error ();
4178         }
4179         mono_set_pending_exception (ex);
4180         return NULL;
4181 }
4182
4183 ICALL_EXPORT MonoArray*
4184 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4185 {
4186         MonoError error;
4187         MonoReflectionType *rt;
4188         MonoDomain *domain; 
4189         MonoClass *klass;
4190         MonoArray *res;
4191         int i, match;
4192         MonoClass *nested;
4193         gpointer iter;
4194         char *str = NULL;
4195         MonoPtrArray tmp_array;
4196
4197         domain = ((MonoObject *)type)->vtable->domain;
4198         if (type->type->byref)
4199                 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4200         klass = mono_class_from_mono_type (type->type);
4201
4202         /*
4203          * If a nested type is generic, return its generic type definition.
4204          * Note that this means that the return value is essentially the set
4205          * of nested types of the generic type definition of @klass.
4206          *
4207          * A note in MSDN claims that a generic type definition can have
4208          * nested types that aren't generic.  In any case, the container of that
4209          * nested type would be the generic type definition.
4210          */
4211         if (klass->generic_class)
4212                 klass = klass->generic_class->container_class;
4213
4214         mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4215         iter = NULL;
4216         while ((nested = mono_class_get_nested_types (klass, &iter))) {
4217                 match = 0;
4218                 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4219                         if (bflags & BFLAGS_Public)
4220                                 match++;
4221                 } else {
4222                         if (bflags & BFLAGS_NonPublic)
4223                                 match++;
4224                 }
4225                 if (!match)
4226                         continue;
4227
4228                 if (name != NULL) {
4229                         if (str == NULL) {
4230                                 str = mono_string_to_utf8 (name);
4231                                 mono_identifier_unescape_type_name_chars (str);
4232                         }
4233
4234                         if (strcmp (nested->name, str))
4235                                 continue;
4236                 }
4237
4238                 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4239                 mono_error_raise_exception (&error);
4240
4241                 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4242         }
4243
4244         res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4245
4246         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4247                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4248
4249         mono_ptr_array_destroy (tmp_array);
4250
4251         if (!str)
4252                 g_free (str);
4253
4254         return res;
4255 }
4256
4257 ICALL_EXPORT MonoReflectionType*
4258 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4259 {
4260         MonoError error;
4261         MonoReflectionType *ret;
4262         gchar *str;
4263         MonoType *type = NULL;
4264         MonoTypeNameParse info;
4265         gboolean type_resolve;
4266
4267         /* On MS.NET, this does not fire a TypeResolve event */
4268         type_resolve = TRUE;
4269         str = mono_string_to_utf8 (name);
4270         /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4271         if (!mono_reflection_parse_type (str, &info)) {
4272                 g_free (str);
4273                 mono_reflection_free_type_info (&info);
4274                 if (throwOnError) {
4275                         mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4276                         return NULL;
4277                 }
4278                 /*g_print ("failed parse\n");*/
4279                 return NULL;
4280         }
4281
4282         if (info.assembly.name) {
4283                 g_free (str);
4284                 mono_reflection_free_type_info (&info);
4285                 if (throwOnError) {
4286                         /* 1.0 and 2.0 throw different exceptions */
4287                         if (mono_defaults.generic_ilist_class)
4288                                 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4289                         else
4290                                 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4291                         return NULL;
4292                 }
4293                 return NULL;
4294         }
4295
4296         if (module != NULL) {
4297                 if (module->image)
4298                         type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4299                 else
4300                         type = NULL;
4301         }
4302         else
4303                 if (assembly_is_dynamic (assembly->assembly)) {
4304                         /* Enumerate all modules */
4305                         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4306                         int i;
4307
4308                         type = NULL;
4309                         if (abuilder->modules) {
4310                                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4311                                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4312                                         type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4313                                         if (type)
4314                                                 break;
4315                                 }
4316                         }
4317
4318                         if (!type && abuilder->loaded_modules) {
4319                                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4320                                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4321                                         type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4322                                         if (type)
4323                                                 break;
4324                                 }
4325                         }
4326                 }
4327                 else
4328                         type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4329         g_free (str);
4330         mono_reflection_free_type_info (&info);
4331         if (!type) {
4332                 MonoException *e = NULL;
4333                 
4334                 if (throwOnError)
4335                         e = mono_get_exception_type_load (name, NULL);
4336
4337                 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4338                         e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4339
4340                 mono_loader_clear_error ();
4341
4342                 if (e != NULL)
4343                         mono_set_pending_exception (e);
4344                 return NULL;
4345         } else if (mono_loader_get_last_error ()) {
4346                 if (throwOnError) {
4347                         mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4348                         return NULL;
4349                 }
4350                 mono_loader_clear_error ();
4351         }
4352
4353         if (type->type == MONO_TYPE_CLASS) {
4354                 MonoClass *klass = mono_type_get_class (type);
4355
4356                 /* need to report exceptions ? */
4357                 if (throwOnError && klass->exception_type) {
4358                         /* report SecurityException (or others) that occured when loading the assembly */
4359                         MonoException *exc = mono_class_get_exception_for_failure (klass);
4360                         mono_loader_clear_error ();
4361                         mono_set_pending_exception (exc);
4362                         return NULL;
4363                 }
4364         }
4365
4366         /* g_print ("got it\n"); */
4367         ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4368         mono_error_raise_exception (&error);
4369
4370         return ret;
4371 }
4372
4373 static gboolean
4374 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4375 {
4376         gchar *content;
4377         gchar *shadow_ini_file;
4378         gsize len;
4379
4380         /* Check for shadow-copied assembly */
4381         if (mono_is_shadow_copy_enabled (domain, dirname)) {
4382                 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4383                 content = NULL;
4384                 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4385                         !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4386                         if (content) {
4387                                 g_free (content);
4388                                 content = NULL;
4389                         }
4390                 }
4391                 g_free (shadow_ini_file);
4392                 if (content != NULL) {
4393                         if (*filename)
4394                                 g_free (*filename);
4395                         *filename = content;
4396                         return TRUE;
4397                 }
4398         }
4399         return FALSE;
4400 }
4401
4402 ICALL_EXPORT MonoString *
4403 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4404 {
4405         MonoDomain *domain = mono_object_domain (assembly); 
4406         MonoAssembly *mass = assembly->assembly;
4407         MonoString *res = NULL;
4408         gchar *uri;
4409         gchar *absolute;
4410         gchar *dirname;
4411         
4412         if (g_path_is_absolute (mass->image->name)) {
4413                 absolute = g_strdup (mass->image->name);
4414                 dirname = g_path_get_dirname (absolute);
4415         } else {
4416                 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4417                 dirname = g_strdup (mass->basedir);
4418         }
4419
4420         replace_shadow_path (domain, dirname, &absolute);
4421         g_free (dirname);
4422 #if HOST_WIN32
4423         {
4424                 gint i;
4425                 for (i = strlen (absolute) - 1; i >= 0; i--)
4426                         if (absolute [i] == '\\')
4427                                 absolute [i] = '/';
4428         }
4429 #endif
4430         if (escaped) {
4431                 uri = g_filename_to_uri (absolute, NULL, NULL);
4432         } else {
4433                 const char *prepend = "file://";
4434 #if HOST_WIN32
4435                 if (*absolute == '/' && *(absolute + 1) == '/') {
4436                         prepend = "file:";
4437                 } else {
4438                         prepend = "file:///";
4439                 }
4440 #endif
4441                 uri = g_strconcat (prepend, absolute, NULL);
4442         }
4443
4444         if (uri) {
4445                 res = mono_string_new (domain, uri);
4446                 g_free (uri);
4447         }
4448         g_free (absolute);
4449         return res;
4450 }
4451
4452 ICALL_EXPORT MonoBoolean
4453 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4454 {
4455         MonoAssembly *mass = assembly->assembly;
4456
4457         return mass->in_gac;
4458 }
4459
4460 ICALL_EXPORT MonoReflectionAssembly*
4461 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4462 {
4463         gchar *name;
4464         MonoAssembly *res;
4465         MonoImageOpenStatus status;
4466         
4467         name = mono_string_to_utf8 (mname);
4468         res = mono_assembly_load_with_partial_name (name, &status);
4469
4470         g_free (name);
4471
4472         if (res == NULL)
4473                 return NULL;
4474         return mono_assembly_get_object (mono_domain_get (), res);
4475 }
4476
4477 ICALL_EXPORT MonoString *
4478 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4479 {
4480         MonoDomain *domain = mono_object_domain (assembly); 
4481         MonoString *res;
4482
4483         res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4484
4485         return res;
4486 }
4487
4488 ICALL_EXPORT MonoBoolean
4489 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4490 {
4491         return assembly->assembly->ref_only;
4492 }
4493
4494 ICALL_EXPORT MonoString *
4495 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4496 {
4497         MonoDomain *domain = mono_object_domain (assembly); 
4498
4499         return mono_string_new (domain, assembly->assembly->image->version);
4500 }
4501
4502 ICALL_EXPORT MonoReflectionMethod*
4503 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly) 
4504 {
4505         MonoError error;
4506         MonoReflectionMethod *res = NULL;
4507         MonoMethod *method;
4508
4509         guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4510
4511         if (!token)
4512                 return NULL;
4513         method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4514         if (!mono_error_ok (&error))
4515                 goto leave;
4516
4517         res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4518
4519 leave:
4520         if (!mono_error_ok (&error))
4521                 mono_error_set_pending_exception (&error);
4522         return res;
4523 }
4524
4525 ICALL_EXPORT MonoReflectionModule*
4526 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly) 
4527 {
4528         MonoError error;
4529         MonoReflectionModule *result = NULL;
4530         result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4531         if (!mono_error_ok (&error))
4532                 mono_error_set_pending_exception (&error);
4533         return result;
4534 }
4535
4536 ICALL_EXPORT MonoArray*
4537 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly) 
4538 {
4539         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4540         MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4541         int i;
4542         const char *val;
4543
4544         for (i = 0; i < table->rows; ++i) {
4545                 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4546                 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4547         }
4548         return result;
4549 }
4550
4551 static MonoObject*
4552 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4553 {
4554         static MonoClass *System_Version = NULL;
4555         static MonoMethod *create_version = NULL;
4556         MonoError error;
4557         MonoObject *result;
4558         gpointer args [4];
4559         
4560         if (!System_Version) {
4561                 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4562                 g_assert (System_Version);
4563         }
4564
4565         if (!create_version) {
4566                 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4567                 create_version = mono_method_desc_search_in_class (desc, System_Version);
4568                 g_assert (create_version);
4569                 mono_method_desc_free (desc);
4570         }
4571
4572         args [0] = &major;
4573         args [1] = &minor;
4574         args [2] = &build;
4575         args [3] = &revision;
4576         result = mono_object_new_checked (domain, System_Version, &error);
4577         mono_error_raise_exception (&error); /* FIXME don't raise here */
4578         mono_runtime_invoke (create_version, result, args, NULL);
4579
4580         return result;
4581 }
4582
4583 ICALL_EXPORT MonoArray*
4584 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly) 
4585 {
4586         static MonoClass *System_Reflection_AssemblyName;
4587         MonoError error;
4588         MonoArray *result;
4589         MonoDomain *domain = mono_object_domain (assembly);
4590         int i, count = 0;
4591         static MonoMethod *create_culture = NULL;
4592         MonoImage *image = assembly->assembly->image;
4593         MonoTableInfo *t;
4594
4595         if (!System_Reflection_AssemblyName)
4596                 System_Reflection_AssemblyName = mono_class_from_name (
4597                         mono_defaults.corlib, "System.Reflection", "AssemblyName");
4598
4599         t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4600         count = t->rows;
4601
4602         result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4603
4604         if (count > 0 && !create_culture) {
4605                 MonoMethodDesc *desc = mono_method_desc_new (
4606                         "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4607                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4608                 g_assert (create_culture);
4609                 mono_method_desc_free (desc);
4610         }
4611
4612         for (i = 0; i < count; i++) {
4613                 MonoReflectionAssemblyName *aname;
4614                 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4615
4616                 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4617
4618                 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4619                         domain, System_Reflection_AssemblyName, &error);
4620                 mono_error_raise_exception (&error);
4621
4622                 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4623
4624                 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4625                 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4626                 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4627                 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4628                 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4629                 aname->versioncompat = 1; /* SameMachine (default) */
4630                 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4631                 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4632
4633                 if (create_culture) {
4634                         gpointer args [2];
4635                         MonoBoolean assembly_ref = 1;
4636                         args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4637                         args [1] = &assembly_ref;
4638                         MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4639                 }
4640                 
4641                 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4642                         const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4643                         guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4644
4645                         if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4646                                 /* public key token isn't copied - the class library will 
4647                                 automatically generate it from the public key if required */
4648                                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4649                                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4650                         } else {
4651                                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4652                                 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4653                         }
4654                 } else {
4655                         MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4656                 }
4657                 
4658                 /* note: this function doesn't return the codebase on purpose (i.e. it can
4659                          be used under partial trust as path information isn't present). */
4660
4661                 mono_array_setref (result, i, aname);
4662         }
4663         return result;
4664 }
4665
4666 /* move this in some file in mono/util/ */
4667 static char *
4668 g_concat_dir_and_file (const char *dir, const char *file)
4669 {
4670         g_return_val_if_fail (dir != NULL, NULL);
4671         g_return_val_if_fail (file != NULL, NULL);
4672
4673         /*
4674          * If the directory name doesn't have a / on the end, we need
4675          * to add one so we get a proper path to the file
4676          */
4677         if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4678                 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4679         else
4680                 return g_strconcat (dir, file, NULL);
4681 }
4682
4683 ICALL_EXPORT void *
4684 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module) 
4685 {
4686         MonoError error;
4687         char *n = mono_string_to_utf8 (name);
4688         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4689         guint32 i;
4690         guint32 cols [MONO_MANIFEST_SIZE];
4691         guint32 impl, file_idx;
4692         const char *val;
4693         MonoImage *module;
4694
4695         for (i = 0; i < table->rows; ++i) {
4696                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4697                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4698                 if (strcmp (val, n) == 0)
4699                         break;
4700         }
4701         g_free (n);
4702         if (i == table->rows)
4703                 return NULL;
4704         /* FIXME */
4705         impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4706         if (impl) {
4707                 /*
4708                  * this code should only be called after obtaining the 
4709                  * ResourceInfo and handling the other cases.
4710                  */
4711                 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4712                 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4713
4714                 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4715                 if (!module)
4716                         return NULL;
4717         }
4718         else
4719                 module = assembly->assembly->image;
4720
4721         
4722         MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4723         mono_error_raise_exception (&error);
4724         mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4725
4726         return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4727 }
4728
4729 ICALL_EXPORT gboolean
4730 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4731 {
4732         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4733         int i;
4734         guint32 cols [MONO_MANIFEST_SIZE];
4735         guint32 file_cols [MONO_FILE_SIZE];
4736         const char *val;
4737         char *n;
4738
4739         n = mono_string_to_utf8 (name);
4740         for (i = 0; i < table->rows; ++i) {
4741                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4742                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4743                 if (strcmp (val, n) == 0)
4744                         break;
4745         }
4746         g_free (n);
4747         if (i == table->rows)
4748                 return FALSE;
4749
4750         if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4751                 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4752         }
4753         else {
4754                 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4755                 case MONO_IMPLEMENTATION_FILE:
4756                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4757                         table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4758                         mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4759                         val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4760                         MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4761                         if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4762                                 info->location = 0;
4763                         else
4764                                 info->location = RESOURCE_LOCATION_EMBEDDED;
4765                         break;
4766
4767                 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4768                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4769                         mono_assembly_load_reference (assembly->assembly->image, i - 1);
4770                         if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4771                                 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4772                                 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4773                                 g_free (msg);
4774                                 mono_set_pending_exception (ex);
4775                                 return FALSE;
4776                         }
4777                         MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4778
4779                         /* Obtain info recursively */
4780                         ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4781                         info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4782                         break;
4783
4784                 case MONO_IMPLEMENTATION_EXP_TYPE:
4785                         g_assert_not_reached ();
4786                         break;
4787                 }
4788         }
4789
4790         return TRUE;
4791 }
4792
4793 ICALL_EXPORT MonoObject*
4794 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules) 
4795 {
4796         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4797         MonoArray *result = NULL;
4798         int i, count;
4799         const char *val;
4800         char *n;
4801
4802         /* check hash if needed */
4803         if (name) {
4804                 n = mono_string_to_utf8 (name);
4805                 for (i = 0; i < table->rows; ++i) {
4806                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4807                         if (strcmp (val, n) == 0) {
4808                                 MonoString *fn;
4809                                 g_free (n);
4810                                 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4811                                 fn = mono_string_new (mono_object_domain (assembly), n);
4812                                 g_free (n);
4813                                 return (MonoObject*)fn;
4814                         }
4815                 }
4816                 g_free (n);
4817                 return NULL;
4818         }
4819
4820         count = 0;
4821         for (i = 0; i < table->rows; ++i) {
4822                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4823                         count ++;
4824         }
4825
4826         result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4827
4828         count = 0;
4829         for (i = 0; i < table->rows; ++i) {
4830                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4831                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4832                         n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4833                         mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4834                         g_free (n);
4835                         count ++;
4836                 }
4837         }
4838         return (MonoObject*)result;
4839 }
4840
4841 ICALL_EXPORT MonoArray*
4842 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4843 {
4844         MonoError error;
4845         MonoDomain *domain = mono_domain_get();
4846         MonoArray *res;
4847         MonoClass *klass;
4848         int i, j, file_count = 0;
4849         MonoImage **modules;
4850         guint32 module_count, real_module_count;
4851         MonoTableInfo *table;
4852         guint32 cols [MONO_FILE_SIZE];
4853         MonoImage *image = assembly->assembly->image;
4854
4855         g_assert (image != NULL);
4856         g_assert (!assembly_is_dynamic (assembly->assembly));
4857
4858         table = &image->tables [MONO_TABLE_FILE];
4859         file_count = table->rows;
4860
4861         modules = image->modules;
4862         module_count = image->module_count;
4863
4864         real_module_count = 0;
4865         for (i = 0; i < module_count; ++i)
4866                 if (modules [i])
4867                         real_module_count ++;
4868
4869         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4870         res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4871
4872         MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
4873         mono_error_raise_exception (&error);
4874         mono_array_setref (res, 0, image_obj);
4875         j = 1;
4876         for (i = 0; i < module_count; ++i)
4877                 if (modules [i]) {
4878                         MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
4879                         mono_error_raise_exception (&error);
4880                         mono_array_setref (res, j, rm);
4881                         ++j;
4882                 }
4883
4884         for (i = 0; i < file_count; ++i, ++j) {
4885                 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4886                 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4887                         mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4888                 else {
4889                         MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4890                         if (!m) {
4891                                 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4892                                 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
4893                                 return NULL;
4894                         }
4895                         MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
4896                         mono_error_raise_exception (&error);
4897                         mono_array_setref (res, j, rm);
4898                 }
4899         }
4900
4901         return res;
4902 }
4903
4904 ICALL_EXPORT MonoReflectionMethod*
4905 ves_icall_GetCurrentMethod (void) 
4906 {
4907         MonoReflectionMethod *res = NULL;
4908         MonoError error;
4909
4910         MonoMethod *m = mono_method_get_last_managed ();
4911
4912         if (!m) {
4913                 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
4914                 return NULL;
4915         }
4916
4917         while (m->is_inflated)
4918                 m = ((MonoMethodInflated*)m)->declaring;
4919
4920         res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
4921         mono_error_raise_exception (&error);
4922         return res;
4923 }
4924
4925
4926 static MonoMethod*
4927 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4928 {
4929         int offset = -1, i;
4930         if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4931                 MonoError error;
4932                 MonoMethod *result;
4933                 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4934                 //method is inflated, we should inflate it on the other class
4935                 MonoGenericContext ctx;
4936                 ctx.method_inst = inflated->context.method_inst;
4937                 ctx.class_inst = inflated->context.class_inst;
4938                 if (klass->generic_class)
4939                         ctx.class_inst = klass->generic_class->context.class_inst;
4940                 else if (klass->generic_container)
4941                         ctx.class_inst = klass->generic_container->context.class_inst;
4942                 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
4943                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4944                 return result;
4945         }
4946
4947         mono_class_setup_methods (method->klass);
4948         if (method->klass->exception_type)
4949                 return NULL;
4950         for (i = 0; i < method->klass->method.count; ++i) {
4951                 if (method->klass->methods [i] == method) {
4952                         offset = i;
4953                         break;
4954                 }       
4955         }
4956         mono_class_setup_methods (klass);
4957         if (klass->exception_type)
4958                 return NULL;
4959         g_assert (offset >= 0 && offset < klass->method.count);
4960         return klass->methods [offset];
4961 }
4962
4963 ICALL_EXPORT MonoReflectionMethod*
4964 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4965 {
4966         MonoReflectionMethod *res = NULL;
4967         MonoError error;
4968         MonoClass *klass;
4969         if (type) {
4970                 klass = mono_class_from_mono_type (type);
4971                 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass)) 
4972                         return NULL;
4973                 if (method->klass != klass) {
4974                         method = mono_method_get_equivalent_method (method, klass);
4975                         if (!method)
4976                                 return NULL;
4977                 }
4978         } else
4979                 klass = method->klass;
4980         res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
4981         mono_error_raise_exception (&error);
4982         return res;
4983 }
4984
4985 ICALL_EXPORT MonoReflectionMethodBody*
4986 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4987 {
4988         return mono_method_body_get_object (mono_domain_get (), method);
4989 }
4990
4991 ICALL_EXPORT MonoReflectionAssembly*
4992 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4993 {
4994         MonoMethod *dest = NULL;
4995
4996         mono_stack_walk_no_il (get_executing, &dest);
4997         g_assert (dest);
4998         return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4999 }
5000
5001
5002 ICALL_EXPORT MonoReflectionAssembly*
5003 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5004 {
5005         MonoDomain* domain = mono_domain_get ();
5006
5007         if (!domain->entry_assembly)
5008                 return NULL;
5009
5010         return mono_assembly_get_object (domain, domain->entry_assembly);
5011 }
5012
5013 ICALL_EXPORT MonoReflectionAssembly*
5014 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5015 {
5016         MonoMethod *m;
5017         MonoMethod *dest;
5018
5019         dest = NULL;
5020         mono_stack_walk_no_il (get_executing, &dest);
5021         m = dest;
5022         mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5023         if (!dest)
5024                 dest = m;
5025         if (!m) {
5026                 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5027                 return NULL;
5028         }
5029         return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5030 }
5031
5032 ICALL_EXPORT MonoString *
5033 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5034                                        gboolean assembly_qualified)
5035 {
5036         MonoDomain *domain = mono_object_domain (object); 
5037         MonoTypeNameFormat format;
5038         MonoString *res;
5039         gchar *name;
5040
5041         if (full_name)
5042                 format = assembly_qualified ?
5043                         MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5044                         MONO_TYPE_NAME_FORMAT_FULL_NAME;
5045         else
5046                 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5047  
5048         name = mono_type_get_name_full (object->type, format);
5049         if (!name)
5050                 return NULL;
5051
5052         if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5053                 g_free (name);
5054                 return NULL;
5055         }
5056
5057         res = mono_string_new (domain, name);
5058         g_free (name);
5059
5060         return res;
5061 }
5062
5063 ICALL_EXPORT int
5064 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5065 {
5066         MonoClass *klass = mono_class_from_mono_type (rfield->type);
5067         mono_class_init_or_throw (klass);
5068         return mono_security_core_clr_class_level (klass);
5069 }
5070
5071 ICALL_EXPORT int
5072 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5073 {
5074         MonoClassField *field = rfield->field;
5075         return mono_security_core_clr_field_level (field, TRUE);
5076 }
5077
5078 ICALL_EXPORT int
5079 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5080 {
5081         MonoMethod *method = rfield->method;
5082         return mono_security_core_clr_method_level (method, TRUE);
5083 }
5084
5085 static void
5086 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
5087 {
5088         static MonoMethod *create_culture = NULL;
5089         gpointer args [2];
5090         guint32 pkey_len;
5091         const char *pkey_ptr;
5092         gchar *codebase;
5093         MonoBoolean assembly_ref = 0;
5094
5095         MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5096         aname->major = name->major;
5097         aname->minor = name->minor;
5098         aname->build = name->build;
5099         aname->flags = name->flags;
5100         aname->revision = name->revision;
5101         aname->hashalg = name->hash_alg;
5102         aname->versioncompat = 1; /* SameMachine (default) */
5103         aname->processor_architecture = name->arch;
5104
5105         if (by_default_version)
5106                 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
5107
5108         codebase = NULL;
5109         if (absolute != NULL && *absolute != '\0') {
5110                 const gchar *prepend = "file://";
5111                 gchar *result;
5112
5113                 codebase = g_strdup (absolute);
5114
5115 #if HOST_WIN32
5116                 {
5117                         gint i;
5118                         for (i = strlen (codebase) - 1; i >= 0; i--)
5119                                 if (codebase [i] == '\\')
5120                                         codebase [i] = '/';
5121
5122                         if (*codebase == '/' && *(codebase + 1) == '/') {
5123                                 prepend = "file:";
5124                         } else {
5125                                 prepend = "file:///";
5126                         }
5127                 }
5128 #endif
5129                 result = g_strconcat (prepend, codebase, NULL);
5130                 g_free (codebase);
5131                 codebase = result;
5132         }
5133
5134         if (codebase) {
5135                 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5136                 g_free (codebase);
5137         }
5138
5139         if (!create_culture) {
5140                 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5141                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5142                 g_assert (create_culture);
5143                 mono_method_desc_free (desc);
5144         }
5145
5146         if (name->culture) {
5147                 args [0] = mono_string_new (domain, name->culture);
5148                 args [1] = &assembly_ref;
5149                 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5150         }
5151
5152         if (name->public_key) {
5153                 pkey_ptr = (char*)name->public_key;
5154                 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5155
5156                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5157                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5158                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5159         } else if (default_publickey) {
5160                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5161                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5162         }
5163
5164         /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5165         if (name->public_key_token [0]) {
5166                 int i, j;
5167                 char *p;
5168
5169                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5170                 p = mono_array_addr (aname->keyToken, char, 0);
5171
5172                 for (i = 0, j = 0; i < 8; i++) {
5173                         *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5174                         *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5175                         p++;
5176                 }
5177         } else if (default_token) {
5178                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5179         }
5180 }
5181
5182 ICALL_EXPORT MonoString *
5183 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5184 {
5185         MonoDomain *domain = mono_object_domain (assembly); 
5186         MonoAssembly *mass = assembly->assembly;
5187         MonoString *res;
5188         gchar *name;
5189
5190         name = mono_stringify_assembly_name (&mass->aname);
5191         res = mono_string_new (domain, name);
5192         g_free (name);
5193
5194         return res;
5195 }
5196
5197 ICALL_EXPORT void
5198 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5199 {
5200         gchar *absolute;
5201         MonoAssembly *mass = assembly->assembly;
5202
5203         if (g_path_is_absolute (mass->image->name)) {
5204                 fill_reflection_assembly_name (mono_object_domain (assembly),
5205                         aname, &mass->aname, mass->image->name, TRUE,
5206                         TRUE, TRUE);
5207                 return;
5208         }
5209         absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5210
5211         fill_reflection_assembly_name (mono_object_domain (assembly),
5212                 aname, &mass->aname, absolute, TRUE, TRUE,
5213                 TRUE);
5214
5215         g_free (absolute);
5216 }
5217
5218 ICALL_EXPORT void
5219 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5220 {
5221         char *filename;
5222         MonoImageOpenStatus status = MONO_IMAGE_OK;
5223         gboolean res;
5224         MonoImage *image;
5225         MonoAssemblyName name;
5226         char *dirname;
5227
5228         filename = mono_string_to_utf8 (fname);
5229
5230         dirname = g_path_get_dirname (filename);
5231         replace_shadow_path (mono_domain_get (), dirname, &filename);
5232         g_free (dirname);
5233
5234         image = mono_image_open (filename, &status);
5235
5236         if (!image){
5237                 MonoException *exc;
5238
5239                 g_free (filename);
5240                 if (status == MONO_IMAGE_IMAGE_INVALID)
5241                         exc = mono_get_exception_bad_image_format2 (NULL, fname);
5242                 else
5243                         exc = mono_get_exception_file_not_found2 (NULL, fname);
5244                 mono_set_pending_exception (exc);
5245                 return;
5246         }
5247
5248         res = mono_assembly_fill_assembly_name (image, &name);
5249         if (!res) {
5250                 mono_image_close (image);
5251                 g_free (filename);
5252                 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5253                 return;
5254         }
5255
5256         fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5257                 TRUE, FALSE, TRUE);
5258
5259         g_free (filename);
5260         mono_image_close (image);
5261 }
5262
5263 ICALL_EXPORT MonoBoolean
5264 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5265         char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5266 {
5267         MonoBoolean result = FALSE;
5268         MonoDeclSecurityEntry entry;
5269
5270         /* SecurityAction.RequestMinimum */
5271         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5272                 *minimum = entry.blob;
5273                 *minLength = entry.size;
5274                 result = TRUE;
5275         }
5276         /* SecurityAction.RequestOptional */
5277         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5278                 *optional = entry.blob;
5279                 *optLength = entry.size;
5280                 result = TRUE;
5281         }
5282         /* SecurityAction.RequestRefuse */
5283         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5284                 *refused = entry.blob;
5285                 *refLength = entry.size;
5286                 result = TRUE;
5287         }
5288
5289         return result;  
5290 }
5291
5292 static gboolean
5293 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5294 {
5295         guint32 attrs, visibility;
5296         do {
5297                 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5298                 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5299                 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5300                         return FALSE;
5301
5302         } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5303
5304         return TRUE;
5305 }
5306
5307 static MonoArray*
5308 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5309 {
5310         MonoError error;
5311         MonoReflectionType *rt;
5312         MonoArray *res;
5313         MonoClass *klass;
5314         MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5315         int i, count;
5316
5317         /* we start the count from 1 because we skip the special type <Module> */
5318         if (exportedOnly) {
5319                 count = 0;
5320                 for (i = 1; i < tdef->rows; ++i) {
5321                         if (mono_module_type_is_visible (tdef, image, i + 1))
5322                                 count++;
5323                 }
5324         } else {
5325                 count = tdef->rows - 1;
5326         }
5327         res = mono_array_new (domain, mono_defaults.monotype_class, count);
5328         *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5329         count = 0;
5330         for (i = 1; i < tdef->rows; ++i) {
5331                 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5332                         klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, &error);
5333                         mono_loader_assert_no_error (); /* Plug any leaks */
5334                         g_assert (mono_error_ok (&error));
5335                         
5336                         if (klass) {
5337                                 rt = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5338                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
5339
5340                                 mono_array_setref (res, count, rt);
5341                         } else {
5342                                 MonoException *ex = mono_error_convert_to_exception (&error);
5343                                 mono_array_setref (*exceptions, count, ex);
5344                         }
5345                         count++;
5346                 }
5347         }
5348         
5349         return res;
5350 }
5351
5352 ICALL_EXPORT MonoArray*
5353 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5354 {
5355         MonoArray *res = NULL;
5356         MonoArray *exceptions = NULL;
5357         MonoImage *image = NULL;
5358         MonoTableInfo *table = NULL;
5359         MonoDomain *domain;
5360         GList *list = NULL;
5361         int i, len, ex_count;
5362
5363         domain = mono_object_domain (assembly);
5364
5365         g_assert (!assembly_is_dynamic (assembly->assembly));
5366         image = assembly->assembly->image;
5367         table = &image->tables [MONO_TABLE_FILE];
5368         res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5369
5370         /* Append data from all modules in the assembly */
5371         for (i = 0; i < table->rows; ++i) {
5372                 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5373                         MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5374                         if (loaded_image) {
5375                                 MonoArray *ex2;
5376                                 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5377                                 /* Append the new types to the end of the array */
5378                                 if (mono_array_length (res2) > 0) {
5379                                         guint32 len1, len2;
5380                                         MonoArray *res3, *ex3;
5381
5382                                         len1 = mono_array_length (res);
5383                                         len2 = mono_array_length (res2);
5384
5385                                         res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5386                                         mono_array_memcpy_refs (res3, 0, res, 0, len1);
5387                                         mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5388                                         res = res3;
5389
5390                                         ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5391                                         mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5392                                         mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5393                                         exceptions = ex3;
5394                                 }
5395                         }
5396                 }
5397         }
5398
5399         /* the ReflectionTypeLoadException must have all the types (Types property), 
5400          * NULL replacing types which throws an exception. The LoaderException must
5401          * contain all exceptions for NULL items.
5402          */
5403
5404         len = mono_array_length (res);
5405
5406         ex_count = 0;
5407         for (i = 0; i < len; i++) {
5408                 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5409                 MonoClass *klass;
5410
5411                 if (t) {
5412                         klass = mono_type_get_class (t->type);
5413                         if ((klass != NULL) && klass->exception_type) {
5414                                 /* keep the class in the list */
5415                                 list = g_list_append (list, klass);
5416                                 /* and replace Type with NULL */
5417                                 mono_array_setref (res, i, NULL);
5418                         }
5419                 } else {
5420                         ex_count ++;
5421                 }
5422         }
5423
5424         if (list || ex_count) {
5425                 GList *tmp = NULL;
5426                 MonoException *exc = NULL;
5427                 MonoArray *exl = NULL;
5428                 int j, length = g_list_length (list) + ex_count;
5429
5430                 mono_loader_clear_error ();
5431
5432                 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5433                 /* Types for which mono_class_get_checked () succeeded */
5434                 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5435                         MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5436                         mono_array_setref (exl, i, exc);
5437                 }
5438                 /* Types for which it don't */
5439                 for (j = 0; j < mono_array_length (exceptions); ++j) {
5440                         MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5441                         if (exc) {
5442                                 g_assert (i < length);
5443                                 mono_array_setref (exl, i, exc);
5444                                 i ++;
5445                         }
5446                 }
5447                 g_list_free (list);
5448                 list = NULL;
5449
5450                 exc = mono_get_exception_reflection_type_load (res, exl);
5451                 mono_loader_clear_error ();
5452                 mono_set_pending_exception (exc);
5453                 return NULL;
5454         }
5455                 
5456         return res;
5457 }
5458
5459 ICALL_EXPORT gboolean
5460 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5461 {
5462         MonoAssemblyName aname;
5463         MonoDomain *domain = mono_object_domain (name);
5464         char *val;
5465         gboolean is_version_defined;
5466         gboolean is_token_defined;
5467
5468         aname.public_key = NULL;
5469         val = mono_string_to_utf8 (assname);
5470         if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5471                 g_free ((guint8*) aname.public_key);
5472                 g_free (val);
5473                 return FALSE;
5474         }
5475         
5476         fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5477                 FALSE, is_token_defined);
5478
5479         mono_assembly_name_free (&aname);
5480         g_free ((guint8*) aname.public_key);
5481         g_free (val);
5482
5483         return TRUE;
5484 }
5485
5486 ICALL_EXPORT MonoReflectionType*
5487 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5488 {
5489         MonoError error;
5490         MonoReflectionType *ret;
5491         MonoDomain *domain = mono_object_domain (module); 
5492         MonoClass *klass;
5493
5494         g_assert (module->image);
5495
5496         if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5497                 /* These images do not have a global type */
5498                 return NULL;
5499
5500         klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5501         if (!mono_error_ok (&error)) {
5502                 mono_error_set_pending_exception (&error);
5503                 return NULL;
5504         }
5505
5506         ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5507         if (!mono_error_ok (&error)) {
5508                 mono_error_set_pending_exception (&error);
5509                 return NULL;
5510         }
5511
5512         return ret;
5513 }
5514
5515 ICALL_EXPORT void
5516 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5517 {
5518         /*if (module->image)
5519                 mono_image_close (module->image);*/
5520 }
5521
5522 ICALL_EXPORT MonoString*
5523 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5524 {
5525         MonoDomain *domain = mono_object_domain (module); 
5526
5527         g_assert (module->image);
5528         return mono_string_new (domain, module->image->guid);
5529 }
5530
5531 ICALL_EXPORT gpointer
5532 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5533 {
5534 #ifdef HOST_WIN32
5535         if (module->image && module->image->is_module_handle)
5536                 return module->image->raw_data;
5537 #endif
5538
5539         return (gpointer) (-1);
5540 }
5541
5542 ICALL_EXPORT void
5543 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5544 {
5545         if (image_is_dynamic (image)) {
5546                 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5547                 *pe_kind = dyn->pe_kind;
5548                 *machine = dyn->machine;
5549         }
5550         else {
5551                 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5552                 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5553         }
5554 }
5555
5556 ICALL_EXPORT gint32
5557 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5558 {
5559         return (image->md_version_major << 16) | (image->md_version_minor);
5560 }
5561
5562 ICALL_EXPORT MonoArray*
5563 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5564 {
5565         MonoArray *exceptions;
5566         int i;
5567
5568         if (!module->image)
5569                 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5570         else {
5571                 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5572                 for (i = 0; i < mono_array_length (exceptions); ++i) {
5573                         MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5574                         if (ex) {
5575                                 mono_set_pending_exception (ex);
5576                                 return NULL;
5577                         }
5578                 }
5579                 return res;
5580         }
5581 }
5582
5583 static gboolean
5584 mono_memberref_is_method (MonoImage *image, guint32 token)
5585 {
5586         if (!image_is_dynamic (image)) {
5587                 guint32 cols [MONO_MEMBERREF_SIZE];
5588                 const char *sig;
5589                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5590                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5591                 mono_metadata_decode_blob_size (sig, &sig);
5592                 return (*sig != 0x6);
5593         } else {
5594                 MonoClass *handle_class;
5595
5596                 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5597                         return FALSE;
5598
5599                 return mono_defaults.methodhandle_class == handle_class;
5600         }
5601 }
5602
5603 static void
5604 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5605 {
5606         if (type_args)
5607                 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5608                                                                       mono_array_addr (type_args, MonoType*, 0));
5609         else
5610                 context->class_inst = NULL;
5611         if (method_args)
5612                 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5613                                                                        mono_array_addr (method_args, MonoType*, 0));
5614         else
5615                 context->method_inst = NULL;
5616 }
5617
5618 ICALL_EXPORT MonoType*
5619 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5620 {
5621         MonoClass *klass;
5622         int table = mono_metadata_token_table (token);
5623         int index = mono_metadata_token_index (token);
5624         MonoGenericContext context;
5625         MonoError error;
5626
5627         *resolve_error = ResolveTokenError_Other;
5628
5629         /* Validate token */
5630         if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) && 
5631                 (table != MONO_TABLE_TYPESPEC)) {
5632                 *resolve_error = ResolveTokenError_BadTable;
5633                 return NULL;
5634         }
5635
5636         if (image_is_dynamic (image)) {
5637                 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5638                         klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5639                         return klass ? &klass->byval_arg : NULL;
5640                 }
5641
5642                 init_generic_context_from_args (&context, type_args, method_args);
5643                 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5644                 return klass ? &klass->byval_arg : NULL;
5645         }
5646
5647         if ((index <= 0) || (index > image->tables [table].rows)) {
5648                 *resolve_error = ResolveTokenError_OutOfRange;
5649                 return NULL;
5650         }
5651
5652         init_generic_context_from_args (&context, type_args, method_args);
5653         klass = mono_class_get_checked (image, token, &error);
5654         if (klass)
5655                 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5656         if (!mono_error_ok (&error)) {
5657                 mono_error_set_pending_exception (&error);
5658                 return NULL;
5659         }
5660
5661         if (klass)
5662                 return &klass->byval_arg;
5663         else
5664                 return NULL;
5665 }
5666
5667 ICALL_EXPORT MonoMethod*
5668 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5669 {
5670         MonoError error;
5671         int table = mono_metadata_token_table (token);
5672         int index = mono_metadata_token_index (token);
5673         MonoGenericContext context;
5674         MonoMethod *method;
5675
5676         *resolve_error = ResolveTokenError_Other;
5677
5678         /* Validate token */
5679         if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) && 
5680                 (table != MONO_TABLE_MEMBERREF)) {
5681                 *resolve_error = ResolveTokenError_BadTable;
5682                 return NULL;
5683         }
5684
5685         if (image_is_dynamic (image)) {
5686                 if (table == MONO_TABLE_METHOD)
5687                         return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5688
5689                 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5690                         *resolve_error = ResolveTokenError_BadTable;
5691                         return NULL;
5692                 }
5693
5694                 init_generic_context_from_args (&context, type_args, method_args);
5695                 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5696         }
5697
5698         if ((index <= 0) || (index > image->tables [table].rows)) {
5699                 *resolve_error = ResolveTokenError_OutOfRange;
5700                 return NULL;
5701         }
5702         if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5703                 *resolve_error = ResolveTokenError_BadTable;
5704                 return NULL;
5705         }
5706
5707         init_generic_context_from_args (&context, type_args, method_args);
5708         method = mono_get_method_checked (image, token, NULL, &context, &error);
5709         mono_error_set_pending_exception (&error);
5710
5711         return method;
5712 }
5713
5714 ICALL_EXPORT MonoString*
5715 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5716 {
5717         int index = mono_metadata_token_index (token);
5718
5719         *error = ResolveTokenError_Other;
5720
5721         /* Validate token */
5722         if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5723                 *error = ResolveTokenError_BadTable;
5724                 return NULL;
5725         }
5726
5727         if (image_is_dynamic (image))
5728                 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5729
5730         if ((index <= 0) || (index >= image->heap_us.size)) {
5731                 *error = ResolveTokenError_OutOfRange;
5732                 return NULL;
5733         }
5734
5735         /* FIXME: What to do if the index points into the middle of a string ? */
5736
5737         return mono_ldstr (mono_domain_get (), image, index);
5738 }
5739
5740 ICALL_EXPORT MonoClassField*
5741 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5742 {
5743         MonoError error;
5744         MonoClass *klass;
5745         int table = mono_metadata_token_table (token);
5746         int index = mono_metadata_token_index (token);
5747         MonoGenericContext context;
5748         MonoClassField *field;
5749
5750         *resolve_error = ResolveTokenError_Other;
5751
5752         /* Validate token */
5753         if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5754                 *resolve_error = ResolveTokenError_BadTable;
5755                 return NULL;
5756         }
5757
5758         if (image_is_dynamic (image)) {
5759                 if (table == MONO_TABLE_FIELD)
5760                         return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5761
5762                 if (mono_memberref_is_method (image, token)) {
5763                         *resolve_error = ResolveTokenError_BadTable;
5764                         return NULL;
5765                 }
5766
5767                 init_generic_context_from_args (&context, type_args, method_args);
5768                 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5769         }
5770
5771         if ((index <= 0) || (index > image->tables [table].rows)) {
5772                 *resolve_error = ResolveTokenError_OutOfRange;
5773                 return NULL;
5774         }
5775         if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5776                 *resolve_error = ResolveTokenError_BadTable;
5777                 return NULL;
5778         }
5779
5780         init_generic_context_from_args (&context, type_args, method_args);
5781         field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5782         mono_error_set_pending_exception (&error);
5783         
5784         return field;
5785 }
5786
5787
5788 ICALL_EXPORT MonoObject*
5789 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5790 {
5791         MonoError merror;
5792         MonoObject *ret;
5793         int table = mono_metadata_token_table (token);
5794
5795         *error = ResolveTokenError_Other;
5796
5797         switch (table) {
5798         case MONO_TABLE_TYPEDEF:
5799         case MONO_TABLE_TYPEREF:
5800         case MONO_TABLE_TYPESPEC: {
5801                 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5802                 if (t) {
5803                         ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
5804                         mono_error_raise_exception (&merror);
5805
5806                         return ret;
5807                 }
5808                 else
5809                         return NULL;
5810         }
5811         case MONO_TABLE_METHOD:
5812         case MONO_TABLE_METHODSPEC: {
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         case MONO_TABLE_FIELD: {
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         case MONO_TABLE_MEMBERREF:
5833                 if (mono_memberref_is_method (image, token)) {
5834                         MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5835                         if (m) {
5836                                 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5837                                 mono_error_raise_exception (&merror);
5838
5839                                 return ret;
5840                         } else
5841                                 return NULL;
5842                 }
5843                 else {
5844                         MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5845                         if (f) {
5846                                 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5847                                 mono_error_raise_exception (&merror);
5848                                 return ret;
5849                         }
5850                         else
5851                                 return NULL;
5852                 }
5853                 break;
5854
5855         default:
5856                 *error = ResolveTokenError_BadTable;
5857         }
5858
5859         return NULL;
5860 }
5861
5862 ICALL_EXPORT MonoArray*
5863 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5864 {
5865         int table = mono_metadata_token_table (token);
5866         int idx = mono_metadata_token_index (token);
5867         MonoTableInfo *tables = image->tables;
5868         guint32 sig, len;
5869         const char *ptr;
5870         MonoArray *res;
5871
5872         *error = ResolveTokenError_OutOfRange;
5873
5874         /* FIXME: Support other tables ? */
5875         if (table != MONO_TABLE_STANDALONESIG)
5876                 return NULL;
5877
5878         if (image_is_dynamic (image))
5879                 return NULL;
5880
5881         if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5882                 return NULL;
5883
5884         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5885
5886         ptr = mono_metadata_blob_heap (image, sig);
5887         len = mono_metadata_decode_blob_size (ptr, &ptr);
5888
5889         res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5890         memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5891         return res;
5892 }
5893
5894 ICALL_EXPORT MonoReflectionType*
5895 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5896 {
5897         MonoError error;
5898         MonoReflectionType *ret;
5899         MonoClass *klass;
5900         int isbyref = 0, rank;
5901         char *str = mono_string_to_utf8 (smodifiers);
5902         char *p;
5903
5904         klass = mono_class_from_mono_type (tb->type.type);
5905         p = str;
5906         /* logic taken from mono_reflection_parse_type(): keep in sync */
5907         while (*p) {
5908                 switch (*p) {
5909                 case '&':
5910                         if (isbyref) { /* only one level allowed by the spec */
5911                                 g_free (str);
5912                                 return NULL;
5913                         }
5914                         isbyref = 1;
5915                         p++;
5916
5917                         g_free (str);
5918
5919                         ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
5920                         mono_error_raise_exception (&error);
5921
5922                         return ret;
5923                 case '*':
5924                         klass = mono_ptr_class_get (&klass->byval_arg);
5925                         mono_class_init (klass);
5926                         p++;
5927                         break;
5928                 case '[':
5929                         rank = 1;
5930                         p++;
5931                         while (*p) {
5932                                 if (*p == ']')
5933                                         break;
5934                                 if (*p == ',')
5935                                         rank++;
5936                                 else if (*p != '*') { /* '*' means unknown lower bound */
5937                                         g_free (str);
5938                                         return NULL;
5939                                 }
5940                                 ++p;
5941                         }
5942                         if (*p != ']') {
5943                                 g_free (str);
5944                                 return NULL;
5945                         }
5946                         p++;
5947                         klass = mono_array_class_get (klass, rank);
5948                         mono_class_init (klass);
5949                         break;
5950                 default:
5951                         break;
5952                 }
5953         }
5954
5955         g_free (str);
5956
5957         ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
5958         mono_error_raise_exception (&error);
5959
5960         return ret;
5961 }
5962
5963 ICALL_EXPORT MonoBoolean
5964 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5965 {
5966         MonoType *type;
5967         MonoBoolean res;
5968
5969         type = t->type;
5970         res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5971
5972         return res;
5973 }
5974
5975 static void
5976 check_for_invalid_type (MonoClass *klass)
5977 {
5978         char *name;
5979         MonoString *str;
5980         if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5981                 return;
5982
5983         name = mono_type_get_full_name (klass);
5984         str =  mono_string_new (mono_domain_get (), name);
5985         g_free (name);
5986         mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5987
5988 }
5989 ICALL_EXPORT MonoReflectionType *
5990 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5991 {
5992         MonoError error;
5993         MonoReflectionType *ret;
5994         MonoClass *klass, *aklass;
5995
5996         klass = mono_class_from_mono_type (type->type);
5997         check_for_invalid_type (klass);
5998
5999         if (rank == 0) //single dimentional array
6000                 aklass = mono_array_class_get (klass, 1);
6001         else
6002                 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6003
6004         ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6005         mono_error_raise_exception (&error);
6006
6007         return ret;
6008 }
6009
6010 ICALL_EXPORT MonoReflectionType *
6011 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6012 {
6013         MonoError error;
6014         MonoReflectionType *ret;
6015         MonoClass *klass;
6016
6017         klass = mono_class_from_mono_type (type->type);
6018         mono_class_init_or_throw (klass);
6019         check_for_invalid_type (klass);
6020
6021         ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6022         mono_error_raise_exception (&error);
6023
6024         return ret;
6025 }
6026
6027 ICALL_EXPORT MonoReflectionType *
6028 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6029 {
6030         MonoError error;
6031         MonoReflectionType *ret;
6032         MonoClass *klass, *pklass;
6033
6034         klass = mono_class_from_mono_type (type->type);
6035         mono_class_init_or_throw (klass);
6036         check_for_invalid_type (klass);
6037
6038         pklass = mono_ptr_class_get (type->type);
6039
6040         ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6041         mono_error_raise_exception (&error);
6042
6043         return ret;
6044 }
6045
6046 ICALL_EXPORT MonoObject *
6047 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6048                                                    MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6049 {
6050         MonoError error;
6051         MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6052         MonoObject *delegate;
6053         gpointer func;
6054         MonoMethod *method = info->method;
6055
6056         mono_class_init_or_throw (delegate_class);
6057
6058         mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
6059
6060         if (mono_security_core_clr_enabled ()) {
6061                 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6062                         return NULL;
6063         }
6064
6065         delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6066         mono_error_raise_exception (&error);
6067
6068         if (method_is_dynamic (method)) {
6069                 /* Creating a trampoline would leak memory */
6070                 func = mono_compile_method (method);
6071         } else {
6072                 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6073                         method = mono_object_get_virtual_method (target, method);
6074                 func = mono_create_ftnptr (mono_domain_get (),
6075                         mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6076         }
6077
6078         mono_delegate_ctor_with_method (delegate, target, func, method);
6079
6080         return delegate;
6081 }
6082
6083 ICALL_EXPORT MonoMulticastDelegate *
6084 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6085 {
6086         MonoError error;
6087         MonoMulticastDelegate *ret;
6088
6089         g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6090
6091         ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6092         mono_error_raise_exception (&error);
6093         ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6094
6095         return ret;
6096 }
6097
6098 ICALL_EXPORT MonoReflectionMethod*
6099 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6100 {
6101         MonoReflectionMethod *ret = NULL;
6102         MonoError error;
6103         ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6104         mono_error_raise_exception (&error);
6105         return ret;
6106 }
6107
6108 /* System.Buffer */
6109
6110 static inline gint32 
6111 mono_array_get_byte_length (MonoArray *array)
6112 {
6113         MonoClass *klass;
6114         int length;
6115         int i;
6116
6117         klass = array->obj.vtable->klass;
6118
6119         if (array->bounds == NULL)
6120                 length = array->max_length;
6121         else {
6122                 length = 1;
6123                 for (i = 0; i < klass->rank; ++ i)
6124                         length *= array->bounds [i].length;
6125         }
6126
6127         switch (klass->element_class->byval_arg.type) {
6128         case MONO_TYPE_I1:
6129         case MONO_TYPE_U1:
6130         case MONO_TYPE_BOOLEAN:
6131                 return length;
6132         case MONO_TYPE_I2:
6133         case MONO_TYPE_U2:
6134         case MONO_TYPE_CHAR:
6135                 return length << 1;
6136         case MONO_TYPE_I4:
6137         case MONO_TYPE_U4:
6138         case MONO_TYPE_R4:
6139                 return length << 2;
6140         case MONO_TYPE_I:
6141         case MONO_TYPE_U:
6142                 return length * sizeof (gpointer);
6143         case MONO_TYPE_I8:
6144         case MONO_TYPE_U8:
6145         case MONO_TYPE_R8:
6146                 return length << 3;
6147         default:
6148                 return -1;
6149         }
6150 }
6151
6152 ICALL_EXPORT gint32 
6153 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array) 
6154 {
6155         return mono_array_get_byte_length (array);
6156 }
6157
6158 ICALL_EXPORT gint8 
6159 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx) 
6160 {
6161         return mono_array_get (array, gint8, idx);
6162 }
6163
6164 ICALL_EXPORT void 
6165 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value) 
6166 {
6167         mono_array_set (array, gint8, idx, value);
6168 }
6169
6170 ICALL_EXPORT MonoBoolean
6171 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count) 
6172 {
6173         guint8 *src_buf, *dest_buf;
6174
6175         if (count < 0) {
6176                 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6177                 return FALSE;
6178         }
6179
6180         g_assert (count >= 0);
6181
6182         /* This is called directly from the class libraries without going through the managed wrapper */
6183         MONO_CHECK_ARG_NULL (src, FALSE);
6184         MONO_CHECK_ARG_NULL (dest, FALSE);
6185
6186         /* watch out for integer overflow */
6187         if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6188                 return FALSE;
6189
6190         src_buf = (guint8 *)src->vector + src_offset;
6191         dest_buf = (guint8 *)dest->vector + dest_offset;
6192
6193         if (src != dest)
6194                 memcpy (dest_buf, src_buf, count);
6195         else
6196                 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6197
6198         return TRUE;
6199 }
6200
6201 #ifndef DISABLE_REMOTING
6202 ICALL_EXPORT MonoObject *
6203 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6204 {
6205         MonoError error;
6206         MonoDomain *domain = mono_object_domain (this_obj); 
6207         MonoObject *res;
6208         MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6209         MonoTransparentProxy *tp;
6210         MonoType *type;
6211         MonoClass *klass;
6212
6213         res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6214         mono_error_raise_exception (&error);
6215         tp = (MonoTransparentProxy*) res;
6216         
6217         MONO_OBJECT_SETREF (tp, rp, rp);
6218         type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6219         klass = mono_class_from_mono_type (type);
6220
6221         // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6222         mono_class_setup_vtable (klass);
6223         if (klass->exception_type) {
6224                 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6225                 return NULL;
6226         }
6227
6228         tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6229         tp->remote_class = mono_remote_class (domain, class_name, klass);
6230
6231         res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6232         return res;
6233 }
6234
6235 ICALL_EXPORT MonoReflectionType *
6236 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6237 {
6238         MonoError error;
6239         MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6240         mono_error_raise_exception (&error);
6241
6242         return ret;
6243 }
6244 #endif
6245
6246 /* System.Environment */
6247
6248 MonoString*
6249 ves_icall_System_Environment_get_UserName (void)
6250 {
6251         /* using glib is more portable */
6252         return mono_string_new (mono_domain_get (), g_get_user_name ());
6253 }
6254
6255
6256 ICALL_EXPORT MonoString *
6257 ves_icall_System_Environment_get_MachineName (void)
6258 {
6259 #if defined (HOST_WIN32)
6260         gunichar2 *buf;
6261         guint32 len;
6262         MonoString *result;
6263
6264         len = MAX_COMPUTERNAME_LENGTH + 1;
6265         buf = g_new (gunichar2, len);
6266
6267         result = NULL;
6268         if (GetComputerName (buf, (PDWORD) &len)) {
6269                 MonoError error;
6270                 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6271                 mono_error_raise_exception (&error);
6272         }
6273
6274         g_free (buf);
6275         return result;
6276 #elif !defined(DISABLE_SOCKETS)
6277         MonoString *result;
6278         char *buf;
6279         int n;
6280 #if defined _SC_HOST_NAME_MAX
6281         n = sysconf (_SC_HOST_NAME_MAX);
6282         if (n == -1)
6283 #endif
6284         n = 512;
6285         buf = g_malloc (n+1);
6286         
6287         if (gethostname (buf, n) == 0){
6288                 buf [n] = 0;
6289                 result = mono_string_new (mono_domain_get (), buf);
6290         } else
6291                 result = NULL;
6292         g_free (buf);
6293         
6294         return result;
6295 #else
6296         return mono_string_new (mono_domain_get (), "mono");
6297 #endif
6298 }
6299
6300 ICALL_EXPORT int
6301 ves_icall_System_Environment_get_Platform (void)
6302 {
6303 #if defined (TARGET_WIN32)
6304         /* Win32NT */
6305         return 2;
6306 #elif defined(__MACH__)
6307         /* OSX */
6308         //
6309         // Notice that the value is hidden from user code, and only exposed
6310         // to mscorlib.   This is due to Mono's Unix/MacOS code predating the
6311         // define and making assumptions based on Unix/128/4 values before there
6312         // was a MacOS define.    Lots of code would assume that not-Unix meant
6313         // Windows, but in this case, it would be OSX. 
6314         //
6315         return 6;
6316 #else
6317         /* Unix */
6318         return 4;
6319 #endif
6320 }
6321
6322 ICALL_EXPORT MonoString *
6323 ves_icall_System_Environment_get_NewLine (void)
6324 {
6325 #if defined (HOST_WIN32)
6326         return mono_string_new (mono_domain_get (), "\r\n");
6327 #else
6328         return mono_string_new (mono_domain_get (), "\n");
6329 #endif
6330 }
6331
6332 ICALL_EXPORT MonoBoolean
6333 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6334 {
6335 #if SIZEOF_VOID_P == 8
6336         return TRUE;
6337 #else
6338 #ifdef HOST_WIN32
6339         gboolean isWow64Process = FALSE;
6340         if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6341                 return (MonoBoolean)isWow64Process;
6342         }
6343 #elif defined(HAVE_SYS_UTSNAME_H)
6344         struct utsname name;
6345
6346         if (uname (&name) >= 0) {
6347                 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6348         }
6349 #endif
6350         return FALSE;
6351 #endif
6352 }
6353
6354 ICALL_EXPORT MonoString *
6355 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6356 {
6357         const gchar *value;
6358         gchar *utf8_name;
6359
6360         if (name == NULL)
6361                 return NULL;
6362
6363         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6364         value = g_getenv (utf8_name);
6365
6366         g_free (utf8_name);
6367
6368         if (value == 0)
6369                 return NULL;
6370         
6371         return mono_string_new (mono_domain_get (), value);
6372 }
6373
6374 /*
6375  * There is no standard way to get at environ.
6376  */
6377 #ifndef _MSC_VER
6378 #ifndef __MINGW32_VERSION
6379 #if defined(__APPLE__)
6380 #if defined (TARGET_OSX)
6381 /* Apple defines this in crt_externs.h but doesn't provide that header for 
6382  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
6383  * in fact exist on all implementations (so far) 
6384  */
6385 gchar ***_NSGetEnviron(void);
6386 #define environ (*_NSGetEnviron())
6387 #else
6388 static char *mono_environ[1] = { NULL };
6389 #define environ mono_environ
6390 #endif /* defined (TARGET_OSX) */
6391 #else
6392 extern
6393 char **environ;
6394 #endif
6395 #endif
6396 #endif
6397
6398 ICALL_EXPORT MonoArray *
6399 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6400 {
6401 #ifdef HOST_WIN32
6402         MonoArray *names;
6403         MonoDomain *domain;
6404         MonoString *str;
6405         WCHAR* env_strings;
6406         WCHAR* env_string;
6407         WCHAR* equal_str;
6408         int n = 0;
6409
6410         env_strings = GetEnvironmentStrings();
6411
6412         if (env_strings) {
6413                 env_string = env_strings;
6414                 while (*env_string != '\0') {
6415                 /* weird case that MS seems to skip */
6416                         if (*env_string != '=')
6417                                 n++;
6418                         while (*env_string != '\0')
6419                                 env_string++;
6420                         env_string++;
6421                 }
6422         }
6423
6424         domain = mono_domain_get ();
6425         names = mono_array_new (domain, mono_defaults.string_class, n);
6426
6427         if (env_strings) {
6428                 n = 0;
6429                 env_string = env_strings;
6430                 while (*env_string != '\0') {
6431                         /* weird case that MS seems to skip */
6432                         if (*env_string != '=') {
6433                                 equal_str = wcschr(env_string, '=');
6434                                 g_assert(equal_str);
6435                                 MonoError error;
6436                                 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6437                                 mono_error_raise_exception (&error);
6438                                 mono_array_setref (names, n, str);
6439                                 n++;
6440                         }
6441                         while (*env_string != '\0')
6442                                 env_string++;
6443                         env_string++;
6444                 }
6445
6446                 FreeEnvironmentStrings (env_strings);
6447         }
6448
6449         return names;
6450
6451 #else
6452         MonoArray *names;
6453         MonoDomain *domain;
6454         MonoString *str;
6455         gchar **e, **parts;
6456         int n;
6457
6458         n = 0;
6459         for (e = environ; *e != 0; ++ e)
6460                 ++ n;
6461
6462         domain = mono_domain_get ();
6463         names = mono_array_new (domain, mono_defaults.string_class, n);
6464
6465         n = 0;
6466         for (e = environ; *e != 0; ++ e) {
6467                 parts = g_strsplit (*e, "=", 2);
6468                 if (*parts != 0) {
6469                         str = mono_string_new (domain, *parts);
6470                         mono_array_setref (names, n, str);
6471                 }
6472
6473                 g_strfreev (parts);
6474
6475                 ++ n;
6476         }
6477
6478         return names;
6479 #endif
6480 }
6481
6482 /*
6483  * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6484  */
6485 #if !GLIB_CHECK_VERSION(2,4,0)
6486 #define g_setenv(a,b,c)   setenv(a,b,c)
6487 #define g_unsetenv(a) unsetenv(a)
6488 #endif
6489
6490 ICALL_EXPORT void
6491 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6492 {
6493 #ifdef HOST_WIN32
6494         gunichar2 *utf16_name, *utf16_value;
6495 #else
6496         gchar *utf8_name, *utf8_value;
6497         MonoError error;
6498 #endif
6499
6500 #ifdef HOST_WIN32
6501         utf16_name = mono_string_to_utf16 (name);
6502         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6503                 SetEnvironmentVariable (utf16_name, NULL);
6504                 g_free (utf16_name);
6505                 return;
6506         }
6507
6508         utf16_value = mono_string_to_utf16 (value);
6509
6510         SetEnvironmentVariable (utf16_name, utf16_value);
6511
6512         g_free (utf16_name);
6513         g_free (utf16_value);
6514 #else
6515         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6516
6517         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6518                 g_unsetenv (utf8_name);
6519                 g_free (utf8_name);
6520                 return;
6521         }
6522
6523         utf8_value = mono_string_to_utf8_checked (value, &error);
6524         if (!mono_error_ok (&error)) {
6525                 g_free (utf8_name);
6526                 mono_error_set_pending_exception (&error);
6527                 return;
6528         }
6529         g_setenv (utf8_name, utf8_value, TRUE);
6530
6531         g_free (utf8_name);
6532         g_free (utf8_value);
6533 #endif
6534 }
6535
6536 ICALL_EXPORT void
6537 ves_icall_System_Environment_Exit (int result)
6538 {
6539         mono_environment_exitcode_set (result);
6540
6541 /* FIXME: There are some cleanup hangs that should be worked out, but
6542  * if the program is going to exit, everything will be cleaned up when
6543  * NaCl exits anyway.
6544  */
6545 #ifndef __native_client__
6546         if (!mono_runtime_try_shutdown ())
6547                 mono_thread_exit ();
6548
6549         /* Suspend all managed threads since the runtime is going away */
6550         mono_thread_suspend_all_other_threads ();
6551
6552         mono_runtime_quit ();
6553 #endif
6554
6555         /* we may need to do some cleanup here... */
6556         exit (result);
6557 }
6558
6559 ICALL_EXPORT MonoString*
6560 ves_icall_System_Environment_GetGacPath (void)
6561 {
6562         return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6563 }
6564
6565 ICALL_EXPORT MonoString*
6566 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6567 {
6568 #if defined (HOST_WIN32)
6569         #ifndef CSIDL_FLAG_CREATE
6570                 #define CSIDL_FLAG_CREATE       0x8000
6571         #endif
6572
6573         WCHAR path [MAX_PATH];
6574         /* Create directory if no existing */
6575         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6576                 int len = 0;
6577                 while (path [len])
6578                         ++ len;
6579                 MonoError error;
6580                 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6581                 mono_error_raise_exception (&error);
6582                 return res;
6583         }
6584 #else
6585         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6586 #endif
6587         return mono_string_new (mono_domain_get (), "");
6588 }
6589
6590 ICALL_EXPORT MonoArray *
6591 ves_icall_System_Environment_GetLogicalDrives (void)
6592 {
6593         MonoError error;
6594         gunichar2 buf [256], *ptr, *dname;
6595         gunichar2 *u16;
6596         guint initial_size = 127, size = 128;
6597         gint ndrives;
6598         MonoArray *result;
6599         MonoString *drivestr;
6600         MonoDomain *domain = mono_domain_get ();
6601         gint len;
6602
6603         buf [0] = '\0';
6604         ptr = buf;
6605
6606         while (size > initial_size) {
6607                 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6608                 if (size > initial_size) {
6609                         if (ptr != buf)
6610                                 g_free (ptr);
6611                         ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6612                         initial_size = size;
6613                         size++;
6614                 }
6615         }
6616
6617         /* Count strings */
6618         dname = ptr;
6619         ndrives = 0;
6620         do {
6621                 while (*dname++);
6622                 ndrives++;
6623         } while (*dname);
6624
6625         dname = ptr;
6626         result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6627         ndrives = 0;
6628         do {
6629                 len = 0;
6630                 u16 = dname;
6631                 while (*u16) { u16++; len ++; }
6632                 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6633                 mono_error_raise_exception (&error);
6634                 mono_array_setref (result, ndrives++, drivestr);
6635                 while (*dname++);
6636         } while (*dname);
6637
6638         if (ptr != buf)
6639                 g_free (ptr);
6640
6641         return result;
6642 }
6643
6644 ICALL_EXPORT MonoString *
6645 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6646 {
6647         gunichar2 volume_name [MAX_PATH + 1];
6648         
6649         if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6650                 return NULL;
6651         return mono_string_from_utf16 (volume_name);
6652 }
6653
6654 ICALL_EXPORT MonoString *
6655 ves_icall_System_Environment_InternalGetHome (void)
6656 {
6657         return mono_string_new (mono_domain_get (), g_get_home_dir ());
6658 }
6659
6660 static const char *encodings [] = {
6661         (char *) 1,
6662                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6663                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6664                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6665         (char *) 2,
6666                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6667                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6668                 "x_unicode_2_0_utf_7",
6669         (char *) 3,
6670                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6671                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6672         (char *) 4,
6673                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6674                 "iso_10646_ucs2",
6675         (char *) 5,
6676                 "unicodefffe", "utf_16be",
6677         (char *) 6,
6678                 "iso_8859_1",
6679         (char *) 0
6680 };
6681
6682 /*
6683  * Returns the internal codepage, if the value of "int_code_page" is
6684  * 1 at entry, and we can not compute a suitable code page number,
6685  * returns the code page as a string
6686  */
6687 ICALL_EXPORT MonoString*
6688 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page) 
6689 {
6690         const char *cset;
6691         const char *p;
6692         char *c;
6693         char *codepage = NULL;
6694         int code;
6695         int want_name = *int_code_page;
6696         int i;
6697         
6698         *int_code_page = -1;
6699
6700         g_get_charset (&cset);
6701         c = codepage = strdup (cset);
6702         for (c = codepage; *c; c++){
6703                 if (isascii (*c) && isalpha (*c))
6704                         *c = tolower (*c);
6705                 if (*c == '-')
6706                         *c = '_';
6707         }
6708         /* g_print ("charset: %s\n", cset); */
6709         
6710         /* handle some common aliases */
6711         p = encodings [0];
6712         code = 0;
6713         for (i = 0; p != 0; ){
6714                 if ((gsize) p < 7){
6715                         code = (gssize) p;
6716                         p = encodings [++i];
6717                         continue;
6718                 }
6719                 if (strcmp (p, codepage) == 0){
6720                         *int_code_page = code;
6721                         break;
6722                 }
6723                 p = encodings [++i];
6724         }
6725         
6726         if (strstr (codepage, "utf_8") != NULL)
6727                 *int_code_page |= 0x10000000;
6728         free (codepage);
6729         
6730         if (want_name && *int_code_page == -1)
6731                 return mono_string_new (mono_domain_get (), cset);
6732         else
6733                 return NULL;
6734 }
6735
6736 ICALL_EXPORT MonoBoolean
6737 ves_icall_System_Environment_get_HasShutdownStarted (void)
6738 {
6739         if (mono_runtime_is_shutting_down ())
6740                 return TRUE;
6741
6742         if (mono_domain_is_unloading (mono_domain_get ()))
6743                 return TRUE;
6744
6745         return FALSE;
6746 }
6747
6748 ICALL_EXPORT void
6749 ves_icall_System_Environment_BroadcastSettingChange (void)
6750 {
6751 #ifdef HOST_WIN32
6752         SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6753 #endif
6754 }
6755
6756 ICALL_EXPORT gint32
6757 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6758 {
6759         return 9;
6760 }
6761
6762 ICALL_EXPORT void
6763 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj, 
6764                                          MonoReflectionMethod *method,
6765                                          MonoArray *out_args)
6766 {
6767         mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6768 }
6769
6770 #ifndef DISABLE_REMOTING
6771 ICALL_EXPORT MonoBoolean
6772 ves_icall_IsTransparentProxy (MonoObject *proxy)
6773 {
6774         if (!proxy)
6775                 return 0;
6776
6777         if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6778                 return 1;
6779
6780         return 0;
6781 }
6782
6783 ICALL_EXPORT MonoReflectionMethod *
6784 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6785         MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6786 {
6787         MonoReflectionMethod *ret = NULL;
6788         MonoError error;
6789
6790         MonoClass *klass;
6791         MonoMethod *method;
6792         MonoMethod **vtable;
6793         MonoMethod *res = NULL;
6794
6795         MONO_CHECK_ARG_NULL (rtype, NULL);
6796         MONO_CHECK_ARG_NULL (rmethod, NULL);
6797
6798         method = rmethod->method;
6799         klass = mono_class_from_mono_type (rtype->type);
6800         mono_class_init_or_throw (klass);
6801
6802         if (MONO_CLASS_IS_INTERFACE (klass))
6803                 return NULL;
6804
6805         if (method->flags & METHOD_ATTRIBUTE_STATIC)
6806                 return NULL;
6807
6808         if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6809                 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6810                         return rmethod;
6811                 else
6812                         return NULL;
6813         }
6814
6815         mono_class_setup_vtable (klass);
6816         vtable = klass->vtable;
6817
6818         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6819                 gboolean variance_used = FALSE;
6820                 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6821                 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6822                 if (offs >= 0)
6823                         res = vtable [offs + method->slot];
6824         } else {
6825                 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6826                         return NULL;
6827
6828                 if (method->slot != -1)
6829                         res = vtable [method->slot];
6830         }
6831
6832         if (!res)
6833                 return NULL;
6834
6835         ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
6836         mono_error_raise_exception (&error);
6837         return ret;
6838 }
6839
6840 ICALL_EXPORT void
6841 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6842 {
6843         MonoClass *klass;
6844         MonoVTable* vtable;
6845
6846         klass = mono_class_from_mono_type (type->type);
6847         vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6848
6849         mono_vtable_set_is_remote (vtable, enable);
6850 }
6851
6852 #else /* DISABLE_REMOTING */
6853
6854 ICALL_EXPORT void
6855 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6856 {
6857         g_assert_not_reached ();
6858 }
6859
6860 #endif
6861
6862 ICALL_EXPORT MonoObject *
6863 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6864 {
6865         MonoError error;
6866         MonoClass *klass;
6867         MonoDomain *domain;
6868         MonoObject *ret;
6869         
6870         domain = mono_object_domain (type);
6871         klass = mono_class_from_mono_type (type->type);
6872         mono_class_init_or_throw (klass);
6873
6874         if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
6875                 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6876                 return NULL;
6877         }
6878
6879         if (klass->rank >= 1) {
6880                 g_assert (klass->rank == 1);
6881                 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6882         } else {
6883                 /* Bypass remoting object creation check */
6884                 ret = mono_object_new_alloc_specific_checked (mono_class_vtable_full (domain, klass, TRUE), &error);
6885                 mono_error_set_pending_exception (&error);
6886
6887                 return ret;
6888         }
6889 }
6890
6891 ICALL_EXPORT MonoString *
6892 ves_icall_System_IO_get_temp_path (void)
6893 {
6894         return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6895 }
6896
6897 #ifndef PLATFORM_NO_DRIVEINFO
6898 ICALL_EXPORT MonoBoolean
6899 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6900                                                 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6901                                                 gint32 *error)
6902 {
6903         gboolean result;
6904         ULARGE_INTEGER wapi_free_bytes_avail;
6905         ULARGE_INTEGER wapi_total_number_of_bytes;
6906         ULARGE_INTEGER wapi_total_number_of_free_bytes;
6907
6908         *error = ERROR_SUCCESS;
6909         result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6910                                      &wapi_total_number_of_free_bytes);
6911
6912         if (result) {
6913                 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6914                 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6915                 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6916         } else {
6917                 *free_bytes_avail = 0;
6918                 *total_number_of_bytes = 0;
6919                 *total_number_of_free_bytes = 0;
6920                 *error = GetLastError ();
6921         }
6922
6923         return result;
6924 }
6925
6926 ICALL_EXPORT guint32
6927 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6928 {
6929         return GetDriveType (mono_string_chars (root_path_name));
6930 }
6931 #endif
6932
6933 ICALL_EXPORT gpointer
6934 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6935 {
6936         return mono_compile_method (method);
6937 }
6938
6939 ICALL_EXPORT MonoString *
6940 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6941 {
6942         MonoString *mcpath;
6943         gchar *path;
6944
6945         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6946
6947 #if defined (HOST_WIN32)
6948         /* Avoid mixing '/' and '\\' */
6949         {
6950                 gint i;
6951                 for (i = strlen (path) - 1; i >= 0; i--)
6952                         if (path [i] == '/')
6953                                 path [i] = '\\';
6954         }
6955 #endif
6956         mcpath = mono_string_new (mono_domain_get (), path);
6957         g_free (path);
6958
6959         return mcpath;
6960 }
6961
6962 static MonoString *
6963 get_bundled_app_config (void)
6964 {
6965         const gchar *app_config;
6966         MonoDomain *domain;
6967         MonoString *file;
6968         gchar *config_file_name, *config_file_path;
6969         gsize len, config_file_path_length, config_ext_length;
6970         gchar *module;
6971
6972         domain = mono_domain_get ();
6973         file = domain->setup->configuration_file;
6974         if (!file || file->length == 0)
6975                 return NULL;
6976
6977         // Retrieve config file and remove the extension
6978         config_file_name = mono_string_to_utf8 (file);
6979         config_file_path = mono_portability_find_file (config_file_name, TRUE);
6980         if (!config_file_path)
6981                 config_file_path = config_file_name;
6982
6983         config_file_path_length = strlen (config_file_path);
6984         config_ext_length = strlen (".config");
6985         if (config_file_path_length <= config_ext_length)
6986                 return NULL;
6987
6988         len = config_file_path_length - config_ext_length;
6989         module = (gchar *)g_malloc0 (len + 1);
6990         memcpy (module, config_file_path, len);
6991         // Get the config file from the module name
6992         app_config = mono_config_string_for_assembly_file (module);
6993         // Clean-up
6994         g_free (module);
6995         if (config_file_name != config_file_path)
6996                 g_free (config_file_name);
6997         g_free (config_file_path);
6998
6999         if (!app_config)
7000                 return NULL;
7001
7002         return mono_string_new (mono_domain_get (), app_config);
7003 }
7004
7005 static MonoString *
7006 get_bundled_machine_config (void)
7007 {
7008         const gchar *machine_config;
7009
7010         machine_config = mono_get_machine_config ();
7011
7012         if (!machine_config)
7013                 return NULL;
7014
7015         return mono_string_new (mono_domain_get (), machine_config);
7016 }
7017
7018 ICALL_EXPORT MonoString *
7019 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7020 {
7021         MonoString *ipath;
7022         gchar *path;
7023
7024         path = g_path_get_dirname (mono_get_config_dir ());
7025
7026 #if defined (HOST_WIN32)
7027         /* Avoid mixing '/' and '\\' */
7028         {
7029                 gint i;
7030                 for (i = strlen (path) - 1; i >= 0; i--)
7031                         if (path [i] == '/')
7032                                 path [i] = '\\';
7033         }
7034 #endif
7035         ipath = mono_string_new (mono_domain_get (), path);
7036         g_free (path);
7037
7038         return ipath;
7039 }
7040
7041 ICALL_EXPORT gboolean
7042 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7043 {
7044         MonoPEResourceDataEntry *entry;
7045         MonoImage *image;
7046
7047         if (!assembly || !result || !size)
7048                 return FALSE;
7049
7050         *result = NULL;
7051         *size = 0;
7052         image = assembly->assembly->image;
7053         entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7054         if (!entry)
7055                 return FALSE;
7056
7057         *result = mono_image_rva_map (image, entry->rde_data_offset);
7058         if (!(*result)) {
7059                 g_free (entry);
7060                 return FALSE;
7061         }
7062         *size = entry->rde_size;
7063         g_free (entry);
7064         return TRUE;
7065 }
7066
7067 ICALL_EXPORT MonoBoolean
7068 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7069 {
7070         return mono_is_debugger_attached ();
7071 }
7072
7073 ICALL_EXPORT MonoBoolean
7074 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7075 {
7076         if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7077                 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7078         else
7079                 return FALSE;
7080 }
7081
7082 ICALL_EXPORT void
7083 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7084 {
7085         if (mono_get_runtime_callbacks ()->debug_log)
7086                 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7087 }
7088
7089 ICALL_EXPORT void
7090 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7091 {
7092 #if defined (HOST_WIN32)
7093         OutputDebugString (mono_string_chars (message));
7094 #else
7095         g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7096 #endif
7097 }
7098
7099 /* Only used for value types */
7100 ICALL_EXPORT MonoObject *
7101 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7102 {
7103         MonoError error;
7104         MonoObject *result;
7105         MonoClass *klass;
7106         MonoDomain *domain;
7107         
7108         domain = mono_object_domain (type);
7109         klass = mono_class_from_mono_type (type->type);
7110         mono_class_init_or_throw (klass);
7111
7112         if (mono_class_is_nullable (klass))
7113                 /* No arguments -> null */
7114                 return NULL;
7115
7116         result = mono_object_new_checked (domain, klass, &error);
7117         mono_error_raise_exception (&error);
7118         return result;
7119 }
7120
7121 ICALL_EXPORT MonoReflectionMethod *
7122 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7123 {
7124         MonoReflectionMethod *ret = NULL;
7125         MonoError error;
7126
7127         MonoClass *klass, *parent;
7128         MonoGenericContext *generic_inst = NULL;
7129         MonoMethod *method = m->method;
7130         MonoMethod *result = NULL;
7131         int slot;
7132
7133         if (method->klass == NULL)
7134                 return m;
7135
7136         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7137             MONO_CLASS_IS_INTERFACE (method->klass) ||
7138             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7139                 return m;
7140
7141         slot = mono_method_get_vtable_slot (method);
7142         if (slot == -1)
7143                 return m;
7144
7145         klass = method->klass;
7146         if (klass->generic_class) {
7147                 generic_inst = mono_class_get_context (klass);
7148                 klass = klass->generic_class->container_class;
7149         }
7150
7151         if (definition) {
7152                 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7153                 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7154                         /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7155                            or klass is the generic container class and generic_inst is the instantiation.
7156
7157                            when we go to the parent, if the parent is an open constructed type, we need to
7158                            replace the type parameters by the definitions from the generic_inst, and then take it
7159                            apart again into the klass and the generic_inst.
7160
7161                            For cases like this:
7162                            class C<T> : B<T, int> {
7163                                public override void Foo () { ... }
7164                            }
7165                            class B<U,V> : A<HashMap<U,V>> {
7166                                public override void Foo () { ... }
7167                            }
7168                            class A<X> {
7169                                public virtual void Foo () { ... }
7170                            }
7171
7172                            if at each iteration the parent isn't open, we can skip inflating it.  if at some
7173                            iteration the parent isn't generic (after possible inflation), we set generic_inst to
7174                            NULL;
7175                         */
7176                         MonoGenericContext *parent_inst = NULL;
7177                         if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7178                                 MonoError error;
7179                                 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7180                                 if (!mono_error_ok (&error)) {
7181                                         mono_error_set_pending_exception (&error);
7182                                         return NULL;
7183                                 }
7184                         }
7185                         if (parent->generic_class) {
7186                                 parent_inst = mono_class_get_context (parent);
7187                                 parent = parent->generic_class->container_class;
7188                         }
7189
7190                         mono_class_setup_vtable (parent);
7191                         if (parent->vtable_size <= slot)
7192                                 break;
7193                         klass = parent;
7194                         generic_inst = parent_inst;
7195                 }
7196         } else {
7197                 klass = klass->parent;
7198                 if (!klass)
7199                         return m;
7200                 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7201                         klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7202                         if (!mono_error_ok (&error)) {
7203                                 mono_error_set_pending_exception (&error);
7204                                 return NULL;
7205                         }
7206
7207                         generic_inst = NULL;
7208                 }
7209                 if (klass->generic_class) {
7210                         generic_inst = mono_class_get_context (klass);
7211                         klass = klass->generic_class->container_class;
7212                 }
7213
7214         }
7215
7216         if (generic_inst) {
7217                 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7218                 if (!mono_error_ok (&error)) {
7219                         mono_error_set_pending_exception (&error);
7220                         return NULL;
7221                 }
7222         }
7223
7224         if (klass == method->klass)
7225                 return m;
7226
7227         /*This is possible if definition == FALSE.
7228          * Do it here to be really sure we don't read invalid memory.
7229          */
7230         if (slot >= klass->vtable_size)
7231                 return m;
7232
7233         mono_class_setup_vtable (klass);
7234
7235         result = klass->vtable [slot];
7236         if (result == NULL) {
7237                 /* It is an abstract method */
7238                 gpointer iter = NULL;
7239                 while ((result = mono_class_get_methods (klass, &iter)))
7240                         if (result->slot == slot)
7241                                 break;
7242         }
7243
7244         if (result == NULL)
7245                 return m;
7246
7247         ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7248         mono_error_raise_exception (&error);
7249         return ret;
7250 }
7251
7252 ICALL_EXPORT MonoString*
7253 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7254 {
7255         MonoMethod *method = m->method;
7256
7257         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7258         return m->name;
7259 }
7260
7261 ICALL_EXPORT void
7262 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7263 {
7264         iter->sig = *(MonoMethodSignature**)argsp;
7265         
7266         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7267         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7268
7269         iter->next_arg = 0;
7270         /* FIXME: it's not documented what start is exactly... */
7271         if (start) {
7272                 iter->args = start;
7273         } else {
7274                 iter->args = argsp + sizeof (gpointer);
7275         }
7276         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7277
7278         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7279 }
7280
7281 ICALL_EXPORT MonoTypedRef
7282 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7283 {
7284         guint32 i, arg_size;
7285         gint32 align;
7286         MonoTypedRef res;
7287
7288         i = iter->sig->sentinelpos + iter->next_arg;
7289
7290         g_assert (i < iter->sig->param_count);
7291
7292         res.type = iter->sig->params [i];
7293         res.klass = mono_class_from_mono_type (res.type);
7294         arg_size = mono_type_stack_size (res.type, &align);
7295 #if defined(__arm__) || defined(__mips__)
7296         iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7297 #endif
7298         res.value = iter->args;
7299 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7300         /* Values are stored as 8 byte register sized objects, but 'value'
7301          * is dereferenced as a pointer in other routines.
7302          */
7303         res.value = (char*)res.value + 4;
7304 #endif
7305 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7306         if (arg_size <= sizeof (gpointer)) {
7307                 int dummy;
7308                 int padding = arg_size - mono_type_size (res.type, &dummy);
7309                 res.value = (guint8*)res.value + padding;
7310         }
7311 #endif
7312         iter->args = (char*)iter->args + arg_size;
7313         iter->next_arg++;
7314
7315         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7316
7317         return res;
7318 }
7319
7320 ICALL_EXPORT MonoTypedRef
7321 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7322 {
7323         guint32 i, arg_size;
7324         gint32 align;
7325         MonoTypedRef res;
7326
7327         i = iter->sig->sentinelpos + iter->next_arg;
7328
7329         g_assert (i < iter->sig->param_count);
7330
7331         while (i < iter->sig->param_count) {
7332                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7333                         continue;
7334                 res.type = iter->sig->params [i];
7335                 res.klass = mono_class_from_mono_type (res.type);
7336                 /* FIXME: endianess issue... */
7337                 arg_size = mono_type_stack_size (res.type, &align);
7338 #if defined(__arm__) || defined(__mips__)
7339                 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7340 #endif
7341                 res.value = iter->args;
7342                 iter->args = (char*)iter->args + arg_size;
7343                 iter->next_arg++;
7344                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7345                 return res;
7346         }
7347         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7348
7349         res.type = NULL;
7350         res.value = NULL;
7351         res.klass = NULL;
7352         return res;
7353 }
7354
7355 ICALL_EXPORT MonoType*
7356 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7357 {
7358         gint i;
7359         
7360         i = iter->sig->sentinelpos + iter->next_arg;
7361
7362         g_assert (i < iter->sig->param_count);
7363
7364         return iter->sig->params [i];
7365 }
7366
7367 ICALL_EXPORT MonoObject*
7368 mono_TypedReference_ToObject (MonoTypedRef* tref)
7369 {
7370         if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7371                 MonoObject** objp = (MonoObject **)tref->value;
7372                 return *objp;
7373         }
7374
7375         return mono_value_box (mono_domain_get (), tref->klass, tref->value);
7376 }
7377
7378 ICALL_EXPORT MonoTypedRef
7379 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7380 {
7381         MonoTypedRef res;
7382         MonoReflectionField *f;
7383         MonoClass *klass;
7384         MonoType *ftype = NULL;
7385         guint8 *p = NULL;
7386         int i;
7387
7388         memset (&res, 0, sizeof (res));
7389
7390         g_assert (fields);
7391         g_assert (mono_array_length (fields) > 0);
7392
7393         klass = target->vtable->klass;
7394
7395         for (i = 0; i < mono_array_length (fields); ++i) {
7396                 f = mono_array_get (fields, MonoReflectionField*, i);
7397                 if (f == NULL) {
7398                         mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7399                         return res;
7400                 }
7401                 if (f->field->parent != klass) {
7402                         mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7403                         return res;
7404                 }
7405                 if (i == 0)
7406                         p = (guint8*)target + f->field->offset;
7407                 else
7408                         p += f->field->offset - sizeof (MonoObject);
7409                 klass = mono_class_from_mono_type (f->field->type);
7410                 ftype = f->field->type;
7411         }
7412
7413         res.type = ftype;
7414         res.klass = mono_class_from_mono_type (ftype);
7415         res.value = p;
7416
7417         return res;
7418 }
7419
7420 static void
7421 prelink_method (MonoMethod *method)
7422 {
7423         const char *exc_class, *exc_arg;
7424         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7425                 return;
7426         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7427         if (exc_class) {
7428                 mono_raise_exception( 
7429                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7430         }
7431         /* create the wrapper, too? */
7432 }
7433
7434 ICALL_EXPORT void
7435 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7436 {
7437         prelink_method (method->method);
7438 }
7439
7440 ICALL_EXPORT void
7441 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7442 {
7443         MonoClass *klass = mono_class_from_mono_type (type->type);
7444         MonoMethod* m;
7445         gpointer iter = NULL;
7446
7447         mono_class_init_or_throw (klass);
7448
7449         while ((m = mono_class_get_methods (klass, &iter)))
7450                 prelink_method (m);
7451 }
7452
7453 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7454 ICALL_EXPORT void
7455 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7456                                             gint32 const **exponents,
7457                                             gunichar2 const **digitLowerTable,
7458                                             gunichar2 const **digitUpperTable,
7459                                             gint64 const **tenPowersList,
7460                                             gint32 const **decHexDigits)
7461 {
7462         *mantissas = Formatter_MantissaBitsTable;
7463         *exponents = Formatter_TensExponentTable;
7464         *digitLowerTable = Formatter_DigitLowerTable;
7465         *digitUpperTable = Formatter_DigitUpperTable;
7466         *tenPowersList = Formatter_TenPowersList;
7467         *decHexDigits = Formatter_DecHexDigits;
7468 }
7469
7470 /*
7471  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7472  * and avoid useless allocations.
7473  * 
7474  * MAY THROW
7475  */
7476 static MonoArray*
7477 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7478 {
7479         MonoError error;
7480         MonoReflectionType *rt;
7481         MonoArray *res;
7482         int i, count = 0;
7483         for (i = 0; i < type->num_mods; ++i) {
7484                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7485                         count++;
7486         }
7487         if (!count)
7488                 return NULL;
7489         res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7490         count = 0;
7491         for (i = 0; i < type->num_mods; ++i) {
7492                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7493                         MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
7494                         mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */ 
7495
7496                         rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, &error);
7497                         mono_error_raise_exception (&error);
7498
7499                         mono_array_setref (res, count, rt);
7500                         count++;
7501                 }
7502         }
7503         return res;
7504 }
7505
7506 ICALL_EXPORT MonoArray*
7507 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7508 {
7509         MonoType *type = param->ClassImpl->type;
7510         MonoClass *member_class = mono_object_class (param->MemberImpl);
7511         MonoMethod *method = NULL;
7512         MonoImage *image;
7513         int pos;
7514         MonoMethodSignature *sig;
7515
7516         if (mono_class_is_reflection_method_or_constructor (member_class)) {
7517                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7518                 method = rmethod->method;
7519         } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7520                 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7521                 if (!(method = prop->property->get))
7522                         method = prop->property->set;
7523                 g_assert (method);      
7524         } else {
7525                 char *type_name = mono_type_get_full_name (member_class);
7526                 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7527                 MonoException *ex = mono_get_exception_not_supported  (msg);
7528                 g_free (type_name);
7529                 g_free (msg);
7530                 mono_set_pending_exception (ex);
7531                 return NULL;
7532         }
7533
7534         image = method->klass->image;
7535         pos = param->PositionImpl;
7536         sig = mono_method_signature (method);
7537         if (pos == -1)
7538                 type = sig->ret;
7539         else
7540                 type = sig->params [pos];
7541
7542         return type_array_from_modifiers (image, type, optional);
7543 }
7544
7545 static MonoType*
7546 get_property_type (MonoProperty *prop)
7547 {
7548         MonoMethodSignature *sig;
7549         if (prop->get) {
7550                 sig = mono_method_signature (prop->get);
7551                 return sig->ret;
7552         } else if (prop->set) {
7553                 sig = mono_method_signature (prop->set);
7554                 return sig->params [sig->param_count - 1];
7555         }
7556         return NULL;
7557 }
7558
7559 ICALL_EXPORT MonoArray*
7560 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7561 {
7562         MonoType *type = get_property_type (property->property);
7563         MonoImage *image = property->klass->image;
7564
7565         if (!type)
7566                 return NULL;
7567         return type_array_from_modifiers (image, type, optional);
7568 }
7569
7570 /*
7571  *Construct a MonoType suited to be used to decode a constant blob object.
7572  *
7573  * @type is the target type which will be constructed
7574  * @blob_type is the blob type, for example, that comes from the constant table
7575  * @real_type is the expected constructed type.
7576  */
7577 static void
7578 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7579 {
7580         type->type = blob_type;
7581         type->data.klass = NULL;
7582         if (blob_type == MONO_TYPE_CLASS)
7583                 type->data.klass = mono_defaults.object_class;
7584         else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7585                 /* For enums, we need to use the base type */
7586                 type->type = MONO_TYPE_VALUETYPE;
7587                 type->data.klass = mono_class_from_mono_type (real_type);
7588         } else
7589                 type->data.klass = mono_class_from_mono_type (real_type);
7590 }
7591
7592 ICALL_EXPORT MonoObject*
7593 property_info_get_default_value (MonoReflectionProperty *property)
7594 {
7595         MonoType blob_type;
7596         MonoProperty *prop = property->property;
7597         MonoType *type = get_property_type (prop);
7598         MonoDomain *domain = mono_object_domain (property); 
7599         MonoTypeEnum def_type;
7600         const char *def_value;
7601         MonoObject *o;
7602
7603         mono_class_init (prop->parent);
7604
7605         if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7606                 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7607                 return NULL;
7608         }
7609
7610         def_value = mono_class_get_property_default_value (prop, &def_type);
7611
7612         mono_type_from_blob_type (&blob_type, def_type, type);
7613         o = mono_get_object_from_blob (domain, &blob_type, def_value);
7614
7615         return o;
7616 }
7617
7618 ICALL_EXPORT MonoBoolean
7619 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7620 {
7621         MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7622         MonoCustomAttrInfo *cinfo;
7623         gboolean found;
7624
7625         mono_class_init_or_throw (attr_class);
7626
7627         cinfo = mono_reflection_get_custom_attrs_info (obj);
7628         if (!cinfo)
7629                 return FALSE;
7630         found = mono_custom_attrs_has_attr (cinfo, attr_class);
7631         if (!cinfo->cached)
7632                 mono_custom_attrs_free (cinfo);
7633         return found;
7634 }
7635
7636 ICALL_EXPORT MonoArray*
7637 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7638 {
7639         MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7640         MonoArray *res;
7641         MonoError error;
7642
7643         if (attr_class)
7644                 mono_class_init_or_throw (attr_class);
7645
7646         res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7647         if (!mono_error_ok (&error)) {
7648                 mono_error_set_pending_exception (&error);
7649                 return NULL;
7650         }
7651
7652         if (mono_loader_get_last_error ()) {
7653                 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7654                 return NULL;
7655         } else {
7656                 return res;
7657         }
7658 }
7659
7660 ICALL_EXPORT MonoString*
7661 ves_icall_Mono_Runtime_GetDisplayName (void)
7662 {
7663         char *info;
7664         MonoString *display_name;
7665
7666         info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7667         display_name = mono_string_new (mono_domain_get (), info);
7668         g_free (info);
7669         return display_name;
7670 }
7671
7672 ICALL_EXPORT MonoString*
7673 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7674 {
7675         MonoError error;
7676         MonoString *message;
7677         guint32 ret;
7678         gunichar2 buf[256];
7679         
7680         ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7681                              FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7682                              buf, 255, NULL);
7683         if (ret == 0) {
7684                 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7685         } else {
7686                 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7687                 mono_error_raise_exception (&error);
7688         }
7689         
7690         return message;
7691 }
7692
7693 ICALL_EXPORT int
7694 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7695 {
7696         guint32 il_offset;
7697         char *path_str = mono_string_to_utf8 (path);
7698
7699         if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7700                 il_offset = -1;
7701
7702         g_free (path_str);
7703
7704         return il_offset;
7705 }
7706
7707 #ifndef DISABLE_ICALL_TABLES
7708
7709 #define ICALL_TYPE(id,name,first)
7710 #define ICALL(id,name,func) Icall_ ## id,
7711
7712 enum {
7713 #include "metadata/icall-def.h"
7714         Icall_last
7715 };
7716
7717 #undef ICALL_TYPE
7718 #undef ICALL
7719 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7720 #define ICALL(id,name,func)
7721 enum {
7722 #include "metadata/icall-def.h"
7723         Icall_type_num
7724 };
7725
7726 #undef ICALL_TYPE
7727 #undef ICALL
7728 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7729 #define ICALL(id,name,func)
7730 typedef struct {
7731         guint16 first_icall;
7732 } IcallTypeDesc;
7733
7734 static const IcallTypeDesc
7735 icall_type_descs [] = {
7736 #include "metadata/icall-def.h"
7737         {Icall_last}
7738 };
7739
7740 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7741
7742 #undef ICALL_TYPE
7743 #define ICALL_TYPE(id,name,first)
7744 #undef ICALL
7745
7746 #ifdef HAVE_ARRAY_ELEM_INIT
7747 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7748 #define MSGSTRFIELD1(line) str##line
7749
7750 static const struct msgstrtn_t {
7751 #define ICALL(id,name,func)
7752 #undef ICALL_TYPE
7753 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7754 #include "metadata/icall-def.h"
7755 #undef ICALL_TYPE
7756 } icall_type_names_str = {
7757 #define ICALL_TYPE(id,name,first) (name),
7758 #include "metadata/icall-def.h"
7759 #undef ICALL_TYPE
7760 };
7761 static const guint16 icall_type_names_idx [] = {
7762 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7763 #include "metadata/icall-def.h"
7764 #undef ICALL_TYPE
7765 };
7766 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7767
7768 static const struct msgstr_t {
7769 #undef ICALL
7770 #define ICALL_TYPE(id,name,first)
7771 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7772 #include "metadata/icall-def.h"
7773 #undef ICALL
7774 } icall_names_str = {
7775 #define ICALL(id,name,func) (name),
7776 #include "metadata/icall-def.h"
7777 #undef ICALL
7778 };
7779 static const guint16 icall_names_idx [] = {
7780 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7781 #include "metadata/icall-def.h"
7782 #undef ICALL
7783 };
7784 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7785
7786 #else
7787
7788 #undef ICALL_TYPE
7789 #undef ICALL
7790 #define ICALL_TYPE(id,name,first) name,
7791 #define ICALL(id,name,func)
7792 static const char* const
7793 icall_type_names [] = {
7794 #include "metadata/icall-def.h"
7795         NULL
7796 };
7797
7798 #define icall_type_name_get(id) (icall_type_names [(id)])
7799
7800 #undef ICALL_TYPE
7801 #undef ICALL
7802 #define ICALL_TYPE(id,name,first)
7803 #define ICALL(id,name,func) name,
7804 static const char* const
7805 icall_names [] = {
7806 #include "metadata/icall-def.h"
7807         NULL
7808 };
7809 #define icall_name_get(id) icall_names [(id)]
7810
7811 #endif /* !HAVE_ARRAY_ELEM_INIT */
7812
7813 #undef ICALL_TYPE
7814 #undef ICALL
7815 #define ICALL_TYPE(id,name,first)
7816 #define ICALL(id,name,func) func,
7817 static const gconstpointer
7818 icall_functions [] = {
7819 #include "metadata/icall-def.h"
7820         NULL
7821 };
7822
7823 #ifdef ENABLE_ICALL_SYMBOL_MAP
7824 #undef ICALL_TYPE
7825 #undef ICALL
7826 #define ICALL_TYPE(id,name,first)
7827 #define ICALL(id,name,func) #func,
7828 static const gconstpointer
7829 icall_symbols [] = {
7830 #include "metadata/icall-def.h"
7831         NULL
7832 };
7833 #endif
7834
7835 #endif /* DISABLE_ICALL_TABLES */
7836
7837 static mono_mutex_t icall_mutex;
7838 static GHashTable *icall_hash = NULL;
7839 static GHashTable *jit_icall_hash_name = NULL;
7840 static GHashTable *jit_icall_hash_addr = NULL;
7841
7842 void
7843 mono_icall_init (void)
7844 {
7845 #ifndef DISABLE_ICALL_TABLES
7846         int i = 0;
7847
7848         /* check that tables are sorted: disable in release */
7849         if (TRUE) {
7850                 int j;
7851                 const char *prev_class = NULL;
7852                 const char *prev_method;
7853                 
7854                 for (i = 0; i < Icall_type_num; ++i) {
7855                         const IcallTypeDesc *desc;
7856                         int num_icalls;
7857                         prev_method = NULL;
7858                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7859                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7860                         prev_class = icall_type_name_get (i);
7861                         desc = &icall_type_descs [i];
7862                         num_icalls = icall_desc_num_icalls (desc);
7863                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7864                         for (j = 0; j < num_icalls; ++j) {
7865                                 const char *methodn = icall_name_get (desc->first_icall + j);
7866                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
7867                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
7868                                 prev_method = methodn;
7869                         }
7870                 }
7871         }
7872 #endif
7873
7874         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7875         mono_os_mutex_init (&icall_mutex);
7876 }
7877
7878 static void
7879 mono_icall_lock (void)
7880 {
7881         mono_locks_os_acquire (&icall_mutex, IcallLock);
7882 }
7883
7884 static void
7885 mono_icall_unlock (void)
7886 {
7887         mono_locks_os_release (&icall_mutex, IcallLock);
7888 }
7889
7890 void
7891 mono_icall_cleanup (void)
7892 {
7893         g_hash_table_destroy (icall_hash);
7894         g_hash_table_destroy (jit_icall_hash_name);
7895         g_hash_table_destroy (jit_icall_hash_addr);
7896         mono_os_mutex_destroy (&icall_mutex);
7897 }
7898
7899 void
7900 mono_add_internal_call (const char *name, gconstpointer method)
7901 {
7902         mono_icall_lock ();
7903
7904         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7905
7906         mono_icall_unlock ();
7907 }
7908
7909 #ifndef DISABLE_ICALL_TABLES
7910
7911 #ifdef HAVE_ARRAY_ELEM_INIT
7912 static int
7913 compare_method_imap (const void *key, const void *elem)
7914 {
7915         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7916         return strcmp (key, method_name);
7917 }
7918
7919 static gpointer
7920 find_method_icall (const IcallTypeDesc *imap, const char *name)
7921 {
7922         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);
7923         if (!nameslot)
7924                 return NULL;
7925         return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7926 }
7927
7928 static int
7929 compare_class_imap (const void *key, const void *elem)
7930 {
7931         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7932         return strcmp (key, class_name);
7933 }
7934
7935 static const IcallTypeDesc*
7936 find_class_icalls (const char *name)
7937 {
7938         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);
7939         if (!nameslot)
7940                 return NULL;
7941         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7942 }
7943
7944 #else /* HAVE_ARRAY_ELEM_INIT */
7945
7946 static int
7947 compare_method_imap (const void *key, const void *elem)
7948 {
7949         const char** method_name = (const char**)elem;
7950         return strcmp (key, *method_name);
7951 }
7952
7953 static gpointer
7954 find_method_icall (const IcallTypeDesc *imap, const char *name)
7955 {
7956         const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7957         if (!nameslot)
7958                 return NULL;
7959         return (gpointer)icall_functions [(nameslot - icall_names)];
7960 }
7961
7962 static int
7963 compare_class_imap (const void *key, const void *elem)
7964 {
7965         const char** class_name = (const char**)elem;
7966         return strcmp (key, *class_name);
7967 }
7968
7969 static const IcallTypeDesc*
7970 find_class_icalls (const char *name)
7971 {
7972         const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7973         if (!nameslot)
7974                 return NULL;
7975         return &icall_type_descs [nameslot - icall_type_names];
7976 }
7977
7978 #endif /* HAVE_ARRAY_ELEM_INIT */
7979
7980 #endif /* DISABLE_ICALL_TABLES */
7981
7982 /* 
7983  * we should probably export this as an helper (handle nested types).
7984  * Returns the number of chars written in buf.
7985  */
7986 static int
7987 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7988 {
7989         int nspacelen, cnamelen;
7990         nspacelen = strlen (klass->name_space);
7991         cnamelen = strlen (klass->name);
7992         if (nspacelen + cnamelen + 2 > bufsize)
7993                 return 0;
7994         if (nspacelen) {
7995                 memcpy (buf, klass->name_space, nspacelen);
7996                 buf [nspacelen ++] = '.';
7997         }
7998         memcpy (buf + nspacelen, klass->name, cnamelen);
7999         buf [nspacelen + cnamelen] = 0;
8000         return nspacelen + cnamelen;
8001 }
8002
8003 #ifdef DISABLE_ICALL_TABLES
8004 static void
8005 no_icall_table (void)
8006 {
8007         g_assert_not_reached ();
8008 }
8009 #endif
8010
8011 gpointer
8012 mono_lookup_internal_call (MonoMethod *method)
8013 {
8014         char *sigstart;
8015         char *tmpsig;
8016         char mname [2048];
8017         int typelen = 0, mlen, siglen;
8018         gpointer res;
8019 #ifndef DISABLE_ICALL_TABLES
8020         const IcallTypeDesc *imap = NULL;
8021 #endif
8022
8023         g_assert (method != NULL);
8024
8025         if (method->is_inflated)
8026                 method = ((MonoMethodInflated *) method)->declaring;
8027
8028         if (method->klass->nested_in) {
8029                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8030                 if (!pos)
8031                         return NULL;
8032
8033                 mname [pos++] = '/';
8034                 mname [pos] = 0;
8035
8036                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8037                 if (!typelen)
8038                         return NULL;
8039
8040                 typelen += pos;
8041         } else {
8042                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8043                 if (!typelen)
8044                         return NULL;
8045         }
8046
8047 #ifndef DISABLE_ICALL_TABLES
8048         imap = find_class_icalls (mname);
8049 #endif
8050
8051         mname [typelen] = ':';
8052         mname [typelen + 1] = ':';
8053
8054         mlen = strlen (method->name);
8055         memcpy (mname + typelen + 2, method->name, mlen);
8056         sigstart = mname + typelen + 2 + mlen;
8057         *sigstart = 0;
8058
8059         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8060         siglen = strlen (tmpsig);
8061         if (typelen + mlen + siglen + 6 > sizeof (mname))
8062                 return NULL;
8063         sigstart [0] = '(';
8064         memcpy (sigstart + 1, tmpsig, siglen);
8065         sigstart [siglen + 1] = ')';
8066         sigstart [siglen + 2] = 0;
8067         g_free (tmpsig);
8068         
8069         mono_icall_lock ();
8070
8071         res = g_hash_table_lookup (icall_hash, mname);
8072         if (res) {
8073                 mono_icall_unlock ();;
8074                 return res;
8075         }
8076         /* try without signature */
8077         *sigstart = 0;
8078         res = g_hash_table_lookup (icall_hash, mname);
8079         if (res) {
8080                 mono_icall_unlock ();
8081                 return res;
8082         }
8083
8084 #ifdef DISABLE_ICALL_TABLES
8085         mono_icall_unlock ();
8086         /* Fail only when the result is actually used */
8087         /* mono_marshal_get_native_wrapper () depends on this */
8088         if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8089                 return ves_icall_System_String_ctor_RedirectToCreateString;
8090         else
8091                 return no_icall_table;
8092 #else
8093         /* it wasn't found in the static call tables */
8094         if (!imap) {
8095                 mono_icall_unlock ();
8096                 return NULL;
8097         }
8098         res = find_method_icall (imap, sigstart - mlen);
8099         if (res) {
8100                 mono_icall_unlock ();
8101                 return res;
8102         }
8103         /* try _with_ signature */
8104         *sigstart = '(';
8105         res = find_method_icall (imap, sigstart - mlen);
8106         if (res) {
8107                 mono_icall_unlock ();
8108                 return res;
8109         }
8110
8111         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8112         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8113         g_print ("The out of sync library is: %s\n", method->klass->image->name);
8114         g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8115         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");
8116         g_print ("If you see other errors or faults after this message they are probably related\n");
8117         g_print ("and you need to fix your mono install first.\n");
8118
8119         mono_icall_unlock ();
8120
8121         return NULL;
8122 #endif
8123 }
8124
8125 #ifdef ENABLE_ICALL_SYMBOL_MAP
8126 static int
8127 func_cmp (gconstpointer key, gconstpointer p)
8128 {
8129         return (gsize)key - (gsize)*(gsize*)p;
8130 }
8131 #endif
8132
8133 /*
8134  * mono_lookup_icall_symbol:
8135  *
8136  *   Given the icall METHOD, returns its C symbol.
8137  */
8138 const char*
8139 mono_lookup_icall_symbol (MonoMethod *m)
8140 {
8141 #ifdef DISABLE_ICALL_TABLES
8142         g_assert_not_reached ();
8143         return NULL;
8144 #else
8145 #ifdef ENABLE_ICALL_SYMBOL_MAP
8146         gpointer func;
8147         int i;
8148         gpointer slot;
8149         static gconstpointer *functions_sorted;
8150         static const char**symbols_sorted;
8151         static gboolean inited;
8152
8153         if (!inited) {
8154                 gboolean changed;
8155
8156                 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8157                 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8158                 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8159                 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8160                 /* Bubble sort the two arrays */
8161                 changed = TRUE;
8162                 while (changed) {
8163                         changed = FALSE;
8164                         for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8165                                 if (functions_sorted [i] > functions_sorted [i + 1]) {
8166                                         gconstpointer tmp;
8167
8168                                         tmp = functions_sorted [i];
8169                                         functions_sorted [i] = functions_sorted [i + 1];
8170                                         functions_sorted [i + 1] = tmp;
8171                                         tmp = symbols_sorted [i];
8172                                         symbols_sorted [i] = symbols_sorted [i + 1];
8173                                         symbols_sorted [i + 1] = tmp;
8174                                         changed = TRUE;
8175                                 }
8176                         }
8177                 }
8178         }
8179
8180         func = mono_lookup_internal_call (m);
8181         if (!func)
8182                 return NULL;
8183         slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8184         if (!slot)
8185                 return NULL;
8186         g_assert (slot);
8187         return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8188 #else
8189         fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8190         g_assert_not_reached ();
8191         return 0;
8192 #endif
8193 #endif
8194 }
8195
8196 static MonoType*
8197 type_from_typename (char *type_name)
8198 {
8199         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
8200
8201         if (!strcmp (type_name, "int"))
8202                 klass = mono_defaults.int_class;
8203         else if (!strcmp (type_name, "ptr"))
8204                 klass = mono_defaults.int_class;
8205         else if (!strcmp (type_name, "void"))
8206                 klass = mono_defaults.void_class;
8207         else if (!strcmp (type_name, "int32"))
8208                 klass = mono_defaults.int32_class;
8209         else if (!strcmp (type_name, "uint32"))
8210                 klass = mono_defaults.uint32_class;
8211         else if (!strcmp (type_name, "int8"))
8212                 klass = mono_defaults.sbyte_class;
8213         else if (!strcmp (type_name, "uint8"))
8214                 klass = mono_defaults.byte_class;
8215         else if (!strcmp (type_name, "int16"))
8216                 klass = mono_defaults.int16_class;
8217         else if (!strcmp (type_name, "uint16"))
8218                 klass = mono_defaults.uint16_class;
8219         else if (!strcmp (type_name, "long"))
8220                 klass = mono_defaults.int64_class;
8221         else if (!strcmp (type_name, "ulong"))
8222                 klass = mono_defaults.uint64_class;
8223         else if (!strcmp (type_name, "float"))
8224                 klass = mono_defaults.single_class;
8225         else if (!strcmp (type_name, "double"))
8226                 klass = mono_defaults.double_class;
8227         else if (!strcmp (type_name, "object"))
8228                 klass = mono_defaults.object_class;
8229         else if (!strcmp (type_name, "obj"))
8230                 klass = mono_defaults.object_class;
8231         else if (!strcmp (type_name, "string"))
8232                 klass = mono_defaults.string_class;
8233         else if (!strcmp (type_name, "bool"))
8234                 klass = mono_defaults.boolean_class;
8235         else if (!strcmp (type_name, "boolean"))
8236                 klass = mono_defaults.boolean_class;
8237         else {
8238                 g_error ("%s", type_name);
8239                 g_assert_not_reached ();
8240         }
8241         return &klass->byval_arg;
8242 }
8243
8244 /**
8245  * LOCKING: Take the corlib image lock.
8246  */
8247 MonoMethodSignature*
8248 mono_create_icall_signature (const char *sigstr)
8249 {
8250         gchar **parts;
8251         int i, len;
8252         gchar **tmp;
8253         MonoMethodSignature *res, *res2;
8254         MonoImage *corlib = mono_defaults.corlib;
8255
8256         mono_image_lock (corlib);
8257         res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8258         mono_image_unlock (corlib);
8259
8260         if (res)
8261                 return res;
8262
8263         parts = g_strsplit (sigstr, " ", 256);
8264
8265         tmp = parts;
8266         len = 0;
8267         while (*tmp) {
8268                 len ++;
8269                 tmp ++;
8270         }
8271
8272         res = mono_metadata_signature_alloc (corlib, len - 1);
8273         res->pinvoke = 1;
8274
8275 #ifdef HOST_WIN32
8276         /* 
8277          * Under windows, the default pinvoke calling convention is STDCALL but
8278          * we need CDECL.
8279          */
8280         res->call_convention = MONO_CALL_C;
8281 #endif
8282
8283         res->ret = type_from_typename (parts [0]);
8284         for (i = 1; i < len; ++i) {
8285                 res->params [i - 1] = type_from_typename (parts [i]);
8286         }
8287
8288         g_strfreev (parts);
8289
8290         mono_image_lock (corlib);
8291         res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8292         if (res2)
8293                 res = res2; /*Value is allocated in the image pool*/
8294         else
8295                 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8296         mono_image_unlock (corlib);
8297
8298         return res;
8299 }
8300
8301 MonoJitICallInfo *
8302 mono_find_jit_icall_by_name (const char *name)
8303 {
8304         MonoJitICallInfo *info;
8305         g_assert (jit_icall_hash_name);
8306
8307         mono_icall_lock ();
8308         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8309         mono_icall_unlock ();
8310         return info;
8311 }
8312
8313 MonoJitICallInfo *
8314 mono_find_jit_icall_by_addr (gconstpointer addr)
8315 {
8316         MonoJitICallInfo *info;
8317         g_assert (jit_icall_hash_addr);
8318
8319         mono_icall_lock ();
8320         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8321         mono_icall_unlock ();
8322
8323         return info;
8324 }
8325
8326 /*
8327  * mono_get_jit_icall_info:
8328  *
8329  *   Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8330  * caller should access it while holding the icall lock.
8331  */
8332 GHashTable*
8333 mono_get_jit_icall_info (void)
8334 {
8335         return jit_icall_hash_name;
8336 }
8337
8338 /*
8339  * mono_lookup_jit_icall_symbol:
8340  *
8341  *   Given the jit icall NAME, returns its C symbol if possible, or NULL.
8342  */
8343 const char*
8344 mono_lookup_jit_icall_symbol (const char *name)
8345 {
8346         MonoJitICallInfo *info;
8347         const char *res = NULL;
8348
8349         mono_icall_lock ();
8350         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8351         if (info)
8352                 res = info->c_symbol;
8353         mono_icall_unlock ();
8354         return res;
8355 }
8356
8357 void
8358 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8359 {
8360         mono_icall_lock ();
8361         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8362         mono_icall_unlock ();
8363 }
8364
8365 /*
8366  * 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
8367  * icalls without wrappers in some cases.
8368  */
8369 MonoJitICallInfo *
8370 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8371 {
8372         MonoJitICallInfo *info;
8373         
8374         g_assert (func);
8375         g_assert (name);
8376
8377         mono_icall_lock ();
8378
8379         if (!jit_icall_hash_name) {
8380                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8381                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8382         }
8383
8384         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8385                 g_warning ("jit icall already defined \"%s\"\n", name);
8386                 g_assert_not_reached ();
8387         }
8388
8389         info = g_new0 (MonoJitICallInfo, 1);
8390         
8391         info->name = name;
8392         info->func = func;
8393         info->sig = sig;
8394         info->c_symbol = c_symbol;
8395         info->no_raise = no_raise;
8396
8397         if (is_save) {
8398                 info->wrapper = func;
8399         } else {
8400                 info->wrapper = NULL;
8401         }
8402
8403         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8404         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8405
8406         mono_icall_unlock ();
8407         return info;
8408 }
8409
8410 MonoJitICallInfo *
8411 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8412 {
8413         return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);
8414 }
8415