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