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