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