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