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