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