2009-04-13 Zoltan Varga <vargaz@gmail.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                 return res;
3753         }
3754
3755         mono_class_setup_vtable (klass);
3756
3757         if (is_generic_parameter (type->type))
3758                 nslots = klass->parent->vtable_size;
3759         else
3760                 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : klass->vtable_size;
3761         if (nslots >= sizeof (method_slots_default) * 8) {
3762                 method_slots = g_new0 (guint32, nslots / 32 + 1);
3763         } else {
3764                 method_slots = method_slots_default;
3765                 memset (method_slots, 0, sizeof (method_slots_default));
3766         }
3767 handle_parent:
3768         mono_class_setup_vtable (klass);
3769         if (klass->exception_type != MONO_EXCEPTION_NONE)
3770                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3771
3772         iter = NULL;
3773         while ((method = mono_class_get_methods (klass, &iter))) {
3774                 match = 0;
3775                 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3776                         continue;
3777                 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3778                         if (bflags & BFLAGS_Public)
3779                                 match++;
3780                 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3781                                 match++;
3782                 }
3783                 if (!match)
3784                         continue;
3785                 match = 0;
3786                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3787                         if (bflags & BFLAGS_Static)
3788                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3789                                         match++;
3790                 } else {
3791                         if (bflags & BFLAGS_Instance)
3792                                 match++;
3793                 }
3794
3795                 if (!match)
3796                         continue;
3797
3798                 if (name != NULL) {
3799                         if (compare_func (mname, method->name))
3800                                 continue;
3801                 }
3802                 
3803                 match = 0;
3804                 if (method->slot != -1) {
3805                         g_assert (method->slot < nslots);
3806                         if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3807                                 continue;
3808                         method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3809                 }
3810                 
3811                 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3812                 
3813                 mono_ptr_array_append (tmp_array, member);
3814         }
3815         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3816                 goto handle_parent;
3817
3818         g_free (mname);
3819         if (method_slots != method_slots_default)
3820                 g_free (method_slots);
3821
3822         res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3823
3824         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3825                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3826
3827         mono_ptr_array_destroy (tmp_array);
3828         return res;
3829 }
3830
3831 static MonoArray*
3832 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3833 {
3834         MonoDomain *domain; 
3835         static MonoClass *System_Reflection_ConstructorInfo;
3836         MonoClass *startklass, *klass, *refklass;
3837         MonoArray *res;
3838         MonoMethod *method;
3839         MonoObject *member;
3840         int i, match;
3841         gpointer iter = NULL;
3842         MonoPtrArray tmp_array;
3843         
3844         MONO_ARCH_SAVE_REGS;
3845
3846         mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3847
3848         domain = ((MonoObject *)type)->vtable->domain;
3849         if (type->type->byref)
3850                 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3851         klass = startklass = mono_class_from_mono_type (type->type);
3852         refklass = mono_class_from_mono_type (reftype->type);
3853
3854         if (klass->exception_type != MONO_EXCEPTION_NONE)
3855                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3856
3857         if (!System_Reflection_ConstructorInfo)
3858                 System_Reflection_ConstructorInfo = mono_class_from_name (
3859                         mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3860
3861         iter = NULL;
3862         while ((method = mono_class_get_methods (klass, &iter))) {
3863                 match = 0;
3864                 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3865                         continue;
3866                 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3867                         if (bflags & BFLAGS_Public)
3868                                 match++;
3869                 } else {
3870                         if (bflags & BFLAGS_NonPublic)
3871                                 match++;
3872                 }
3873                 if (!match)
3874                         continue;
3875                 match = 0;
3876                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3877                         if (bflags & BFLAGS_Static)
3878                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3879                                         match++;
3880                 } else {
3881                         if (bflags & BFLAGS_Instance)
3882                                 match++;
3883                 }
3884
3885                 if (!match)
3886                         continue;
3887                 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3888
3889                 mono_ptr_array_append (tmp_array, member);
3890         }
3891
3892         res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3893
3894         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3895                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3896
3897         mono_ptr_array_destroy (tmp_array);
3898
3899         return res;
3900 }
3901
3902 static guint
3903 property_hash (gconstpointer data)
3904 {
3905         MonoProperty *prop = (MonoProperty*)data;
3906
3907         return g_str_hash (prop->name);
3908 }
3909
3910 static gboolean
3911 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3912 {
3913         // Properties are hide-by-name-and-signature
3914         if (!g_str_equal (prop1->name, prop2->name))
3915                 return FALSE;
3916
3917         if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3918                 return FALSE;
3919         if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3920                 return FALSE;
3921         return TRUE;
3922 }
3923
3924 static gboolean
3925 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3926 {
3927         if (!accessor)
3928                 return FALSE;
3929
3930         return method_nonpublic (accessor, start_klass);
3931 }
3932
3933 static MonoArray*
3934 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3935 {
3936         MonoDomain *domain; 
3937         static MonoClass *System_Reflection_PropertyInfo;
3938         MonoClass *startklass, *klass;
3939         MonoArray *res;
3940         MonoMethod *method;
3941         MonoProperty *prop;
3942         int i, match;
3943         guint32 flags;
3944         gchar *propname = NULL;
3945         int (*compare_func) (const char *s1, const char *s2) = NULL;
3946         gpointer iter;
3947         GHashTable *properties;
3948         MonoPtrArray tmp_array;
3949
3950         MONO_ARCH_SAVE_REGS;
3951
3952         mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3953
3954         if (!System_Reflection_PropertyInfo)
3955                 System_Reflection_PropertyInfo = mono_class_from_name (
3956                         mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3957
3958         domain = ((MonoObject *)type)->vtable->domain;
3959         if (type->type->byref)
3960                 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3961         klass = startklass = mono_class_from_mono_type (type->type);
3962         if (name != NULL) {
3963                 propname = mono_string_to_utf8 (name);
3964                 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3965         }
3966
3967         mono_class_setup_vtable (klass);
3968
3969         properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3970 handle_parent:
3971         mono_class_setup_vtable (klass);
3972         if (klass->exception_type != MONO_EXCEPTION_NONE) {
3973                 g_hash_table_destroy (properties);
3974                 if (name != NULL)
3975                         g_free (propname);
3976                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3977         }
3978
3979         iter = NULL;
3980         while ((prop = mono_class_get_properties (klass, &iter))) {
3981                 match = 0;
3982                 method = prop->get;
3983                 if (!method)
3984                         method = prop->set;
3985                 if (method)
3986                         flags = method->flags;
3987                 else
3988                         flags = 0;
3989                 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3990                         (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3991                         if (bflags & BFLAGS_Public)
3992                                 match++;
3993                 } else if (bflags & BFLAGS_NonPublic) {
3994                         if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3995                                 property_accessor_nonpublic(prop->set, startklass == klass)) {
3996                                 match++;
3997                         }
3998                 }
3999                 if (!match)
4000                         continue;
4001                 match = 0;
4002                 if (flags & METHOD_ATTRIBUTE_STATIC) {
4003                         if (bflags & BFLAGS_Static)
4004                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4005                                         match++;
4006                 } else {
4007                         if (bflags & BFLAGS_Instance)
4008                                 match++;
4009                 }
4010
4011                 if (!match)
4012                         continue;
4013                 match = 0;
4014
4015                 if (name != NULL) {
4016                         if (compare_func (propname, prop->name))
4017                                 continue;
4018                 }
4019                 
4020                 if (g_hash_table_lookup (properties, prop))
4021                         continue;
4022
4023                 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
4024                 
4025                 g_hash_table_insert (properties, prop, prop);
4026         }
4027         if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4028                 goto handle_parent;
4029
4030         g_hash_table_destroy (properties);
4031         g_free (propname);
4032
4033         res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
4034         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4035                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4036
4037         mono_ptr_array_destroy (tmp_array);
4038
4039         return res;
4040 }
4041
4042 static MonoReflectionEvent *
4043 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
4044 {
4045         MonoDomain *domain;
4046         MonoClass *klass, *startklass;
4047         gpointer iter;
4048         MonoEvent *event;
4049         MonoMethod *method;
4050         gchar *event_name;
4051
4052         MONO_ARCH_SAVE_REGS;
4053
4054         event_name = mono_string_to_utf8 (name);
4055         if (type->type->byref)
4056                 return NULL;
4057         klass = startklass = mono_class_from_mono_type (type->type);
4058         domain = mono_object_domain (type);
4059
4060 handle_parent:  
4061         if (klass->exception_type != MONO_EXCEPTION_NONE)
4062                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4063
4064         iter = NULL;
4065         while ((event = mono_class_get_events (klass, &iter))) {
4066                 if (strcmp (event->name, event_name))
4067                         continue;
4068
4069                 method = event->add;
4070                 if (!method)
4071                         method = event->remove;
4072                 if (!method)
4073                         method = event->raise;
4074                 if (method) {
4075                         if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4076                                 if (!(bflags & BFLAGS_Public))
4077                                         continue;
4078                         } else {
4079                                 if (!(bflags & BFLAGS_NonPublic))
4080                                         continue;
4081                                 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
4082                                         continue;
4083                         }
4084                 }
4085                 else
4086                         if (!(bflags & BFLAGS_NonPublic))
4087                                 continue;
4088
4089                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4090                         if (!(bflags & BFLAGS_Static))
4091                                 continue;
4092                         if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
4093                                 continue;
4094                 } else {
4095                         if (!(bflags & BFLAGS_Instance))
4096                                 continue;
4097                 }
4098
4099                 g_free (event_name);
4100                 return mono_event_get_object (domain, startklass, event);
4101         }
4102
4103         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4104                 goto handle_parent;
4105
4106         g_free (event_name);
4107         return NULL;
4108 }
4109
4110 static MonoArray*
4111 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4112 {
4113         MonoDomain *domain; 
4114         static MonoClass *System_Reflection_EventInfo;
4115         MonoClass *startklass, *klass;
4116         MonoArray *res;
4117         MonoMethod *method;
4118         MonoEvent *event;
4119         int i, match;
4120         gpointer iter;
4121         
4122         MonoPtrArray tmp_array;
4123
4124         MONO_ARCH_SAVE_REGS;
4125
4126         mono_ptr_array_init (tmp_array, 4);
4127
4128         if (!System_Reflection_EventInfo)
4129                 System_Reflection_EventInfo = mono_class_from_name (
4130                         mono_defaults.corlib, "System.Reflection", "EventInfo");
4131
4132         domain = mono_object_domain (type);
4133         if (type->type->byref)
4134                 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
4135         klass = startklass = mono_class_from_mono_type (type->type);
4136
4137 handle_parent:  
4138         if (klass->exception_type != MONO_EXCEPTION_NONE)
4139                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4140
4141         iter = NULL;
4142         while ((event = mono_class_get_events (klass, &iter))) {
4143                 match = 0;
4144                 method = event->add;
4145                 if (!method)
4146                         method = event->remove;
4147                 if (!method)
4148                         method = event->raise;
4149                 if (method) {
4150                         if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4151                                 if (bflags & BFLAGS_Public)
4152                                         match++;
4153                         } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4154                                 if (bflags & BFLAGS_NonPublic)
4155                                         match++;
4156                         }
4157                 }
4158                 else
4159                         if (bflags & BFLAGS_NonPublic)
4160                                 match ++;
4161                 if (!match)
4162                         continue;
4163                 match = 0;
4164                 if (method) {
4165                         if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4166                                 if (bflags & BFLAGS_Static)
4167                                         if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4168                                                 match++;
4169                         } else {
4170                                 if (bflags & BFLAGS_Instance)
4171                                         match++;
4172                         }
4173                 }
4174                 else
4175                         if (bflags & BFLAGS_Instance)
4176                                 match ++;
4177                 if (!match)
4178                         continue;
4179                 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
4180         }
4181         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4182                 goto handle_parent;
4183
4184         res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4185
4186         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4187                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4188
4189         mono_ptr_array_destroy (tmp_array);
4190
4191         return res;
4192 }
4193
4194 static MonoReflectionType *
4195 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4196 {
4197         MonoDomain *domain; 
4198         MonoClass *klass;
4199         MonoClass *nested;
4200         char *str;
4201         gpointer iter;
4202         
4203         MONO_ARCH_SAVE_REGS;
4204
4205         domain = ((MonoObject *)type)->vtable->domain;
4206         if (type->type->byref)
4207                 return NULL;
4208         klass = mono_class_from_mono_type (type->type);
4209         str = mono_string_to_utf8 (name);
4210
4211  handle_parent:
4212         if (klass->exception_type != MONO_EXCEPTION_NONE)
4213                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4214
4215         /*
4216          * If a nested type is generic, return its generic type definition.
4217          * Note that this means that the return value is essentially a
4218          * nested type of the generic type definition of @klass.
4219          *
4220          * A note in MSDN claims that a generic type definition can have
4221          * nested types that aren't generic.  In any case, the container of that
4222          * nested type would be the generic type definition.
4223          */
4224         if (klass->generic_class)
4225                 klass = klass->generic_class->container_class;
4226
4227         iter = NULL;
4228         while ((nested = mono_class_get_nested_types (klass, &iter))) {
4229                 int match = 0;
4230                 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4231                         if (bflags & BFLAGS_Public)
4232                                 match++;
4233                 } else {
4234                         if (bflags & BFLAGS_NonPublic)
4235                                 match++;
4236                 }
4237                 if (!match)
4238                         continue;
4239                 if (strcmp (nested->name, str) == 0){
4240                         g_free (str);
4241                         return mono_type_get_object (domain, &nested->byval_arg);
4242                 }
4243         }
4244         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4245                 goto handle_parent;
4246         g_free (str);
4247         return NULL;
4248 }
4249
4250 static MonoArray*
4251 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4252 {
4253         MonoDomain *domain; 
4254         MonoClass *klass;
4255         MonoArray *res;
4256         MonoObject *member;
4257         int i, match;
4258         MonoClass *nested;
4259         gpointer iter;
4260         MonoPtrArray tmp_array;
4261
4262         MONO_ARCH_SAVE_REGS;
4263
4264         domain = ((MonoObject *)type)->vtable->domain;
4265         if (type->type->byref)
4266                 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4267         klass = mono_class_from_mono_type (type->type);
4268         if (klass->exception_type != MONO_EXCEPTION_NONE)
4269                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4270
4271         /*
4272          * If a nested type is generic, return its generic type definition.
4273          * Note that this means that the return value is essentially the set
4274          * of nested types of the generic type definition of @klass.
4275          *
4276          * A note in MSDN claims that a generic type definition can have
4277          * nested types that aren't generic.  In any case, the container of that
4278          * nested type would be the generic type definition.
4279          */
4280         if (klass->generic_class)
4281                 klass = klass->generic_class->container_class;
4282
4283         mono_ptr_array_init (tmp_array, 1);
4284         iter = NULL;
4285         while ((nested = mono_class_get_nested_types (klass, &iter))) {
4286                 match = 0;
4287                 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4288                         if (bflags & BFLAGS_Public)
4289                                 match++;
4290                 } else {
4291                         if (bflags & BFLAGS_NonPublic)
4292                                 match++;
4293                 }
4294                 if (!match)
4295                         continue;
4296                 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4297                 mono_ptr_array_append (tmp_array, member);
4298         }
4299
4300         res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4301
4302         for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4303                 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4304
4305         mono_ptr_array_destroy (tmp_array);
4306
4307         return res;
4308 }
4309
4310 static MonoReflectionType*
4311 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4312 {
4313         gchar *str;
4314         MonoType *type = NULL;
4315         MonoTypeNameParse info;
4316         gboolean type_resolve;
4317
4318         MONO_ARCH_SAVE_REGS;
4319
4320         /* On MS.NET, this does not fire a TypeResolve event */
4321         type_resolve = TRUE;
4322         str = mono_string_to_utf8 (name);
4323         /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4324         if (!mono_reflection_parse_type (str, &info)) {
4325                 g_free (str);
4326                 mono_reflection_free_type_info (&info);
4327                 if (throwOnError) /* uhm: this is a parse error, though... */
4328                         mono_raise_exception (mono_get_exception_type_load (name, NULL));
4329                 /*g_print ("failed parse\n");*/
4330                 return NULL;
4331         }
4332
4333         if (info.assembly.name) {
4334                 g_free (str);
4335                 mono_reflection_free_type_info (&info);
4336                 if (throwOnError) {
4337                         /* 1.0 and 2.0 throw different exceptions */
4338                         if (mono_defaults.generic_ilist_class)
4339                                 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4340                         else
4341                                 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4342                 }
4343                 return NULL;
4344         }
4345
4346         if (module != NULL) {
4347                 if (module->image)
4348                         type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4349                 else
4350                         type = NULL;
4351         }
4352         else
4353                 if (assembly->assembly->dynamic) {
4354                         /* Enumerate all modules */
4355                         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4356                         int i;
4357
4358                         type = NULL;
4359                         if (abuilder->modules) {
4360                                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4361                                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4362                                         type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4363                                         if (type)
4364                                                 break;
4365                                 }
4366                         }
4367
4368                         if (!type && abuilder->loaded_modules) {
4369                                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4370                                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4371                                         type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4372                                         if (type)
4373                                                 break;
4374                                 }
4375                         }
4376                 }
4377                 else
4378                         type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4379         g_free (str);
4380         mono_reflection_free_type_info (&info);
4381         if (!type) {
4382                 MonoException *e = NULL;
4383                 
4384                 if (throwOnError)
4385                         e = mono_get_exception_type_load (name, NULL);
4386
4387                 mono_loader_clear_error ();
4388
4389                 if (e != NULL)
4390                         mono_raise_exception (e);
4391
4392                 return NULL;
4393         }
4394
4395         if (type->type == MONO_TYPE_CLASS) {
4396                 MonoClass *klass = mono_type_get_class (type);
4397
4398                 if (mono_is_security_manager_active () && !klass->exception_type)
4399                         /* Some security problems are detected during generic vtable construction */
4400                         mono_class_setup_vtable (klass);
4401                 /* need to report exceptions ? */
4402                 if (throwOnError && klass->exception_type) {
4403                         /* report SecurityException (or others) that occured when loading the assembly */
4404                         MonoException *exc = mono_class_get_exception_for_failure (klass);
4405                         mono_loader_clear_error ();
4406                         mono_raise_exception (exc);
4407                 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4408                         return NULL;
4409                 }
4410         }
4411
4412         /* g_print ("got it\n"); */
4413         return mono_type_get_object (mono_object_domain (assembly), type);
4414 }
4415
4416 static gboolean
4417 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4418 {
4419         gchar *content;
4420         gchar *shadow_ini_file;
4421         gsize len;
4422
4423         /* Check for shadow-copied assembly */
4424         if (mono_is_shadow_copy_enabled (domain, dirname)) {
4425                 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4426                 content = NULL;
4427                 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4428                         !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4429                         if (content) {
4430                                 g_free (content);
4431                                 content = NULL;
4432                         }
4433                 }
4434                 g_free (shadow_ini_file);
4435                 if (content != NULL) {
4436                         if (*filename)
4437                                 g_free (*filename);
4438                         *filename = content;
4439                         return TRUE;
4440                 }
4441         }
4442         return FALSE;
4443 }
4444
4445 static MonoString *
4446 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4447 {
4448         MonoDomain *domain = mono_object_domain (assembly); 
4449         MonoAssembly *mass = assembly->assembly;
4450         MonoString *res = NULL;
4451         gchar *uri;
4452         gchar *absolute;
4453         gchar *dirname;
4454         
4455         MONO_ARCH_SAVE_REGS;
4456
4457         if (g_path_is_absolute (mass->image->name)) {
4458                 absolute = g_strdup (mass->image->name);
4459                 dirname = g_path_get_dirname (absolute);
4460         } else {
4461                 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4462                 dirname = g_strdup (mass->basedir);
4463         }
4464
4465         replace_shadow_path (domain, dirname, &absolute);
4466         g_free (dirname);
4467 #if PLATFORM_WIN32
4468         {
4469                 gint i;
4470                 for (i = strlen (absolute) - 1; i >= 0; i--)
4471                         if (absolute [i] == '\\')
4472                                 absolute [i] = '/';
4473         }
4474 #endif
4475         if (escaped) {
4476                 uri = g_filename_to_uri (absolute, NULL, NULL);
4477         } else {
4478                 const char *prepend = "file://";
4479 #if PLATFORM_WIN32
4480                 if (*absolute == '/' && *(absolute + 1) == '/') {
4481                         prepend = "file:";
4482                 } else {
4483                         prepend = "file:///";
4484                 }
4485 #endif
4486                 uri = g_strconcat (prepend, absolute, NULL);
4487         }
4488
4489         if (uri) {
4490                 res = mono_string_new (domain, uri);
4491                 g_free (uri);
4492         }
4493         g_free (absolute);
4494         return res;
4495 }
4496
4497 static MonoBoolean
4498 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4499 {
4500         MonoAssembly *mass = assembly->assembly;
4501
4502         MONO_ARCH_SAVE_REGS;
4503
4504         return mass->in_gac;
4505 }
4506
4507 static MonoReflectionAssembly*
4508 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4509 {
4510         gchar *name;
4511         MonoAssembly *res;
4512         MonoImageOpenStatus status;
4513         
4514         MONO_ARCH_SAVE_REGS;
4515
4516         name = mono_string_to_utf8 (mname);
4517         res = mono_assembly_load_with_partial_name (name, &status);
4518
4519         g_free (name);
4520
4521         if (res == NULL)
4522                 return NULL;
4523         return mono_assembly_get_object (mono_domain_get (), res);
4524 }
4525
4526 static MonoString *
4527 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4528 {
4529         MonoDomain *domain = mono_object_domain (assembly); 
4530         MonoString *res;
4531
4532         MONO_ARCH_SAVE_REGS;
4533
4534         res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4535
4536         return res;
4537 }
4538
4539 static MonoBoolean
4540 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4541 {
4542         MONO_ARCH_SAVE_REGS;
4543
4544         return assembly->assembly->ref_only;
4545 }
4546
4547 static MonoString *
4548 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4549 {
4550         MonoDomain *domain = mono_object_domain (assembly); 
4551
4552         MONO_ARCH_SAVE_REGS;
4553
4554         return mono_string_new (domain, assembly->assembly->image->version);
4555 }
4556
4557 static MonoReflectionMethod*
4558 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly) 
4559 {
4560         guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4561
4562         MONO_ARCH_SAVE_REGS;
4563
4564         if (!token)
4565                 return NULL;
4566         return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4567 }
4568
4569 static MonoReflectionModule*
4570 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly) 
4571 {
4572         return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4573 }
4574
4575 static MonoArray*
4576 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly) 
4577 {
4578         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4579         MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4580         int i;
4581         const char *val;
4582
4583         MONO_ARCH_SAVE_REGS;
4584
4585         for (i = 0; i < table->rows; ++i) {
4586                 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4587                 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4588         }
4589         return result;
4590 }
4591
4592 static MonoObject*
4593 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4594 {
4595         static MonoClass *System_Version = NULL;
4596         static MonoMethod *create_version = NULL;
4597         MonoObject *result;
4598         gpointer args [4];
4599         
4600         if (!System_Version) {
4601                 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4602                 g_assert (System_Version);
4603         }
4604
4605         if (!create_version) {
4606                 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4607                 create_version = mono_method_desc_search_in_class (desc, System_Version);
4608                 g_assert (create_version);
4609                 mono_method_desc_free (desc);
4610         }
4611
4612         args [0] = &major;
4613         args [1] = &minor;
4614         args [2] = &build;
4615         args [3] = &revision;
4616         result = mono_object_new (domain, System_Version);
4617         mono_runtime_invoke (create_version, result, args, NULL);
4618
4619         return result;
4620 }
4621
4622 static MonoArray*
4623 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly) 
4624 {
4625         static MonoClass *System_Reflection_AssemblyName;
4626         MonoArray *result;
4627         MonoDomain *domain = mono_object_domain (assembly);
4628         int i, count = 0;
4629         static MonoMethod *create_culture = NULL;
4630         MonoImage *image = assembly->assembly->image;
4631         MonoTableInfo *t;
4632
4633         MONO_ARCH_SAVE_REGS;
4634
4635         if (!System_Reflection_AssemblyName)
4636                 System_Reflection_AssemblyName = mono_class_from_name (
4637                         mono_defaults.corlib, "System.Reflection", "AssemblyName");
4638
4639         t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4640         count = t->rows;
4641
4642         result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4643
4644         if (count > 0 && !create_culture) {
4645                 MonoMethodDesc *desc = mono_method_desc_new (
4646                         "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4647                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4648                 g_assert (create_culture);
4649                 mono_method_desc_free (desc);
4650         }
4651
4652         for (i = 0; i < count; i++) {
4653                 MonoReflectionAssemblyName *aname;
4654                 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4655
4656                 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4657
4658                 aname = (MonoReflectionAssemblyName *) mono_object_new (
4659                         domain, System_Reflection_AssemblyName);
4660
4661                 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4662
4663                 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4664                 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4665                 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4666                 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4667                 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4668                 aname->versioncompat = 1; /* SameMachine (default) */
4669                 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4670                 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4671
4672                 if (create_culture) {
4673                         gpointer args [2];
4674                         MonoBoolean assembly_ref = 1;
4675                         args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4676                         args [1] = &assembly_ref;
4677                         MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4678                 }
4679                 
4680                 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4681                         const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4682                         guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4683
4684                         if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4685                                 /* public key token isn't copied - the class library will 
4686                                 automatically generate it from the public key if required */
4687                                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4688                                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4689                         } else {
4690                                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4691                                 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4692                         }
4693                 } else {
4694                         MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4695                 }
4696                 
4697                 /* note: this function doesn't return the codebase on purpose (i.e. it can
4698                          be used under partial trust as path information isn't present). */
4699
4700                 mono_array_setref (result, i, aname);
4701         }
4702         return result;
4703 }
4704
4705 typedef struct {
4706         MonoArray *res;
4707         int idx;
4708 } NameSpaceInfo;
4709
4710 static void
4711 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4712 {
4713         MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4714
4715         mono_array_setref (info->res, info->idx, name);
4716         info->idx++;
4717 }
4718
4719 static MonoArray*
4720 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly) 
4721 {
4722         MonoImage *img = assembly->assembly->image;
4723         MonoArray *res;
4724         NameSpaceInfo info;
4725
4726         MONO_ARCH_SAVE_REGS;
4727
4728         if (!img->name_cache)
4729                 mono_image_init_name_cache (img);
4730
4731         res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, g_hash_table_size (img->name_cache));
4732         info.res = res;
4733         info.idx = 0;
4734         g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4735
4736         return res;
4737 }
4738
4739 /* move this in some file in mono/util/ */
4740 static char *
4741 g_concat_dir_and_file (const char *dir, const char *file)
4742 {
4743         g_return_val_if_fail (dir != NULL, NULL);
4744         g_return_val_if_fail (file != NULL, NULL);
4745
4746         /*
4747          * If the directory name doesn't have a / on the end, we need
4748          * to add one so we get a proper path to the file
4749          */
4750         if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4751                 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4752         else
4753                 return g_strconcat (dir, file, NULL);
4754 }
4755
4756 static void *
4757 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module) 
4758 {
4759         char *n = mono_string_to_utf8 (name);
4760         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4761         guint32 i;
4762         guint32 cols [MONO_MANIFEST_SIZE];
4763         guint32 impl, file_idx;
4764         const char *val;
4765         MonoImage *module;
4766
4767         MONO_ARCH_SAVE_REGS;
4768
4769         for (i = 0; i < table->rows; ++i) {
4770                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4771                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4772                 if (strcmp (val, n) == 0)
4773                         break;
4774         }
4775         g_free (n);
4776         if (i == table->rows)
4777                 return NULL;
4778         /* FIXME */
4779         impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4780         if (impl) {
4781                 /*
4782                  * this code should only be called after obtaining the 
4783                  * ResourceInfo and handling the other cases.
4784                  */
4785                 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4786                 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4787
4788                 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4789                 if (!module)
4790                         return NULL;
4791         }
4792         else
4793                 module = assembly->assembly->image;
4794
4795         *ref_module = mono_module_get_object (mono_domain_get (), module);
4796
4797         return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4798 }
4799
4800 static gboolean
4801 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4802 {
4803         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4804         int i;
4805         guint32 cols [MONO_MANIFEST_SIZE];
4806         guint32 file_cols [MONO_FILE_SIZE];
4807         const char *val;
4808         char *n;
4809
4810         MONO_ARCH_SAVE_REGS;
4811
4812         n = mono_string_to_utf8 (name);
4813         for (i = 0; i < table->rows; ++i) {
4814                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4815                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4816                 if (strcmp (val, n) == 0)
4817                         break;
4818         }
4819         g_free (n);
4820         if (i == table->rows)
4821                 return FALSE;
4822
4823         if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4824                 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4825         }
4826         else {
4827                 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4828                 case MONO_IMPLEMENTATION_FILE:
4829                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4830                         table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4831                         mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4832                         val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4833                         MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4834                         if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4835                                 info->location = 0;
4836                         else
4837                                 info->location = RESOURCE_LOCATION_EMBEDDED;
4838                         break;
4839
4840                 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4841                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4842                         mono_assembly_load_reference (assembly->assembly->image, i - 1);
4843                         if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4844                                 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4845                                 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4846                                 g_free (msg);
4847                                 mono_raise_exception (ex);
4848                         }
4849                         MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4850
4851                         /* Obtain info recursively */
4852                         ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4853                         info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4854                         break;
4855
4856                 case MONO_IMPLEMENTATION_EXP_TYPE:
4857                         g_assert_not_reached ();
4858                         break;
4859                 }
4860         }
4861
4862         return TRUE;
4863 }
4864
4865 static MonoObject*
4866 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules) 
4867 {
4868         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4869         MonoArray *result = NULL;
4870         int i, count;
4871         const char *val;
4872         char *n;
4873
4874         MONO_ARCH_SAVE_REGS;
4875
4876         /* check hash if needed */
4877         if (name) {
4878                 n = mono_string_to_utf8 (name);
4879                 for (i = 0; i < table->rows; ++i) {
4880                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4881                         if (strcmp (val, n) == 0) {
4882                                 MonoString *fn;
4883                                 g_free (n);
4884                                 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4885                                 fn = mono_string_new (mono_object_domain (assembly), n);
4886                                 g_free (n);
4887                                 return (MonoObject*)fn;
4888                         }
4889                 }
4890                 g_free (n);
4891                 return NULL;
4892         }
4893
4894         count = 0;
4895         for (i = 0; i < table->rows; ++i) {
4896                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4897                         count ++;
4898         }
4899
4900         result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4901
4902         count = 0;
4903         for (i = 0; i < table->rows; ++i) {
4904                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4905                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4906                         n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4907                         mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4908                         g_free (n);
4909                         count ++;
4910                 }
4911         }
4912         return (MonoObject*)result;
4913 }
4914
4915 static MonoArray*
4916 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4917 {
4918         MonoDomain *domain = mono_domain_get();
4919         MonoArray *res;
4920         MonoClass *klass;
4921         int i, j, file_count = 0;
4922         MonoImage **modules;
4923         guint32 module_count, real_module_count;
4924         MonoTableInfo *table;
4925         guint32 cols [MONO_FILE_SIZE];
4926         MonoImage *image = assembly->assembly->image;
4927
4928         g_assert (image != NULL);
4929         g_assert (!assembly->assembly->dynamic);
4930
4931         table = &image->tables [MONO_TABLE_FILE];
4932         file_count = table->rows;
4933
4934         modules = image->modules;
4935         module_count = image->module_count;
4936
4937         real_module_count = 0;
4938         for (i = 0; i < module_count; ++i)
4939                 if (modules [i])
4940                         real_module_count ++;
4941
4942         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4943         res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4944
4945         mono_array_setref (res, 0, mono_module_get_object (domain, image));
4946         j = 1;
4947         for (i = 0; i < module_count; ++i)
4948                 if (modules [i]) {
4949                         mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4950                         ++j;
4951                 }
4952
4953         for (i = 0; i < file_count; ++i, ++j) {
4954                 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4955                 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4956                         mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4957                 else {
4958                         MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4959                         if (!m) {
4960                                 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4961                                 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4962                         }
4963                         mono_array_setref (res, j, mono_module_get_object (domain, m));
4964                 }
4965         }
4966
4967         return res;
4968 }
4969
4970 static MonoReflectionMethod*
4971 ves_icall_GetCurrentMethod (void) 
4972 {
4973         MonoMethod *m = mono_method_get_last_managed ();
4974
4975         MONO_ARCH_SAVE_REGS;
4976
4977         return mono_method_get_object (mono_domain_get (), m, NULL);
4978 }
4979
4980
4981 static MonoMethod*
4982 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4983 {
4984         int offset = -1, i;
4985         if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4986                 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4987                 //method is inflated, we should inflate it on the other class
4988                 MonoGenericContext ctx;
4989                 ctx.method_inst = inflated->context.method_inst;
4990                 ctx.class_inst = inflated->context.class_inst;
4991                 if (klass->generic_class)
4992                         ctx.class_inst = klass->generic_class->context.class_inst;
4993                 else if (klass->generic_container)
4994                         ctx.class_inst = klass->generic_container->context.class_inst;
4995                 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4996         }
4997
4998         mono_class_setup_methods (method->klass);
4999         for (i = 0; i < method->klass->method.count; ++i) {
5000                 if (method->klass->methods [i] == method) {
5001                         offset = i;
5002                         break;
5003                 }       
5004         }
5005         mono_class_setup_methods (klass);
5006         g_assert (offset >= 0 && offset < klass->method.count);
5007         return klass->methods [offset];
5008 }
5009
5010 static MonoReflectionMethod*
5011 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5012 {
5013         MonoClass *klass;
5014         if (type) {
5015                 klass = mono_class_from_mono_type (type);
5016                 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass)) 
5017                         return NULL;
5018                 if (method->klass != klass)
5019                         method = mono_method_get_equivalent_method (method, klass);
5020         } else
5021                 klass = method->klass;
5022         return mono_method_get_object (mono_domain_get (), method, klass);
5023 }
5024
5025 static MonoReflectionMethod*
5026 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
5027 {
5028         return mono_method_get_object (mono_domain_get (), method, NULL);
5029 }
5030
5031 static MonoReflectionMethodBody*
5032 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5033 {
5034         return mono_method_body_get_object (mono_domain_get (), method);
5035 }
5036
5037 static MonoReflectionAssembly*
5038 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5039 {
5040         MonoMethod *dest = NULL;
5041
5042         MONO_ARCH_SAVE_REGS;
5043
5044         mono_stack_walk_no_il (get_executing, &dest);
5045         return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5046 }
5047
5048
5049 static MonoReflectionAssembly*
5050 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5051 {
5052         MonoDomain* domain = mono_domain_get ();
5053
5054         MONO_ARCH_SAVE_REGS;
5055
5056         if (!domain->entry_assembly)
5057                 return NULL;
5058
5059         return mono_assembly_get_object (domain, domain->entry_assembly);
5060 }
5061
5062 static MonoReflectionAssembly*
5063 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5064 {
5065         MonoMethod *m;
5066         MonoMethod *dest;
5067
5068         MONO_ARCH_SAVE_REGS;
5069
5070         dest = NULL;
5071         mono_stack_walk_no_il (get_executing, &dest);
5072         m = dest;
5073         mono_stack_walk_no_il (get_caller, &dest);
5074         if (!dest)
5075                 dest = m;
5076         return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5077 }
5078
5079 static MonoString *
5080 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5081                                        gboolean assembly_qualified)
5082 {
5083         MonoDomain *domain = mono_object_domain (object); 
5084         MonoTypeNameFormat format;
5085         MonoString *res;
5086         gchar *name;
5087
5088         MONO_ARCH_SAVE_REGS;
5089         if (full_name)
5090                 format = assembly_qualified ?
5091                         MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5092                         MONO_TYPE_NAME_FORMAT_FULL_NAME;
5093         else
5094                 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5095  
5096         name = mono_type_get_name_full (object->type, format);
5097         if (!name)
5098                 return NULL;
5099
5100         if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5101                 g_free (name);
5102                 return NULL;
5103         }
5104
5105         res = mono_string_new (domain, name);
5106         g_free (name);
5107
5108         return res;
5109 }
5110
5111 static void
5112 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
5113 {
5114         static MonoMethod *create_culture = NULL;
5115         gpointer args [2];
5116         guint32 pkey_len;
5117         const char *pkey_ptr;
5118         gchar *codebase;
5119         MonoBoolean assembly_ref = 0;
5120
5121         MONO_ARCH_SAVE_REGS;
5122
5123         MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5124         aname->major = name->major;
5125         aname->minor = name->minor;
5126         aname->build = name->build;
5127         aname->flags = name->flags;
5128         aname->revision = name->revision;
5129         aname->hashalg = name->hash_alg;
5130         aname->versioncompat = 1; /* SameMachine (default) */
5131
5132         if (by_default_version)
5133                 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
5134
5135         codebase = NULL;
5136         if (absolute != NULL && *absolute != '\0') {
5137                 const gchar *prepend = "file://";
5138                 gchar *result;
5139
5140                 codebase = g_strdup (absolute);
5141
5142 #if PLATFORM_WIN32
5143                 {
5144                         gint i;
5145                         for (i = strlen (codebase) - 1; i >= 0; i--)
5146                                 if (codebase [i] == '\\')
5147                                         codebase [i] = '/';
5148
5149                         if (*codebase == '/' && *(codebase + 1) == '/') {
5150                                 prepend = "file:";
5151                         } else {
5152                                 prepend = "file:///";
5153                         }
5154                 }
5155 #endif
5156                 result = g_strconcat (prepend, codebase, NULL);
5157                 g_free (codebase);
5158                 codebase = result;
5159         }
5160
5161         if (codebase) {
5162                 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5163                 g_free (codebase);
5164         }
5165
5166         if (!create_culture) {
5167                 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5168                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5169                 g_assert (create_culture);
5170                 mono_method_desc_free (desc);
5171         }
5172
5173         if (name->culture) {
5174                 args [0] = mono_string_new (domain, name->culture);
5175                 args [1] = &assembly_ref;
5176                 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5177         }
5178
5179         if (name->public_key) {
5180                 pkey_ptr = (char*)name->public_key;
5181                 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5182
5183                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5184                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5185                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5186         } else if (default_publickey) {
5187                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5188                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5189         }
5190
5191         /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5192         if (name->public_key_token [0]) {
5193                 int i, j;
5194                 char *p;
5195
5196                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5197                 p = mono_array_addr (aname->keyToken, char, 0);
5198
5199                 for (i = 0, j = 0; i < 8; i++) {
5200                         *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5201                         *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5202                         p++;
5203                 }
5204         } else if (default_token) {
5205                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5206         }
5207 }
5208
5209 static MonoString *
5210 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5211 {
5212         MonoDomain *domain = mono_object_domain (assembly); 
5213         MonoAssembly *mass = assembly->assembly;
5214         MonoString *res;
5215         gchar *name;
5216
5217         name = g_strdup_printf (
5218                 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5219                 mass->aname.name,
5220                 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5221                 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5222                 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5223                 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5224
5225         res = mono_string_new (domain, name);
5226         g_free (name);
5227
5228         return res;
5229 }
5230
5231 static void
5232 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5233 {
5234         gchar *absolute;
5235         MonoAssembly *mass = assembly->assembly;
5236
5237         MONO_ARCH_SAVE_REGS;
5238
5239         if (g_path_is_absolute (mass->image->name)) {
5240                 fill_reflection_assembly_name (mono_object_domain (assembly),
5241                         aname, &mass->aname, mass->image->name, TRUE,
5242                         TRUE, mono_framework_version () >= 2);
5243                 return;
5244         }
5245         absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5246
5247         fill_reflection_assembly_name (mono_object_domain (assembly),
5248                 aname, &mass->aname, absolute, TRUE, TRUE,
5249                 mono_framework_version () >= 2);
5250
5251         g_free (absolute);
5252 }
5253
5254 static void
5255 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5256 {
5257         char *filename;
5258         MonoImageOpenStatus status = MONO_IMAGE_OK;
5259         gboolean res;
5260         MonoImage *image;
5261         MonoAssemblyName name;
5262         char *dirname
5263
5264         MONO_ARCH_SAVE_REGS;
5265
5266         filename = mono_string_to_utf8 (fname);
5267
5268         dirname = g_path_get_dirname (filename);
5269         replace_shadow_path (mono_domain_get (), dirname, &filename);
5270         g_free (dirname);
5271
5272         image = mono_image_open (filename, &status);
5273
5274         if (!image){
5275                 MonoException *exc;
5276
5277                 g_free (filename);
5278                 if (status == MONO_IMAGE_IMAGE_INVALID)
5279                         exc = mono_get_exception_bad_image_format2 (NULL, fname);
5280                 else
5281                         exc = mono_get_exception_file_not_found2 (NULL, fname);
5282                 mono_raise_exception (exc);
5283         }
5284
5285         res = mono_assembly_fill_assembly_name (image, &name);
5286         if (!res) {
5287                 mono_image_close (image);
5288                 g_free (filename);
5289                 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5290         }
5291
5292         fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5293                 TRUE, mono_framework_version () == 1,
5294                 mono_framework_version () >= 2);
5295
5296         g_free (filename);
5297         mono_image_close (image);
5298 }
5299
5300 static MonoBoolean
5301 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5302         char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5303 {
5304         MonoBoolean result = FALSE;
5305         MonoDeclSecurityEntry entry;
5306
5307         /* SecurityAction.RequestMinimum */
5308         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5309                 *minimum = entry.blob;
5310                 *minLength = entry.size;
5311                 result = TRUE;
5312         }
5313         /* SecurityAction.RequestOptional */
5314         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5315                 *optional = entry.blob;
5316                 *optLength = entry.size;
5317                 result = TRUE;
5318         }
5319         /* SecurityAction.RequestRefuse */
5320         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5321                 *refused = entry.blob;
5322                 *refLength = entry.size;
5323                 result = TRUE;
5324         }
5325
5326         return result;  
5327 }
5328
5329 static MonoArray*
5330 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5331 {
5332         MonoArray *res;
5333         MonoClass *klass;
5334         MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5335         int i, count;
5336         guint32 attrs, visibility;
5337
5338         /* we start the count from 1 because we skip the special type <Module> */
5339         if (exportedOnly) {
5340                 count = 0;
5341                 for (i = 1; i < tdef->rows; ++i) {
5342                         attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5343                         visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5344                         if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5345                                 count++;
5346                 }
5347         } else {
5348                 count = tdef->rows - 1;
5349         }
5350         res = mono_array_new (domain, mono_defaults.monotype_class, count);
5351         *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5352         count = 0;
5353         for (i = 1; i < tdef->rows; ++i) {
5354                 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5355                 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5356                 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5357                         klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5358                         if (klass) {
5359                                 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5360                         } else {
5361                                 MonoLoaderError *error;
5362                                 MonoException *ex;
5363                                 
5364                                 error = mono_loader_get_last_error ();
5365                                 g_assert (error != NULL);
5366         
5367                                 ex = mono_loader_error_prepare_exception (error);
5368                                 mono_array_setref (*exceptions, count, ex);
5369                         }
5370                         if (mono_loader_get_last_error ())
5371                                 mono_loader_clear_error ();
5372                         count++;
5373                 }
5374         }
5375         
5376         return res;
5377 }
5378
5379 static MonoArray*
5380 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5381 {
5382         MonoArray *res = NULL;
5383         MonoArray *exceptions = NULL;
5384         MonoImage *image = NULL;
5385         MonoTableInfo *table = NULL;
5386         MonoDomain *domain;
5387         GList *list = NULL;
5388         int i, len, ex_count;
5389
5390         MONO_ARCH_SAVE_REGS;
5391
5392         domain = mono_object_domain (assembly);
5393
5394         g_assert (!assembly->assembly->dynamic);
5395         image = assembly->assembly->image;
5396         table = &image->tables [MONO_TABLE_FILE];
5397         res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5398
5399         /* Append data from all modules in the assembly */
5400         for (i = 0; i < table->rows; ++i) {
5401                 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5402                         MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5403                         if (loaded_image) {
5404                                 MonoArray *ex2;
5405                                 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5406                                 /* Append the new types to the end of the array */
5407                                 if (mono_array_length (res2) > 0) {
5408                                         guint32 len1, len2;
5409                                         MonoArray *res3, *ex3;
5410
5411                                         len1 = mono_array_length (res);
5412                                         len2 = mono_array_length (res2);
5413
5414                                         res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5415                                         mono_array_memcpy_refs (res3, 0, res, 0, len1);
5416                                         mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5417                                         res = res3;
5418
5419                                         ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5420                                         mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5421                                         mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5422                                         exceptions = ex3;
5423                                 }
5424                         }
5425                 }
5426         }
5427
5428         /* the ReflectionTypeLoadException must have all the types (Types property), 
5429          * NULL replacing types which throws an exception. The LoaderException must
5430          * contain all exceptions for NULL items.
5431          */
5432
5433         len = mono_array_length (res);
5434
5435         ex_count = 0;
5436         for (i = 0; i < len; i++) {
5437                 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5438                 MonoClass *klass;
5439
5440                 if (t) {
5441                         klass = mono_type_get_class (t->type);
5442                         if ((klass != NULL) && klass->exception_type) {
5443                                 /* keep the class in the list */
5444                                 list = g_list_append (list, klass);
5445                                 /* and replace Type with NULL */
5446                                 mono_array_setref (res, i, NULL);
5447                         }
5448                 } else {
5449                         ex_count ++;
5450                 }
5451         }
5452
5453         if (list || ex_count) {
5454                 GList *tmp = NULL;
5455                 MonoException *exc = NULL;
5456                 MonoArray *exl = NULL;
5457                 int j, length = g_list_length (list) + ex_count;
5458
5459                 mono_loader_clear_error ();
5460
5461                 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5462                 /* Types for which mono_class_get () succeeded */
5463                 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5464                         MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5465                         mono_array_setref (exl, i, exc);
5466                 }
5467                 /* Types for which it don't */
5468                 for (j = 0; j < mono_array_length (exceptions); ++j) {
5469                         MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5470                         if (exc) {
5471                                 g_assert (i < length);
5472                                 mono_array_setref (exl, i, exc);
5473                                 i ++;
5474                         }
5475                 }
5476                 g_list_free (list);
5477                 list = NULL;
5478
5479                 exc = mono_get_exception_reflection_type_load (res, exl);
5480                 mono_loader_clear_error ();
5481                 mono_raise_exception (exc);
5482         }
5483                 
5484         return res;
5485 }
5486
5487 static gboolean
5488 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5489 {
5490         MonoAssemblyName aname;
5491         MonoDomain *domain = mono_object_domain (name);
5492         char *val;
5493         gboolean is_version_defined;
5494         gboolean is_token_defined;
5495
5496         aname.public_key = NULL;
5497         val = mono_string_to_utf8 (assname);
5498         if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5499                 g_free ((guint8*) aname.public_key);
5500                 g_free (val);
5501                 return FALSE;
5502         }
5503         
5504         fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5505                 FALSE, is_token_defined);
5506
5507         mono_assembly_name_free (&aname);
5508         g_free ((guint8*) aname.public_key);
5509         g_free (val);
5510
5511         return TRUE;
5512 }
5513
5514 static MonoReflectionType*
5515 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5516 {
5517         MonoDomain *domain = mono_object_domain (module); 
5518         MonoClass *klass;
5519
5520         MONO_ARCH_SAVE_REGS;
5521
5522         g_assert (module->image);
5523
5524         if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5525                 /* These images do not have a global type */
5526                 return NULL;
5527
5528         klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5529         return mono_type_get_object (domain, &klass->byval_arg);
5530 }
5531
5532 static void
5533 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5534 {
5535         /*if (module->image)
5536                 mono_image_close (module->image);*/
5537 }
5538
5539 static MonoString*
5540 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5541 {
5542         MonoDomain *domain = mono_object_domain (module); 
5543
5544         MONO_ARCH_SAVE_REGS;
5545
5546         g_assert (module->image);
5547         return mono_string_new (domain, module->image->guid);
5548 }
5549
5550 static gpointer
5551 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5552 {
5553 #ifdef PLATFORM_WIN32
5554         if (module->image && module->image->is_module_handle)
5555                 return module->image->raw_data;
5556 #endif
5557
5558         return (gpointer) (-1);
5559 }
5560
5561 static void
5562 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5563 {
5564         if (image->dynamic) {
5565                 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5566                 *pe_kind = dyn->pe_kind;
5567                 *machine = dyn->machine;
5568         }
5569         else {
5570                 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5571                 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5572         }
5573 }
5574
5575 static gint32
5576 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5577 {
5578         return (image->md_version_major << 16) | (image->md_version_minor);
5579 }
5580
5581 static MonoArray*
5582 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5583 {
5584         MonoArray *exceptions;
5585         int i;
5586
5587         MONO_ARCH_SAVE_REGS;
5588
5589         if (!module->image)
5590                 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5591         else {
5592                 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5593                 for (i = 0; i < mono_array_length (exceptions); ++i) {
5594                         MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5595                         if (ex)
5596                                 mono_raise_exception (ex);
5597                 }
5598                 return res;
5599         }
5600 }
5601
5602 static gboolean
5603 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5604 {
5605         guint32 cols [MONO_MEMBERREF_SIZE];
5606         const char *sig;
5607         mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5608         sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5609         mono_metadata_decode_blob_size (sig, &sig);
5610         return (*sig != 0x6);
5611 }
5612
5613 static void
5614 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5615 {
5616         if (type_args)
5617                 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5618                                                                       mono_array_addr (type_args, MonoType*, 0));
5619         else
5620                 context->class_inst = NULL;
5621         if (method_args)
5622                 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5623                                                                        mono_array_addr (method_args, MonoType*, 0));
5624         else
5625                 context->method_inst = NULL;
5626 }
5627
5628 static MonoType*
5629 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5630 {
5631         MonoClass *klass;
5632         int table = mono_metadata_token_table (token);
5633         int index = mono_metadata_token_index (token);
5634         MonoGenericContext context;
5635
5636         *error = ResolveTokenError_Other;
5637
5638         /* Validate token */
5639         if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) && 
5640                 (table != MONO_TABLE_TYPESPEC)) {
5641                 *error = ResolveTokenError_BadTable;
5642                 return NULL;
5643         }
5644
5645         if (image->dynamic) {
5646                 if (type_args || method_args)
5647                         mono_raise_exception (mono_get_exception_not_implemented (NULL));
5648                 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5649                 if (!klass)
5650                         return NULL;
5651                 return &klass->byval_arg;
5652         }
5653
5654         if ((index <= 0) || (index > image->tables [table].rows)) {
5655                 *error = ResolveTokenError_OutOfRange;
5656                 return NULL;
5657         }
5658
5659         init_generic_context_from_args (&context, type_args, method_args);
5660         klass = mono_class_get_full (image, token, &context);
5661
5662         if (mono_loader_get_last_error ())
5663                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5664
5665         if (klass)
5666                 return &klass->byval_arg;
5667         else
5668                 return NULL;
5669 }
5670
5671 static MonoMethod*
5672 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5673 {
5674         int table = mono_metadata_token_table (token);
5675         int index = mono_metadata_token_index (token);
5676         MonoGenericContext context;
5677         MonoMethod *method;
5678
5679         *error = ResolveTokenError_Other;
5680
5681         /* Validate token */
5682         if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) && 
5683                 (table != MONO_TABLE_MEMBERREF)) {
5684                 *error = ResolveTokenError_BadTable;
5685                 return NULL;
5686         }
5687
5688         if (image->dynamic) {
5689                 if (type_args || method_args)
5690                         mono_raise_exception (mono_get_exception_not_implemented (NULL));
5691                 /* FIXME: validate memberref token type */
5692                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5693         }
5694
5695         if ((index <= 0) || (index > image->tables [table].rows)) {
5696                 *error = ResolveTokenError_OutOfRange;
5697                 return NULL;
5698         }
5699         if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5700                 *error = ResolveTokenError_BadTable;
5701                 return NULL;
5702         }
5703
5704         init_generic_context_from_args (&context, type_args, method_args);
5705         method = mono_get_method_full (image, token, NULL, &context);
5706
5707         if (mono_loader_get_last_error ())
5708                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5709
5710         return method;
5711 }
5712
5713 static MonoString*
5714 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5715 {
5716         int index = mono_metadata_token_index (token);
5717
5718         *error = ResolveTokenError_Other;
5719
5720         /* Validate token */
5721         if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5722                 *error = ResolveTokenError_BadTable;
5723                 return NULL;
5724         }
5725
5726         if (image->dynamic)
5727                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5728
5729         if ((index <= 0) || (index >= image->heap_us.size)) {
5730                 *error = ResolveTokenError_OutOfRange;
5731                 return NULL;
5732         }
5733
5734         /* FIXME: What to do if the index points into the middle of a string ? */
5735
5736         return mono_ldstr (mono_domain_get (), image, index);
5737 }
5738
5739 static MonoClassField*
5740 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5741 {
5742         MonoClass *klass;
5743         int table = mono_metadata_token_table (token);
5744         int index = mono_metadata_token_index (token);
5745         MonoGenericContext context;
5746         MonoClassField *field;
5747
5748         *error = ResolveTokenError_Other;
5749
5750         /* Validate token */
5751         if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5752                 *error = ResolveTokenError_BadTable;
5753                 return NULL;
5754         }
5755
5756         if (image->dynamic) {
5757                 if (type_args || method_args)
5758                         mono_raise_exception (mono_get_exception_not_implemented (NULL));
5759                 /* FIXME: validate memberref token type */
5760                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5761         }
5762
5763         if ((index <= 0) || (index > image->tables [table].rows)) {
5764                 *error = ResolveTokenError_OutOfRange;
5765                 return NULL;
5766         }
5767         if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5768                 *error = ResolveTokenError_BadTable;
5769                 return NULL;
5770         }
5771
5772         init_generic_context_from_args (&context, type_args, method_args);
5773         field = mono_field_from_token (image, token, &klass, &context);
5774
5775         if (mono_loader_get_last_error ())
5776                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5777         
5778         return field;
5779 }
5780
5781
5782 static MonoObject*
5783 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5784 {
5785         int table = mono_metadata_token_table (token);
5786
5787         *error = ResolveTokenError_Other;
5788
5789         switch (table) {
5790         case MONO_TABLE_TYPEDEF:
5791         case MONO_TABLE_TYPEREF:
5792         case MONO_TABLE_TYPESPEC: {
5793                 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5794                 if (t)
5795                         return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5796                 else
5797                         return NULL;
5798         }
5799         case MONO_TABLE_METHOD:
5800         case MONO_TABLE_METHODSPEC: {
5801                 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5802                 if (m)
5803                         return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5804                 else
5805                         return NULL;
5806         }               
5807         case MONO_TABLE_FIELD: {
5808                 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5809                 if (f)
5810                         return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5811                 else
5812                         return NULL;
5813         }
5814         case MONO_TABLE_MEMBERREF:
5815                 if (mono_metadata_memberref_is_method (image, token)) {
5816                         MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5817                         if (m)
5818                                 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5819                         else
5820                                 return NULL;
5821                 }
5822                 else {
5823                         MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5824                         if (f)
5825                                 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5826                         else
5827                                 return NULL;
5828                 }
5829                 break;
5830
5831         default:
5832                 *error = ResolveTokenError_BadTable;
5833         }
5834
5835         return NULL;
5836 }
5837
5838 static MonoArray*
5839 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5840 {
5841         int table = mono_metadata_token_table (token);
5842         int idx = mono_metadata_token_index (token);
5843         MonoTableInfo *tables = image->tables;
5844         guint32 sig, len;
5845         const char *ptr;
5846         MonoArray *res;
5847
5848         *error = ResolveTokenError_OutOfRange;
5849
5850         /* FIXME: Support other tables ? */
5851         if (table != MONO_TABLE_STANDALONESIG)
5852                 return NULL;
5853
5854         if (image->dynamic)
5855                 return NULL;
5856
5857         if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5858                 return NULL;
5859
5860         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5861
5862         ptr = mono_metadata_blob_heap (image, sig);
5863         len = mono_metadata_decode_blob_size (ptr, &ptr);
5864
5865         res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5866         memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5867         return res;
5868 }
5869
5870 static MonoReflectionType*
5871 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5872 {
5873         MonoClass *klass;
5874         int isbyref = 0, rank;
5875         char *str = mono_string_to_utf8 (smodifiers);
5876         char *p;
5877
5878         MONO_ARCH_SAVE_REGS;
5879
5880         klass = mono_class_from_mono_type (tb->type.type);
5881         p = str;
5882         /* logic taken from mono_reflection_parse_type(): keep in sync */
5883         while (*p) {
5884                 switch (*p) {
5885                 case '&':
5886                         if (isbyref) { /* only one level allowed by the spec */
5887                                 g_free (str);
5888                                 return NULL;
5889                         }
5890                         isbyref = 1;
5891                         p++;
5892                         g_free (str);
5893                         return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5894                         break;
5895                 case '*':
5896                         klass = mono_ptr_class_get (&klass->byval_arg);
5897                         mono_class_init (klass);
5898                         p++;
5899                         break;
5900                 case '[':
5901                         rank = 1;
5902                         p++;
5903                         while (*p) {
5904                                 if (*p == ']')
5905                                         break;
5906                                 if (*p == ',')
5907                                         rank++;
5908                                 else if (*p != '*') { /* '*' means unknown lower bound */
5909                                         g_free (str);
5910                                         return NULL;
5911                                 }
5912                                 ++p;
5913                         }
5914                         if (*p != ']') {
5915                                 g_free (str);
5916                                 return NULL;
5917                         }
5918                         p++;
5919                         klass = mono_array_class_get (klass, rank);
5920                         mono_class_init (klass);
5921                         break;
5922                 default:
5923                         break;
5924                 }
5925         }
5926         g_free (str);
5927         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5928 }
5929
5930 static MonoBoolean
5931 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5932 {
5933         MonoType *type;
5934         MonoBoolean res;
5935
5936         MONO_ARCH_SAVE_REGS;
5937
5938         type = t->type;
5939         res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5940
5941         return res;
5942 }
5943
5944 static MonoReflectionType *
5945 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5946 {
5947         MonoClass *klass, *aklass;
5948
5949         MONO_ARCH_SAVE_REGS;
5950
5951         klass = mono_class_from_mono_type (type->type);
5952         aklass = mono_array_class_get (klass, rank);
5953
5954         return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5955 }
5956
5957 static MonoReflectionType *
5958 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5959 {
5960         MonoClass *klass;
5961
5962         MONO_ARCH_SAVE_REGS;
5963
5964         klass = mono_class_from_mono_type (type->type);
5965
5966         return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5967 }
5968
5969 static MonoReflectionType *
5970 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5971 {
5972         MonoClass *pklass;
5973
5974         MONO_ARCH_SAVE_REGS;
5975
5976         pklass = mono_ptr_class_get (type->type);
5977
5978         return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5979 }
5980
5981 static MonoObject *
5982 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5983                                                    MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5984 {
5985         MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5986         MonoObject *delegate;
5987         gpointer func;
5988         MonoMethod *method = info->method;
5989
5990         MONO_ARCH_SAVE_REGS;
5991
5992         mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5993
5994         if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5995                 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5996                         return NULL;
5997         }
5998
5999         delegate = mono_object_new (mono_object_domain (type), delegate_class);
6000
6001         if (mono_method_needs_static_rgctx_invoke (method, FALSE)) {
6002                 method = mono_marshal_get_static_rgctx_invoke (method);
6003                 func = mono_compile_method (method);
6004         } else if (method->dynamic) {
6005                 /* Creating a trampoline would leak memory */
6006                 func = mono_compile_method (method);
6007         } else {
6008                 func = mono_create_ftnptr (mono_domain_get (),
6009                         mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6010         }
6011
6012         mono_delegate_ctor_with_method (delegate, target, func, method);
6013
6014         return delegate;
6015 }
6016
6017 static void
6018 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
6019 {
6020         /* Reset the invoke impl to the default one */
6021         this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
6022 }
6023
6024 /*
6025  * Magic number to convert a time which is relative to
6026  * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
6027  */
6028 #define EPOCH_ADJUST    ((guint64)62135596800LL)
6029
6030 /*
6031  * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
6032  */
6033 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
6034
6035 #ifdef PLATFORM_WIN32
6036 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
6037 static void
6038 convert_to_absolute_date(SYSTEMTIME *date)
6039 {
6040 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
6041         static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
6042         static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
6043         /* from the calendar FAQ */
6044         int a = (14 - date->wMonth) / 12;
6045         int y = date->wYear - a;
6046         int m = date->wMonth + 12 * a - 2;
6047         int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
6048
6049         /* d is now the day of the week for the first of the month (0 == Sunday) */
6050
6051         int day_of_week = date->wDayOfWeek;
6052
6053         /* set day_in_month to the first day in the month which falls on day_of_week */    
6054         int day_in_month = 1 + (day_of_week - d);
6055         if (day_in_month <= 0)
6056                 day_in_month += 7;
6057
6058         /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
6059         date->wDay = day_in_month + (date->wDay - 1) * 7;
6060         if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
6061                 date->wDay -= 7;
6062 }
6063 #endif
6064
6065 #ifndef PLATFORM_WIN32
6066 /*
6067  * Return's the offset from GMT of a local time.
6068  * 
6069  *  tm is a local time
6070  *  t  is the same local time as seconds.
6071  */
6072 static int 
6073 gmt_offset(struct tm *tm, time_t t)
6074 {
6075 #if defined (HAVE_TM_GMTOFF)
6076         return tm->tm_gmtoff;
6077 #else
6078         struct tm g;
6079         time_t t2;
6080         g = *gmtime(&t);
6081         g.tm_isdst = tm->tm_isdst;
6082         t2 = mktime(&g);
6083         return (int)difftime(t, t2);
6084 #endif
6085 }
6086 #endif
6087 /*
6088  * This is heavily based on zdump.c from glibc 2.2.
6089  *
6090  *  * data[0]:  start of daylight saving time (in DateTime ticks).
6091  *  * data[1]:  end of daylight saving time (in DateTime ticks).
6092  *  * data[2]:  utcoffset (in TimeSpan ticks).
6093  *  * data[3]:  additional offset when daylight saving (in TimeSpan ticks).
6094  *  * name[0]:  name of this timezone when not daylight saving.
6095  *  * name[1]:  name of this timezone when daylight saving.
6096  *
6097  *  FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
6098  *         the class library allows years between 1 and 9999.
6099  *
6100  *  Returns true on success and zero on failure.
6101  */
6102 static guint32
6103 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
6104 {
6105 #ifndef PLATFORM_WIN32
6106         MonoDomain *domain = mono_domain_get ();
6107         struct tm start, tt;
6108         time_t t;
6109
6110         long int gmtoff;
6111         int is_daylight = 0, day;
6112         char tzone [64];
6113
6114         MONO_ARCH_SAVE_REGS;
6115
6116         MONO_CHECK_ARG_NULL (data);
6117         MONO_CHECK_ARG_NULL (names);
6118
6119         (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
6120         (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
6121
6122         /* 
6123          * no info is better than crashing: we'll need our own tz data
6124          * to make this work properly, anyway. The range is probably
6125          * reduced to 1970 .. 2037 because that is what mktime is
6126          * guaranteed to support (we get into an infinite loop
6127          * otherwise).
6128          */
6129
6130         memset (&start, 0, sizeof (start));
6131
6132         start.tm_mday = 1;
6133         start.tm_year = year-1900;
6134
6135         t = mktime (&start);
6136
6137         if ((year < 1970) || (year > 2037) || (t == -1)) {
6138                 t = time (NULL);
6139                 tt = *localtime (&t);
6140                 strftime (tzone, sizeof (tzone), "%Z", &tt);
6141                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6142                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6143                 return 1;
6144         }
6145
6146         gmtoff = gmt_offset (&start, t);
6147
6148         /* For each day of the year, calculate the tm_gmtoff. */
6149         for (day = 0; day < 365; day++) {
6150
6151                 t += 3600*24;
6152                 tt = *localtime (&t);
6153
6154                 /* Daylight saving starts or ends here. */
6155                 if (gmt_offset (&tt, t) != gmtoff) {
6156                         struct tm tt1;
6157                         time_t t1;
6158
6159                         /* Try to find the exact hour when daylight saving starts/ends. */
6160                         t1 = t;
6161                         do {
6162                                 t1 -= 3600;
6163                                 tt1 = *localtime (&t1);
6164                         } while (gmt_offset (&tt1, t1) != gmtoff);
6165
6166                         /* Try to find the exact minute when daylight saving starts/ends. */
6167                         do {
6168                                 t1 += 60;
6169                                 tt1 = *localtime (&t1);
6170                         } while (gmt_offset (&tt1, t1) == gmtoff);
6171                         t1+=gmtoff;
6172                         strftime (tzone, sizeof (tzone), "%Z", &tt);
6173                         
6174                         /* Write data, if we're already in daylight saving, we're done. */
6175                         if (is_daylight) {
6176                                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6177                                 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6178                                 return 1;
6179                         } else {
6180                                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6181                                 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6182                                 is_daylight = 1;
6183                         }
6184
6185                         /* This is only set once when we enter daylight saving. */
6186                         mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6187                         mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6188
6189                         gmtoff = gmt_offset (&tt, t);
6190                 }
6191         }
6192
6193         if (!is_daylight) {
6194                 strftime (tzone, sizeof (tzone), "%Z", &tt);
6195                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6196                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6197                 mono_array_set ((*data), gint64, 0, 0);
6198                 mono_array_set ((*data), gint64, 1, 0);
6199                 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6200                 mono_array_set ((*data), gint64, 3, 0);
6201         }
6202
6203         return 1;
6204 #else
6205         MonoDomain *domain = mono_domain_get ();
6206         TIME_ZONE_INFORMATION tz_info;
6207         FILETIME ft;
6208         int i;
6209         int err, tz_id;
6210
6211         tz_id = GetTimeZoneInformation (&tz_info);
6212         if (tz_id == TIME_ZONE_ID_INVALID)
6213                 return 0;
6214
6215         MONO_CHECK_ARG_NULL (data);
6216         MONO_CHECK_ARG_NULL (names);
6217
6218         (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
6219         (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
6220
6221         for (i = 0; i < 32; ++i)
6222                 if (!tz_info.DaylightName [i])
6223                         break;
6224         mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6225         for (i = 0; i < 32; ++i)
6226                 if (!tz_info.StandardName [i])
6227                         break;
6228         mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6229
6230         if ((year <= 1601) || (year > 30827)) {
6231                 /*
6232                  * According to MSDN, the MS time functions can't handle dates outside
6233                  * this interval.
6234                  */
6235                 return 1;
6236         }
6237
6238         /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6239         if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6240                 tz_info.StandardDate.wYear = year;
6241                 convert_to_absolute_date(&tz_info.StandardDate);
6242                 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6243                 //g_assert(err);
6244                 if (err == 0)
6245                         return 0;
6246                 
6247                 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6248                 tz_info.DaylightDate.wYear = year;
6249                 convert_to_absolute_date(&tz_info.DaylightDate);
6250                 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6251                 //g_assert(err);
6252                 if (err == 0)
6253                         return 0;
6254                 
6255                 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6256         }
6257         mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6258         mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6259
6260         return 1;
6261 #endif
6262 }
6263
6264 static gpointer
6265 ves_icall_System_Object_obj_address (MonoObject *this) 
6266 {
6267         MONO_ARCH_SAVE_REGS;
6268
6269         return this;
6270 }
6271
6272 /* System.Buffer */
6273
6274 static inline gint32 
6275 mono_array_get_byte_length (MonoArray *array)
6276 {
6277         MonoClass *klass;
6278         int length;
6279         int i;
6280
6281         klass = array->obj.vtable->klass;
6282
6283         if (array->bounds == NULL)
6284                 length = array->max_length;
6285         else {
6286                 length = 1;
6287                 for (i = 0; i < klass->rank; ++ i)
6288                         length *= array->bounds [i].length;
6289         }
6290
6291         switch (klass->element_class->byval_arg.type) {
6292         case MONO_TYPE_I1:
6293         case MONO_TYPE_U1:
6294         case MONO_TYPE_BOOLEAN:
6295                 return length;
6296         case MONO_TYPE_I2:
6297         case MONO_TYPE_U2:
6298         case MONO_TYPE_CHAR:
6299                 return length << 1;
6300         case MONO_TYPE_I4:
6301         case MONO_TYPE_U4:
6302         case MONO_TYPE_R4:
6303                 return length << 2;
6304         case MONO_TYPE_I:
6305         case MONO_TYPE_U:
6306                 return length * sizeof (gpointer);
6307         case MONO_TYPE_I8:
6308         case MONO_TYPE_U8:
6309         case MONO_TYPE_R8:
6310                 return length << 3;
6311         default:
6312                 return -1;
6313         }
6314 }
6315
6316 static gint32 
6317 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array) 
6318 {
6319         MONO_ARCH_SAVE_REGS;
6320
6321         return mono_array_get_byte_length (array);
6322 }
6323
6324 static gint8 
6325 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx) 
6326 {
6327         MONO_ARCH_SAVE_REGS;
6328
6329         return mono_array_get (array, gint8, idx);
6330 }
6331
6332 static void 
6333 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value) 
6334 {
6335         MONO_ARCH_SAVE_REGS;
6336
6337         mono_array_set (array, gint8, idx, value);
6338 }
6339
6340 static MonoBoolean
6341 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count) 
6342 {
6343         guint8 *src_buf, *dest_buf;
6344
6345         MONO_ARCH_SAVE_REGS;
6346
6347         /* watch out for integer overflow */
6348         if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6349                 return FALSE;
6350
6351         src_buf = (guint8 *)src->vector + src_offset;
6352         dest_buf = (guint8 *)dest->vector + dest_offset;
6353
6354         if (src != dest)
6355                 memcpy (dest_buf, src_buf, count);
6356         else
6357                 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6358
6359         return TRUE;
6360 }
6361
6362 static MonoObject *
6363 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6364 {
6365         MonoDomain *domain = mono_object_domain (this); 
6366         MonoObject *res;
6367         MonoRealProxy *rp = ((MonoRealProxy *)this);
6368         MonoTransparentProxy *tp;
6369         MonoType *type;
6370         MonoClass *klass;
6371
6372         MONO_ARCH_SAVE_REGS;
6373
6374         res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6375         tp = (MonoTransparentProxy*) res;
6376         
6377         MONO_OBJECT_SETREF (tp, rp, rp);
6378         type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6379         klass = mono_class_from_mono_type (type);
6380
6381         tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6382         tp->remote_class = mono_remote_class (domain, class_name, klass);
6383
6384         res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6385         return res;
6386 }
6387
6388 static MonoReflectionType *
6389 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6390 {
6391         return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6392 }
6393
6394 /* System.Environment */
6395
6396 MonoString*
6397 ves_icall_System_Environment_get_UserName (void)
6398 {
6399         MONO_ARCH_SAVE_REGS;
6400
6401         /* using glib is more portable */
6402         return mono_string_new (mono_domain_get (), g_get_user_name ());
6403 }
6404
6405
6406 static MonoString *
6407 ves_icall_System_Environment_get_MachineName (void)
6408 {
6409 #if defined (PLATFORM_WIN32)
6410         gunichar2 *buf;
6411         guint32 len;
6412         MonoString *result;
6413
6414         len = MAX_COMPUTERNAME_LENGTH + 1;
6415         buf = g_new (gunichar2, len);
6416
6417         result = NULL;
6418         if (GetComputerName (buf, (PDWORD) &len))
6419                 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6420
6421         g_free (buf);
6422         return result;
6423 #elif !defined(DISABLE_SOCKETS)
6424         gchar buf [256];
6425         MonoString *result;
6426
6427         if (gethostname (buf, sizeof (buf)) == 0)
6428                 result = mono_string_new (mono_domain_get (), buf);
6429         else
6430                 result = NULL;
6431         
6432         return result;
6433 #else
6434         return mono_string_new (mono_domain_get (), "mono");
6435 #endif
6436 }
6437
6438 static int
6439 ves_icall_System_Environment_get_Platform (void)
6440 {
6441 #if defined (PLATFORM_WIN32)
6442         /* Win32NT */
6443         return 2;
6444 #elif defined(__MACH__)
6445         /* OSX */
6446         if (mono_framework_version () < 2)
6447                 return 128;
6448
6449         //
6450         // For compatibility with our client code, this will be 4 for a while.
6451         // We will eventually move to 6 to match .NET, but it requires all client
6452         // code to be updated and the documentation everywhere to be updated 
6453         // first.
6454         //
6455         return 4;
6456 #else
6457         /* Unix */
6458         if (mono_framework_version () < 2)
6459                 return 128;
6460         return 4;
6461 #endif
6462 }
6463
6464 static MonoString *
6465 ves_icall_System_Environment_get_NewLine (void)
6466 {
6467         MONO_ARCH_SAVE_REGS;
6468
6469 #if defined (PLATFORM_WIN32)
6470         return mono_string_new (mono_domain_get (), "\r\n");
6471 #else
6472         return mono_string_new (mono_domain_get (), "\n");
6473 #endif
6474 }
6475
6476 static MonoString *
6477 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6478 {
6479         const gchar *value;
6480         gchar *utf8_name;
6481
6482         MONO_ARCH_SAVE_REGS;
6483
6484         if (name == NULL)
6485                 return NULL;
6486
6487         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6488         value = g_getenv (utf8_name);
6489
6490         g_free (utf8_name);
6491
6492         if (value == 0)
6493                 return NULL;
6494         
6495         return mono_string_new (mono_domain_get (), value);
6496 }
6497
6498 /*
6499  * There is no standard way to get at environ.
6500  */
6501 #ifndef _MSC_VER
6502 #ifndef __MINGW32_VERSION
6503 #ifdef __APPLE__
6504 /* Apple defines this in crt_externs.h but doesn't provide that header for 
6505  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
6506  * in fact exist on all implementations (so far) 
6507  */
6508 gchar ***_NSGetEnviron();
6509 #define environ (*_NSGetEnviron())
6510 #else
6511 extern
6512 char **environ;
6513 #endif
6514 #endif
6515 #endif
6516
6517 static MonoArray *
6518 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6519 {
6520 #ifdef PLATFORM_WIN32
6521         MonoArray *names;
6522         MonoDomain *domain;
6523         MonoString *str;
6524         WCHAR* env_strings;
6525         WCHAR* env_string;
6526         WCHAR* equal_str;
6527         int n = 0;
6528
6529         env_strings = GetEnvironmentStrings();
6530
6531         if (env_strings) {
6532                 env_string = env_strings;
6533                 while (*env_string != '\0') {
6534                 /* weird case that MS seems to skip */
6535                         if (*env_string != '=')
6536                                 n++;
6537                         while (*env_string != '\0')
6538                                 env_string++;
6539                         env_string++;
6540                 }
6541         }
6542
6543         domain = mono_domain_get ();
6544         names = mono_array_new (domain, mono_defaults.string_class, n);
6545
6546         if (env_strings) {
6547                 n = 0;
6548                 env_string = env_strings;
6549                 while (*env_string != '\0') {
6550                         /* weird case that MS seems to skip */
6551                         if (*env_string != '=') {
6552                                 equal_str = wcschr(env_string, '=');
6553                                 g_assert(equal_str);
6554                                 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6555                                 mono_array_setref (names, n, str);
6556                                 n++;
6557                         }
6558                         while (*env_string != '\0')
6559                                 env_string++;
6560                         env_string++;
6561                 }
6562
6563                 FreeEnvironmentStrings (env_strings);
6564         }
6565
6566         return names;
6567
6568 #else
6569         MonoArray *names;
6570         MonoDomain *domain;
6571         MonoString *str;
6572         gchar **e, **parts;
6573         int n;
6574
6575         MONO_ARCH_SAVE_REGS;
6576
6577         n = 0;
6578         for (e = environ; *e != 0; ++ e)
6579                 ++ n;
6580
6581         domain = mono_domain_get ();
6582         names = mono_array_new (domain, mono_defaults.string_class, n);
6583
6584         n = 0;
6585         for (e = environ; *e != 0; ++ e) {
6586                 parts = g_strsplit (*e, "=", 2);
6587                 if (*parts != 0) {
6588                         str = mono_string_new (domain, *parts);
6589                         mono_array_setref (names, n, str);
6590                 }
6591
6592                 g_strfreev (parts);
6593
6594                 ++ n;
6595         }
6596
6597         return names;
6598 #endif
6599 }
6600
6601 /*
6602  * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6603  */
6604 #if !GLIB_CHECK_VERSION(2,4,0)
6605 #define g_setenv(a,b,c)   setenv(a,b,c)
6606 #define g_unsetenv(a) unsetenv(a)
6607 #endif
6608
6609 static void
6610 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6611 {
6612 #ifdef PLATFORM_WIN32
6613         gunichar2 *utf16_name, *utf16_value;
6614 #else
6615         gchar *utf8_name, *utf8_value;
6616 #endif
6617
6618         MONO_ARCH_SAVE_REGS;
6619         
6620 #ifdef PLATFORM_WIN32
6621         utf16_name = mono_string_to_utf16 (name);
6622         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6623                 SetEnvironmentVariable (utf16_name, NULL);
6624                 g_free (utf16_name);
6625                 return;
6626         }
6627
6628         utf16_value = mono_string_to_utf16 (value);
6629
6630         SetEnvironmentVariable (utf16_name, utf16_value);
6631
6632         g_free (utf16_name);
6633         g_free (utf16_value);
6634 #else
6635         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6636
6637         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6638                 g_unsetenv (utf8_name);
6639                 g_free (utf8_name);
6640                 return;
6641         }
6642
6643         utf8_value = mono_string_to_utf8 (value);
6644         g_setenv (utf8_name, utf8_value, TRUE);
6645
6646         g_free (utf8_name);
6647         g_free (utf8_value);
6648 #endif
6649 }
6650
6651 static void
6652 ves_icall_System_Environment_Exit (int result)
6653 {
6654         MONO_ARCH_SAVE_REGS;
6655
6656         mono_threads_set_shutting_down ();
6657
6658         mono_runtime_set_shutting_down ();
6659
6660         /* Suspend all managed threads since the runtime is going away */
6661         mono_thread_suspend_all_other_threads ();
6662
6663         mono_runtime_quit ();
6664
6665         /* we may need to do some cleanup here... */
6666         exit (result);
6667 }
6668
6669 static MonoString*
6670 ves_icall_System_Environment_GetGacPath (void)
6671 {
6672         return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6673 }
6674
6675 static MonoString*
6676 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6677 {
6678 #if defined (PLATFORM_WIN32)
6679         #ifndef CSIDL_FLAG_CREATE
6680                 #define CSIDL_FLAG_CREATE       0x8000
6681         #endif
6682
6683         WCHAR path [MAX_PATH];
6684         /* Create directory if no existing */
6685         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6686                 int len = 0;
6687                 while (path [len])
6688                         ++ len;
6689                 return mono_string_new_utf16 (mono_domain_get (), path, len);
6690         }
6691 #else
6692         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6693 #endif
6694         return mono_string_new (mono_domain_get (), "");
6695 }
6696
6697 static MonoArray *
6698 ves_icall_System_Environment_GetLogicalDrives (void)
6699 {
6700         gunichar2 buf [128], *ptr, *dname;
6701         gunichar2 *u16;
6702         guint initial_size = 127, size = 128;
6703         gint ndrives;
6704         MonoArray *result;
6705         MonoString *drivestr;
6706         MonoDomain *domain = mono_domain_get ();
6707         gint len;
6708
6709         MONO_ARCH_SAVE_REGS;
6710
6711         buf [0] = '\0';
6712         ptr = buf;
6713
6714         while (size > initial_size) {
6715                 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6716                 if (size > initial_size) {
6717                         if (ptr != buf)
6718                                 g_free (ptr);
6719                         ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6720                         initial_size = size;
6721                         size++;
6722                 }
6723         }
6724
6725         /* Count strings */
6726         dname = ptr;
6727         ndrives = 0;
6728         do {
6729                 while (*dname++);
6730                 ndrives++;
6731         } while (*dname);
6732
6733         dname = ptr;
6734         result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6735         ndrives = 0;
6736         do {
6737                 len = 0;
6738                 u16 = dname;
6739                 while (*u16) { u16++; len ++; }
6740                 drivestr = mono_string_new_utf16 (domain, dname, len);
6741                 mono_array_setref (result, ndrives++, drivestr);
6742                 while (*dname++);
6743         } while (*dname);
6744
6745         if (ptr != buf)
6746                 g_free (ptr);
6747
6748         return result;
6749 }
6750
6751 static MonoString *
6752 ves_icall_System_Environment_InternalGetHome (void)
6753 {
6754         MONO_ARCH_SAVE_REGS;
6755
6756         return mono_string_new (mono_domain_get (), g_get_home_dir ());
6757 }
6758
6759 static const char *encodings [] = {
6760         (char *) 1,
6761                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6762                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6763                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6764         (char *) 2,
6765                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6766                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6767                 "x_unicode_2_0_utf_7",
6768         (char *) 3,
6769                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6770                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6771         (char *) 4,
6772                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6773                 "iso_10646_ucs2",
6774         (char *) 5,
6775                 "unicodefffe", "utf_16be",
6776         (char *) 6,
6777                 "iso_8859_1",
6778         (char *) 0
6779 };
6780
6781 /*
6782  * Returns the internal codepage, if the value of "int_code_page" is
6783  * 1 at entry, and we can not compute a suitable code page number,
6784  * returns the code page as a string
6785  */
6786 static MonoString*
6787 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page) 
6788 {
6789         const char *cset;
6790         const char *p;
6791         char *c;
6792         char *codepage = NULL;
6793         int code;
6794         int want_name = *int_code_page;
6795         int i;
6796         
6797         *int_code_page = -1;
6798         MONO_ARCH_SAVE_REGS;
6799
6800         g_get_charset (&cset);
6801         c = codepage = strdup (cset);
6802         for (c = codepage; *c; c++){
6803                 if (isascii (*c) && isalpha (*c))
6804                         *c = tolower (*c);
6805                 if (*c == '-')
6806                         *c = '_';
6807         }
6808         /* g_print ("charset: %s\n", cset); */
6809         
6810         /* handle some common aliases */
6811         p = encodings [0];
6812         code = 0;
6813         for (i = 0; p != 0; ){
6814                 if ((gssize) p < 7){
6815                         code = (gssize) p;
6816                         p = encodings [++i];
6817                         continue;
6818                 }
6819                 if (strcmp (p, codepage) == 0){
6820                         *int_code_page = code;
6821                         break;
6822                 }
6823                 p = encodings [++i];
6824         }
6825         
6826         if (strstr (codepage, "utf_8") != NULL)
6827                 *int_code_page |= 0x10000000;
6828         free (codepage);
6829         
6830         if (want_name && *int_code_page == -1)
6831                 return mono_string_new (mono_domain_get (), cset);
6832         else
6833                 return NULL;
6834 }
6835
6836 static MonoBoolean
6837 ves_icall_System_Environment_get_HasShutdownStarted (void)
6838 {
6839         if (mono_runtime_is_shutting_down ())
6840                 return TRUE;
6841
6842         if (mono_domain_is_unloading (mono_domain_get ()))
6843                 return TRUE;
6844
6845         return FALSE;
6846 }
6847
6848 static void
6849 ves_icall_System_Environment_BroadcastSettingChange (void)
6850 {
6851 #ifdef PLATFORM_WIN32
6852         SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6853 #endif
6854 }
6855
6856 static void
6857 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this, 
6858                                          MonoReflectionMethod *method,
6859                                          MonoArray *out_args)
6860 {
6861         MONO_ARCH_SAVE_REGS;
6862
6863         mono_message_init (mono_object_domain (this), this, method, out_args);
6864 }
6865
6866 static MonoBoolean
6867 ves_icall_IsTransparentProxy (MonoObject *proxy)
6868 {
6869         MONO_ARCH_SAVE_REGS;
6870
6871         if (!proxy)
6872                 return 0;
6873
6874         if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6875                 return 1;
6876
6877         return 0;
6878 }
6879
6880 static MonoReflectionMethod *
6881 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6882         MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6883 {
6884         MonoClass *klass;
6885         MonoMethod *method;
6886         MonoMethod **vtable;
6887         MonoMethod *res = NULL;
6888
6889         MONO_CHECK_ARG_NULL (rtype);
6890         MONO_CHECK_ARG_NULL (rmethod);
6891
6892         method = rmethod->method;
6893         klass = mono_class_from_mono_type (rtype->type);
6894
6895         if (MONO_CLASS_IS_INTERFACE (klass))
6896                 return NULL;
6897
6898         if (method->flags & METHOD_ATTRIBUTE_STATIC)
6899                 return NULL;
6900
6901         if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6902                 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6903                         return rmethod;
6904                 else
6905                         return NULL;
6906         }
6907
6908         mono_class_setup_vtable (klass);
6909         vtable = klass->vtable;
6910
6911         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6912                 int offs = mono_class_interface_offset (klass, method->klass);
6913                 if (offs >= 0)
6914                         res = vtable [offs + method->slot];
6915         } else {
6916                 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6917                         return NULL;
6918
6919                 if (method->slot != -1)
6920                         res = vtable [method->slot];
6921         }
6922
6923         if (!res)
6924                 return NULL;
6925
6926         return mono_method_get_object (mono_domain_get (), res, NULL);
6927 }
6928
6929 static void
6930 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6931 {
6932         MonoClass *klass;
6933         MonoVTable* vtable;
6934
6935         MONO_ARCH_SAVE_REGS;
6936
6937         klass = mono_class_from_mono_type (type->type);
6938         vtable = mono_class_vtable (mono_domain_get (), klass);
6939
6940         if (enable) vtable->remote = 1;
6941         else vtable->remote = 0;
6942 }
6943
6944 static MonoObject *
6945 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6946 {
6947         MonoClass *klass;
6948         MonoDomain *domain;
6949         
6950         MONO_ARCH_SAVE_REGS;
6951
6952         domain = mono_object_domain (type);
6953         klass = mono_class_from_mono_type (type->type);
6954
6955         if (klass->rank >= 1) {
6956                 g_assert (klass->rank == 1);
6957                 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6958         } else {
6959                 /* Bypass remoting object creation check */
6960                 return mono_object_new_alloc_specific (mono_class_vtable (domain, klass));
6961         }
6962 }
6963
6964 static MonoString *
6965 ves_icall_System_IO_get_temp_path (void)
6966 {
6967         MONO_ARCH_SAVE_REGS;
6968
6969         return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6970 }
6971
6972 #ifndef PLATFORM_NO_DRIVEINFO
6973 static MonoBoolean
6974 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6975                                                 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6976                                                 gint32 *error)
6977 {
6978         gboolean result;
6979         ULARGE_INTEGER wapi_free_bytes_avail;
6980         ULARGE_INTEGER wapi_total_number_of_bytes;
6981         ULARGE_INTEGER wapi_total_number_of_free_bytes;
6982
6983         MONO_ARCH_SAVE_REGS;
6984
6985         *error = ERROR_SUCCESS;
6986         result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6987                                      &wapi_total_number_of_free_bytes);
6988
6989         if (result) {
6990                 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6991                 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6992                 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6993         } else {
6994                 *free_bytes_avail = 0;
6995                 *total_number_of_bytes = 0;
6996                 *total_number_of_free_bytes = 0;
6997                 *error = GetLastError ();
6998         }
6999
7000         return result;
7001 }
7002
7003 static guint32
7004 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7005 {
7006         MONO_ARCH_SAVE_REGS;
7007
7008         return GetDriveType (mono_string_chars (root_path_name));
7009 }
7010 #endif
7011
7012 static gpointer
7013 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
7014 {
7015         MONO_ARCH_SAVE_REGS;
7016
7017         return mono_compile_method (method);
7018 }
7019
7020 static MonoString *
7021 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7022 {
7023         MonoString *mcpath;
7024         gchar *path;
7025
7026         MONO_ARCH_SAVE_REGS;
7027
7028         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7029
7030 #if defined (PLATFORM_WIN32)
7031         /* Avoid mixing '/' and '\\' */
7032         {
7033                 gint i;
7034                 for (i = strlen (path) - 1; i >= 0; i--)
7035                         if (path [i] == '/')
7036                                 path [i] = '\\';
7037         }
7038 #endif
7039         mcpath = mono_string_new (mono_domain_get (), path);
7040         g_free (path);
7041
7042         return mcpath;
7043 }
7044
7045 static MonoString *
7046 get_bundled_machine_config (void)
7047 {
7048         const gchar *machine_config;
7049
7050         MONO_ARCH_SAVE_REGS;
7051
7052         machine_config = mono_get_machine_config ();
7053
7054         if (!machine_config)
7055                 return NULL;
7056
7057         return mono_string_new (mono_domain_get (), machine_config);
7058 }
7059
7060 static MonoString *
7061 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7062 {
7063         MonoString *ipath;
7064         gchar *path;
7065
7066         MONO_ARCH_SAVE_REGS;
7067
7068         path = g_path_get_dirname (mono_get_config_dir ());
7069
7070 #if defined (PLATFORM_WIN32)
7071         /* Avoid mixing '/' and '\\' */
7072         {
7073                 gint i;
7074                 for (i = strlen (path) - 1; i >= 0; i--)
7075                         if (path [i] == '/')
7076                                 path [i] = '\\';
7077         }
7078 #endif
7079         ipath = mono_string_new (mono_domain_get (), path);
7080         g_free (path);
7081
7082         return ipath;
7083 }
7084
7085 static gboolean
7086 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7087 {
7088         MonoPEResourceDataEntry *entry;
7089         MonoImage *image;
7090
7091         MONO_ARCH_SAVE_REGS;
7092
7093         if (!assembly || !result || !size)
7094                 return FALSE;
7095
7096         *result = NULL;
7097         *size = 0;
7098         image = assembly->assembly->image;
7099         entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7100         if (!entry)
7101                 return FALSE;
7102
7103         *result = mono_image_rva_map (image, entry->rde_data_offset);
7104         if (!(*result)) {
7105                 g_free (entry);
7106                 return FALSE;
7107         }
7108         *size = entry->rde_size;
7109         g_free (entry);
7110         return TRUE;
7111 }
7112
7113 static MonoBoolean
7114 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7115 {
7116         return mono_debug_using_mono_debugger ();
7117 }
7118
7119 static void
7120 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7121 {
7122 #if defined (PLATFORM_WIN32)
7123         OutputDebugString (mono_string_chars (message));
7124 #else
7125         g_warning ("WriteWindowsDebugString called and PLATFORM_WIN32 not defined!\n");
7126 #endif
7127 }
7128
7129 /* Only used for value types */
7130 static MonoObject *
7131 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7132 {
7133         MonoClass *klass;
7134         MonoDomain *domain;
7135         
7136         MONO_ARCH_SAVE_REGS;
7137
7138         domain = mono_object_domain (type);
7139         klass = mono_class_from_mono_type (type->type);
7140
7141         if (mono_class_is_nullable (klass))
7142                 /* No arguments -> null */
7143                 return NULL;
7144
7145         return mono_object_new (domain, klass);
7146 }
7147
7148 static MonoReflectionMethod *
7149 ves_icall_MonoMethod_get_base_definition (MonoReflectionMethod *m)
7150 {
7151         MonoClass *klass, *parent;
7152         MonoMethod *method = m->method;
7153         MonoMethod *result = NULL;
7154
7155         MONO_ARCH_SAVE_REGS;
7156
7157         if (method->klass == NULL)
7158                 return m;
7159
7160         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7161             MONO_CLASS_IS_INTERFACE (method->klass) ||
7162             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7163                 return m;
7164
7165         klass = method->klass;
7166         if (klass->generic_class)
7167                 klass = klass->generic_class->container_class;
7168
7169         /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7170         for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7171                 mono_class_setup_vtable (parent);
7172                 if (parent->vtable_size <= method->slot)
7173                         break;
7174                 klass = parent;
7175         }               
7176
7177         if (klass == method->klass)
7178                 return m;
7179
7180         result = klass->vtable [method->slot];
7181         if (result == NULL) {
7182                 /* It is an abstract method */
7183                 gpointer iter = NULL;
7184                 while ((result = mono_class_get_methods (klass, &iter)))
7185                         if (result->slot == method->slot)
7186                                 break;
7187         }
7188
7189         if (result == NULL)
7190                 return m;
7191
7192         return mono_method_get_object (mono_domain_get (), result, NULL);
7193 }
7194
7195 static MonoString*
7196 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7197 {
7198         MonoMethod *method = m->method;
7199
7200         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7201         return m->name;
7202 }
7203
7204 static void
7205 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7206 {
7207         MONO_ARCH_SAVE_REGS;
7208
7209         iter->sig = *(MonoMethodSignature**)argsp;
7210         
7211         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7212         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7213
7214         iter->next_arg = 0;
7215         /* FIXME: it's not documented what start is exactly... */
7216         if (start) {
7217                 iter->args = start;
7218         } else {
7219                 guint32 i, arg_size;
7220                 gint32 align;
7221                 iter->args = argsp + sizeof (gpointer);
7222 #ifndef MONO_ARCH_REGPARMS
7223                 for (i = 0; i < iter->sig->sentinelpos; ++i) {
7224                         arg_size = mono_type_stack_size (iter->sig->params [i], &align);
7225                         iter->args = (char*)iter->args + arg_size;
7226                 }
7227 #endif
7228         }
7229         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7230
7231         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7232 }
7233
7234 static MonoTypedRef
7235 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7236 {
7237         guint32 i, arg_size;
7238         gint32 align;
7239         MonoTypedRef res;
7240         MONO_ARCH_SAVE_REGS;
7241
7242         i = iter->sig->sentinelpos + iter->next_arg;
7243
7244         g_assert (i < iter->sig->param_count);
7245
7246         res.type = iter->sig->params [i];
7247         res.klass = mono_class_from_mono_type (res.type);
7248         res.value = iter->args;
7249         arg_size = mono_type_stack_size (res.type, &align);
7250 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7251         if (arg_size <= sizeof (gpointer)) {
7252                 int dummy;
7253                 int padding = arg_size - mono_type_size (res.type, &dummy);
7254                 res.value = (guint8*)res.value + padding;
7255         }
7256 #endif
7257         iter->args = (char*)iter->args + arg_size;
7258         iter->next_arg++;
7259
7260         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7261
7262         return res;
7263 }
7264
7265 static MonoTypedRef
7266 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7267 {
7268         guint32 i, arg_size;
7269         gint32 align;
7270         MonoTypedRef res;
7271         MONO_ARCH_SAVE_REGS;
7272
7273         i = iter->sig->sentinelpos + iter->next_arg;
7274
7275         g_assert (i < iter->sig->param_count);
7276
7277         while (i < iter->sig->param_count) {
7278                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7279                         continue;
7280                 res.type = iter->sig->params [i];
7281                 res.klass = mono_class_from_mono_type (res.type);
7282                 /* FIXME: endianess issue... */
7283                 res.value = iter->args;
7284                 arg_size = mono_type_stack_size (res.type, &align);
7285                 iter->args = (char*)iter->args + arg_size;
7286                 iter->next_arg++;
7287                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7288                 return res;
7289         }
7290         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7291
7292         res.type = NULL;
7293         res.value = NULL;
7294         res.klass = NULL;
7295         return res;
7296 }
7297
7298 static MonoType*
7299 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7300 {
7301         gint i;
7302         MONO_ARCH_SAVE_REGS;
7303         
7304         i = iter->sig->sentinelpos + iter->next_arg;
7305
7306         g_assert (i < iter->sig->param_count);
7307
7308         return iter->sig->params [i];
7309 }
7310
7311 static MonoObject*
7312 mono_TypedReference_ToObject (MonoTypedRef tref)
7313 {
7314         MONO_ARCH_SAVE_REGS;
7315
7316         if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7317                 MonoObject** objp = tref.value;
7318                 return *objp;
7319         }
7320
7321         return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7322 }
7323
7324 static MonoObject*
7325 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7326 {
7327         MONO_ARCH_SAVE_REGS;
7328
7329         if (MONO_TYPE_IS_REFERENCE (type)) {
7330                 MonoObject** objp = value;
7331                 return *objp;
7332         }
7333
7334         return mono_value_box (mono_domain_get (), klass, value);
7335 }
7336
7337 static void
7338 prelink_method (MonoMethod *method)
7339 {
7340         const char *exc_class, *exc_arg;
7341         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7342                 return;
7343         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7344         if (exc_class) {
7345                 mono_raise_exception( 
7346                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7347         }
7348         /* create the wrapper, too? */
7349 }
7350
7351 static void
7352 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7353 {
7354         MONO_ARCH_SAVE_REGS;
7355         prelink_method (method->method);
7356 }
7357
7358 static void
7359 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7360 {
7361         MonoClass *klass = mono_class_from_mono_type (type->type);
7362         MonoMethod* m;
7363         gpointer iter = NULL;
7364         MONO_ARCH_SAVE_REGS;
7365
7366         while ((m = mono_class_get_methods (klass, &iter)))
7367                 prelink_method (m);
7368 }
7369
7370 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7371 static void
7372 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7373                                             gint32 const **exponents,
7374                                             gunichar2 const **digitLowerTable,
7375                                             gunichar2 const **digitUpperTable,
7376                                             gint64 const **tenPowersList,
7377                                             gint32 const **decHexDigits)
7378 {
7379         *mantissas = Formatter_MantissaBitsTable;
7380         *exponents = Formatter_TensExponentTable;
7381         *digitLowerTable = Formatter_DigitLowerTable;
7382         *digitUpperTable = Formatter_DigitUpperTable;
7383         *tenPowersList = Formatter_TenPowersList;
7384         *decHexDigits = Formatter_DecHexDigits;
7385 }
7386
7387 /* These parameters are "readonly" in corlib/System/Char.cs */
7388 static void
7389 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7390                                             guint8 const **numeric_data,
7391                                             gdouble const **numeric_data_values,
7392                                             guint16 const **to_lower_data_low,
7393                                             guint16 const **to_lower_data_high,
7394                                             guint16 const **to_upper_data_low,
7395                                             guint16 const **to_upper_data_high)
7396 {
7397         *category_data = CategoryData;
7398         *numeric_data = NumericData;
7399         *numeric_data_values = NumericDataValues;
7400         *to_lower_data_low = ToLowerDataLow;
7401         *to_lower_data_high = ToLowerDataHigh;
7402         *to_upper_data_low = ToUpperDataLow;
7403         *to_upper_data_high = ToUpperDataHigh;
7404 }
7405
7406 static gint32
7407 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7408 {
7409         return method->method->token;
7410 }
7411
7412 /*
7413  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7414  * and avoid useless allocations.
7415  */
7416 static MonoArray*
7417 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7418 {
7419         MonoArray *res;
7420         int i, count = 0;
7421         for (i = 0; i < type->num_mods; ++i) {
7422                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7423                         count++;
7424         }
7425         if (!count)
7426                 return NULL;
7427         res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7428         count = 0;
7429         for (i = 0; i < type->num_mods; ++i) {
7430                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7431                         MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7432                         mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7433                         count++;
7434                 }
7435         }
7436         return res;
7437 }
7438
7439 static MonoArray*
7440 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7441 {
7442         MonoType *type = param->ClassImpl->type;
7443         MonoReflectionMethod *method = (MonoReflectionMethod*)param->MemberImpl;
7444         MonoImage *image = method->method->klass->image;
7445         int pos = param->PositionImpl;
7446         MonoMethodSignature *sig = mono_method_signature (method->method);
7447         if (pos == -1)
7448                 type = sig->ret;
7449         else
7450                 type = sig->params [pos];
7451
7452         return type_array_from_modifiers (image, type, optional);
7453 }
7454
7455 static MonoType*
7456 get_property_type (MonoProperty *prop)
7457 {
7458         MonoMethodSignature *sig;
7459         if (prop->get) {
7460                 sig = mono_method_signature (prop->get);
7461                 return sig->ret;
7462         } else if (prop->set) {
7463                 sig = mono_method_signature (prop->set);
7464                 return sig->params [sig->param_count - 1];
7465         }
7466         return NULL;
7467 }
7468
7469 static MonoArray*
7470 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7471 {
7472         MonoType *type = get_property_type (property->property);
7473         MonoImage *image = property->klass->image;
7474
7475         if (!type)
7476                 return NULL;
7477         return type_array_from_modifiers (image, type, optional);
7478 }
7479
7480 static MonoBoolean
7481 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7482 {
7483         MonoCustomAttrInfo *cinfo;
7484         gboolean found;
7485
7486         cinfo = mono_reflection_get_custom_attrs_info (obj);
7487         if (!cinfo)
7488                 return FALSE;
7489         found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7490         if (!cinfo->cached)
7491                 mono_custom_attrs_free (cinfo);
7492         return found;
7493 }
7494
7495 static MonoArray*
7496 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7497 {
7498         MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7499
7500         if (mono_loader_get_last_error ()) {
7501                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7502                 g_assert_not_reached ();
7503         } else {
7504                 return res;
7505         }
7506 }
7507
7508 static MonoBoolean
7509 GCHandle_CheckCurrentDomain (guint32 gchandle)
7510 {
7511         return mono_gchandle_is_in_domain (gchandle, mono_domain_get ());
7512 }
7513
7514 static MonoString*
7515 ves_icall_Mono_Runtime_GetDisplayName (void)
7516 {
7517         static const char display_name_str [] = "Mono " VERSION;
7518         MonoString *display_name = mono_string_new (mono_domain_get (), display_name_str);
7519         return display_name;
7520 }
7521
7522 static MonoString*
7523 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7524 {
7525         MonoString *message;
7526         guint32 ret;
7527         gunichar2 buf[256];
7528         
7529         ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7530                              FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7531                              buf, 255, NULL);
7532         if (ret == 0) {
7533                 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7534         } else {
7535                 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7536         }
7537         
7538         return message;
7539 }
7540
7541 const static guchar
7542 dbase64 [] = {
7543         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7544         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7545         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7546         52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7547         128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7548         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7549         128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7550         41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7551 };
7552
7553 static MonoArray *
7554 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7555 {
7556         gint ignored;
7557         gint i;
7558         gunichar2 c;
7559         gunichar2 last, prev_last, prev2_last;
7560         gint olength;
7561         MonoArray *result;
7562         guchar *res_ptr;
7563         gint a [4], b [4];
7564         MonoException *exc;
7565
7566         ignored = 0;
7567         last = prev_last = 0, prev2_last = 0;
7568         for (i = 0; i < ilength; i++) {
7569                 c = start [i];
7570                 if (c >= sizeof (dbase64)) {
7571                         exc = mono_exception_from_name_msg (mono_get_corlib (),
7572                                 "System", "FormatException",
7573                                 "Invalid character found.");
7574                         mono_raise_exception (exc);
7575                 } else if (isspace (c)) {
7576                         ignored++;
7577                 } else {
7578                         prev2_last = prev_last;
7579                         prev_last = last;
7580                         last = c;
7581                 }
7582         }
7583
7584         olength = ilength - ignored;
7585
7586         if (allowWhitespaceOnly && olength == 0) {
7587                 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7588         }
7589
7590         if ((olength & 3) != 0 || olength <= 0) {
7591                 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7592                                         "FormatException", "Invalid length.");
7593                 mono_raise_exception (exc);
7594         }
7595
7596         if (prev2_last == '=') {
7597                 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7598                 mono_raise_exception (exc);
7599         }
7600
7601         olength = (olength * 3) / 4;
7602         if (last == '=')
7603                 olength--;
7604
7605         if (prev_last == '=')
7606                 olength--;
7607
7608         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7609         res_ptr = mono_array_addr (result, guchar, 0);
7610         for (i = 0; i < ilength; ) {
7611                 int k;
7612
7613                 for (k = 0; k < 4 && i < ilength;) {
7614                         c = start [i++];
7615                         if (isspace (c))
7616                                 continue;
7617
7618                         a [k] = (guchar) c;
7619                         if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7620                                 exc = mono_exception_from_name_msg (mono_get_corlib (),
7621                                         "System", "FormatException",
7622                                         "Invalid character found.");
7623                                 mono_raise_exception (exc);
7624                         }
7625                         k++;
7626                 }
7627
7628                 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7629                 if (a [2] != '=')
7630                         *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7631                 if (a [3] != '=')
7632                         *res_ptr++ = (b [2] << 6) | b [3];
7633
7634                 while (i < ilength && isspace (start [i]))
7635                         i++;
7636         }
7637
7638         return result;
7639 }
7640
7641 static MonoArray *
7642 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7643 {
7644         MONO_ARCH_SAVE_REGS;
7645
7646         return base64_to_byte_array (mono_string_chars (str), 
7647                 mono_string_length (str), allowWhitespaceOnly);
7648 }
7649
7650 static MonoArray *
7651 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7652 {
7653         MONO_ARCH_SAVE_REGS;
7654
7655         return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7656                 length, FALSE);
7657 }
7658
7659 #define ICALL_TYPE(id,name,first)
7660 #define ICALL(id,name,func) Icall_ ## id,
7661
7662 enum {
7663 #include "metadata/icall-def.h"
7664         Icall_last
7665 };
7666
7667 #undef ICALL_TYPE
7668 #undef ICALL
7669 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7670 #define ICALL(id,name,func)
7671 enum {
7672 #include "metadata/icall-def.h"
7673         Icall_type_num
7674 };
7675
7676 #undef ICALL_TYPE
7677 #undef ICALL
7678 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7679 #define ICALL(id,name,func)
7680 typedef struct {
7681         guint16 first_icall;
7682 } IcallTypeDesc;
7683
7684 static const IcallTypeDesc
7685 icall_type_descs [] = {
7686 #include "metadata/icall-def.h"
7687         {Icall_last}
7688 };
7689
7690 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7691
7692 #undef ICALL_TYPE
7693 #define ICALL_TYPE(id,name,first)
7694 #undef ICALL
7695
7696 #ifdef HAVE_ARRAY_ELEM_INIT
7697 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7698 #define MSGSTRFIELD1(line) str##line
7699
7700 static const struct msgstrtn_t {
7701 #define ICALL(id,name,func)
7702 #undef ICALL_TYPE
7703 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7704 #include "metadata/icall-def.h"
7705 #undef ICALL_TYPE
7706 } icall_type_names_str = {
7707 #define ICALL_TYPE(id,name,first) (name),
7708 #include "metadata/icall-def.h"
7709 #undef ICALL_TYPE
7710 };
7711 static const guint16 icall_type_names_idx [] = {
7712 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7713 #include "metadata/icall-def.h"
7714 #undef ICALL_TYPE
7715 };
7716 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7717
7718 static const struct msgstr_t {
7719 #undef ICALL
7720 #define ICALL_TYPE(id,name,first)
7721 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7722 #include "metadata/icall-def.h"
7723 #undef ICALL
7724 } icall_names_str = {
7725 #define ICALL(id,name,func) (name),
7726 #include "metadata/icall-def.h"
7727 #undef ICALL
7728 };
7729 static const guint16 icall_names_idx [] = {
7730 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7731 #include "metadata/icall-def.h"
7732 #undef ICALL
7733 };
7734 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7735
7736 #else
7737
7738 #undef ICALL_TYPE
7739 #undef ICALL
7740 #define ICALL_TYPE(id,name,first) name,
7741 #define ICALL(id,name,func)
7742 static const char* const
7743 icall_type_names [] = {
7744 #include "metadata/icall-def.h"
7745         NULL
7746 };
7747
7748 #define icall_type_name_get(id) (icall_type_names [(id)])
7749
7750 #undef ICALL_TYPE
7751 #undef ICALL
7752 #define ICALL_TYPE(id,name,first)
7753 #define ICALL(id,name,func) name,
7754 static const char* const
7755 icall_names [] = {
7756 #include "metadata/icall-def.h"
7757         NULL
7758 };
7759 #define icall_name_get(id) icall_names [(id)]
7760
7761 #endif /* !HAVE_ARRAY_ELEM_INIT */
7762
7763 #undef ICALL_TYPE
7764 #undef ICALL
7765 #define ICALL_TYPE(id,name,first)
7766 #define ICALL(id,name,func) func,
7767 static const gconstpointer
7768 icall_functions [] = {
7769 #include "metadata/icall-def.h"
7770         NULL
7771 };
7772
7773 static GHashTable *icall_hash = NULL;
7774 static GHashTable *jit_icall_hash_name = NULL;
7775 static GHashTable *jit_icall_hash_addr = NULL;
7776
7777 void
7778 mono_icall_init (void)
7779 {
7780         int i = 0;
7781
7782         /* check that tables are sorted: disable in release */
7783         if (TRUE) {
7784                 int j;
7785                 const char *prev_class = NULL;
7786                 const char *prev_method;
7787                 
7788                 for (i = 0; i < Icall_type_num; ++i) {
7789                         const IcallTypeDesc *desc;
7790                         int num_icalls;
7791                         prev_method = NULL;
7792                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7793                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7794                         prev_class = icall_type_name_get (i);
7795                         desc = &icall_type_descs [i];
7796                         num_icalls = icall_desc_num_icalls (desc);
7797                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7798                         for (j = 0; j < num_icalls; ++j) {
7799                                 const char *methodn = icall_name_get (desc->first_icall + j);
7800                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
7801                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
7802                                 prev_method = methodn;
7803                         }
7804                 }
7805         }
7806
7807         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7808 }
7809
7810 void
7811 mono_icall_cleanup (void)
7812 {
7813         g_hash_table_destroy (icall_hash);
7814         g_hash_table_destroy (jit_icall_hash_name);
7815         g_hash_table_destroy (jit_icall_hash_addr);
7816 }
7817
7818 void
7819 mono_add_internal_call (const char *name, gconstpointer method)
7820 {
7821         mono_loader_lock ();
7822
7823         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7824
7825         mono_loader_unlock ();
7826 }
7827
7828 #ifdef HAVE_ARRAY_ELEM_INIT
7829 static int
7830 compare_method_imap (const void *key, const void *elem)
7831 {
7832         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7833         return strcmp (key, method_name);
7834 }
7835
7836 static gpointer
7837 find_method_icall (const IcallTypeDesc *imap, const char *name)
7838 {
7839         const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7840         if (!nameslot)
7841                 return NULL;
7842         return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7843 }
7844
7845 static int
7846 compare_class_imap (const void *key, const void *elem)
7847 {
7848         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7849         return strcmp (key, class_name);
7850 }
7851
7852 static const IcallTypeDesc*
7853 find_class_icalls (const char *name)
7854 {
7855         const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7856         if (!nameslot)
7857                 return NULL;
7858         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7859 }
7860
7861 #else
7862 static int
7863 compare_method_imap (const void *key, const void *elem)
7864 {
7865         const char** method_name = (const char**)elem;
7866         return strcmp (key, *method_name);
7867 }
7868
7869 static gpointer
7870 find_method_icall (const IcallTypeDesc *imap, const char *name)
7871 {
7872         const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7873         if (!nameslot)
7874                 return NULL;
7875         return (gpointer)icall_functions [(nameslot - icall_names)];
7876 }
7877
7878 static int
7879 compare_class_imap (const void *key, const void *elem)
7880 {
7881         const char** class_name = (const char**)elem;
7882         return strcmp (key, *class_name);
7883 }
7884
7885 static const IcallTypeDesc*
7886 find_class_icalls (const char *name)
7887 {
7888         const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7889         if (!nameslot)
7890                 return NULL;
7891         return &icall_type_descs [nameslot - icall_type_names];
7892 }
7893
7894 #endif
7895
7896 /* 
7897  * we should probably export this as an helper (handle nested types).
7898  * Returns the number of chars written in buf.
7899  */
7900 static int
7901 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7902 {
7903         int nspacelen, cnamelen;
7904         nspacelen = strlen (klass->name_space);
7905         cnamelen = strlen (klass->name);
7906         if (nspacelen + cnamelen + 2 > bufsize)
7907                 return 0;
7908         if (nspacelen) {
7909                 memcpy (buf, klass->name_space, nspacelen);
7910                 buf [nspacelen ++] = '.';
7911         }
7912         memcpy (buf + nspacelen, klass->name, cnamelen);
7913         buf [nspacelen + cnamelen] = 0;
7914         return nspacelen + cnamelen;
7915 }
7916
7917 gpointer
7918 mono_lookup_internal_call (MonoMethod *method)
7919 {
7920         char *sigstart;
7921         char *tmpsig;
7922         char mname [2048];
7923         int typelen = 0, mlen, siglen;
7924         gpointer res;
7925         const IcallTypeDesc *imap;
7926
7927         g_assert (method != NULL);
7928
7929         if (method->is_inflated)
7930                 method = ((MonoMethodInflated *) method)->declaring;
7931
7932         if (method->klass->nested_in) {
7933                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7934                 if (!pos)
7935                         return NULL;
7936
7937                 mname [pos++] = '/';
7938                 mname [pos] = 0;
7939
7940                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7941                 if (!typelen)
7942                         return NULL;
7943
7944                 typelen += pos;
7945         } else {
7946                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7947                 if (!typelen)
7948                         return NULL;
7949         }
7950
7951         imap = find_class_icalls (mname);
7952
7953         mname [typelen] = ':';
7954         mname [typelen + 1] = ':';
7955
7956         mlen = strlen (method->name);
7957         memcpy (mname + typelen + 2, method->name, mlen);
7958         sigstart = mname + typelen + 2 + mlen;
7959         *sigstart = 0;
7960
7961         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7962         siglen = strlen (tmpsig);
7963         if (typelen + mlen + siglen + 6 > sizeof (mname))
7964                 return NULL;
7965         sigstart [0] = '(';
7966         memcpy (sigstart + 1, tmpsig, siglen);
7967         sigstart [siglen + 1] = ')';
7968         sigstart [siglen + 2] = 0;
7969         g_free (tmpsig);
7970         
7971         mono_loader_lock ();
7972
7973         res = g_hash_table_lookup (icall_hash, mname);
7974         if (res) {
7975                 mono_loader_unlock ();
7976                 return res;
7977         }
7978         /* try without signature */
7979         *sigstart = 0;
7980         res = g_hash_table_lookup (icall_hash, mname);
7981         if (res) {
7982                 mono_loader_unlock ();
7983                 return res;
7984         }
7985
7986         /* it wasn't found in the static call tables */
7987         if (!imap) {
7988                 mono_loader_unlock ();
7989                 return NULL;
7990         }
7991         res = find_method_icall (imap, sigstart - mlen);
7992         if (res) {
7993                 mono_loader_unlock ();
7994                 return res;
7995         }
7996         /* try _with_ signature */
7997         *sigstart = '(';
7998         res = find_method_icall (imap, sigstart - mlen);
7999         if (res) {
8000                 mono_loader_unlock ();
8001                 return res;
8002         }
8003
8004         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8005         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8006         g_print ("The out of sync library is: %s\n", method->klass->image->name);
8007         g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8008         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");
8009         g_print ("If you see other errors or faults after this message they are probably related\n");
8010         g_print ("and you need to fix your mono install first.\n");
8011
8012         mono_loader_unlock ();
8013
8014         return NULL;
8015 }
8016
8017 static MonoType*
8018 type_from_typename (char *typename)
8019 {
8020         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
8021
8022         if (!strcmp (typename, "int"))
8023                 klass = mono_defaults.int_class;
8024         else if (!strcmp (typename, "ptr"))
8025                 klass = mono_defaults.int_class;
8026         else if (!strcmp (typename, "void"))
8027                 klass = mono_defaults.void_class;
8028         else if (!strcmp (typename, "int32"))
8029                 klass = mono_defaults.int32_class;
8030         else if (!strcmp (typename, "uint32"))
8031                 klass = mono_defaults.uint32_class;
8032         else if (!strcmp (typename, "int8"))
8033                 klass = mono_defaults.sbyte_class;
8034         else if (!strcmp (typename, "uint8"))
8035                 klass = mono_defaults.byte_class;
8036         else if (!strcmp (typename, "int16"))
8037                 klass = mono_defaults.int16_class;
8038         else if (!strcmp (typename, "uint16"))
8039                 klass = mono_defaults.uint16_class;
8040         else if (!strcmp (typename, "long"))
8041                 klass = mono_defaults.int64_class;
8042         else if (!strcmp (typename, "ulong"))
8043                 klass = mono_defaults.uint64_class;
8044         else if (!strcmp (typename, "float"))
8045                 klass = mono_defaults.single_class;
8046         else if (!strcmp (typename, "double"))
8047                 klass = mono_defaults.double_class;
8048         else if (!strcmp (typename, "object"))
8049                 klass = mono_defaults.object_class;
8050         else if (!strcmp (typename, "obj"))
8051                 klass = mono_defaults.object_class;
8052         else if (!strcmp (typename, "string"))
8053                 klass = mono_defaults.string_class;
8054         else if (!strcmp (typename, "bool"))
8055                 klass = mono_defaults.boolean_class;
8056         else if (!strcmp (typename, "boolean"))
8057                 klass = mono_defaults.boolean_class;
8058         else {
8059                 g_error ("%s", typename);
8060                 g_assert_not_reached ();
8061         }
8062         return &klass->byval_arg;
8063 }
8064
8065 MonoMethodSignature*
8066 mono_create_icall_signature (const char *sigstr)
8067 {
8068         gchar **parts;
8069         int i, len;
8070         gchar **tmp;
8071         MonoMethodSignature *res;
8072
8073         mono_loader_lock ();
8074         res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8075         if (res) {
8076                 mono_loader_unlock ();
8077                 return res;
8078         }
8079
8080         parts = g_strsplit (sigstr, " ", 256);
8081
8082         tmp = parts;
8083         len = 0;
8084         while (*tmp) {
8085                 len ++;
8086                 tmp ++;
8087         }
8088
8089         res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8090         res->pinvoke = 1;
8091
8092 #ifdef PLATFORM_WIN32
8093         /* 
8094          * Under windows, the default pinvoke calling convention is STDCALL but
8095          * we need CDECL.
8096          */
8097         res->call_convention = MONO_CALL_C;
8098 #endif
8099
8100         res->ret = type_from_typename (parts [0]);
8101         for (i = 1; i < len; ++i) {
8102                 res->params [i - 1] = type_from_typename (parts [i]);
8103         }
8104
8105         g_strfreev (parts);
8106
8107         g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8108
8109         mono_loader_unlock ();
8110
8111         return res;
8112 }
8113
8114 MonoJitICallInfo *
8115 mono_find_jit_icall_by_name (const char *name)
8116 {
8117         MonoJitICallInfo *info;
8118         g_assert (jit_icall_hash_name);
8119
8120         mono_loader_lock ();
8121         info = g_hash_table_lookup (jit_icall_hash_name, name);
8122         mono_loader_unlock ();
8123         return info;
8124 }
8125
8126 MonoJitICallInfo *
8127 mono_find_jit_icall_by_addr (gconstpointer addr)
8128 {
8129         MonoJitICallInfo *info;
8130         g_assert (jit_icall_hash_addr);
8131
8132         mono_loader_lock ();
8133         info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8134         mono_loader_unlock ();
8135
8136         return info;
8137 }
8138
8139 /*
8140  * mono_get_jit_icall_info:
8141  *
8142  *   Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8143  * caller should access it while holding the loader lock.
8144  */
8145 GHashTable*
8146 mono_get_jit_icall_info (void)
8147 {
8148         return jit_icall_hash_name;
8149 }
8150
8151 void
8152 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8153 {
8154         mono_loader_lock ();
8155         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8156         mono_loader_unlock ();
8157 }
8158
8159 MonoJitICallInfo *
8160 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8161 {
8162         MonoJitICallInfo *info;
8163         
8164         g_assert (func);
8165         g_assert (name);
8166
8167         mono_loader_lock ();
8168
8169         if (!jit_icall_hash_name) {
8170                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8171                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8172         }
8173
8174         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8175                 g_warning ("jit icall already defined \"%s\"\n", name);
8176                 g_assert_not_reached ();
8177         }
8178
8179         info = g_new0 (MonoJitICallInfo, 1);
8180         
8181         info->name = name;
8182         info->func = func;
8183         info->sig = sig;
8184
8185         if (is_save) {
8186                 info->wrapper = func;
8187         } else {
8188                 info->wrapper = NULL;
8189         }
8190
8191         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8192         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8193
8194         mono_loader_unlock ();
8195         return info;
8196 }