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