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