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