Merge pull request #778 from cmorris98/master
[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 (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 (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 (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 (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 (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 (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)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 ICALL_EXPORT gpointer
6122 ves_icall_System_Object_obj_address (MonoObject *this) 
6123 {
6124         MONO_ARCH_SAVE_REGS;
6125
6126         return this;
6127 }
6128
6129 /* System.Buffer */
6130
6131 static inline gint32 
6132 mono_array_get_byte_length (MonoArray *array)
6133 {
6134         MonoClass *klass;
6135         int length;
6136         int i;
6137
6138         klass = array->obj.vtable->klass;
6139
6140         if (array->bounds == NULL)
6141                 length = array->max_length;
6142         else {
6143                 length = 1;
6144                 for (i = 0; i < klass->rank; ++ i)
6145                         length *= array->bounds [i].length;
6146         }
6147
6148         switch (klass->element_class->byval_arg.type) {
6149         case MONO_TYPE_I1:
6150         case MONO_TYPE_U1:
6151         case MONO_TYPE_BOOLEAN:
6152                 return length;
6153         case MONO_TYPE_I2:
6154         case MONO_TYPE_U2:
6155         case MONO_TYPE_CHAR:
6156                 return length << 1;
6157         case MONO_TYPE_I4:
6158         case MONO_TYPE_U4:
6159         case MONO_TYPE_R4:
6160                 return length << 2;
6161         case MONO_TYPE_I:
6162         case MONO_TYPE_U:
6163                 return length * sizeof (gpointer);
6164         case MONO_TYPE_I8:
6165         case MONO_TYPE_U8:
6166         case MONO_TYPE_R8:
6167                 return length << 3;
6168         default:
6169                 return -1;
6170         }
6171 }
6172
6173 ICALL_EXPORT gint32 
6174 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array) 
6175 {
6176         MONO_ARCH_SAVE_REGS;
6177
6178         return mono_array_get_byte_length (array);
6179 }
6180
6181 ICALL_EXPORT gint8 
6182 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx) 
6183 {
6184         MONO_ARCH_SAVE_REGS;
6185
6186         return mono_array_get (array, gint8, idx);
6187 }
6188
6189 ICALL_EXPORT void 
6190 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value) 
6191 {
6192         MONO_ARCH_SAVE_REGS;
6193
6194         mono_array_set (array, gint8, idx, value);
6195 }
6196
6197 ICALL_EXPORT MonoBoolean
6198 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count) 
6199 {
6200         guint8 *src_buf, *dest_buf;
6201
6202         MONO_ARCH_SAVE_REGS;
6203
6204         /* This is called directly from the class libraries without going through the managed wrapper */
6205         MONO_CHECK_ARG_NULL (src);
6206         MONO_CHECK_ARG_NULL (dest);
6207
6208         /* watch out for integer overflow */
6209         if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6210                 return FALSE;
6211
6212         src_buf = (guint8 *)src->vector + src_offset;
6213         dest_buf = (guint8 *)dest->vector + dest_offset;
6214
6215         if (src != dest)
6216                 memcpy (dest_buf, src_buf, count);
6217         else
6218                 mono_gc_memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6219
6220         return TRUE;
6221 }
6222
6223 #ifndef DISABLE_REMOTING
6224 ICALL_EXPORT MonoObject *
6225 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6226 {
6227         MonoDomain *domain = mono_object_domain (this); 
6228         MonoObject *res;
6229         MonoRealProxy *rp = ((MonoRealProxy *)this);
6230         MonoTransparentProxy *tp;
6231         MonoType *type;
6232         MonoClass *klass;
6233
6234         MONO_ARCH_SAVE_REGS;
6235
6236         res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6237         tp = (MonoTransparentProxy*) res;
6238         
6239         MONO_OBJECT_SETREF (tp, rp, rp);
6240         type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6241         klass = mono_class_from_mono_type (type);
6242
6243         tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6244         tp->remote_class = mono_remote_class (domain, class_name, klass);
6245
6246         res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6247         return res;
6248 }
6249
6250 ICALL_EXPORT MonoReflectionType *
6251 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6252 {
6253         return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6254 }
6255 #endif
6256
6257 /* System.Environment */
6258
6259 MonoString*
6260 ves_icall_System_Environment_get_UserName (void)
6261 {
6262         MONO_ARCH_SAVE_REGS;
6263
6264         /* using glib is more portable */
6265         return mono_string_new (mono_domain_get (), g_get_user_name ());
6266 }
6267
6268
6269 ICALL_EXPORT MonoString *
6270 ves_icall_System_Environment_get_MachineName (void)
6271 {
6272 #if defined (HOST_WIN32)
6273         gunichar2 *buf;
6274         guint32 len;
6275         MonoString *result;
6276
6277         len = MAX_COMPUTERNAME_LENGTH + 1;
6278         buf = g_new (gunichar2, len);
6279
6280         result = NULL;
6281         if (GetComputerName (buf, (PDWORD) &len))
6282                 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6283
6284         g_free (buf);
6285         return result;
6286 #elif !defined(DISABLE_SOCKETS)
6287         gchar buf [256];
6288         MonoString *result;
6289
6290         if (gethostname (buf, sizeof (buf)) == 0)
6291                 result = mono_string_new (mono_domain_get (), buf);
6292         else
6293                 result = NULL;
6294         
6295         return result;
6296 #else
6297         return mono_string_new (mono_domain_get (), "mono");
6298 #endif
6299 }
6300
6301 ICALL_EXPORT int
6302 ves_icall_System_Environment_get_Platform (void)
6303 {
6304 #if defined (TARGET_WIN32)
6305         /* Win32NT */
6306         return 2;
6307 #elif defined(__MACH__)
6308         /* OSX */
6309         //
6310         // Notice that the value is hidden from user code, and only exposed
6311         // to mscorlib.   This is due to Mono's Unix/MacOS code predating the
6312         // define and making assumptions based on Unix/128/4 values before there
6313         // was a MacOS define.    Lots of code would assume that not-Unix meant
6314         // Windows, but in this case, it would be OSX. 
6315         //
6316         return 6;
6317 #else
6318         /* Unix */
6319         return 4;
6320 #endif
6321 }
6322
6323 ICALL_EXPORT MonoString *
6324 ves_icall_System_Environment_get_NewLine (void)
6325 {
6326         MONO_ARCH_SAVE_REGS;
6327
6328 #if defined (HOST_WIN32)
6329         return mono_string_new (mono_domain_get (), "\r\n");
6330 #else
6331         return mono_string_new (mono_domain_get (), "\n");
6332 #endif
6333 }
6334
6335 ICALL_EXPORT MonoString *
6336 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6337 {
6338         const gchar *value;
6339         gchar *utf8_name;
6340
6341         MONO_ARCH_SAVE_REGS;
6342
6343         if (name == NULL)
6344                 return NULL;
6345
6346         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6347         value = g_getenv (utf8_name);
6348
6349         g_free (utf8_name);
6350
6351         if (value == 0)
6352                 return NULL;
6353         
6354         return mono_string_new (mono_domain_get (), value);
6355 }
6356
6357 /*
6358  * There is no standard way to get at environ.
6359  */
6360 #ifndef _MSC_VER
6361 #ifndef __MINGW32_VERSION
6362 #if defined(__APPLE__) && !defined (__arm__)
6363 /* Apple defines this in crt_externs.h but doesn't provide that header for 
6364  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
6365  * in fact exist on all implementations (so far) 
6366  */
6367 gchar ***_NSGetEnviron(void);
6368 #define environ (*_NSGetEnviron())
6369 #else
6370 extern
6371 char **environ;
6372 #endif
6373 #endif
6374 #endif
6375
6376 ICALL_EXPORT MonoArray *
6377 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6378 {
6379 #ifdef HOST_WIN32
6380         MonoArray *names;
6381         MonoDomain *domain;
6382         MonoString *str;
6383         WCHAR* env_strings;
6384         WCHAR* env_string;
6385         WCHAR* equal_str;
6386         int n = 0;
6387
6388         env_strings = GetEnvironmentStrings();
6389
6390         if (env_strings) {
6391                 env_string = env_strings;
6392                 while (*env_string != '\0') {
6393                 /* weird case that MS seems to skip */
6394                         if (*env_string != '=')
6395                                 n++;
6396                         while (*env_string != '\0')
6397                                 env_string++;
6398                         env_string++;
6399                 }
6400         }
6401
6402         domain = mono_domain_get ();
6403         names = mono_array_new (domain, mono_defaults.string_class, n);
6404
6405         if (env_strings) {
6406                 n = 0;
6407                 env_string = env_strings;
6408                 while (*env_string != '\0') {
6409                         /* weird case that MS seems to skip */
6410                         if (*env_string != '=') {
6411                                 equal_str = wcschr(env_string, '=');
6412                                 g_assert(equal_str);
6413                                 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6414                                 mono_array_setref (names, n, str);
6415                                 n++;
6416                         }
6417                         while (*env_string != '\0')
6418                                 env_string++;
6419                         env_string++;
6420                 }
6421
6422                 FreeEnvironmentStrings (env_strings);
6423         }
6424
6425         return names;
6426
6427 #else
6428         MonoArray *names;
6429         MonoDomain *domain;
6430         MonoString *str;
6431         gchar **e, **parts;
6432         int n;
6433
6434         MONO_ARCH_SAVE_REGS;
6435
6436         n = 0;
6437         for (e = environ; *e != 0; ++ e)
6438                 ++ n;
6439
6440         domain = mono_domain_get ();
6441         names = mono_array_new (domain, mono_defaults.string_class, n);
6442
6443         n = 0;
6444         for (e = environ; *e != 0; ++ e) {
6445                 parts = g_strsplit (*e, "=", 2);
6446                 if (*parts != 0) {
6447                         str = mono_string_new (domain, *parts);
6448                         mono_array_setref (names, n, str);
6449                 }
6450
6451                 g_strfreev (parts);
6452
6453                 ++ n;
6454         }
6455
6456         return names;
6457 #endif
6458 }
6459
6460 /*
6461  * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6462  */
6463 #if !GLIB_CHECK_VERSION(2,4,0)
6464 #define g_setenv(a,b,c)   setenv(a,b,c)
6465 #define g_unsetenv(a) unsetenv(a)
6466 #endif
6467
6468 ICALL_EXPORT void
6469 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6470 {
6471         MonoError error;
6472 #ifdef HOST_WIN32
6473
6474         gunichar2 *utf16_name, *utf16_value;
6475 #else
6476         gchar *utf8_name, *utf8_value;
6477 #endif
6478
6479         MONO_ARCH_SAVE_REGS;
6480         
6481 #ifdef HOST_WIN32
6482         utf16_name = mono_string_to_utf16 (name);
6483         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6484                 SetEnvironmentVariable (utf16_name, NULL);
6485                 g_free (utf16_name);
6486                 return;
6487         }
6488
6489         utf16_value = mono_string_to_utf16 (value);
6490
6491         SetEnvironmentVariable (utf16_name, utf16_value);
6492
6493         g_free (utf16_name);
6494         g_free (utf16_value);
6495 #else
6496         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6497
6498         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6499                 g_unsetenv (utf8_name);
6500                 g_free (utf8_name);
6501                 return;
6502         }
6503
6504         utf8_value = mono_string_to_utf8_checked (value, &error);
6505         if (!mono_error_ok (&error)) {
6506                 g_free (utf8_name);
6507                 mono_error_raise_exception (&error);
6508         }
6509         g_setenv (utf8_name, utf8_value, TRUE);
6510
6511         g_free (utf8_name);
6512         g_free (utf8_value);
6513 #endif
6514 }
6515
6516 ICALL_EXPORT void
6517 ves_icall_System_Environment_Exit (int result)
6518 {
6519         MONO_ARCH_SAVE_REGS;
6520
6521         mono_environment_exitcode_set (result);
6522
6523 /* FIXME: There are some cleanup hangs that should be worked out, but
6524  * if the program is going to exit, everything will be cleaned up when
6525  * NaCl exits anyway.
6526  */
6527 #ifndef __native_client__
6528         if (!mono_runtime_try_shutdown ())
6529                 mono_thread_exit ();
6530
6531         /* Suspend all managed threads since the runtime is going away */
6532         mono_thread_suspend_all_other_threads ();
6533
6534         mono_runtime_quit ();
6535 #endif
6536
6537         /* we may need to do some cleanup here... */
6538         exit (result);
6539 }
6540
6541 ICALL_EXPORT MonoString*
6542 ves_icall_System_Environment_GetGacPath (void)
6543 {
6544         return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6545 }
6546
6547 ICALL_EXPORT MonoString*
6548 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6549 {
6550 #if defined (HOST_WIN32)
6551         #ifndef CSIDL_FLAG_CREATE
6552                 #define CSIDL_FLAG_CREATE       0x8000
6553         #endif
6554
6555         WCHAR path [MAX_PATH];
6556         /* Create directory if no existing */
6557         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6558                 int len = 0;
6559                 while (path [len])
6560                         ++ len;
6561                 return mono_string_new_utf16 (mono_domain_get (), path, len);
6562         }
6563 #else
6564         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6565 #endif
6566         return mono_string_new (mono_domain_get (), "");
6567 }
6568
6569 ICALL_EXPORT MonoArray *
6570 ves_icall_System_Environment_GetLogicalDrives (void)
6571 {
6572         gunichar2 buf [256], *ptr, *dname;
6573         gunichar2 *u16;
6574         guint initial_size = 127, size = 128;
6575         gint ndrives;
6576         MonoArray *result;
6577         MonoString *drivestr;
6578         MonoDomain *domain = mono_domain_get ();
6579         gint len;
6580
6581         MONO_ARCH_SAVE_REGS;
6582
6583         buf [0] = '\0';
6584         ptr = buf;
6585
6586         while (size > initial_size) {
6587                 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6588                 if (size > initial_size) {
6589                         if (ptr != buf)
6590                                 g_free (ptr);
6591                         ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6592                         initial_size = size;
6593                         size++;
6594                 }
6595         }
6596
6597         /* Count strings */
6598         dname = ptr;
6599         ndrives = 0;
6600         do {
6601                 while (*dname++);
6602                 ndrives++;
6603         } while (*dname);
6604
6605         dname = ptr;
6606         result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6607         ndrives = 0;
6608         do {
6609                 len = 0;
6610                 u16 = dname;
6611                 while (*u16) { u16++; len ++; }
6612                 drivestr = mono_string_new_utf16 (domain, dname, len);
6613                 mono_array_setref (result, ndrives++, drivestr);
6614                 while (*dname++);
6615         } while (*dname);
6616
6617         if (ptr != buf)
6618                 g_free (ptr);
6619
6620         return result;
6621 }
6622
6623 ICALL_EXPORT MonoString *
6624 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6625 {
6626         gunichar2 volume_name [MAX_PATH + 1];
6627         
6628         if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6629                 return NULL;
6630         return mono_string_from_utf16 (volume_name);
6631 }
6632
6633 ICALL_EXPORT MonoString *
6634 ves_icall_System_Environment_InternalGetHome (void)
6635 {
6636         MONO_ARCH_SAVE_REGS;
6637
6638         return mono_string_new (mono_domain_get (), g_get_home_dir ());
6639 }
6640
6641 static const char *encodings [] = {
6642         (char *) 1,
6643                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6644                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6645                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6646         (char *) 2,
6647                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6648                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6649                 "x_unicode_2_0_utf_7",
6650         (char *) 3,
6651                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6652                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6653         (char *) 4,
6654                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6655                 "iso_10646_ucs2",
6656         (char *) 5,
6657                 "unicodefffe", "utf_16be",
6658         (char *) 6,
6659                 "iso_8859_1",
6660         (char *) 0
6661 };
6662
6663 /*
6664  * Returns the internal codepage, if the value of "int_code_page" is
6665  * 1 at entry, and we can not compute a suitable code page number,
6666  * returns the code page as a string
6667  */
6668 ICALL_EXPORT MonoString*
6669 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page) 
6670 {
6671         const char *cset;
6672         const char *p;
6673         char *c;
6674         char *codepage = NULL;
6675         int code;
6676         int want_name = *int_code_page;
6677         int i;
6678         
6679         *int_code_page = -1;
6680         MONO_ARCH_SAVE_REGS;
6681
6682         g_get_charset (&cset);
6683         c = codepage = strdup (cset);
6684         for (c = codepage; *c; c++){
6685                 if (isascii (*c) && isalpha (*c))
6686                         *c = tolower (*c);
6687                 if (*c == '-')
6688                         *c = '_';
6689         }
6690         /* g_print ("charset: %s\n", cset); */
6691         
6692         /* handle some common aliases */
6693         p = encodings [0];
6694         code = 0;
6695         for (i = 0; p != 0; ){
6696                 if ((gssize) p < 7){
6697                         code = (gssize) p;
6698                         p = encodings [++i];
6699                         continue;
6700                 }
6701                 if (strcmp (p, codepage) == 0){
6702                         *int_code_page = code;
6703                         break;
6704                 }
6705                 p = encodings [++i];
6706         }
6707         
6708         if (strstr (codepage, "utf_8") != NULL)
6709                 *int_code_page |= 0x10000000;
6710         free (codepage);
6711         
6712         if (want_name && *int_code_page == -1)
6713                 return mono_string_new (mono_domain_get (), cset);
6714         else
6715                 return NULL;
6716 }
6717
6718 ICALL_EXPORT MonoBoolean
6719 ves_icall_System_Environment_get_HasShutdownStarted (void)
6720 {
6721         if (mono_runtime_is_shutting_down ())
6722                 return TRUE;
6723
6724         if (mono_domain_is_unloading (mono_domain_get ()))
6725                 return TRUE;
6726
6727         return FALSE;
6728 }
6729
6730 ICALL_EXPORT void
6731 ves_icall_System_Environment_BroadcastSettingChange (void)
6732 {
6733 #ifdef HOST_WIN32
6734         SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6735 #endif
6736 }
6737
6738 ICALL_EXPORT void
6739 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this, 
6740                                          MonoReflectionMethod *method,
6741                                          MonoArray *out_args)
6742 {
6743         MONO_ARCH_SAVE_REGS;
6744
6745         mono_message_init (mono_object_domain (this), this, method, out_args);
6746 }
6747
6748 #ifndef DISABLE_REMOTING
6749 ICALL_EXPORT MonoBoolean
6750 ves_icall_IsTransparentProxy (MonoObject *proxy)
6751 {
6752         MONO_ARCH_SAVE_REGS;
6753
6754         if (!proxy)
6755                 return 0;
6756
6757         if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6758                 return 1;
6759
6760         return 0;
6761 }
6762
6763 ICALL_EXPORT MonoReflectionMethod *
6764 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6765         MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6766 {
6767         MonoClass *klass;
6768         MonoMethod *method;
6769         MonoMethod **vtable;
6770         MonoMethod *res = NULL;
6771
6772         MONO_CHECK_ARG_NULL (rtype);
6773         MONO_CHECK_ARG_NULL (rmethod);
6774
6775         method = rmethod->method;
6776         klass = mono_class_from_mono_type (rtype->type);
6777         mono_class_init_or_throw (klass);
6778
6779         if (MONO_CLASS_IS_INTERFACE (klass))
6780                 return NULL;
6781
6782         if (method->flags & METHOD_ATTRIBUTE_STATIC)
6783                 return NULL;
6784
6785         if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6786                 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6787                         return rmethod;
6788                 else
6789                         return NULL;
6790         }
6791
6792         mono_class_setup_vtable (klass);
6793         vtable = klass->vtable;
6794
6795         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6796                 gboolean variance_used = FALSE;
6797                 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6798                 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6799                 if (offs >= 0)
6800                         res = vtable [offs + method->slot];
6801         } else {
6802                 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6803                         return NULL;
6804
6805                 if (method->slot != -1)
6806                         res = vtable [method->slot];
6807         }
6808
6809         if (!res)
6810                 return NULL;
6811
6812         return mono_method_get_object (mono_domain_get (), res, NULL);
6813 }
6814
6815 ICALL_EXPORT void
6816 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6817 {
6818         MonoClass *klass;
6819         MonoVTable* vtable;
6820
6821         MONO_ARCH_SAVE_REGS;
6822
6823         klass = mono_class_from_mono_type (type->type);
6824         vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6825
6826         mono_vtable_set_is_remote (vtable, enable);
6827 }
6828
6829 #else /* DISABLE_REMOTING */
6830
6831 ICALL_EXPORT void
6832 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6833 {
6834         g_assert_not_reached ();
6835 }
6836
6837 #endif
6838
6839 ICALL_EXPORT MonoObject *
6840 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6841 {
6842         MonoClass *klass;
6843         MonoDomain *domain;
6844         
6845         MONO_ARCH_SAVE_REGS;
6846
6847         domain = mono_object_domain (type);
6848         klass = mono_class_from_mono_type (type->type);
6849         mono_class_init_or_throw (klass);
6850
6851         if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6852                 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6853
6854         if (klass->rank >= 1) {
6855                 g_assert (klass->rank == 1);
6856                 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6857         } else {
6858                 /* Bypass remoting object creation check */
6859                 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6860         }
6861 }
6862
6863 ICALL_EXPORT MonoString *
6864 ves_icall_System_IO_get_temp_path (void)
6865 {
6866         MONO_ARCH_SAVE_REGS;
6867
6868         return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6869 }
6870
6871 #ifndef PLATFORM_NO_DRIVEINFO
6872 ICALL_EXPORT MonoBoolean
6873 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6874                                                 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6875                                                 gint32 *error)
6876 {
6877         gboolean result;
6878         ULARGE_INTEGER wapi_free_bytes_avail;
6879         ULARGE_INTEGER wapi_total_number_of_bytes;
6880         ULARGE_INTEGER wapi_total_number_of_free_bytes;
6881
6882         MONO_ARCH_SAVE_REGS;
6883
6884         *error = ERROR_SUCCESS;
6885         result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6886                                      &wapi_total_number_of_free_bytes);
6887
6888         if (result) {
6889                 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6890                 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6891                 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6892         } else {
6893                 *free_bytes_avail = 0;
6894                 *total_number_of_bytes = 0;
6895                 *total_number_of_free_bytes = 0;
6896                 *error = GetLastError ();
6897         }
6898
6899         return result;
6900 }
6901
6902 ICALL_EXPORT guint32
6903 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6904 {
6905         MONO_ARCH_SAVE_REGS;
6906
6907         return GetDriveType (mono_string_chars (root_path_name));
6908 }
6909 #endif
6910
6911 ICALL_EXPORT gpointer
6912 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6913 {
6914         MONO_ARCH_SAVE_REGS;
6915
6916         return mono_compile_method (method);
6917 }
6918
6919 ICALL_EXPORT MonoString *
6920 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6921 {
6922         MonoString *mcpath;
6923         gchar *path;
6924
6925         MONO_ARCH_SAVE_REGS;
6926
6927         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6928
6929 #if defined (HOST_WIN32)
6930         /* Avoid mixing '/' and '\\' */
6931         {
6932                 gint i;
6933                 for (i = strlen (path) - 1; i >= 0; i--)
6934                         if (path [i] == '/')
6935                                 path [i] = '\\';
6936         }
6937 #endif
6938         mcpath = mono_string_new (mono_domain_get (), path);
6939         g_free (path);
6940
6941         return mcpath;
6942 }
6943
6944 static MonoString *
6945 get_bundled_app_config (void)
6946 {
6947         const gchar *app_config;
6948         MonoDomain *domain;
6949         MonoString *file;
6950         gchar *config_file_name, *config_file_path;
6951         gsize len;
6952         gchar *module;
6953
6954         MONO_ARCH_SAVE_REGS;
6955
6956         domain = mono_domain_get ();
6957         file = domain->setup->configuration_file;
6958         if (!file)
6959                 return NULL;
6960
6961         // Retrieve config file and remove the extension
6962         config_file_name = mono_string_to_utf8 (file);
6963         config_file_path = mono_portability_find_file (config_file_name, TRUE);
6964         if (!config_file_path)
6965                 config_file_path = config_file_name;
6966         len = strlen (config_file_path) - strlen (".config");
6967         module = g_malloc0 (len + 1);
6968         memcpy (module, config_file_path, len);
6969         // Get the config file from the module name
6970         app_config = mono_config_string_for_assembly_file (module);
6971         // Clean-up
6972         g_free (module);
6973         if (config_file_name != config_file_path)
6974                 g_free (config_file_name);
6975         g_free (config_file_path);
6976
6977         if (!app_config)
6978                 return NULL;
6979
6980         return mono_string_new (mono_domain_get (), app_config);
6981 }
6982
6983 static MonoString *
6984 get_bundled_machine_config (void)
6985 {
6986         const gchar *machine_config;
6987
6988         MONO_ARCH_SAVE_REGS;
6989
6990         machine_config = mono_get_machine_config ();
6991
6992         if (!machine_config)
6993                 return NULL;
6994
6995         return mono_string_new (mono_domain_get (), machine_config);
6996 }
6997
6998 ICALL_EXPORT MonoString *
6999 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7000 {
7001         MonoString *ipath;
7002         gchar *path;
7003
7004         MONO_ARCH_SAVE_REGS;
7005
7006         path = g_path_get_dirname (mono_get_config_dir ());
7007
7008 #if defined (HOST_WIN32)
7009         /* Avoid mixing '/' and '\\' */
7010         {
7011                 gint i;
7012                 for (i = strlen (path) - 1; i >= 0; i--)
7013                         if (path [i] == '/')
7014                                 path [i] = '\\';
7015         }
7016 #endif
7017         ipath = mono_string_new (mono_domain_get (), path);
7018         g_free (path);
7019
7020         return ipath;
7021 }
7022
7023 ICALL_EXPORT gboolean
7024 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7025 {
7026         MonoPEResourceDataEntry *entry;
7027         MonoImage *image;
7028
7029         MONO_ARCH_SAVE_REGS;
7030
7031         if (!assembly || !result || !size)
7032                 return FALSE;
7033
7034         *result = NULL;
7035         *size = 0;
7036         image = assembly->assembly->image;
7037         entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7038         if (!entry)
7039                 return FALSE;
7040
7041         *result = mono_image_rva_map (image, entry->rde_data_offset);
7042         if (!(*result)) {
7043                 g_free (entry);
7044                 return FALSE;
7045         }
7046         *size = entry->rde_size;
7047         g_free (entry);
7048         return TRUE;
7049 }
7050
7051 ICALL_EXPORT MonoBoolean
7052 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7053 {
7054         return mono_is_debugger_attached ();
7055 }
7056
7057 ICALL_EXPORT MonoBoolean
7058 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7059 {
7060         if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7061                 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7062         else
7063                 return FALSE;
7064 }
7065
7066 ICALL_EXPORT void
7067 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7068 {
7069         if (mono_get_runtime_callbacks ()->debug_log)
7070                 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7071 }
7072
7073 ICALL_EXPORT void
7074 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7075 {
7076 #if defined (HOST_WIN32)
7077         OutputDebugString (mono_string_chars (message));
7078 #else
7079         g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7080 #endif
7081 }
7082
7083 /* Only used for value types */
7084 ICALL_EXPORT MonoObject *
7085 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7086 {
7087         MonoClass *klass;
7088         MonoDomain *domain;
7089         
7090         MONO_ARCH_SAVE_REGS;
7091
7092         domain = mono_object_domain (type);
7093         klass = mono_class_from_mono_type (type->type);
7094         mono_class_init_or_throw (klass);
7095
7096         if (mono_class_is_nullable (klass))
7097                 /* No arguments -> null */
7098                 return NULL;
7099
7100         return mono_object_new (domain, klass);
7101 }
7102
7103 ICALL_EXPORT MonoReflectionMethod *
7104 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7105 {
7106         MonoClass *klass, *parent;
7107         MonoMethod *method = m->method;
7108         MonoMethod *result = NULL;
7109         int slot;
7110
7111         MONO_ARCH_SAVE_REGS;
7112
7113         if (method->klass == NULL)
7114                 return m;
7115
7116         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7117             MONO_CLASS_IS_INTERFACE (method->klass) ||
7118             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7119                 return m;
7120
7121         slot = mono_method_get_vtable_slot (method);
7122         if (slot == -1)
7123                 return m;
7124
7125         klass = method->klass;
7126         if (klass->generic_class)
7127                 klass = klass->generic_class->container_class;
7128
7129         if (definition) {
7130                 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7131                 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7132                         mono_class_setup_vtable (parent);
7133                         if (parent->vtable_size <= slot)
7134                                 break;
7135                         klass = parent;
7136                 }
7137         } else {
7138                 klass = klass->parent;
7139                 if (!klass)
7140                         return m;
7141         }
7142
7143         if (klass == method->klass)
7144                 return m;
7145
7146         /*This is possible if definition == FALSE.
7147          * Do it here to be really sure we don't read invalid memory.
7148          */
7149         if (slot >= klass->vtable_size)
7150                 return m;
7151
7152         mono_class_setup_vtable (klass);
7153
7154         result = klass->vtable [slot];
7155         if (result == NULL) {
7156                 /* It is an abstract method */
7157                 gpointer iter = NULL;
7158                 while ((result = mono_class_get_methods (klass, &iter)))
7159                         if (result->slot == slot)
7160                                 break;
7161         }
7162
7163         if (result == NULL)
7164                 return m;
7165
7166         return mono_method_get_object (mono_domain_get (), result, NULL);
7167 }
7168
7169 ICALL_EXPORT MonoString*
7170 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7171 {
7172         MonoMethod *method = m->method;
7173
7174         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7175         return m->name;
7176 }
7177
7178 ICALL_EXPORT void
7179 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7180 {
7181         MONO_ARCH_SAVE_REGS;
7182
7183         iter->sig = *(MonoMethodSignature**)argsp;
7184         
7185         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7186         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7187
7188         iter->next_arg = 0;
7189         /* FIXME: it's not documented what start is exactly... */
7190         if (start) {
7191                 iter->args = start;
7192         } else {
7193                 iter->args = argsp + sizeof (gpointer);
7194         }
7195         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7196
7197         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7198 }
7199
7200 ICALL_EXPORT MonoTypedRef
7201 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7202 {
7203         guint32 i, arg_size;
7204         gint32 align;
7205         MonoTypedRef res;
7206         MONO_ARCH_SAVE_REGS;
7207
7208         i = iter->sig->sentinelpos + iter->next_arg;
7209
7210         g_assert (i < iter->sig->param_count);
7211
7212         res.type = iter->sig->params [i];
7213         res.klass = mono_class_from_mono_type (res.type);
7214         arg_size = mono_type_stack_size (res.type, &align);
7215 #if defined(__arm__) || defined(__mips__)
7216         iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7217 #endif
7218         res.value = iter->args;
7219 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7220         /* Values are stored as 8 byte register sized objects, but 'value'
7221          * is dereferenced as a pointer in other routines.
7222          */
7223         res.value = (char*)res.value + 4;
7224 #endif
7225 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7226         if (arg_size <= sizeof (gpointer)) {
7227                 int dummy;
7228                 int padding = arg_size - mono_type_size (res.type, &dummy);
7229                 res.value = (guint8*)res.value + padding;
7230         }
7231 #endif
7232         iter->args = (char*)iter->args + arg_size;
7233         iter->next_arg++;
7234
7235         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7236
7237         return res;
7238 }
7239
7240 ICALL_EXPORT MonoTypedRef
7241 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7242 {
7243         guint32 i, arg_size;
7244         gint32 align;
7245         MonoTypedRef res;
7246         MONO_ARCH_SAVE_REGS;
7247
7248         i = iter->sig->sentinelpos + iter->next_arg;
7249
7250         g_assert (i < iter->sig->param_count);
7251
7252         while (i < iter->sig->param_count) {
7253                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7254                         continue;
7255                 res.type = iter->sig->params [i];
7256                 res.klass = mono_class_from_mono_type (res.type);
7257                 /* FIXME: endianess issue... */
7258                 arg_size = mono_type_stack_size (res.type, &align);
7259 #if defined(__arm__) || defined(__mips__)
7260                 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7261 #endif
7262                 res.value = iter->args;
7263                 iter->args = (char*)iter->args + arg_size;
7264                 iter->next_arg++;
7265                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7266                 return res;
7267         }
7268         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7269
7270         res.type = NULL;
7271         res.value = NULL;
7272         res.klass = NULL;
7273         return res;
7274 }
7275
7276 ICALL_EXPORT MonoType*
7277 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7278 {
7279         gint i;
7280         MONO_ARCH_SAVE_REGS;
7281         
7282         i = iter->sig->sentinelpos + iter->next_arg;
7283
7284         g_assert (i < iter->sig->param_count);
7285
7286         return iter->sig->params [i];
7287 }
7288
7289 ICALL_EXPORT MonoObject*
7290 mono_TypedReference_ToObject (MonoTypedRef tref)
7291 {
7292         MONO_ARCH_SAVE_REGS;
7293
7294         if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7295                 MonoObject** objp = tref.value;
7296                 return *objp;
7297         }
7298
7299         return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7300 }
7301
7302 ICALL_EXPORT MonoObject*
7303 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7304 {
7305         MONO_ARCH_SAVE_REGS;
7306
7307         if (MONO_TYPE_IS_REFERENCE (type)) {
7308                 MonoObject** objp = value;
7309                 return *objp;
7310         }
7311
7312         return mono_value_box (mono_domain_get (), klass, value);
7313 }
7314
7315 static void
7316 prelink_method (MonoMethod *method)
7317 {
7318         const char *exc_class, *exc_arg;
7319         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7320                 return;
7321         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7322         if (exc_class) {
7323                 mono_raise_exception( 
7324                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7325         }
7326         /* create the wrapper, too? */
7327 }
7328
7329 ICALL_EXPORT void
7330 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7331 {
7332         MONO_ARCH_SAVE_REGS;
7333         prelink_method (method->method);
7334 }
7335
7336 ICALL_EXPORT void
7337 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7338 {
7339         MonoClass *klass = mono_class_from_mono_type (type->type);
7340         MonoMethod* m;
7341         gpointer iter = NULL;
7342         MONO_ARCH_SAVE_REGS;
7343
7344         mono_class_init_or_throw (klass);
7345
7346         while ((m = mono_class_get_methods (klass, &iter)))
7347                 prelink_method (m);
7348 }
7349
7350 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7351 ICALL_EXPORT void
7352 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7353                                             gint32 const **exponents,
7354                                             gunichar2 const **digitLowerTable,
7355                                             gunichar2 const **digitUpperTable,
7356                                             gint64 const **tenPowersList,
7357                                             gint32 const **decHexDigits)
7358 {
7359         *mantissas = Formatter_MantissaBitsTable;
7360         *exponents = Formatter_TensExponentTable;
7361         *digitLowerTable = Formatter_DigitLowerTable;
7362         *digitUpperTable = Formatter_DigitUpperTable;
7363         *tenPowersList = Formatter_TenPowersList;
7364         *decHexDigits = Formatter_DecHexDigits;
7365 }
7366
7367 ICALL_EXPORT void
7368 get_category_data (int version,
7369                    guint8 const **category_data,
7370                    guint16 const **category_astral_index)
7371 {
7372         *category_astral_index = NULL;
7373
7374 #ifndef DISABLE_NET_4_0
7375         if (version == 4) {
7376                 *category_data = CategoryData_v4;
7377 #ifndef DISABLE_ASTRAL
7378                 *category_astral_index = CategoryData_v4_astral_index;
7379 #endif
7380                 return;
7381         }
7382 #endif
7383
7384         *category_data = CategoryData_v2;
7385 #ifndef DISABLE_ASTRAL
7386         *category_astral_index = CategoryData_v2_astral_index;
7387 #endif
7388 }
7389
7390 /* These parameters are "readonly" in corlib/System/Char.cs */
7391 ICALL_EXPORT void
7392 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7393                                             guint8 const **category_data,
7394                                             guint16 const **category_astral_index,
7395                                             guint8 const **numeric_data,
7396                                             gdouble const **numeric_data_values,
7397                                             guint16 const **to_lower_data_low,
7398                                             guint16 const **to_lower_data_high,
7399                                             guint16 const **to_upper_data_low,
7400                                             guint16 const **to_upper_data_high)
7401 {
7402         get_category_data (category_data_version, category_data, category_astral_index);
7403         *numeric_data = NumericData;
7404         *numeric_data_values = NumericDataValues;
7405         *to_lower_data_low = ToLowerDataLow;
7406         *to_lower_data_high = ToLowerDataHigh;
7407         *to_upper_data_low = ToUpperDataLow;
7408         *to_upper_data_high = ToUpperDataHigh;
7409 }
7410
7411 ICALL_EXPORT gint32
7412 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7413 {
7414         return method->method->token;
7415 }
7416
7417 /*
7418  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7419  * and avoid useless allocations.
7420  */
7421 static MonoArray*
7422 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7423 {
7424         MonoArray *res;
7425         int i, count = 0;
7426         for (i = 0; i < type->num_mods; ++i) {
7427                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7428                         count++;
7429         }
7430         if (!count)
7431                 return NULL;
7432         res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7433         count = 0;
7434         for (i = 0; i < type->num_mods; ++i) {
7435                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7436                         MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7437                         mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7438                         count++;
7439                 }
7440         }
7441         return res;
7442 }
7443
7444 ICALL_EXPORT MonoArray*
7445 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7446 {
7447         MonoType *type = param->ClassImpl->type;
7448         MonoClass *member_class = mono_object_class (param->MemberImpl);
7449         MonoMethod *method = NULL;
7450         MonoImage *image;
7451         int pos;
7452         MonoMethodSignature *sig;
7453
7454         if (mono_class_is_reflection_method_or_constructor (member_class)) {
7455                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7456                 method = rmethod->method;
7457         } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7458                 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7459                 if (!(method = prop->property->get))
7460                         method = prop->property->set;
7461                 g_assert (method);      
7462         } else {
7463                 char *type_name = mono_type_get_full_name (member_class);
7464                 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7465                 MonoException *ex = mono_get_exception_not_supported  (msg);
7466                 g_free (type_name);
7467                 g_free (msg);
7468                 mono_raise_exception (ex);
7469         }
7470
7471         image = method->klass->image;
7472         pos = param->PositionImpl;
7473         sig = mono_method_signature (method);
7474         if (pos == -1)
7475                 type = sig->ret;
7476         else
7477                 type = sig->params [pos];
7478
7479         return type_array_from_modifiers (image, type, optional);
7480 }
7481
7482 static MonoType*
7483 get_property_type (MonoProperty *prop)
7484 {
7485         MonoMethodSignature *sig;
7486         if (prop->get) {
7487                 sig = mono_method_signature (prop->get);
7488                 return sig->ret;
7489         } else if (prop->set) {
7490                 sig = mono_method_signature (prop->set);
7491                 return sig->params [sig->param_count - 1];
7492         }
7493         return NULL;
7494 }
7495
7496 ICALL_EXPORT MonoArray*
7497 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7498 {
7499         MonoType *type = get_property_type (property->property);
7500         MonoImage *image = property->klass->image;
7501
7502         if (!type)
7503                 return NULL;
7504         return type_array_from_modifiers (image, type, optional);
7505 }
7506
7507 /*
7508  *Construct a MonoType suited to be used to decode a constant blob object.
7509  *
7510  * @type is the target type which will be constructed
7511  * @blob_type is the blob type, for example, that comes from the constant table
7512  * @real_type is the expected constructed type.
7513  */
7514 static void
7515 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7516 {
7517         type->type = blob_type;
7518         type->data.klass = NULL;
7519         if (blob_type == MONO_TYPE_CLASS)
7520                 type->data.klass = mono_defaults.object_class;
7521         else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7522                 /* For enums, we need to use the base type */
7523                 type->type = MONO_TYPE_VALUETYPE;
7524                 type->data.klass = mono_class_from_mono_type (real_type);
7525         } else
7526                 type->data.klass = mono_class_from_mono_type (real_type);
7527 }
7528
7529 ICALL_EXPORT MonoObject*
7530 property_info_get_default_value (MonoReflectionProperty *property)
7531 {
7532         MonoType blob_type;
7533         MonoProperty *prop = property->property;
7534         MonoType *type = get_property_type (prop);
7535         MonoDomain *domain = mono_object_domain (property); 
7536         MonoTypeEnum def_type;
7537         const char *def_value;
7538         MonoObject *o;
7539
7540         mono_class_init (prop->parent);
7541
7542         if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7543                 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7544
7545         def_value = mono_class_get_property_default_value (prop, &def_type);
7546
7547         mono_type_from_blob_type (&blob_type, def_type, type);
7548         o = mono_get_object_from_blob (domain, &blob_type, def_value);
7549
7550         return o;
7551 }
7552
7553 ICALL_EXPORT MonoBoolean
7554 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7555 {
7556         MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7557         MonoCustomAttrInfo *cinfo;
7558         gboolean found;
7559
7560         mono_class_init_or_throw (attr_class);
7561
7562         cinfo = mono_reflection_get_custom_attrs_info (obj);
7563         if (!cinfo)
7564                 return FALSE;
7565         found = mono_custom_attrs_has_attr (cinfo, attr_class);
7566         if (!cinfo->cached)
7567                 mono_custom_attrs_free (cinfo);
7568         return found;
7569 }
7570
7571 ICALL_EXPORT MonoArray*
7572 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7573 {
7574         MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7575         MonoArray *res;
7576         MonoError error;
7577
7578         if (attr_class)
7579                 mono_class_init_or_throw (attr_class);
7580
7581         res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7582         if (!mono_error_ok (&error))
7583                 mono_error_raise_exception (&error);
7584         if (mono_loader_get_last_error ()) {
7585                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7586                 g_assert_not_reached ();
7587                 /* Not reached */
7588                 return NULL;
7589         } else {
7590                 return res;
7591         }
7592 }
7593
7594 ICALL_EXPORT MonoString*
7595 ves_icall_Mono_Runtime_GetDisplayName (void)
7596 {
7597         char *info;
7598         MonoString *display_name;
7599
7600         info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7601         display_name = mono_string_new (mono_domain_get (), info);
7602         g_free (info);
7603         return display_name;
7604 }
7605
7606 ICALL_EXPORT MonoString*
7607 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7608 {
7609         MonoString *message;
7610         guint32 ret;
7611         gunichar2 buf[256];
7612         
7613         ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7614                              FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7615                              buf, 255, NULL);
7616         if (ret == 0) {
7617                 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7618         } else {
7619                 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7620         }
7621         
7622         return message;
7623 }
7624
7625 const static guchar
7626 dbase64 [] = {
7627         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7628         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7629         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7630         52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7631         128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7632         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7633         128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7634         41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7635 };
7636
7637 static MonoArray *
7638 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7639 {
7640         gint ignored;
7641         gint i;
7642         gunichar2 c;
7643         gunichar2 last, prev_last, prev2_last;
7644         gint olength;
7645         MonoArray *result;
7646         guchar *res_ptr;
7647         gint a [4], b [4];
7648         MonoException *exc;
7649
7650         int havePadding = 0;
7651         ignored = 0;
7652         last = prev_last = 0, prev2_last = 0;
7653         for (i = 0; i < ilength; i++) {
7654                 c = start [i];
7655                 if (c >= sizeof (dbase64)) {
7656                         exc = mono_exception_from_name_msg (mono_get_corlib (),
7657                                 "System", "FormatException",
7658                                 "Invalid character found.");
7659                         mono_raise_exception (exc);
7660                 } else if (isspace (c)) {
7661                         ignored++;
7662                 } else if (havePadding && c != '=') {
7663                         exc = mono_exception_from_name_msg (mono_get_corlib (),
7664                                 "System", "FormatException",
7665                                 "Invalid character found.");
7666                         mono_raise_exception (exc);
7667                 } else {
7668                         if (c == '=') havePadding = 1;
7669                         prev2_last = prev_last;
7670                         prev_last = last;
7671                         last = c;
7672                 }
7673         }
7674
7675         olength = ilength - ignored;
7676
7677         if (allowWhitespaceOnly && olength == 0) {
7678                 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7679         }
7680
7681         if ((olength & 3) != 0 || olength <= 0) {
7682                 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7683                                         "FormatException", "Invalid length.");
7684                 mono_raise_exception (exc);
7685         }
7686
7687         if (prev2_last == '=') {
7688                 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7689                 mono_raise_exception (exc);
7690         }
7691
7692         olength = (olength * 3) / 4;
7693         if (last == '=')
7694                 olength--;
7695
7696         if (prev_last == '=')
7697                 olength--;
7698
7699         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7700         res_ptr = mono_array_addr (result, guchar, 0);
7701         for (i = 0; i < ilength; ) {
7702                 int k;
7703
7704                 for (k = 0; k < 4 && i < ilength;) {
7705                         c = start [i++];
7706                         if (isspace (c))
7707                                 continue;
7708
7709                         a [k] = (guchar) c;
7710                         if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7711                                 exc = mono_exception_from_name_msg (mono_get_corlib (),
7712                                         "System", "FormatException",
7713                                         "Invalid character found.");
7714                                 mono_raise_exception (exc);
7715                         }
7716                         k++;
7717                 }
7718
7719                 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7720                 if (a [2] != '=')
7721                         *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7722                 if (a [3] != '=')
7723                         *res_ptr++ = (b [2] << 6) | b [3];
7724
7725                 while (i < ilength && isspace (start [i]))
7726                         i++;
7727         }
7728
7729         return result;
7730 }
7731
7732 ICALL_EXPORT MonoArray *
7733 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7734 {
7735         MONO_ARCH_SAVE_REGS;
7736
7737         return base64_to_byte_array (mono_string_chars (str), 
7738                 mono_string_length (str), allowWhitespaceOnly);
7739 }
7740
7741 ICALL_EXPORT MonoArray *
7742 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7743 {
7744         MONO_ARCH_SAVE_REGS;
7745
7746         return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7747                 length, FALSE);
7748 }
7749
7750 #ifndef DISABLE_ICALL_TABLES
7751
7752 #define ICALL_TYPE(id,name,first)
7753 #define ICALL(id,name,func) Icall_ ## id,
7754
7755 enum {
7756 #include "metadata/icall-def.h"
7757         Icall_last
7758 };
7759
7760 #undef ICALL_TYPE
7761 #undef ICALL
7762 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7763 #define ICALL(id,name,func)
7764 enum {
7765 #include "metadata/icall-def.h"
7766         Icall_type_num
7767 };
7768
7769 #undef ICALL_TYPE
7770 #undef ICALL
7771 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7772 #define ICALL(id,name,func)
7773 typedef struct {
7774         guint16 first_icall;
7775 } IcallTypeDesc;
7776
7777 static const IcallTypeDesc
7778 icall_type_descs [] = {
7779 #include "metadata/icall-def.h"
7780         {Icall_last}
7781 };
7782
7783 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7784
7785 #undef ICALL_TYPE
7786 #define ICALL_TYPE(id,name,first)
7787 #undef ICALL
7788
7789 #ifdef HAVE_ARRAY_ELEM_INIT
7790 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7791 #define MSGSTRFIELD1(line) str##line
7792
7793 static const struct msgstrtn_t {
7794 #define ICALL(id,name,func)
7795 #undef ICALL_TYPE
7796 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7797 #include "metadata/icall-def.h"
7798 #undef ICALL_TYPE
7799 } icall_type_names_str = {
7800 #define ICALL_TYPE(id,name,first) (name),
7801 #include "metadata/icall-def.h"
7802 #undef ICALL_TYPE
7803 };
7804 static const guint16 icall_type_names_idx [] = {
7805 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7806 #include "metadata/icall-def.h"
7807 #undef ICALL_TYPE
7808 };
7809 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7810
7811 static const struct msgstr_t {
7812 #undef ICALL
7813 #define ICALL_TYPE(id,name,first)
7814 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7815 #include "metadata/icall-def.h"
7816 #undef ICALL
7817 } icall_names_str = {
7818 #define ICALL(id,name,func) (name),
7819 #include "metadata/icall-def.h"
7820 #undef ICALL
7821 };
7822 static const guint16 icall_names_idx [] = {
7823 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7824 #include "metadata/icall-def.h"
7825 #undef ICALL
7826 };
7827 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7828
7829 #else
7830
7831 #undef ICALL_TYPE
7832 #undef ICALL
7833 #define ICALL_TYPE(id,name,first) name,
7834 #define ICALL(id,name,func)
7835 static const char* const
7836 icall_type_names [] = {
7837 #include "metadata/icall-def.h"
7838         NULL
7839 };
7840
7841 #define icall_type_name_get(id) (icall_type_names [(id)])
7842
7843 #undef ICALL_TYPE
7844 #undef ICALL
7845 #define ICALL_TYPE(id,name,first)
7846 #define ICALL(id,name,func) name,
7847 static const char* const
7848 icall_names [] = {
7849 #include "metadata/icall-def.h"
7850         NULL
7851 };
7852 #define icall_name_get(id) icall_names [(id)]
7853
7854 #endif /* !HAVE_ARRAY_ELEM_INIT */
7855
7856 #undef ICALL_TYPE
7857 #undef ICALL
7858 #define ICALL_TYPE(id,name,first)
7859 #define ICALL(id,name,func) func,
7860 static const gconstpointer
7861 icall_functions [] = {
7862 #include "metadata/icall-def.h"
7863         NULL
7864 };
7865
7866 #ifdef ENABLE_ICALL_SYMBOL_MAP
7867 #undef ICALL_TYPE
7868 #undef ICALL
7869 #define ICALL_TYPE(id,name,first)
7870 #define ICALL(id,name,func) #func,
7871 static const gconstpointer
7872 icall_symbols [] = {
7873 #include "metadata/icall-def.h"
7874         NULL
7875 };
7876 #endif
7877
7878 #endif /* DISABLE_ICALL_TABLES */
7879
7880 static mono_mutex_t icall_mutex;
7881 static GHashTable *icall_hash = NULL;
7882 static GHashTable *jit_icall_hash_name = NULL;
7883 static GHashTable *jit_icall_hash_addr = NULL;
7884
7885 void
7886 mono_icall_init (void)
7887 {
7888 #ifndef DISABLE_ICALL_TABLES
7889         int i = 0;
7890
7891         /* check that tables are sorted: disable in release */
7892         if (TRUE) {
7893                 int j;
7894                 const char *prev_class = NULL;
7895                 const char *prev_method;
7896                 
7897                 for (i = 0; i < Icall_type_num; ++i) {
7898                         const IcallTypeDesc *desc;
7899                         int num_icalls;
7900                         prev_method = NULL;
7901                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7902                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7903                         prev_class = icall_type_name_get (i);
7904                         desc = &icall_type_descs [i];
7905                         num_icalls = icall_desc_num_icalls (desc);
7906                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7907                         for (j = 0; j < num_icalls; ++j) {
7908                                 const char *methodn = icall_name_get (desc->first_icall + j);
7909                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
7910                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
7911                                 prev_method = methodn;
7912                         }
7913                 }
7914         }
7915 #endif
7916
7917         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7918         mono_mutex_init (&icall_mutex);
7919 }
7920
7921 static void
7922 mono_icall_lock (void)
7923 {
7924         mono_locks_mutex_acquire (&icall_mutex, IcallLock);
7925 }
7926
7927 static void
7928 mono_icall_unlock (void)
7929 {
7930         mono_locks_mutex_release (&icall_mutex, IcallLock);
7931 }
7932
7933 void
7934 mono_icall_cleanup (void)
7935 {
7936         g_hash_table_destroy (icall_hash);
7937         g_hash_table_destroy (jit_icall_hash_name);
7938         g_hash_table_destroy (jit_icall_hash_addr);
7939         mono_mutex_destroy (&icall_mutex);
7940 }
7941
7942 void
7943 mono_add_internal_call (const char *name, gconstpointer method)
7944 {
7945         mono_icall_lock ();
7946
7947         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7948
7949         mono_icall_unlock ();
7950 }
7951
7952 #ifndef DISABLE_ICALL_TABLES
7953
7954 #ifdef HAVE_ARRAY_ELEM_INIT
7955 static int
7956 compare_method_imap (const void *key, const void *elem)
7957 {
7958         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7959         return strcmp (key, method_name);
7960 }
7961
7962 static gpointer
7963 find_method_icall (const IcallTypeDesc *imap, const char *name)
7964 {
7965         const guint16 *nameslot = mono_binary_search (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7966         if (!nameslot)
7967                 return NULL;
7968         return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7969 }
7970
7971 static int
7972 compare_class_imap (const void *key, const void *elem)
7973 {
7974         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7975         return strcmp (key, class_name);
7976 }
7977
7978 static const IcallTypeDesc*
7979 find_class_icalls (const char *name)
7980 {
7981         const guint16 *nameslot = mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7982         if (!nameslot)
7983                 return NULL;
7984         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7985 }
7986
7987 #else /* HAVE_ARRAY_ELEM_INIT */
7988
7989 static int
7990 compare_method_imap (const void *key, const void *elem)
7991 {
7992         const char** method_name = (const char**)elem;
7993         return strcmp (key, *method_name);
7994 }
7995
7996 static gpointer
7997 find_method_icall (const IcallTypeDesc *imap, const char *name)
7998 {
7999         const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8000         if (!nameslot)
8001                 return NULL;
8002         return (gpointer)icall_functions [(nameslot - icall_names)];
8003 }
8004
8005 static int
8006 compare_class_imap (const void *key, const void *elem)
8007 {
8008         const char** class_name = (const char**)elem;
8009         return strcmp (key, *class_name);
8010 }
8011
8012 static const IcallTypeDesc*
8013 find_class_icalls (const char *name)
8014 {
8015         const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8016         if (!nameslot)
8017                 return NULL;
8018         return &icall_type_descs [nameslot - icall_type_names];
8019 }
8020
8021 #endif /* HAVE_ARRAY_ELEM_INIT */
8022
8023 #endif /* DISABLE_ICALL_TABLES */
8024
8025 /* 
8026  * we should probably export this as an helper (handle nested types).
8027  * Returns the number of chars written in buf.
8028  */
8029 static int
8030 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8031 {
8032         int nspacelen, cnamelen;
8033         nspacelen = strlen (klass->name_space);
8034         cnamelen = strlen (klass->name);
8035         if (nspacelen + cnamelen + 2 > bufsize)
8036                 return 0;
8037         if (nspacelen) {
8038                 memcpy (buf, klass->name_space, nspacelen);
8039                 buf [nspacelen ++] = '.';
8040         }
8041         memcpy (buf + nspacelen, klass->name, cnamelen);
8042         buf [nspacelen + cnamelen] = 0;
8043         return nspacelen + cnamelen;
8044 }
8045
8046 #ifdef DISABLE_ICALL_TABLES
8047 static void
8048 no_icall_table (void)
8049 {
8050         g_assert_not_reached ();
8051 }
8052 #endif
8053
8054 gpointer
8055 mono_lookup_internal_call (MonoMethod *method)
8056 {
8057         char *sigstart;
8058         char *tmpsig;
8059         char mname [2048];
8060         int typelen = 0, mlen, siglen;
8061         gpointer res;
8062 #ifndef DISABLE_ICALL_TABLES
8063         const IcallTypeDesc *imap = NULL;
8064 #endif
8065
8066         g_assert (method != NULL);
8067
8068         if (method->is_inflated)
8069                 method = ((MonoMethodInflated *) method)->declaring;
8070
8071         if (method->klass->nested_in) {
8072                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8073                 if (!pos)
8074                         return NULL;
8075
8076                 mname [pos++] = '/';
8077                 mname [pos] = 0;
8078
8079                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8080                 if (!typelen)
8081                         return NULL;
8082
8083                 typelen += pos;
8084         } else {
8085                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8086                 if (!typelen)
8087                         return NULL;
8088         }
8089
8090 #ifndef DISABLE_ICALL_TABLES
8091         imap = find_class_icalls (mname);
8092 #endif
8093
8094         mname [typelen] = ':';
8095         mname [typelen + 1] = ':';
8096
8097         mlen = strlen (method->name);
8098         memcpy (mname + typelen + 2, method->name, mlen);
8099         sigstart = mname + typelen + 2 + mlen;
8100         *sigstart = 0;
8101
8102         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8103         siglen = strlen (tmpsig);
8104         if (typelen + mlen + siglen + 6 > sizeof (mname))
8105                 return NULL;
8106         sigstart [0] = '(';
8107         memcpy (sigstart + 1, tmpsig, siglen);
8108         sigstart [siglen + 1] = ')';
8109         sigstart [siglen + 2] = 0;
8110         g_free (tmpsig);
8111         
8112         mono_icall_lock ();
8113
8114         res = g_hash_table_lookup (icall_hash, mname);
8115         if (res) {
8116                 mono_icall_unlock ();;
8117                 return res;
8118         }
8119         /* try without signature */
8120         *sigstart = 0;
8121         res = g_hash_table_lookup (icall_hash, mname);
8122         if (res) {
8123                 mono_icall_unlock ();
8124                 return res;
8125         }
8126
8127 #ifdef DISABLE_ICALL_TABLES
8128         mono_icall_unlock ();
8129         /* Fail only when the result is actually used */
8130         /* mono_marshal_get_native_wrapper () depends on this */
8131         if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8132                 return ves_icall_System_String_ctor_RedirectToCreateString;
8133         else
8134                 return no_icall_table;
8135 #else
8136         /* it wasn't found in the static call tables */
8137         if (!imap) {
8138                 mono_icall_unlock ();
8139                 return NULL;
8140         }
8141         res = find_method_icall (imap, sigstart - mlen);
8142         if (res) {
8143                 mono_icall_unlock ();
8144                 return res;
8145         }
8146         /* try _with_ signature */
8147         *sigstart = '(';
8148         res = find_method_icall (imap, sigstart - mlen);
8149         if (res) {
8150                 mono_icall_unlock ();
8151                 return res;
8152         }
8153
8154         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8155         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8156         g_print ("The out of sync library is: %s\n", method->klass->image->name);
8157         g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8158         g_print ("Do not report this as a bug unless you're sure you have updated correctly:\nyou probably have a broken mono install.\n");
8159         g_print ("If you see other errors or faults after this message they are probably related\n");
8160         g_print ("and you need to fix your mono install first.\n");
8161
8162         mono_icall_unlock ();
8163
8164         return NULL;
8165 #endif
8166 }
8167
8168 #ifdef ENABLE_ICALL_SYMBOL_MAP
8169 static int
8170 func_cmp (gconstpointer key, gconstpointer p)
8171 {
8172         return (gsize)key - (gsize)*(gsize*)p;
8173 }
8174 #endif
8175
8176 /*
8177  * mono_lookup_icall_symbol:
8178  *
8179  *   Given the icall METHOD, returns its C symbol.
8180  */
8181 const char*
8182 mono_lookup_icall_symbol (MonoMethod *m)
8183 {
8184 #ifdef DISABLE_ICALL_TABLES
8185         g_assert_not_reached ();
8186         return NULL;
8187 #else
8188 #ifdef ENABLE_ICALL_SYMBOL_MAP
8189         gpointer func;
8190         int i;
8191         gpointer slot;
8192         static gconstpointer *functions_sorted;
8193         static const char**symbols_sorted;
8194         static gboolean inited;
8195
8196         if (!inited) {
8197                 gboolean changed;
8198
8199                 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8200                 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8201                 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8202                 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8203                 /* Bubble sort the two arrays */
8204                 changed = TRUE;
8205                 while (changed) {
8206                         changed = FALSE;
8207                         for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8208                                 if (functions_sorted [i] > functions_sorted [i + 1]) {
8209                                         gconstpointer tmp;
8210
8211                                         tmp = functions_sorted [i];
8212                                         functions_sorted [i] = functions_sorted [i + 1];
8213                                         functions_sorted [i + 1] = tmp;
8214                                         tmp = symbols_sorted [i];
8215                                         symbols_sorted [i] = symbols_sorted [i + 1];
8216                                         symbols_sorted [i + 1] = tmp;
8217                                         changed = TRUE;
8218                                 }
8219                         }
8220                 }
8221         }
8222
8223         func = mono_lookup_internal_call (m);
8224         if (!func)
8225                 return NULL;
8226         slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8227         if (!slot)
8228                 return NULL;
8229         g_assert (slot);
8230         return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8231 #else
8232         fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8233         g_assert_not_reached ();
8234         return 0;
8235 #endif
8236 #endif
8237 }
8238
8239 static MonoType*
8240 type_from_typename (char *typename)
8241 {
8242         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
8243
8244         if (!strcmp (typename, "int"))
8245                 klass = mono_defaults.int_class;
8246         else if (!strcmp (typename, "ptr"))
8247                 klass = mono_defaults.int_class;
8248         else if (!strcmp (typename, "void"))
8249                 klass = mono_defaults.void_class;
8250         else if (!strcmp (typename, "int32"))
8251                 klass = mono_defaults.int32_class;
8252         else if (!strcmp (typename, "uint32"))
8253                 klass = mono_defaults.uint32_class;
8254         else if (!strcmp (typename, "int8"))
8255                 klass = mono_defaults.sbyte_class;
8256         else if (!strcmp (typename, "uint8"))
8257                 klass = mono_defaults.byte_class;
8258         else if (!strcmp (typename, "int16"))
8259                 klass = mono_defaults.int16_class;
8260         else if (!strcmp (typename, "uint16"))
8261                 klass = mono_defaults.uint16_class;
8262         else if (!strcmp (typename, "long"))
8263                 klass = mono_defaults.int64_class;
8264         else if (!strcmp (typename, "ulong"))
8265                 klass = mono_defaults.uint64_class;
8266         else if (!strcmp (typename, "float"))
8267                 klass = mono_defaults.single_class;
8268         else if (!strcmp (typename, "double"))
8269                 klass = mono_defaults.double_class;
8270         else if (!strcmp (typename, "object"))
8271                 klass = mono_defaults.object_class;
8272         else if (!strcmp (typename, "obj"))
8273                 klass = mono_defaults.object_class;
8274         else if (!strcmp (typename, "string"))
8275                 klass = mono_defaults.string_class;
8276         else if (!strcmp (typename, "bool"))
8277                 klass = mono_defaults.boolean_class;
8278         else if (!strcmp (typename, "boolean"))
8279                 klass = mono_defaults.boolean_class;
8280         else {
8281                 g_error ("%s", typename);
8282                 g_assert_not_reached ();
8283         }
8284         return &klass->byval_arg;
8285 }
8286
8287 /**
8288  * LOCKING: Take the corlib image lock.
8289  */
8290 MonoMethodSignature*
8291 mono_create_icall_signature (const char *sigstr)
8292 {
8293         gchar **parts;
8294         int i, len;
8295         gchar **tmp;
8296         MonoMethodSignature *res, *res2;
8297         MonoImage *corlib = mono_defaults.corlib;
8298
8299         mono_image_lock (corlib);
8300         res = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8301         mono_image_unlock (corlib);
8302
8303         if (res)
8304                 return res;
8305
8306         parts = g_strsplit (sigstr, " ", 256);
8307
8308         tmp = parts;
8309         len = 0;
8310         while (*tmp) {
8311                 len ++;
8312                 tmp ++;
8313         }
8314
8315         res = mono_metadata_signature_alloc (corlib, len - 1);
8316         res->pinvoke = 1;
8317
8318 #ifdef HOST_WIN32
8319         /* 
8320          * Under windows, the default pinvoke calling convention is STDCALL but
8321          * we need CDECL.
8322          */
8323         res->call_convention = MONO_CALL_C;
8324 #endif
8325
8326         res->ret = type_from_typename (parts [0]);
8327         for (i = 1; i < len; ++i) {
8328                 res->params [i - 1] = type_from_typename (parts [i]);
8329         }
8330
8331         g_strfreev (parts);
8332
8333         mono_image_lock (corlib);
8334         res2 = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8335         if (res2)
8336                 res = res2; /*Value is allocated in the image pool*/
8337         else
8338                 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8339         mono_image_unlock (corlib);
8340
8341         return res;
8342 }
8343
8344 MonoJitICallInfo *
8345 mono_find_jit_icall_by_name (const char *name)
8346 {
8347         MonoJitICallInfo *info;
8348         g_assert (jit_icall_hash_name);
8349
8350         mono_icall_lock ();
8351         info = g_hash_table_lookup (jit_icall_hash_name, name);
8352         mono_icall_unlock ();
8353         return info;
8354 }
8355
8356 MonoJitICallInfo *
8357 mono_find_jit_icall_by_addr (gconstpointer addr)
8358 {
8359         MonoJitICallInfo *info;
8360         g_assert (jit_icall_hash_addr);
8361
8362         mono_icall_lock ();
8363         info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8364         mono_icall_unlock ();
8365
8366         return info;
8367 }
8368
8369 /*
8370  * mono_get_jit_icall_info:
8371  *
8372  *   Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8373  * caller should access it while holding the icall lock.
8374  */
8375 GHashTable*
8376 mono_get_jit_icall_info (void)
8377 {
8378         return jit_icall_hash_name;
8379 }
8380
8381 /*
8382  * mono_lookup_jit_icall_symbol:
8383  *
8384  *   Given the jit icall NAME, returns its C symbol if possible, or NULL.
8385  */
8386 const char*
8387 mono_lookup_jit_icall_symbol (const char *name)
8388 {
8389         MonoJitICallInfo *info;
8390         const char *res = NULL;
8391
8392         mono_icall_lock ();
8393         info = g_hash_table_lookup (jit_icall_hash_name, name);
8394         if (info)
8395                 res = info->c_symbol;
8396         mono_icall_unlock ();
8397         return res;
8398 }
8399
8400 void
8401 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8402 {
8403         mono_icall_lock ();
8404         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8405         mono_icall_unlock ();
8406 }
8407
8408 MonoJitICallInfo *
8409 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8410 {
8411         MonoJitICallInfo *info;
8412         
8413         g_assert (func);
8414         g_assert (name);
8415
8416         mono_icall_lock ();
8417
8418         if (!jit_icall_hash_name) {
8419                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8420                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8421         }
8422
8423         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8424                 g_warning ("jit icall already defined \"%s\"\n", name);
8425                 g_assert_not_reached ();
8426         }
8427
8428         info = g_new0 (MonoJitICallInfo, 1);
8429         
8430         info->name = name;
8431         info->func = func;
8432         info->sig = sig;
8433         info->c_symbol = c_symbol;
8434
8435         if (is_save) {
8436                 info->wrapper = func;
8437         } else {
8438                 info->wrapper = NULL;
8439         }
8440
8441         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8442         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8443
8444         mono_icall_unlock ();
8445         return info;
8446 }
8447
8448 MonoJitICallInfo *
8449 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8450 {
8451         return mono_register_jit_icall_full (func, name, sig, is_save, NULL);
8452 }
8453