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