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