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