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