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