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