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