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