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