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