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