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