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