Merge pull request #3686 from lambdageek/dev-format-printf
[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), NULL, "");
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                         MonoException *exc = mono_class_get_exception_for_failure (klass);
4437                         mono_set_pending_exception (exc);
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         MonoString *str;
6148
6149         mono_error_init (error);
6150
6151         if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6152                 return;
6153
6154         name = mono_type_get_full_name (klass);
6155         str =  mono_string_new (mono_domain_get (), name);
6156         g_free (name);
6157         mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6158
6159 }
6160 ICALL_EXPORT MonoReflectionType *
6161 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6162 {
6163         MonoError error;
6164         MonoReflectionType *ret;
6165         MonoClass *klass, *aklass;
6166
6167         klass = mono_class_from_mono_type (type->type);
6168         check_for_invalid_type (klass, &error);
6169         mono_error_set_pending_exception (&error);
6170
6171         if (rank == 0) //single dimentional array
6172                 aklass = mono_array_class_get (klass, 1);
6173         else
6174                 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6175
6176         ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6177         mono_error_set_pending_exception (&error);
6178
6179         return ret;
6180 }
6181
6182 ICALL_EXPORT MonoReflectionType *
6183 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6184 {
6185         MonoError error;
6186         MonoReflectionType *ret;
6187         MonoClass *klass;
6188
6189         klass = mono_class_from_mono_type (type->type);
6190         mono_class_init_checked (klass, &error);
6191         if (mono_error_set_pending_exception (&error))
6192                 return NULL;
6193
6194         check_for_invalid_type (klass, &error);
6195         if (mono_error_set_pending_exception (&error))
6196                 return NULL;
6197
6198         ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6199         mono_error_set_pending_exception (&error);
6200
6201         return ret;
6202 }
6203
6204 ICALL_EXPORT MonoReflectionType *
6205 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6206 {
6207         MonoError error;
6208         MonoReflectionType *ret;
6209         MonoClass *klass, *pklass;
6210
6211         klass = mono_class_from_mono_type (type->type);
6212         mono_class_init_checked (klass, &error);
6213         if (mono_error_set_pending_exception (&error))
6214                 return NULL;
6215         check_for_invalid_type (klass, &error);
6216         if (mono_error_set_pending_exception (&error))
6217                 return NULL;
6218
6219         pklass = mono_ptr_class_get (type->type);
6220
6221         ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6222         mono_error_set_pending_exception (&error);
6223
6224         return ret;
6225 }
6226
6227 ICALL_EXPORT MonoObject *
6228 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6229                                                    MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6230 {
6231         MonoError error;
6232         MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6233         MonoObject *delegate;
6234         gpointer func;
6235         MonoMethod *method = info->method;
6236         MonoMethodSignature *sig = mono_method_signature(method);
6237
6238         mono_class_init_checked (delegate_class, &error);
6239         if (mono_error_set_pending_exception (&error))
6240                 return NULL;
6241
6242         if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6243                 /* FIXME improve this exception message */
6244                 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6245                                                  __func__,
6246                                                  "delegate_class->parent == mono_defaults.multicastdelegate_class");
6247                 mono_error_set_pending_exception (&error);
6248                 return NULL;
6249         }
6250
6251         if (mono_security_core_clr_enabled ()) {
6252                 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6253                         if (throwOnBindFailure)
6254                                 mono_error_set_pending_exception (&error);
6255                         else
6256                                 mono_error_cleanup (&error);
6257                         return NULL;
6258                 }
6259         }
6260
6261         if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
6262                 if (!method->is_inflated) {
6263                         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"));
6264                         return NULL;
6265                 }
6266         }
6267
6268         delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6269         if (mono_error_set_pending_exception (&error))
6270                 return NULL;
6271
6272         if (method_is_dynamic (method)) {
6273                 /* Creating a trampoline would leak memory */
6274                 func = mono_compile_method_checked (method, &error);
6275                 if (mono_error_set_pending_exception (&error))
6276                         return NULL;
6277         } else {
6278                 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6279                         method = mono_object_get_virtual_method (target, method);
6280                 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6281                 if (mono_error_set_pending_exception (&error))
6282                         return NULL;
6283                 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6284         }
6285
6286         mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6287         if (mono_error_set_pending_exception (&error))
6288                 return NULL;
6289         return delegate;
6290 }
6291
6292 ICALL_EXPORT MonoMulticastDelegate *
6293 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6294 {
6295         MonoError error;
6296         MonoMulticastDelegate *ret;
6297
6298         g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6299
6300         ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6301         if (mono_error_set_pending_exception (&error))
6302                 return NULL;
6303
6304         ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6305
6306         return ret;
6307 }
6308
6309 ICALL_EXPORT MonoReflectionMethod*
6310 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6311 {
6312         MonoReflectionMethod *ret = NULL;
6313         MonoError error;
6314         ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6315         mono_error_set_pending_exception (&error);
6316         return ret;
6317 }
6318
6319 /* System.Buffer */
6320
6321 static inline gint32 
6322 mono_array_get_byte_length (MonoArray *array)
6323 {
6324         MonoClass *klass;
6325         int length;
6326         int i;
6327
6328         klass = array->obj.vtable->klass;
6329
6330         if (array->bounds == NULL)
6331                 length = array->max_length;
6332         else {
6333                 length = 1;
6334                 for (i = 0; i < klass->rank; ++ i)
6335                         length *= array->bounds [i].length;
6336         }
6337
6338         switch (klass->element_class->byval_arg.type) {
6339         case MONO_TYPE_I1:
6340         case MONO_TYPE_U1:
6341         case MONO_TYPE_BOOLEAN:
6342                 return length;
6343         case MONO_TYPE_I2:
6344         case MONO_TYPE_U2:
6345         case MONO_TYPE_CHAR:
6346                 return length << 1;
6347         case MONO_TYPE_I4:
6348         case MONO_TYPE_U4:
6349         case MONO_TYPE_R4:
6350                 return length << 2;
6351         case MONO_TYPE_I:
6352         case MONO_TYPE_U:
6353                 return length * sizeof (gpointer);
6354         case MONO_TYPE_I8:
6355         case MONO_TYPE_U8:
6356         case MONO_TYPE_R8:
6357                 return length << 3;
6358         default:
6359                 return -1;
6360         }
6361 }
6362
6363 ICALL_EXPORT gint32 
6364 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array) 
6365 {
6366         return mono_array_get_byte_length (array);
6367 }
6368
6369 ICALL_EXPORT gint8 
6370 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx) 
6371 {
6372         return mono_array_get (array, gint8, idx);
6373 }
6374
6375 ICALL_EXPORT void 
6376 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value) 
6377 {
6378         mono_array_set (array, gint8, idx, value);
6379 }
6380
6381 ICALL_EXPORT MonoBoolean
6382 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count) 
6383 {
6384         guint8 *src_buf, *dest_buf;
6385
6386         if (count < 0) {
6387                 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6388                 return FALSE;
6389         }
6390
6391         g_assert (count >= 0);
6392
6393         /* This is called directly from the class libraries without going through the managed wrapper */
6394         MONO_CHECK_ARG_NULL (src, FALSE);
6395         MONO_CHECK_ARG_NULL (dest, FALSE);
6396
6397         /* watch out for integer overflow */
6398         if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6399                 return FALSE;
6400
6401         src_buf = (guint8 *)src->vector + src_offset;
6402         dest_buf = (guint8 *)dest->vector + dest_offset;
6403
6404         if (src != dest)
6405                 memcpy (dest_buf, src_buf, count);
6406         else
6407                 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6408
6409         return TRUE;
6410 }
6411
6412 #ifndef DISABLE_REMOTING
6413 ICALL_EXPORT MonoObject *
6414 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6415 {
6416         MonoError error;
6417         MonoDomain *domain = mono_object_domain (this_obj); 
6418         MonoObject *res;
6419         MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6420         MonoTransparentProxy *tp;
6421         MonoType *type;
6422         MonoClass *klass;
6423
6424         res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6425         if (mono_error_set_pending_exception (&error))
6426                 return NULL;
6427
6428         tp = (MonoTransparentProxy*) res;
6429         
6430         MONO_OBJECT_SETREF (tp, rp, rp);
6431         type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6432         klass = mono_class_from_mono_type (type);
6433
6434         // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6435         mono_class_setup_vtable (klass);
6436         if (mono_class_has_failure (klass)) {
6437                 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6438                 return NULL;
6439         }
6440
6441         tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6442         if (mono_error_set_pending_exception (&error))
6443                 return NULL;
6444         tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6445         if (mono_error_set_pending_exception (&error))
6446                 return NULL;
6447
6448         res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6449         if (mono_error_set_pending_exception (&error))
6450                 return NULL;
6451         return res;
6452 }
6453
6454 ICALL_EXPORT MonoReflectionType *
6455 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6456 {
6457         MonoError error;
6458         MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6459         mono_error_set_pending_exception (&error);
6460
6461         return ret;
6462 }
6463 #endif
6464
6465 /* System.Environment */
6466
6467 MonoString*
6468 ves_icall_System_Environment_get_UserName (void)
6469 {
6470         /* using glib is more portable */
6471         return mono_string_new (mono_domain_get (), g_get_user_name ());
6472 }
6473
6474
6475 ICALL_EXPORT MonoString *
6476 ves_icall_System_Environment_get_MachineName (void)
6477 {
6478 #if defined (HOST_WIN32)
6479         gunichar2 *buf;
6480         guint32 len;
6481         MonoString *result;
6482
6483         len = MAX_COMPUTERNAME_LENGTH + 1;
6484         buf = g_new (gunichar2, len);
6485
6486         result = NULL;
6487         if (GetComputerName (buf, (PDWORD) &len)) {
6488                 MonoError error;
6489                 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6490                 mono_error_set_pending_exception (&error);
6491         }
6492
6493         g_free (buf);
6494         return result;
6495 #elif !defined(DISABLE_SOCKETS)
6496         MonoString *result;
6497         char *buf;
6498         int n;
6499 #if defined _SC_HOST_NAME_MAX
6500         n = sysconf (_SC_HOST_NAME_MAX);
6501         if (n == -1)
6502 #endif
6503         n = 512;
6504         buf = g_malloc (n+1);
6505         
6506         if (gethostname (buf, n) == 0){
6507                 buf [n] = 0;
6508                 result = mono_string_new (mono_domain_get (), buf);
6509         } else
6510                 result = NULL;
6511         g_free (buf);
6512         
6513         return result;
6514 #else
6515         return mono_string_new (mono_domain_get (), "mono");
6516 #endif
6517 }
6518
6519 ICALL_EXPORT int
6520 ves_icall_System_Environment_get_Platform (void)
6521 {
6522 #if defined (TARGET_WIN32)
6523         /* Win32NT */
6524         return 2;
6525 #elif defined(__MACH__)
6526         /* OSX */
6527         //
6528         // Notice that the value is hidden from user code, and only exposed
6529         // to mscorlib.   This is due to Mono's Unix/MacOS code predating the
6530         // define and making assumptions based on Unix/128/4 values before there
6531         // was a MacOS define.    Lots of code would assume that not-Unix meant
6532         // Windows, but in this case, it would be OSX. 
6533         //
6534         return 6;
6535 #else
6536         /* Unix */
6537         return 4;
6538 #endif
6539 }
6540
6541 ICALL_EXPORT MonoString *
6542 ves_icall_System_Environment_get_NewLine (void)
6543 {
6544 #if defined (HOST_WIN32)
6545         return mono_string_new (mono_domain_get (), "\r\n");
6546 #else
6547         return mono_string_new (mono_domain_get (), "\n");
6548 #endif
6549 }
6550
6551 ICALL_EXPORT MonoBoolean
6552 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6553 {
6554 #if SIZEOF_VOID_P == 8
6555         return TRUE;
6556 #else
6557 #ifdef HOST_WIN32
6558         gboolean isWow64Process = FALSE;
6559         if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6560                 return (MonoBoolean)isWow64Process;
6561         }
6562 #elif defined(HAVE_SYS_UTSNAME_H)
6563         struct utsname name;
6564
6565         if (uname (&name) >= 0) {
6566                 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6567         }
6568 #endif
6569         return FALSE;
6570 #endif
6571 }
6572
6573 ICALL_EXPORT MonoStringHandle
6574 ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
6575 {
6576         const gchar *value;
6577
6578         if (utf8_name == NULL)
6579                 return NULL_HANDLE_STRING;
6580
6581         value = g_getenv (utf8_name);
6582
6583         if (value == 0)
6584                 return NULL_HANDLE_STRING;
6585         
6586         return mono_string_new_handle (mono_domain_get (), value, error);
6587 }
6588
6589 /*
6590  * There is no standard way to get at environ.
6591  */
6592 #ifndef _MSC_VER
6593 #ifndef __MINGW32_VERSION
6594 #if defined(__APPLE__)
6595 #if defined (TARGET_OSX)
6596 /* Apple defines this in crt_externs.h but doesn't provide that header for 
6597  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
6598  * in fact exist on all implementations (so far) 
6599  */
6600 gchar ***_NSGetEnviron(void);
6601 #define environ (*_NSGetEnviron())
6602 #else
6603 static char *mono_environ[1] = { NULL };
6604 #define environ mono_environ
6605 #endif /* defined (TARGET_OSX) */
6606 #else
6607 extern
6608 char **environ;
6609 #endif
6610 #endif
6611 #endif
6612
6613 ICALL_EXPORT MonoArray *
6614 ves_icall_System_Environment_GetCoomandLineArgs (void)
6615 {
6616         MonoError error;
6617         MonoArray *result = mono_runtime_get_main_args_checked (&error);
6618         mono_error_set_pending_exception (&error);
6619         return result;
6620 }
6621
6622 ICALL_EXPORT MonoArray *
6623 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6624 {
6625 #ifdef HOST_WIN32
6626         MonoError error;
6627         MonoArray *names;
6628         MonoDomain *domain;
6629         MonoString *str;
6630         WCHAR* env_strings;
6631         WCHAR* env_string;
6632         WCHAR* equal_str;
6633         int n = 0;
6634
6635         env_strings = GetEnvironmentStrings();
6636
6637         if (env_strings) {
6638                 env_string = env_strings;
6639                 while (*env_string != '\0') {
6640                 /* weird case that MS seems to skip */
6641                         if (*env_string != '=')
6642                                 n++;
6643                         while (*env_string != '\0')
6644                                 env_string++;
6645                         env_string++;
6646                 }
6647         }
6648
6649         domain = mono_domain_get ();
6650         names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6651         if (mono_error_set_pending_exception (&error))
6652                 return NULL;
6653
6654         if (env_strings) {
6655                 n = 0;
6656                 env_string = env_strings;
6657                 while (*env_string != '\0') {
6658                         /* weird case that MS seems to skip */
6659                         if (*env_string != '=') {
6660                                 equal_str = wcschr(env_string, '=');
6661                                 g_assert(equal_str);
6662                                 MonoError error;
6663                                 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6664                                 if (mono_error_set_pending_exception (&error))
6665                                         return NULL;
6666
6667                                 mono_array_setref (names, n, str);
6668                                 n++;
6669                         }
6670                         while (*env_string != '\0')
6671                                 env_string++;
6672                         env_string++;
6673                 }
6674
6675                 FreeEnvironmentStrings (env_strings);
6676         }
6677
6678         return names;
6679
6680 #else
6681         MonoError error;
6682         MonoArray *names;
6683         MonoDomain *domain;
6684         MonoString *str;
6685         gchar **e, **parts;
6686         int n;
6687
6688         n = 0;
6689         for (e = environ; *e != 0; ++ e)
6690                 ++ n;
6691
6692         domain = mono_domain_get ();
6693         names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6694         if (mono_error_set_pending_exception (&error))
6695                 return NULL;
6696
6697         n = 0;
6698         for (e = environ; *e != 0; ++ e) {
6699                 parts = g_strsplit (*e, "=", 2);
6700                 if (*parts != 0) {
6701                         str = mono_string_new (domain, *parts);
6702                         mono_array_setref (names, n, str);
6703                 }
6704
6705                 g_strfreev (parts);
6706
6707                 ++ n;
6708         }
6709
6710         return names;
6711 #endif
6712 }
6713
6714 ICALL_EXPORT void
6715 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6716 {
6717 #ifdef HOST_WIN32
6718         gunichar2 *utf16_name, *utf16_value;
6719 #else
6720         gchar *utf8_name, *utf8_value;
6721         MonoError error;
6722 #endif
6723
6724 #ifdef HOST_WIN32
6725         utf16_name = mono_string_to_utf16 (name);
6726         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6727                 SetEnvironmentVariable (utf16_name, NULL);
6728                 g_free (utf16_name);
6729                 return;
6730         }
6731
6732         utf16_value = mono_string_to_utf16 (value);
6733
6734         SetEnvironmentVariable (utf16_name, utf16_value);
6735
6736         g_free (utf16_name);
6737         g_free (utf16_value);
6738 #else
6739         utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6740         if (mono_error_set_pending_exception (&error))
6741                 return;
6742
6743         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6744                 g_unsetenv (utf8_name);
6745                 g_free (utf8_name);
6746                 return;
6747         }
6748
6749         utf8_value = mono_string_to_utf8_checked (value, &error);
6750         if (!mono_error_ok (&error)) {
6751                 g_free (utf8_name);
6752                 mono_error_set_pending_exception (&error);
6753                 return;
6754         }
6755         g_setenv (utf8_name, utf8_value, TRUE);
6756
6757         g_free (utf8_name);
6758         g_free (utf8_value);
6759 #endif
6760 }
6761
6762 ICALL_EXPORT void
6763 ves_icall_System_Environment_Exit (int result)
6764 {
6765         mono_environment_exitcode_set (result);
6766
6767 /* FIXME: There are some cleanup hangs that should be worked out, but
6768  * if the program is going to exit, everything will be cleaned up when
6769  * NaCl exits anyway.
6770  */
6771 #ifndef __native_client__
6772         if (!mono_runtime_try_shutdown ())
6773                 mono_thread_exit ();
6774
6775         /* Suspend all managed threads since the runtime is going away */
6776         mono_thread_suspend_all_other_threads ();
6777
6778         mono_runtime_quit ();
6779 #endif
6780
6781         /* we may need to do some cleanup here... */
6782         exit (result);
6783 }
6784
6785 ICALL_EXPORT MonoStringHandle
6786 ves_icall_System_Environment_GetGacPath (MonoError *error)
6787 {
6788         return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error);
6789 }
6790
6791 ICALL_EXPORT MonoString*
6792 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6793 {
6794 #if defined (HOST_WIN32)
6795         #ifndef CSIDL_FLAG_CREATE
6796                 #define CSIDL_FLAG_CREATE       0x8000
6797         #endif
6798
6799         WCHAR path [MAX_PATH];
6800         /* Create directory if no existing */
6801         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6802                 int len = 0;
6803                 while (path [len])
6804                         ++ len;
6805                 MonoError error;
6806                 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6807                 mono_error_set_pending_exception (&error);
6808                 return res;
6809         }
6810 #else
6811         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6812 #endif
6813         return mono_string_new (mono_domain_get (), "");
6814 }
6815
6816 ICALL_EXPORT MonoArray *
6817 ves_icall_System_Environment_GetLogicalDrives (void)
6818 {
6819         MonoError error;
6820         gunichar2 buf [256], *ptr, *dname;
6821         gunichar2 *u16;
6822         guint initial_size = 127, size = 128;
6823         gint ndrives;
6824         MonoArray *result;
6825         MonoString *drivestr;
6826         MonoDomain *domain = mono_domain_get ();
6827         gint len;
6828
6829         buf [0] = '\0';
6830         ptr = buf;
6831
6832         while (size > initial_size) {
6833                 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6834                 if (size > initial_size) {
6835                         if (ptr != buf)
6836                                 g_free (ptr);
6837                         ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6838                         initial_size = size;
6839                         size++;
6840                 }
6841         }
6842
6843         /* Count strings */
6844         dname = ptr;
6845         ndrives = 0;
6846         do {
6847                 while (*dname++);
6848                 ndrives++;
6849         } while (*dname);
6850
6851         dname = ptr;
6852         result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
6853         if (mono_error_set_pending_exception (&error))
6854                 goto leave;
6855
6856         ndrives = 0;
6857         do {
6858                 len = 0;
6859                 u16 = dname;
6860                 while (*u16) { u16++; len ++; }
6861                 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6862                 if (mono_error_set_pending_exception (&error))
6863                         goto leave;
6864
6865                 mono_array_setref (result, ndrives++, drivestr);
6866                 while (*dname++);
6867         } while (*dname);
6868
6869 leave:
6870         if (ptr != buf)
6871                 g_free (ptr);
6872
6873         return result;
6874 }
6875
6876 ICALL_EXPORT MonoString *
6877 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6878 {
6879         MonoError error;
6880         gunichar2 volume_name [MAX_PATH + 1];
6881         
6882         if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6883                 return NULL;
6884         MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
6885         mono_error_set_pending_exception (&error);
6886         return result;
6887 }
6888
6889 ICALL_EXPORT MonoStringHandle
6890 ves_icall_System_Environment_InternalGetHome (MonoError *error)
6891 {
6892         return mono_string_new_handle (mono_domain_get (), g_get_home_dir (), error);
6893 }
6894
6895 static const char *encodings [] = {
6896         (char *) 1,
6897                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6898                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6899                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6900         (char *) 2,
6901                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6902                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6903                 "x_unicode_2_0_utf_7",
6904         (char *) 3,
6905                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6906                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6907         (char *) 4,
6908                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6909                 "iso_10646_ucs2",
6910         (char *) 5,
6911                 "unicodefffe", "utf_16be",
6912         (char *) 6,
6913                 "iso_8859_1",
6914         (char *) 0
6915 };
6916
6917 /*
6918  * Returns the internal codepage, if the value of "int_code_page" is
6919  * 1 at entry, and we can not compute a suitable code page number,
6920  * returns the code page as a string
6921  */
6922 ICALL_EXPORT MonoString*
6923 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page) 
6924 {
6925         const char *cset;
6926         const char *p;
6927         char *c;
6928         char *codepage = NULL;
6929         int code;
6930         int want_name = *int_code_page;
6931         int i;
6932         
6933         *int_code_page = -1;
6934
6935         g_get_charset (&cset);
6936         c = codepage = strdup (cset);
6937         for (c = codepage; *c; c++){
6938                 if (isascii (*c) && isalpha (*c))
6939                         *c = tolower (*c);
6940                 if (*c == '-')
6941                         *c = '_';
6942         }
6943         /* g_print ("charset: %s\n", cset); */
6944         
6945         /* handle some common aliases */
6946         p = encodings [0];
6947         code = 0;
6948         for (i = 0; p != 0; ){
6949                 if ((gsize) p < 7){
6950                         code = (gssize) p;
6951                         p = encodings [++i];
6952                         continue;
6953                 }
6954                 if (strcmp (p, codepage) == 0){
6955                         *int_code_page = code;
6956                         break;
6957                 }
6958                 p = encodings [++i];
6959         }
6960         
6961         if (strstr (codepage, "utf_8") != NULL)
6962                 *int_code_page |= 0x10000000;
6963         g_free (codepage);
6964         
6965         if (want_name && *int_code_page == -1)
6966                 return mono_string_new (mono_domain_get (), cset);
6967         else
6968                 return NULL;
6969 }
6970
6971 ICALL_EXPORT MonoBoolean
6972 ves_icall_System_Environment_get_HasShutdownStarted (void)
6973 {
6974         if (mono_runtime_is_shutting_down ())
6975                 return TRUE;
6976
6977         if (mono_domain_is_unloading (mono_domain_get ()))
6978                 return TRUE;
6979
6980         return FALSE;
6981 }
6982
6983 ICALL_EXPORT void
6984 ves_icall_System_Environment_BroadcastSettingChange (void)
6985 {
6986 #ifdef HOST_WIN32
6987         SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6988 #endif
6989 }
6990
6991 ICALL_EXPORT
6992 gint32
6993 ves_icall_System_Environment_get_TickCount (void)
6994 {
6995         /* this will overflow after ~24 days */
6996         return (gint32) (mono_msec_boottime () & 0xffffffff);
6997 }
6998
6999 ICALL_EXPORT gint32
7000 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7001 {
7002         return 9;
7003 }
7004
7005 #ifndef DISABLE_REMOTING
7006 ICALL_EXPORT MonoBoolean
7007 ves_icall_IsTransparentProxy (MonoObject *proxy)
7008 {
7009         if (!proxy)
7010                 return 0;
7011
7012         if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7013                 return 1;
7014
7015         return 0;
7016 }
7017
7018 ICALL_EXPORT MonoReflectionMethod *
7019 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7020         MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7021 {
7022         MonoReflectionMethod *ret = NULL;
7023         MonoError error;
7024
7025         MonoClass *klass;
7026         MonoMethod *method;
7027         MonoMethod **vtable;
7028         MonoMethod *res = NULL;
7029
7030         MONO_CHECK_ARG_NULL (rtype, NULL);
7031         MONO_CHECK_ARG_NULL (rmethod, NULL);
7032
7033         method = rmethod->method;
7034         klass = mono_class_from_mono_type (rtype->type);
7035         mono_class_init_checked (klass, &error);
7036         if (mono_error_set_pending_exception (&error))
7037                 return NULL;
7038
7039         if (MONO_CLASS_IS_INTERFACE (klass))
7040                 return NULL;
7041
7042         if (method->flags & METHOD_ATTRIBUTE_STATIC)
7043                 return NULL;
7044
7045         if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7046                 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7047                         return rmethod;
7048                 else
7049                         return NULL;
7050         }
7051
7052         mono_class_setup_vtable (klass);
7053         vtable = klass->vtable;
7054
7055         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7056                 gboolean variance_used = FALSE;
7057                 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7058                 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7059                 if (offs >= 0)
7060                         res = vtable [offs + method->slot];
7061         } else {
7062                 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7063                         return NULL;
7064
7065                 if (method->slot != -1)
7066                         res = vtable [method->slot];
7067         }
7068
7069         if (!res)
7070                 return NULL;
7071
7072         ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7073         mono_error_set_pending_exception (&error);
7074         return ret;
7075 }
7076
7077 ICALL_EXPORT void
7078 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7079 {
7080         MonoError error;
7081         MonoClass *klass;
7082         MonoVTable* vtable;
7083
7084         klass = mono_class_from_mono_type (type->type);
7085         vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7086         if (!is_ok (&error)) {
7087                 mono_error_set_pending_exception (&error);
7088                 return;
7089         }
7090
7091         mono_vtable_set_is_remote (vtable, enable);
7092 }
7093
7094 #else /* DISABLE_REMOTING */
7095
7096 ICALL_EXPORT void
7097 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7098 {
7099         g_assert_not_reached ();
7100 }
7101
7102 #endif
7103
7104 ICALL_EXPORT MonoObject *
7105 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7106 {
7107         MonoError error;
7108         MonoClass *klass;
7109         MonoDomain *domain;
7110         MonoObject *ret;
7111         
7112         domain = mono_object_domain (type);
7113         klass = mono_class_from_mono_type (type->type);
7114         mono_class_init_checked (klass, &error);
7115         if (mono_error_set_pending_exception (&error))
7116                 return NULL;
7117
7118         if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7119                 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7120                 return NULL;
7121         }
7122
7123         if (klass->rank >= 1) {
7124                 g_assert (klass->rank == 1);
7125                 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7126                 mono_error_set_pending_exception (&error);
7127                 return ret;
7128         } else {
7129                 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7130                 if (!is_ok (&error)) {
7131                         mono_error_set_pending_exception (&error);
7132                         return NULL;
7133                 }
7134                 /* Bypass remoting object creation check */
7135                 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7136                 mono_error_set_pending_exception (&error);
7137
7138                 return ret;
7139         }
7140 }
7141
7142 ICALL_EXPORT MonoStringHandle
7143 ves_icall_System_IO_get_temp_path (MonoError *error)
7144 {
7145         return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error);
7146 }
7147
7148 #ifndef PLATFORM_NO_DRIVEINFO
7149 ICALL_EXPORT MonoBoolean
7150 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7151                                                 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7152                                                 gint32 *error)
7153 {
7154         gboolean result;
7155         ULARGE_INTEGER wapi_free_bytes_avail;
7156         ULARGE_INTEGER wapi_total_number_of_bytes;
7157         ULARGE_INTEGER wapi_total_number_of_free_bytes;
7158
7159         *error = ERROR_SUCCESS;
7160         result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7161                                      &wapi_total_number_of_free_bytes);
7162
7163         if (result) {
7164                 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7165                 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7166                 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7167         } else {
7168                 *free_bytes_avail = 0;
7169                 *total_number_of_bytes = 0;
7170                 *total_number_of_free_bytes = 0;
7171                 *error = GetLastError ();
7172         }
7173
7174         return result;
7175 }
7176
7177 ICALL_EXPORT guint32
7178 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7179 {
7180         return GetDriveType (mono_string_chars (root_path_name));
7181 }
7182 #endif
7183
7184 ICALL_EXPORT gpointer
7185 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7186 {
7187         MonoError error;
7188         gpointer result = mono_compile_method_checked (method, &error);
7189         mono_error_set_pending_exception (&error);
7190         return result;
7191 }
7192
7193 ICALL_EXPORT MonoString *
7194 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7195 {
7196         MonoString *mcpath;
7197         gchar *path;
7198
7199         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7200
7201 #if defined (HOST_WIN32)
7202         /* Avoid mixing '/' and '\\' */
7203         {
7204                 gint i;
7205                 for (i = strlen (path) - 1; i >= 0; i--)
7206                         if (path [i] == '/')
7207                                 path [i] = '\\';
7208         }
7209 #endif
7210         mcpath = mono_string_new (mono_domain_get (), path);
7211         g_free (path);
7212
7213         return mcpath;
7214 }
7215
7216 /* this is an icall */
7217 static MonoString *
7218 get_bundled_app_config (void)
7219 {
7220         MonoError error;
7221         const gchar *app_config;
7222         MonoDomain *domain;
7223         MonoString *file;
7224         gchar *config_file_name, *config_file_path;
7225         gsize len, config_file_path_length, config_ext_length;
7226         gchar *module;
7227
7228         domain = mono_domain_get ();
7229         file = domain->setup->configuration_file;
7230         if (!file || file->length == 0)
7231                 return NULL;
7232
7233         // Retrieve config file and remove the extension
7234         config_file_name = mono_string_to_utf8_checked (file, &error);
7235         if (mono_error_set_pending_exception (&error))
7236                 return NULL;
7237         config_file_path = mono_portability_find_file (config_file_name, TRUE);
7238         if (!config_file_path)
7239                 config_file_path = config_file_name;
7240
7241         config_file_path_length = strlen (config_file_path);
7242         config_ext_length = strlen (".config");
7243         if (config_file_path_length <= config_ext_length)
7244                 return NULL;
7245
7246         len = config_file_path_length - config_ext_length;
7247         module = (gchar *)g_malloc0 (len + 1);
7248         memcpy (module, config_file_path, len);
7249         // Get the config file from the module name
7250         app_config = mono_config_string_for_assembly_file (module);
7251         // Clean-up
7252         g_free (module);
7253         if (config_file_name != config_file_path)
7254                 g_free (config_file_name);
7255         g_free (config_file_path);
7256
7257         if (!app_config)
7258                 return NULL;
7259
7260         return mono_string_new (mono_domain_get (), app_config);
7261 }
7262
7263 /* this is an icall */
7264 static MonoStringHandle
7265 get_bundled_machine_config (MonoError *error)
7266 {
7267         const gchar *machine_config;
7268
7269         machine_config = mono_get_machine_config ();
7270
7271         if (!machine_config)
7272                 return NULL_HANDLE_STRING;
7273
7274         return mono_string_new_handle (mono_domain_get (), machine_config, error);
7275 }
7276
7277 ICALL_EXPORT MonoString *
7278 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7279 {
7280         MonoString *ipath;
7281         gchar *path;
7282
7283         path = g_path_get_dirname (mono_get_config_dir ());
7284
7285 #if defined (HOST_WIN32)
7286         /* Avoid mixing '/' and '\\' */
7287         {
7288                 gint i;
7289                 for (i = strlen (path) - 1; i >= 0; i--)
7290                         if (path [i] == '/')
7291                                 path [i] = '\\';
7292         }
7293 #endif
7294         ipath = mono_string_new (mono_domain_get (), path);
7295         g_free (path);
7296
7297         return ipath;
7298 }
7299
7300 ICALL_EXPORT gboolean
7301 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7302 {
7303         MonoPEResourceDataEntry *entry;
7304         MonoImage *image;
7305
7306         if (!assembly || !result || !size)
7307                 return FALSE;
7308
7309         *result = NULL;
7310         *size = 0;
7311         image = assembly->assembly->image;
7312         entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7313         if (!entry)
7314                 return FALSE;
7315
7316         *result = mono_image_rva_map (image, entry->rde_data_offset);
7317         if (!(*result)) {
7318                 g_free (entry);
7319                 return FALSE;
7320         }
7321         *size = entry->rde_size;
7322         g_free (entry);
7323         return TRUE;
7324 }
7325
7326 ICALL_EXPORT MonoBoolean
7327 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7328 {
7329         return mono_is_debugger_attached ();
7330 }
7331
7332 ICALL_EXPORT MonoBoolean
7333 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7334 {
7335         if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7336                 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7337         else
7338                 return FALSE;
7339 }
7340
7341 ICALL_EXPORT void
7342 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7343 {
7344         if (mono_get_runtime_callbacks ()->debug_log)
7345                 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7346 }
7347
7348 ICALL_EXPORT void
7349 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7350 {
7351 #if defined (HOST_WIN32)
7352         OutputDebugString (mono_string_chars (message));
7353 #else
7354         g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7355 #endif
7356 }
7357
7358 /* Only used for value types */
7359 ICALL_EXPORT MonoObject *
7360 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7361 {
7362         MonoError error;
7363         MonoObject *result;
7364         MonoClass *klass;
7365         MonoDomain *domain;
7366         
7367         domain = mono_object_domain (type);
7368         klass = mono_class_from_mono_type (type->type);
7369         mono_class_init_checked (klass, &error);
7370         if (mono_error_set_pending_exception (&error))
7371                 return NULL;
7372
7373         if (mono_class_is_nullable (klass))
7374                 /* No arguments -> null */
7375                 return NULL;
7376
7377         result = mono_object_new_checked (domain, klass, &error);
7378         mono_error_set_pending_exception (&error);
7379         return result;
7380 }
7381
7382 ICALL_EXPORT MonoReflectionMethod *
7383 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7384 {
7385         MonoReflectionMethod *ret = NULL;
7386         MonoError error;
7387
7388         MonoClass *klass, *parent;
7389         MonoGenericContext *generic_inst = NULL;
7390         MonoMethod *method = m->method;
7391         MonoMethod *result = NULL;
7392         int slot;
7393
7394         if (method->klass == NULL)
7395                 return m;
7396
7397         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7398             MONO_CLASS_IS_INTERFACE (method->klass) ||
7399             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7400                 return m;
7401
7402         slot = mono_method_get_vtable_slot (method);
7403         if (slot == -1)
7404                 return m;
7405
7406         klass = method->klass;
7407         if (klass->generic_class) {
7408                 generic_inst = mono_class_get_context (klass);
7409                 klass = klass->generic_class->container_class;
7410         }
7411
7412 retry:
7413         if (definition) {
7414                 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7415                 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7416                         /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7417                            or klass is the generic container class and generic_inst is the instantiation.
7418
7419                            when we go to the parent, if the parent is an open constructed type, we need to
7420                            replace the type parameters by the definitions from the generic_inst, and then take it
7421                            apart again into the klass and the generic_inst.
7422
7423                            For cases like this:
7424                            class C<T> : B<T, int> {
7425                                public override void Foo () { ... }
7426                            }
7427                            class B<U,V> : A<HashMap<U,V>> {
7428                                public override void Foo () { ... }
7429                            }
7430                            class A<X> {
7431                                public virtual void Foo () { ... }
7432                            }
7433
7434                            if at each iteration the parent isn't open, we can skip inflating it.  if at some
7435                            iteration the parent isn't generic (after possible inflation), we set generic_inst to
7436                            NULL;
7437                         */
7438                         MonoGenericContext *parent_inst = NULL;
7439                         if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7440                                 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7441                                 if (!mono_error_ok (&error)) {
7442                                         mono_error_set_pending_exception (&error);
7443                                         return NULL;
7444                                 }
7445                         }
7446                         if (parent->generic_class) {
7447                                 parent_inst = mono_class_get_context (parent);
7448                                 parent = parent->generic_class->container_class;
7449                         }
7450
7451                         mono_class_setup_vtable (parent);
7452                         if (parent->vtable_size <= slot)
7453                                 break;
7454                         klass = parent;
7455                         generic_inst = parent_inst;
7456                 }
7457         } else {
7458                 klass = klass->parent;
7459                 if (!klass)
7460                         return m;
7461                 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7462                         klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7463                         if (!mono_error_ok (&error)) {
7464                                 mono_error_set_pending_exception (&error);
7465                                 return NULL;
7466                         }
7467
7468                         generic_inst = NULL;
7469                 }
7470                 if (klass->generic_class) {
7471                         generic_inst = mono_class_get_context (klass);
7472                         klass = klass->generic_class->container_class;
7473                 }
7474
7475         }
7476
7477         if (generic_inst) {
7478                 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7479                 if (!mono_error_ok (&error)) {
7480                         mono_error_set_pending_exception (&error);
7481                         return NULL;
7482                 }
7483         }
7484
7485         if (klass == method->klass)
7486                 return m;
7487
7488         /*This is possible if definition == FALSE.
7489          * Do it here to be really sure we don't read invalid memory.
7490          */
7491         if (slot >= klass->vtable_size)
7492                 return m;
7493
7494         mono_class_setup_vtable (klass);
7495
7496         result = klass->vtable [slot];
7497         if (result == NULL) {
7498                 /* It is an abstract method */
7499                 gboolean found = FALSE;
7500                 gpointer iter = NULL;
7501                 while ((result = mono_class_get_methods (klass, &iter))) {
7502                         if (result->slot == slot) {
7503                                 found = TRUE;
7504                                 break;
7505                         }
7506                 }
7507                 /* found might be FALSE if we looked in an abstract class
7508                  * that doesn't override an abstract method of its
7509                  * parent: 
7510                  *   abstract class Base {
7511                  *     public abstract void Foo ();
7512                  *   }
7513                  *   abstract class Derived : Base { }
7514                  *   class Child : Derived {
7515                  *     public override void Foo () { }
7516                  *  }
7517                  *
7518                  *  if m was Child.Foo and we ask for the base method,
7519                  *  then we get here with klass == Derived and found == FALSE
7520                  */
7521                 /* but it shouldn't be the case that if we're looking
7522                  * for the definition and didn't find a result; the
7523                  * loop above should've taken us as far as we could
7524                  * go! */
7525                 g_assert (!(definition && !found));
7526                 if (!found)
7527                         goto retry;
7528         }
7529
7530         g_assert (result != NULL);
7531
7532         ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7533         mono_error_set_pending_exception (&error);
7534         return ret;
7535 }
7536
7537 ICALL_EXPORT MonoString*
7538 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7539 {
7540         MonoMethod *method = m->method;
7541
7542         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7543         return m->name;
7544 }
7545
7546 ICALL_EXPORT void
7547 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7548 {
7549         iter->sig = *(MonoMethodSignature**)argsp;
7550         
7551         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7552         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7553
7554         iter->next_arg = 0;
7555         /* FIXME: it's not documented what start is exactly... */
7556         if (start) {
7557                 iter->args = start;
7558         } else {
7559                 iter->args = argsp + sizeof (gpointer);
7560         }
7561         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7562
7563         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7564 }
7565
7566 ICALL_EXPORT MonoTypedRef
7567 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7568 {
7569         guint32 i, arg_size;
7570         gint32 align;
7571         MonoTypedRef res;
7572
7573         i = iter->sig->sentinelpos + iter->next_arg;
7574
7575         g_assert (i < iter->sig->param_count);
7576
7577         res.type = iter->sig->params [i];
7578         res.klass = mono_class_from_mono_type (res.type);
7579         arg_size = mono_type_stack_size (res.type, &align);
7580 #if defined(__arm__) || defined(__mips__)
7581         iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7582 #endif
7583         res.value = iter->args;
7584 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7585         /* Values are stored as 8 byte register sized objects, but 'value'
7586          * is dereferenced as a pointer in other routines.
7587          */
7588         res.value = (char*)res.value + 4;
7589 #endif
7590 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7591         if (arg_size <= sizeof (gpointer)) {
7592                 int dummy;
7593                 int padding = arg_size - mono_type_size (res.type, &dummy);
7594                 res.value = (guint8*)res.value + padding;
7595         }
7596 #endif
7597         iter->args = (char*)iter->args + arg_size;
7598         iter->next_arg++;
7599
7600         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7601
7602         return res;
7603 }
7604
7605 ICALL_EXPORT MonoTypedRef
7606 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7607 {
7608         guint32 i, arg_size;
7609         gint32 align;
7610         MonoTypedRef res;
7611
7612         i = iter->sig->sentinelpos + iter->next_arg;
7613
7614         g_assert (i < iter->sig->param_count);
7615
7616         while (i < iter->sig->param_count) {
7617                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7618                         continue;
7619                 res.type = iter->sig->params [i];
7620                 res.klass = mono_class_from_mono_type (res.type);
7621                 /* FIXME: endianess issue... */
7622                 arg_size = mono_type_stack_size (res.type, &align);
7623 #if defined(__arm__) || defined(__mips__)
7624                 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7625 #endif
7626                 res.value = iter->args;
7627                 iter->args = (char*)iter->args + arg_size;
7628                 iter->next_arg++;
7629                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7630                 return res;
7631         }
7632         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7633
7634         res.type = NULL;
7635         res.value = NULL;
7636         res.klass = NULL;
7637         return res;
7638 }
7639
7640 ICALL_EXPORT MonoType*
7641 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7642 {
7643         gint i;
7644         
7645         i = iter->sig->sentinelpos + iter->next_arg;
7646
7647         g_assert (i < iter->sig->param_count);
7648
7649         return iter->sig->params [i];
7650 }
7651
7652 ICALL_EXPORT MonoObject*
7653 mono_TypedReference_ToObject (MonoTypedRef* tref)
7654 {
7655         MonoError error;
7656         MonoObject *result = NULL;
7657         if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7658                 MonoObject** objp = (MonoObject **)tref->value;
7659                 return *objp;
7660         }
7661
7662         result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7663         mono_error_set_pending_exception (&error);
7664         return result;
7665 }
7666
7667 ICALL_EXPORT MonoTypedRef
7668 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7669 {
7670         MonoTypedRef res;
7671         MonoReflectionField *f;
7672         MonoClass *klass;
7673         MonoType *ftype = NULL;
7674         guint8 *p = NULL;
7675         int i;
7676
7677         memset (&res, 0, sizeof (res));
7678
7679         g_assert (fields);
7680         g_assert (mono_array_length (fields) > 0);
7681
7682         klass = target->vtable->klass;
7683
7684         for (i = 0; i < mono_array_length (fields); ++i) {
7685                 f = mono_array_get (fields, MonoReflectionField*, i);
7686                 if (f == NULL) {
7687                         mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7688                         return res;
7689                 }
7690                 if (f->field->parent != klass) {
7691                         mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7692                         return res;
7693                 }
7694                 if (i == 0)
7695                         p = (guint8*)target + f->field->offset;
7696                 else
7697                         p += f->field->offset - sizeof (MonoObject);
7698                 klass = mono_class_from_mono_type (f->field->type);
7699                 ftype = f->field->type;
7700         }
7701
7702         res.type = ftype;
7703         res.klass = mono_class_from_mono_type (ftype);
7704         res.value = p;
7705
7706         return res;
7707 }
7708
7709 static void
7710 prelink_method (MonoMethod *method, MonoError *error)
7711 {
7712         const char *exc_class, *exc_arg;
7713
7714         mono_error_init (error);
7715         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7716                 return;
7717         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7718         if (exc_class) {
7719                 mono_error_set_exception_instance (error,
7720                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7721                 return;
7722         }
7723         /* create the wrapper, too? */
7724 }
7725
7726 ICALL_EXPORT void
7727 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7728 {
7729         MonoError error;
7730
7731         prelink_method (method->method, &error);
7732         mono_error_set_pending_exception (&error);
7733 }
7734
7735 ICALL_EXPORT void
7736 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7737 {
7738         MonoError error;
7739         MonoClass *klass = mono_class_from_mono_type (type->type);
7740         MonoMethod* m;
7741         gpointer iter = NULL;
7742
7743         mono_class_init_checked (klass, &error);
7744         if (mono_error_set_pending_exception (&error))
7745                 return;
7746
7747         while ((m = mono_class_get_methods (klass, &iter))) {
7748                 prelink_method (m, &error);
7749                 if (mono_error_set_pending_exception (&error))
7750                         return;
7751         }
7752 }
7753
7754 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7755 ICALL_EXPORT void
7756 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7757                                             gint32 const **exponents,
7758                                             gunichar2 const **digitLowerTable,
7759                                             gunichar2 const **digitUpperTable,
7760                                             gint64 const **tenPowersList,
7761                                             gint32 const **decHexDigits)
7762 {
7763         *mantissas = Formatter_MantissaBitsTable;
7764         *exponents = Formatter_TensExponentTable;
7765         *digitLowerTable = Formatter_DigitLowerTable;
7766         *digitUpperTable = Formatter_DigitUpperTable;
7767         *tenPowersList = Formatter_TenPowersList;
7768         *decHexDigits = Formatter_DecHexDigits;
7769 }
7770
7771 /*
7772  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7773  * and avoid useless allocations.
7774  */
7775 static MonoArray*
7776 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7777 {
7778         MonoReflectionType *rt;
7779         MonoArray *res;
7780         int i, count = 0;
7781
7782         mono_error_init (error);
7783         for (i = 0; i < type->num_mods; ++i) {
7784                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7785                         count++;
7786         }
7787         if (!count)
7788                 return NULL;
7789         res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7790         return_val_if_nok (error, NULL);
7791         count = 0;
7792         for (i = 0; i < type->num_mods; ++i) {
7793                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7794                         MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7795                         return_val_if_nok (error, NULL);
7796
7797                         rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7798                         return_val_if_nok (error, NULL);
7799
7800                         mono_array_setref (res, count, rt);
7801                         count++;
7802                 }
7803         }
7804         return res;
7805 }
7806
7807 ICALL_EXPORT MonoArray*
7808 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7809 {
7810         MonoError error;
7811         MonoType *type = param->ClassImpl->type;
7812         MonoClass *member_class = mono_object_class (param->MemberImpl);
7813         MonoMethod *method = NULL;
7814         MonoImage *image;
7815         int pos;
7816         MonoMethodSignature *sig;
7817         MonoArray *res;
7818
7819         if (mono_class_is_reflection_method_or_constructor (member_class)) {
7820                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7821                 method = rmethod->method;
7822         } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7823                 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7824                 if (!(method = prop->property->get))
7825                         method = prop->property->set;
7826                 g_assert (method);      
7827         } else {
7828                 char *type_name = mono_type_get_full_name (member_class);
7829                 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7830                 MonoException *ex = mono_get_exception_not_supported  (msg);
7831                 g_free (type_name);
7832                 g_free (msg);
7833                 mono_set_pending_exception (ex);
7834                 return NULL;
7835         }
7836
7837         image = method->klass->image;
7838         pos = param->PositionImpl;
7839         sig = mono_method_signature (method);
7840         if (pos == -1)
7841                 type = sig->ret;
7842         else
7843                 type = sig->params [pos];
7844
7845         res = type_array_from_modifiers (image, type, optional, &error);
7846         mono_error_set_pending_exception (&error);
7847         return res;
7848 }
7849
7850 static MonoType*
7851 get_property_type (MonoProperty *prop)
7852 {
7853         MonoMethodSignature *sig;
7854         if (prop->get) {
7855                 sig = mono_method_signature (prop->get);
7856                 return sig->ret;
7857         } else if (prop->set) {
7858                 sig = mono_method_signature (prop->set);
7859                 return sig->params [sig->param_count - 1];
7860         }
7861         return NULL;
7862 }
7863
7864 ICALL_EXPORT MonoArray*
7865 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7866 {
7867         MonoError error;
7868         MonoType *type = get_property_type (property->property);
7869         MonoImage *image = property->klass->image;
7870         MonoArray *res;
7871
7872         if (!type)
7873                 return NULL;
7874         res = type_array_from_modifiers (image, type, optional, &error);
7875         mono_error_set_pending_exception (&error);
7876         return res;
7877 }
7878
7879 /*
7880  *Construct a MonoType suited to be used to decode a constant blob object.
7881  *
7882  * @type is the target type which will be constructed
7883  * @blob_type is the blob type, for example, that comes from the constant table
7884  * @real_type is the expected constructed type.
7885  */
7886 static void
7887 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7888 {
7889         type->type = blob_type;
7890         type->data.klass = NULL;
7891         if (blob_type == MONO_TYPE_CLASS)
7892                 type->data.klass = mono_defaults.object_class;
7893         else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7894                 /* For enums, we need to use the base type */
7895                 type->type = MONO_TYPE_VALUETYPE;
7896                 type->data.klass = mono_class_from_mono_type (real_type);
7897         } else
7898                 type->data.klass = mono_class_from_mono_type (real_type);
7899 }
7900
7901 ICALL_EXPORT MonoObject*
7902 property_info_get_default_value (MonoReflectionProperty *property)
7903 {
7904         MonoError error;
7905         MonoType blob_type;
7906         MonoProperty *prop = property->property;
7907         MonoType *type = get_property_type (prop);
7908         MonoDomain *domain = mono_object_domain (property); 
7909         MonoTypeEnum def_type;
7910         const char *def_value;
7911         MonoObject *o;
7912
7913         mono_class_init (prop->parent);
7914
7915         if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7916                 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7917                 return NULL;
7918         }
7919
7920         def_value = mono_class_get_property_default_value (prop, &def_type);
7921
7922         mono_type_from_blob_type (&blob_type, def_type, type);
7923         o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7924
7925         mono_error_set_pending_exception (&error);
7926         return o;
7927 }
7928
7929 ICALL_EXPORT MonoBoolean
7930 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7931 {
7932         MonoError error;
7933         MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7934         MonoCustomAttrInfo *cinfo;
7935         gboolean found;
7936
7937         mono_class_init_checked (attr_class, &error);
7938         if (mono_error_set_pending_exception (&error))
7939                 return FALSE;
7940
7941         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7942         if (!is_ok (&error)) {
7943                 mono_error_set_pending_exception (&error);
7944                 return FALSE;
7945         }
7946         if (!cinfo)
7947                 return FALSE;
7948         found = mono_custom_attrs_has_attr (cinfo, attr_class);
7949         if (!cinfo->cached)
7950                 mono_custom_attrs_free (cinfo);
7951         return found;
7952 }
7953
7954 ICALL_EXPORT MonoArray*
7955 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7956 {
7957         MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7958         MonoArray *res;
7959         MonoError error;
7960
7961         if (attr_class) {
7962                 mono_class_init_checked (attr_class, &error);
7963                 if (mono_error_set_pending_exception (&error))
7964                         return NULL;
7965         }
7966
7967         res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7968         if (!mono_error_ok (&error)) {
7969                 mono_error_set_pending_exception (&error);
7970                 return NULL;
7971         }
7972
7973         return res;
7974 }
7975
7976 ICALL_EXPORT MonoArray*
7977 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7978 {
7979         MonoError error;
7980         MonoArray *result;
7981         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7982         mono_error_set_pending_exception (&error);
7983         return result;
7984 }
7985
7986
7987 ICALL_EXPORT MonoString*
7988 ves_icall_Mono_Runtime_GetDisplayName (void)
7989 {
7990         char *info;
7991         MonoString *display_name;
7992
7993         info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7994         display_name = mono_string_new (mono_domain_get (), info);
7995         g_free (info);
7996         return display_name;
7997 }
7998
7999 ICALL_EXPORT MonoString*
8000 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8001 {
8002         MonoError error;
8003         MonoString *message;
8004         guint32 ret;
8005         gunichar2 buf[256];
8006         
8007         ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8008                              FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8009                              buf, 255, NULL);
8010         if (ret == 0) {
8011                 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8012         } else {
8013                 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8014                 if (mono_error_set_pending_exception (&error))
8015                         return NULL;
8016         }
8017         
8018         return message;
8019 }
8020
8021 ICALL_EXPORT gpointer
8022 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8023 {
8024         return GetCurrentProcess ();
8025 }
8026
8027 ICALL_EXPORT MonoBoolean
8028 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8029 {
8030         return GetExitCodeProcess (handle, (guint32*) exitcode);
8031 }
8032
8033 ICALL_EXPORT MonoBoolean
8034 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8035 {
8036 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8037         return CloseHandle (handle);
8038 #else
8039         return CloseProcess (handle);
8040 #endif
8041 }
8042
8043 ICALL_EXPORT MonoBoolean
8044 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8045 {
8046         return TerminateProcess (handle, exitcode);
8047 }
8048
8049 ICALL_EXPORT gint32
8050 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8051 {
8052 #ifdef HOST_WIN32
8053         return WaitForInputIdle (handle, milliseconds);
8054 #else
8055         /*TODO: Not implemented*/
8056         return WAIT_TIMEOUT;
8057 #endif
8058 }
8059
8060 ICALL_EXPORT MonoBoolean
8061 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8062 {
8063         return GetProcessWorkingSetSize (handle, min, max);
8064 }
8065
8066 ICALL_EXPORT MonoBoolean
8067 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8068 {
8069         return SetProcessWorkingSetSize (handle, min, max);
8070 }
8071
8072 ICALL_EXPORT MonoBoolean
8073 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8074 {
8075         return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8076 }
8077
8078 ICALL_EXPORT gint32
8079 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8080 {
8081         return mono_process_current_pid ();
8082 }
8083
8084 ICALL_EXPORT gint32
8085 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8086 {
8087         return GetPriorityClass (handle);
8088 }
8089
8090 ICALL_EXPORT MonoBoolean
8091 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8092 {
8093         return SetPriorityClass (handle, priorityClass);
8094 }
8095
8096 ICALL_EXPORT MonoBoolean
8097 ves_icall_Mono_Btls_Provider_IsSupported (void)
8098 {
8099 #if HAVE_BTLS
8100         return TRUE;
8101 #else
8102         return FALSE;
8103 #endif
8104 }
8105
8106 #ifndef DISABLE_ICALL_TABLES
8107
8108 #define ICALL_TYPE(id,name,first)
8109 #define ICALL(id,name,func) Icall_ ## id,
8110 #define HANDLES(inner) inner
8111
8112 enum {
8113 #include "metadata/icall-def.h"
8114         Icall_last
8115 };
8116
8117 #undef ICALL_TYPE
8118 #undef ICALL
8119 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8120 #define ICALL(id,name,func)
8121 #undef HANDLES
8122 #define HANDLES(inner) inner
8123 enum {
8124 #include "metadata/icall-def.h"
8125         Icall_type_num
8126 };
8127
8128 #undef ICALL_TYPE
8129 #undef ICALL
8130 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8131 #define ICALL(id,name,func)
8132 #undef HANDLES
8133 #define HANDLES(inner) inner
8134 typedef struct {
8135         guint16 first_icall;
8136 } IcallTypeDesc;
8137
8138 static const IcallTypeDesc
8139 icall_type_descs [] = {
8140 #include "metadata/icall-def.h"
8141         {Icall_last}
8142 };
8143
8144 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8145
8146 #undef HANDLES
8147 #define HANDLES(inner) inner
8148 #undef ICALL_TYPE
8149 #define ICALL_TYPE(id,name,first)
8150 #undef ICALL
8151
8152 #ifdef HAVE_ARRAY_ELEM_INIT
8153 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8154 #define MSGSTRFIELD1(line) str##line
8155
8156 static const struct msgstrtn_t {
8157 #define ICALL(id,name,func)
8158 #undef ICALL_TYPE
8159 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8160 #include "metadata/icall-def.h"
8161 #undef ICALL_TYPE
8162 } icall_type_names_str = {
8163 #define ICALL_TYPE(id,name,first) (name),
8164 #include "metadata/icall-def.h"
8165 #undef ICALL_TYPE
8166 };
8167 static const guint16 icall_type_names_idx [] = {
8168 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8169 #include "metadata/icall-def.h"
8170 #undef ICALL_TYPE
8171 };
8172 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8173
8174 static const struct msgstr_t {
8175 #undef ICALL
8176 #define ICALL_TYPE(id,name,first)
8177 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8178 #include "metadata/icall-def.h"
8179 #undef ICALL
8180 } icall_names_str = {
8181 #define ICALL(id,name,func) (name),
8182 #include "metadata/icall-def.h"
8183 #undef ICALL
8184 };
8185 static const guint16 icall_names_idx [] = {
8186 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8187 #include "metadata/icall-def.h"
8188 #undef ICALL
8189 };
8190 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8191
8192 #else
8193
8194 #undef ICALL_TYPE
8195 #undef ICALL
8196 #define ICALL_TYPE(id,name,first) name,
8197 #define ICALL(id,name,func)
8198 static const char* const
8199 icall_type_names [] = {
8200 #include "metadata/icall-def.h"
8201         NULL
8202 };
8203
8204 #define icall_type_name_get(id) (icall_type_names [(id)])
8205
8206 #undef ICALL_TYPE
8207 #undef ICALL
8208 #define ICALL_TYPE(id,name,first)
8209 #define ICALL(id,name,func) name,
8210 static const char* const
8211 icall_names [] = {
8212 #include "metadata/icall-def.h"
8213         NULL
8214 };
8215 #define icall_name_get(id) icall_names [(id)]
8216
8217 #endif /* !HAVE_ARRAY_ELEM_INIT */
8218
8219 #undef HANDLES
8220 #define HANDLES(inner) inner
8221 #undef ICALL_TYPE
8222 #undef ICALL
8223 #define ICALL_TYPE(id,name,first)
8224 #define ICALL(id,name,func) func,
8225 static const gconstpointer
8226 icall_functions [] = {
8227 #include "metadata/icall-def.h"
8228         NULL
8229 };
8230
8231 #ifdef ENABLE_ICALL_SYMBOL_MAP
8232 #undef HANDLES
8233 #define HANDLES(inner) inner
8234 #undef ICALL_TYPE
8235 #undef ICALL
8236 #define ICALL_TYPE(id,name,first)
8237 #define ICALL(id,name,func) #func,
8238 static const gconstpointer
8239 icall_symbols [] = {
8240 #include "metadata/icall-def.h"
8241         NULL
8242 };
8243 #endif
8244
8245 #undef ICALL_TYPE
8246 #undef ICALL
8247 #define ICALL_TYPE(id,name,first)
8248 #define ICALL(id,name,func) 0,
8249 #undef HANDLES
8250 #define HANDLES(inner) 1,
8251 static const guchar
8252 icall_uses_handles [] = {
8253 #include "metadata/icall-def.h"
8254 #undef ICALL
8255 #undef HANDLES
8256 };
8257
8258 #endif /* DISABLE_ICALL_TABLES */
8259
8260 static mono_mutex_t icall_mutex;
8261 static GHashTable *icall_hash = NULL;
8262 static GHashTable *jit_icall_hash_name = NULL;
8263 static GHashTable *jit_icall_hash_addr = NULL;
8264
8265 void
8266 mono_icall_init (void)
8267 {
8268 #ifndef DISABLE_ICALL_TABLES
8269         int i = 0;
8270
8271         /* check that tables are sorted: disable in release */
8272         if (TRUE) {
8273                 int j;
8274                 const char *prev_class = NULL;
8275                 const char *prev_method;
8276                 
8277                 for (i = 0; i < Icall_type_num; ++i) {
8278                         const IcallTypeDesc *desc;
8279                         int num_icalls;
8280                         prev_method = NULL;
8281                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8282                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8283                         prev_class = icall_type_name_get (i);
8284                         desc = &icall_type_descs [i];
8285                         num_icalls = icall_desc_num_icalls (desc);
8286                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8287                         for (j = 0; j < num_icalls; ++j) {
8288                                 const char *methodn = icall_name_get (desc->first_icall + j);
8289                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
8290                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
8291                                 prev_method = methodn;
8292                         }
8293                 }
8294         }
8295 #endif
8296
8297         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8298         mono_os_mutex_init (&icall_mutex);
8299 }
8300
8301 static void
8302 mono_icall_lock (void)
8303 {
8304         mono_locks_os_acquire (&icall_mutex, IcallLock);
8305 }
8306
8307 static void
8308 mono_icall_unlock (void)
8309 {
8310         mono_locks_os_release (&icall_mutex, IcallLock);
8311 }
8312
8313 void
8314 mono_icall_cleanup (void)
8315 {
8316         g_hash_table_destroy (icall_hash);
8317         g_hash_table_destroy (jit_icall_hash_name);
8318         g_hash_table_destroy (jit_icall_hash_addr);
8319         mono_os_mutex_destroy (&icall_mutex);
8320 }
8321
8322 /**
8323  * mono_add_internal_call:
8324  * @name: method specification to surface to the managed world
8325  * @method: pointer to a C method to invoke when the method is called
8326  *
8327  * This method surfaces the C function pointed by @method as a method
8328  * that has been surfaced in managed code with the method specified in
8329  * @name as an internal call.
8330  *
8331  * Internal calls are surfaced to all app domains loaded and they are
8332  * accessibly by a type with the specified name.
8333  *
8334  * You must provide a fully qualified type name, that is namespaces
8335  * and type name, followed by a colon and the method name, with an
8336  * optional signature to bind.
8337  *
8338  * For example, the following are all valid declarations:
8339  *
8340  * "MyApp.Services.ScriptService:Accelerate"
8341  * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8342  *
8343  * You use method parameters in cases where there might be more than
8344  * one surface method to managed code.  That way you can register different
8345  * internal calls for different method overloads.
8346  *
8347  * The internal calls are invoked with no marshalling.   This means that .NET
8348  * types like System.String are exposed as `MonoString *` parameters.   This is
8349  * different than the way that strings are surfaced in P/Invoke.
8350  *
8351  * For more information on how the parameters are marshalled, see the
8352  * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8353  * page.
8354  *
8355  * See the <a  href="mono-api-methods.html#method-desc">Method Description</a>
8356  * reference for more information on the format of method descriptions.
8357  */
8358 void
8359 mono_add_internal_call (const char *name, gconstpointer method)
8360 {
8361         mono_icall_lock ();
8362
8363         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8364
8365         mono_icall_unlock ();
8366 }
8367
8368 #ifndef DISABLE_ICALL_TABLES
8369
8370 #ifdef HAVE_ARRAY_ELEM_INIT
8371 static int
8372 compare_method_imap (const void *key, const void *elem)
8373 {
8374         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8375         return strcmp (key, method_name);
8376 }
8377
8378 static gsize
8379 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8380 {
8381         const 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);
8382         if (!nameslot)
8383                 return -1;
8384         return (nameslot - &icall_names_idx [0]);
8385 }
8386
8387 static gboolean
8388 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8389 {
8390         gsize slotnum = find_slot_icall (imap, name);
8391         if (slotnum == -1)
8392                 return FALSE;
8393         return (gboolean)icall_uses_handles [slotnum];
8394 }
8395
8396 static gpointer
8397 find_method_icall (const IcallTypeDesc *imap, const char *name)
8398 {
8399         gsize slotnum = find_slot_icall (imap, name);
8400         if (slotnum == -1)
8401                 return NULL;
8402         return (gpointer)icall_functions [slotnum];
8403 }
8404
8405 static int
8406 compare_class_imap (const void *key, const void *elem)
8407 {
8408         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8409         return strcmp (key, class_name);
8410 }
8411
8412 static const IcallTypeDesc*
8413 find_class_icalls (const char *name)
8414 {
8415         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);
8416         if (!nameslot)
8417                 return NULL;
8418         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8419 }
8420
8421 #else /* HAVE_ARRAY_ELEM_INIT */
8422
8423 static int
8424 compare_method_imap (const void *key, const void *elem)
8425 {
8426         const char** method_name = (const char**)elem;
8427         return strcmp (key, *method_name);
8428 }
8429
8430 static gsize
8431 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8432 {
8433         const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8434         if (!nameslot)
8435                 return -1;
8436         return nameslot - icall_names;
8437 }
8438
8439 static gpointer
8440 find_method_icall (const IcallTypeDesc *imap, const char *name)
8441 {
8442         gsize slotnum = find_slot_icall (imap, name);
8443         if (slotnum == -1)
8444                 return NULL;
8445         return (gpointer)icall_functions [slotnum];
8446 }
8447
8448 static gboolean
8449 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8450 {
8451         gsize slotnum = find_slot_icall (imap, name);
8452         if (slotnum == -1)
8453                 return FALSE;
8454         return (gboolean)icall_uses_handles [slotnum];
8455 }
8456
8457 static int
8458 compare_class_imap (const void *key, const void *elem)
8459 {
8460         const char** class_name = (const char**)elem;
8461         return strcmp (key, *class_name);
8462 }
8463
8464 static const IcallTypeDesc*
8465 find_class_icalls (const char *name)
8466 {
8467         const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8468         if (!nameslot)
8469                 return NULL;
8470         return &icall_type_descs [nameslot - icall_type_names];
8471 }
8472
8473 #endif /* HAVE_ARRAY_ELEM_INIT */
8474
8475 #endif /* DISABLE_ICALL_TABLES */
8476
8477 /* 
8478  * we should probably export this as an helper (handle nested types).
8479  * Returns the number of chars written in buf.
8480  */
8481 static int
8482 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8483 {
8484         int nspacelen, cnamelen;
8485         nspacelen = strlen (klass->name_space);
8486         cnamelen = strlen (klass->name);
8487         if (nspacelen + cnamelen + 2 > bufsize)
8488                 return 0;
8489         if (nspacelen) {
8490                 memcpy (buf, klass->name_space, nspacelen);
8491                 buf [nspacelen ++] = '.';
8492         }
8493         memcpy (buf + nspacelen, klass->name, cnamelen);
8494         buf [nspacelen + cnamelen] = 0;
8495         return nspacelen + cnamelen;
8496 }
8497
8498 #ifdef DISABLE_ICALL_TABLES
8499 static void
8500 no_icall_table (void)
8501 {
8502         g_assert_not_reached ();
8503 }
8504 #endif
8505
8506 /**
8507  * mono_lookup_internal_call_full:
8508  * @method: the method to look up
8509  * @uses_handles: out argument if method needs handles around managed objects.
8510  *
8511  * Returns a pointer to the icall code for the given method.  If
8512  * uses_handles is not NULL, it will be set to TRUE if the method
8513  * needs managed objects wrapped using the infrastructure in handle.h
8514  *
8515  * If the method is not found, warns and returns NULL.
8516  */
8517 gpointer
8518 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8519 {
8520         char *sigstart;
8521         char *tmpsig;
8522         char mname [2048];
8523         int typelen = 0, mlen, siglen;
8524         gpointer res;
8525 #ifndef DISABLE_ICALL_TABLES
8526         const IcallTypeDesc *imap = NULL;
8527 #endif
8528
8529         g_assert (method != NULL);
8530
8531         if (method->is_inflated)
8532                 method = ((MonoMethodInflated *) method)->declaring;
8533
8534         if (method->klass->nested_in) {
8535                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8536                 if (!pos)
8537                         return NULL;
8538
8539                 mname [pos++] = '/';
8540                 mname [pos] = 0;
8541
8542                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8543                 if (!typelen)
8544                         return NULL;
8545
8546                 typelen += pos;
8547         } else {
8548                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8549                 if (!typelen)
8550                         return NULL;
8551         }
8552
8553 #ifndef DISABLE_ICALL_TABLES
8554         imap = find_class_icalls (mname);
8555 #endif
8556
8557         mname [typelen] = ':';
8558         mname [typelen + 1] = ':';
8559
8560         mlen = strlen (method->name);
8561         memcpy (mname + typelen + 2, method->name, mlen);
8562         sigstart = mname + typelen + 2 + mlen;
8563         *sigstart = 0;
8564
8565         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8566         siglen = strlen (tmpsig);
8567         if (typelen + mlen + siglen + 6 > sizeof (mname))
8568                 return NULL;
8569         sigstart [0] = '(';
8570         memcpy (sigstart + 1, tmpsig, siglen);
8571         sigstart [siglen + 1] = ')';
8572         sigstart [siglen + 2] = 0;
8573         g_free (tmpsig);
8574         
8575         mono_icall_lock ();
8576
8577         res = g_hash_table_lookup (icall_hash, mname);
8578         if (res) {
8579                 if (uses_handles)
8580                         *uses_handles = FALSE;
8581                 mono_icall_unlock ();;
8582                 return res;
8583         }
8584         /* try without signature */
8585         *sigstart = 0;
8586         res = g_hash_table_lookup (icall_hash, mname);
8587         if (res) {
8588                 if (uses_handles)
8589                         *uses_handles = FALSE;
8590                 mono_icall_unlock ();
8591                 return res;
8592         }
8593
8594 #ifdef DISABLE_ICALL_TABLES
8595         mono_icall_unlock ();
8596         /* Fail only when the result is actually used */
8597         /* mono_marshal_get_native_wrapper () depends on this */
8598         if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8599                 return ves_icall_System_String_ctor_RedirectToCreateString;
8600         else
8601                 return no_icall_table;
8602 #else
8603         /* it wasn't found in the static call tables */
8604         if (!imap) {
8605                 if (uses_handles)
8606                         *uses_handles = FALSE;
8607                 mono_icall_unlock ();
8608                 return NULL;
8609         }
8610         res = find_method_icall (imap, sigstart - mlen);
8611         if (res) {
8612                 if (uses_handles)
8613                         *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8614                 mono_icall_unlock ();
8615                 return res;
8616         }
8617         /* try _with_ signature */
8618         *sigstart = '(';
8619         res = find_method_icall (imap, sigstart - mlen);
8620         if (res) {
8621                 if (uses_handles)
8622                         *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8623                 mono_icall_unlock ();
8624                 return res;
8625         }
8626
8627         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8628         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8629         g_print ("The out of sync library is: %s\n", method->klass->image->name);
8630         g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8631         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");
8632         g_print ("If you see other errors or faults after this message they are probably related\n");
8633         g_print ("and you need to fix your mono install first.\n");
8634
8635         mono_icall_unlock ();
8636
8637         return NULL;
8638 #endif
8639 }
8640
8641 gpointer
8642 mono_lookup_internal_call (MonoMethod *method)
8643 {
8644         return mono_lookup_internal_call_full (method, NULL);
8645 }
8646
8647 #ifdef ENABLE_ICALL_SYMBOL_MAP
8648 static int
8649 func_cmp (gconstpointer key, gconstpointer p)
8650 {
8651         return (gsize)key - (gsize)*(gsize*)p;
8652 }
8653 #endif
8654
8655 /*
8656  * mono_lookup_icall_symbol:
8657  *
8658  *   Given the icall METHOD, returns its C symbol.
8659  */
8660 const char*
8661 mono_lookup_icall_symbol (MonoMethod *m)
8662 {
8663 #ifdef DISABLE_ICALL_TABLES
8664         g_assert_not_reached ();
8665         return NULL;
8666 #else
8667 #ifdef ENABLE_ICALL_SYMBOL_MAP
8668         gpointer func;
8669         int i;
8670         gpointer slot;
8671         static gconstpointer *functions_sorted;
8672         static const char**symbols_sorted;
8673         static gboolean inited;
8674
8675         if (!inited) {
8676                 gboolean changed;
8677
8678                 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8679                 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8680                 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8681                 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8682                 /* Bubble sort the two arrays */
8683                 changed = TRUE;
8684                 while (changed) {
8685                         changed = FALSE;
8686                         for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8687                                 if (functions_sorted [i] > functions_sorted [i + 1]) {
8688                                         gconstpointer tmp;
8689
8690                                         tmp = functions_sorted [i];
8691                                         functions_sorted [i] = functions_sorted [i + 1];
8692                                         functions_sorted [i + 1] = tmp;
8693                                         tmp = symbols_sorted [i];
8694                                         symbols_sorted [i] = symbols_sorted [i + 1];
8695                                         symbols_sorted [i + 1] = tmp;
8696                                         changed = TRUE;
8697                                 }
8698                         }
8699                 }
8700         }
8701
8702         func = mono_lookup_internal_call (m);
8703         if (!func)
8704                 return NULL;
8705         slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8706         if (!slot)
8707                 return NULL;
8708         g_assert (slot);
8709         return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8710 #else
8711         fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8712         g_assert_not_reached ();
8713         return 0;
8714 #endif
8715 #endif
8716 }
8717
8718 static MonoType*
8719 type_from_typename (char *type_name)
8720 {
8721         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
8722
8723         if (!strcmp (type_name, "int"))
8724                 klass = mono_defaults.int_class;
8725         else if (!strcmp (type_name, "ptr"))
8726                 klass = mono_defaults.int_class;
8727         else if (!strcmp (type_name, "void"))
8728                 klass = mono_defaults.void_class;
8729         else if (!strcmp (type_name, "int32"))
8730                 klass = mono_defaults.int32_class;
8731         else if (!strcmp (type_name, "uint32"))
8732                 klass = mono_defaults.uint32_class;
8733         else if (!strcmp (type_name, "int8"))
8734                 klass = mono_defaults.sbyte_class;
8735         else if (!strcmp (type_name, "uint8"))
8736                 klass = mono_defaults.byte_class;
8737         else if (!strcmp (type_name, "int16"))
8738                 klass = mono_defaults.int16_class;
8739         else if (!strcmp (type_name, "uint16"))
8740                 klass = mono_defaults.uint16_class;
8741         else if (!strcmp (type_name, "long"))
8742                 klass = mono_defaults.int64_class;
8743         else if (!strcmp (type_name, "ulong"))
8744                 klass = mono_defaults.uint64_class;
8745         else if (!strcmp (type_name, "float"))
8746                 klass = mono_defaults.single_class;
8747         else if (!strcmp (type_name, "double"))
8748                 klass = mono_defaults.double_class;
8749         else if (!strcmp (type_name, "object"))
8750                 klass = mono_defaults.object_class;
8751         else if (!strcmp (type_name, "obj"))
8752                 klass = mono_defaults.object_class;
8753         else if (!strcmp (type_name, "string"))
8754                 klass = mono_defaults.string_class;
8755         else if (!strcmp (type_name, "bool"))
8756                 klass = mono_defaults.boolean_class;
8757         else if (!strcmp (type_name, "boolean"))
8758                 klass = mono_defaults.boolean_class;
8759         else {
8760                 g_error ("%s", type_name);
8761                 g_assert_not_reached ();
8762         }
8763         return &klass->byval_arg;
8764 }
8765
8766 /**
8767  * LOCKING: Take the corlib image lock.
8768  */
8769 MonoMethodSignature*
8770 mono_create_icall_signature (const char *sigstr)
8771 {
8772         gchar **parts;
8773         int i, len;
8774         gchar **tmp;
8775         MonoMethodSignature *res, *res2;
8776         MonoImage *corlib = mono_defaults.corlib;
8777
8778         mono_image_lock (corlib);
8779         res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8780         mono_image_unlock (corlib);
8781
8782         if (res)
8783                 return res;
8784
8785         parts = g_strsplit (sigstr, " ", 256);
8786
8787         tmp = parts;
8788         len = 0;
8789         while (*tmp) {
8790                 len ++;
8791                 tmp ++;
8792         }
8793
8794         res = mono_metadata_signature_alloc (corlib, len - 1);
8795         res->pinvoke = 1;
8796
8797 #ifdef HOST_WIN32
8798         /* 
8799          * Under windows, the default pinvoke calling convention is STDCALL but
8800          * we need CDECL.
8801          */
8802         res->call_convention = MONO_CALL_C;
8803 #endif
8804
8805         res->ret = type_from_typename (parts [0]);
8806         for (i = 1; i < len; ++i) {
8807                 res->params [i - 1] = type_from_typename (parts [i]);
8808         }
8809
8810         g_strfreev (parts);
8811
8812         mono_image_lock (corlib);
8813         res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8814         if (res2)
8815                 res = res2; /*Value is allocated in the image pool*/
8816         else
8817                 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8818         mono_image_unlock (corlib);
8819
8820         return res;
8821 }
8822
8823 MonoJitICallInfo *
8824 mono_find_jit_icall_by_name (const char *name)
8825 {
8826         MonoJitICallInfo *info;
8827         g_assert (jit_icall_hash_name);
8828
8829         mono_icall_lock ();
8830         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8831         mono_icall_unlock ();
8832         return info;
8833 }
8834
8835 MonoJitICallInfo *
8836 mono_find_jit_icall_by_addr (gconstpointer addr)
8837 {
8838         MonoJitICallInfo *info;
8839         g_assert (jit_icall_hash_addr);
8840
8841         mono_icall_lock ();
8842         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8843         mono_icall_unlock ();
8844
8845         return info;
8846 }
8847
8848 /*
8849  * mono_get_jit_icall_info:
8850  *
8851  *   Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8852  * caller should access it while holding the icall lock.
8853  */
8854 GHashTable*
8855 mono_get_jit_icall_info (void)
8856 {
8857         return jit_icall_hash_name;
8858 }
8859
8860 /*
8861  * mono_lookup_jit_icall_symbol:
8862  *
8863  *   Given the jit icall NAME, returns its C symbol if possible, or NULL.
8864  */
8865 const char*
8866 mono_lookup_jit_icall_symbol (const char *name)
8867 {
8868         MonoJitICallInfo *info;
8869         const char *res = NULL;
8870
8871         mono_icall_lock ();
8872         info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8873         if (info)
8874                 res = info->c_symbol;
8875         mono_icall_unlock ();
8876         return res;
8877 }
8878
8879 void
8880 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8881 {
8882         mono_icall_lock ();
8883         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8884         mono_icall_unlock ();
8885 }
8886
8887 /*
8888  * 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
8889  * icalls without wrappers in some cases.
8890  */
8891 MonoJitICallInfo *
8892 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8893 {
8894         MonoJitICallInfo *info;
8895         
8896         g_assert (func);
8897         g_assert (name);
8898
8899         mono_icall_lock ();
8900
8901         if (!jit_icall_hash_name) {
8902                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8903                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8904         }
8905
8906         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8907                 g_warning ("jit icall already defined \"%s\"\n", name);
8908                 g_assert_not_reached ();
8909         }
8910
8911         info = g_new0 (MonoJitICallInfo, 1);
8912         
8913         info->name = name;
8914         info->func = func;
8915         info->sig = sig;
8916         info->c_symbol = c_symbol;
8917         info->no_raise = no_raise;
8918
8919         if (is_save) {
8920                 info->wrapper = func;
8921         } else {
8922                 info->wrapper = NULL;
8923         }
8924
8925         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8926         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8927
8928         mono_icall_unlock ();
8929         return info;
8930 }
8931
8932 MonoJitICallInfo *
8933 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8934 {
8935         return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);
8936 }
8937