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