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