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