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