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