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