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