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