[corlib] Bring AssemblyName(string) to the happy C# world.
[mono-project.git] / mono / metadata / icall.c
blob2e3240354898d39ce5f3facc3d931fe501e45420
1 /*
2 * icall.c:
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)
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 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
17 #include <config.h>
18 #include <glib.h>
19 #include <stdarg.h>
20 #include <string.h>
21 #include <ctype.h>
22 #ifdef HAVE_ALLOCA_H
23 #include <alloca.h>
24 #endif
25 #ifdef HAVE_SYS_TIME_H
26 #include <sys/time.h>
27 #endif
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31 #if defined (HOST_WIN32)
32 #include <stdlib.h>
33 #endif
34 #if defined (HAVE_WCHAR_H)
35 #include <wchar.h>
36 #endif
38 #include "mono/utils/mono-membar.h"
39 #include <mono/metadata/object.h>
40 #include <mono/metadata/threads.h>
41 #include <mono/metadata/threads-types.h>
42 #include <mono/metadata/threadpool-ms.h>
43 #include <mono/metadata/threadpool-ms-io.h>
44 #include <mono/metadata/monitor.h>
45 #include <mono/metadata/reflection.h>
46 #include <mono/metadata/assembly.h>
47 #include <mono/metadata/tabledefs.h>
48 #include <mono/metadata/exception.h>
49 #include <mono/metadata/exception-internals.h>
50 #include <mono/metadata/file-io.h>
51 #include <mono/metadata/console-io.h>
52 #include <mono/metadata/mono-route.h>
53 #include <mono/metadata/socket-io.h>
54 #include <mono/metadata/mono-endian.h>
55 #include <mono/metadata/tokentype.h>
56 #include <mono/metadata/domain-internals.h>
57 #include <mono/metadata/metadata-internals.h>
58 #include <mono/metadata/class-internals.h>
59 #include <mono/metadata/reflection-internals.h>
60 #include <mono/metadata/marshal.h>
61 #include <mono/metadata/gc-internals.h>
62 #include <mono/metadata/mono-gc.h>
63 #include <mono/metadata/rand.h>
64 #include <mono/metadata/sysmath.h>
65 #include <mono/metadata/string-icalls.h>
66 #include <mono/metadata/debug-helpers.h>
67 #include <mono/metadata/process.h>
68 #include <mono/metadata/environment.h>
69 #include <mono/metadata/profiler-private.h>
70 #include <mono/metadata/locales.h>
71 #include <mono/metadata/filewatcher.h>
72 #include <mono/metadata/security.h>
73 #include <mono/metadata/mono-config.h>
74 #include <mono/metadata/cil-coff.h>
75 #include <mono/metadata/number-formatter.h>
76 #include <mono/metadata/security-manager.h>
77 #include <mono/metadata/security-core-clr.h>
78 #include <mono/metadata/mono-perfcounters.h>
79 #include <mono/metadata/mono-debug.h>
80 #include <mono/metadata/mono-ptr-array.h>
81 #include <mono/metadata/verify-internals.h>
82 #include <mono/metadata/runtime.h>
83 #include <mono/metadata/file-mmap.h>
84 #include <mono/metadata/seq-points-data.h>
85 #include <mono/io-layer/io-layer.h>
86 #include <mono/utils/monobitset.h>
87 #include <mono/utils/mono-time.h>
88 #include <mono/utils/mono-proclib.h>
89 #include <mono/utils/mono-string.h>
90 #include <mono/utils/mono-error-internals.h>
91 #include <mono/utils/mono-mmap.h>
92 #include <mono/utils/mono-io-portability.h>
93 #include <mono/utils/mono-digest.h>
94 #include <mono/utils/bsearch.h>
95 #include <mono/utils/mono-os-mutex.h>
96 #include <mono/utils/mono-threads.h>
98 #if defined (HOST_WIN32)
99 #include <windows.h>
100 #include <shlobj.h>
101 #endif
102 #include "decimal-ms.h"
103 #include "number-ms.h"
105 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
106 #include <sys/utsname.h>
107 #endif
109 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
111 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
113 /* Lazy class loading functions */
114 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
115 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
116 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
119 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
121 static MonoArray*
122 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
124 static inline MonoBoolean
125 is_generic_parameter (MonoType *type)
127 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
130 static void
131 mono_class_init_checked (MonoClass *klass, MonoError *error)
133 mono_error_init (error);
135 if (!mono_class_init (klass))
136 mono_error_set_for_class_failure (error, klass);
139 ICALL_EXPORT MonoObject *
140 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
142 MonoError error;
143 MonoClass *ac;
144 gint32 esize;
145 gpointer *ea;
146 MonoObject *result = NULL;
148 ac = (MonoClass *)arr->obj.vtable->klass;
150 esize = mono_array_element_size (ac);
151 ea = (gpointer*)((char*)arr->vector + (pos * esize));
153 if (ac->element_class->valuetype) {
154 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
155 mono_error_set_pending_exception (&error);
156 } else
157 result = (MonoObject *)*ea;
158 return result;
161 ICALL_EXPORT MonoObject *
162 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
164 MonoClass *ac, *ic;
165 MonoArray *io;
166 gint32 i, pos, *ind;
168 MONO_CHECK_ARG_NULL (idxs, NULL);
170 io = idxs;
171 ic = (MonoClass *)io->obj.vtable->klass;
173 ac = (MonoClass *)arr->obj.vtable->klass;
175 g_assert (ic->rank == 1);
176 if (io->bounds != NULL || io->max_length != ac->rank) {
177 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
178 return NULL;
181 ind = (gint32 *)io->vector;
183 if (arr->bounds == NULL) {
184 if (*ind < 0 || *ind >= arr->max_length) {
185 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
186 return NULL;
189 return ves_icall_System_Array_GetValueImpl (arr, *ind);
192 for (i = 0; i < ac->rank; i++) {
193 if ((ind [i] < arr->bounds [i].lower_bound) ||
194 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
195 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
196 return NULL;
200 pos = ind [0] - arr->bounds [0].lower_bound;
201 for (i = 1; i < ac->rank; i++)
202 pos = pos * arr->bounds [i].length + ind [i] -
203 arr->bounds [i].lower_bound;
205 return ves_icall_System_Array_GetValueImpl (arr, pos);
208 ICALL_EXPORT void
209 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
211 MonoError error;
212 MonoClass *ac, *vc, *ec;
213 gint32 esize, vsize;
214 gpointer *ea, *va;
215 int et, vt;
217 guint64 u64 = 0;
218 gint64 i64 = 0;
219 gdouble r64 = 0;
221 mono_error_init (&error);
223 if (value)
224 vc = value->vtable->klass;
225 else
226 vc = NULL;
228 ac = arr->obj.vtable->klass;
229 ec = ac->element_class;
231 esize = mono_array_element_size (ac);
232 ea = (gpointer*)((char*)arr->vector + (pos * esize));
233 va = (gpointer*)((char*)value + sizeof (MonoObject));
235 if (mono_class_is_nullable (ec)) {
236 mono_nullable_init ((guint8*)ea, value, ec);
237 return;
240 if (!value) {
241 mono_gc_bzero_atomic (ea, esize);
242 return;
245 #define NO_WIDENING_CONVERSION G_STMT_START{\
246 mono_set_pending_exception (mono_get_exception_argument ( \
247 "value", "not a widening conversion")); \
248 return; \
249 }G_STMT_END
251 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
252 if (esize < vsize + (extra)) { \
253 mono_set_pending_exception (mono_get_exception_argument ( \
254 "value", "not a widening conversion")); \
255 return; \
257 }G_STMT_END
259 #define INVALID_CAST G_STMT_START{ \
260 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
261 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
262 return; \
263 }G_STMT_END
265 /* Check element (destination) type. */
266 switch (ec->byval_arg.type) {
267 case MONO_TYPE_STRING:
268 switch (vc->byval_arg.type) {
269 case MONO_TYPE_STRING:
270 break;
271 default:
272 INVALID_CAST;
274 break;
275 case MONO_TYPE_BOOLEAN:
276 switch (vc->byval_arg.type) {
277 case MONO_TYPE_BOOLEAN:
278 break;
279 case MONO_TYPE_CHAR:
280 case MONO_TYPE_U1:
281 case MONO_TYPE_U2:
282 case MONO_TYPE_U4:
283 case MONO_TYPE_U8:
284 case MONO_TYPE_I1:
285 case MONO_TYPE_I2:
286 case MONO_TYPE_I4:
287 case MONO_TYPE_I8:
288 case MONO_TYPE_R4:
289 case MONO_TYPE_R8:
290 NO_WIDENING_CONVERSION;
291 default:
292 INVALID_CAST;
294 break;
295 default:
296 break;
299 if (!ec->valuetype) {
300 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
301 if (mono_error_set_pending_exception (&error))
302 return;
303 if (!castOk)
304 INVALID_CAST;
305 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
306 return;
309 if (mono_object_isinst_checked (value, ec, &error)) {
310 if (ec->has_references)
311 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
312 else
313 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
314 return;
316 if (mono_error_set_pending_exception (&error))
317 return;
319 if (!vc->valuetype)
320 INVALID_CAST;
322 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
324 et = ec->byval_arg.type;
325 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
326 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
328 vt = vc->byval_arg.type;
329 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
330 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
332 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
333 switch (vt) { \
334 case MONO_TYPE_U1: \
335 case MONO_TYPE_U2: \
336 case MONO_TYPE_U4: \
337 case MONO_TYPE_U8: \
338 case MONO_TYPE_CHAR: \
339 CHECK_WIDENING_CONVERSION(0); \
340 *(etype *) ea = (etype) u64; \
341 return; \
342 /* You can't assign a signed value to an unsigned array. */ \
343 case MONO_TYPE_I1: \
344 case MONO_TYPE_I2: \
345 case MONO_TYPE_I4: \
346 case MONO_TYPE_I8: \
347 /* You can't assign a floating point number to an integer array. */ \
348 case MONO_TYPE_R4: \
349 case MONO_TYPE_R8: \
350 NO_WIDENING_CONVERSION; \
352 }G_STMT_END
354 #define ASSIGN_SIGNED(etype) G_STMT_START{\
355 switch (vt) { \
356 case MONO_TYPE_I1: \
357 case MONO_TYPE_I2: \
358 case MONO_TYPE_I4: \
359 case MONO_TYPE_I8: \
360 CHECK_WIDENING_CONVERSION(0); \
361 *(etype *) ea = (etype) i64; \
362 return; \
363 /* You can assign an unsigned value to a signed array if the array's */ \
364 /* element size is larger than the value size. */ \
365 case MONO_TYPE_U1: \
366 case MONO_TYPE_U2: \
367 case MONO_TYPE_U4: \
368 case MONO_TYPE_U8: \
369 case MONO_TYPE_CHAR: \
370 CHECK_WIDENING_CONVERSION(1); \
371 *(etype *) ea = (etype) u64; \
372 return; \
373 /* You can't assign a floating point number to an integer array. */ \
374 case MONO_TYPE_R4: \
375 case MONO_TYPE_R8: \
376 NO_WIDENING_CONVERSION; \
378 }G_STMT_END
380 #define ASSIGN_REAL(etype) G_STMT_START{\
381 switch (vt) { \
382 case MONO_TYPE_R4: \
383 case MONO_TYPE_R8: \
384 CHECK_WIDENING_CONVERSION(0); \
385 *(etype *) ea = (etype) r64; \
386 return; \
387 /* All integer values fit into a floating point array, so we don't */ \
388 /* need to CHECK_WIDENING_CONVERSION here. */ \
389 case MONO_TYPE_I1: \
390 case MONO_TYPE_I2: \
391 case MONO_TYPE_I4: \
392 case MONO_TYPE_I8: \
393 *(etype *) ea = (etype) i64; \
394 return; \
395 case MONO_TYPE_U1: \
396 case MONO_TYPE_U2: \
397 case MONO_TYPE_U4: \
398 case MONO_TYPE_U8: \
399 case MONO_TYPE_CHAR: \
400 *(etype *) ea = (etype) u64; \
401 return; \
403 }G_STMT_END
405 switch (vt) {
406 case MONO_TYPE_U1:
407 u64 = *(guint8 *) va;
408 break;
409 case MONO_TYPE_U2:
410 u64 = *(guint16 *) va;
411 break;
412 case MONO_TYPE_U4:
413 u64 = *(guint32 *) va;
414 break;
415 case MONO_TYPE_U8:
416 u64 = *(guint64 *) va;
417 break;
418 case MONO_TYPE_I1:
419 i64 = *(gint8 *) va;
420 break;
421 case MONO_TYPE_I2:
422 i64 = *(gint16 *) va;
423 break;
424 case MONO_TYPE_I4:
425 i64 = *(gint32 *) va;
426 break;
427 case MONO_TYPE_I8:
428 i64 = *(gint64 *) va;
429 break;
430 case MONO_TYPE_R4:
431 r64 = *(gfloat *) va;
432 break;
433 case MONO_TYPE_R8:
434 r64 = *(gdouble *) va;
435 break;
436 case MONO_TYPE_CHAR:
437 u64 = *(guint16 *) va;
438 break;
439 case MONO_TYPE_BOOLEAN:
440 /* Boolean is only compatible with itself. */
441 switch (et) {
442 case MONO_TYPE_CHAR:
443 case MONO_TYPE_U1:
444 case MONO_TYPE_U2:
445 case MONO_TYPE_U4:
446 case MONO_TYPE_U8:
447 case MONO_TYPE_I1:
448 case MONO_TYPE_I2:
449 case MONO_TYPE_I4:
450 case MONO_TYPE_I8:
451 case MONO_TYPE_R4:
452 case MONO_TYPE_R8:
453 NO_WIDENING_CONVERSION;
454 default:
455 INVALID_CAST;
457 break;
460 /* If we can't do a direct copy, let's try a widening conversion. */
461 switch (et) {
462 case MONO_TYPE_CHAR:
463 ASSIGN_UNSIGNED (guint16);
464 case MONO_TYPE_U1:
465 ASSIGN_UNSIGNED (guint8);
466 case MONO_TYPE_U2:
467 ASSIGN_UNSIGNED (guint16);
468 case MONO_TYPE_U4:
469 ASSIGN_UNSIGNED (guint32);
470 case MONO_TYPE_U8:
471 ASSIGN_UNSIGNED (guint64);
472 case MONO_TYPE_I1:
473 ASSIGN_SIGNED (gint8);
474 case MONO_TYPE_I2:
475 ASSIGN_SIGNED (gint16);
476 case MONO_TYPE_I4:
477 ASSIGN_SIGNED (gint32);
478 case MONO_TYPE_I8:
479 ASSIGN_SIGNED (gint64);
480 case MONO_TYPE_R4:
481 ASSIGN_REAL (gfloat);
482 case MONO_TYPE_R8:
483 ASSIGN_REAL (gdouble);
486 INVALID_CAST;
487 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
488 return;
490 #undef INVALID_CAST
491 #undef NO_WIDENING_CONVERSION
492 #undef CHECK_WIDENING_CONVERSION
493 #undef ASSIGN_UNSIGNED
494 #undef ASSIGN_SIGNED
495 #undef ASSIGN_REAL
498 ICALL_EXPORT void
499 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
500 MonoArray *idxs)
502 MonoClass *ac, *ic;
503 gint32 i, pos, *ind;
505 MONO_CHECK_ARG_NULL (idxs,);
507 ic = idxs->obj.vtable->klass;
508 ac = arr->obj.vtable->klass;
510 g_assert (ic->rank == 1);
511 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
512 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
513 return;
516 ind = (gint32 *)idxs->vector;
518 if (arr->bounds == NULL) {
519 if (*ind < 0 || *ind >= arr->max_length) {
520 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
521 return;
524 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
525 return;
528 for (i = 0; i < ac->rank; i++)
529 if ((ind [i] < arr->bounds [i].lower_bound) ||
530 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
531 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
532 return;
535 pos = ind [0] - arr->bounds [0].lower_bound;
536 for (i = 1; i < ac->rank; i++)
537 pos = pos * arr->bounds [i].length + ind [i] -
538 arr->bounds [i].lower_bound;
540 ves_icall_System_Array_SetValueImpl (arr, value, pos);
543 ICALL_EXPORT MonoArray *
544 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
546 MonoError error;
547 MonoClass *aklass, *klass;
548 MonoArray *array;
549 uintptr_t *sizes, i;
550 gboolean bounded = FALSE;
552 MONO_CHECK_ARG_NULL (type, NULL);
553 MONO_CHECK_ARG_NULL (lengths, NULL);
555 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
556 if (bounds)
557 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
559 for (i = 0; i < mono_array_length (lengths); i++) {
560 if (mono_array_get (lengths, gint32, i) < 0) {
561 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
562 return NULL;
566 klass = mono_class_from_mono_type (type->type);
567 mono_class_init_checked (klass, &error);
568 if (mono_error_set_pending_exception (&error))
569 return NULL;
571 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
572 /* vectors are not the same as one dimensional arrays with no-zero bounds */
573 bounded = TRUE;
574 else
575 bounded = FALSE;
577 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
579 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
580 for (i = 0; i < aklass->rank; ++i) {
581 sizes [i] = mono_array_get (lengths, guint32, i);
582 if (bounds)
583 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
584 else
585 sizes [i + aklass->rank] = 0;
588 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
589 mono_error_set_pending_exception (&error);
591 return array;
594 ICALL_EXPORT MonoArray *
595 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
597 MonoError error;
598 MonoClass *aklass, *klass;
599 MonoArray *array;
600 uintptr_t *sizes, i;
601 gboolean bounded = FALSE;
603 MONO_CHECK_ARG_NULL (type, NULL);
604 MONO_CHECK_ARG_NULL (lengths, NULL);
606 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
607 if (bounds)
608 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
610 for (i = 0; i < mono_array_length (lengths); i++) {
611 if ((mono_array_get (lengths, gint64, i) < 0) ||
612 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
613 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
614 return NULL;
618 klass = mono_class_from_mono_type (type->type);
619 mono_class_init_checked (klass, &error);
620 if (mono_error_set_pending_exception (&error))
621 return NULL;
623 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
624 /* vectors are not the same as one dimensional arrays with no-zero bounds */
625 bounded = TRUE;
626 else
627 bounded = FALSE;
629 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
631 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
632 for (i = 0; i < aklass->rank; ++i) {
633 sizes [i] = mono_array_get (lengths, guint64, i);
634 if (bounds)
635 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
636 else
637 sizes [i + aklass->rank] = 0;
640 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
641 mono_error_set_pending_exception (&error);
643 return array;
646 ICALL_EXPORT gint32
647 ves_icall_System_Array_GetRank (MonoObject *arr)
649 return arr->vtable->klass->rank;
652 ICALL_EXPORT gint32
653 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
655 gint32 rank = arr->obj.vtable->klass->rank;
656 uintptr_t length;
658 if ((dimension < 0) || (dimension >= rank)) {
659 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
660 return 0;
663 if (arr->bounds == NULL)
664 length = arr->max_length;
665 else
666 length = arr->bounds [dimension].length;
668 #ifdef MONO_BIG_ARRAYS
669 if (length > G_MAXINT32) {
670 mono_set_pending_exception (mono_get_exception_overflow ());
671 return 0;
673 #endif
674 return length;
677 ICALL_EXPORT gint64
678 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
680 gint32 rank = arr->obj.vtable->klass->rank;
682 if ((dimension < 0) || (dimension >= rank)) {
683 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
684 return 0;
687 if (arr->bounds == NULL)
688 return arr->max_length;
690 return arr->bounds [dimension].length;
693 ICALL_EXPORT gint32
694 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
696 gint32 rank = arr->obj.vtable->klass->rank;
698 if ((dimension < 0) || (dimension >= rank)) {
699 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
700 return 0;
703 if (arr->bounds == NULL)
704 return 0;
706 return arr->bounds [dimension].lower_bound;
709 ICALL_EXPORT void
710 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
712 int sz = mono_array_element_size (mono_object_class (arr));
713 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
716 ICALL_EXPORT MonoArray*
717 ves_icall_System_Array_Clone (MonoArray *arr)
719 MonoError error;
720 MonoArray *result = mono_array_clone_checked (arr, &error);
721 mono_error_set_pending_exception (&error);
722 return result;
725 ICALL_EXPORT gboolean
726 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
728 int element_size;
729 void * dest_addr;
730 void * source_addr;
731 MonoVTable *src_vtable;
732 MonoVTable *dest_vtable;
733 MonoClass *src_class;
734 MonoClass *dest_class;
736 src_vtable = source->obj.vtable;
737 dest_vtable = dest->obj.vtable;
739 if (src_vtable->rank != dest_vtable->rank)
740 return FALSE;
742 if (source->bounds || dest->bounds)
743 return FALSE;
745 /* there's no integer overflow since mono_array_length returns an unsigned integer */
746 if ((dest_idx + length > mono_array_length_fast (dest)) ||
747 (source_idx + length > mono_array_length_fast (source)))
748 return FALSE;
750 src_class = src_vtable->klass->element_class;
751 dest_class = dest_vtable->klass->element_class;
754 * Handle common cases.
757 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
758 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
760 if (src_class == mono_defaults.object_class && dest_class->valuetype)
761 return FALSE;
763 /* Check if we're copying a char[] <==> (u)short[] */
764 if (src_class != dest_class) {
765 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
766 return FALSE;
768 /* 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. */
769 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
770 return FALSE;
773 if (dest_class->valuetype) {
774 element_size = mono_array_element_size (source->obj.vtable->klass);
775 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
776 if (dest_class->has_references) {
777 mono_value_copy_array (dest, dest_idx, source_addr, length);
778 } else {
779 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
780 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
782 } else {
783 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
786 return TRUE;
789 ICALL_EXPORT void
790 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
792 MonoClass *ac;
793 gint32 esize;
794 gpointer *ea;
796 ac = (MonoClass *)arr->obj.vtable->klass;
798 esize = mono_array_element_size (ac);
799 ea = (gpointer*)((char*)arr->vector + (pos * esize));
801 mono_gc_memmove_atomic (value, ea, esize);
804 ICALL_EXPORT void
805 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
807 MonoClass *ac, *ec;
808 gint32 esize;
809 gpointer *ea;
811 ac = (MonoClass *)arr->obj.vtable->klass;
812 ec = ac->element_class;
814 esize = mono_array_element_size (ac);
815 ea = (gpointer*)((char*)arr->vector + (pos * esize));
817 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
818 g_assert (esize == sizeof (gpointer));
819 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
820 } else {
821 g_assert (ec->inited);
822 g_assert (esize == mono_class_value_size (ec, NULL));
823 if (ec->has_references)
824 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
825 else
826 mono_gc_memmove_atomic (ea, value, esize);
830 ICALL_EXPORT void
831 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
833 MonoClass *klass = array->obj.vtable->klass;
834 guint32 size = mono_array_element_size (klass);
835 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
836 int align;
837 const char *field_data;
839 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
840 MonoException *exc = mono_get_exception_argument("array",
841 "Cannot initialize array of non-primitive type.");
842 mono_set_pending_exception (exc);
843 return;
846 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
847 MonoException *exc = mono_get_exception_argument("field_handle",
848 "Field doesn't have an RVA");
849 mono_set_pending_exception (exc);
850 return;
853 size *= array->max_length;
854 field_data = mono_field_get_data (field_handle);
856 if (size > mono_type_size (field_handle->type, &align)) {
857 MonoException *exc = mono_get_exception_argument("field_handle",
858 "Field not large enough to fill array");
859 mono_set_pending_exception (exc);
860 return;
863 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
864 #define SWAP(n) { \
865 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
866 guint ## n *src = (guint ## n *) field_data; \
867 int i, \
868 nEnt = (size / sizeof(guint ## n)); \
870 for (i = 0; i < nEnt; i++) { \
871 data[i] = read ## n (&src[i]); \
875 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
877 switch (type->type) {
878 case MONO_TYPE_CHAR:
879 case MONO_TYPE_I2:
880 case MONO_TYPE_U2:
881 SWAP (16);
882 break;
883 case MONO_TYPE_I4:
884 case MONO_TYPE_U4:
885 case MONO_TYPE_R4:
886 SWAP (32);
887 break;
888 case MONO_TYPE_I8:
889 case MONO_TYPE_U8:
890 case MONO_TYPE_R8:
891 SWAP (64);
892 break;
893 default:
894 memcpy (mono_array_addr (array, char, 0), field_data, size);
895 break;
897 #else
898 memcpy (mono_array_addr (array, char, 0), field_data, size);
899 #endif
902 ICALL_EXPORT gint
903 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
905 return offsetof (MonoString, chars);
908 ICALL_EXPORT MonoObject *
909 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
911 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
912 return obj;
913 else {
914 MonoError error;
915 MonoObject *ret = mono_object_clone_checked (obj, &error);
916 mono_error_set_pending_exception (&error);
918 return ret;
922 ICALL_EXPORT void
923 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
925 MonoError error;
926 MonoClass *klass;
927 MonoVTable *vtable;
929 MONO_CHECK_ARG_NULL (handle,);
931 klass = mono_class_from_mono_type (handle);
932 MONO_CHECK_ARG (handle, klass,);
934 if (klass->generic_container)
935 return;
937 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
938 if (!is_ok (&error)) {
939 mono_error_set_pending_exception (&error);
940 return;
943 /* This will call the type constructor */
944 if (!mono_runtime_class_init_full (vtable, &error))
945 mono_error_set_pending_exception (&error);
948 ICALL_EXPORT void
949 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
951 MonoError error;
953 mono_image_check_for_module_cctor (image);
954 if (image->has_module_cctor) {
955 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
956 if (!mono_error_ok (&error)) {
957 mono_error_set_pending_exception (&error);
958 return;
960 /*It's fine to raise the exception here*/
961 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
962 if (!is_ok (&error)) {
963 mono_error_set_pending_exception (&error);
964 return;
966 if (!mono_runtime_class_init_full (vtable, &error))
967 mono_error_set_pending_exception (&error);
971 ICALL_EXPORT MonoBoolean
972 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
974 guint8 *stack_addr;
975 guint8 *current;
976 size_t stack_size;
977 /* later make this configurable and per-arch */
978 int min_size = 4096 * 4 * sizeof (void*);
979 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
980 /* if we have no info we are optimistic and assume there is enough room */
981 if (!stack_addr)
982 return TRUE;
983 #ifdef HOST_WIN32
984 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
985 // to the current sp
986 return TRUE;
987 #endif
988 current = (guint8 *)&stack_addr;
989 if (current > stack_addr) {
990 if ((current - stack_addr) < min_size)
991 return FALSE;
992 } else {
993 if (current - (stack_addr - stack_size) < min_size)
994 return FALSE;
996 return TRUE;
999 ICALL_EXPORT MonoObject *
1000 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1002 MonoError error;
1003 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1004 mono_error_set_pending_exception (&error);
1006 return ret;
1009 ICALL_EXPORT gint32
1010 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1012 MonoError error;
1013 MonoClass *klass;
1014 MonoObject **values = NULL;
1015 MonoObject *o;
1016 int count = 0;
1017 gint32 result = (int)(gsize)mono_defaults.int32_class;
1018 MonoClassField* field;
1019 gpointer iter;
1021 klass = mono_object_class (this_obj);
1023 if (mono_class_num_fields (klass) == 0)
1024 return result;
1027 * Compute the starting value of the hashcode for fields of primitive
1028 * types, and return the remaining fields in an array to the managed side.
1029 * This way, we can avoid costly reflection operations in managed code.
1031 iter = NULL;
1032 while ((field = mono_class_get_fields (klass, &iter))) {
1033 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1034 continue;
1035 if (mono_field_is_deleted (field))
1036 continue;
1037 /* FIXME: Add more types */
1038 switch (field->type->type) {
1039 case MONO_TYPE_I4:
1040 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1041 break;
1042 case MONO_TYPE_STRING: {
1043 MonoString *s;
1044 s = *(MonoString**)((guint8*)this_obj + field->offset);
1045 if (s != NULL)
1046 result ^= mono_string_hash (s);
1047 break;
1049 default:
1050 if (!values)
1051 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1052 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1053 if (!is_ok (&error)) {
1054 mono_error_set_pending_exception (&error);
1055 return 0;
1057 values [count++] = o;
1061 if (values) {
1062 int i;
1063 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1064 if (mono_error_set_pending_exception (&error))
1065 return 0;
1066 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1067 for (i = 0; i < count; ++i)
1068 mono_array_setref (*fields, i, values [i]);
1069 } else {
1070 *fields = NULL;
1072 return result;
1075 ICALL_EXPORT MonoBoolean
1076 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1078 MonoError error;
1079 MonoClass *klass;
1080 MonoObject **values = NULL;
1081 MonoObject *o;
1082 MonoClassField* field;
1083 gpointer iter;
1084 int count = 0;
1086 MONO_CHECK_ARG_NULL (that, FALSE);
1088 if (this_obj->vtable != that->vtable)
1089 return FALSE;
1091 klass = mono_object_class (this_obj);
1093 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1094 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1097 * Do the comparison for fields of primitive type and return a result if
1098 * possible. Otherwise, return the remaining fields in an array to the
1099 * managed side. This way, we can avoid costly reflection operations in
1100 * managed code.
1102 *fields = NULL;
1103 iter = NULL;
1104 while ((field = mono_class_get_fields (klass, &iter))) {
1105 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1106 continue;
1107 if (mono_field_is_deleted (field))
1108 continue;
1109 /* FIXME: Add more types */
1110 switch (field->type->type) {
1111 case MONO_TYPE_U1:
1112 case MONO_TYPE_I1:
1113 case MONO_TYPE_BOOLEAN:
1114 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1115 return FALSE;
1116 break;
1117 case MONO_TYPE_U2:
1118 case MONO_TYPE_I2:
1119 case MONO_TYPE_CHAR:
1120 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1121 return FALSE;
1122 break;
1123 case MONO_TYPE_U4:
1124 case MONO_TYPE_I4:
1125 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1126 return FALSE;
1127 break;
1128 case MONO_TYPE_U8:
1129 case MONO_TYPE_I8:
1130 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1131 return FALSE;
1132 break;
1133 case MONO_TYPE_R4:
1134 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1135 return FALSE;
1136 break;
1137 case MONO_TYPE_R8:
1138 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1139 return FALSE;
1140 break;
1143 case MONO_TYPE_STRING: {
1144 MonoString *s1, *s2;
1145 guint32 s1len, s2len;
1146 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1147 s2 = *(MonoString**)((guint8*)that + field->offset);
1148 if (s1 == s2)
1149 break;
1150 if ((s1 == NULL) || (s2 == NULL))
1151 return FALSE;
1152 s1len = mono_string_length (s1);
1153 s2len = mono_string_length (s2);
1154 if (s1len != s2len)
1155 return FALSE;
1157 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1158 return FALSE;
1159 break;
1161 default:
1162 if (!values)
1163 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1164 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1165 if (!is_ok (&error)) {
1166 mono_error_set_pending_exception (&error);
1167 return FALSE;
1169 values [count++] = o;
1170 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1171 if (!is_ok (&error)) {
1172 mono_error_set_pending_exception (&error);
1173 return FALSE;
1175 values [count++] = o;
1178 if (klass->enumtype)
1179 /* enums only have one non-static field */
1180 break;
1183 if (values) {
1184 int i;
1185 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1186 if (mono_error_set_pending_exception (&error))
1187 return FALSE;
1188 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1189 for (i = 0; i < count; ++i)
1190 mono_array_setref_fast (*fields, i, values [i]);
1191 return FALSE;
1192 } else {
1193 return TRUE;
1197 ICALL_EXPORT MonoReflectionType *
1198 ves_icall_System_Object_GetType (MonoObject *obj)
1200 MonoError error;
1201 MonoReflectionType *ret;
1202 #ifndef DISABLE_REMOTING
1203 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1204 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1205 else
1206 #endif
1207 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1209 mono_error_set_pending_exception (&error);
1210 return ret;
1213 ICALL_EXPORT gint32
1214 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1216 MONO_CHECK_ARG_NULL (obj, 0);
1218 MonoError error;
1219 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1220 mono_error_set_pending_exception (&error);
1221 return result;
1224 ICALL_EXPORT gint32
1225 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1226 MonoReflectionMethod *method,
1227 MonoArray *opt_param_types)
1229 MONO_CHECK_ARG_NULL (method, 0);
1231 MonoError error;
1232 gint32 result = mono_image_create_method_token (
1233 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1234 mono_error_set_pending_exception (&error);
1235 return result;
1238 ICALL_EXPORT void
1239 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1241 MonoError error;
1242 mono_image_create_pefile (mb, file, &error);
1243 mono_error_set_pending_exception (&error);
1246 ICALL_EXPORT void
1247 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1249 MonoError error;
1250 mono_image_build_metadata (mb, &error);
1251 mono_error_set_pending_exception (&error);
1254 ICALL_EXPORT void
1255 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1257 mono_image_register_token (mb->dynamic_image, token, obj);
1260 ICALL_EXPORT MonoObject*
1261 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1263 MonoObject *obj;
1265 mono_loader_lock ();
1266 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1267 mono_loader_unlock ();
1269 return obj;
1272 ICALL_EXPORT MonoReflectionModule*
1273 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1275 MonoError error;
1276 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1277 mono_error_set_pending_exception (&error);
1278 return result;
1282 * ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class:
1283 * @tb: a TypeBuilder object
1285 * (icall)
1286 * Creates the generic class after all generic parameters have been added.
1288 ICALL_EXPORT void
1289 ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class (MonoReflectionTypeBuilder *tb)
1291 MonoError error;
1292 (void) mono_reflection_create_generic_class (tb, &error);
1293 mono_error_set_pending_exception (&error);
1296 #ifndef DISABLE_REFLECTION_EMIT
1297 ICALL_EXPORT MonoArray*
1298 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1300 MonoError error;
1301 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1302 mono_error_set_pending_exception (&error);
1303 return result;
1305 #endif
1307 static gboolean
1308 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1310 MonoMethod **dest = (MonoMethod **)data;
1312 /* skip unmanaged frames */
1313 if (!managed)
1314 return FALSE;
1316 if (!(*dest)) {
1317 if (!strcmp (m->klass->name_space, "System.Reflection"))
1318 return FALSE;
1319 *dest = m;
1320 return TRUE;
1322 return FALSE;
1325 static gboolean
1326 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1328 MonoMethod **dest = (MonoMethod **)data;
1330 /* skip unmanaged frames */
1331 if (!managed)
1332 return FALSE;
1334 if (m->wrapper_type != MONO_WRAPPER_NONE)
1335 return FALSE;
1337 if (m == *dest) {
1338 *dest = NULL;
1339 return FALSE;
1342 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1343 return FALSE;
1345 if (!(*dest)) {
1346 *dest = m;
1347 return TRUE;
1349 return FALSE;
1352 static gboolean
1353 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1355 MonoMethod **dest = (MonoMethod **)data;
1357 /* skip unmanaged frames */
1358 if (!managed)
1359 return FALSE;
1361 if (m->wrapper_type != MONO_WRAPPER_NONE)
1362 return FALSE;
1364 if (m == *dest) {
1365 *dest = NULL;
1366 return FALSE;
1369 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1370 || (!strcmp (m->klass->name_space, "System"))))
1371 return FALSE;
1373 if (!(*dest)) {
1374 *dest = m;
1375 return TRUE;
1377 return FALSE;
1380 static MonoReflectionType *
1381 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1383 MonoMethod *m, *dest;
1385 MonoType *type = NULL;
1386 MonoAssembly *assembly = NULL;
1387 gboolean type_resolve = FALSE;
1388 MonoImage *rootimage = NULL;
1390 mono_error_init (error);
1393 * We must compute the calling assembly as type loading must happen under a metadata context.
1394 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1395 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1397 m = mono_method_get_last_managed ();
1398 dest = m;
1399 if (m && m->klass->image != mono_defaults.corlib) {
1400 /* Happens with inlining */
1401 } else {
1402 /* Ugly hack: type_from_parsed_name is called from
1403 * System.Type.internal_from_name, which is called most
1404 * directly from System.Type.GetType(string,bool,bool) but
1405 * also indirectly from places such as
1406 * System.Type.GetType(string,func,func) (via
1407 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1408 * so we need to skip over all of those to find the true caller.
1410 * It would be nice if we had stack marks.
1412 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1413 if (!dest)
1414 dest = m;
1418 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1419 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1420 * to crash. This only seems to happen in some strange remoting
1421 * scenarios and I was unable to figure out what's happening there.
1422 * Dec 10, 2005 - Martin.
1425 if (dest) {
1426 assembly = dest->klass->image->assembly;
1427 type_resolve = TRUE;
1428 rootimage = assembly->image;
1429 } else {
1430 g_warning (G_STRLOC);
1433 if (info->assembly.name)
1434 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1436 if (assembly) {
1437 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1438 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1439 return_val_if_nok (error, NULL);
1442 // XXXX - aleksey -
1443 // Say we're looking for System.Generic.Dict<int, Local>
1444 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1445 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1446 // is messed up when we go to construct the Local as the type arg...
1448 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1449 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1450 if (!info->assembly.name && !type) {
1451 /* try mscorlib */
1452 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1453 return_val_if_nok (error, NULL);
1455 if (assembly && !type && type_resolve) {
1456 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1457 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1458 return_val_if_nok (error, NULL);
1461 if (!type)
1462 return NULL;
1464 return mono_type_get_object_checked (mono_domain_get (), type, error);
1467 ICALL_EXPORT MonoReflectionType*
1468 ves_icall_System_Type_internal_from_name (MonoString *name,
1469 MonoBoolean throwOnError,
1470 MonoBoolean ignoreCase)
1472 MonoError error;
1473 MonoTypeNameParse info;
1474 MonoReflectionType *type = NULL;
1475 gboolean parsedOk;
1477 char *str = mono_string_to_utf8_checked (name, &error);
1478 if (!is_ok (&error))
1479 goto leave;
1481 parsedOk = mono_reflection_parse_type (str, &info);
1483 /* mono_reflection_parse_type() mangles the string */
1484 if (!parsedOk) {
1485 mono_reflection_free_type_info (&info);
1486 if (throwOnError)
1487 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1488 goto leave;
1491 type = type_from_parsed_name (&info, ignoreCase, &error);
1493 mono_reflection_free_type_info (&info);
1495 if (!is_ok (&error))
1496 goto leave;
1498 if (type == NULL){
1499 if (throwOnError) {
1500 mono_error_set_type_load_name (&error, g_strdup (str), NULL, "");
1501 goto leave;
1505 leave:
1506 g_free (str);
1507 if (!is_ok (&error)) {
1508 if (throwOnError)
1509 mono_error_set_pending_exception (&error);
1510 else
1511 mono_error_cleanup (&error);
1512 return NULL;
1515 return type;
1519 ICALL_EXPORT MonoReflectionType*
1520 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1522 MonoError error;
1523 MonoReflectionType *ret;
1524 MonoDomain *domain = mono_domain_get ();
1526 ret = mono_type_get_object_checked (domain, handle, &error);
1527 mono_error_set_pending_exception (&error);
1529 return ret;
1532 ICALL_EXPORT MonoType*
1533 ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
1535 return mono_class_get_type (klass);
1538 ICALL_EXPORT void
1539 ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array)
1541 g_ptr_array_free (ptr_array, TRUE);
1544 ICALL_EXPORT void
1545 ves_icall_Mono_SafeStringMarshal_GFree (void *c_str)
1547 g_free (c_str);
1550 ICALL_EXPORT char*
1551 ves_icall_Mono_SafeStringMarshal_StringToUtf8 (MonoString *s)
1553 MonoError error;
1554 char *res = mono_string_to_utf8_checked (s, &error);
1555 mono_error_set_pending_exception (&error);
1556 return res;
1559 /* System.TypeCode */
1560 typedef enum {
1561 TYPECODE_EMPTY,
1562 TYPECODE_OBJECT,
1563 TYPECODE_DBNULL,
1564 TYPECODE_BOOLEAN,
1565 TYPECODE_CHAR,
1566 TYPECODE_SBYTE,
1567 TYPECODE_BYTE,
1568 TYPECODE_INT16,
1569 TYPECODE_UINT16,
1570 TYPECODE_INT32,
1571 TYPECODE_UINT32,
1572 TYPECODE_INT64,
1573 TYPECODE_UINT64,
1574 TYPECODE_SINGLE,
1575 TYPECODE_DOUBLE,
1576 TYPECODE_DECIMAL,
1577 TYPECODE_DATETIME,
1578 TYPECODE_STRING = 18
1579 } TypeCode;
1581 ICALL_EXPORT guint32
1582 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1584 int t = type->type->type;
1586 if (type->type->byref)
1587 return TYPECODE_OBJECT;
1589 handle_enum:
1590 switch (t) {
1591 case MONO_TYPE_VOID:
1592 return TYPECODE_OBJECT;
1593 case MONO_TYPE_BOOLEAN:
1594 return TYPECODE_BOOLEAN;
1595 case MONO_TYPE_U1:
1596 return TYPECODE_BYTE;
1597 case MONO_TYPE_I1:
1598 return TYPECODE_SBYTE;
1599 case MONO_TYPE_U2:
1600 return TYPECODE_UINT16;
1601 case MONO_TYPE_I2:
1602 return TYPECODE_INT16;
1603 case MONO_TYPE_CHAR:
1604 return TYPECODE_CHAR;
1605 case MONO_TYPE_PTR:
1606 case MONO_TYPE_U:
1607 case MONO_TYPE_I:
1608 return TYPECODE_OBJECT;
1609 case MONO_TYPE_U4:
1610 return TYPECODE_UINT32;
1611 case MONO_TYPE_I4:
1612 return TYPECODE_INT32;
1613 case MONO_TYPE_U8:
1614 return TYPECODE_UINT64;
1615 case MONO_TYPE_I8:
1616 return TYPECODE_INT64;
1617 case MONO_TYPE_R4:
1618 return TYPECODE_SINGLE;
1619 case MONO_TYPE_R8:
1620 return TYPECODE_DOUBLE;
1621 case MONO_TYPE_VALUETYPE: {
1622 MonoClass *klass = type->type->data.klass;
1624 if (klass->enumtype) {
1625 t = mono_class_enum_basetype (klass)->type;
1626 goto handle_enum;
1627 } else if (mono_is_corlib_image (klass->image)) {
1628 if (strcmp (klass->name_space, "System") == 0) {
1629 if (strcmp (klass->name, "Decimal") == 0)
1630 return TYPECODE_DECIMAL;
1631 else if (strcmp (klass->name, "DateTime") == 0)
1632 return TYPECODE_DATETIME;
1635 return TYPECODE_OBJECT;
1637 case MONO_TYPE_STRING:
1638 return TYPECODE_STRING;
1639 case MONO_TYPE_SZARRAY:
1640 case MONO_TYPE_ARRAY:
1641 case MONO_TYPE_OBJECT:
1642 case MONO_TYPE_VAR:
1643 case MONO_TYPE_MVAR:
1644 case MONO_TYPE_TYPEDBYREF:
1645 return TYPECODE_OBJECT;
1646 case MONO_TYPE_CLASS:
1648 MonoClass *klass = type->type->data.klass;
1649 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1650 if (strcmp (klass->name, "DBNull") == 0)
1651 return TYPECODE_DBNULL;
1654 return TYPECODE_OBJECT;
1655 case MONO_TYPE_GENERICINST:
1656 return TYPECODE_OBJECT;
1657 default:
1658 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1660 return 0;
1663 static gboolean
1664 mono_type_is_primitive (MonoType *type)
1666 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1667 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1670 static MonoType*
1671 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1673 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1674 return mono_class_enum_basetype (type->data.klass);
1675 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1676 return mono_class_enum_basetype (type->data.generic_class->container_class);
1677 return type;
1680 ICALL_EXPORT guint32
1681 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1683 MonoClass *klass;
1684 MonoClass *klassc;
1686 g_assert (type != NULL);
1688 klass = mono_class_from_mono_type (type->type);
1689 klassc = mono_class_from_mono_type (c->type);
1691 if (type->type->byref ^ c->type->byref)
1692 return FALSE;
1694 if (type->type->byref) {
1695 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1696 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1698 klass = mono_class_from_mono_type (t);
1699 klassc = mono_class_from_mono_type (ot);
1701 if (mono_type_is_primitive (t)) {
1702 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1703 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1704 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1705 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1706 return t->type == ot->type;
1707 } else {
1708 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1709 return FALSE;
1711 if (klass->valuetype)
1712 return klass == klassc;
1713 return klass->valuetype == klassc->valuetype;
1716 return mono_class_is_assignable_from (klass, klassc);
1719 ICALL_EXPORT guint32
1720 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1722 MonoError error;
1723 MonoClass *klass = mono_class_from_mono_type (type->type);
1724 mono_class_init_checked (klass, &error);
1725 if (!is_ok (&error)) {
1726 mono_error_set_pending_exception (&error);
1727 return FALSE;
1729 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1730 mono_error_set_pending_exception (&error);
1731 return result;
1734 ICALL_EXPORT guint32
1735 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1737 MonoClass *klass = mono_class_from_mono_type (type->type);
1738 return klass->flags;
1741 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1742 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1744 MonoError error;
1745 MonoClass *klass = field->field->parent;
1746 MonoMarshalType *info;
1747 MonoType *ftype;
1748 int i;
1750 if (klass->generic_container ||
1751 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1752 return NULL;
1754 ftype = mono_field_get_type (field->field);
1755 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1756 return NULL;
1758 info = mono_marshal_load_type_info (klass);
1760 for (i = 0; i < info->num_fields; ++i) {
1761 if (info->fields [i].field == field->field) {
1762 if (!info->fields [i].mspec)
1763 return NULL;
1764 else {
1765 MonoReflectionMarshalAsAttribute* obj;
1766 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1767 if (!mono_error_ok (&error))
1768 mono_error_set_pending_exception (&error);
1769 return obj;
1774 return NULL;
1777 ICALL_EXPORT MonoReflectionField*
1778 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1780 MonoError error;
1781 gboolean found = FALSE;
1782 MonoClass *klass;
1784 g_assert (handle);
1786 if (!type) {
1787 klass = handle->parent;
1788 } else {
1789 klass = mono_class_from_mono_type (type);
1791 found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1793 if (!found)
1794 /* The managed code will throw the exception */
1795 return NULL;
1798 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1799 mono_error_set_pending_exception (&error);
1800 return result;
1803 ICALL_EXPORT MonoReflectionEvent*
1804 ves_icall_System_Reflection_EventInfo_internal_from_handle_type (MonoEvent *handle, MonoType *type)
1806 MonoError error;
1807 MonoClass *klass;
1809 g_assert (handle);
1811 if (!type) {
1812 klass = handle->parent;
1813 } else {
1814 klass = mono_class_from_mono_type (type);
1816 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1817 if (!found)
1818 /* Managed code will throw an exception */
1819 return NULL;
1822 MonoReflectionEvent *result = mono_event_get_object_checked (mono_domain_get (), klass, handle, &error);
1823 mono_error_set_pending_exception (&error);
1824 return result;
1828 ICALL_EXPORT MonoReflectionProperty*
1829 ves_icall_System_Reflection_PropertyInfo_internal_from_handle_type (MonoProperty *handle, MonoType *type)
1831 MonoError error;
1832 MonoClass *klass;
1834 g_assert (handle);
1836 if (!type) {
1837 klass = handle->parent;
1838 } else {
1839 klass = mono_class_from_mono_type (type);
1841 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1842 if (!found)
1843 /* Managed code will throw an exception */
1844 return NULL;
1847 MonoReflectionProperty *result = mono_property_get_object_checked (mono_domain_get (), klass, handle, &error);
1848 mono_error_set_pending_exception (&error);
1849 return result;
1852 ICALL_EXPORT MonoArray*
1853 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1855 MonoError error;
1856 MonoType *type = mono_field_get_type_checked (field->field, &error);
1857 MonoArray *res;
1859 if (!mono_error_ok (&error)) {
1860 mono_error_set_pending_exception (&error);
1861 return NULL;
1864 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1865 mono_error_set_pending_exception (&error);
1866 return res;
1869 ICALL_EXPORT int
1870 vell_icall_get_method_attributes (MonoMethod *method)
1872 return method->flags;
1875 ICALL_EXPORT void
1876 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1878 MonoError error;
1879 MonoReflectionType *rt;
1880 MonoDomain *domain = mono_domain_get ();
1881 MonoMethodSignature* sig;
1883 sig = mono_method_signature_checked (method, &error);
1884 if (!mono_error_ok (&error)) {
1885 mono_error_set_pending_exception (&error);
1886 return;
1889 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1890 if (!mono_error_ok (&error)) {
1891 mono_error_set_pending_exception (&error);
1892 return;
1895 MONO_STRUCT_SETREF (info, parent, rt);
1897 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1898 if (!mono_error_ok (&error)) {
1899 mono_error_set_pending_exception (&error);
1900 return;
1903 MONO_STRUCT_SETREF (info, ret, rt);
1905 info->attrs = method->flags;
1906 info->implattrs = method->iflags;
1907 if (sig->call_convention == MONO_CALL_DEFAULT)
1908 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1909 else {
1910 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1911 info->callconv = 2;
1912 else
1913 info->callconv = 1;
1915 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1918 ICALL_EXPORT MonoArray*
1919 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1921 MonoError error;
1922 MonoDomain *domain = mono_domain_get ();
1924 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1925 mono_error_set_pending_exception (&error);
1926 return result;
1929 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1930 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1932 MonoError error;
1933 MonoDomain *domain = mono_domain_get ();
1934 MonoReflectionMarshalAsAttribute* res = NULL;
1935 MonoMarshalSpec **mspecs;
1936 int i;
1938 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1939 mono_method_get_marshal_info (method, mspecs);
1941 if (mspecs [0]) {
1942 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1943 if (!mono_error_ok (&error)) {
1944 mono_error_set_pending_exception (&error);
1945 return NULL;
1949 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1950 if (mspecs [i])
1951 mono_metadata_free_marshal_spec (mspecs [i]);
1952 g_free (mspecs);
1954 return res;
1957 ICALL_EXPORT gint32
1958 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1960 MonoClass *parent = field->field->parent;
1961 if (!parent->size_inited)
1962 mono_class_init (parent);
1963 mono_class_setup_fields_locking (parent);
1965 return field->field->offset - sizeof (MonoObject);
1968 ICALL_EXPORT MonoReflectionType*
1969 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1971 MonoError error;
1972 MonoReflectionType *ret;
1973 MonoClass *parent;
1975 parent = declaring? field->field->parent: field->klass;
1977 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1978 mono_error_set_pending_exception (&error);
1980 return ret;
1984 ICALL_EXPORT MonoObject *
1985 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1987 MonoError error;
1988 MonoClass *fklass = field->klass;
1989 MonoClassField *cf = field->field;
1990 MonoDomain *domain = mono_object_domain (field);
1992 if (fklass->image->assembly->ref_only) {
1993 mono_set_pending_exception (mono_get_exception_invalid_operation (
1994 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1995 return NULL;
1998 if (mono_security_core_clr_enabled () &&
1999 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
2000 mono_error_set_pending_exception (&error);
2001 return NULL;
2004 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
2005 mono_error_set_pending_exception (&error);
2006 return result;
2009 ICALL_EXPORT void
2010 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
2012 MonoError error;
2013 MonoClassField *cf = field->field;
2014 MonoType *type;
2015 gchar *v;
2017 if (field->klass->image->assembly->ref_only) {
2018 mono_set_pending_exception (mono_get_exception_invalid_operation (
2019 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
2020 return;
2023 if (mono_security_core_clr_enabled () &&
2024 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
2025 mono_error_set_pending_exception (&error);
2026 return;
2029 type = mono_field_get_type_checked (cf, &error);
2030 if (!mono_error_ok (&error)) {
2031 mono_error_set_pending_exception (&error);
2032 return;
2035 v = (gchar *) value;
2036 if (!type->byref) {
2037 switch (type->type) {
2038 case MONO_TYPE_U1:
2039 case MONO_TYPE_I1:
2040 case MONO_TYPE_BOOLEAN:
2041 case MONO_TYPE_U2:
2042 case MONO_TYPE_I2:
2043 case MONO_TYPE_CHAR:
2044 case MONO_TYPE_U:
2045 case MONO_TYPE_I:
2046 case MONO_TYPE_U4:
2047 case MONO_TYPE_I4:
2048 case MONO_TYPE_R4:
2049 case MONO_TYPE_U8:
2050 case MONO_TYPE_I8:
2051 case MONO_TYPE_R8:
2052 case MONO_TYPE_VALUETYPE:
2053 case MONO_TYPE_PTR:
2054 if (v != NULL)
2055 v += sizeof (MonoObject);
2056 break;
2057 case MONO_TYPE_STRING:
2058 case MONO_TYPE_OBJECT:
2059 case MONO_TYPE_CLASS:
2060 case MONO_TYPE_ARRAY:
2061 case MONO_TYPE_SZARRAY:
2062 /* Do nothing */
2063 break;
2064 case MONO_TYPE_GENERICINST: {
2065 MonoGenericClass *gclass = type->data.generic_class;
2066 g_assert (!gclass->context.class_inst->is_open);
2068 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
2069 MonoClass *nklass = mono_class_from_mono_type (type);
2070 MonoObject *nullable;
2073 * Convert the boxed vtype into a Nullable structure.
2074 * This is complicated by the fact that Nullables have
2075 * a variable structure.
2077 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2078 if (!mono_error_ok (&error)) {
2079 mono_error_set_pending_exception (&error);
2080 return;
2083 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2085 v = (gchar *)mono_object_unbox (nullable);
2087 else
2088 if (gclass->container_class->valuetype && (v != NULL))
2089 v += sizeof (MonoObject);
2090 break;
2092 default:
2093 g_error ("type 0x%x not handled in "
2094 "ves_icall_FieldInfo_SetValueInternal", type->type);
2095 return;
2099 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2100 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2101 if (!is_ok (&error)) {
2102 mono_error_set_pending_exception (&error);
2103 return;
2105 if (!vtable->initialized) {
2106 if (!mono_runtime_class_init_full (vtable, &error)) {
2107 mono_error_set_pending_exception (&error);
2108 return;
2111 mono_field_static_set_value (vtable, cf, v);
2112 } else {
2113 mono_field_set_value (obj, cf, v);
2117 ICALL_EXPORT void
2118 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2120 MonoClassField *f;
2122 g_assert (field);
2123 g_assert (obj);
2124 g_assert (value);
2126 f = field->field;
2127 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2128 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2129 return;
2132 if (MONO_TYPE_IS_REFERENCE (f->type))
2133 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2134 else
2135 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2138 ICALL_EXPORT MonoObject *
2139 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2141 MonoObject *o = NULL;
2142 MonoClassField *field = rfield->field;
2143 MonoClass *klass;
2144 MonoDomain *domain = mono_object_domain (rfield);
2145 gchar *v;
2146 MonoTypeEnum def_type;
2147 const char *def_value;
2148 MonoType *t;
2149 MonoError error;
2151 mono_class_init (field->parent);
2153 t = mono_field_get_type_checked (field, &error);
2154 if (!mono_error_ok (&error)) {
2155 mono_error_set_pending_exception (&error);
2156 return NULL;
2159 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2160 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2161 return NULL;
2164 if (image_is_dynamic (field->parent->image)) {
2165 MonoClass *klass = field->parent;
2166 int fidx = field - klass->fields;
2168 g_assert (fidx >= 0 && fidx < klass->field.count);
2169 g_assert (klass->ext);
2170 g_assert (klass->ext->field_def_values);
2171 def_type = klass->ext->field_def_values [fidx].def_type;
2172 def_value = klass->ext->field_def_values [fidx].data;
2173 if (def_type == MONO_TYPE_END) {
2174 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2175 return NULL;
2177 } else {
2178 def_value = mono_class_get_field_default_value (field, &def_type);
2179 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2180 if (!def_value) {
2181 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2182 return NULL;
2186 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2187 switch (def_type) {
2188 case MONO_TYPE_U1:
2189 case MONO_TYPE_I1:
2190 case MONO_TYPE_BOOLEAN:
2191 case MONO_TYPE_U2:
2192 case MONO_TYPE_I2:
2193 case MONO_TYPE_CHAR:
2194 case MONO_TYPE_U:
2195 case MONO_TYPE_I:
2196 case MONO_TYPE_U4:
2197 case MONO_TYPE_I4:
2198 case MONO_TYPE_R4:
2199 case MONO_TYPE_U8:
2200 case MONO_TYPE_I8:
2201 case MONO_TYPE_R8: {
2202 MonoType *t;
2204 /* boxed value type */
2205 t = g_new0 (MonoType, 1);
2206 t->type = def_type;
2207 klass = mono_class_from_mono_type (t);
2208 g_free (t);
2209 o = mono_object_new_checked (domain, klass, &error);
2210 if (!mono_error_ok (&error)) {
2211 mono_error_set_pending_exception (&error);
2212 return NULL;
2214 v = ((gchar *) o) + sizeof (MonoObject);
2215 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2216 if (mono_error_set_pending_exception (&error))
2217 return NULL;
2218 break;
2220 case MONO_TYPE_STRING:
2221 case MONO_TYPE_CLASS:
2222 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2223 if (mono_error_set_pending_exception (&error))
2224 return NULL;
2225 break;
2226 default:
2227 g_assert_not_reached ();
2230 return o;
2233 ICALL_EXPORT MonoReflectionType*
2234 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2236 MonoError error;
2237 MonoReflectionType *ret;
2238 MonoType *type;
2240 type = mono_field_get_type_checked (ref_field->field, &error);
2241 if (!mono_error_ok (&error)) {
2242 mono_error_set_pending_exception (&error);
2243 return NULL;
2246 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2247 if (!mono_error_ok (&error)) {
2248 mono_error_set_pending_exception (&error);
2249 return NULL;
2252 return ret;
2255 /* From MonoProperty.cs */
2256 typedef enum {
2257 PInfo_Attributes = 1,
2258 PInfo_GetMethod = 1 << 1,
2259 PInfo_SetMethod = 1 << 2,
2260 PInfo_ReflectedType = 1 << 3,
2261 PInfo_DeclaringType = 1 << 4,
2262 PInfo_Name = 1 << 5
2263 } PInfo;
2265 ICALL_EXPORT void
2266 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2268 MonoError error;
2269 MonoReflectionType *rt;
2270 MonoReflectionMethod *rm;
2271 MonoDomain *domain = mono_object_domain (property);
2272 const MonoProperty *pproperty = property->property;
2274 if ((req_info & PInfo_ReflectedType) != 0) {
2275 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2276 if (mono_error_set_pending_exception (&error))
2277 return;
2279 MONO_STRUCT_SETREF (info, parent, rt);
2281 if ((req_info & PInfo_DeclaringType) != 0) {
2282 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2283 if (mono_error_set_pending_exception (&error))
2284 return;
2286 MONO_STRUCT_SETREF (info, declaring_type, rt);
2289 if ((req_info & PInfo_Name) != 0)
2290 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2292 if ((req_info & PInfo_Attributes) != 0)
2293 info->attrs = pproperty->attrs;
2295 if ((req_info & PInfo_GetMethod) != 0) {
2296 if (pproperty->get &&
2297 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2298 pproperty->get->klass == property->klass)) {
2299 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2300 if (mono_error_set_pending_exception (&error))
2301 return;
2302 } else {
2303 rm = NULL;
2306 MONO_STRUCT_SETREF (info, get, rm);
2308 if ((req_info & PInfo_SetMethod) != 0) {
2309 if (pproperty->set &&
2310 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2311 pproperty->set->klass == property->klass)) {
2312 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2313 if (mono_error_set_pending_exception (&error))
2314 return;
2315 } else {
2316 rm = NULL;
2319 MONO_STRUCT_SETREF (info, set, rm);
2322 * There may be other methods defined for properties, though, it seems they are not exposed
2323 * in the reflection API
2327 ICALL_EXPORT void
2328 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2330 MonoError error;
2331 MonoReflectionType *rt;
2332 MonoReflectionMethod *rm;
2333 MonoDomain *domain = mono_object_domain (event);
2335 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2336 if (mono_error_set_pending_exception (&error))
2337 return;
2339 MONO_STRUCT_SETREF (info, reflected_type, rt);
2341 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2342 if (mono_error_set_pending_exception (&error))
2343 return;
2345 MONO_STRUCT_SETREF (info, declaring_type, rt);
2347 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2348 info->attrs = event->event->attrs;
2350 if (event->event->add) {
2351 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2352 if (mono_error_set_pending_exception (&error))
2353 return;
2354 } else {
2355 rm = NULL;
2358 MONO_STRUCT_SETREF (info, add_method, rm);
2360 if (event->event->remove) {
2361 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2362 if (mono_error_set_pending_exception (&error))
2363 return;
2364 } else {
2365 rm = NULL;
2368 MONO_STRUCT_SETREF (info, remove_method, rm);
2370 if (event->event->raise) {
2371 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2372 if (mono_error_set_pending_exception (&error))
2373 return;
2374 } else {
2375 rm = NULL;
2378 MONO_STRUCT_SETREF (info, raise_method, rm);
2380 #ifndef MONO_SMALL_CONFIG
2381 if (event->event->other) {
2382 int i, n = 0;
2383 while (event->event->other [n])
2384 n++;
2385 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2386 if (mono_error_set_pending_exception (&error))
2387 return;
2388 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2390 for (i = 0; i < n; i++) {
2391 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2392 if (mono_error_set_pending_exception (&error))
2393 return;
2394 mono_array_setref (info->other_methods, i, rm);
2397 #endif
2400 static void
2401 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2403 int i;
2404 MonoClass *ic;
2406 mono_class_setup_interfaces (klass, error);
2407 if (!mono_error_ok (error))
2408 return;
2410 for (i = 0; i < klass->interface_count; i++) {
2411 ic = klass->interfaces [i];
2412 g_hash_table_insert (ifaces, ic, ic);
2414 collect_interfaces (ic, ifaces, error);
2415 if (!mono_error_ok (error))
2416 return;
2420 typedef struct {
2421 MonoArray *iface_array;
2422 MonoGenericContext *context;
2423 MonoError *error;
2424 MonoDomain *domain;
2425 int next_idx;
2426 } FillIfaceArrayData;
2428 static void
2429 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2431 MonoReflectionType *rt;
2432 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2433 MonoClass *ic = (MonoClass *)key;
2434 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2436 if (!mono_error_ok (data->error))
2437 return;
2439 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2440 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2441 if (!mono_error_ok (data->error))
2442 return;
2445 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2446 if (!mono_error_ok (data->error))
2447 return;
2449 mono_array_setref (data->iface_array, data->next_idx++, rt);
2451 if (inflated)
2452 mono_metadata_free_type (inflated);
2455 static guint
2456 get_interfaces_hash (gconstpointer v1)
2458 MonoClass *k = (MonoClass*)v1;
2460 return k->type_token;
2463 ICALL_EXPORT MonoArray*
2464 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2466 MonoError error;
2467 MonoClass *klass = mono_class_from_mono_type (type->type);
2468 MonoClass *parent;
2469 FillIfaceArrayData data = { 0 };
2470 int len;
2472 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2474 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2475 data.context = mono_class_get_context (klass);
2476 klass = klass->generic_class->container_class;
2479 for (parent = klass; parent; parent = parent->parent) {
2480 mono_class_setup_interfaces (parent, &error);
2481 if (!mono_error_ok (&error))
2482 goto fail;
2483 collect_interfaces (parent, iface_hash, &error);
2484 if (!mono_error_ok (&error))
2485 goto fail;
2488 data.error = &error;
2489 data.domain = mono_object_domain (type);
2491 len = g_hash_table_size (iface_hash);
2492 if (len == 0) {
2493 g_hash_table_destroy (iface_hash);
2494 if (!data.domain->empty_types) {
2495 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2496 if (!is_ok (&error))
2497 goto fail;
2499 return data.domain->empty_types;
2502 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2503 if (!is_ok (&error))
2504 goto fail;
2505 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2506 if (!mono_error_ok (&error))
2507 goto fail;
2509 g_hash_table_destroy (iface_hash);
2510 return data.iface_array;
2512 fail:
2513 g_hash_table_destroy (iface_hash);
2514 mono_error_set_pending_exception (&error);
2515 return NULL;
2518 ICALL_EXPORT void
2519 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2521 gboolean variance_used;
2522 MonoClass *klass = mono_class_from_mono_type (type->type);
2523 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2524 MonoReflectionMethod *member;
2525 MonoMethod* method;
2526 gpointer iter;
2527 int i = 0, len, ioffset;
2528 MonoDomain *domain;
2529 MonoError error;
2531 mono_class_init_checked (klass, &error);
2532 if (mono_error_set_pending_exception (&error))
2533 return;
2534 mono_class_init_checked (iclass, &error);
2535 if (mono_error_set_pending_exception (&error))
2536 return;
2538 mono_class_setup_vtable (klass);
2540 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2541 if (ioffset == -1)
2542 return;
2544 len = mono_class_num_methods (iclass);
2545 domain = mono_object_domain (type);
2546 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2547 if (mono_error_set_pending_exception (&error))
2548 return;
2549 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2550 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2551 if (mono_error_set_pending_exception (&error))
2552 return;
2553 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2554 iter = NULL;
2555 while ((method = mono_class_get_methods (iclass, &iter))) {
2556 member = mono_method_get_object_checked (domain, method, iclass, &error);
2557 if (mono_error_set_pending_exception (&error))
2558 return;
2559 mono_array_setref (*methods, i, member);
2560 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2561 if (mono_error_set_pending_exception (&error))
2562 return;
2563 mono_array_setref (*targets, i, member);
2565 i ++;
2569 ICALL_EXPORT void
2570 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2572 MonoError error;
2573 MonoClass *klass = mono_class_from_mono_type (type->type);
2575 mono_class_init_checked (klass, &error);
2576 if (mono_error_set_pending_exception (&error))
2577 return;
2579 if (image_is_dynamic (klass->image)) {
2580 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2581 *packing = tb->packing_size;
2582 *size = tb->class_size;
2583 } else {
2584 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2588 ICALL_EXPORT MonoReflectionType*
2589 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2591 MonoError error;
2592 MonoReflectionType *ret;
2593 MonoClass *klass;
2595 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2596 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2597 mono_error_set_pending_exception (&error);
2598 return ret;
2601 klass = mono_class_from_mono_type (type->type);
2602 mono_class_init_checked (klass, &error);
2603 if (mono_error_set_pending_exception (&error))
2604 return NULL;
2607 // GetElementType should only return a type for:
2608 // Array Pointer PassedByRef
2609 if (type->type->byref)
2610 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2611 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2612 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2613 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2614 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2615 else
2616 return NULL;
2618 mono_error_set_pending_exception (&error);
2620 return ret;
2623 ICALL_EXPORT MonoReflectionType*
2624 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2626 MonoError error;
2627 MonoReflectionType *ret;
2629 if (type->type->byref)
2630 return NULL;
2632 MonoClass *klass = mono_class_from_mono_type (type->type);
2633 if (!klass->parent)
2634 return NULL;
2636 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2637 mono_error_set_pending_exception (&error);
2639 return ret;
2642 ICALL_EXPORT MonoBoolean
2643 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2645 return type->type->type == MONO_TYPE_PTR;
2648 ICALL_EXPORT MonoBoolean
2649 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2651 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)));
2654 ICALL_EXPORT MonoBoolean
2655 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2657 return type->type->byref;
2660 ICALL_EXPORT MonoBoolean
2661 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2663 MonoError error;
2664 MonoClass *klass = mono_class_from_mono_type (type->type);
2665 mono_class_init_checked (klass, &error);
2666 if (mono_error_set_pending_exception (&error))
2667 return FALSE;
2669 return mono_class_is_com_object (klass);
2672 ICALL_EXPORT guint32
2673 ves_icall_reflection_get_token (MonoObject* obj)
2675 MonoError error;
2676 guint32 result = mono_reflection_get_token_checked (obj, &error);
2677 mono_error_set_pending_exception (&error);
2678 return result;
2681 ICALL_EXPORT MonoReflectionModule*
2682 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2684 MonoError error;
2685 MonoReflectionModule *result = NULL;
2686 MonoClass *klass = mono_class_from_mono_type (type->type);
2687 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2688 mono_error_set_pending_exception (&error);
2689 return result;
2692 ICALL_EXPORT MonoReflectionAssembly*
2693 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2695 MonoError error;
2696 MonoDomain *domain = mono_domain_get ();
2697 MonoClass *klass = mono_class_from_mono_type (type->type);
2698 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2699 mono_error_set_pending_exception (&error);
2700 return result;
2703 ICALL_EXPORT MonoReflectionType*
2704 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2706 MonoError error;
2707 MonoReflectionType *ret;
2708 MonoDomain *domain = mono_domain_get ();
2709 MonoClass *klass;
2711 if (type->type->byref)
2712 return NULL;
2713 if (type->type->type == MONO_TYPE_VAR) {
2714 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2715 klass = param ? param->owner.klass : NULL;
2716 } else if (type->type->type == MONO_TYPE_MVAR) {
2717 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2718 klass = param ? param->owner.method->klass : NULL;
2719 } else {
2720 klass = mono_class_from_mono_type (type->type)->nested_in;
2723 if (!klass)
2724 return NULL;
2726 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2727 mono_error_set_pending_exception (&error);
2729 return ret;
2732 ICALL_EXPORT MonoString*
2733 ves_icall_RuntimeType_get_Name (MonoReflectionType *type)
2735 MonoDomain *domain = mono_domain_get ();
2736 MonoClass *klass = mono_class_from_mono_type (type->type);
2738 if (type->type->byref) {
2739 char *n = g_strdup_printf ("%s&", klass->name);
2740 MonoString *res = mono_string_new (domain, n);
2742 g_free (n);
2744 return res;
2745 } else {
2746 return mono_string_new (domain, klass->name);
2750 ICALL_EXPORT MonoString*
2751 ves_icall_RuntimeType_get_Namespace (MonoReflectionType *type)
2753 MonoDomain *domain = mono_domain_get ();
2754 MonoClass *klass = mono_class_from_mono_type (type->type);
2756 while (klass->nested_in)
2757 klass = klass->nested_in;
2759 if (klass->name_space [0] == '\0')
2760 return NULL;
2761 else
2762 return mono_string_new (domain, klass->name_space);
2765 ICALL_EXPORT gint32
2766 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2768 MonoClass *klass;
2770 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2771 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2772 return 0;
2775 klass = mono_class_from_mono_type (type->type);
2777 return klass->rank;
2780 static MonoArray*
2781 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2783 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2786 ICALL_EXPORT MonoArray*
2787 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2789 MonoError error;
2790 MonoReflectionType *rt;
2791 MonoArray *res;
2792 MonoClass *klass, *pklass;
2793 MonoDomain *domain = mono_object_domain (type);
2794 int i;
2796 klass = mono_class_from_mono_type (type->type);
2798 if (klass->generic_container) {
2799 MonoGenericContainer *container = klass->generic_container;
2800 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2801 if (mono_error_set_pending_exception (&error))
2802 return NULL;
2803 for (i = 0; i < container->type_argc; ++i) {
2804 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2806 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2807 if (mono_error_set_pending_exception (&error))
2808 return NULL;
2810 mono_array_setref (res, i, rt);
2812 } else if (klass->generic_class) {
2813 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2814 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2815 if (mono_error_set_pending_exception (&error))
2816 return NULL;
2817 for (i = 0; i < inst->type_argc; ++i) {
2818 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2819 if (mono_error_set_pending_exception (&error))
2820 return NULL;
2822 mono_array_setref (res, i, rt);
2824 } else {
2825 res = NULL;
2827 return res;
2830 ICALL_EXPORT gboolean
2831 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2833 MonoClass *klass;
2835 if (!IS_MONOTYPE (type))
2836 return FALSE;
2838 if (type->type->byref)
2839 return FALSE;
2841 klass = mono_class_from_mono_type (type->type);
2842 return klass->generic_container != NULL;
2845 ICALL_EXPORT MonoReflectionType*
2846 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2848 MonoError error;
2849 MonoReflectionType *ret;
2850 MonoClass *klass;
2852 if (type->type->byref)
2853 return NULL;
2855 klass = mono_class_from_mono_type (type->type);
2857 if (klass->generic_container) {
2858 return type; /* check this one */
2860 if (klass->generic_class) {
2861 MonoClass *generic_class = klass->generic_class->container_class;
2862 gpointer tb;
2864 tb = mono_class_get_ref_info (generic_class);
2866 if (generic_class->wastypebuilder && tb)
2867 return (MonoReflectionType *)tb;
2868 else {
2869 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2870 mono_error_set_pending_exception (&error);
2872 return ret;
2875 return NULL;
2878 ICALL_EXPORT MonoReflectionType*
2879 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2881 MonoError error;
2882 MonoReflectionType *ret;
2883 MonoClass *klass;
2884 MonoType *geninst, **types;
2885 int i, count;
2887 g_assert (IS_MONOTYPE (type));
2888 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2889 if (mono_error_set_pending_exception (&error))
2890 return NULL;
2892 count = mono_array_length (type_array);
2893 types = g_new0 (MonoType *, count);
2895 for (i = 0; i < count; i++) {
2896 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2897 types [i] = t->type;
2900 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2901 g_free (types);
2902 if (!geninst) {
2903 mono_error_set_pending_exception (&error);
2904 return NULL;
2907 klass = mono_class_from_mono_type (geninst);
2909 /*we might inflate to the GTD*/
2910 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2911 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2912 return NULL;
2915 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2916 mono_error_set_pending_exception (&error);
2918 return ret;
2921 ICALL_EXPORT gboolean
2922 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2924 MonoClass *klass;
2926 if (!IS_MONOTYPE (type))
2927 return FALSE;
2929 if (type->type->byref)
2930 return FALSE;
2932 klass = mono_class_from_mono_type (type->type);
2933 return klass->generic_class != NULL || klass->generic_container != NULL;
2936 ICALL_EXPORT gint32
2937 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2939 if (!IS_MONOTYPE (type))
2940 return -1;
2942 if (is_generic_parameter (type->type))
2943 return mono_type_get_generic_param_num (type->type);
2944 return -1;
2947 ICALL_EXPORT MonoGenericParamInfo *
2948 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionType *type)
2950 return mono_generic_param_info (type->type->data.generic_param);
2953 ICALL_EXPORT MonoBoolean
2954 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2956 return is_generic_parameter (type->type);
2959 ICALL_EXPORT MonoBoolean
2960 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2962 return is_generic_parameter (tb->type.type);
2965 ICALL_EXPORT void
2966 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2967 MonoReflectionType *t)
2969 enumtype->type = t->type;
2972 ICALL_EXPORT MonoReflectionMethod*
2973 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2974 MonoReflectionMethod* generic)
2976 MonoDomain *domain;
2977 MonoClass *klass;
2978 MonoMethod *method;
2979 gpointer iter;
2980 MonoError error;
2981 MonoReflectionMethod *ret = NULL;
2983 domain = ((MonoObject *)type)->vtable->domain;
2985 klass = mono_class_from_mono_type (type->type);
2986 mono_class_init_checked (klass, &error);
2987 if (mono_error_set_pending_exception (&error))
2988 return NULL;
2990 iter = NULL;
2991 while ((method = mono_class_get_methods (klass, &iter))) {
2992 if (method->token == generic->method->token) {
2993 ret = mono_method_get_object_checked (domain, method, klass, &error);
2994 if (mono_error_set_pending_exception (&error))
2995 return NULL;
2999 return ret;
3002 ICALL_EXPORT MonoReflectionMethod *
3003 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
3005 MonoMethod *method;
3006 MonoType *type = ref_type->type;
3007 MonoError error;
3008 MonoReflectionMethod *ret = NULL;
3010 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
3011 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
3012 return NULL;
3014 if (type->type == MONO_TYPE_VAR)
3015 return NULL;
3017 method = mono_type_get_generic_param_owner (type)->owner.method;
3018 g_assert (method);
3020 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
3021 if (!mono_error_ok (&error))
3022 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3023 return ret;
3026 ICALL_EXPORT MonoBoolean
3027 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
3029 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3030 return FALSE;
3033 ICALL_EXPORT MonoBoolean
3034 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
3036 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3037 return FALSE;
3040 ICALL_EXPORT void
3041 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
3043 MonoDomain *domain = mono_domain_get ();
3044 MonoImage *image = method->method->klass->image;
3045 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
3046 MonoTableInfo *tables = image->tables;
3047 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
3048 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
3049 guint32 im_cols [MONO_IMPLMAP_SIZE];
3050 guint32 scope_token;
3051 const char *import = NULL;
3052 const char *scope = NULL;
3054 if (image_is_dynamic (image)) {
3055 MonoReflectionMethodAux *method_aux =
3056 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
3057 if (method_aux) {
3058 import = method_aux->dllentry;
3059 scope = method_aux->dll;
3062 if (!import || !scope) {
3063 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
3064 return;
3067 else {
3068 if (piinfo->implmap_idx) {
3069 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
3071 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3072 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3073 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3074 scope = mono_metadata_string_heap (image, scope_token);
3078 *flags = piinfo->piflags;
3079 *entry_point = mono_string_new (domain, import);
3080 *dll_name = mono_string_new (domain, scope);
3083 ICALL_EXPORT MonoReflectionMethod *
3084 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3086 MonoMethodInflated *imethod;
3087 MonoMethod *result;
3088 MonoReflectionMethod *ret = NULL;
3089 MonoError error;
3091 if (method->method->is_generic)
3092 return method;
3094 if (!method->method->is_inflated)
3095 return NULL;
3097 imethod = (MonoMethodInflated *) method->method;
3099 result = imethod->declaring;
3100 /* Not a generic method. */
3101 if (!result->is_generic)
3102 return NULL;
3104 if (image_is_dynamic (method->method->klass->image)) {
3105 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3106 MonoReflectionMethod *res;
3109 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3110 * the dynamic case as well ?
3112 mono_image_lock ((MonoImage*)image);
3113 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3114 mono_image_unlock ((MonoImage*)image);
3116 if (res)
3117 return res;
3120 if (imethod->context.class_inst) {
3121 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3122 /*Generic methods gets the context of the GTD.*/
3123 if (mono_class_get_context (klass)) {
3124 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3125 if (!mono_error_ok (&error))
3126 goto leave;
3130 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3131 leave:
3132 if (!mono_error_ok (&error))
3133 mono_error_set_pending_exception (&error);
3134 return ret;
3137 ICALL_EXPORT gboolean
3138 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3140 return mono_method_signature (method->method)->generic_param_count != 0;
3143 ICALL_EXPORT gboolean
3144 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3146 return method->method->is_generic;
3149 ICALL_EXPORT MonoArray*
3150 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3152 MonoError error;
3153 MonoReflectionType *rt;
3154 MonoArray *res;
3155 MonoDomain *domain;
3156 int count, i;
3158 domain = mono_object_domain (method);
3160 if (method->method->is_inflated) {
3161 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3163 if (inst) {
3164 count = inst->type_argc;
3165 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3166 if (mono_error_set_pending_exception (&error))
3167 return NULL;
3169 for (i = 0; i < count; i++) {
3170 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3171 if (mono_error_set_pending_exception (&error))
3172 return NULL;
3174 mono_array_setref (res, i, rt);
3177 return res;
3181 count = mono_method_signature (method->method)->generic_param_count;
3182 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3183 if (mono_error_set_pending_exception (&error))
3184 return NULL;
3186 for (i = 0; i < count; i++) {
3187 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3188 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3189 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3191 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3192 if (mono_error_set_pending_exception (&error))
3193 return NULL;
3195 mono_array_setref (res, i, rt);
3198 return res;
3201 ICALL_EXPORT MonoObject *
3202 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3204 MonoError error;
3206 * Invoke from reflection is supposed to always be a virtual call (the API
3207 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3208 * greater flexibility.
3210 MonoMethod *m = method->method;
3211 MonoMethodSignature *sig = mono_method_signature (m);
3212 MonoImage *image;
3213 int pcount;
3214 void *obj = this_arg;
3216 *exc = NULL;
3218 if (mono_security_core_clr_enabled () &&
3219 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3220 mono_error_set_pending_exception (&error);
3221 return NULL;
3224 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3225 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3226 mono_error_cleanup (&error); /* FIXME does this make sense? */
3227 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3228 return NULL;
3231 if (this_arg) {
3232 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3233 if (!is_ok (&error)) {
3234 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3235 return NULL;
3237 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3238 char *target_name = mono_type_get_full_name (m->klass);
3239 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3240 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3241 g_free (msg);
3242 g_free (target_name);
3243 g_free (this_name);
3244 return NULL;
3246 m = mono_object_get_virtual_method (this_arg, m);
3247 /* must pass the pointer to the value for valuetype methods */
3248 if (m->klass->valuetype)
3249 obj = mono_object_unbox (this_arg);
3250 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3251 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3252 return NULL;
3256 if (sig->ret->byref) {
3257 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"));
3258 return NULL;
3261 pcount = params? mono_array_length (params): 0;
3262 if (pcount != sig->param_count) {
3263 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3264 return NULL;
3267 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3268 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."));
3269 return NULL;
3272 image = m->klass->image;
3273 if (image->assembly->ref_only) {
3274 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."));
3275 return NULL;
3278 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3279 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3280 return NULL;
3283 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3284 MonoArray *arr;
3285 int i;
3286 uintptr_t *lengths;
3287 intptr_t *lower_bounds;
3288 pcount = mono_array_length (params);
3289 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3290 /* Note: the synthetized array .ctors have int32 as argument type */
3291 for (i = 0; i < pcount; ++i)
3292 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3294 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3295 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3296 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3297 if (!mono_error_ok (&error)) {
3298 mono_error_set_pending_exception (&error);
3299 return NULL;
3302 for (i = 0; i < mono_array_length (arr); ++i) {
3303 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3304 if (!mono_error_ok (&error)) {
3305 mono_error_set_pending_exception (&error);
3306 return NULL;
3308 mono_array_setref_fast (arr, i, subarray);
3310 return (MonoObject*)arr;
3313 if (m->klass->rank == pcount) {
3314 /* Only lengths provided. */
3315 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3316 if (!mono_error_ok (&error)) {
3317 mono_error_set_pending_exception (&error);
3318 return NULL;
3321 return (MonoObject*)arr;
3322 } else {
3323 g_assert (pcount == (m->klass->rank * 2));
3324 /* The arguments are lower-bound-length pairs */
3325 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3327 for (i = 0; i < pcount / 2; ++i) {
3328 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3329 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3332 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3333 if (!mono_error_ok (&error)) {
3334 mono_error_set_pending_exception (&error);
3335 return NULL;
3338 return (MonoObject*)arr;
3341 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3342 mono_error_set_pending_exception (&error);
3343 return result;
3346 #ifndef DISABLE_REMOTING
3347 ICALL_EXPORT MonoObject *
3348 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3350 MonoError error;
3351 MonoDomain *domain = mono_object_domain (method);
3352 MonoMethod *m = method->method;
3353 MonoMethodSignature *sig = mono_method_signature (m);
3354 MonoArray *out_args;
3355 MonoObject *result;
3356 int i, j, outarg_count = 0;
3358 if (m->klass == mono_defaults.object_class) {
3359 if (!strcmp (m->name, "FieldGetter")) {
3360 MonoClass *k = this_arg->vtable->klass;
3361 MonoString *name;
3362 char *str;
3364 /* If this is a proxy, then it must be a CBO */
3365 if (k == mono_defaults.transparent_proxy_class) {
3366 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3367 this_arg = tp->rp->unwrapped_server;
3368 g_assert (this_arg);
3369 k = this_arg->vtable->klass;
3372 name = mono_array_get (params, MonoString *, 1);
3373 str = mono_string_to_utf8_checked (name, &error);
3374 if (mono_error_set_pending_exception (&error))
3375 return NULL;
3377 do {
3378 MonoClassField* field = mono_class_get_field_from_name (k, str);
3379 if (field) {
3380 g_free (str);
3381 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3382 if (field_klass->valuetype) {
3383 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3384 if (mono_error_set_pending_exception (&error))
3385 return NULL;
3386 } else
3387 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3389 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3390 if (mono_error_set_pending_exception (&error))
3391 return NULL;
3392 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3393 mono_array_setref (out_args, 0, result);
3394 return NULL;
3396 k = k->parent;
3397 } while (k);
3399 g_free (str);
3400 g_assert_not_reached ();
3402 } else if (!strcmp (m->name, "FieldSetter")) {
3403 MonoClass *k = this_arg->vtable->klass;
3404 MonoString *name;
3405 guint32 size;
3406 gint32 align;
3407 char *str;
3409 /* If this is a proxy, then it must be a CBO */
3410 if (k == mono_defaults.transparent_proxy_class) {
3411 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3412 this_arg = tp->rp->unwrapped_server;
3413 g_assert (this_arg);
3414 k = this_arg->vtable->klass;
3417 name = mono_array_get (params, MonoString *, 1);
3418 str = mono_string_to_utf8_checked (name, &error);
3419 if (mono_error_set_pending_exception (&error))
3420 return NULL;
3422 do {
3423 MonoClassField* field = mono_class_get_field_from_name (k, str);
3424 if (field) {
3425 g_free (str);
3426 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3427 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3429 if (field_klass->valuetype) {
3430 size = mono_type_size (field->type, &align);
3431 g_assert (size == mono_class_value_size (field_klass, NULL));
3432 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3433 } else {
3434 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3437 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3438 if (mono_error_set_pending_exception (&error))
3439 return NULL;
3440 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3442 return NULL;
3445 k = k->parent;
3446 } while (k);
3448 g_free (str);
3449 g_assert_not_reached ();
3454 for (i = 0; i < mono_array_length (params); i++) {
3455 if (sig->params [i]->byref)
3456 outarg_count++;
3459 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3460 if (mono_error_set_pending_exception (&error))
3461 return NULL;
3463 /* handle constructors only for objects already allocated */
3464 if (!strcmp (method->method->name, ".ctor"))
3465 g_assert (this_arg);
3467 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3468 g_assert (!method->method->klass->valuetype);
3469 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3470 if (mono_error_set_pending_exception (&error))
3471 return NULL;
3473 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3474 if (sig->params [i]->byref) {
3475 gpointer arg;
3476 arg = mono_array_get (params, gpointer, i);
3477 mono_array_setref (out_args, j, arg);
3478 j++;
3482 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3484 return result;
3486 #endif
3488 static guint64
3489 read_enum_value (const char *mem, int type)
3491 switch (type) {
3492 case MONO_TYPE_BOOLEAN:
3493 case MONO_TYPE_U1:
3494 return *(guint8*)mem;
3495 case MONO_TYPE_I1:
3496 return *(gint8*)mem;
3497 case MONO_TYPE_CHAR:
3498 case MONO_TYPE_U2:
3499 return read16 (mem);
3500 case MONO_TYPE_I2:
3501 return (gint16) read16 (mem);
3502 case MONO_TYPE_U4:
3503 return read32 (mem);
3504 case MONO_TYPE_I4:
3505 return (gint32) read32 (mem);
3506 case MONO_TYPE_U8:
3507 case MONO_TYPE_I8:
3508 return read64 (mem);
3509 default:
3510 g_assert_not_reached ();
3512 return 0;
3515 static void
3516 write_enum_value (char *mem, int type, guint64 value)
3518 switch (type) {
3519 case MONO_TYPE_U1:
3520 case MONO_TYPE_I1: {
3521 guint8 *p = (guint8*)mem;
3522 *p = value;
3523 break;
3525 case MONO_TYPE_U2:
3526 case MONO_TYPE_I2:
3527 case MONO_TYPE_CHAR: {
3528 guint16 *p = (guint16 *)mem;
3529 *p = value;
3530 break;
3532 case MONO_TYPE_U4:
3533 case MONO_TYPE_I4: {
3534 guint32 *p = (guint32 *)mem;
3535 *p = value;
3536 break;
3538 case MONO_TYPE_U8:
3539 case MONO_TYPE_I8: {
3540 guint64 *p = (guint64 *)mem;
3541 *p = value;
3542 break;
3544 default:
3545 g_assert_not_reached ();
3547 return;
3550 ICALL_EXPORT MonoObject *
3551 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3553 MonoError error;
3554 MonoDomain *domain;
3555 MonoClass *enumc;
3556 MonoObject *res;
3557 MonoType *etype;
3559 domain = mono_object_domain (enumType);
3560 enumc = mono_class_from_mono_type (enumType->type);
3562 mono_class_init_checked (enumc, &error);
3563 if (mono_error_set_pending_exception (&error))
3564 return NULL;
3566 etype = mono_class_enum_basetype (enumc);
3568 res = mono_object_new_checked (domain, enumc, &error);
3569 if (mono_error_set_pending_exception (&error))
3570 return NULL;
3571 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3573 return res;
3576 ICALL_EXPORT MonoBoolean
3577 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3579 int size = mono_class_value_size (a->vtable->klass, NULL);
3580 guint64 a_val = 0, b_val = 0;
3582 memcpy (&a_val, mono_object_unbox (a), size);
3583 memcpy (&b_val, mono_object_unbox (b), size);
3585 return (a_val & b_val) == b_val;
3588 ICALL_EXPORT MonoObject *
3589 ves_icall_System_Enum_get_value (MonoObject *eobj)
3591 MonoError error;
3592 MonoObject *res;
3593 MonoClass *enumc;
3594 gpointer dst;
3595 gpointer src;
3596 int size;
3598 if (!eobj)
3599 return NULL;
3601 g_assert (eobj->vtable->klass->enumtype);
3603 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3604 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3605 if (mono_error_set_pending_exception (&error))
3606 return NULL;
3607 dst = (char *)res + sizeof (MonoObject);
3608 src = (char *)eobj + sizeof (MonoObject);
3609 size = mono_class_value_size (enumc, NULL);
3611 memcpy (dst, src, size);
3613 return res;
3616 ICALL_EXPORT MonoReflectionType *
3617 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3619 MonoError error;
3620 MonoReflectionType *ret;
3621 MonoType *etype;
3622 MonoClass *klass;
3624 klass = mono_class_from_mono_type (type->type);
3625 mono_class_init_checked (klass, &error);
3626 if (mono_error_set_pending_exception (&error))
3627 return NULL;
3629 etype = mono_class_enum_basetype (klass);
3630 if (!etype) {
3631 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3632 return NULL;
3635 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3636 mono_error_set_pending_exception (&error);
3638 return ret;
3641 ICALL_EXPORT int
3642 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3644 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3645 gpointer odata = (char *)other + sizeof (MonoObject);
3646 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3647 g_assert (basetype);
3649 if (other == NULL)
3650 return 1;
3652 if (eobj->vtable->klass != other->vtable->klass)
3653 return 2;
3655 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3656 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3657 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3658 if (me == other) \
3659 return 0; \
3660 return me > other ? 1 : -1; \
3661 } while (0)
3663 switch (basetype->type) {
3664 case MONO_TYPE_U1:
3665 COMPARE_ENUM_VALUES (guint8);
3666 case MONO_TYPE_I1:
3667 COMPARE_ENUM_VALUES (gint8);
3668 case MONO_TYPE_CHAR:
3669 case MONO_TYPE_U2:
3670 COMPARE_ENUM_VALUES (guint16);
3671 case MONO_TYPE_I2:
3672 COMPARE_ENUM_VALUES (gint16);
3673 case MONO_TYPE_U4:
3674 COMPARE_ENUM_VALUES (guint32);
3675 case MONO_TYPE_I4:
3676 COMPARE_ENUM_VALUES (gint32);
3677 case MONO_TYPE_U8:
3678 COMPARE_ENUM_VALUES (guint64);
3679 case MONO_TYPE_I8:
3680 COMPARE_ENUM_VALUES (gint64);
3681 default:
3682 break;
3684 #undef COMPARE_ENUM_VALUES
3685 /* indicates that the enum was of an unsupported unerlying type */
3686 return 3;
3689 ICALL_EXPORT int
3690 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3692 gpointer data = (char *)eobj + sizeof (MonoObject);
3693 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3694 g_assert (basetype);
3696 switch (basetype->type) {
3697 case MONO_TYPE_I1: {
3698 gint8 value = *((gint8*)data);
3699 return ((int)value ^ (int)value << 8);
3701 case MONO_TYPE_U1:
3702 return *((guint8*)data);
3703 case MONO_TYPE_CHAR:
3704 case MONO_TYPE_U2:
3705 return *((guint16*)data);
3707 case MONO_TYPE_I2: {
3708 gint16 value = *((gint16*)data);
3709 return ((int)(guint16)value | (((int)value) << 16));
3711 case MONO_TYPE_U4:
3712 return *((guint32*)data);
3713 case MONO_TYPE_I4:
3714 return *((gint32*)data);
3715 case MONO_TYPE_U8:
3716 case MONO_TYPE_I8: {
3717 gint64 value = *((gint64*)data);
3718 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3720 default:
3721 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3723 return 0;
3726 ICALL_EXPORT MonoBoolean
3727 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3729 MonoError error;
3730 MonoDomain *domain = mono_object_domain (type);
3731 MonoClass *enumc = mono_class_from_mono_type (type->type);
3732 guint j = 0, nvalues;
3733 gpointer iter;
3734 MonoClassField *field;
3735 int base_type;
3736 guint64 field_value, previous_value = 0;
3737 gboolean sorted = TRUE;
3739 mono_class_init_checked (enumc, &error);
3740 if (mono_error_set_pending_exception (&error))
3741 return FALSE;
3744 if (!enumc->enumtype) {
3745 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3746 return TRUE;
3749 base_type = mono_class_enum_basetype (enumc)->type;
3751 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3752 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3753 if (mono_error_set_pending_exception (&error))
3754 return FALSE;
3755 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3756 if (mono_error_set_pending_exception (&error))
3757 return FALSE;
3759 iter = NULL;
3760 while ((field = mono_class_get_fields (enumc, &iter))) {
3761 const char *p;
3762 MonoTypeEnum def_type;
3764 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3765 continue;
3766 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3767 continue;
3768 if (mono_field_is_deleted (field))
3769 continue;
3770 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3772 p = mono_class_get_field_default_value (field, &def_type);
3773 /* len = */ mono_metadata_decode_blob_size (p, &p);
3775 field_value = read_enum_value (p, base_type);
3776 mono_array_set (*values, guint64, j, field_value);
3778 if (previous_value > field_value)
3779 sorted = FALSE;
3781 previous_value = field_value;
3782 ++j;
3785 return sorted;
3788 enum {
3789 BFLAGS_IgnoreCase = 1,
3790 BFLAGS_DeclaredOnly = 2,
3791 BFLAGS_Instance = 4,
3792 BFLAGS_Static = 8,
3793 BFLAGS_Public = 0x10,
3794 BFLAGS_NonPublic = 0x20,
3795 BFLAGS_FlattenHierarchy = 0x40,
3796 BFLAGS_InvokeMethod = 0x100,
3797 BFLAGS_CreateInstance = 0x200,
3798 BFLAGS_GetField = 0x400,
3799 BFLAGS_SetField = 0x800,
3800 BFLAGS_GetProperty = 0x1000,
3801 BFLAGS_SetProperty = 0x2000,
3802 BFLAGS_ExactBinding = 0x10000,
3803 BFLAGS_SuppressChangeType = 0x20000,
3804 BFLAGS_OptionalParamBinding = 0x40000
3807 ICALL_EXPORT GPtrArray*
3808 ves_icall_RuntimeType_GetFields_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
3810 MonoError error;
3811 MonoClass *startklass, *klass;
3812 int match;
3813 gpointer iter;
3814 int (*compare_func) (const char *s1, const char *s2) = NULL;
3815 MonoClassField *field;
3817 if (type->type->byref) {
3818 return g_ptr_array_new ();
3821 mono_error_init (&error);
3823 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3825 klass = startklass = mono_class_from_mono_type (type->type);
3827 GPtrArray *ptr_array = g_ptr_array_sized_new (16);
3829 handle_parent:
3830 if (mono_class_has_failure (klass)) {
3831 mono_error_set_for_class_failure (&error, klass);
3832 goto fail;
3835 iter = NULL;
3836 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3837 guint32 flags = mono_field_get_flags (field);
3838 match = 0;
3839 if (mono_field_is_deleted_with_flags (field, flags))
3840 continue;
3841 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3842 if (bflags & BFLAGS_Public)
3843 match++;
3844 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3845 if (bflags & BFLAGS_NonPublic) {
3846 match++;
3849 if (!match)
3850 continue;
3851 match = 0;
3852 if (flags & FIELD_ATTRIBUTE_STATIC) {
3853 if (bflags & BFLAGS_Static)
3854 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3855 match++;
3856 } else {
3857 if (bflags & BFLAGS_Instance)
3858 match++;
3861 if (!match)
3862 continue;
3864 if (utf8_name != NULL && compare_func (mono_field_get_name (field), utf8_name))
3865 continue;
3867 g_ptr_array_add (ptr_array, field);
3869 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3870 goto handle_parent;
3872 return ptr_array;
3874 fail:
3875 g_ptr_array_free (ptr_array, TRUE);
3876 mono_error_set_pending_exception (&error);
3877 return NULL;
3880 static gboolean
3881 method_nonpublic (MonoMethod* method, gboolean start_klass)
3883 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3884 case METHOD_ATTRIBUTE_ASSEM:
3885 return (start_klass || mono_defaults.generic_ilist_class);
3886 case METHOD_ATTRIBUTE_PRIVATE:
3887 return start_klass;
3888 case METHOD_ATTRIBUTE_PUBLIC:
3889 return FALSE;
3890 default:
3891 return TRUE;
3895 GPtrArray*
3896 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError *error)
3898 GPtrArray *array;
3899 MonoClass *startklass;
3900 MonoMethod *method;
3901 gpointer iter;
3902 int match, nslots;
3903 /*FIXME, use MonoBitSet*/
3904 guint32 method_slots_default [8];
3905 guint32 *method_slots = NULL;
3906 int (*compare_func) (const char *s1, const char *s2) = NULL;
3908 array = g_ptr_array_new ();
3909 startklass = klass;
3910 mono_error_init (error);
3912 if (name != NULL)
3913 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3915 /* An optimization for calls made from Delegate:CreateDelegate () */
3916 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3917 method = mono_get_delegate_invoke (klass);
3918 g_assert (method);
3920 g_ptr_array_add (array, method);
3921 return array;
3924 mono_class_setup_methods (klass);
3925 mono_class_setup_vtable (klass);
3926 if (mono_class_has_failure (klass))
3927 goto loader_error;
3929 if (is_generic_parameter (&klass->byval_arg))
3930 nslots = mono_class_get_vtable_size (klass->parent);
3931 else
3932 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3933 if (nslots >= sizeof (method_slots_default) * 8) {
3934 method_slots = g_new0 (guint32, nslots / 32 + 1);
3935 } else {
3936 method_slots = method_slots_default;
3937 memset (method_slots, 0, sizeof (method_slots_default));
3939 handle_parent:
3940 mono_class_setup_methods (klass);
3941 mono_class_setup_vtable (klass);
3942 if (mono_class_has_failure (klass))
3943 goto loader_error;
3945 iter = NULL;
3946 while ((method = mono_class_get_methods (klass, &iter))) {
3947 match = 0;
3948 if (method->slot != -1) {
3949 g_assert (method->slot < nslots);
3950 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3951 continue;
3952 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3953 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3956 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3957 continue;
3958 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3959 if (bflags & BFLAGS_Public)
3960 match++;
3961 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3962 match++;
3964 if (!match)
3965 continue;
3966 match = 0;
3967 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3968 if (bflags & BFLAGS_Static)
3969 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3970 match++;
3971 } else {
3972 if (bflags & BFLAGS_Instance)
3973 match++;
3976 if (!match)
3977 continue;
3979 if (name != NULL) {
3980 if (compare_func (name, method->name))
3981 continue;
3984 match = 0;
3985 g_ptr_array_add (array, method);
3987 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3988 goto handle_parent;
3989 if (method_slots != method_slots_default)
3990 g_free (method_slots);
3992 return array;
3994 loader_error:
3995 if (method_slots != method_slots_default)
3996 g_free (method_slots);
3997 g_ptr_array_free (array, TRUE);
3999 g_assert (mono_class_has_failure (klass));
4000 mono_error_set_for_class_failure (error, klass);
4001 return NULL;
4004 ICALL_EXPORT GPtrArray*
4005 ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionType *type, const char *mname, guint32 bflags, MonoBoolean ignore_case)
4007 MonoError error;
4008 GPtrArray *method_array;
4009 MonoClass *klass;
4011 klass = mono_class_from_mono_type (type->type);
4012 if (type->type->byref) {
4013 return g_ptr_array_new ();
4016 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &error);
4017 mono_error_set_pending_exception (&error);
4018 return method_array;
4021 ICALL_EXPORT GPtrArray*
4022 ves_icall_RuntimeType_GetConstructors_native (MonoReflectionType *type, guint32 bflags)
4024 MonoClass *startklass, *klass;
4025 MonoMethod *method;
4026 int match;
4027 gpointer iter = NULL;
4028 GPtrArray *res_array;
4029 MonoError error;
4031 if (type->type->byref) {
4032 return g_ptr_array_new ();
4035 klass = startklass = mono_class_from_mono_type (type->type);
4037 mono_class_setup_methods (klass);
4038 if (mono_class_has_failure (klass)) {
4039 mono_error_init (&error);
4040 mono_error_set_for_class_failure (&error, klass);
4041 mono_error_set_pending_exception (&error);
4042 return NULL;
4045 res_array = g_ptr_array_sized_new (4); /* FIXME, guestimating */
4047 iter = NULL;
4048 while ((method = mono_class_get_methods (klass, &iter))) {
4049 match = 0;
4050 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
4051 continue;
4052 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4053 if (bflags & BFLAGS_Public)
4054 match++;
4055 } else {
4056 if (bflags & BFLAGS_NonPublic)
4057 match++;
4059 if (!match)
4060 continue;
4061 match = 0;
4062 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4063 if (bflags & BFLAGS_Static)
4064 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4065 match++;
4066 } else {
4067 if (bflags & BFLAGS_Instance)
4068 match++;
4071 if (!match)
4072 continue;
4073 g_ptr_array_add (res_array, method);
4076 return res_array;
4079 static guint
4080 property_hash (gconstpointer data)
4082 MonoProperty *prop = (MonoProperty*)data;
4084 return g_str_hash (prop->name);
4087 static gboolean
4088 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
4090 if (method1->slot != -1 && method1->slot == method2->slot)
4091 return TRUE;
4093 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
4094 if (method1->is_inflated)
4095 method1 = ((MonoMethodInflated*) method1)->declaring;
4096 if (method2->is_inflated)
4097 method2 = ((MonoMethodInflated*) method2)->declaring;
4100 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4103 static gboolean
4104 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4106 // Properties are hide-by-name-and-signature
4107 if (!g_str_equal (prop1->name, prop2->name))
4108 return FALSE;
4110 /* If we see a property in a generic method, we want to
4111 compare the generic signatures, not the inflated signatures
4112 because we might conflate two properties that were
4113 distinct:
4115 class Foo<T,U> {
4116 public T this[T t] { getter { return t; } } // method 1
4117 public U this[U u] { getter { return u; } } // method 2
4120 If we see int Foo<int,int>::Item[int] we need to know if
4121 the indexer came from method 1 or from method 2, and we
4122 shouldn't conflate them. (Bugzilla 36283)
4124 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4125 return FALSE;
4127 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4128 return FALSE;
4130 return TRUE;
4133 static gboolean
4134 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4136 if (!accessor)
4137 return FALSE;
4139 return method_nonpublic (accessor, start_klass);
4142 ICALL_EXPORT GPtrArray*
4143 ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionType *type, gchar *propname, guint32 bflags, MonoBoolean ignore_case)
4145 MonoError error;
4146 MonoClass *startklass, *klass;
4147 MonoMethod *method;
4148 MonoProperty *prop;
4149 int match;
4150 guint32 flags;
4151 int (*compare_func) (const char *s1, const char *s2) = NULL;
4152 gpointer iter;
4153 GHashTable *properties = NULL;
4154 GPtrArray *res_array;
4156 if (type->type->byref) {
4157 return g_ptr_array_new ();
4160 mono_error_init (&error);
4162 klass = startklass = mono_class_from_mono_type (type->type);
4164 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4166 res_array = g_ptr_array_sized_new (8); /*This the average for ASP.NET types*/
4168 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4169 handle_parent:
4170 mono_class_setup_methods (klass);
4171 mono_class_setup_vtable (klass);
4172 if (mono_class_has_failure (klass)) {
4173 mono_error_set_for_class_failure (&error, klass);
4174 goto loader_error;
4177 iter = NULL;
4178 while ((prop = mono_class_get_properties (klass, &iter))) {
4179 match = 0;
4180 method = prop->get;
4181 if (!method)
4182 method = prop->set;
4183 if (method)
4184 flags = method->flags;
4185 else
4186 flags = 0;
4187 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4188 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4189 if (bflags & BFLAGS_Public)
4190 match++;
4191 } else if (bflags & BFLAGS_NonPublic) {
4192 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4193 property_accessor_nonpublic(prop->set, startklass == klass)) {
4194 match++;
4197 if (!match)
4198 continue;
4199 match = 0;
4200 if (flags & METHOD_ATTRIBUTE_STATIC) {
4201 if (bflags & BFLAGS_Static)
4202 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4203 match++;
4204 } else {
4205 if (bflags & BFLAGS_Instance)
4206 match++;
4209 if (!match)
4210 continue;
4211 match = 0;
4213 if (propname != NULL && compare_func (propname, prop->name))
4214 continue;
4216 if (g_hash_table_lookup (properties, prop))
4217 continue;
4219 g_ptr_array_add (res_array, prop);
4221 g_hash_table_insert (properties, prop, prop);
4223 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4224 goto handle_parent;
4226 g_hash_table_destroy (properties);
4228 return res_array;
4231 loader_error:
4232 if (properties)
4233 g_hash_table_destroy (properties);
4234 g_ptr_array_free (res_array, TRUE);
4236 mono_error_set_pending_exception (&error);
4238 return NULL;
4241 static guint
4242 event_hash (gconstpointer data)
4244 MonoEvent *event = (MonoEvent*)data;
4246 return g_str_hash (event->name);
4249 static gboolean
4250 event_equal (MonoEvent *event1, MonoEvent *event2)
4252 // Events are hide-by-name
4253 return g_str_equal (event1->name, event2->name);
4256 ICALL_EXPORT GPtrArray*
4257 ves_icall_RuntimeType_GetEvents_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
4259 MonoError error;
4260 MonoClass *startklass, *klass;
4261 MonoMethod *method;
4262 MonoEvent *event;
4263 int match;
4264 gpointer iter;
4265 int (*compare_func) (const char *s1, const char *s2) = NULL;
4266 GHashTable *events = NULL;
4267 GPtrArray *res_array;
4269 if (type->type->byref) {
4270 return g_ptr_array_new ();
4273 mono_error_init (&error);
4275 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4277 res_array = g_ptr_array_sized_new (4);
4279 klass = startklass = mono_class_from_mono_type (type->type);
4281 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4282 handle_parent:
4283 mono_class_setup_methods (klass);
4284 mono_class_setup_vtable (klass);
4285 if (mono_class_has_failure (klass)) {
4286 mono_error_set_for_class_failure (&error, klass);
4287 goto failure;
4290 iter = NULL;
4291 while ((event = mono_class_get_events (klass, &iter))) {
4292 match = 0;
4293 method = event->add;
4294 if (!method)
4295 method = event->remove;
4296 if (!method)
4297 method = event->raise;
4298 if (method) {
4299 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4300 if (bflags & BFLAGS_Public)
4301 match++;
4302 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4303 if (bflags & BFLAGS_NonPublic)
4304 match++;
4307 else
4308 if (bflags & BFLAGS_NonPublic)
4309 match ++;
4310 if (!match)
4311 continue;
4312 match = 0;
4313 if (method) {
4314 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4315 if (bflags & BFLAGS_Static)
4316 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4317 match++;
4318 } else {
4319 if (bflags & BFLAGS_Instance)
4320 match++;
4323 else
4324 if (bflags & BFLAGS_Instance)
4325 match ++;
4326 if (!match)
4327 continue;
4329 if (utf8_name != NULL && compare_func (event->name, utf8_name))
4330 continue;
4332 if (g_hash_table_lookup (events, event))
4333 continue;
4335 g_ptr_array_add (res_array, event);
4337 g_hash_table_insert (events, event, event);
4339 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4340 goto handle_parent;
4342 g_hash_table_destroy (events);
4344 return res_array;
4346 failure:
4347 if (events != NULL)
4348 g_hash_table_destroy (events);
4350 g_ptr_array_free (res_array, TRUE);
4352 mono_error_set_pending_exception (&error);
4353 return NULL;
4356 ICALL_EXPORT GPtrArray *
4357 ves_icall_RuntimeType_GetNestedTypes_native (MonoReflectionType *type, char *str, guint32 bflags)
4359 MonoClass *klass;
4360 int match;
4361 MonoClass *nested;
4362 gpointer iter;
4363 GPtrArray *res_array;
4365 if (type->type->byref) {
4366 return g_ptr_array_new ();
4369 klass = mono_class_from_mono_type (type->type);
4372 * If a nested type is generic, return its generic type definition.
4373 * Note that this means that the return value is essentially the set
4374 * of nested types of the generic type definition of @klass.
4376 * A note in MSDN claims that a generic type definition can have
4377 * nested types that aren't generic. In any case, the container of that
4378 * nested type would be the generic type definition.
4380 if (klass->generic_class)
4381 klass = klass->generic_class->container_class;
4383 res_array = g_ptr_array_new ();
4385 iter = NULL;
4386 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4387 match = 0;
4388 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4389 if (bflags & BFLAGS_Public)
4390 match++;
4391 } else {
4392 if (bflags & BFLAGS_NonPublic)
4393 match++;
4395 if (!match)
4396 continue;
4398 if (str != NULL && strcmp (nested->name, str))
4399 continue;
4401 g_ptr_array_add (res_array, &nested->byval_arg);
4404 return res_array;
4407 ICALL_EXPORT MonoReflectionType*
4408 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4410 MonoError error;
4411 MonoReflectionType *ret;
4412 gchar *str;
4413 MonoType *type = NULL;
4414 MonoTypeNameParse info;
4415 gboolean type_resolve;
4417 /* On MS.NET, this does not fire a TypeResolve event */
4418 type_resolve = TRUE;
4419 str = mono_string_to_utf8_checked (name, &error);
4420 if (mono_error_set_pending_exception (&error))
4421 return NULL;
4422 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4423 if (!mono_reflection_parse_type (str, &info)) {
4424 g_free (str);
4425 mono_reflection_free_type_info (&info);
4426 if (throwOnError) {
4427 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4428 return NULL;
4430 /*g_print ("failed parse\n");*/
4431 return NULL;
4434 if (info.assembly.name) {
4435 g_free (str);
4436 mono_reflection_free_type_info (&info);
4437 if (throwOnError) {
4438 /* 1.0 and 2.0 throw different exceptions */
4439 if (mono_defaults.generic_ilist_class)
4440 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4441 else
4442 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4443 return NULL;
4445 return NULL;
4448 if (module != NULL) {
4449 if (module->image) {
4450 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4451 if (!is_ok (&error)) {
4452 g_free (str);
4453 mono_reflection_free_type_info (&info);
4454 mono_error_set_pending_exception (&error);
4455 return NULL;
4457 } else
4458 type = NULL;
4460 else
4461 if (assembly_is_dynamic (assembly->assembly)) {
4462 /* Enumerate all modules */
4463 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4464 int i;
4466 type = NULL;
4467 if (abuilder->modules) {
4468 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4469 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4470 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4471 if (!is_ok (&error)) {
4472 g_free (str);
4473 mono_reflection_free_type_info (&info);
4474 mono_error_set_pending_exception (&error);
4475 return NULL;
4477 if (type)
4478 break;
4482 if (!type && abuilder->loaded_modules) {
4483 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4484 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4485 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4486 if (!is_ok (&error)) {
4487 g_free (str);
4488 mono_reflection_free_type_info (&info);
4489 mono_error_set_pending_exception (&error);
4490 return NULL;
4492 if (type)
4493 break;
4497 else {
4498 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4499 if (!is_ok (&error)) {
4500 g_free (str);
4501 mono_reflection_free_type_info (&info);
4502 mono_error_set_pending_exception (&error);
4503 return NULL;
4506 g_free (str);
4507 mono_reflection_free_type_info (&info);
4508 if (!type) {
4509 MonoException *e = NULL;
4511 if (throwOnError)
4512 e = mono_get_exception_type_load (name, NULL);
4514 if (e != NULL)
4515 mono_set_pending_exception (e);
4516 return NULL;
4519 if (type->type == MONO_TYPE_CLASS) {
4520 MonoClass *klass = mono_type_get_class (type);
4522 /* need to report exceptions ? */
4523 if (throwOnError && mono_class_has_failure (klass)) {
4524 /* report SecurityException (or others) that occured when loading the assembly */
4525 MonoException *exc = mono_class_get_exception_for_failure (klass);
4526 mono_set_pending_exception (exc);
4527 return NULL;
4531 /* g_print ("got it\n"); */
4532 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4533 mono_error_set_pending_exception (&error);
4535 return ret;
4538 static gboolean
4539 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4541 gchar *content;
4542 gchar *shadow_ini_file;
4543 gsize len;
4545 /* Check for shadow-copied assembly */
4546 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4547 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4548 content = NULL;
4549 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4550 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4551 if (content) {
4552 g_free (content);
4553 content = NULL;
4556 g_free (shadow_ini_file);
4557 if (content != NULL) {
4558 if (*filename)
4559 g_free (*filename);
4560 *filename = content;
4561 return TRUE;
4564 return FALSE;
4567 ICALL_EXPORT MonoString *
4568 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4570 MonoDomain *domain = mono_object_domain (assembly);
4571 MonoAssembly *mass = assembly->assembly;
4572 MonoString *res = NULL;
4573 gchar *uri;
4574 gchar *absolute;
4575 gchar *dirname;
4577 if (g_path_is_absolute (mass->image->name)) {
4578 absolute = g_strdup (mass->image->name);
4579 dirname = g_path_get_dirname (absolute);
4580 } else {
4581 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4582 dirname = g_strdup (mass->basedir);
4585 replace_shadow_path (domain, dirname, &absolute);
4586 g_free (dirname);
4587 #if HOST_WIN32
4589 gint i;
4590 for (i = strlen (absolute) - 1; i >= 0; i--)
4591 if (absolute [i] == '\\')
4592 absolute [i] = '/';
4594 #endif
4595 if (escaped) {
4596 uri = g_filename_to_uri (absolute, NULL, NULL);
4597 } else {
4598 const char *prepend = "file://";
4599 #if HOST_WIN32
4600 if (*absolute == '/' && *(absolute + 1) == '/') {
4601 prepend = "file:";
4602 } else {
4603 prepend = "file:///";
4605 #endif
4606 uri = g_strconcat (prepend, absolute, NULL);
4609 if (uri) {
4610 res = mono_string_new (domain, uri);
4611 g_free (uri);
4613 g_free (absolute);
4614 return res;
4617 ICALL_EXPORT MonoBoolean
4618 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4620 MonoAssembly *mass = assembly->assembly;
4622 return mass->in_gac;
4625 ICALL_EXPORT MonoReflectionAssembly*
4626 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4628 MonoError error;
4629 gchar *name;
4630 MonoAssembly *res;
4631 MonoImageOpenStatus status;
4632 MonoReflectionAssembly* result = NULL;
4634 name = mono_string_to_utf8_checked (mname, &error);
4635 if (mono_error_set_pending_exception (&error))
4636 return NULL;
4637 res = mono_assembly_load_with_partial_name (name, &status);
4639 g_free (name);
4641 if (res == NULL)
4642 return NULL;
4643 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4644 if (!result)
4645 mono_error_set_pending_exception (&error);
4646 return result;
4649 ICALL_EXPORT MonoString *
4650 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4652 MonoDomain *domain = mono_object_domain (assembly);
4653 MonoString *res;
4655 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4657 return res;
4660 ICALL_EXPORT MonoBoolean
4661 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4663 return assembly->assembly->ref_only;
4666 ICALL_EXPORT MonoString *
4667 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4669 MonoDomain *domain = mono_object_domain (assembly);
4671 return mono_string_new (domain, assembly->assembly->image->version);
4674 ICALL_EXPORT MonoReflectionMethod*
4675 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4677 MonoError error;
4678 MonoReflectionMethod *res = NULL;
4679 MonoMethod *method;
4681 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4683 if (!token)
4684 return NULL;
4685 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4686 if (!mono_error_ok (&error))
4687 goto leave;
4689 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4691 leave:
4692 if (!mono_error_ok (&error))
4693 mono_error_set_pending_exception (&error);
4694 return res;
4697 ICALL_EXPORT MonoReflectionModule*
4698 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4700 MonoError error;
4701 MonoReflectionModule *result = NULL;
4702 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4703 if (!mono_error_ok (&error))
4704 mono_error_set_pending_exception (&error);
4705 return result;
4708 ICALL_EXPORT MonoArray*
4709 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4711 MonoError error;
4712 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4713 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4714 if (mono_error_set_pending_exception (&error))
4715 return NULL;
4716 int i;
4717 const char *val;
4719 for (i = 0; i < table->rows; ++i) {
4720 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4721 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4723 return result;
4726 ICALL_EXPORT MonoString*
4727 ves_icall_System_Reflection_Assembly_GetAotId ()
4729 int i;
4730 guint8 aotid_sum = 0;
4731 MonoDomain* domain = mono_domain_get ();
4733 if (!domain->entry_assembly || !domain->entry_assembly->image)
4734 return NULL;
4736 guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
4738 for (i = 0; i < 16; ++i)
4739 aotid_sum |= (*aotid)[i];
4741 if (aotid_sum == 0)
4742 return NULL;
4744 return mono_string_new (domain, mono_guid_to_string((guint8*) aotid));
4747 static MonoObject*
4748 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4750 static MonoMethod *create_version = NULL;
4751 MonoObject *result;
4752 gpointer args [4];
4754 mono_error_init (error);
4757 if (!create_version) {
4758 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4759 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4760 g_assert (create_version);
4761 mono_method_desc_free (desc);
4764 args [0] = &major;
4765 args [1] = &minor;
4766 args [2] = &build;
4767 args [3] = &revision;
4768 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4769 return_val_if_nok (error, NULL);
4771 mono_runtime_invoke_checked (create_version, result, args, error);
4772 return_val_if_nok (error, NULL);
4774 return result;
4777 ICALL_EXPORT MonoArray*
4778 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4780 MonoError error;
4781 MonoArray *result;
4782 MonoDomain *domain = mono_object_domain (assembly);
4783 int i, count = 0;
4784 static MonoMethod *create_culture = NULL;
4785 MonoImage *image = assembly->assembly->image;
4786 MonoTableInfo *t;
4787 MonoObject *o;
4789 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4790 count = t->rows;
4792 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4793 if (mono_error_set_pending_exception (&error))
4794 return NULL;
4797 if (count > 0 && !create_culture) {
4798 MonoMethodDesc *desc = mono_method_desc_new (
4799 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4800 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4801 g_assert (create_culture);
4802 mono_method_desc_free (desc);
4805 for (i = 0; i < count; i++) {
4806 MonoObject *version;
4807 MonoReflectionAssemblyName *aname;
4808 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4810 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4812 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4813 domain, mono_class_get_assembly_name_class (), &error);
4814 if (mono_error_set_pending_exception (&error))
4815 return NULL;
4817 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4819 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4820 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4821 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4822 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4823 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4824 aname->versioncompat = 1; /* SameMachine (default) */
4825 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4827 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4828 if (mono_error_set_pending_exception (&error))
4829 return NULL;
4831 MONO_OBJECT_SETREF (aname, version, version);
4833 if (create_culture) {
4834 gpointer args [2];
4835 MonoBoolean assembly_ref = 1;
4836 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4837 args [1] = &assembly_ref;
4839 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4840 if (mono_error_set_pending_exception (&error))
4841 return NULL;
4843 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4846 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4847 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4848 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4850 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4851 /* public key token isn't copied - the class library will
4852 automatically generate it from the public key if required */
4853 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4854 if (mono_error_set_pending_exception (&error))
4855 return NULL;
4857 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4858 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4859 } else {
4860 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4861 if (mono_error_set_pending_exception (&error))
4862 return NULL;
4864 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4865 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
4867 } else {
4868 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
4869 if (mono_error_set_pending_exception (&error))
4870 return NULL;
4872 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4875 /* note: this function doesn't return the codebase on purpose (i.e. it can
4876 be used under partial trust as path information isn't present). */
4878 mono_array_setref (result, i, aname);
4880 return result;
4883 /* move this in some file in mono/util/ */
4884 static char *
4885 g_concat_dir_and_file (const char *dir, const char *file)
4887 g_return_val_if_fail (dir != NULL, NULL);
4888 g_return_val_if_fail (file != NULL, NULL);
4891 * If the directory name doesn't have a / on the end, we need
4892 * to add one so we get a proper path to the file
4894 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4895 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4896 else
4897 return g_strconcat (dir, file, NULL);
4900 ICALL_EXPORT void *
4901 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4903 MonoError error;
4904 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4905 guint32 i;
4906 guint32 cols [MONO_MANIFEST_SIZE];
4907 guint32 impl, file_idx;
4908 const char *val;
4909 MonoImage *module;
4911 char *n = mono_string_to_utf8_checked (name, &error);
4912 if (mono_error_set_pending_exception (&error))
4913 return NULL;
4915 for (i = 0; i < table->rows; ++i) {
4916 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4917 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4918 if (strcmp (val, n) == 0)
4919 break;
4921 g_free (n);
4922 if (i == table->rows)
4923 return NULL;
4924 /* FIXME */
4925 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4926 if (impl) {
4928 * this code should only be called after obtaining the
4929 * ResourceInfo and handling the other cases.
4931 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4932 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4934 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4935 if (!module)
4936 return NULL;
4938 else
4939 module = assembly->assembly->image;
4942 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4943 if (mono_error_set_pending_exception (&error))
4944 return NULL;
4945 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4947 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4950 ICALL_EXPORT gboolean
4951 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4953 MonoError error;
4954 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4955 int i;
4956 guint32 cols [MONO_MANIFEST_SIZE];
4957 guint32 file_cols [MONO_FILE_SIZE];
4958 const char *val;
4959 char *n;
4961 n = mono_string_to_utf8_checked (name, &error);
4962 if (mono_error_set_pending_exception (&error))
4963 return FALSE;
4964 for (i = 0; i < table->rows; ++i) {
4965 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4966 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4967 if (strcmp (val, n) == 0)
4968 break;
4970 g_free (n);
4971 if (i == table->rows)
4972 return FALSE;
4974 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4975 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4977 else {
4978 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4979 case MONO_IMPLEMENTATION_FILE:
4980 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4981 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4982 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4983 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4984 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4985 if (file_cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA)
4986 info->location = 0;
4987 else
4988 info->location = RESOURCE_LOCATION_EMBEDDED;
4989 break;
4991 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4992 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4993 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4994 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4995 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4996 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4997 g_free (msg);
4998 mono_set_pending_exception (ex);
4999 return FALSE;
5001 MonoReflectionAssembly *assm_obj;
5002 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5003 if (!assm_obj) {
5004 mono_error_set_pending_exception (&error);
5005 return FALSE;
5007 MONO_OBJECT_SETREF (info, assembly, assm_obj);
5009 /* Obtain info recursively */
5010 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5011 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5012 break;
5014 case MONO_IMPLEMENTATION_EXP_TYPE:
5015 g_assert_not_reached ();
5016 break;
5020 return TRUE;
5023 ICALL_EXPORT MonoObject*
5024 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
5026 MonoError error;
5027 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5028 MonoArray *result = NULL;
5029 int i, count;
5030 const char *val;
5031 char *n;
5033 /* check hash if needed */
5034 if (name) {
5035 n = mono_string_to_utf8_checked (name, &error);
5036 if (mono_error_set_pending_exception (&error))
5037 return NULL;
5039 for (i = 0; i < table->rows; ++i) {
5040 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5041 if (strcmp (val, n) == 0) {
5042 MonoString *fn;
5043 g_free (n);
5044 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5045 fn = mono_string_new (mono_object_domain (assembly), n);
5046 g_free (n);
5047 return (MonoObject*)fn;
5050 g_free (n);
5051 return NULL;
5054 count = 0;
5055 for (i = 0; i < table->rows; ++i) {
5056 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5057 count ++;
5060 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
5061 if (mono_error_set_pending_exception (&error))
5062 return NULL;
5065 count = 0;
5066 for (i = 0; i < table->rows; ++i) {
5067 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5068 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5069 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5070 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5071 g_free (n);
5072 count ++;
5075 return (MonoObject*)result;
5078 ICALL_EXPORT MonoArray*
5079 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5081 MonoError error;
5082 MonoDomain *domain = mono_domain_get();
5083 MonoArray *res;
5084 MonoClass *klass;
5085 int i, j, file_count = 0;
5086 MonoImage **modules;
5087 guint32 module_count, real_module_count;
5088 MonoTableInfo *table;
5089 guint32 cols [MONO_FILE_SIZE];
5090 MonoImage *image = assembly->assembly->image;
5092 g_assert (image != NULL);
5093 g_assert (!assembly_is_dynamic (assembly->assembly));
5095 table = &image->tables [MONO_TABLE_FILE];
5096 file_count = table->rows;
5098 modules = image->modules;
5099 module_count = image->module_count;
5101 real_module_count = 0;
5102 for (i = 0; i < module_count; ++i)
5103 if (modules [i])
5104 real_module_count ++;
5106 klass = mono_class_get_module_class ();
5107 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5108 if (mono_error_set_pending_exception (&error))
5109 return NULL;
5111 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5112 if (mono_error_set_pending_exception (&error))
5113 return NULL;
5115 mono_array_setref (res, 0, image_obj);
5116 j = 1;
5117 for (i = 0; i < module_count; ++i)
5118 if (modules [i]) {
5119 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5120 if (mono_error_set_pending_exception (&error))
5121 return NULL;
5122 mono_array_setref (res, j, rm);
5123 ++j;
5126 for (i = 0; i < file_count; ++i, ++j) {
5127 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5128 if (cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA) {
5129 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5130 if (mono_error_set_pending_exception (&error))
5131 return NULL;
5132 mono_array_setref (res, j, rm);
5134 else {
5135 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5136 if (!m) {
5137 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5138 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5139 return NULL;
5141 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5142 if (mono_error_set_pending_exception (&error))
5143 return NULL;
5144 mono_array_setref (res, j, rm);
5148 return res;
5151 ICALL_EXPORT MonoReflectionMethod*
5152 ves_icall_GetCurrentMethod (void)
5154 MonoReflectionMethod *res = NULL;
5155 MonoError error;
5157 MonoMethod *m = mono_method_get_last_managed ();
5159 if (!m) {
5160 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5161 return NULL;
5164 while (m->is_inflated)
5165 m = ((MonoMethodInflated*)m)->declaring;
5167 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5168 mono_error_set_pending_exception (&error);
5169 return res;
5173 static MonoMethod*
5174 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5176 int offset = -1, i;
5177 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5178 MonoError error;
5179 MonoMethod *result;
5180 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5181 //method is inflated, we should inflate it on the other class
5182 MonoGenericContext ctx;
5183 ctx.method_inst = inflated->context.method_inst;
5184 ctx.class_inst = inflated->context.class_inst;
5185 if (klass->generic_class)
5186 ctx.class_inst = klass->generic_class->context.class_inst;
5187 else if (klass->generic_container)
5188 ctx.class_inst = klass->generic_container->context.class_inst;
5189 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5190 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5191 return result;
5194 mono_class_setup_methods (method->klass);
5195 if (mono_class_has_failure (method->klass))
5196 return NULL;
5197 for (i = 0; i < method->klass->method.count; ++i) {
5198 if (method->klass->methods [i] == method) {
5199 offset = i;
5200 break;
5203 mono_class_setup_methods (klass);
5204 if (mono_class_has_failure (klass))
5205 return NULL;
5206 g_assert (offset >= 0 && offset < klass->method.count);
5207 return klass->methods [offset];
5210 ICALL_EXPORT MonoReflectionMethod*
5211 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check)
5213 MonoReflectionMethod *res = NULL;
5214 MonoError error;
5215 MonoClass *klass;
5216 if (type && generic_check) {
5217 klass = mono_class_from_mono_type (type);
5218 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5219 return NULL;
5221 if (method->klass != klass) {
5222 method = mono_method_get_equivalent_method (method, klass);
5223 if (!method)
5224 return NULL;
5226 } else if (type)
5227 klass = mono_class_from_mono_type (type);
5228 else
5229 klass = method->klass;
5230 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5231 mono_error_set_pending_exception (&error);
5232 return res;
5235 ICALL_EXPORT MonoReflectionMethodBody*
5236 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5238 MonoError error;
5239 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5240 mono_error_set_pending_exception (&error);
5241 return result;
5244 ICALL_EXPORT MonoReflectionAssembly*
5245 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5247 MonoError error;
5248 MonoReflectionAssembly *result;
5249 MonoMethod *dest = NULL;
5251 mono_stack_walk_no_il (get_executing, &dest);
5252 g_assert (dest);
5253 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5254 if (!result)
5255 mono_error_set_pending_exception (&error);
5256 return result;
5260 ICALL_EXPORT MonoReflectionAssembly*
5261 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5263 MonoError error;
5264 MonoReflectionAssembly *result;
5265 MonoDomain* domain = mono_domain_get ();
5267 if (!domain->entry_assembly)
5268 return NULL;
5270 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5271 if (!result)
5272 mono_error_set_pending_exception (&error);
5273 return result;
5276 ICALL_EXPORT MonoReflectionAssembly*
5277 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5279 MonoError error;
5280 MonoMethod *m;
5281 MonoMethod *dest;
5282 MonoReflectionAssembly *result;
5284 dest = NULL;
5285 mono_stack_walk_no_il (get_executing, &dest);
5286 m = dest;
5287 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5288 if (!dest)
5289 dest = m;
5290 if (!m) {
5291 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5292 return NULL;
5294 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5295 if (!result)
5296 mono_error_set_pending_exception (&error);
5297 return result;
5300 ICALL_EXPORT MonoString *
5301 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5302 gboolean assembly_qualified)
5304 MonoDomain *domain = mono_object_domain (object);
5305 MonoTypeNameFormat format;
5306 MonoString *res;
5307 gchar *name;
5309 if (full_name)
5310 format = assembly_qualified ?
5311 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5312 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5313 else
5314 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5316 name = mono_type_get_name_full (object->type, format);
5317 if (!name)
5318 return NULL;
5320 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5321 g_free (name);
5322 return NULL;
5325 res = mono_string_new (domain, name);
5326 g_free (name);
5328 return res;
5331 ICALL_EXPORT int
5332 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5334 MonoError error;
5335 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5337 mono_class_init_checked (klass, &error);
5338 mono_error_set_pending_exception (&error);
5339 return mono_security_core_clr_class_level (klass);
5342 ICALL_EXPORT int
5343 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5345 MonoClassField *field = rfield->field;
5346 return mono_security_core_clr_field_level (field, TRUE);
5349 ICALL_EXPORT int
5350 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5352 MonoMethod *method = rfield->method;
5353 return mono_security_core_clr_method_level (method, TRUE);
5356 static void
5357 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)
5359 static MonoMethod *create_culture = NULL;
5360 MonoObject *obj;
5361 gpointer args [2];
5362 guint32 pkey_len;
5363 const char *pkey_ptr;
5364 gchar *codebase;
5365 MonoBoolean assembly_ref = 0;
5367 mono_error_init (error);
5369 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5370 aname->major = name->major;
5371 aname->minor = name->minor;
5372 aname->build = name->build;
5373 aname->flags = name->flags;
5374 aname->revision = name->revision;
5375 aname->hashalg = name->hash_alg;
5376 aname->versioncompat = 1; /* SameMachine (default) */
5377 aname->processor_architecture = name->arch;
5379 if (by_default_version) {
5380 MonoObject *version;
5382 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5383 return_if_nok (error);
5385 MONO_OBJECT_SETREF (aname, version, version);
5388 codebase = NULL;
5389 if (absolute != NULL && *absolute != '\0') {
5390 const gchar *prepend = "file://";
5391 gchar *result;
5393 codebase = g_strdup (absolute);
5395 #if HOST_WIN32
5397 gint i;
5398 for (i = strlen (codebase) - 1; i >= 0; i--)
5399 if (codebase [i] == '\\')
5400 codebase [i] = '/';
5402 if (*codebase == '/' && *(codebase + 1) == '/') {
5403 prepend = "file:";
5404 } else {
5405 prepend = "file:///";
5408 #endif
5409 result = g_strconcat (prepend, codebase, NULL);
5410 g_free (codebase);
5411 codebase = result;
5414 if (codebase) {
5415 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5416 g_free (codebase);
5419 if (!create_culture) {
5420 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5421 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5422 g_assert (create_culture);
5423 mono_method_desc_free (desc);
5426 if (name->culture) {
5427 args [0] = mono_string_new (domain, name->culture);
5428 args [1] = &assembly_ref;
5430 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5431 return_if_nok (error);
5433 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5436 if (name->public_key) {
5437 pkey_ptr = (char*)name->public_key;
5438 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5440 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5441 return_if_nok (error);
5442 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5443 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5444 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5445 } else if (default_publickey) {
5446 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5447 return_if_nok (error);
5448 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5449 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5452 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5453 if (name->public_key_token [0]) {
5454 int i, j;
5455 char *p;
5457 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5458 return_if_nok (error);
5460 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5461 p = mono_array_addr (keyToken, char, 0);
5463 for (i = 0, j = 0; i < 8; i++) {
5464 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5465 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5466 p++;
5468 } else if (default_token) {
5469 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5470 return_if_nok (error);
5471 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5475 ICALL_EXPORT MonoString *
5476 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5478 MonoDomain *domain = mono_object_domain (assembly);
5479 MonoAssembly *mass = assembly->assembly;
5480 MonoString *res;
5481 gchar *name;
5483 name = mono_stringify_assembly_name (&mass->aname);
5484 res = mono_string_new (domain, name);
5485 g_free (name);
5487 return res;
5490 ICALL_EXPORT MonoAssemblyName *
5491 ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
5493 return &mass->aname;
5496 ICALL_EXPORT void
5497 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5499 MonoError error;
5500 char *filename;
5501 MonoImageOpenStatus status = MONO_IMAGE_OK;
5502 gboolean res;
5503 MonoImage *image;
5504 MonoAssemblyName name;
5505 char *dirname;
5507 filename = mono_string_to_utf8_checked (fname, &error);
5508 if (mono_error_set_pending_exception (&error))
5509 return;
5511 dirname = g_path_get_dirname (filename);
5512 replace_shadow_path (mono_domain_get (), dirname, &filename);
5513 g_free (dirname);
5515 image = mono_image_open (filename, &status);
5517 if (!image){
5518 MonoException *exc;
5520 g_free (filename);
5521 if (status == MONO_IMAGE_IMAGE_INVALID)
5522 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5523 else
5524 exc = mono_get_exception_file_not_found2 (NULL, fname);
5525 mono_set_pending_exception (exc);
5526 return;
5529 res = mono_assembly_fill_assembly_name (image, &name);
5530 if (!res) {
5531 mono_image_close (image);
5532 g_free (filename);
5533 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5534 return;
5537 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5538 mono_error_set_pending_exception (&error);
5540 mono_image_close (image);
5541 g_free (filename);
5544 ICALL_EXPORT MonoBoolean
5545 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5546 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5548 MonoBoolean result = FALSE;
5549 MonoDeclSecurityEntry entry;
5551 /* SecurityAction.RequestMinimum */
5552 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5553 *minimum = entry.blob;
5554 *minLength = entry.size;
5555 result = TRUE;
5557 /* SecurityAction.RequestOptional */
5558 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5559 *optional = entry.blob;
5560 *optLength = entry.size;
5561 result = TRUE;
5563 /* SecurityAction.RequestRefuse */
5564 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5565 *refused = entry.blob;
5566 *refLength = entry.size;
5567 result = TRUE;
5570 return result;
5573 static gboolean
5574 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5576 guint32 attrs, visibility;
5577 do {
5578 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5579 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5580 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5581 return FALSE;
5583 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5585 return TRUE;
5588 static MonoArray*
5589 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5591 MonoReflectionType *rt;
5592 MonoArray *res;
5593 MonoClass *klass;
5594 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5595 int i, count;
5597 mono_error_init (error);
5599 /* we start the count from 1 because we skip the special type <Module> */
5600 if (exportedOnly) {
5601 count = 0;
5602 for (i = 1; i < tdef->rows; ++i) {
5603 if (mono_module_type_is_visible (tdef, image, i + 1))
5604 count++;
5606 } else {
5607 count = tdef->rows - 1;
5609 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5610 return_val_if_nok (error, NULL);
5611 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5612 return_val_if_nok (error, NULL);
5613 count = 0;
5614 for (i = 1; i < tdef->rows; ++i) {
5615 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5616 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5618 if (klass) {
5619 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5620 return_val_if_nok (error, NULL);
5622 mono_array_setref (res, count, rt);
5623 } else {
5624 MonoException *ex = mono_error_convert_to_exception (error);
5625 mono_array_setref (*exceptions, count, ex);
5627 count++;
5631 return res;
5634 ICALL_EXPORT MonoArray*
5635 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5637 MonoError error;
5638 MonoArray *res = NULL;
5639 MonoArray *exceptions = NULL;
5640 MonoImage *image = NULL;
5641 MonoTableInfo *table = NULL;
5642 MonoDomain *domain;
5643 GList *list = NULL;
5644 int i, len, ex_count;
5646 domain = mono_object_domain (assembly);
5648 g_assert (!assembly_is_dynamic (assembly->assembly));
5649 image = assembly->assembly->image;
5650 table = &image->tables [MONO_TABLE_FILE];
5651 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5652 if (mono_error_set_pending_exception (&error))
5653 return NULL;
5655 /* Append data from all modules in the assembly */
5656 for (i = 0; i < table->rows; ++i) {
5657 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5658 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5659 if (loaded_image) {
5660 MonoArray *ex2;
5661 MonoArray *res2;
5663 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5664 if (mono_error_set_pending_exception (&error))
5665 return NULL;
5668 /* Append the new types to the end of the array */
5669 if (mono_array_length (res2) > 0) {
5670 guint32 len1, len2;
5671 MonoArray *res3, *ex3;
5673 len1 = mono_array_length (res);
5674 len2 = mono_array_length (res2);
5676 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5677 if (mono_error_set_pending_exception (&error))
5678 return NULL;
5679 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5680 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5681 res = res3;
5683 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5684 if (mono_error_set_pending_exception (&error))
5685 return NULL;
5686 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5687 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5688 exceptions = ex3;
5694 /* the ReflectionTypeLoadException must have all the types (Types property),
5695 * NULL replacing types which throws an exception. The LoaderException must
5696 * contain all exceptions for NULL items.
5699 len = mono_array_length (res);
5701 ex_count = 0;
5702 for (i = 0; i < len; i++) {
5703 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5704 MonoClass *klass;
5706 if (t) {
5707 klass = mono_type_get_class (t->type);
5708 if ((klass != NULL) && mono_class_has_failure (klass)) {
5709 /* keep the class in the list */
5710 list = g_list_append (list, klass);
5711 /* and replace Type with NULL */
5712 mono_array_setref (res, i, NULL);
5714 } else {
5715 ex_count ++;
5719 if (list || ex_count) {
5720 GList *tmp = NULL;
5721 MonoException *exc = NULL;
5722 MonoArray *exl = NULL;
5723 int j, length = g_list_length (list) + ex_count;
5725 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5726 if (mono_error_set_pending_exception (&error)) {
5727 g_list_free (list);
5728 return NULL;
5730 /* Types for which mono_class_get_checked () succeeded */
5731 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5732 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5733 mono_array_setref (exl, i, exc);
5735 /* Types for which it don't */
5736 for (j = 0; j < mono_array_length (exceptions); ++j) {
5737 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5738 if (exc) {
5739 g_assert (i < length);
5740 mono_array_setref (exl, i, exc);
5741 i ++;
5744 g_list_free (list);
5745 list = NULL;
5747 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5748 if (!is_ok (&error)) {
5749 mono_error_set_pending_exception (&error);
5750 return NULL;
5752 mono_set_pending_exception (exc);
5753 return NULL;
5756 return res;
5759 ICALL_EXPORT void
5760 ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname)
5762 mono_assembly_name_free (aname);
5765 ICALL_EXPORT gboolean
5766 ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined)
5768 *is_version_definited = *is_token_defined = FALSE;
5770 return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined);
5773 ICALL_EXPORT MonoReflectionType*
5774 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5776 MonoError error;
5777 MonoReflectionType *ret;
5778 MonoDomain *domain = mono_object_domain (module);
5779 MonoClass *klass;
5781 g_assert (module->image);
5783 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5784 /* These images do not have a global type */
5785 return NULL;
5787 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5788 if (!mono_error_ok (&error)) {
5789 mono_error_set_pending_exception (&error);
5790 return NULL;
5793 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5794 if (!mono_error_ok (&error)) {
5795 mono_error_set_pending_exception (&error);
5796 return NULL;
5799 return ret;
5802 ICALL_EXPORT void
5803 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5805 /*if (module->image)
5806 mono_image_close (module->image);*/
5809 ICALL_EXPORT MonoString*
5810 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5812 MonoDomain *domain = mono_object_domain (module);
5814 g_assert (module->image);
5815 return mono_string_new (domain, module->image->guid);
5818 ICALL_EXPORT gpointer
5819 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5821 #ifdef HOST_WIN32
5822 if (module->image && module->image->is_module_handle)
5823 return module->image->raw_data;
5824 #endif
5826 return (gpointer) (-1);
5829 ICALL_EXPORT void
5830 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5832 if (image_is_dynamic (image)) {
5833 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5834 *pe_kind = dyn->pe_kind;
5835 *machine = dyn->machine;
5837 else {
5838 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5839 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5843 ICALL_EXPORT gint32
5844 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5846 return (image->md_version_major << 16) | (image->md_version_minor);
5849 ICALL_EXPORT MonoArray*
5850 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5852 MonoError error;
5853 MonoArray *exceptions;
5854 int i;
5856 if (!module->image) {
5857 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
5858 mono_error_set_pending_exception (&error);
5859 return arr;
5860 } else {
5861 MonoArray *res;
5863 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5864 if (mono_error_set_pending_exception (&error))
5865 return NULL;
5867 for (i = 0; i < mono_array_length (exceptions); ++i) {
5868 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5869 if (ex) {
5870 mono_set_pending_exception (ex);
5871 return NULL;
5874 return res;
5878 static gboolean
5879 mono_memberref_is_method (MonoImage *image, guint32 token)
5881 if (!image_is_dynamic (image)) {
5882 guint32 cols [MONO_MEMBERREF_SIZE];
5883 const char *sig;
5884 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5885 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5886 mono_metadata_decode_blob_size (sig, &sig);
5887 return (*sig != 0x6);
5888 } else {
5889 MonoError error;
5890 MonoClass *handle_class;
5892 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5893 mono_error_cleanup (&error); /* just probing, ignore error */
5894 return FALSE;
5897 return mono_defaults.methodhandle_class == handle_class;
5901 static void
5902 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5904 if (type_args)
5905 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5906 mono_array_addr (type_args, MonoType*, 0));
5907 else
5908 context->class_inst = NULL;
5909 if (method_args)
5910 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5911 mono_array_addr (method_args, MonoType*, 0));
5912 else
5913 context->method_inst = NULL;
5916 ICALL_EXPORT MonoType*
5917 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5919 MonoClass *klass;
5920 int table = mono_metadata_token_table (token);
5921 int index = mono_metadata_token_index (token);
5922 MonoGenericContext context;
5923 MonoError error;
5925 *resolve_error = ResolveTokenError_Other;
5927 /* Validate token */
5928 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5929 (table != MONO_TABLE_TYPESPEC)) {
5930 *resolve_error = ResolveTokenError_BadTable;
5931 return NULL;
5934 if (image_is_dynamic (image)) {
5935 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5936 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5937 mono_error_cleanup (&error);
5938 return klass ? &klass->byval_arg : NULL;
5941 init_generic_context_from_args (&context, type_args, method_args);
5942 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5943 mono_error_cleanup (&error);
5944 return klass ? &klass->byval_arg : NULL;
5947 if ((index <= 0) || (index > image->tables [table].rows)) {
5948 *resolve_error = ResolveTokenError_OutOfRange;
5949 return NULL;
5952 init_generic_context_from_args (&context, type_args, method_args);
5953 klass = mono_class_get_checked (image, token, &error);
5954 if (klass)
5955 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5956 if (!mono_error_ok (&error)) {
5957 mono_error_set_pending_exception (&error);
5958 return NULL;
5961 if (klass)
5962 return &klass->byval_arg;
5963 else
5964 return NULL;
5967 ICALL_EXPORT MonoMethod*
5968 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5970 MonoError error;
5971 int table = mono_metadata_token_table (token);
5972 int index = mono_metadata_token_index (token);
5973 MonoGenericContext context;
5974 MonoMethod *method;
5976 *resolve_error = ResolveTokenError_Other;
5978 /* Validate token */
5979 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5980 (table != MONO_TABLE_MEMBERREF)) {
5981 *resolve_error = ResolveTokenError_BadTable;
5982 return NULL;
5985 if (image_is_dynamic (image)) {
5986 if (table == MONO_TABLE_METHOD) {
5987 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5988 mono_error_cleanup (&error);
5989 return method;
5992 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5993 *resolve_error = ResolveTokenError_BadTable;
5994 return NULL;
5997 init_generic_context_from_args (&context, type_args, method_args);
5998 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5999 mono_error_cleanup (&error);
6000 return method;
6003 if ((index <= 0) || (index > image->tables [table].rows)) {
6004 *resolve_error = ResolveTokenError_OutOfRange;
6005 return NULL;
6007 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6008 *resolve_error = ResolveTokenError_BadTable;
6009 return NULL;
6012 init_generic_context_from_args (&context, type_args, method_args);
6013 method = mono_get_method_checked (image, token, NULL, &context, &error);
6014 mono_error_set_pending_exception (&error);
6016 return method;
6019 ICALL_EXPORT MonoString*
6020 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6022 MonoError error;
6023 int index = mono_metadata_token_index (token);
6025 *resolve_error = ResolveTokenError_Other;
6027 /* Validate token */
6028 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6029 *resolve_error = ResolveTokenError_BadTable;
6030 return NULL;
6033 if (image_is_dynamic (image)) {
6034 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6035 mono_error_cleanup (&error);
6036 return result;
6039 if ((index <= 0) || (index >= image->heap_us.size)) {
6040 *resolve_error = ResolveTokenError_OutOfRange;
6041 return NULL;
6044 /* FIXME: What to do if the index points into the middle of a string ? */
6046 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
6047 mono_error_set_pending_exception (&error);
6048 return result;
6051 ICALL_EXPORT MonoClassField*
6052 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6054 MonoError error;
6055 MonoClass *klass;
6056 int table = mono_metadata_token_table (token);
6057 int index = mono_metadata_token_index (token);
6058 MonoGenericContext context;
6059 MonoClassField *field;
6061 *resolve_error = ResolveTokenError_Other;
6063 /* Validate token */
6064 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6065 *resolve_error = ResolveTokenError_BadTable;
6066 return NULL;
6069 if (image_is_dynamic (image)) {
6070 if (table == MONO_TABLE_FIELD) {
6071 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6072 mono_error_cleanup (&error);
6073 return field;
6076 if (mono_memberref_is_method (image, token)) {
6077 *resolve_error = ResolveTokenError_BadTable;
6078 return NULL;
6081 init_generic_context_from_args (&context, type_args, method_args);
6082 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6083 mono_error_cleanup (&error);
6084 return field;
6087 if ((index <= 0) || (index > image->tables [table].rows)) {
6088 *resolve_error = ResolveTokenError_OutOfRange;
6089 return NULL;
6091 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6092 *resolve_error = ResolveTokenError_BadTable;
6093 return NULL;
6096 init_generic_context_from_args (&context, type_args, method_args);
6097 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6098 mono_error_set_pending_exception (&error);
6100 return field;
6104 ICALL_EXPORT MonoObject*
6105 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6107 MonoError merror;
6108 MonoObject *ret;
6109 int table = mono_metadata_token_table (token);
6111 *error = ResolveTokenError_Other;
6113 switch (table) {
6114 case MONO_TABLE_TYPEDEF:
6115 case MONO_TABLE_TYPEREF:
6116 case MONO_TABLE_TYPESPEC: {
6117 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6118 if (t) {
6119 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6120 mono_error_set_pending_exception (&merror);
6122 return ret;
6124 else
6125 return NULL;
6127 case MONO_TABLE_METHOD:
6128 case MONO_TABLE_METHODSPEC: {
6129 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6130 if (m) {
6131 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6132 mono_error_set_pending_exception (&merror);
6134 return ret;
6135 } else
6136 return NULL;
6138 case MONO_TABLE_FIELD: {
6139 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6140 if (f) {
6141 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6142 mono_error_set_pending_exception (&merror);
6143 return ret;
6145 else
6146 return NULL;
6148 case MONO_TABLE_MEMBERREF:
6149 if (mono_memberref_is_method (image, token)) {
6150 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6151 if (m) {
6152 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6153 mono_error_set_pending_exception (&merror);
6155 return ret;
6156 } else
6157 return NULL;
6159 else {
6160 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6161 if (f) {
6162 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6163 mono_error_set_pending_exception (&merror);
6164 return ret;
6166 else
6167 return NULL;
6169 break;
6171 default:
6172 *error = ResolveTokenError_BadTable;
6175 return NULL;
6178 ICALL_EXPORT MonoArray*
6179 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6181 MonoError error;
6182 int table = mono_metadata_token_table (token);
6183 int idx = mono_metadata_token_index (token);
6184 MonoTableInfo *tables = image->tables;
6185 guint32 sig, len;
6186 const char *ptr;
6187 MonoArray *res;
6189 *resolve_error = ResolveTokenError_OutOfRange;
6191 /* FIXME: Support other tables ? */
6192 if (table != MONO_TABLE_STANDALONESIG)
6193 return NULL;
6195 if (image_is_dynamic (image))
6196 return NULL;
6198 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6199 return NULL;
6201 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6203 ptr = mono_metadata_blob_heap (image, sig);
6204 len = mono_metadata_decode_blob_size (ptr, &ptr);
6206 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6207 if (mono_error_set_pending_exception (&error))
6208 return NULL;
6209 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6210 return res;
6213 ICALL_EXPORT MonoReflectionType*
6214 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6216 MonoError error;
6217 MonoReflectionType *ret;
6218 MonoClass *klass;
6219 int isbyref = 0, rank;
6220 char *p;
6221 char *str = mono_string_to_utf8_checked (smodifiers, &error);
6222 if (mono_error_set_pending_exception (&error))
6223 return NULL;
6225 klass = mono_class_from_mono_type (tb->type.type);
6226 p = str;
6227 /* logic taken from mono_reflection_parse_type(): keep in sync */
6228 while (*p) {
6229 switch (*p) {
6230 case '&':
6231 if (isbyref) { /* only one level allowed by the spec */
6232 g_free (str);
6233 return NULL;
6235 isbyref = 1;
6236 p++;
6238 g_free (str);
6240 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6241 mono_error_set_pending_exception (&error);
6243 return ret;
6244 case '*':
6245 klass = mono_ptr_class_get (&klass->byval_arg);
6246 mono_class_init (klass);
6247 p++;
6248 break;
6249 case '[':
6250 rank = 1;
6251 p++;
6252 while (*p) {
6253 if (*p == ']')
6254 break;
6255 if (*p == ',')
6256 rank++;
6257 else if (*p != '*') { /* '*' means unknown lower bound */
6258 g_free (str);
6259 return NULL;
6261 ++p;
6263 if (*p != ']') {
6264 g_free (str);
6265 return NULL;
6267 p++;
6268 klass = mono_array_class_get (klass, rank);
6269 mono_class_init (klass);
6270 break;
6271 default:
6272 break;
6276 g_free (str);
6278 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6279 mono_error_set_pending_exception (&error);
6281 return ret;
6284 ICALL_EXPORT MonoBoolean
6285 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6287 MonoType *type;
6288 MonoBoolean res;
6290 type = t->type;
6291 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6293 return res;
6296 static void
6297 check_for_invalid_type (MonoClass *klass, MonoError *error)
6299 char *name;
6300 MonoString *str;
6302 mono_error_init (error);
6304 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6305 return;
6307 name = mono_type_get_full_name (klass);
6308 str = mono_string_new (mono_domain_get (), name);
6309 g_free (name);
6310 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6313 ICALL_EXPORT MonoReflectionType *
6314 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6316 MonoError error;
6317 MonoReflectionType *ret;
6318 MonoClass *klass, *aklass;
6320 klass = mono_class_from_mono_type (type->type);
6321 check_for_invalid_type (klass, &error);
6322 mono_error_set_pending_exception (&error);
6324 if (rank == 0) //single dimentional array
6325 aklass = mono_array_class_get (klass, 1);
6326 else
6327 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6329 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6330 mono_error_set_pending_exception (&error);
6332 return ret;
6335 ICALL_EXPORT MonoReflectionType *
6336 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6338 MonoError error;
6339 MonoReflectionType *ret;
6340 MonoClass *klass;
6342 klass = mono_class_from_mono_type (type->type);
6343 mono_class_init_checked (klass, &error);
6344 if (mono_error_set_pending_exception (&error))
6345 return NULL;
6347 check_for_invalid_type (klass, &error);
6348 if (mono_error_set_pending_exception (&error))
6349 return NULL;
6351 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6352 mono_error_set_pending_exception (&error);
6354 return ret;
6357 ICALL_EXPORT MonoReflectionType *
6358 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6360 MonoError error;
6361 MonoReflectionType *ret;
6362 MonoClass *klass, *pklass;
6364 klass = mono_class_from_mono_type (type->type);
6365 mono_class_init_checked (klass, &error);
6366 if (mono_error_set_pending_exception (&error))
6367 return NULL;
6368 check_for_invalid_type (klass, &error);
6369 if (mono_error_set_pending_exception (&error))
6370 return NULL;
6372 pklass = mono_ptr_class_get (type->type);
6374 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6375 mono_error_set_pending_exception (&error);
6377 return ret;
6380 ICALL_EXPORT MonoObject *
6381 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6382 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6384 MonoError error;
6385 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6386 MonoObject *delegate;
6387 gpointer func;
6388 MonoMethod *method = info->method;
6390 mono_class_init_checked (delegate_class, &error);
6391 if (mono_error_set_pending_exception (&error))
6392 return NULL;
6394 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6395 /* FIXME improve this exception message */
6396 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6397 __func__,
6398 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6399 mono_error_set_pending_exception (&error);
6400 return NULL;
6403 if (mono_security_core_clr_enabled ()) {
6404 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6405 if (throwOnBindFailure)
6406 mono_error_set_pending_exception (&error);
6407 else
6408 mono_error_cleanup (&error);
6409 return NULL;
6413 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6414 if (mono_error_set_pending_exception (&error))
6415 return NULL;
6417 if (method_is_dynamic (method)) {
6418 /* Creating a trampoline would leak memory */
6419 func = mono_compile_method_checked (method, &error);
6420 if (mono_error_set_pending_exception (&error))
6421 return NULL;
6422 } else {
6423 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6424 method = mono_object_get_virtual_method (target, method);
6425 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6426 if (mono_error_set_pending_exception (&error))
6427 return NULL;
6428 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6431 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6432 if (mono_error_set_pending_exception (&error))
6433 return NULL;
6434 return delegate;
6437 ICALL_EXPORT MonoMulticastDelegate *
6438 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6440 MonoError error;
6441 MonoMulticastDelegate *ret;
6443 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6445 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6446 if (mono_error_set_pending_exception (&error))
6447 return NULL;
6449 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6451 return ret;
6454 ICALL_EXPORT MonoReflectionMethod*
6455 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6457 MonoReflectionMethod *ret = NULL;
6458 MonoError error;
6459 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6460 mono_error_set_pending_exception (&error);
6461 return ret;
6464 /* System.Buffer */
6466 static inline gint32
6467 mono_array_get_byte_length (MonoArray *array)
6469 MonoClass *klass;
6470 int length;
6471 int i;
6473 klass = array->obj.vtable->klass;
6475 if (array->bounds == NULL)
6476 length = array->max_length;
6477 else {
6478 length = 1;
6479 for (i = 0; i < klass->rank; ++ i)
6480 length *= array->bounds [i].length;
6483 switch (klass->element_class->byval_arg.type) {
6484 case MONO_TYPE_I1:
6485 case MONO_TYPE_U1:
6486 case MONO_TYPE_BOOLEAN:
6487 return length;
6488 case MONO_TYPE_I2:
6489 case MONO_TYPE_U2:
6490 case MONO_TYPE_CHAR:
6491 return length << 1;
6492 case MONO_TYPE_I4:
6493 case MONO_TYPE_U4:
6494 case MONO_TYPE_R4:
6495 return length << 2;
6496 case MONO_TYPE_I:
6497 case MONO_TYPE_U:
6498 return length * sizeof (gpointer);
6499 case MONO_TYPE_I8:
6500 case MONO_TYPE_U8:
6501 case MONO_TYPE_R8:
6502 return length << 3;
6503 default:
6504 return -1;
6508 ICALL_EXPORT gint32
6509 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6511 return mono_array_get_byte_length (array);
6514 ICALL_EXPORT gint8
6515 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6517 return mono_array_get (array, gint8, idx);
6520 ICALL_EXPORT void
6521 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6523 mono_array_set (array, gint8, idx, value);
6526 ICALL_EXPORT MonoBoolean
6527 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6529 guint8 *src_buf, *dest_buf;
6531 if (count < 0) {
6532 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6533 return FALSE;
6536 g_assert (count >= 0);
6538 /* This is called directly from the class libraries without going through the managed wrapper */
6539 MONO_CHECK_ARG_NULL (src, FALSE);
6540 MONO_CHECK_ARG_NULL (dest, FALSE);
6542 /* watch out for integer overflow */
6543 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6544 return FALSE;
6546 src_buf = (guint8 *)src->vector + src_offset;
6547 dest_buf = (guint8 *)dest->vector + dest_offset;
6549 if (src != dest)
6550 memcpy (dest_buf, src_buf, count);
6551 else
6552 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6554 return TRUE;
6557 #ifndef DISABLE_REMOTING
6558 ICALL_EXPORT MonoObject *
6559 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6561 MonoError error;
6562 MonoDomain *domain = mono_object_domain (this_obj);
6563 MonoObject *res;
6564 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6565 MonoTransparentProxy *tp;
6566 MonoType *type;
6567 MonoClass *klass;
6569 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6570 if (mono_error_set_pending_exception (&error))
6571 return NULL;
6573 tp = (MonoTransparentProxy*) res;
6575 MONO_OBJECT_SETREF (tp, rp, rp);
6576 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6577 klass = mono_class_from_mono_type (type);
6579 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6580 mono_class_setup_vtable (klass);
6581 if (mono_class_has_failure (klass)) {
6582 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6583 return NULL;
6586 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6587 if (mono_error_set_pending_exception (&error))
6588 return NULL;
6589 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6590 if (mono_error_set_pending_exception (&error))
6591 return NULL;
6593 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6594 if (mono_error_set_pending_exception (&error))
6595 return NULL;
6596 return res;
6599 ICALL_EXPORT MonoReflectionType *
6600 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6602 MonoError error;
6603 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6604 mono_error_set_pending_exception (&error);
6606 return ret;
6608 #endif
6610 /* System.Environment */
6612 MonoString*
6613 ves_icall_System_Environment_get_UserName (void)
6615 /* using glib is more portable */
6616 return mono_string_new (mono_domain_get (), g_get_user_name ());
6620 ICALL_EXPORT MonoString *
6621 ves_icall_System_Environment_get_MachineName (void)
6623 #if defined (HOST_WIN32)
6624 gunichar2 *buf;
6625 guint32 len;
6626 MonoString *result;
6628 len = MAX_COMPUTERNAME_LENGTH + 1;
6629 buf = g_new (gunichar2, len);
6631 result = NULL;
6632 if (GetComputerName (buf, (PDWORD) &len)) {
6633 MonoError error;
6634 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6635 mono_error_set_pending_exception (&error);
6638 g_free (buf);
6639 return result;
6640 #elif !defined(DISABLE_SOCKETS)
6641 MonoString *result;
6642 char *buf;
6643 int n;
6644 #if defined _SC_HOST_NAME_MAX
6645 n = sysconf (_SC_HOST_NAME_MAX);
6646 if (n == -1)
6647 #endif
6648 n = 512;
6649 buf = g_malloc (n+1);
6651 if (gethostname (buf, n) == 0){
6652 buf [n] = 0;
6653 result = mono_string_new (mono_domain_get (), buf);
6654 } else
6655 result = NULL;
6656 g_free (buf);
6658 return result;
6659 #else
6660 return mono_string_new (mono_domain_get (), "mono");
6661 #endif
6664 ICALL_EXPORT int
6665 ves_icall_System_Environment_get_Platform (void)
6667 #if defined (TARGET_WIN32)
6668 /* Win32NT */
6669 return 2;
6670 #elif defined(__MACH__)
6671 /* OSX */
6673 // Notice that the value is hidden from user code, and only exposed
6674 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6675 // define and making assumptions based on Unix/128/4 values before there
6676 // was a MacOS define. Lots of code would assume that not-Unix meant
6677 // Windows, but in this case, it would be OSX.
6679 return 6;
6680 #else
6681 /* Unix */
6682 return 4;
6683 #endif
6686 ICALL_EXPORT MonoString *
6687 ves_icall_System_Environment_get_NewLine (void)
6689 #if defined (HOST_WIN32)
6690 return mono_string_new (mono_domain_get (), "\r\n");
6691 #else
6692 return mono_string_new (mono_domain_get (), "\n");
6693 #endif
6696 ICALL_EXPORT MonoBoolean
6697 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6699 #if SIZEOF_VOID_P == 8
6700 return TRUE;
6701 #else
6702 #ifdef HOST_WIN32
6703 gboolean isWow64Process = FALSE;
6704 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6705 return (MonoBoolean)isWow64Process;
6707 #elif defined(HAVE_SYS_UTSNAME_H)
6708 struct utsname name;
6710 if (uname (&name) >= 0) {
6711 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6713 #endif
6714 return FALSE;
6715 #endif
6718 ICALL_EXPORT MonoString *
6719 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6721 MonoError error;
6722 const gchar *value;
6723 gchar *utf8_name;
6725 if (name == NULL)
6726 return NULL;
6728 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6729 if (mono_error_set_pending_exception (&error))
6730 return NULL;
6731 value = g_getenv (utf8_name);
6733 g_free (utf8_name);
6735 if (value == 0)
6736 return NULL;
6738 return mono_string_new (mono_domain_get (), value);
6742 * There is no standard way to get at environ.
6744 #ifndef _MSC_VER
6745 #ifndef __MINGW32_VERSION
6746 #if defined(__APPLE__)
6747 #if defined (TARGET_OSX)
6748 /* Apple defines this in crt_externs.h but doesn't provide that header for
6749 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6750 * in fact exist on all implementations (so far)
6752 gchar ***_NSGetEnviron(void);
6753 #define environ (*_NSGetEnviron())
6754 #else
6755 static char *mono_environ[1] = { NULL };
6756 #define environ mono_environ
6757 #endif /* defined (TARGET_OSX) */
6758 #else
6759 extern
6760 char **environ;
6761 #endif
6762 #endif
6763 #endif
6765 ICALL_EXPORT MonoArray *
6766 ves_icall_System_Environment_GetCoomandLineArgs (void)
6768 MonoError error;
6769 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6770 mono_error_set_pending_exception (&error);
6771 return result;
6774 ICALL_EXPORT MonoArray *
6775 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6777 #ifdef HOST_WIN32
6778 MonoError error;
6779 MonoArray *names;
6780 MonoDomain *domain;
6781 MonoString *str;
6782 WCHAR* env_strings;
6783 WCHAR* env_string;
6784 WCHAR* equal_str;
6785 int n = 0;
6787 env_strings = GetEnvironmentStrings();
6789 if (env_strings) {
6790 env_string = env_strings;
6791 while (*env_string != '\0') {
6792 /* weird case that MS seems to skip */
6793 if (*env_string != '=')
6794 n++;
6795 while (*env_string != '\0')
6796 env_string++;
6797 env_string++;
6801 domain = mono_domain_get ();
6802 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6803 if (mono_error_set_pending_exception (&error))
6804 return NULL;
6806 if (env_strings) {
6807 n = 0;
6808 env_string = env_strings;
6809 while (*env_string != '\0') {
6810 /* weird case that MS seems to skip */
6811 if (*env_string != '=') {
6812 equal_str = wcschr(env_string, '=');
6813 g_assert(equal_str);
6814 MonoError error;
6815 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6816 if (mono_error_set_pending_exception (&error))
6817 return NULL;
6819 mono_array_setref (names, n, str);
6820 n++;
6822 while (*env_string != '\0')
6823 env_string++;
6824 env_string++;
6827 FreeEnvironmentStrings (env_strings);
6830 return names;
6832 #else
6833 MonoError error;
6834 MonoArray *names;
6835 MonoDomain *domain;
6836 MonoString *str;
6837 gchar **e, **parts;
6838 int n;
6840 n = 0;
6841 for (e = environ; *e != 0; ++ e)
6842 ++ n;
6844 domain = mono_domain_get ();
6845 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6846 if (mono_error_set_pending_exception (&error))
6847 return NULL;
6849 n = 0;
6850 for (e = environ; *e != 0; ++ e) {
6851 parts = g_strsplit (*e, "=", 2);
6852 if (*parts != 0) {
6853 str = mono_string_new (domain, *parts);
6854 mono_array_setref (names, n, str);
6857 g_strfreev (parts);
6859 ++ n;
6862 return names;
6863 #endif
6866 ICALL_EXPORT void
6867 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6869 #ifdef HOST_WIN32
6870 gunichar2 *utf16_name, *utf16_value;
6871 #else
6872 gchar *utf8_name, *utf8_value;
6873 MonoError error;
6874 #endif
6876 #ifdef HOST_WIN32
6877 utf16_name = mono_string_to_utf16 (name);
6878 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6879 SetEnvironmentVariable (utf16_name, NULL);
6880 g_free (utf16_name);
6881 return;
6884 utf16_value = mono_string_to_utf16 (value);
6886 SetEnvironmentVariable (utf16_name, utf16_value);
6888 g_free (utf16_name);
6889 g_free (utf16_value);
6890 #else
6891 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6892 if (mono_error_set_pending_exception (&error))
6893 return;
6895 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6896 g_unsetenv (utf8_name);
6897 g_free (utf8_name);
6898 return;
6901 utf8_value = mono_string_to_utf8_checked (value, &error);
6902 if (!mono_error_ok (&error)) {
6903 g_free (utf8_name);
6904 mono_error_set_pending_exception (&error);
6905 return;
6907 g_setenv (utf8_name, utf8_value, TRUE);
6909 g_free (utf8_name);
6910 g_free (utf8_value);
6911 #endif
6914 ICALL_EXPORT void
6915 ves_icall_System_Environment_Exit (int result)
6917 mono_environment_exitcode_set (result);
6919 /* FIXME: There are some cleanup hangs that should be worked out, but
6920 * if the program is going to exit, everything will be cleaned up when
6921 * NaCl exits anyway.
6923 #ifndef __native_client__
6924 if (!mono_runtime_try_shutdown ())
6925 mono_thread_exit ();
6927 /* Suspend all managed threads since the runtime is going away */
6928 mono_thread_suspend_all_other_threads ();
6930 mono_runtime_quit ();
6931 #endif
6933 /* we may need to do some cleanup here... */
6934 exit (result);
6937 ICALL_EXPORT MonoString*
6938 ves_icall_System_Environment_GetGacPath (void)
6940 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6943 ICALL_EXPORT MonoString*
6944 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6946 #if defined (HOST_WIN32)
6947 #ifndef CSIDL_FLAG_CREATE
6948 #define CSIDL_FLAG_CREATE 0x8000
6949 #endif
6951 WCHAR path [MAX_PATH];
6952 /* Create directory if no existing */
6953 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6954 int len = 0;
6955 while (path [len])
6956 ++ len;
6957 MonoError error;
6958 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6959 mono_error_set_pending_exception (&error);
6960 return res;
6962 #else
6963 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6964 #endif
6965 return mono_string_new (mono_domain_get (), "");
6968 ICALL_EXPORT MonoArray *
6969 ves_icall_System_Environment_GetLogicalDrives (void)
6971 MonoError error;
6972 gunichar2 buf [256], *ptr, *dname;
6973 gunichar2 *u16;
6974 guint initial_size = 127, size = 128;
6975 gint ndrives;
6976 MonoArray *result;
6977 MonoString *drivestr;
6978 MonoDomain *domain = mono_domain_get ();
6979 gint len;
6981 buf [0] = '\0';
6982 ptr = buf;
6984 while (size > initial_size) {
6985 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6986 if (size > initial_size) {
6987 if (ptr != buf)
6988 g_free (ptr);
6989 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6990 initial_size = size;
6991 size++;
6995 /* Count strings */
6996 dname = ptr;
6997 ndrives = 0;
6998 do {
6999 while (*dname++);
7000 ndrives++;
7001 } while (*dname);
7003 dname = ptr;
7004 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7005 if (mono_error_set_pending_exception (&error))
7006 goto leave;
7008 ndrives = 0;
7009 do {
7010 len = 0;
7011 u16 = dname;
7012 while (*u16) { u16++; len ++; }
7013 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7014 if (mono_error_set_pending_exception (&error))
7015 goto leave;
7017 mono_array_setref (result, ndrives++, drivestr);
7018 while (*dname++);
7019 } while (*dname);
7021 leave:
7022 if (ptr != buf)
7023 g_free (ptr);
7025 return result;
7028 ICALL_EXPORT MonoString *
7029 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7031 MonoError error;
7032 gunichar2 volume_name [MAX_PATH + 1];
7034 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7035 return NULL;
7036 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
7037 mono_error_set_pending_exception (&error);
7038 return result;
7041 ICALL_EXPORT MonoString *
7042 ves_icall_System_Environment_InternalGetHome (void)
7044 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7047 static const char *encodings [] = {
7048 (char *) 1,
7049 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7050 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7051 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7052 (char *) 2,
7053 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7054 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7055 "x_unicode_2_0_utf_7",
7056 (char *) 3,
7057 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7058 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7059 (char *) 4,
7060 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7061 "iso_10646_ucs2",
7062 (char *) 5,
7063 "unicodefffe", "utf_16be",
7064 (char *) 6,
7065 "iso_8859_1",
7066 (char *) 0
7070 * Returns the internal codepage, if the value of "int_code_page" is
7071 * 1 at entry, and we can not compute a suitable code page number,
7072 * returns the code page as a string
7074 ICALL_EXPORT MonoString*
7075 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
7077 const char *cset;
7078 const char *p;
7079 char *c;
7080 char *codepage = NULL;
7081 int code;
7082 int want_name = *int_code_page;
7083 int i;
7085 *int_code_page = -1;
7087 g_get_charset (&cset);
7088 c = codepage = strdup (cset);
7089 for (c = codepage; *c; c++){
7090 if (isascii (*c) && isalpha (*c))
7091 *c = tolower (*c);
7092 if (*c == '-')
7093 *c = '_';
7095 /* g_print ("charset: %s\n", cset); */
7097 /* handle some common aliases */
7098 p = encodings [0];
7099 code = 0;
7100 for (i = 0; p != 0; ){
7101 if ((gsize) p < 7){
7102 code = (gssize) p;
7103 p = encodings [++i];
7104 continue;
7106 if (strcmp (p, codepage) == 0){
7107 *int_code_page = code;
7108 break;
7110 p = encodings [++i];
7113 if (strstr (codepage, "utf_8") != NULL)
7114 *int_code_page |= 0x10000000;
7115 free (codepage);
7117 if (want_name && *int_code_page == -1)
7118 return mono_string_new (mono_domain_get (), cset);
7119 else
7120 return NULL;
7123 ICALL_EXPORT MonoBoolean
7124 ves_icall_System_Environment_get_HasShutdownStarted (void)
7126 if (mono_runtime_is_shutting_down ())
7127 return TRUE;
7129 if (mono_domain_is_unloading (mono_domain_get ()))
7130 return TRUE;
7132 return FALSE;
7135 ICALL_EXPORT void
7136 ves_icall_System_Environment_BroadcastSettingChange (void)
7138 #ifdef HOST_WIN32
7139 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7140 #endif
7143 ICALL_EXPORT
7144 gint32
7145 ves_icall_System_Environment_get_TickCount (void)
7147 /* this will overflow after ~24 days */
7148 return (gint32) (mono_msec_boottime () & 0xffffffff);
7151 ICALL_EXPORT gint32
7152 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7154 return 9;
7157 #ifndef DISABLE_REMOTING
7158 ICALL_EXPORT MonoBoolean
7159 ves_icall_IsTransparentProxy (MonoObject *proxy)
7161 if (!proxy)
7162 return 0;
7164 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7165 return 1;
7167 return 0;
7170 ICALL_EXPORT MonoReflectionMethod *
7171 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7172 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7174 MonoReflectionMethod *ret = NULL;
7175 MonoError error;
7177 MonoClass *klass;
7178 MonoMethod *method;
7179 MonoMethod **vtable;
7180 MonoMethod *res = NULL;
7182 MONO_CHECK_ARG_NULL (rtype, NULL);
7183 MONO_CHECK_ARG_NULL (rmethod, NULL);
7185 method = rmethod->method;
7186 klass = mono_class_from_mono_type (rtype->type);
7187 mono_class_init_checked (klass, &error);
7188 if (mono_error_set_pending_exception (&error))
7189 return NULL;
7191 if (MONO_CLASS_IS_INTERFACE (klass))
7192 return NULL;
7194 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7195 return NULL;
7197 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7198 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7199 return rmethod;
7200 else
7201 return NULL;
7204 mono_class_setup_vtable (klass);
7205 vtable = klass->vtable;
7207 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7208 gboolean variance_used = FALSE;
7209 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7210 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7211 if (offs >= 0)
7212 res = vtable [offs + method->slot];
7213 } else {
7214 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7215 return NULL;
7217 if (method->slot != -1)
7218 res = vtable [method->slot];
7221 if (!res)
7222 return NULL;
7224 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7225 mono_error_set_pending_exception (&error);
7226 return ret;
7229 ICALL_EXPORT void
7230 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7232 MonoError error;
7233 MonoClass *klass;
7234 MonoVTable* vtable;
7236 klass = mono_class_from_mono_type (type->type);
7237 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7238 if (!is_ok (&error)) {
7239 mono_error_set_pending_exception (&error);
7240 return;
7243 mono_vtable_set_is_remote (vtable, enable);
7246 #else /* DISABLE_REMOTING */
7248 ICALL_EXPORT void
7249 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7251 g_assert_not_reached ();
7254 #endif
7256 ICALL_EXPORT MonoObject *
7257 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7259 MonoError error;
7260 MonoClass *klass;
7261 MonoDomain *domain;
7262 MonoObject *ret;
7264 domain = mono_object_domain (type);
7265 klass = mono_class_from_mono_type (type->type);
7266 mono_class_init_checked (klass, &error);
7267 if (mono_error_set_pending_exception (&error))
7268 return NULL;
7270 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7271 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7272 return NULL;
7275 if (klass->rank >= 1) {
7276 g_assert (klass->rank == 1);
7277 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7278 mono_error_set_pending_exception (&error);
7279 return ret;
7280 } else {
7281 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7282 if (!is_ok (&error)) {
7283 mono_error_set_pending_exception (&error);
7284 return NULL;
7286 /* Bypass remoting object creation check */
7287 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7288 mono_error_set_pending_exception (&error);
7290 return ret;
7294 ICALL_EXPORT MonoString *
7295 ves_icall_System_IO_get_temp_path (void)
7297 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7300 #ifndef PLATFORM_NO_DRIVEINFO
7301 ICALL_EXPORT MonoBoolean
7302 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7303 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7304 gint32 *error)
7306 gboolean result;
7307 ULARGE_INTEGER wapi_free_bytes_avail;
7308 ULARGE_INTEGER wapi_total_number_of_bytes;
7309 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7311 *error = ERROR_SUCCESS;
7312 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7313 &wapi_total_number_of_free_bytes);
7315 if (result) {
7316 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7317 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7318 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7319 } else {
7320 *free_bytes_avail = 0;
7321 *total_number_of_bytes = 0;
7322 *total_number_of_free_bytes = 0;
7323 *error = GetLastError ();
7326 return result;
7329 ICALL_EXPORT guint32
7330 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7332 return GetDriveType (mono_string_chars (root_path_name));
7334 #endif
7336 ICALL_EXPORT gpointer
7337 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7339 MonoError error;
7340 gpointer result = mono_compile_method_checked (method, &error);
7341 mono_error_set_pending_exception (&error);
7342 return result;
7345 ICALL_EXPORT MonoString *
7346 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7348 MonoString *mcpath;
7349 gchar *path;
7351 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7353 #if defined (HOST_WIN32)
7354 /* Avoid mixing '/' and '\\' */
7356 gint i;
7357 for (i = strlen (path) - 1; i >= 0; i--)
7358 if (path [i] == '/')
7359 path [i] = '\\';
7361 #endif
7362 mcpath = mono_string_new (mono_domain_get (), path);
7363 g_free (path);
7365 return mcpath;
7368 /* this is an icall */
7369 static MonoString *
7370 get_bundled_app_config (void)
7372 MonoError error;
7373 const gchar *app_config;
7374 MonoDomain *domain;
7375 MonoString *file;
7376 gchar *config_file_name, *config_file_path;
7377 gsize len, config_file_path_length, config_ext_length;
7378 gchar *module;
7380 domain = mono_domain_get ();
7381 file = domain->setup->configuration_file;
7382 if (!file || file->length == 0)
7383 return NULL;
7385 // Retrieve config file and remove the extension
7386 config_file_name = mono_string_to_utf8_checked (file, &error);
7387 if (mono_error_set_pending_exception (&error))
7388 return NULL;
7389 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7390 if (!config_file_path)
7391 config_file_path = config_file_name;
7393 config_file_path_length = strlen (config_file_path);
7394 config_ext_length = strlen (".config");
7395 if (config_file_path_length <= config_ext_length)
7396 return NULL;
7398 len = config_file_path_length - config_ext_length;
7399 module = (gchar *)g_malloc0 (len + 1);
7400 memcpy (module, config_file_path, len);
7401 // Get the config file from the module name
7402 app_config = mono_config_string_for_assembly_file (module);
7403 // Clean-up
7404 g_free (module);
7405 if (config_file_name != config_file_path)
7406 g_free (config_file_name);
7407 g_free (config_file_path);
7409 if (!app_config)
7410 return NULL;
7412 return mono_string_new (mono_domain_get (), app_config);
7415 static MonoString *
7416 get_bundled_machine_config (void)
7418 const gchar *machine_config;
7420 machine_config = mono_get_machine_config ();
7422 if (!machine_config)
7423 return NULL;
7425 return mono_string_new (mono_domain_get (), machine_config);
7428 ICALL_EXPORT MonoString *
7429 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7431 MonoString *ipath;
7432 gchar *path;
7434 path = g_path_get_dirname (mono_get_config_dir ());
7436 #if defined (HOST_WIN32)
7437 /* Avoid mixing '/' and '\\' */
7439 gint i;
7440 for (i = strlen (path) - 1; i >= 0; i--)
7441 if (path [i] == '/')
7442 path [i] = '\\';
7444 #endif
7445 ipath = mono_string_new (mono_domain_get (), path);
7446 g_free (path);
7448 return ipath;
7451 ICALL_EXPORT gboolean
7452 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7454 MonoPEResourceDataEntry *entry;
7455 MonoImage *image;
7457 if (!assembly || !result || !size)
7458 return FALSE;
7460 *result = NULL;
7461 *size = 0;
7462 image = assembly->assembly->image;
7463 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7464 if (!entry)
7465 return FALSE;
7467 *result = mono_image_rva_map (image, entry->rde_data_offset);
7468 if (!(*result)) {
7469 g_free (entry);
7470 return FALSE;
7472 *size = entry->rde_size;
7473 g_free (entry);
7474 return TRUE;
7477 ICALL_EXPORT MonoBoolean
7478 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7480 return mono_is_debugger_attached ();
7483 ICALL_EXPORT MonoBoolean
7484 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7486 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7487 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7488 else
7489 return FALSE;
7492 ICALL_EXPORT void
7493 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7495 if (mono_get_runtime_callbacks ()->debug_log)
7496 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7499 ICALL_EXPORT void
7500 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7502 #if defined (HOST_WIN32)
7503 OutputDebugString (mono_string_chars (message));
7504 #else
7505 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7506 #endif
7509 /* Only used for value types */
7510 ICALL_EXPORT MonoObject *
7511 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7513 MonoError error;
7514 MonoObject *result;
7515 MonoClass *klass;
7516 MonoDomain *domain;
7518 domain = mono_object_domain (type);
7519 klass = mono_class_from_mono_type (type->type);
7520 mono_class_init_checked (klass, &error);
7521 if (mono_error_set_pending_exception (&error))
7522 return NULL;
7524 if (mono_class_is_nullable (klass))
7525 /* No arguments -> null */
7526 return NULL;
7528 result = mono_object_new_checked (domain, klass, &error);
7529 mono_error_set_pending_exception (&error);
7530 return result;
7533 ICALL_EXPORT MonoReflectionMethod *
7534 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7536 MonoReflectionMethod *ret = NULL;
7537 MonoError error;
7539 MonoClass *klass, *parent;
7540 MonoGenericContext *generic_inst = NULL;
7541 MonoMethod *method = m->method;
7542 MonoMethod *result = NULL;
7543 int slot;
7545 if (method->klass == NULL)
7546 return m;
7548 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7549 MONO_CLASS_IS_INTERFACE (method->klass) ||
7550 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7551 return m;
7553 slot = mono_method_get_vtable_slot (method);
7554 if (slot == -1)
7555 return m;
7557 klass = method->klass;
7558 if (klass->generic_class) {
7559 generic_inst = mono_class_get_context (klass);
7560 klass = klass->generic_class->container_class;
7563 if (definition) {
7564 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7565 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7566 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7567 or klass is the generic container class and generic_inst is the instantiation.
7569 when we go to the parent, if the parent is an open constructed type, we need to
7570 replace the type parameters by the definitions from the generic_inst, and then take it
7571 apart again into the klass and the generic_inst.
7573 For cases like this:
7574 class C<T> : B<T, int> {
7575 public override void Foo () { ... }
7577 class B<U,V> : A<HashMap<U,V>> {
7578 public override void Foo () { ... }
7580 class A<X> {
7581 public virtual void Foo () { ... }
7584 if at each iteration the parent isn't open, we can skip inflating it. if at some
7585 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7586 NULL;
7588 MonoGenericContext *parent_inst = NULL;
7589 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7590 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7591 if (!mono_error_ok (&error)) {
7592 mono_error_set_pending_exception (&error);
7593 return NULL;
7596 if (parent->generic_class) {
7597 parent_inst = mono_class_get_context (parent);
7598 parent = parent->generic_class->container_class;
7601 mono_class_setup_vtable (parent);
7602 if (parent->vtable_size <= slot)
7603 break;
7604 klass = parent;
7605 generic_inst = parent_inst;
7607 } else {
7608 klass = klass->parent;
7609 if (!klass)
7610 return m;
7611 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7612 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7613 if (!mono_error_ok (&error)) {
7614 mono_error_set_pending_exception (&error);
7615 return NULL;
7618 generic_inst = NULL;
7620 if (klass->generic_class) {
7621 generic_inst = mono_class_get_context (klass);
7622 klass = klass->generic_class->container_class;
7627 if (generic_inst) {
7628 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7629 if (!mono_error_ok (&error)) {
7630 mono_error_set_pending_exception (&error);
7631 return NULL;
7635 if (klass == method->klass)
7636 return m;
7638 /*This is possible if definition == FALSE.
7639 * Do it here to be really sure we don't read invalid memory.
7641 if (slot >= klass->vtable_size)
7642 return m;
7644 mono_class_setup_vtable (klass);
7646 result = klass->vtable [slot];
7647 if (result == NULL) {
7648 /* It is an abstract method */
7649 gpointer iter = NULL;
7650 while ((result = mono_class_get_methods (klass, &iter)))
7651 if (result->slot == slot)
7652 break;
7655 if (result == NULL)
7656 return m;
7658 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7659 mono_error_set_pending_exception (&error);
7660 return ret;
7663 ICALL_EXPORT MonoString*
7664 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7666 MonoMethod *method = m->method;
7668 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7669 return m->name;
7672 ICALL_EXPORT void
7673 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7675 iter->sig = *(MonoMethodSignature**)argsp;
7677 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7678 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7680 iter->next_arg = 0;
7681 /* FIXME: it's not documented what start is exactly... */
7682 if (start) {
7683 iter->args = start;
7684 } else {
7685 iter->args = argsp + sizeof (gpointer);
7687 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7689 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7692 ICALL_EXPORT MonoTypedRef
7693 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7695 guint32 i, arg_size;
7696 gint32 align;
7697 MonoTypedRef res;
7699 i = iter->sig->sentinelpos + iter->next_arg;
7701 g_assert (i < iter->sig->param_count);
7703 res.type = iter->sig->params [i];
7704 res.klass = mono_class_from_mono_type (res.type);
7705 arg_size = mono_type_stack_size (res.type, &align);
7706 #if defined(__arm__) || defined(__mips__)
7707 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7708 #endif
7709 res.value = iter->args;
7710 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7711 /* Values are stored as 8 byte register sized objects, but 'value'
7712 * is dereferenced as a pointer in other routines.
7714 res.value = (char*)res.value + 4;
7715 #endif
7716 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7717 if (arg_size <= sizeof (gpointer)) {
7718 int dummy;
7719 int padding = arg_size - mono_type_size (res.type, &dummy);
7720 res.value = (guint8*)res.value + padding;
7722 #endif
7723 iter->args = (char*)iter->args + arg_size;
7724 iter->next_arg++;
7726 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7728 return res;
7731 ICALL_EXPORT MonoTypedRef
7732 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7734 guint32 i, arg_size;
7735 gint32 align;
7736 MonoTypedRef res;
7738 i = iter->sig->sentinelpos + iter->next_arg;
7740 g_assert (i < iter->sig->param_count);
7742 while (i < iter->sig->param_count) {
7743 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7744 continue;
7745 res.type = iter->sig->params [i];
7746 res.klass = mono_class_from_mono_type (res.type);
7747 /* FIXME: endianess issue... */
7748 arg_size = mono_type_stack_size (res.type, &align);
7749 #if defined(__arm__) || defined(__mips__)
7750 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7751 #endif
7752 res.value = iter->args;
7753 iter->args = (char*)iter->args + arg_size;
7754 iter->next_arg++;
7755 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7756 return res;
7758 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7760 res.type = NULL;
7761 res.value = NULL;
7762 res.klass = NULL;
7763 return res;
7766 ICALL_EXPORT MonoType*
7767 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7769 gint i;
7771 i = iter->sig->sentinelpos + iter->next_arg;
7773 g_assert (i < iter->sig->param_count);
7775 return iter->sig->params [i];
7778 ICALL_EXPORT MonoObject*
7779 mono_TypedReference_ToObject (MonoTypedRef* tref)
7781 MonoError error;
7782 MonoObject *result = NULL;
7783 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7784 MonoObject** objp = (MonoObject **)tref->value;
7785 return *objp;
7788 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7789 mono_error_set_pending_exception (&error);
7790 return result;
7793 ICALL_EXPORT MonoTypedRef
7794 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7796 MonoTypedRef res;
7797 MonoReflectionField *f;
7798 MonoClass *klass;
7799 MonoType *ftype = NULL;
7800 guint8 *p = NULL;
7801 int i;
7803 memset (&res, 0, sizeof (res));
7805 g_assert (fields);
7806 g_assert (mono_array_length (fields) > 0);
7808 klass = target->vtable->klass;
7810 for (i = 0; i < mono_array_length (fields); ++i) {
7811 f = mono_array_get (fields, MonoReflectionField*, i);
7812 if (f == NULL) {
7813 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7814 return res;
7816 if (f->field->parent != klass) {
7817 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7818 return res;
7820 if (i == 0)
7821 p = (guint8*)target + f->field->offset;
7822 else
7823 p += f->field->offset - sizeof (MonoObject);
7824 klass = mono_class_from_mono_type (f->field->type);
7825 ftype = f->field->type;
7828 res.type = ftype;
7829 res.klass = mono_class_from_mono_type (ftype);
7830 res.value = p;
7832 return res;
7835 static void
7836 prelink_method (MonoMethod *method, MonoError *error)
7838 const char *exc_class, *exc_arg;
7840 mono_error_init (error);
7841 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7842 return;
7843 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7844 if (exc_class) {
7845 mono_error_set_exception_instance (error,
7846 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7847 return;
7849 /* create the wrapper, too? */
7852 ICALL_EXPORT void
7853 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7855 MonoError error;
7857 prelink_method (method->method, &error);
7858 mono_error_set_pending_exception (&error);
7861 ICALL_EXPORT void
7862 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7864 MonoError error;
7865 MonoClass *klass = mono_class_from_mono_type (type->type);
7866 MonoMethod* m;
7867 gpointer iter = NULL;
7869 mono_class_init_checked (klass, &error);
7870 if (mono_error_set_pending_exception (&error))
7871 return;
7873 while ((m = mono_class_get_methods (klass, &iter))) {
7874 prelink_method (m, &error);
7875 if (mono_error_set_pending_exception (&error))
7876 return;
7880 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7881 ICALL_EXPORT void
7882 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7883 gint32 const **exponents,
7884 gunichar2 const **digitLowerTable,
7885 gunichar2 const **digitUpperTable,
7886 gint64 const **tenPowersList,
7887 gint32 const **decHexDigits)
7889 *mantissas = Formatter_MantissaBitsTable;
7890 *exponents = Formatter_TensExponentTable;
7891 *digitLowerTable = Formatter_DigitLowerTable;
7892 *digitUpperTable = Formatter_DigitUpperTable;
7893 *tenPowersList = Formatter_TenPowersList;
7894 *decHexDigits = Formatter_DecHexDigits;
7898 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7899 * and avoid useless allocations.
7901 static MonoArray*
7902 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7904 MonoReflectionType *rt;
7905 MonoArray *res;
7906 int i, count = 0;
7908 mono_error_init (error);
7909 for (i = 0; i < type->num_mods; ++i) {
7910 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7911 count++;
7913 if (!count)
7914 return NULL;
7915 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7916 return_val_if_nok (error, NULL);
7917 count = 0;
7918 for (i = 0; i < type->num_mods; ++i) {
7919 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7920 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7921 return_val_if_nok (error, NULL);
7923 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7924 return_val_if_nok (error, NULL);
7926 mono_array_setref (res, count, rt);
7927 count++;
7930 return res;
7933 ICALL_EXPORT MonoArray*
7934 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7936 MonoError error;
7937 MonoType *type = param->ClassImpl->type;
7938 MonoClass *member_class = mono_object_class (param->MemberImpl);
7939 MonoMethod *method = NULL;
7940 MonoImage *image;
7941 int pos;
7942 MonoMethodSignature *sig;
7943 MonoArray *res;
7945 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7946 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7947 method = rmethod->method;
7948 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7949 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7950 if (!(method = prop->property->get))
7951 method = prop->property->set;
7952 g_assert (method);
7953 } else {
7954 char *type_name = mono_type_get_full_name (member_class);
7955 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7956 MonoException *ex = mono_get_exception_not_supported (msg);
7957 g_free (type_name);
7958 g_free (msg);
7959 mono_set_pending_exception (ex);
7960 return NULL;
7963 image = method->klass->image;
7964 pos = param->PositionImpl;
7965 sig = mono_method_signature (method);
7966 if (pos == -1)
7967 type = sig->ret;
7968 else
7969 type = sig->params [pos];
7971 res = type_array_from_modifiers (image, type, optional, &error);
7972 mono_error_set_pending_exception (&error);
7973 return res;
7976 static MonoType*
7977 get_property_type (MonoProperty *prop)
7979 MonoMethodSignature *sig;
7980 if (prop->get) {
7981 sig = mono_method_signature (prop->get);
7982 return sig->ret;
7983 } else if (prop->set) {
7984 sig = mono_method_signature (prop->set);
7985 return sig->params [sig->param_count - 1];
7987 return NULL;
7990 ICALL_EXPORT MonoArray*
7991 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7993 MonoError error;
7994 MonoType *type = get_property_type (property->property);
7995 MonoImage *image = property->klass->image;
7996 MonoArray *res;
7998 if (!type)
7999 return NULL;
8000 res = type_array_from_modifiers (image, type, optional, &error);
8001 mono_error_set_pending_exception (&error);
8002 return res;
8006 *Construct a MonoType suited to be used to decode a constant blob object.
8008 * @type is the target type which will be constructed
8009 * @blob_type is the blob type, for example, that comes from the constant table
8010 * @real_type is the expected constructed type.
8012 static void
8013 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8015 type->type = blob_type;
8016 type->data.klass = NULL;
8017 if (blob_type == MONO_TYPE_CLASS)
8018 type->data.klass = mono_defaults.object_class;
8019 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8020 /* For enums, we need to use the base type */
8021 type->type = MONO_TYPE_VALUETYPE;
8022 type->data.klass = mono_class_from_mono_type (real_type);
8023 } else
8024 type->data.klass = mono_class_from_mono_type (real_type);
8027 ICALL_EXPORT MonoObject*
8028 property_info_get_default_value (MonoReflectionProperty *property)
8030 MonoError error;
8031 MonoType blob_type;
8032 MonoProperty *prop = property->property;
8033 MonoType *type = get_property_type (prop);
8034 MonoDomain *domain = mono_object_domain (property);
8035 MonoTypeEnum def_type;
8036 const char *def_value;
8037 MonoObject *o;
8039 mono_class_init (prop->parent);
8041 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8042 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8043 return NULL;
8046 def_value = mono_class_get_property_default_value (prop, &def_type);
8048 mono_type_from_blob_type (&blob_type, def_type, type);
8049 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8051 mono_error_set_pending_exception (&error);
8052 return o;
8055 ICALL_EXPORT MonoBoolean
8056 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8058 MonoError error;
8059 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8060 MonoCustomAttrInfo *cinfo;
8061 gboolean found;
8063 mono_class_init_checked (attr_class, &error);
8064 if (mono_error_set_pending_exception (&error))
8065 return FALSE;
8067 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8068 if (!is_ok (&error)) {
8069 mono_error_set_pending_exception (&error);
8070 return FALSE;
8072 if (!cinfo)
8073 return FALSE;
8074 found = mono_custom_attrs_has_attr (cinfo, attr_class);
8075 if (!cinfo->cached)
8076 mono_custom_attrs_free (cinfo);
8077 return found;
8080 ICALL_EXPORT MonoArray*
8081 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8083 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8084 MonoArray *res;
8085 MonoError error;
8087 if (attr_class) {
8088 mono_class_init_checked (attr_class, &error);
8089 if (mono_error_set_pending_exception (&error))
8090 return NULL;
8093 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8094 if (!mono_error_ok (&error)) {
8095 mono_error_set_pending_exception (&error);
8096 return NULL;
8099 return res;
8102 ICALL_EXPORT MonoArray*
8103 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8105 MonoError error;
8106 MonoArray *result;
8107 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8108 mono_error_set_pending_exception (&error);
8109 return result;
8113 ICALL_EXPORT MonoString*
8114 ves_icall_Mono_Runtime_GetDisplayName (void)
8116 char *info;
8117 MonoString *display_name;
8119 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8120 display_name = mono_string_new (mono_domain_get (), info);
8121 g_free (info);
8122 return display_name;
8125 ICALL_EXPORT MonoString*
8126 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8128 MonoError error;
8129 MonoString *message;
8130 guint32 ret;
8131 gunichar2 buf[256];
8133 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8134 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8135 buf, 255, NULL);
8136 if (ret == 0) {
8137 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8138 } else {
8139 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8140 if (mono_error_set_pending_exception (&error))
8141 return NULL;
8144 return message;
8147 ICALL_EXPORT gpointer
8148 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8150 return GetCurrentProcess ();
8153 ICALL_EXPORT MonoBoolean
8154 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8156 return GetExitCodeProcess (handle, (guint32*) exitcode);
8159 ICALL_EXPORT MonoBoolean
8160 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8162 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8163 return CloseHandle (handle);
8164 #else
8165 return CloseProcess (handle);
8166 #endif
8169 ICALL_EXPORT MonoBoolean
8170 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8172 return TerminateProcess (handle, exitcode);
8175 ICALL_EXPORT gint32
8176 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8178 return WaitForInputIdle (handle, milliseconds);
8181 ICALL_EXPORT MonoBoolean
8182 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8184 return GetProcessWorkingSetSize (handle, min, max);
8187 ICALL_EXPORT MonoBoolean
8188 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8190 return SetProcessWorkingSetSize (handle, min, max);
8193 ICALL_EXPORT MonoBoolean
8194 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8196 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8199 ICALL_EXPORT gint32
8200 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8202 return mono_process_current_pid ();
8205 ICALL_EXPORT gint32
8206 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8208 return GetPriorityClass (handle);
8211 ICALL_EXPORT MonoBoolean
8212 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8214 return SetPriorityClass (handle, priorityClass);
8217 #ifndef DISABLE_ICALL_TABLES
8219 #define ICALL_TYPE(id,name,first)
8220 #define ICALL(id,name,func) Icall_ ## id,
8222 enum {
8223 #include "metadata/icall-def.h"
8224 Icall_last
8227 #undef ICALL_TYPE
8228 #undef ICALL
8229 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8230 #define ICALL(id,name,func)
8231 enum {
8232 #include "metadata/icall-def.h"
8233 Icall_type_num
8236 #undef ICALL_TYPE
8237 #undef ICALL
8238 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8239 #define ICALL(id,name,func)
8240 typedef struct {
8241 guint16 first_icall;
8242 } IcallTypeDesc;
8244 static const IcallTypeDesc
8245 icall_type_descs [] = {
8246 #include "metadata/icall-def.h"
8247 {Icall_last}
8250 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8252 #undef ICALL_TYPE
8253 #define ICALL_TYPE(id,name,first)
8254 #undef ICALL
8256 #ifdef HAVE_ARRAY_ELEM_INIT
8257 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8258 #define MSGSTRFIELD1(line) str##line
8260 static const struct msgstrtn_t {
8261 #define ICALL(id,name,func)
8262 #undef ICALL_TYPE
8263 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8264 #include "metadata/icall-def.h"
8265 #undef ICALL_TYPE
8266 } icall_type_names_str = {
8267 #define ICALL_TYPE(id,name,first) (name),
8268 #include "metadata/icall-def.h"
8269 #undef ICALL_TYPE
8271 static const guint16 icall_type_names_idx [] = {
8272 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8273 #include "metadata/icall-def.h"
8274 #undef ICALL_TYPE
8276 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8278 static const struct msgstr_t {
8279 #undef ICALL
8280 #define ICALL_TYPE(id,name,first)
8281 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8282 #include "metadata/icall-def.h"
8283 #undef ICALL
8284 } icall_names_str = {
8285 #define ICALL(id,name,func) (name),
8286 #include "metadata/icall-def.h"
8287 #undef ICALL
8289 static const guint16 icall_names_idx [] = {
8290 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8291 #include "metadata/icall-def.h"
8292 #undef ICALL
8294 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8296 #else
8298 #undef ICALL_TYPE
8299 #undef ICALL
8300 #define ICALL_TYPE(id,name,first) name,
8301 #define ICALL(id,name,func)
8302 static const char* const
8303 icall_type_names [] = {
8304 #include "metadata/icall-def.h"
8305 NULL
8308 #define icall_type_name_get(id) (icall_type_names [(id)])
8310 #undef ICALL_TYPE
8311 #undef ICALL
8312 #define ICALL_TYPE(id,name,first)
8313 #define ICALL(id,name,func) name,
8314 static const char* const
8315 icall_names [] = {
8316 #include "metadata/icall-def.h"
8317 NULL
8319 #define icall_name_get(id) icall_names [(id)]
8321 #endif /* !HAVE_ARRAY_ELEM_INIT */
8323 #undef ICALL_TYPE
8324 #undef ICALL
8325 #define ICALL_TYPE(id,name,first)
8326 #define ICALL(id,name,func) func,
8327 static const gconstpointer
8328 icall_functions [] = {
8329 #include "metadata/icall-def.h"
8330 NULL
8333 #ifdef ENABLE_ICALL_SYMBOL_MAP
8334 #undef ICALL_TYPE
8335 #undef ICALL
8336 #define ICALL_TYPE(id,name,first)
8337 #define ICALL(id,name,func) #func,
8338 static const gconstpointer
8339 icall_symbols [] = {
8340 #include "metadata/icall-def.h"
8341 NULL
8343 #endif
8345 #endif /* DISABLE_ICALL_TABLES */
8347 static mono_mutex_t icall_mutex;
8348 static GHashTable *icall_hash = NULL;
8349 static GHashTable *jit_icall_hash_name = NULL;
8350 static GHashTable *jit_icall_hash_addr = NULL;
8352 void
8353 mono_icall_init (void)
8355 #ifndef DISABLE_ICALL_TABLES
8356 int i = 0;
8358 /* check that tables are sorted: disable in release */
8359 if (TRUE) {
8360 int j;
8361 const char *prev_class = NULL;
8362 const char *prev_method;
8364 for (i = 0; i < Icall_type_num; ++i) {
8365 const IcallTypeDesc *desc;
8366 int num_icalls;
8367 prev_method = NULL;
8368 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8369 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8370 prev_class = icall_type_name_get (i);
8371 desc = &icall_type_descs [i];
8372 num_icalls = icall_desc_num_icalls (desc);
8373 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8374 for (j = 0; j < num_icalls; ++j) {
8375 const char *methodn = icall_name_get (desc->first_icall + j);
8376 if (prev_method && strcmp (prev_method, methodn) >= 0)
8377 g_print ("method %s should come before method %s\n", methodn, prev_method);
8378 prev_method = methodn;
8382 #endif
8384 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8385 mono_os_mutex_init (&icall_mutex);
8388 static void
8389 mono_icall_lock (void)
8391 mono_locks_os_acquire (&icall_mutex, IcallLock);
8394 static void
8395 mono_icall_unlock (void)
8397 mono_locks_os_release (&icall_mutex, IcallLock);
8400 void
8401 mono_icall_cleanup (void)
8403 g_hash_table_destroy (icall_hash);
8404 g_hash_table_destroy (jit_icall_hash_name);
8405 g_hash_table_destroy (jit_icall_hash_addr);
8406 mono_os_mutex_destroy (&icall_mutex);
8410 * mono_add_internal_call:
8411 * @name: method specification to surface to the managed world
8412 * @method: pointer to a C method to invoke when the method is called
8414 * This method surfaces the C function pointed by @method as a method
8415 * that has been surfaced in managed code with the method specified in
8416 * @name as an internal call.
8418 * Internal calls are surfaced to all app domains loaded and they are
8419 * accessibly by a type with the specified name.
8421 * You must provide a fully qualified type name, that is namespaces
8422 * and type name, followed by a colon and the method name, with an
8423 * optional signature to bind.
8425 * For example, the following are all valid declarations:
8427 * "MyApp.Services.ScriptService:Accelerate"
8428 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8430 * You use method parameters in cases where there might be more than
8431 * one surface method to managed code. That way you can register different
8432 * internal calls for different method overloads.
8434 * The internal calls are invoked with no marshalling. This means that .NET
8435 * types like System.String are exposed as `MonoString *` parameters. This is
8436 * different than the way that strings are surfaced in P/Invoke.
8438 * For more information on how the parameters are marshalled, see the
8439 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8440 * page.
8442 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8443 * reference for more information on the format of method descriptions.
8445 void
8446 mono_add_internal_call (const char *name, gconstpointer method)
8448 mono_icall_lock ();
8450 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8452 mono_icall_unlock ();
8455 #ifndef DISABLE_ICALL_TABLES
8457 #ifdef HAVE_ARRAY_ELEM_INIT
8458 static int
8459 compare_method_imap (const void *key, const void *elem)
8461 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8462 return strcmp (key, method_name);
8465 static gpointer
8466 find_method_icall (const IcallTypeDesc *imap, const char *name)
8468 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);
8469 if (!nameslot)
8470 return NULL;
8471 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8474 static int
8475 compare_class_imap (const void *key, const void *elem)
8477 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8478 return strcmp (key, class_name);
8481 static const IcallTypeDesc*
8482 find_class_icalls (const char *name)
8484 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);
8485 if (!nameslot)
8486 return NULL;
8487 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8490 #else /* HAVE_ARRAY_ELEM_INIT */
8492 static int
8493 compare_method_imap (const void *key, const void *elem)
8495 const char** method_name = (const char**)elem;
8496 return strcmp (key, *method_name);
8499 static gpointer
8500 find_method_icall (const IcallTypeDesc *imap, const char *name)
8502 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8503 if (!nameslot)
8504 return NULL;
8505 return (gpointer)icall_functions [(nameslot - icall_names)];
8508 static int
8509 compare_class_imap (const void *key, const void *elem)
8511 const char** class_name = (const char**)elem;
8512 return strcmp (key, *class_name);
8515 static const IcallTypeDesc*
8516 find_class_icalls (const char *name)
8518 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8519 if (!nameslot)
8520 return NULL;
8521 return &icall_type_descs [nameslot - icall_type_names];
8524 #endif /* HAVE_ARRAY_ELEM_INIT */
8526 #endif /* DISABLE_ICALL_TABLES */
8529 * we should probably export this as an helper (handle nested types).
8530 * Returns the number of chars written in buf.
8532 static int
8533 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8535 int nspacelen, cnamelen;
8536 nspacelen = strlen (klass->name_space);
8537 cnamelen = strlen (klass->name);
8538 if (nspacelen + cnamelen + 2 > bufsize)
8539 return 0;
8540 if (nspacelen) {
8541 memcpy (buf, klass->name_space, nspacelen);
8542 buf [nspacelen ++] = '.';
8544 memcpy (buf + nspacelen, klass->name, cnamelen);
8545 buf [nspacelen + cnamelen] = 0;
8546 return nspacelen + cnamelen;
8549 #ifdef DISABLE_ICALL_TABLES
8550 static void
8551 no_icall_table (void)
8553 g_assert_not_reached ();
8555 #endif
8557 gpointer
8558 mono_lookup_internal_call (MonoMethod *method)
8560 char *sigstart;
8561 char *tmpsig;
8562 char mname [2048];
8563 int typelen = 0, mlen, siglen;
8564 gpointer res;
8565 #ifndef DISABLE_ICALL_TABLES
8566 const IcallTypeDesc *imap = NULL;
8567 #endif
8569 g_assert (method != NULL);
8571 if (method->is_inflated)
8572 method = ((MonoMethodInflated *) method)->declaring;
8574 if (method->klass->nested_in) {
8575 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8576 if (!pos)
8577 return NULL;
8579 mname [pos++] = '/';
8580 mname [pos] = 0;
8582 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8583 if (!typelen)
8584 return NULL;
8586 typelen += pos;
8587 } else {
8588 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8589 if (!typelen)
8590 return NULL;
8593 #ifndef DISABLE_ICALL_TABLES
8594 imap = find_class_icalls (mname);
8595 #endif
8597 mname [typelen] = ':';
8598 mname [typelen + 1] = ':';
8600 mlen = strlen (method->name);
8601 memcpy (mname + typelen + 2, method->name, mlen);
8602 sigstart = mname + typelen + 2 + mlen;
8603 *sigstart = 0;
8605 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8606 siglen = strlen (tmpsig);
8607 if (typelen + mlen + siglen + 6 > sizeof (mname))
8608 return NULL;
8609 sigstart [0] = '(';
8610 memcpy (sigstart + 1, tmpsig, siglen);
8611 sigstart [siglen + 1] = ')';
8612 sigstart [siglen + 2] = 0;
8613 g_free (tmpsig);
8615 mono_icall_lock ();
8617 res = g_hash_table_lookup (icall_hash, mname);
8618 if (res) {
8619 mono_icall_unlock ();;
8620 return res;
8622 /* try without signature */
8623 *sigstart = 0;
8624 res = g_hash_table_lookup (icall_hash, mname);
8625 if (res) {
8626 mono_icall_unlock ();
8627 return res;
8630 #ifdef DISABLE_ICALL_TABLES
8631 mono_icall_unlock ();
8632 /* Fail only when the result is actually used */
8633 /* mono_marshal_get_native_wrapper () depends on this */
8634 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8635 return ves_icall_System_String_ctor_RedirectToCreateString;
8636 else
8637 return no_icall_table;
8638 #else
8639 /* it wasn't found in the static call tables */
8640 if (!imap) {
8641 mono_icall_unlock ();
8642 return NULL;
8644 res = find_method_icall (imap, sigstart - mlen);
8645 if (res) {
8646 mono_icall_unlock ();
8647 return res;
8649 /* try _with_ signature */
8650 *sigstart = '(';
8651 res = find_method_icall (imap, sigstart - mlen);
8652 if (res) {
8653 mono_icall_unlock ();
8654 return res;
8657 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8658 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8659 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8660 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8661 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");
8662 g_print ("If you see other errors or faults after this message they are probably related\n");
8663 g_print ("and you need to fix your mono install first.\n");
8665 mono_icall_unlock ();
8667 return NULL;
8668 #endif
8671 #ifdef ENABLE_ICALL_SYMBOL_MAP
8672 static int
8673 func_cmp (gconstpointer key, gconstpointer p)
8675 return (gsize)key - (gsize)*(gsize*)p;
8677 #endif
8680 * mono_lookup_icall_symbol:
8682 * Given the icall METHOD, returns its C symbol.
8684 const char*
8685 mono_lookup_icall_symbol (MonoMethod *m)
8687 #ifdef DISABLE_ICALL_TABLES
8688 g_assert_not_reached ();
8689 return NULL;
8690 #else
8691 #ifdef ENABLE_ICALL_SYMBOL_MAP
8692 gpointer func;
8693 int i;
8694 gpointer slot;
8695 static gconstpointer *functions_sorted;
8696 static const char**symbols_sorted;
8697 static gboolean inited;
8699 if (!inited) {
8700 gboolean changed;
8702 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8703 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8704 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8705 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8706 /* Bubble sort the two arrays */
8707 changed = TRUE;
8708 while (changed) {
8709 changed = FALSE;
8710 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8711 if (functions_sorted [i] > functions_sorted [i + 1]) {
8712 gconstpointer tmp;
8714 tmp = functions_sorted [i];
8715 functions_sorted [i] = functions_sorted [i + 1];
8716 functions_sorted [i + 1] = tmp;
8717 tmp = symbols_sorted [i];
8718 symbols_sorted [i] = symbols_sorted [i + 1];
8719 symbols_sorted [i + 1] = tmp;
8720 changed = TRUE;
8726 func = mono_lookup_internal_call (m);
8727 if (!func)
8728 return NULL;
8729 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8730 if (!slot)
8731 return NULL;
8732 g_assert (slot);
8733 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8734 #else
8735 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8736 g_assert_not_reached ();
8737 return 0;
8738 #endif
8739 #endif
8742 static MonoType*
8743 type_from_typename (char *type_name)
8745 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8747 if (!strcmp (type_name, "int"))
8748 klass = mono_defaults.int_class;
8749 else if (!strcmp (type_name, "ptr"))
8750 klass = mono_defaults.int_class;
8751 else if (!strcmp (type_name, "void"))
8752 klass = mono_defaults.void_class;
8753 else if (!strcmp (type_name, "int32"))
8754 klass = mono_defaults.int32_class;
8755 else if (!strcmp (type_name, "uint32"))
8756 klass = mono_defaults.uint32_class;
8757 else if (!strcmp (type_name, "int8"))
8758 klass = mono_defaults.sbyte_class;
8759 else if (!strcmp (type_name, "uint8"))
8760 klass = mono_defaults.byte_class;
8761 else if (!strcmp (type_name, "int16"))
8762 klass = mono_defaults.int16_class;
8763 else if (!strcmp (type_name, "uint16"))
8764 klass = mono_defaults.uint16_class;
8765 else if (!strcmp (type_name, "long"))
8766 klass = mono_defaults.int64_class;
8767 else if (!strcmp (type_name, "ulong"))
8768 klass = mono_defaults.uint64_class;
8769 else if (!strcmp (type_name, "float"))
8770 klass = mono_defaults.single_class;
8771 else if (!strcmp (type_name, "double"))
8772 klass = mono_defaults.double_class;
8773 else if (!strcmp (type_name, "object"))
8774 klass = mono_defaults.object_class;
8775 else if (!strcmp (type_name, "obj"))
8776 klass = mono_defaults.object_class;
8777 else if (!strcmp (type_name, "string"))
8778 klass = mono_defaults.string_class;
8779 else if (!strcmp (type_name, "bool"))
8780 klass = mono_defaults.boolean_class;
8781 else if (!strcmp (type_name, "boolean"))
8782 klass = mono_defaults.boolean_class;
8783 else {
8784 g_error ("%s", type_name);
8785 g_assert_not_reached ();
8787 return &klass->byval_arg;
8791 * LOCKING: Take the corlib image lock.
8793 MonoMethodSignature*
8794 mono_create_icall_signature (const char *sigstr)
8796 gchar **parts;
8797 int i, len;
8798 gchar **tmp;
8799 MonoMethodSignature *res, *res2;
8800 MonoImage *corlib = mono_defaults.corlib;
8802 mono_image_lock (corlib);
8803 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8804 mono_image_unlock (corlib);
8806 if (res)
8807 return res;
8809 parts = g_strsplit (sigstr, " ", 256);
8811 tmp = parts;
8812 len = 0;
8813 while (*tmp) {
8814 len ++;
8815 tmp ++;
8818 res = mono_metadata_signature_alloc (corlib, len - 1);
8819 res->pinvoke = 1;
8821 #ifdef HOST_WIN32
8823 * Under windows, the default pinvoke calling convention is STDCALL but
8824 * we need CDECL.
8826 res->call_convention = MONO_CALL_C;
8827 #endif
8829 res->ret = type_from_typename (parts [0]);
8830 for (i = 1; i < len; ++i) {
8831 res->params [i - 1] = type_from_typename (parts [i]);
8834 g_strfreev (parts);
8836 mono_image_lock (corlib);
8837 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8838 if (res2)
8839 res = res2; /*Value is allocated in the image pool*/
8840 else
8841 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8842 mono_image_unlock (corlib);
8844 return res;
8847 MonoJitICallInfo *
8848 mono_find_jit_icall_by_name (const char *name)
8850 MonoJitICallInfo *info;
8851 g_assert (jit_icall_hash_name);
8853 mono_icall_lock ();
8854 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8855 mono_icall_unlock ();
8856 return info;
8859 MonoJitICallInfo *
8860 mono_find_jit_icall_by_addr (gconstpointer addr)
8862 MonoJitICallInfo *info;
8863 g_assert (jit_icall_hash_addr);
8865 mono_icall_lock ();
8866 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8867 mono_icall_unlock ();
8869 return info;
8873 * mono_get_jit_icall_info:
8875 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8876 * caller should access it while holding the icall lock.
8878 GHashTable*
8879 mono_get_jit_icall_info (void)
8881 return jit_icall_hash_name;
8885 * mono_lookup_jit_icall_symbol:
8887 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8889 const char*
8890 mono_lookup_jit_icall_symbol (const char *name)
8892 MonoJitICallInfo *info;
8893 const char *res = NULL;
8895 mono_icall_lock ();
8896 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8897 if (info)
8898 res = info->c_symbol;
8899 mono_icall_unlock ();
8900 return res;
8903 void
8904 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8906 mono_icall_lock ();
8907 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8908 mono_icall_unlock ();
8912 * 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
8913 * icalls without wrappers in some cases.
8915 MonoJitICallInfo *
8916 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8918 MonoJitICallInfo *info;
8920 g_assert (func);
8921 g_assert (name);
8923 mono_icall_lock ();
8925 if (!jit_icall_hash_name) {
8926 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8927 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8930 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8931 g_warning ("jit icall already defined \"%s\"\n", name);
8932 g_assert_not_reached ();
8935 info = g_new0 (MonoJitICallInfo, 1);
8937 info->name = name;
8938 info->func = func;
8939 info->sig = sig;
8940 info->c_symbol = c_symbol;
8941 info->no_raise = no_raise;
8943 if (is_save) {
8944 info->wrapper = func;
8945 } else {
8946 info->wrapper = NULL;
8949 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8950 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8952 mono_icall_unlock ();
8953 return info;
8956 MonoJitICallInfo *
8957 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8959 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);