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