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