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