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