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