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