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