Remove SRE.UnmanagedMarshal dependency from System.Reflection.
[mono-project.git] / mono / metadata / icall.c
blobcff4d622c73d9017566d0fe7ff5a77943c93f3b3
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)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 #include <config.h>
14 #include <glib.h>
15 #include <stdarg.h>
16 #include <string.h>
17 #include <ctype.h>
18 #ifdef HAVE_ALLOCA_H
19 #include <alloca.h>
20 #endif
21 #ifdef HAVE_SYS_TIME_H
22 #include <sys/time.h>
23 #endif
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #if defined (HOST_WIN32)
28 #include <stdlib.h>
29 #endif
30 #if defined (HAVE_WCHAR_H)
31 #include <wchar.h>
32 #endif
34 #include "mono/utils/mono-membar.h"
35 #include <mono/metadata/object.h>
36 #include <mono/metadata/threads.h>
37 #include <mono/metadata/threads-types.h>
38 #include <mono/metadata/threadpool.h>
39 #include <mono/metadata/monitor.h>
40 #include <mono/metadata/reflection.h>
41 #include <mono/metadata/assembly.h>
42 #include <mono/metadata/tabledefs.h>
43 #include <mono/metadata/exception.h>
44 #include <mono/metadata/file-io.h>
45 #include <mono/metadata/console-io.h>
46 #include <mono/metadata/socket-io.h>
47 #include <mono/metadata/mono-endian.h>
48 #include <mono/metadata/tokentype.h>
49 #include <mono/metadata/domain-internals.h>
50 #include <mono/metadata/metadata-internals.h>
51 #include <mono/metadata/class-internals.h>
52 #include <mono/metadata/marshal.h>
53 #include <mono/metadata/gc-internal.h>
54 #include <mono/metadata/mono-gc.h>
55 #include <mono/metadata/rand.h>
56 #include <mono/metadata/sysmath.h>
57 #include <mono/metadata/string-icalls.h>
58 #include <mono/metadata/debug-helpers.h>
59 #include <mono/metadata/process.h>
60 #include <mono/metadata/environment.h>
61 #include <mono/metadata/profiler-private.h>
62 #include <mono/metadata/locales.h>
63 #include <mono/metadata/filewatcher.h>
64 #include <mono/metadata/char-conversions.h>
65 #include <mono/metadata/security.h>
66 #include <mono/metadata/mono-config.h>
67 #include <mono/metadata/cil-coff.h>
68 #include <mono/metadata/number-formatter.h>
69 #include <mono/metadata/security-manager.h>
70 #include <mono/metadata/security-core-clr.h>
71 #include <mono/metadata/mono-perfcounters.h>
72 #include <mono/metadata/mono-debug.h>
73 #include <mono/metadata/mono-ptr-array.h>
74 #include <mono/metadata/verify-internals.h>
75 #include <mono/io-layer/io-layer.h>
76 #include <mono/utils/strtod.h>
77 #include <mono/utils/monobitset.h>
78 #include <mono/utils/mono-time.h>
79 #include <mono/utils/mono-proclib.h>
80 #include <mono/utils/mono-string.h>
81 #include <mono/utils/mono-error-internals.h>
82 #include <mono/utils/mono-mmap.h>
83 #include <mono/utils/mono-io-portability.h>
85 #if defined (HOST_WIN32)
86 #include <windows.h>
87 #include <shlobj.h>
88 #endif
89 #include "decimal.h"
91 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
93 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
95 static MonoArray*
96 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
98 static inline MonoBoolean
99 is_generic_parameter (MonoType *type)
101 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
104 static void
105 mono_class_init_or_throw (MonoClass *klass)
107 if (!mono_class_init (klass))
108 mono_raise_exception (mono_class_get_exception_for_failure (klass));
112 * We expect a pointer to a char, not a string
114 static gboolean
115 mono_double_ParseImpl (char *ptr, double *result)
117 gchar *endptr = NULL;
118 *result = 0.0;
120 MONO_ARCH_SAVE_REGS;
122 #ifdef __arm__
123 if (*ptr)
124 *result = strtod (ptr, &endptr);
125 #else
126 if (*ptr){
127 /* mono_strtod () is not thread-safe */
128 EnterCriticalSection (&mono_strtod_mutex);
129 *result = mono_strtod (ptr, &endptr);
130 LeaveCriticalSection (&mono_strtod_mutex);
132 #endif
134 if (!*ptr || (endptr && *endptr))
135 return FALSE;
137 return TRUE;
140 static MonoObject *
141 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
143 MonoClass *ac;
144 MonoArray *ao;
145 gint32 esize;
146 gpointer *ea;
148 MONO_ARCH_SAVE_REGS;
150 ao = (MonoArray *)this;
151 ac = (MonoClass *)ao->obj.vtable->klass;
153 esize = mono_array_element_size (ac);
154 ea = (gpointer*)((char*)ao->vector + (pos * esize));
156 if (ac->element_class->valuetype)
157 return mono_value_box (this->vtable->domain, ac->element_class, ea);
158 else
159 return *ea;
162 static MonoObject *
163 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
165 MonoClass *ac, *ic;
166 MonoArray *ao, *io;
167 gint32 i, pos, *ind;
169 MONO_ARCH_SAVE_REGS;
171 MONO_CHECK_ARG_NULL (idxs);
173 io = (MonoArray *)idxs;
174 ic = (MonoClass *)io->obj.vtable->klass;
176 ao = (MonoArray *)this;
177 ac = (MonoClass *)ao->obj.vtable->klass;
179 g_assert (ic->rank == 1);
180 if (io->bounds != NULL || io->max_length != ac->rank)
181 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
183 ind = (gint32 *)io->vector;
185 if (ao->bounds == NULL) {
186 if (*ind < 0 || *ind >= ao->max_length)
187 mono_raise_exception (mono_get_exception_index_out_of_range ());
189 return ves_icall_System_Array_GetValueImpl (this, *ind);
192 for (i = 0; i < ac->rank; i++)
193 if ((ind [i] < ao->bounds [i].lower_bound) ||
194 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
195 mono_raise_exception (mono_get_exception_index_out_of_range ());
197 pos = ind [0] - ao->bounds [0].lower_bound;
198 for (i = 1; i < ac->rank; i++)
199 pos = pos*ao->bounds [i].length + ind [i] -
200 ao->bounds [i].lower_bound;
202 return ves_icall_System_Array_GetValueImpl (this, pos);
205 static void
206 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
208 MonoClass *ac, *vc, *ec;
209 gint32 esize, vsize;
210 gpointer *ea, *va;
211 int et, vt;
213 guint64 u64 = 0;
214 gint64 i64 = 0;
215 gdouble r64 = 0;
217 MONO_ARCH_SAVE_REGS;
219 if (value)
220 vc = value->vtable->klass;
221 else
222 vc = NULL;
224 ac = this->obj.vtable->klass;
225 ec = ac->element_class;
227 esize = mono_array_element_size (ac);
228 ea = (gpointer*)((char*)this->vector + (pos * esize));
229 va = (gpointer*)((char*)value + sizeof (MonoObject));
231 if (mono_class_is_nullable (ec)) {
232 mono_nullable_init ((guint8*)ea, value, ec);
233 return;
236 if (!value) {
237 mono_gc_bzero (ea, esize);
238 return;
241 #define NO_WIDENING_CONVERSION G_STMT_START{\
242 mono_raise_exception (mono_get_exception_argument ( \
243 "value", "not a widening conversion")); \
244 }G_STMT_END
246 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
247 if (esize < vsize + (extra)) \
248 mono_raise_exception (mono_get_exception_argument ( \
249 "value", "not a widening conversion")); \
250 }G_STMT_END
252 #define INVALID_CAST G_STMT_START{ \
253 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
254 mono_raise_exception (mono_get_exception_invalid_cast ()); \
255 }G_STMT_END
257 /* Check element (destination) type. */
258 switch (ec->byval_arg.type) {
259 case MONO_TYPE_STRING:
260 switch (vc->byval_arg.type) {
261 case MONO_TYPE_STRING:
262 break;
263 default:
264 INVALID_CAST;
266 break;
267 case MONO_TYPE_BOOLEAN:
268 switch (vc->byval_arg.type) {
269 case MONO_TYPE_BOOLEAN:
270 break;
271 case MONO_TYPE_CHAR:
272 case MONO_TYPE_U1:
273 case MONO_TYPE_U2:
274 case MONO_TYPE_U4:
275 case MONO_TYPE_U8:
276 case MONO_TYPE_I1:
277 case MONO_TYPE_I2:
278 case MONO_TYPE_I4:
279 case MONO_TYPE_I8:
280 case MONO_TYPE_R4:
281 case MONO_TYPE_R8:
282 NO_WIDENING_CONVERSION;
283 default:
284 INVALID_CAST;
286 break;
289 if (!ec->valuetype) {
290 if (!mono_object_isinst (value, ec))
291 INVALID_CAST;
292 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
293 return;
296 if (mono_object_isinst (value, ec)) {
297 if (ec->has_references)
298 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
299 else
300 mono_gc_memmove (ea, (char *)value + sizeof (MonoObject), esize);
301 return;
304 if (!vc->valuetype)
305 INVALID_CAST;
307 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
309 et = ec->byval_arg.type;
310 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
311 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
313 vt = vc->byval_arg.type;
314 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
315 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
317 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
318 switch (vt) { \
319 case MONO_TYPE_U1: \
320 case MONO_TYPE_U2: \
321 case MONO_TYPE_U4: \
322 case MONO_TYPE_U8: \
323 case MONO_TYPE_CHAR: \
324 CHECK_WIDENING_CONVERSION(0); \
325 *(etype *) ea = (etype) u64; \
326 return; \
327 /* You can't assign a signed value to an unsigned array. */ \
328 case MONO_TYPE_I1: \
329 case MONO_TYPE_I2: \
330 case MONO_TYPE_I4: \
331 case MONO_TYPE_I8: \
332 /* You can't assign a floating point number to an integer array. */ \
333 case MONO_TYPE_R4: \
334 case MONO_TYPE_R8: \
335 NO_WIDENING_CONVERSION; \
337 }G_STMT_END
339 #define ASSIGN_SIGNED(etype) G_STMT_START{\
340 switch (vt) { \
341 case MONO_TYPE_I1: \
342 case MONO_TYPE_I2: \
343 case MONO_TYPE_I4: \
344 case MONO_TYPE_I8: \
345 CHECK_WIDENING_CONVERSION(0); \
346 *(etype *) ea = (etype) i64; \
347 return; \
348 /* You can assign an unsigned value to a signed array if the array's */ \
349 /* element size is larger than the value size. */ \
350 case MONO_TYPE_U1: \
351 case MONO_TYPE_U2: \
352 case MONO_TYPE_U4: \
353 case MONO_TYPE_U8: \
354 case MONO_TYPE_CHAR: \
355 CHECK_WIDENING_CONVERSION(1); \
356 *(etype *) ea = (etype) u64; \
357 return; \
358 /* You can't assign a floating point number to an integer array. */ \
359 case MONO_TYPE_R4: \
360 case MONO_TYPE_R8: \
361 NO_WIDENING_CONVERSION; \
363 }G_STMT_END
365 #define ASSIGN_REAL(etype) G_STMT_START{\
366 switch (vt) { \
367 case MONO_TYPE_R4: \
368 case MONO_TYPE_R8: \
369 CHECK_WIDENING_CONVERSION(0); \
370 *(etype *) ea = (etype) r64; \
371 return; \
372 /* All integer values fit into a floating point array, so we don't */ \
373 /* need to CHECK_WIDENING_CONVERSION here. */ \
374 case MONO_TYPE_I1: \
375 case MONO_TYPE_I2: \
376 case MONO_TYPE_I4: \
377 case MONO_TYPE_I8: \
378 *(etype *) ea = (etype) i64; \
379 return; \
380 case MONO_TYPE_U1: \
381 case MONO_TYPE_U2: \
382 case MONO_TYPE_U4: \
383 case MONO_TYPE_U8: \
384 case MONO_TYPE_CHAR: \
385 *(etype *) ea = (etype) u64; \
386 return; \
388 }G_STMT_END
390 switch (vt) {
391 case MONO_TYPE_U1:
392 u64 = *(guint8 *) va;
393 break;
394 case MONO_TYPE_U2:
395 u64 = *(guint16 *) va;
396 break;
397 case MONO_TYPE_U4:
398 u64 = *(guint32 *) va;
399 break;
400 case MONO_TYPE_U8:
401 u64 = *(guint64 *) va;
402 break;
403 case MONO_TYPE_I1:
404 i64 = *(gint8 *) va;
405 break;
406 case MONO_TYPE_I2:
407 i64 = *(gint16 *) va;
408 break;
409 case MONO_TYPE_I4:
410 i64 = *(gint32 *) va;
411 break;
412 case MONO_TYPE_I8:
413 i64 = *(gint64 *) va;
414 break;
415 case MONO_TYPE_R4:
416 r64 = *(gfloat *) va;
417 break;
418 case MONO_TYPE_R8:
419 r64 = *(gdouble *) va;
420 break;
421 case MONO_TYPE_CHAR:
422 u64 = *(guint16 *) va;
423 break;
424 case MONO_TYPE_BOOLEAN:
425 /* Boolean is only compatible with itself. */
426 switch (et) {
427 case MONO_TYPE_CHAR:
428 case MONO_TYPE_U1:
429 case MONO_TYPE_U2:
430 case MONO_TYPE_U4:
431 case MONO_TYPE_U8:
432 case MONO_TYPE_I1:
433 case MONO_TYPE_I2:
434 case MONO_TYPE_I4:
435 case MONO_TYPE_I8:
436 case MONO_TYPE_R4:
437 case MONO_TYPE_R8:
438 NO_WIDENING_CONVERSION;
439 default:
440 INVALID_CAST;
442 break;
445 /* If we can't do a direct copy, let's try a widening conversion. */
446 switch (et) {
447 case MONO_TYPE_CHAR:
448 ASSIGN_UNSIGNED (guint16);
449 case MONO_TYPE_U1:
450 ASSIGN_UNSIGNED (guint8);
451 case MONO_TYPE_U2:
452 ASSIGN_UNSIGNED (guint16);
453 case MONO_TYPE_U4:
454 ASSIGN_UNSIGNED (guint32);
455 case MONO_TYPE_U8:
456 ASSIGN_UNSIGNED (guint64);
457 case MONO_TYPE_I1:
458 ASSIGN_SIGNED (gint8);
459 case MONO_TYPE_I2:
460 ASSIGN_SIGNED (gint16);
461 case MONO_TYPE_I4:
462 ASSIGN_SIGNED (gint32);
463 case MONO_TYPE_I8:
464 ASSIGN_SIGNED (gint64);
465 case MONO_TYPE_R4:
466 ASSIGN_REAL (gfloat);
467 case MONO_TYPE_R8:
468 ASSIGN_REAL (gdouble);
471 INVALID_CAST;
472 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
473 return;
475 #undef INVALID_CAST
476 #undef NO_WIDENING_CONVERSION
477 #undef CHECK_WIDENING_CONVERSION
478 #undef ASSIGN_UNSIGNED
479 #undef ASSIGN_SIGNED
480 #undef ASSIGN_REAL
483 static void
484 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
485 MonoArray *idxs)
487 MonoClass *ac, *ic;
488 gint32 i, pos, *ind;
490 MONO_ARCH_SAVE_REGS;
492 MONO_CHECK_ARG_NULL (idxs);
494 ic = idxs->obj.vtable->klass;
495 ac = this->obj.vtable->klass;
497 g_assert (ic->rank == 1);
498 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
499 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
501 ind = (gint32 *)idxs->vector;
503 if (this->bounds == NULL) {
504 if (*ind < 0 || *ind >= this->max_length)
505 mono_raise_exception (mono_get_exception_index_out_of_range ());
507 ves_icall_System_Array_SetValueImpl (this, value, *ind);
508 return;
511 for (i = 0; i < ac->rank; i++)
512 if ((ind [i] < this->bounds [i].lower_bound) ||
513 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
514 mono_raise_exception (mono_get_exception_index_out_of_range ());
516 pos = ind [0] - this->bounds [0].lower_bound;
517 for (i = 1; i < ac->rank; i++)
518 pos = pos * this->bounds [i].length + ind [i] -
519 this->bounds [i].lower_bound;
521 ves_icall_System_Array_SetValueImpl (this, value, pos);
524 static MonoArray *
525 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
527 MonoClass *aklass, *klass;
528 MonoArray *array;
529 uintptr_t *sizes, i;
530 gboolean bounded = FALSE;
532 MONO_ARCH_SAVE_REGS;
534 MONO_CHECK_ARG_NULL (type);
535 MONO_CHECK_ARG_NULL (lengths);
537 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
538 if (bounds)
539 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
541 for (i = 0; i < mono_array_length (lengths); i++)
542 if (mono_array_get (lengths, gint32, i) < 0)
543 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
545 klass = mono_class_from_mono_type (type->type);
546 mono_class_init_or_throw (klass);
548 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
549 /* vectors are not the same as one dimensional arrays with no-zero bounds */
550 bounded = TRUE;
551 else
552 bounded = FALSE;
554 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
556 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
557 for (i = 0; i < aklass->rank; ++i) {
558 sizes [i] = mono_array_get (lengths, guint32, i);
559 if (bounds)
560 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
561 else
562 sizes [i + aklass->rank] = 0;
565 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
567 return array;
570 static MonoArray *
571 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
573 MonoClass *aklass, *klass;
574 MonoArray *array;
575 uintptr_t *sizes, i;
576 gboolean bounded = FALSE;
578 MONO_ARCH_SAVE_REGS;
580 MONO_CHECK_ARG_NULL (type);
581 MONO_CHECK_ARG_NULL (lengths);
583 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
584 if (bounds)
585 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
587 for (i = 0; i < mono_array_length (lengths); i++)
588 if ((mono_array_get (lengths, gint64, i) < 0) ||
589 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
590 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
592 klass = mono_class_from_mono_type (type->type);
593 mono_class_init_or_throw (klass);
595 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
596 /* vectors are not the same as one dimensional arrays with no-zero bounds */
597 bounded = TRUE;
598 else
599 bounded = FALSE;
601 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
603 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
604 for (i = 0; i < aklass->rank; ++i) {
605 sizes [i] = mono_array_get (lengths, guint64, i);
606 if (bounds)
607 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
608 else
609 sizes [i + aklass->rank] = 0;
612 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
614 return array;
617 static gint32
618 ves_icall_System_Array_GetRank (MonoObject *this)
620 MONO_ARCH_SAVE_REGS;
622 return this->vtable->klass->rank;
625 static gint32
626 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
628 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
629 uintptr_t length;
631 MONO_ARCH_SAVE_REGS;
633 if ((dimension < 0) || (dimension >= rank))
634 mono_raise_exception (mono_get_exception_index_out_of_range ());
636 if (this->bounds == NULL)
637 length = this->max_length;
638 else
639 length = this->bounds [dimension].length;
641 #ifdef MONO_BIG_ARRAYS
642 if (length > G_MAXINT32)
643 mono_raise_exception (mono_get_exception_overflow ());
644 #endif
645 return length;
648 static gint64
649 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
651 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
653 MONO_ARCH_SAVE_REGS;
655 if ((dimension < 0) || (dimension >= rank))
656 mono_raise_exception (mono_get_exception_index_out_of_range ());
658 if (this->bounds == NULL)
659 return this->max_length;
661 return this->bounds [dimension].length;
664 static gint32
665 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
667 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
669 MONO_ARCH_SAVE_REGS;
671 if ((dimension < 0) || (dimension >= rank))
672 mono_raise_exception (mono_get_exception_index_out_of_range ());
674 if (this->bounds == NULL)
675 return 0;
677 return this->bounds [dimension].lower_bound;
680 static void
681 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
683 int sz = mono_array_element_size (mono_object_class (arr));
684 mono_gc_bzero (mono_array_addr_with_size (arr, sz, idx), length * sz);
687 static gboolean
688 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
690 int element_size;
691 void * dest_addr;
692 void * source_addr;
693 MonoClass *src_class;
694 MonoClass *dest_class;
696 MONO_ARCH_SAVE_REGS;
698 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
699 return FALSE;
701 if (source->bounds || dest->bounds)
702 return FALSE;
704 /* there's no integer overflow since mono_array_length returns an unsigned integer */
705 if ((dest_idx + length > mono_array_length (dest)) ||
706 (source_idx + length > mono_array_length (source)))
707 return FALSE;
709 src_class = source->obj.vtable->klass->element_class;
710 dest_class = dest->obj.vtable->klass->element_class;
713 * Handle common cases.
716 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
717 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
718 // FIXME: This is racy
719 return FALSE;
721 int i;
722 int has_refs = dest_class->has_references;
723 for (i = source_idx; i < source_idx + length; ++i) {
724 MonoObject *elem = mono_array_get (source, MonoObject*, i);
725 if (elem && !mono_object_isinst (elem, dest_class))
726 return FALSE;
729 element_size = mono_array_element_size (dest->obj.vtable->klass);
730 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
731 for (i = 0; i < length; ++i) {
732 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
733 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
734 if (!elem)
735 continue;
736 if (has_refs)
737 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
738 else
739 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
741 return TRUE;
745 /* Check if we're copying a char[] <==> (u)short[] */
746 if (src_class != dest_class) {
747 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
748 return FALSE;
750 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
752 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
753 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE)) {
754 // FIXME: This is racy
755 return FALSE;
757 int i;
758 for (i = source_idx; i < source_idx + length; ++i) {
759 MonoObject *elem = mono_array_get (source, MonoObject*, i);
760 if (elem && !mono_object_isinst (elem, dest_class))
761 return FALSE;
764 } else
765 return FALSE;
768 if (dest_class->valuetype) {
769 element_size = mono_array_element_size (source->obj.vtable->klass);
770 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
771 if (dest_class->has_references) {
772 mono_value_copy_array (dest, dest_idx, source_addr, length);
773 } else {
774 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
775 mono_gc_memmove (dest_addr, source_addr, element_size * length);
777 } else {
778 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
781 return TRUE;
784 static void
785 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
787 MonoClass *ac;
788 MonoArray *ao;
789 gint32 esize;
790 gpointer *ea;
792 MONO_ARCH_SAVE_REGS;
794 ao = (MonoArray *)this;
795 ac = (MonoClass *)ao->obj.vtable->klass;
797 esize = mono_array_element_size (ac);
798 ea = (gpointer*)((char*)ao->vector + (pos * esize));
800 mono_gc_memmove (value, ea, esize);
803 static void
804 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
806 MonoClass *ac, *ec;
807 MonoArray *ao;
808 gint32 esize;
809 gpointer *ea;
811 MONO_ARCH_SAVE_REGS;
813 ao = (MonoArray *)this;
814 ac = (MonoClass *)ao->obj.vtable->klass;
815 ec = ac->element_class;
817 esize = mono_array_element_size (ac);
818 ea = (gpointer*)((char*)ao->vector + (pos * esize));
820 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
821 g_assert (esize == sizeof (gpointer));
822 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
823 } else {
824 g_assert (ec->inited);
825 g_assert (esize == mono_class_value_size (ec, NULL));
826 if (ec->has_references)
827 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
828 else
829 mono_gc_memmove (ea, value, esize);
833 static void
834 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
836 MonoClass *klass = array->obj.vtable->klass;
837 guint32 size = mono_array_element_size (klass);
838 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
839 int align;
840 const char *field_data;
842 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
843 MonoException *exc = mono_get_exception_argument("array",
844 "Cannot initialize array of non-primitive type.");
845 mono_raise_exception (exc);
848 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
849 MonoException *exc = mono_get_exception_argument("field_handle",
850 "Field doesn't have an RVA");
851 mono_raise_exception (exc);
854 size *= array->max_length;
855 field_data = mono_field_get_data (field_handle);
857 if (size > mono_type_size (field_handle->type, &align)) {
858 MonoException *exc = mono_get_exception_argument("field_handle",
859 "Field not large enough to fill array");
860 mono_raise_exception (exc);
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 guint ## n *end = (guint ## n *)((char*)src + size); \
869 for (; src < end; data++, src++) { \
870 *data = read ## n (src); \
874 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
876 switch (type->type) {
877 case MONO_TYPE_CHAR:
878 case MONO_TYPE_I2:
879 case MONO_TYPE_U2:
880 SWAP (16);
881 break;
882 case MONO_TYPE_I4:
883 case MONO_TYPE_U4:
884 case MONO_TYPE_R4:
885 SWAP (32);
886 break;
887 case MONO_TYPE_I8:
888 case MONO_TYPE_U8:
889 case MONO_TYPE_R8:
890 SWAP (64);
891 break;
892 default:
893 memcpy (mono_array_addr (array, char, 0), field_data, size);
894 break;
896 #else
897 memcpy (mono_array_addr (array, char, 0), field_data, size);
898 #ifdef ARM_FPU_FPA
899 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
900 gint i;
901 double tmp;
902 double *data = (double*)mono_array_addr (array, double, 0);
904 for (i = 0; i < size; i++, data++) {
905 readr8 (data, &tmp);
906 *data = tmp;
909 #endif
910 #endif
913 static gint
914 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
916 MONO_ARCH_SAVE_REGS;
918 return offsetof (MonoString, chars);
921 static MonoObject *
922 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
924 MONO_ARCH_SAVE_REGS;
926 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
927 return obj;
928 else
929 return mono_object_clone (obj);
932 static void
933 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
935 MonoClass *klass;
936 MonoVTable *vtable;
938 MONO_CHECK_ARG_NULL (handle);
940 klass = mono_class_from_mono_type (handle);
941 MONO_CHECK_ARG (handle, klass);
943 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
945 /* This will call the type constructor */
946 mono_runtime_class_init (vtable);
949 static void
950 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
952 MONO_ARCH_SAVE_REGS;
954 mono_image_check_for_module_cctor (image);
955 if (image->has_module_cctor) {
956 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
957 /*It's fine to raise the exception here*/
958 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
962 static MonoBoolean
963 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
965 guint8 *stack_addr;
966 guint8 *current;
967 size_t stack_size;
968 /* later make this configurable and per-arch */
969 int min_size = 4096 * 4 * sizeof (void*);
970 mono_thread_get_stack_bounds (&stack_addr, &stack_size);
971 /* if we have no info we are optimistic and assume there is enough room */
972 if (!stack_addr)
973 return TRUE;
974 current = (guint8 *)&stack_addr;
975 if (current > stack_addr) {
976 if ((current - stack_addr) < min_size)
977 return FALSE;
978 } else {
979 if (current - (stack_addr - stack_size) < min_size)
980 return FALSE;
982 return TRUE;
985 static MonoObject *
986 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
988 MONO_ARCH_SAVE_REGS;
990 return mono_object_clone (this);
993 static gint32
994 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
996 MonoClass *klass;
997 MonoObject **values = NULL;
998 MonoObject *o;
999 int count = 0;
1000 gint32 result = 0;
1001 MonoClassField* field;
1002 gpointer iter;
1004 MONO_ARCH_SAVE_REGS;
1006 klass = mono_object_class (this);
1008 if (mono_class_num_fields (klass) == 0)
1009 return mono_object_hash (this);
1012 * Compute the starting value of the hashcode for fields of primitive
1013 * types, and return the remaining fields in an array to the managed side.
1014 * This way, we can avoid costly reflection operations in managed code.
1016 iter = NULL;
1017 while ((field = mono_class_get_fields (klass, &iter))) {
1018 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1019 continue;
1020 if (mono_field_is_deleted (field))
1021 continue;
1022 /* FIXME: Add more types */
1023 switch (field->type->type) {
1024 case MONO_TYPE_I4:
1025 result ^= *(gint32*)((guint8*)this + field->offset);
1026 break;
1027 case MONO_TYPE_STRING: {
1028 MonoString *s;
1029 s = *(MonoString**)((guint8*)this + field->offset);
1030 if (s != NULL)
1031 result ^= mono_string_hash (s);
1032 break;
1034 default:
1035 if (!values)
1036 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1037 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1038 values [count++] = o;
1042 if (values) {
1043 int i;
1044 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1045 for (i = 0; i < count; ++i)
1046 mono_array_setref (*fields, i, values [i]);
1047 } else {
1048 *fields = NULL;
1050 return result;
1053 static MonoBoolean
1054 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1056 MonoClass *klass;
1057 MonoObject **values = NULL;
1058 MonoObject *o;
1059 MonoClassField* field;
1060 gpointer iter;
1061 int count = 0;
1063 MONO_ARCH_SAVE_REGS;
1065 MONO_CHECK_ARG_NULL (that);
1067 if (this->vtable != that->vtable)
1068 return FALSE;
1070 klass = mono_object_class (this);
1072 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1073 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1076 * Do the comparison for fields of primitive type and return a result if
1077 * possible. Otherwise, return the remaining fields in an array to the
1078 * managed side. This way, we can avoid costly reflection operations in
1079 * managed code.
1081 *fields = NULL;
1082 iter = NULL;
1083 while ((field = mono_class_get_fields (klass, &iter))) {
1084 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1085 continue;
1086 if (mono_field_is_deleted (field))
1087 continue;
1088 /* FIXME: Add more types */
1089 switch (field->type->type) {
1090 case MONO_TYPE_U1:
1091 case MONO_TYPE_I1:
1092 case MONO_TYPE_BOOLEAN:
1093 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1094 return FALSE;
1095 break;
1096 case MONO_TYPE_U2:
1097 case MONO_TYPE_I2:
1098 case MONO_TYPE_CHAR:
1099 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1100 return FALSE;
1101 break;
1102 case MONO_TYPE_U4:
1103 case MONO_TYPE_I4:
1104 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1105 return FALSE;
1106 break;
1107 case MONO_TYPE_U8:
1108 case MONO_TYPE_I8:
1109 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1110 return FALSE;
1111 break;
1112 case MONO_TYPE_R4:
1113 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1114 return FALSE;
1115 break;
1116 case MONO_TYPE_R8:
1117 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1118 return FALSE;
1119 break;
1122 case MONO_TYPE_STRING: {
1123 MonoString *s1, *s2;
1124 guint32 s1len, s2len;
1125 s1 = *(MonoString**)((guint8*)this + field->offset);
1126 s2 = *(MonoString**)((guint8*)that + field->offset);
1127 if (s1 == s2)
1128 break;
1129 if ((s1 == NULL) || (s2 == NULL))
1130 return FALSE;
1131 s1len = mono_string_length (s1);
1132 s2len = mono_string_length (s2);
1133 if (s1len != s2len)
1134 return FALSE;
1136 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1137 return FALSE;
1138 break;
1140 default:
1141 if (!values)
1142 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1143 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1144 values [count++] = o;
1145 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1146 values [count++] = o;
1149 if (klass->enumtype)
1150 /* enums only have one non-static field */
1151 break;
1154 if (values) {
1155 int i;
1156 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1157 for (i = 0; i < count; ++i)
1158 mono_array_setref (*fields, i, values [i]);
1159 return FALSE;
1160 } else {
1161 return TRUE;
1165 static MonoReflectionType *
1166 ves_icall_System_Object_GetType (MonoObject *obj)
1168 MONO_ARCH_SAVE_REGS;
1170 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1171 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1172 else
1173 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1176 static void
1177 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1179 MONO_ARCH_SAVE_REGS;
1181 mtype->type = &obj->vtable->klass->byval_arg;
1182 g_assert (mtype->type->type);
1185 static gint32
1186 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1188 MONO_ARCH_SAVE_REGS;
1190 MONO_CHECK_ARG_NULL (obj);
1192 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1195 static gint32
1196 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1197 MonoReflectionMethod *method,
1198 MonoArray *opt_param_types)
1200 MONO_ARCH_SAVE_REGS;
1202 MONO_CHECK_ARG_NULL (method);
1204 return mono_image_create_method_token (
1205 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1208 static void
1209 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1211 MONO_ARCH_SAVE_REGS;
1213 mono_image_create_pefile (mb, file);
1216 static void
1217 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1219 MONO_ARCH_SAVE_REGS;
1221 mono_image_build_metadata (mb);
1224 static void
1225 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1227 MONO_ARCH_SAVE_REGS;
1229 mono_image_register_token (mb->dynamic_image, token, obj);
1232 static gboolean
1233 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1235 MonoMethod **dest = data;
1237 /* skip unmanaged frames */
1238 if (!managed)
1239 return FALSE;
1241 if (m == *dest) {
1242 *dest = NULL;
1243 return FALSE;
1245 if (!(*dest)) {
1246 *dest = m;
1247 return TRUE;
1249 return FALSE;
1252 static gboolean
1253 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1255 MonoMethod **dest = data;
1257 /* skip unmanaged frames */
1258 if (!managed)
1259 return FALSE;
1261 if (!(*dest)) {
1262 if (!strcmp (m->klass->name_space, "System.Reflection"))
1263 return FALSE;
1264 *dest = m;
1265 return TRUE;
1267 return FALSE;
1270 static gboolean
1271 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1273 MonoMethod **dest = data;
1275 /* skip unmanaged frames */
1276 if (!managed)
1277 return FALSE;
1279 if (m->wrapper_type != MONO_WRAPPER_NONE)
1280 return FALSE;
1282 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1283 return FALSE;
1285 if (m == *dest) {
1286 *dest = NULL;
1287 return FALSE;
1289 if (!(*dest)) {
1290 *dest = m;
1291 return TRUE;
1293 return FALSE;
1296 static MonoReflectionType *
1297 type_from_name (const char *str, MonoBoolean ignoreCase)
1299 MonoType *type = NULL;
1300 MonoAssembly *assembly = NULL;
1301 MonoTypeNameParse info;
1302 char *temp_str = g_strdup (str);
1303 gboolean type_resolve = FALSE;
1305 MONO_ARCH_SAVE_REGS;
1307 /* mono_reflection_parse_type() mangles the string */
1308 if (!mono_reflection_parse_type (temp_str, &info)) {
1309 mono_reflection_free_type_info (&info);
1310 g_free (temp_str);
1311 return NULL;
1314 if (info.assembly.name) {
1315 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1316 } else {
1317 MonoMethod *m = mono_method_get_last_managed ();
1318 MonoMethod *dest = m;
1320 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1321 if (!dest)
1322 dest = m;
1325 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1326 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1327 * to crash. This only seems to happen in some strange remoting
1328 * scenarios and I was unable to figure out what's happening there.
1329 * Dec 10, 2005 - Martin.
1332 if (dest) {
1333 assembly = dest->klass->image->assembly;
1334 type_resolve = TRUE;
1335 } else {
1336 g_warning (G_STRLOC);
1340 if (assembly) {
1341 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1342 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1345 if (!info.assembly.name && !type) /* try mscorlib */
1346 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1348 if (assembly && !type && type_resolve) {
1349 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1350 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1353 mono_reflection_free_type_info (&info);
1354 g_free (temp_str);
1356 if (!type)
1357 return NULL;
1359 return mono_type_get_object (mono_domain_get (), type);
1362 #ifdef UNUSED
1363 MonoReflectionType *
1364 mono_type_get (const char *str)
1366 char *copy = g_strdup (str);
1367 MonoReflectionType *type = type_from_name (copy, FALSE);
1369 g_free (copy);
1370 return type;
1372 #endif
1374 static MonoReflectionType*
1375 ves_icall_type_from_name (MonoString *name,
1376 MonoBoolean throwOnError,
1377 MonoBoolean ignoreCase)
1379 char *str = mono_string_to_utf8 (name);
1380 MonoReflectionType *type;
1382 type = type_from_name (str, ignoreCase);
1383 g_free (str);
1384 if (type == NULL){
1385 MonoException *e = NULL;
1387 if (throwOnError)
1388 e = mono_get_exception_type_load (name, NULL);
1390 mono_loader_clear_error ();
1391 if (e != NULL)
1392 mono_raise_exception (e);
1395 return type;
1399 static MonoReflectionType*
1400 ves_icall_type_from_handle (MonoType *handle)
1402 MonoDomain *domain = mono_domain_get ();
1404 MONO_ARCH_SAVE_REGS;
1406 return mono_type_get_object (domain, handle);
1409 static MonoBoolean
1410 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1412 MONO_ARCH_SAVE_REGS;
1414 if (c && type->type && c->type)
1415 return mono_metadata_type_equal (type->type, c->type);
1416 else
1417 return (type == c) ? TRUE : FALSE;
1420 /* System.TypeCode */
1421 typedef enum {
1422 TYPECODE_EMPTY,
1423 TYPECODE_OBJECT,
1424 TYPECODE_DBNULL,
1425 TYPECODE_BOOLEAN,
1426 TYPECODE_CHAR,
1427 TYPECODE_SBYTE,
1428 TYPECODE_BYTE,
1429 TYPECODE_INT16,
1430 TYPECODE_UINT16,
1431 TYPECODE_INT32,
1432 TYPECODE_UINT32,
1433 TYPECODE_INT64,
1434 TYPECODE_UINT64,
1435 TYPECODE_SINGLE,
1436 TYPECODE_DOUBLE,
1437 TYPECODE_DECIMAL,
1438 TYPECODE_DATETIME,
1439 TYPECODE_STRING = 18
1440 } TypeCode;
1442 static guint32
1443 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1445 int t = type->type->type;
1447 MONO_ARCH_SAVE_REGS;
1449 if (type->type->byref)
1450 return TYPECODE_OBJECT;
1452 handle_enum:
1453 switch (t) {
1454 case MONO_TYPE_VOID:
1455 return TYPECODE_OBJECT;
1456 case MONO_TYPE_BOOLEAN:
1457 return TYPECODE_BOOLEAN;
1458 case MONO_TYPE_U1:
1459 return TYPECODE_BYTE;
1460 case MONO_TYPE_I1:
1461 return TYPECODE_SBYTE;
1462 case MONO_TYPE_U2:
1463 return TYPECODE_UINT16;
1464 case MONO_TYPE_I2:
1465 return TYPECODE_INT16;
1466 case MONO_TYPE_CHAR:
1467 return TYPECODE_CHAR;
1468 case MONO_TYPE_PTR:
1469 case MONO_TYPE_U:
1470 case MONO_TYPE_I:
1471 return TYPECODE_OBJECT;
1472 case MONO_TYPE_U4:
1473 return TYPECODE_UINT32;
1474 case MONO_TYPE_I4:
1475 return TYPECODE_INT32;
1476 case MONO_TYPE_U8:
1477 return TYPECODE_UINT64;
1478 case MONO_TYPE_I8:
1479 return TYPECODE_INT64;
1480 case MONO_TYPE_R4:
1481 return TYPECODE_SINGLE;
1482 case MONO_TYPE_R8:
1483 return TYPECODE_DOUBLE;
1484 case MONO_TYPE_VALUETYPE: {
1485 MonoClass *klass = type->type->data.klass;
1487 if (klass->enumtype) {
1488 t = mono_class_enum_basetype (klass)->type;
1489 goto handle_enum;
1490 } else if (mono_is_corlib_image (klass->image)) {
1491 if (strcmp (klass->name_space, "System") == 0) {
1492 if (strcmp (klass->name, "Decimal") == 0)
1493 return TYPECODE_DECIMAL;
1494 else if (strcmp (klass->name, "DateTime") == 0)
1495 return TYPECODE_DATETIME;
1498 return TYPECODE_OBJECT;
1500 case MONO_TYPE_STRING:
1501 return TYPECODE_STRING;
1502 case MONO_TYPE_SZARRAY:
1503 case MONO_TYPE_ARRAY:
1504 case MONO_TYPE_OBJECT:
1505 case MONO_TYPE_VAR:
1506 case MONO_TYPE_MVAR:
1507 case MONO_TYPE_TYPEDBYREF:
1508 return TYPECODE_OBJECT;
1509 case MONO_TYPE_CLASS:
1511 MonoClass *klass = type->type->data.klass;
1512 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1513 if (strcmp (klass->name, "DBNull") == 0)
1514 return TYPECODE_DBNULL;
1517 return TYPECODE_OBJECT;
1518 case MONO_TYPE_GENERICINST:
1519 return TYPECODE_OBJECT;
1520 default:
1521 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1523 return 0;
1526 static guint32
1527 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1529 MonoDomain *domain;
1530 MonoClass *klass;
1531 MonoClass *klassc;
1533 MONO_ARCH_SAVE_REGS;
1535 g_assert (type != NULL);
1537 domain = ((MonoObject *)type)->vtable->domain;
1539 if (!c) /* FIXME: dont know what do do here */
1540 return 0;
1542 klass = mono_class_from_mono_type (type->type);
1543 klassc = mono_class_from_mono_type (c->type);
1545 /* Interface check requires a more complex setup so we
1546 * only do for them. Otherwise we simply avoid mono_class_init.
1548 if (check_interfaces) {
1549 mono_class_init_or_throw (klass);
1550 mono_class_init_or_throw (klassc);
1551 } else if (!klass->supertypes || !klassc->supertypes) {
1552 mono_loader_lock ();
1553 mono_class_setup_supertypes (klass);
1554 mono_class_setup_supertypes (klassc);
1555 mono_loader_unlock ();
1558 if (type->type->byref)
1559 return klassc == mono_defaults.object_class;
1561 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1564 static gboolean
1565 mono_type_is_primitive (MonoType *type)
1567 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1568 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1571 static MonoType*
1572 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1574 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1575 return mono_class_enum_basetype (type->data.klass);
1576 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1577 return mono_class_enum_basetype (type->data.generic_class->container_class);
1578 return type;
1581 static guint32
1582 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1584 MonoDomain *domain;
1585 MonoClass *klass;
1586 MonoClass *klassc;
1588 MONO_ARCH_SAVE_REGS;
1590 g_assert (type != NULL);
1592 domain = ((MonoObject *)type)->vtable->domain;
1594 klass = mono_class_from_mono_type (type->type);
1595 klassc = mono_class_from_mono_type (c->type);
1597 mono_class_init_or_throw (klass);
1598 mono_class_init_or_throw (klassc);
1600 if (type->type->byref ^ c->type->byref)
1601 return FALSE;
1603 if (type->type->byref) {
1604 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1605 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1607 klass = mono_class_from_mono_type (t);
1608 klassc = mono_class_from_mono_type (ot);
1610 if (mono_type_is_primitive (t)) {
1611 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1612 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1613 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1614 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1615 return t->type == ot->type;
1616 } else {
1617 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1618 return FALSE;
1620 if (klass->valuetype)
1621 return klass == klassc;
1622 return klass->valuetype == klassc->valuetype;
1625 return mono_class_is_assignable_from (klass, klassc);
1628 static guint32
1629 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1631 MonoClass *klass = mono_class_from_mono_type (type->type);
1632 mono_class_init_or_throw (klass);
1633 return mono_object_isinst (obj, klass) != NULL;
1636 static guint32
1637 ves_icall_get_attributes (MonoReflectionType *type)
1639 MonoClass *klass = mono_class_from_mono_type (type->type);
1640 return klass->flags;
1643 static MonoReflectionMarshalAsAttribute*
1644 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1646 MonoClass *klass = field->field->parent;
1647 MonoMarshalType *info;
1648 int i;
1650 if (klass->generic_container ||
1651 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1652 return NULL;
1654 info = mono_marshal_load_type_info (klass);
1656 for (i = 0; i < info->num_fields; ++i) {
1657 if (info->fields [i].field == field->field) {
1658 if (!info->fields [i].mspec)
1659 return NULL;
1660 else
1661 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1665 return NULL;
1668 static MonoReflectionField*
1669 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1671 gboolean found = FALSE;
1672 MonoClass *klass;
1673 MonoClass *k;
1675 g_assert (handle);
1677 if (!type) {
1678 klass = handle->parent;
1679 } else {
1680 klass = mono_class_from_mono_type (type);
1682 /* Check that the field belongs to the class */
1683 for (k = klass; k; k = k->parent) {
1684 if (k == handle->parent) {
1685 found = TRUE;
1686 break;
1690 if (!found)
1691 /* The managed code will throw the exception */
1692 return NULL;
1695 return mono_field_get_object (mono_domain_get (), klass, handle);
1698 static MonoArray*
1699 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1701 MonoError error;
1702 MonoType *type = mono_field_get_type_checked (field->field, &error);
1703 if (!mono_error_ok (&error))
1704 mono_error_raise_exception (&error);
1706 return type_array_from_modifiers (field->field->parent->image, type, optional);
1709 static int
1710 vell_icall_get_method_attributes (MonoMethod *method)
1712 return method->flags;
1715 static void
1716 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1718 MonoError error;
1719 MonoDomain *domain = mono_domain_get ();
1720 MonoMethodSignature* sig;
1721 MONO_ARCH_SAVE_REGS;
1723 sig = mono_method_signature_checked (method, &error);
1724 if (!mono_error_ok (&error))
1725 mono_error_raise_exception (&error);
1728 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1729 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1730 info->attrs = method->flags;
1731 info->implattrs = method->iflags;
1732 if (sig->call_convention == MONO_CALL_DEFAULT)
1733 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1734 else {
1735 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1736 info->callconv = 2;
1737 else
1738 info->callconv = 1;
1740 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1743 static MonoArray*
1744 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1746 MonoDomain *domain = mono_domain_get ();
1748 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1751 static MonoReflectionMarshalAsAttribute*
1752 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1754 MonoDomain *domain = mono_domain_get ();
1755 MonoReflectionMarshalAsAttribute* res = NULL;
1756 MonoMarshalSpec **mspecs;
1757 int i;
1759 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1760 mono_method_get_marshal_info (method, mspecs);
1762 if (mspecs [0])
1763 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1765 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1766 if (mspecs [i])
1767 mono_metadata_free_marshal_spec (mspecs [i]);
1768 g_free (mspecs);
1770 return res;
1773 static gint32
1774 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1776 MonoClass *parent = field->field->parent;
1777 if (!parent->size_inited)
1778 mono_class_init (parent);
1780 return field->field->offset - sizeof (MonoObject);
1783 static MonoReflectionType*
1784 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1786 MonoClass *parent;
1787 MONO_ARCH_SAVE_REGS;
1789 parent = declaring? field->field->parent: field->klass;
1791 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1794 static MonoObject *
1795 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1797 MonoClass *fklass = field->klass;
1798 MonoClassField *cf = field->field;
1799 MonoDomain *domain = mono_object_domain (field);
1801 if (fklass->image->assembly->ref_only)
1802 mono_raise_exception (mono_get_exception_invalid_operation (
1803 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1805 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1806 mono_security_core_clr_ensure_reflection_access_field (cf);
1808 return mono_field_get_value_object (domain, cf, obj);
1811 static void
1812 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1814 MonoError error;
1815 MonoClassField *cf = field->field;
1816 MonoType *type;
1817 gchar *v;
1819 MONO_ARCH_SAVE_REGS;
1821 if (field->klass->image->assembly->ref_only)
1822 mono_raise_exception (mono_get_exception_invalid_operation (
1823 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1825 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1826 mono_security_core_clr_ensure_reflection_access_field (cf);
1828 type = mono_field_get_type_checked (cf, &error);
1829 if (!mono_error_ok (&error))
1830 mono_error_raise_exception (&error);
1832 v = (gchar *) value;
1833 if (!type->byref) {
1834 switch (type->type) {
1835 case MONO_TYPE_U1:
1836 case MONO_TYPE_I1:
1837 case MONO_TYPE_BOOLEAN:
1838 case MONO_TYPE_U2:
1839 case MONO_TYPE_I2:
1840 case MONO_TYPE_CHAR:
1841 case MONO_TYPE_U:
1842 case MONO_TYPE_I:
1843 case MONO_TYPE_U4:
1844 case MONO_TYPE_I4:
1845 case MONO_TYPE_R4:
1846 case MONO_TYPE_U8:
1847 case MONO_TYPE_I8:
1848 case MONO_TYPE_R8:
1849 case MONO_TYPE_VALUETYPE:
1850 case MONO_TYPE_PTR:
1851 if (v != NULL)
1852 v += sizeof (MonoObject);
1853 break;
1854 case MONO_TYPE_STRING:
1855 case MONO_TYPE_OBJECT:
1856 case MONO_TYPE_CLASS:
1857 case MONO_TYPE_ARRAY:
1858 case MONO_TYPE_SZARRAY:
1859 /* Do nothing */
1860 break;
1861 case MONO_TYPE_GENERICINST: {
1862 MonoGenericClass *gclass = type->data.generic_class;
1863 g_assert (!gclass->context.class_inst->is_open);
1865 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1866 MonoClass *nklass = mono_class_from_mono_type (type);
1867 MonoObject *nullable;
1870 * Convert the boxed vtype into a Nullable structure.
1871 * This is complicated by the fact that Nullables have
1872 * a variable structure.
1874 nullable = mono_object_new (mono_domain_get (), nklass);
1876 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1878 v = mono_object_unbox (nullable);
1880 else
1881 if (gclass->container_class->valuetype && (v != NULL))
1882 v += sizeof (MonoObject);
1883 break;
1885 default:
1886 g_error ("type 0x%x not handled in "
1887 "ves_icall_FieldInfo_SetValueInternal", type->type);
1888 return;
1892 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1893 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1894 if (!vtable->initialized)
1895 mono_runtime_class_init (vtable);
1896 mono_field_static_set_value (vtable, cf, v);
1897 } else {
1898 mono_field_set_value (obj, cf, v);
1902 static MonoObject *
1903 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1905 MonoObject *o = NULL;
1906 MonoClassField *field = this->field;
1907 MonoClass *klass;
1908 MonoDomain *domain = mono_object_domain (this);
1909 gchar *v;
1910 MonoTypeEnum def_type;
1911 const char *def_value;
1912 MonoType *t;
1913 MonoError error;
1915 MONO_ARCH_SAVE_REGS;
1917 mono_class_init (field->parent);
1919 t = mono_field_get_type_checked (field, &error);
1920 if (!mono_error_ok (&error))
1921 mono_error_raise_exception (&error);
1923 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1924 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1926 if (field->parent->image->dynamic) {
1927 /* FIXME: */
1928 g_assert_not_reached ();
1931 def_value = mono_class_get_field_default_value (field, &def_type);
1933 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1934 switch (def_type) {
1935 case MONO_TYPE_U1:
1936 case MONO_TYPE_I1:
1937 case MONO_TYPE_BOOLEAN:
1938 case MONO_TYPE_U2:
1939 case MONO_TYPE_I2:
1940 case MONO_TYPE_CHAR:
1941 case MONO_TYPE_U:
1942 case MONO_TYPE_I:
1943 case MONO_TYPE_U4:
1944 case MONO_TYPE_I4:
1945 case MONO_TYPE_R4:
1946 case MONO_TYPE_U8:
1947 case MONO_TYPE_I8:
1948 case MONO_TYPE_R8: {
1949 MonoType *t;
1951 /* boxed value type */
1952 t = g_new0 (MonoType, 1);
1953 t->type = def_type;
1954 klass = mono_class_from_mono_type (t);
1955 g_free (t);
1956 o = mono_object_new (domain, klass);
1957 v = ((gchar *) o) + sizeof (MonoObject);
1958 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1959 break;
1961 case MONO_TYPE_STRING:
1962 case MONO_TYPE_CLASS:
1963 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1964 break;
1965 default:
1966 g_assert_not_reached ();
1969 return o;
1972 static MonoReflectionType*
1973 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1975 MonoError error;
1976 MonoClassField *field = ref_field->field;
1977 MonoType *type = mono_field_get_type_checked (field, &error);
1978 if (!mono_error_ok (&error))
1979 mono_error_raise_exception (&error);
1980 return mono_type_get_object (mono_object_domain (ref_field), type);
1983 static MonoReflectionType*
1984 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1986 MonoMethod *method = rmethod->method.method;
1988 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1991 /* From MonoProperty.cs */
1992 typedef enum {
1993 PInfo_Attributes = 1,
1994 PInfo_GetMethod = 1 << 1,
1995 PInfo_SetMethod = 1 << 2,
1996 PInfo_ReflectedType = 1 << 3,
1997 PInfo_DeclaringType = 1 << 4,
1998 PInfo_Name = 1 << 5
1999 } PInfo;
2001 static void
2002 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2004 MonoDomain *domain = mono_object_domain (property);
2006 MONO_ARCH_SAVE_REGS;
2008 if ((req_info & PInfo_ReflectedType) != 0)
2009 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
2010 if ((req_info & PInfo_DeclaringType) != 0)
2011 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
2013 if ((req_info & PInfo_Name) != 0)
2014 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2016 if ((req_info & PInfo_Attributes) != 0)
2017 info->attrs = property->property->attrs;
2019 if ((req_info & PInfo_GetMethod) != 0)
2020 MONO_STRUCT_SETREF (info, get, property->property->get ?
2021 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2023 if ((req_info & PInfo_SetMethod) != 0)
2024 MONO_STRUCT_SETREF (info, set, property->property->set ?
2025 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2027 * There may be other methods defined for properties, though, it seems they are not exposed
2028 * in the reflection API
2032 static void
2033 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2035 MonoDomain *domain = mono_object_domain (event);
2037 MONO_ARCH_SAVE_REGS;
2039 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2040 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2042 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2043 info->attrs = event->event->attrs;
2044 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2045 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2046 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2048 #ifndef MONO_SMALL_CONFIG
2049 if (event->event->other) {
2050 int i, n = 0;
2051 while (event->event->other [n])
2052 n++;
2053 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2055 for (i = 0; i < n; i++)
2056 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2058 #endif
2061 static void
2062 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2064 int i;
2065 MonoClass *ic;
2067 mono_class_setup_interfaces (klass, error);
2068 if (!mono_error_ok (error))
2069 return;
2071 for (i = 0; i < klass->interface_count; i++) {
2072 ic = klass->interfaces [i];
2073 g_hash_table_insert (ifaces, ic, ic);
2075 collect_interfaces (ic, ifaces, error);
2076 if (!mono_error_ok (error))
2077 return;
2081 typedef struct {
2082 MonoArray *iface_array;
2083 MonoGenericContext *context;
2084 MonoError *error;
2085 MonoDomain *domain;
2086 int next_idx;
2087 } FillIfaceArrayData;
2089 static void
2090 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2092 FillIfaceArrayData *data = user_data;
2093 MonoClass *ic = key;
2094 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2096 if (!mono_error_ok (data->error))
2097 return;
2099 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2100 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2101 if (!mono_error_ok (data->error))
2102 return;
2105 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2107 if (inflated)
2108 mono_metadata_free_type (inflated);
2111 static MonoArray*
2112 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2114 MonoError error;
2115 MonoClass *class = mono_class_from_mono_type (type->type);
2116 MonoClass *parent;
2117 FillIfaceArrayData data = { 0 };
2118 int len;
2120 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2122 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2123 data.context = mono_class_get_context (class);
2124 class = class->generic_class->container_class;
2127 for (parent = class; parent; parent = parent->parent) {
2128 mono_class_setup_interfaces (parent, &error);
2129 if (!mono_error_ok (&error))
2130 goto fail;
2131 collect_interfaces (parent, iface_hash, &error);
2132 if (!mono_error_ok (&error))
2133 goto fail;
2136 data.error = &error;
2137 data.domain = mono_object_domain (type);
2139 len = g_hash_table_size (iface_hash);
2140 if (len == 0) {
2141 g_hash_table_destroy (iface_hash);
2142 if (!data.domain->empty_types)
2143 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2144 return data.domain->empty_types;
2147 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2148 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2149 if (!mono_error_ok (&error))
2150 goto fail;
2152 g_hash_table_destroy (iface_hash);
2153 return data.iface_array;
2155 fail:
2156 g_hash_table_destroy (iface_hash);
2157 mono_error_raise_exception (&error);
2158 return NULL;
2161 static void
2162 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2164 gboolean variance_used;
2165 MonoClass *class = mono_class_from_mono_type (type->type);
2166 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2167 MonoReflectionMethod *member;
2168 MonoMethod* method;
2169 gpointer iter;
2170 int i = 0, len, ioffset;
2171 MonoDomain *domain;
2173 MONO_ARCH_SAVE_REGS;
2174 mono_class_init_or_throw (class);
2175 mono_class_init_or_throw (iclass);
2177 mono_class_setup_vtable (class);
2179 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2180 if (ioffset == -1)
2181 return;
2183 len = mono_class_num_methods (iclass);
2184 domain = mono_object_domain (type);
2185 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2186 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2187 iter = NULL;
2188 while ((method = mono_class_get_methods (iclass, &iter))) {
2189 member = mono_method_get_object (domain, method, iclass);
2190 mono_array_setref (*methods, i, member);
2191 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2192 mono_array_setref (*targets, i, member);
2194 i ++;
2198 static void
2199 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2201 MonoClass *klass = mono_class_from_mono_type (type->type);
2202 mono_class_init_or_throw (klass);
2204 if (klass->image->dynamic) {
2205 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2206 *packing = tb->packing_size;
2207 *size = tb->class_size;
2208 } else {
2209 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2213 static MonoReflectionType*
2214 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2216 MonoClass *class;
2218 MONO_ARCH_SAVE_REGS;
2220 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2221 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2223 class = mono_class_from_mono_type (type->type);
2224 mono_class_init_or_throw (class);
2226 // GetElementType should only return a type for:
2227 // Array Pointer PassedByRef
2228 if (type->type->byref)
2229 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2230 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2231 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2232 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2233 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2234 else
2235 return NULL;
2238 static MonoReflectionType*
2239 ves_icall_get_type_parent (MonoReflectionType *type)
2241 MonoClass *class = mono_class_from_mono_type (type->type);
2242 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2245 static MonoBoolean
2246 ves_icall_type_ispointer (MonoReflectionType *type)
2248 MONO_ARCH_SAVE_REGS;
2250 return type->type->type == MONO_TYPE_PTR;
2253 static MonoBoolean
2254 ves_icall_type_isprimitive (MonoReflectionType *type)
2256 MONO_ARCH_SAVE_REGS;
2258 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)));
2261 static MonoBoolean
2262 ves_icall_type_isbyref (MonoReflectionType *type)
2264 MONO_ARCH_SAVE_REGS;
2266 return type->type->byref;
2269 static MonoBoolean
2270 ves_icall_type_iscomobject (MonoReflectionType *type)
2272 MonoClass *klass = mono_class_from_mono_type (type->type);
2273 mono_class_init_or_throw (klass);
2275 return (klass && klass->is_com_object);
2278 static MonoReflectionModule*
2279 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2281 MonoClass *class = mono_class_from_mono_type (type->type);
2282 return mono_module_get_object (mono_object_domain (type), class->image);
2285 static MonoReflectionAssembly*
2286 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2288 MonoDomain *domain = mono_domain_get ();
2289 MonoClass *class = mono_class_from_mono_type (type->type);
2290 return mono_assembly_get_object (domain, class->image->assembly);
2293 static MonoReflectionType*
2294 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2296 MonoDomain *domain = mono_domain_get ();
2297 MonoClass *class;
2299 MONO_ARCH_SAVE_REGS;
2301 if (type->type->byref)
2302 return NULL;
2303 if (type->type->type == MONO_TYPE_VAR)
2304 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2305 else if (type->type->type == MONO_TYPE_MVAR)
2306 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2307 else
2308 class = mono_class_from_mono_type (type->type)->nested_in;
2310 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2313 static MonoString*
2314 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2316 MonoDomain *domain = mono_domain_get ();
2317 MonoClass *class = mono_class_from_mono_type (type->type);
2319 if (type->type->byref) {
2320 char *n = g_strdup_printf ("%s&", class->name);
2321 MonoString *res = mono_string_new (domain, n);
2323 g_free (n);
2325 return res;
2326 } else {
2327 return mono_string_new (domain, class->name);
2331 static MonoString*
2332 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2334 MonoDomain *domain = mono_domain_get ();
2335 MonoClass *class = mono_class_from_mono_type (type->type);
2337 while (class->nested_in)
2338 class = class->nested_in;
2340 if (class->name_space [0] == '\0')
2341 return NULL;
2342 else
2343 return mono_string_new (domain, class->name_space);
2346 static gint32
2347 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2349 MonoClass *class;
2351 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2352 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2354 class = mono_class_from_mono_type (type->type);
2356 return class->rank;
2359 static MonoArray*
2360 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2362 MonoArray *res;
2363 MonoClass *klass, *pklass;
2364 MonoDomain *domain = mono_object_domain (type);
2365 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2366 int i;
2367 MONO_ARCH_SAVE_REGS;
2369 klass = mono_class_from_mono_type (type->type);
2371 if (klass->generic_container) {
2372 MonoGenericContainer *container = klass->generic_container;
2373 res = mono_array_new_specific (array_vtable, container->type_argc);
2374 for (i = 0; i < container->type_argc; ++i) {
2375 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2376 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2378 } else if (klass->generic_class) {
2379 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2380 res = mono_array_new_specific (array_vtable, inst->type_argc);
2381 for (i = 0; i < inst->type_argc; ++i)
2382 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2383 } else {
2384 res = mono_array_new_specific (array_vtable, 0);
2386 return res;
2389 static gboolean
2390 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2392 MonoClass *klass;
2393 MONO_ARCH_SAVE_REGS;
2395 if (!IS_MONOTYPE (type))
2396 return FALSE;
2398 if (type->type->byref)
2399 return FALSE;
2401 klass = mono_class_from_mono_type (type->type);
2402 return klass->generic_container != NULL;
2405 static MonoReflectionType*
2406 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2408 MonoClass *klass;
2409 MONO_ARCH_SAVE_REGS;
2411 if (type->type->byref)
2412 return NULL;
2414 klass = mono_class_from_mono_type (type->type);
2416 if (klass->generic_container) {
2417 return type; /* check this one */
2419 if (klass->generic_class) {
2420 MonoClass *generic_class = klass->generic_class->container_class;
2421 gpointer tb;
2423 tb = mono_class_get_ref_info (generic_class);
2425 if (generic_class->wastypebuilder && tb)
2426 return tb;
2427 else
2428 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2430 return NULL;
2433 static MonoReflectionType*
2434 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2436 MonoClass *class;
2437 MonoType *geninst, **types;
2438 int i, count;
2440 g_assert (IS_MONOTYPE (type));
2441 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2443 count = mono_array_length (type_array);
2444 types = g_new0 (MonoType *, count);
2446 for (i = 0; i < count; i++) {
2447 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2448 types [i] = t->type;
2451 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2452 g_free (types);
2453 if (!geninst)
2454 return NULL;
2456 class = mono_class_from_mono_type (geninst);
2458 /*we might inflate to the GTD*/
2459 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2460 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2462 return mono_type_get_object (mono_object_domain (type), geninst);
2465 static gboolean
2466 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2468 MonoClass *klass;
2469 MONO_ARCH_SAVE_REGS;
2471 if (type->type->byref)
2472 return FALSE;
2474 klass = mono_class_from_mono_type (type->type);
2476 return klass->generic_class != NULL;
2479 static gboolean
2480 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2482 MonoClass *klass;
2483 MONO_ARCH_SAVE_REGS;
2485 if (!IS_MONOTYPE (type))
2486 return FALSE;
2488 if (type->type->byref)
2489 return FALSE;
2491 klass = mono_class_from_mono_type (type->type);
2492 return klass->generic_class != NULL || klass->generic_container != NULL;
2495 static gint32
2496 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2498 MONO_ARCH_SAVE_REGS;
2500 if (!IS_MONOTYPE (type))
2501 return -1;
2503 if (is_generic_parameter (type->type))
2504 return mono_type_get_generic_param_num (type->type);
2505 return -1;
2508 static GenericParameterAttributes
2509 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2511 MONO_ARCH_SAVE_REGS;
2513 g_assert (IS_MONOTYPE (type));
2514 g_assert (is_generic_parameter (type->type));
2515 return mono_generic_param_info (type->type->data.generic_param)->flags;
2518 static MonoArray *
2519 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2521 MonoGenericParamInfo *param_info;
2522 MonoDomain *domain;
2523 MonoClass **ptr;
2524 MonoArray *res;
2525 int i, count;
2527 MONO_ARCH_SAVE_REGS;
2529 g_assert (IS_MONOTYPE (type));
2531 domain = mono_object_domain (type);
2532 param_info = mono_generic_param_info (type->type->data.generic_param);
2533 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2536 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2537 for (i = 0; i < count; i++)
2538 mono_array_setref (res, i, mono_type_get_object (domain, &param_info->constraints [i]->byval_arg));
2541 return res;
2544 static MonoBoolean
2545 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2547 MONO_ARCH_SAVE_REGS;
2548 return is_generic_parameter (type->type);
2551 static MonoBoolean
2552 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2554 MONO_ARCH_SAVE_REGS;
2555 return is_generic_parameter (tb->type.type);
2558 static void
2559 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2560 MonoReflectionType *t)
2562 enumtype->type = t->type;
2565 static MonoReflectionMethod*
2566 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2567 MonoReflectionMethod* generic)
2569 MonoDomain *domain;
2570 MonoClass *klass;
2571 MonoMethod *method;
2572 gpointer iter;
2574 MONO_ARCH_SAVE_REGS;
2576 domain = ((MonoObject *)type)->vtable->domain;
2578 klass = mono_class_from_mono_type (type->type);
2579 mono_class_init_or_throw (klass);
2581 iter = NULL;
2582 while ((method = mono_class_get_methods (klass, &iter))) {
2583 if (method->token == generic->method->token)
2584 return mono_method_get_object (domain, method, klass);
2587 return NULL;
2592 static MonoReflectionMethod *
2593 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2595 MonoMethod *method;
2596 MonoType *type = ref_type->type;
2598 MONO_ARCH_SAVE_REGS;
2600 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2601 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2602 if (type->type == MONO_TYPE_VAR)
2603 return NULL;
2605 method = mono_type_get_generic_param_owner (type)->owner.method;
2606 g_assert (method);
2607 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2610 static MonoReflectionDllImportAttribute*
2611 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2613 static MonoClass *DllImportAttributeClass = NULL;
2614 MonoDomain *domain = mono_domain_get ();
2615 MonoReflectionDllImportAttribute *attr;
2616 MonoImage *image = method->klass->image;
2617 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2618 MonoTableInfo *tables = image->tables;
2619 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2620 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2621 guint32 im_cols [MONO_IMPLMAP_SIZE];
2622 guint32 scope_token;
2623 const char *import = NULL;
2624 const char *scope = NULL;
2625 guint32 flags;
2627 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2628 return NULL;
2630 if (!DllImportAttributeClass) {
2631 DllImportAttributeClass =
2632 mono_class_from_name (mono_defaults.corlib,
2633 "System.Runtime.InteropServices", "DllImportAttribute");
2634 g_assert (DllImportAttributeClass);
2637 if (method->klass->image->dynamic) {
2638 MonoReflectionMethodAux *method_aux =
2639 g_hash_table_lookup (
2640 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2641 if (method_aux) {
2642 import = method_aux->dllentry;
2643 scope = method_aux->dll;
2646 if (!import || !scope) {
2647 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2648 return NULL;
2651 else {
2652 if (piinfo->implmap_idx) {
2653 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2655 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2656 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2657 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2658 scope = mono_metadata_string_heap (image, scope_token);
2661 flags = piinfo->piflags;
2663 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2665 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2666 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2667 attr->call_conv = (flags & 0x700) >> 8;
2668 attr->charset = ((flags & 0x6) >> 1) + 1;
2669 if (attr->charset == 1)
2670 attr->charset = 2;
2671 attr->exact_spelling = (flags & 0x1) != 0;
2672 attr->set_last_error = (flags & 0x40) != 0;
2673 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2674 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2675 attr->preserve_sig = FALSE;
2677 return attr;
2680 static MonoReflectionMethod *
2681 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2683 MonoMethodInflated *imethod;
2684 MonoMethod *result;
2686 MONO_ARCH_SAVE_REGS;
2688 if (method->method->is_generic)
2689 return method;
2691 if (!method->method->is_inflated)
2692 return NULL;
2694 imethod = (MonoMethodInflated *) method->method;
2696 result = imethod->declaring;
2697 /* Not a generic method. */
2698 if (!result->is_generic)
2699 return NULL;
2701 if (method->method->klass->image->dynamic) {
2702 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2703 MonoReflectionMethod *res;
2706 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2707 * the dynamic case as well ?
2709 mono_loader_lock ();
2710 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2711 mono_loader_unlock ();
2713 if (res)
2714 return res;
2717 if (imethod->context.class_inst) {
2718 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2719 /*Generic methods gets the context of the GTD.*/
2720 if (mono_class_get_context (klass))
2721 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2724 return mono_method_get_object (mono_object_domain (method), result, NULL);
2727 static gboolean
2728 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2730 MONO_ARCH_SAVE_REGS;
2732 return mono_method_signature (method->method)->generic_param_count != 0;
2735 static gboolean
2736 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2738 MONO_ARCH_SAVE_REGS;
2740 return method->method->is_generic;
2743 static MonoArray*
2744 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2746 MonoArray *res;
2747 MonoDomain *domain;
2748 int count, i;
2749 MONO_ARCH_SAVE_REGS;
2751 domain = mono_object_domain (method);
2753 if (method->method->is_inflated) {
2754 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2756 if (inst) {
2757 count = inst->type_argc;
2758 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2760 for (i = 0; i < count; i++)
2761 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2763 return res;
2767 count = mono_method_signature (method->method)->generic_param_count;
2768 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2770 for (i = 0; i < count; i++) {
2771 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2772 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2773 MonoClass *pklass = mono_class_from_generic_parameter (
2774 param, method->method->klass->image, TRUE);
2775 mono_array_setref (res, i,
2776 mono_type_get_object (domain, &pklass->byval_arg));
2779 return res;
2782 static MonoObject *
2783 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2786 * Invoke from reflection is supposed to always be a virtual call (the API
2787 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2788 * greater flexibility.
2790 MonoMethod *m = method->method;
2791 int pcount;
2792 void *obj = this;
2794 MONO_ARCH_SAVE_REGS;
2796 *exc = NULL;
2798 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2799 mono_security_core_clr_ensure_reflection_access_method (m);
2801 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2802 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2803 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2804 return NULL;
2807 if (this) {
2808 if (!mono_object_isinst (this, m->klass)) {
2809 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2810 char *target_name = mono_type_get_full_name (m->klass);
2811 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2812 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2813 g_free (msg);
2814 g_free (target_name);
2815 g_free (this_name);
2816 return NULL;
2818 m = mono_object_get_virtual_method (this, m);
2819 /* must pass the pointer to the value for valuetype methods */
2820 if (m->klass->valuetype)
2821 obj = mono_object_unbox (this);
2822 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2823 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2824 return NULL;
2828 pcount = params? mono_array_length (params): 0;
2829 if (pcount != mono_method_signature (m)->param_count) {
2830 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2831 return NULL;
2834 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2835 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."));
2836 return NULL;
2839 if (m->klass->image->assembly->ref_only) {
2840 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."));
2841 return NULL;
2844 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2845 int i;
2846 uintptr_t *lengths;
2847 intptr_t *lower_bounds;
2848 pcount = mono_array_length (params);
2849 lengths = alloca (sizeof (uintptr_t) * pcount);
2850 /* Note: the synthetized array .ctors have int32 as argument type */
2851 for (i = 0; i < pcount; ++i)
2852 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2854 if (m->klass->rank == pcount) {
2855 /* Only lengths provided. */
2856 lower_bounds = NULL;
2857 } else {
2858 g_assert (pcount == (m->klass->rank * 2));
2859 /* lower bounds are first. */
2860 lower_bounds = (intptr_t*)lengths;
2861 lengths += m->klass->rank;
2864 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2866 return mono_runtime_invoke_array (m, obj, params, NULL);
2869 static MonoObject *
2870 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2872 MonoDomain *domain = mono_object_domain (method);
2873 MonoMethod *m = method->method;
2874 MonoMethodSignature *sig = mono_method_signature (m);
2875 MonoArray *out_args;
2876 MonoObject *result;
2877 int i, j, outarg_count = 0;
2879 MONO_ARCH_SAVE_REGS;
2881 if (m->klass == mono_defaults.object_class) {
2883 if (!strcmp (m->name, "FieldGetter")) {
2884 MonoClass *k = this->vtable->klass;
2885 MonoString *name;
2886 char *str;
2888 /* If this is a proxy, then it must be a CBO */
2889 if (k == mono_defaults.transparent_proxy_class) {
2890 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2891 this = tp->rp->unwrapped_server;
2892 g_assert (this);
2893 k = this->vtable->klass;
2896 name = mono_array_get (params, MonoString *, 1);
2897 str = mono_string_to_utf8 (name);
2899 do {
2900 MonoClassField* field = mono_class_get_field_from_name (k, str);
2901 if (field) {
2902 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2903 if (field_klass->valuetype)
2904 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2905 else
2906 result = *((gpointer *)((char *)this + field->offset));
2908 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2909 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2910 mono_array_setref (out_args, 0, result);
2911 g_free (str);
2912 return NULL;
2914 k = k->parent;
2915 } while (k);
2917 g_free (str);
2918 g_assert_not_reached ();
2920 } else if (!strcmp (m->name, "FieldSetter")) {
2921 MonoClass *k = this->vtable->klass;
2922 MonoString *name;
2923 guint32 size;
2924 gint32 align;
2925 char *str;
2927 /* If this is a proxy, then it must be a CBO */
2928 if (k == mono_defaults.transparent_proxy_class) {
2929 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2930 this = tp->rp->unwrapped_server;
2931 g_assert (this);
2932 k = this->vtable->klass;
2935 name = mono_array_get (params, MonoString *, 1);
2936 str = mono_string_to_utf8 (name);
2938 do {
2939 MonoClassField* field = mono_class_get_field_from_name (k, str);
2940 if (field) {
2941 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2942 MonoObject *val = mono_array_get (params, gpointer, 2);
2944 if (field_klass->valuetype) {
2945 size = mono_type_size (field->type, &align);
2946 g_assert (size == mono_class_value_size (field_klass, NULL));
2947 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2948 } else {
2949 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2952 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2953 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2955 g_free (str);
2956 return NULL;
2959 k = k->parent;
2960 } while (k);
2962 g_free (str);
2963 g_assert_not_reached ();
2968 for (i = 0; i < mono_array_length (params); i++) {
2969 if (sig->params [i]->byref)
2970 outarg_count++;
2973 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2975 /* handle constructors only for objects already allocated */
2976 if (!strcmp (method->method->name, ".ctor"))
2977 g_assert (this);
2979 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2980 g_assert (!method->method->klass->valuetype);
2981 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2983 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2984 if (sig->params [i]->byref) {
2985 gpointer arg;
2986 arg = mono_array_get (params, gpointer, i);
2987 mono_array_setref (out_args, j, arg);
2988 j++;
2992 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2994 return result;
2997 static guint64
2998 read_enum_value (char *mem, int type)
3000 switch (type) {
3001 case MONO_TYPE_U1:
3002 return *(guint8*)mem;
3003 case MONO_TYPE_I1:
3004 return *(gint8*)mem;
3005 case MONO_TYPE_U2:
3006 return *(guint16*)mem;
3007 case MONO_TYPE_I2:
3008 return *(gint16*)mem;
3009 case MONO_TYPE_U4:
3010 return *(guint32*)mem;
3011 case MONO_TYPE_I4:
3012 return *(gint32*)mem;
3013 case MONO_TYPE_U8:
3014 return *(guint64*)mem;
3015 case MONO_TYPE_I8:
3016 return *(gint64*)mem;
3017 default:
3018 g_assert_not_reached ();
3020 return 0;
3023 static void
3024 write_enum_value (char *mem, int type, guint64 value)
3026 switch (type) {
3027 case MONO_TYPE_U1:
3028 case MONO_TYPE_I1: {
3029 guint8 *p = (guint8*)mem;
3030 *p = value;
3031 break;
3033 case MONO_TYPE_U2:
3034 case MONO_TYPE_I2: {
3035 guint16 *p = (void*)mem;
3036 *p = value;
3037 break;
3039 case MONO_TYPE_U4:
3040 case MONO_TYPE_I4: {
3041 guint32 *p = (void*)mem;
3042 *p = value;
3043 break;
3045 case MONO_TYPE_U8:
3046 case MONO_TYPE_I8: {
3047 guint64 *p = (void*)mem;
3048 *p = value;
3049 break;
3051 default:
3052 g_assert_not_reached ();
3054 return;
3057 static MonoObject *
3058 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3060 MonoDomain *domain;
3061 MonoClass *enumc, *objc;
3062 MonoObject *res;
3063 MonoType *etype;
3064 guint64 val;
3066 MONO_ARCH_SAVE_REGS;
3068 MONO_CHECK_ARG_NULL (enumType);
3069 MONO_CHECK_ARG_NULL (value);
3071 domain = mono_object_domain (enumType);
3072 enumc = mono_class_from_mono_type (enumType->type);
3074 mono_class_init_or_throw (enumc);
3076 objc = value->vtable->klass;
3078 if (!enumc->enumtype)
3079 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3080 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3081 mono_raise_exception (mono_get_exception_argument ("value", "The value passed in must be an enum base or an underlying type for an enum, such as an Int32."));
3083 etype = mono_class_enum_basetype (enumc);
3084 if (!etype)
3085 /* MS throws this for typebuilders */
3086 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3088 res = mono_object_new (domain, enumc);
3089 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3090 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3092 return res;
3095 static MonoObject *
3096 ves_icall_System_Enum_get_value (MonoObject *this)
3098 MonoObject *res;
3099 MonoClass *enumc;
3100 gpointer dst;
3101 gpointer src;
3102 int size;
3104 MONO_ARCH_SAVE_REGS;
3106 if (!this)
3107 return NULL;
3109 g_assert (this->vtable->klass->enumtype);
3111 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3112 res = mono_object_new (mono_object_domain (this), enumc);
3113 dst = (char *)res + sizeof (MonoObject);
3114 src = (char *)this + sizeof (MonoObject);
3115 size = mono_class_value_size (enumc, NULL);
3117 memcpy (dst, src, size);
3119 return res;
3122 static MonoReflectionType *
3123 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3125 MonoType *etype;
3126 MonoClass *klass;
3128 MONO_ARCH_SAVE_REGS;
3130 klass = mono_class_from_mono_type (type->type);
3131 mono_class_init_or_throw (klass);
3133 etype = mono_class_enum_basetype (klass);
3134 if (!etype)
3135 /* MS throws this for typebuilders */
3136 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3138 return mono_type_get_object (mono_object_domain (type), etype);
3141 static int
3142 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3144 gpointer tdata = (char *)this + sizeof (MonoObject);
3145 gpointer odata = (char *)other + sizeof (MonoObject);
3146 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3147 g_assert (basetype);
3149 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3150 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3151 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3152 if (me == other) \
3153 return 0; \
3154 return me > other ? 1 : -1; \
3155 } while (0)
3157 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3158 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3159 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3160 if (me == other) \
3161 return 0; \
3162 return me - other; \
3163 } while (0)
3165 switch (basetype->type) {
3166 case MONO_TYPE_U1:
3167 COMPARE_ENUM_VALUES (guint8);
3168 case MONO_TYPE_I1:
3169 COMPARE_ENUM_VALUES (gint8);
3170 case MONO_TYPE_CHAR:
3171 case MONO_TYPE_U2:
3172 COMPARE_ENUM_VALUES_RANGE (guint16);
3173 case MONO_TYPE_I2:
3174 COMPARE_ENUM_VALUES (gint16);
3175 case MONO_TYPE_U4:
3176 COMPARE_ENUM_VALUES (guint32);
3177 case MONO_TYPE_I4:
3178 COMPARE_ENUM_VALUES (gint32);
3179 case MONO_TYPE_U8:
3180 COMPARE_ENUM_VALUES (guint64);
3181 case MONO_TYPE_I8:
3182 COMPARE_ENUM_VALUES (gint64);
3183 default:
3184 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3186 #undef COMPARE_ENUM_VALUES_RANGE
3187 #undef COMPARE_ENUM_VALUES
3188 return 0;
3191 static int
3192 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3194 gpointer data = (char *)this + sizeof (MonoObject);
3195 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3196 g_assert (basetype);
3198 switch (basetype->type) {
3199 case MONO_TYPE_I1:
3200 return *((gint8*)data);
3201 case MONO_TYPE_U1:
3202 return *((guint8*)data);
3203 case MONO_TYPE_CHAR:
3204 case MONO_TYPE_U2:
3205 return *((guint16*)data);
3207 case MONO_TYPE_I2:
3208 return *((gint16*)data);
3209 case MONO_TYPE_U4:
3210 return *((guint32*)data);
3211 case MONO_TYPE_I4:
3212 return *((gint32*)data);
3213 case MONO_TYPE_U8:
3214 case MONO_TYPE_I8: {
3215 gint64 value = *((gint64*)data);
3216 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3218 default:
3219 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3221 return 0;
3224 static void
3225 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3227 MonoDomain *domain = mono_object_domain (type);
3228 MonoClass *enumc = mono_class_from_mono_type (type->type);
3229 guint j = 0, nvalues, crow;
3230 gpointer iter;
3231 MonoClassField *field;
3233 MONO_ARCH_SAVE_REGS;
3235 mono_class_init_or_throw (enumc);
3237 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3238 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3239 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3240 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3242 crow = -1;
3243 iter = NULL;
3244 while ((field = mono_class_get_fields (enumc, &iter))) {
3245 const char *p;
3246 int len;
3247 MonoTypeEnum def_type;
3249 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3250 continue;
3251 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3252 continue;
3253 if (mono_field_is_deleted (field))
3254 continue;
3255 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3257 p = mono_class_get_field_default_value (field, &def_type);
3258 len = mono_metadata_decode_blob_size (p, &p);
3259 switch (mono_class_enum_basetype (enumc)->type) {
3260 case MONO_TYPE_U1:
3261 case MONO_TYPE_I1:
3262 mono_array_set (info->values, gchar, j, *p);
3263 break;
3264 case MONO_TYPE_CHAR:
3265 case MONO_TYPE_U2:
3266 case MONO_TYPE_I2:
3267 mono_array_set (info->values, gint16, j, read16 (p));
3268 break;
3269 case MONO_TYPE_U4:
3270 case MONO_TYPE_I4:
3271 mono_array_set (info->values, gint32, j, read32 (p));
3272 break;
3273 case MONO_TYPE_U8:
3274 case MONO_TYPE_I8:
3275 mono_array_set (info->values, gint64, j, read64 (p));
3276 break;
3277 default:
3278 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3280 ++j;
3284 enum {
3285 BFLAGS_IgnoreCase = 1,
3286 BFLAGS_DeclaredOnly = 2,
3287 BFLAGS_Instance = 4,
3288 BFLAGS_Static = 8,
3289 BFLAGS_Public = 0x10,
3290 BFLAGS_NonPublic = 0x20,
3291 BFLAGS_FlattenHierarchy = 0x40,
3292 BFLAGS_InvokeMethod = 0x100,
3293 BFLAGS_CreateInstance = 0x200,
3294 BFLAGS_GetField = 0x400,
3295 BFLAGS_SetField = 0x800,
3296 BFLAGS_GetProperty = 0x1000,
3297 BFLAGS_SetProperty = 0x2000,
3298 BFLAGS_ExactBinding = 0x10000,
3299 BFLAGS_SuppressChangeType = 0x20000,
3300 BFLAGS_OptionalParamBinding = 0x40000
3303 static MonoReflectionField *
3304 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3306 MonoDomain *domain;
3307 MonoClass *startklass, *klass;
3308 int match;
3309 MonoClassField *field;
3310 gpointer iter;
3311 char *utf8_name;
3312 int (*compare_func) (const char *s1, const char *s2) = NULL;
3313 domain = ((MonoObject *)type)->vtable->domain;
3314 klass = startklass = mono_class_from_mono_type (type->type);
3316 if (!name)
3317 mono_raise_exception (mono_get_exception_argument_null ("name"));
3318 if (type->type->byref)
3319 return NULL;
3321 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3323 handle_parent:
3324 if (klass->exception_type != MONO_EXCEPTION_NONE)
3325 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3327 iter = NULL;
3328 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3329 guint32 flags = mono_field_get_flags (field);
3330 match = 0;
3332 if (mono_field_is_deleted_with_flags (field, flags))
3333 continue;
3334 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3335 if (bflags & BFLAGS_Public)
3336 match++;
3337 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3338 if (bflags & BFLAGS_NonPublic) {
3339 match++;
3342 if (!match)
3343 continue;
3344 match = 0;
3345 if (flags & FIELD_ATTRIBUTE_STATIC) {
3346 if (bflags & BFLAGS_Static)
3347 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3348 match++;
3349 } else {
3350 if (bflags & BFLAGS_Instance)
3351 match++;
3354 if (!match)
3355 continue;
3357 utf8_name = mono_string_to_utf8 (name);
3359 if (compare_func (mono_field_get_name (field), utf8_name)) {
3360 g_free (utf8_name);
3361 continue;
3363 g_free (utf8_name);
3365 return mono_field_get_object (domain, klass, field);
3367 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3368 goto handle_parent;
3370 return NULL;
3373 static MonoArray*
3374 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3376 MonoDomain *domain;
3377 MonoClass *startklass, *klass, *refklass;
3378 MonoArray *res;
3379 MonoObject *member;
3380 int i, match;
3381 gpointer iter;
3382 MonoClassField *field;
3383 MonoPtrArray tmp_array;
3385 MONO_ARCH_SAVE_REGS;
3387 domain = ((MonoObject *)type)->vtable->domain;
3388 if (type->type->byref)
3389 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3390 klass = startklass = mono_class_from_mono_type (type->type);
3391 refklass = mono_class_from_mono_type (reftype->type);
3393 mono_ptr_array_init (tmp_array, 2);
3395 handle_parent:
3396 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3397 mono_ptr_array_destroy (tmp_array);
3398 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3401 iter = NULL;
3402 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3403 guint32 flags = mono_field_get_flags (field);
3404 match = 0;
3405 if (mono_field_is_deleted_with_flags (field, flags))
3406 continue;
3407 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3408 if (bflags & BFLAGS_Public)
3409 match++;
3410 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3411 if (bflags & BFLAGS_NonPublic) {
3412 match++;
3415 if (!match)
3416 continue;
3417 match = 0;
3418 if (flags & FIELD_ATTRIBUTE_STATIC) {
3419 if (bflags & BFLAGS_Static)
3420 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3421 match++;
3422 } else {
3423 if (bflags & BFLAGS_Instance)
3424 match++;
3427 if (!match)
3428 continue;
3429 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3430 mono_ptr_array_append (tmp_array, member);
3432 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3433 goto handle_parent;
3435 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3437 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3438 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3440 mono_ptr_array_destroy (tmp_array);
3442 return res;
3445 static gboolean
3446 method_nonpublic (MonoMethod* method, gboolean start_klass)
3448 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3449 case METHOD_ATTRIBUTE_ASSEM:
3450 return (start_klass || mono_defaults.generic_ilist_class);
3451 case METHOD_ATTRIBUTE_PRIVATE:
3452 return start_klass;
3453 case METHOD_ATTRIBUTE_PUBLIC:
3454 return FALSE;
3455 default:
3456 return TRUE;
3460 static MonoArray*
3461 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3463 static MonoClass *MethodInfo_array;
3464 MonoDomain *domain;
3465 MonoClass *startklass, *klass, *refklass;
3466 MonoArray *res;
3467 MonoMethod *method;
3468 gpointer iter;
3469 MonoObject *member;
3470 int i, len, match, nslots;
3471 /*FIXME, use MonoBitSet*/
3472 guint32 method_slots_default [8];
3473 guint32 *method_slots = NULL;
3474 gchar *mname = NULL;
3475 int (*compare_func) (const char *s1, const char *s2) = NULL;
3476 MonoVTable *array_vtable;
3477 MonoException *ex;
3478 MonoPtrArray tmp_array;
3480 mono_ptr_array_init (tmp_array, 4);
3482 if (!MethodInfo_array) {
3483 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3484 mono_memory_barrier ();
3485 MethodInfo_array = klass;
3488 domain = ((MonoObject *)type)->vtable->domain;
3489 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3490 if (type->type->byref)
3491 return mono_array_new_specific (array_vtable, 0);
3492 klass = startklass = mono_class_from_mono_type (type->type);
3493 refklass = mono_class_from_mono_type (reftype->type);
3495 len = 0;
3496 if (name != NULL) {
3497 mname = mono_string_to_utf8 (name);
3498 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3501 /* An optimization for calls made from Delegate:CreateDelegate () */
3502 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3503 method = mono_get_delegate_invoke (klass);
3504 if (mono_loader_get_last_error ())
3505 goto loader_error;
3507 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3509 res = mono_array_new_specific (array_vtable, 1);
3510 mono_array_setref (res, 0, member);
3511 g_free (mname);
3512 return res;
3515 mono_class_setup_vtable (klass);
3516 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3517 goto loader_error;
3519 if (is_generic_parameter (type->type))
3520 nslots = mono_class_get_vtable_size (klass->parent);
3521 else
3522 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3523 if (nslots >= sizeof (method_slots_default) * 8) {
3524 method_slots = g_new0 (guint32, nslots / 32 + 1);
3525 } else {
3526 method_slots = method_slots_default;
3527 memset (method_slots, 0, sizeof (method_slots_default));
3529 handle_parent:
3530 mono_class_setup_vtable (klass);
3531 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3532 goto loader_error;
3534 iter = NULL;
3535 while ((method = mono_class_get_methods (klass, &iter))) {
3536 match = 0;
3537 if (method->slot != -1) {
3538 g_assert (method->slot < nslots);
3539 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3540 continue;
3541 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3542 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3545 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3546 continue;
3547 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3548 if (bflags & BFLAGS_Public)
3549 match++;
3550 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3551 match++;
3553 if (!match)
3554 continue;
3555 match = 0;
3556 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3557 if (bflags & BFLAGS_Static)
3558 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3559 match++;
3560 } else {
3561 if (bflags & BFLAGS_Instance)
3562 match++;
3565 if (!match)
3566 continue;
3568 if (name != NULL) {
3569 if (compare_func (mname, method->name))
3570 continue;
3573 match = 0;
3575 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3577 mono_ptr_array_append (tmp_array, member);
3579 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3580 goto handle_parent;
3582 g_free (mname);
3583 if (method_slots != method_slots_default)
3584 g_free (method_slots);
3586 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3588 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3589 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3591 mono_ptr_array_destroy (tmp_array);
3592 return res;
3594 loader_error:
3595 g_free (mname);
3596 if (method_slots != method_slots_default)
3597 g_free (method_slots);
3598 mono_ptr_array_destroy (tmp_array);
3599 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3600 ex = mono_class_get_exception_for_failure (klass);
3601 } else {
3602 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3603 mono_loader_clear_error ();
3605 mono_raise_exception (ex);
3606 return NULL;
3609 static MonoArray*
3610 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3612 MonoDomain *domain;
3613 static MonoClass *System_Reflection_ConstructorInfo;
3614 MonoClass *startklass, *klass, *refklass;
3615 MonoArray *res;
3616 MonoMethod *method;
3617 MonoObject *member;
3618 int i, match;
3619 gpointer iter = NULL;
3620 MonoPtrArray tmp_array;
3622 MONO_ARCH_SAVE_REGS;
3624 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3626 domain = ((MonoObject *)type)->vtable->domain;
3627 if (type->type->byref)
3628 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3629 klass = startklass = mono_class_from_mono_type (type->type);
3630 refklass = mono_class_from_mono_type (reftype->type);
3632 if (!System_Reflection_ConstructorInfo)
3633 System_Reflection_ConstructorInfo = mono_class_from_name (
3634 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3636 iter = NULL;
3637 while ((method = mono_class_get_methods (klass, &iter))) {
3638 match = 0;
3639 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3640 continue;
3641 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3642 if (bflags & BFLAGS_Public)
3643 match++;
3644 } else {
3645 if (bflags & BFLAGS_NonPublic)
3646 match++;
3648 if (!match)
3649 continue;
3650 match = 0;
3651 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3652 if (bflags & BFLAGS_Static)
3653 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3654 match++;
3655 } else {
3656 if (bflags & BFLAGS_Instance)
3657 match++;
3660 if (!match)
3661 continue;
3662 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3664 mono_ptr_array_append (tmp_array, member);
3667 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3669 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3670 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3672 mono_ptr_array_destroy (tmp_array);
3674 return res;
3677 static guint
3678 property_hash (gconstpointer data)
3680 MonoProperty *prop = (MonoProperty*)data;
3682 return g_str_hash (prop->name);
3685 static gboolean
3686 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3688 // Properties are hide-by-name-and-signature
3689 if (!g_str_equal (prop1->name, prop2->name))
3690 return FALSE;
3692 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3693 return FALSE;
3694 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3695 return FALSE;
3696 return TRUE;
3699 static gboolean
3700 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3702 if (!accessor)
3703 return FALSE;
3705 return method_nonpublic (accessor, start_klass);
3708 static MonoArray*
3709 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3711 MonoException *ex;
3712 MonoDomain *domain;
3713 static MonoClass *System_Reflection_PropertyInfo;
3714 MonoClass *startklass, *klass;
3715 MonoArray *res;
3716 MonoMethod *method;
3717 MonoProperty *prop;
3718 int i, match;
3719 guint32 flags;
3720 gchar *propname = NULL;
3721 int (*compare_func) (const char *s1, const char *s2) = NULL;
3722 gpointer iter;
3723 GHashTable *properties = NULL;
3724 MonoPtrArray tmp_array;
3726 MONO_ARCH_SAVE_REGS;
3728 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3730 if (!System_Reflection_PropertyInfo)
3731 System_Reflection_PropertyInfo = mono_class_from_name (
3732 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3734 domain = ((MonoObject *)type)->vtable->domain;
3735 if (type->type->byref)
3736 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3737 klass = startklass = mono_class_from_mono_type (type->type);
3739 if (name != NULL) {
3740 propname = mono_string_to_utf8 (name);
3741 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3744 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3745 handle_parent:
3746 mono_class_setup_vtable (klass);
3747 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3748 goto loader_error;
3750 iter = NULL;
3751 while ((prop = mono_class_get_properties (klass, &iter))) {
3752 match = 0;
3753 method = prop->get;
3754 if (!method)
3755 method = prop->set;
3756 if (method)
3757 flags = method->flags;
3758 else
3759 flags = 0;
3760 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3761 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3762 if (bflags & BFLAGS_Public)
3763 match++;
3764 } else if (bflags & BFLAGS_NonPublic) {
3765 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3766 property_accessor_nonpublic(prop->set, startklass == klass)) {
3767 match++;
3770 if (!match)
3771 continue;
3772 match = 0;
3773 if (flags & METHOD_ATTRIBUTE_STATIC) {
3774 if (bflags & BFLAGS_Static)
3775 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3776 match++;
3777 } else {
3778 if (bflags & BFLAGS_Instance)
3779 match++;
3782 if (!match)
3783 continue;
3784 match = 0;
3786 if (name != NULL) {
3787 if (compare_func (propname, prop->name))
3788 continue;
3791 if (g_hash_table_lookup (properties, prop))
3792 continue;
3794 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3796 g_hash_table_insert (properties, prop, prop);
3798 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3799 goto handle_parent;
3801 g_hash_table_destroy (properties);
3802 g_free (propname);
3804 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3805 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3806 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3808 mono_ptr_array_destroy (tmp_array);
3810 return res;
3812 loader_error:
3813 if (properties)
3814 g_hash_table_destroy (properties);
3815 if (name)
3816 g_free (propname);
3817 mono_ptr_array_destroy (tmp_array);
3819 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3820 ex = mono_class_get_exception_for_failure (klass);
3821 } else {
3822 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3823 mono_loader_clear_error ();
3825 mono_raise_exception (ex);
3826 return NULL;
3829 static MonoReflectionEvent *
3830 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3832 MonoDomain *domain;
3833 MonoClass *klass, *startklass;
3834 gpointer iter;
3835 MonoEvent *event;
3836 MonoMethod *method;
3837 gchar *event_name;
3838 int (*compare_func) (const char *s1, const char *s2);
3840 MONO_ARCH_SAVE_REGS;
3842 event_name = mono_string_to_utf8 (name);
3843 if (type->type->byref)
3844 return NULL;
3845 klass = startklass = mono_class_from_mono_type (type->type);
3846 domain = mono_object_domain (type);
3848 mono_class_init_or_throw (klass);
3850 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3851 handle_parent:
3852 if (klass->exception_type != MONO_EXCEPTION_NONE)
3853 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3855 iter = NULL;
3856 while ((event = mono_class_get_events (klass, &iter))) {
3857 if (compare_func (event->name, event_name))
3858 continue;
3860 method = event->add;
3861 if (!method)
3862 method = event->remove;
3863 if (!method)
3864 method = event->raise;
3865 if (method) {
3866 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3867 if (!(bflags & BFLAGS_Public))
3868 continue;
3869 } else {
3870 if (!(bflags & BFLAGS_NonPublic))
3871 continue;
3872 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3873 continue;
3876 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3877 if (!(bflags & BFLAGS_Static))
3878 continue;
3879 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3880 continue;
3881 } else {
3882 if (!(bflags & BFLAGS_Instance))
3883 continue;
3885 } else
3886 if (!(bflags & BFLAGS_NonPublic))
3887 continue;
3889 g_free (event_name);
3890 return mono_event_get_object (domain, startklass, event);
3893 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3894 goto handle_parent;
3896 g_free (event_name);
3897 return NULL;
3900 static MonoArray*
3901 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3903 MonoException *ex;
3904 MonoDomain *domain;
3905 static MonoClass *System_Reflection_EventInfo;
3906 MonoClass *startklass, *klass;
3907 MonoArray *res;
3908 MonoMethod *method;
3909 MonoEvent *event;
3910 int i, match;
3911 gpointer iter;
3913 MonoPtrArray tmp_array;
3915 MONO_ARCH_SAVE_REGS;
3917 mono_ptr_array_init (tmp_array, 4);
3919 if (!System_Reflection_EventInfo)
3920 System_Reflection_EventInfo = mono_class_from_name (
3921 mono_defaults.corlib, "System.Reflection", "EventInfo");
3923 domain = mono_object_domain (type);
3924 if (type->type->byref)
3925 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3926 klass = startklass = mono_class_from_mono_type (type->type);
3928 handle_parent:
3929 mono_class_setup_vtable (klass);
3930 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3931 goto loader_error;
3933 iter = NULL;
3934 while ((event = mono_class_get_events (klass, &iter))) {
3935 match = 0;
3936 method = event->add;
3937 if (!method)
3938 method = event->remove;
3939 if (!method)
3940 method = event->raise;
3941 if (method) {
3942 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3943 if (bflags & BFLAGS_Public)
3944 match++;
3945 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3946 if (bflags & BFLAGS_NonPublic)
3947 match++;
3950 else
3951 if (bflags & BFLAGS_NonPublic)
3952 match ++;
3953 if (!match)
3954 continue;
3955 match = 0;
3956 if (method) {
3957 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3958 if (bflags & BFLAGS_Static)
3959 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3960 match++;
3961 } else {
3962 if (bflags & BFLAGS_Instance)
3963 match++;
3966 else
3967 if (bflags & BFLAGS_Instance)
3968 match ++;
3969 if (!match)
3970 continue;
3971 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3973 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3974 goto handle_parent;
3976 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3978 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3979 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3981 mono_ptr_array_destroy (tmp_array);
3983 return res;
3985 loader_error:
3986 mono_ptr_array_destroy (tmp_array);
3987 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3988 ex = mono_class_get_exception_for_failure (klass);
3989 } else {
3990 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3991 mono_loader_clear_error ();
3993 mono_raise_exception (ex);
3994 return NULL;
3997 static MonoReflectionType *
3998 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4000 MonoDomain *domain;
4001 MonoClass *klass;
4002 MonoClass *nested;
4003 char *str;
4004 gpointer iter;
4006 MONO_ARCH_SAVE_REGS;
4008 if (name == NULL)
4009 mono_raise_exception (mono_get_exception_argument_null ("name"));
4011 domain = ((MonoObject *)type)->vtable->domain;
4012 if (type->type->byref)
4013 return NULL;
4014 klass = mono_class_from_mono_type (type->type);
4016 str = mono_string_to_utf8 (name);
4018 handle_parent:
4019 if (klass->exception_type != MONO_EXCEPTION_NONE)
4020 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4023 * If a nested type is generic, return its generic type definition.
4024 * Note that this means that the return value is essentially a
4025 * nested type of the generic type definition of @klass.
4027 * A note in MSDN claims that a generic type definition can have
4028 * nested types that aren't generic. In any case, the container of that
4029 * nested type would be the generic type definition.
4031 if (klass->generic_class)
4032 klass = klass->generic_class->container_class;
4034 iter = NULL;
4035 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4036 int match = 0;
4037 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4038 if (bflags & BFLAGS_Public)
4039 match++;
4040 } else {
4041 if (bflags & BFLAGS_NonPublic)
4042 match++;
4044 if (!match)
4045 continue;
4046 if (strcmp (nested->name, str) == 0){
4047 g_free (str);
4048 return mono_type_get_object (domain, &nested->byval_arg);
4051 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4052 goto handle_parent;
4053 g_free (str);
4054 return NULL;
4057 static MonoArray*
4058 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4060 MonoDomain *domain;
4061 MonoClass *klass;
4062 MonoArray *res;
4063 MonoObject *member;
4064 int i, match;
4065 MonoClass *nested;
4066 gpointer iter;
4067 MonoPtrArray tmp_array;
4069 MONO_ARCH_SAVE_REGS;
4071 domain = ((MonoObject *)type)->vtable->domain;
4072 if (type->type->byref)
4073 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4074 klass = mono_class_from_mono_type (type->type);
4077 * If a nested type is generic, return its generic type definition.
4078 * Note that this means that the return value is essentially the set
4079 * of nested types of the generic type definition of @klass.
4081 * A note in MSDN claims that a generic type definition can have
4082 * nested types that aren't generic. In any case, the container of that
4083 * nested type would be the generic type definition.
4085 if (klass->generic_class)
4086 klass = klass->generic_class->container_class;
4088 mono_ptr_array_init (tmp_array, 1);
4089 iter = NULL;
4090 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4091 match = 0;
4092 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4093 if (bflags & BFLAGS_Public)
4094 match++;
4095 } else {
4096 if (bflags & BFLAGS_NonPublic)
4097 match++;
4099 if (!match)
4100 continue;
4101 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4102 mono_ptr_array_append (tmp_array, member);
4105 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4107 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4108 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4110 mono_ptr_array_destroy (tmp_array);
4112 return res;
4115 static MonoReflectionType*
4116 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4118 gchar *str;
4119 MonoType *type = NULL;
4120 MonoTypeNameParse info;
4121 gboolean type_resolve;
4123 MONO_ARCH_SAVE_REGS;
4125 /* On MS.NET, this does not fire a TypeResolve event */
4126 type_resolve = TRUE;
4127 str = mono_string_to_utf8 (name);
4128 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4129 if (!mono_reflection_parse_type (str, &info)) {
4130 g_free (str);
4131 mono_reflection_free_type_info (&info);
4132 if (throwOnError) /* uhm: this is a parse error, though... */
4133 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4134 /*g_print ("failed parse\n");*/
4135 return NULL;
4138 if (info.assembly.name) {
4139 g_free (str);
4140 mono_reflection_free_type_info (&info);
4141 if (throwOnError) {
4142 /* 1.0 and 2.0 throw different exceptions */
4143 if (mono_defaults.generic_ilist_class)
4144 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4145 else
4146 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4148 return NULL;
4151 if (module != NULL) {
4152 if (module->image)
4153 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4154 else
4155 type = NULL;
4157 else
4158 if (assembly->assembly->dynamic) {
4159 /* Enumerate all modules */
4160 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4161 int i;
4163 type = NULL;
4164 if (abuilder->modules) {
4165 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4166 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4167 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4168 if (type)
4169 break;
4173 if (!type && abuilder->loaded_modules) {
4174 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4175 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4176 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4177 if (type)
4178 break;
4182 else
4183 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4184 g_free (str);
4185 mono_reflection_free_type_info (&info);
4186 if (!type) {
4187 MonoException *e = NULL;
4189 if (throwOnError)
4190 e = mono_get_exception_type_load (name, NULL);
4192 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4193 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4195 mono_loader_clear_error ();
4197 if (e != NULL)
4198 mono_raise_exception (e);
4200 return NULL;
4201 } else if (mono_loader_get_last_error ()) {
4202 if (throwOnError)
4203 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4204 mono_loader_clear_error ();
4207 if (type->type == MONO_TYPE_CLASS) {
4208 MonoClass *klass = mono_type_get_class (type);
4210 if (mono_is_security_manager_active () && !klass->exception_type)
4211 /* Some security problems are detected during generic vtable construction */
4212 mono_class_setup_vtable (klass);
4213 /* need to report exceptions ? */
4214 if (throwOnError && klass->exception_type) {
4215 /* report SecurityException (or others) that occured when loading the assembly */
4216 MonoException *exc = mono_class_get_exception_for_failure (klass);
4217 mono_loader_clear_error ();
4218 mono_raise_exception (exc);
4219 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4220 return NULL;
4224 /* g_print ("got it\n"); */
4225 return mono_type_get_object (mono_object_domain (assembly), type);
4228 static gboolean
4229 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4231 gchar *content;
4232 gchar *shadow_ini_file;
4233 gsize len;
4235 /* Check for shadow-copied assembly */
4236 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4237 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4238 content = NULL;
4239 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4240 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4241 if (content) {
4242 g_free (content);
4243 content = NULL;
4246 g_free (shadow_ini_file);
4247 if (content != NULL) {
4248 if (*filename)
4249 g_free (*filename);
4250 *filename = content;
4251 return TRUE;
4254 return FALSE;
4257 static MonoString *
4258 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4260 MonoDomain *domain = mono_object_domain (assembly);
4261 MonoAssembly *mass = assembly->assembly;
4262 MonoString *res = NULL;
4263 gchar *uri;
4264 gchar *absolute;
4265 gchar *dirname;
4267 MONO_ARCH_SAVE_REGS;
4269 if (g_path_is_absolute (mass->image->name)) {
4270 absolute = g_strdup (mass->image->name);
4271 dirname = g_path_get_dirname (absolute);
4272 } else {
4273 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4274 dirname = g_strdup (mass->basedir);
4277 replace_shadow_path (domain, dirname, &absolute);
4278 g_free (dirname);
4279 #if HOST_WIN32
4281 gint i;
4282 for (i = strlen (absolute) - 1; i >= 0; i--)
4283 if (absolute [i] == '\\')
4284 absolute [i] = '/';
4286 #endif
4287 if (escaped) {
4288 uri = g_filename_to_uri (absolute, NULL, NULL);
4289 } else {
4290 const char *prepend = "file://";
4291 #if HOST_WIN32
4292 if (*absolute == '/' && *(absolute + 1) == '/') {
4293 prepend = "file:";
4294 } else {
4295 prepend = "file:///";
4297 #endif
4298 uri = g_strconcat (prepend, absolute, NULL);
4301 if (uri) {
4302 res = mono_string_new (domain, uri);
4303 g_free (uri);
4305 g_free (absolute);
4306 return res;
4309 static MonoBoolean
4310 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4312 MonoAssembly *mass = assembly->assembly;
4314 MONO_ARCH_SAVE_REGS;
4316 return mass->in_gac;
4319 static MonoReflectionAssembly*
4320 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4322 gchar *name;
4323 MonoAssembly *res;
4324 MonoImageOpenStatus status;
4326 MONO_ARCH_SAVE_REGS;
4328 name = mono_string_to_utf8 (mname);
4329 res = mono_assembly_load_with_partial_name (name, &status);
4331 g_free (name);
4333 if (res == NULL)
4334 return NULL;
4335 return mono_assembly_get_object (mono_domain_get (), res);
4338 static MonoString *
4339 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4341 MonoDomain *domain = mono_object_domain (assembly);
4342 MonoString *res;
4344 MONO_ARCH_SAVE_REGS;
4346 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4348 return res;
4351 static MonoBoolean
4352 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4354 MONO_ARCH_SAVE_REGS;
4356 return assembly->assembly->ref_only;
4359 static MonoString *
4360 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4362 MonoDomain *domain = mono_object_domain (assembly);
4364 MONO_ARCH_SAVE_REGS;
4366 return mono_string_new (domain, assembly->assembly->image->version);
4369 static MonoReflectionMethod*
4370 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4372 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4374 MONO_ARCH_SAVE_REGS;
4376 if (!token)
4377 return NULL;
4378 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4381 static MonoReflectionModule*
4382 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4384 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4387 static MonoArray*
4388 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4390 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4391 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4392 int i;
4393 const char *val;
4395 MONO_ARCH_SAVE_REGS;
4397 for (i = 0; i < table->rows; ++i) {
4398 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4399 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4401 return result;
4404 static MonoObject*
4405 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4407 static MonoClass *System_Version = NULL;
4408 static MonoMethod *create_version = NULL;
4409 MonoObject *result;
4410 gpointer args [4];
4412 if (!System_Version) {
4413 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4414 g_assert (System_Version);
4417 if (!create_version) {
4418 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4419 create_version = mono_method_desc_search_in_class (desc, System_Version);
4420 g_assert (create_version);
4421 mono_method_desc_free (desc);
4424 args [0] = &major;
4425 args [1] = &minor;
4426 args [2] = &build;
4427 args [3] = &revision;
4428 result = mono_object_new (domain, System_Version);
4429 mono_runtime_invoke (create_version, result, args, NULL);
4431 return result;
4434 static MonoArray*
4435 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4437 static MonoClass *System_Reflection_AssemblyName;
4438 MonoArray *result;
4439 MonoDomain *domain = mono_object_domain (assembly);
4440 int i, count = 0;
4441 static MonoMethod *create_culture = NULL;
4442 MonoImage *image = assembly->assembly->image;
4443 MonoTableInfo *t;
4445 MONO_ARCH_SAVE_REGS;
4447 if (!System_Reflection_AssemblyName)
4448 System_Reflection_AssemblyName = mono_class_from_name (
4449 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4451 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4452 count = t->rows;
4454 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4456 if (count > 0 && !create_culture) {
4457 MonoMethodDesc *desc = mono_method_desc_new (
4458 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4459 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4460 g_assert (create_culture);
4461 mono_method_desc_free (desc);
4464 for (i = 0; i < count; i++) {
4465 MonoReflectionAssemblyName *aname;
4466 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4468 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4470 aname = (MonoReflectionAssemblyName *) mono_object_new (
4471 domain, System_Reflection_AssemblyName);
4473 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4475 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4476 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4477 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4478 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4479 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4480 aname->versioncompat = 1; /* SameMachine (default) */
4481 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4482 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4484 if (create_culture) {
4485 gpointer args [2];
4486 MonoBoolean assembly_ref = 1;
4487 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4488 args [1] = &assembly_ref;
4489 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4492 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4493 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4494 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4496 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4497 /* public key token isn't copied - the class library will
4498 automatically generate it from the public key if required */
4499 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4500 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4501 } else {
4502 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4503 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4505 } else {
4506 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4509 /* note: this function doesn't return the codebase on purpose (i.e. it can
4510 be used under partial trust as path information isn't present). */
4512 mono_array_setref (result, i, aname);
4514 return result;
4517 typedef struct {
4518 MonoArray *res;
4519 int idx;
4520 } NameSpaceInfo;
4522 static void
4523 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4525 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4527 mono_array_setref (info->res, info->idx, name);
4528 info->idx++;
4531 static MonoArray*
4532 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4534 MonoImage *img = assembly->assembly->image;
4535 MonoArray *res;
4536 NameSpaceInfo info;
4537 int len;
4539 MONO_ARCH_SAVE_REGS;
4541 mono_image_lock (img);
4542 mono_image_init_name_cache (img);
4544 RETRY_LEN:
4545 len = g_hash_table_size (img->name_cache);
4546 mono_image_unlock (img);
4548 /*we can't create objects holding the image lock */
4549 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4551 mono_image_lock (img);
4552 /*len might have changed, create a new array*/
4553 if (len != g_hash_table_size (img->name_cache))
4554 goto RETRY_LEN;
4556 info.res = res;
4557 info.idx = 0;
4558 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4559 mono_image_unlock (img);
4561 return res;
4564 /* move this in some file in mono/util/ */
4565 static char *
4566 g_concat_dir_and_file (const char *dir, const char *file)
4568 g_return_val_if_fail (dir != NULL, NULL);
4569 g_return_val_if_fail (file != NULL, NULL);
4572 * If the directory name doesn't have a / on the end, we need
4573 * to add one so we get a proper path to the file
4575 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4576 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4577 else
4578 return g_strconcat (dir, file, NULL);
4581 static void *
4582 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4584 char *n = mono_string_to_utf8 (name);
4585 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4586 guint32 i;
4587 guint32 cols [MONO_MANIFEST_SIZE];
4588 guint32 impl, file_idx;
4589 const char *val;
4590 MonoImage *module;
4592 MONO_ARCH_SAVE_REGS;
4594 for (i = 0; i < table->rows; ++i) {
4595 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4596 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4597 if (strcmp (val, n) == 0)
4598 break;
4600 g_free (n);
4601 if (i == table->rows)
4602 return NULL;
4603 /* FIXME */
4604 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4605 if (impl) {
4607 * this code should only be called after obtaining the
4608 * ResourceInfo and handling the other cases.
4610 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4611 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4613 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4614 if (!module)
4615 return NULL;
4617 else
4618 module = assembly->assembly->image;
4620 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4622 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4625 static gboolean
4626 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4628 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4629 int i;
4630 guint32 cols [MONO_MANIFEST_SIZE];
4631 guint32 file_cols [MONO_FILE_SIZE];
4632 const char *val;
4633 char *n;
4635 MONO_ARCH_SAVE_REGS;
4637 n = mono_string_to_utf8 (name);
4638 for (i = 0; i < table->rows; ++i) {
4639 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4640 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4641 if (strcmp (val, n) == 0)
4642 break;
4644 g_free (n);
4645 if (i == table->rows)
4646 return FALSE;
4648 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4649 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4651 else {
4652 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4653 case MONO_IMPLEMENTATION_FILE:
4654 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4655 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4656 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4657 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4658 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4659 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4660 info->location = 0;
4661 else
4662 info->location = RESOURCE_LOCATION_EMBEDDED;
4663 break;
4665 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4666 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4667 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4668 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4669 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4670 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4671 g_free (msg);
4672 mono_raise_exception (ex);
4674 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4676 /* Obtain info recursively */
4677 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4678 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4679 break;
4681 case MONO_IMPLEMENTATION_EXP_TYPE:
4682 g_assert_not_reached ();
4683 break;
4687 return TRUE;
4690 static MonoObject*
4691 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4693 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4694 MonoArray *result = NULL;
4695 int i, count;
4696 const char *val;
4697 char *n;
4699 MONO_ARCH_SAVE_REGS;
4701 /* check hash if needed */
4702 if (name) {
4703 n = mono_string_to_utf8 (name);
4704 for (i = 0; i < table->rows; ++i) {
4705 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4706 if (strcmp (val, n) == 0) {
4707 MonoString *fn;
4708 g_free (n);
4709 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4710 fn = mono_string_new (mono_object_domain (assembly), n);
4711 g_free (n);
4712 return (MonoObject*)fn;
4715 g_free (n);
4716 return NULL;
4719 count = 0;
4720 for (i = 0; i < table->rows; ++i) {
4721 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4722 count ++;
4725 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4727 count = 0;
4728 for (i = 0; i < table->rows; ++i) {
4729 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4730 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4731 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4732 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4733 g_free (n);
4734 count ++;
4737 return (MonoObject*)result;
4740 static MonoArray*
4741 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4743 MonoDomain *domain = mono_domain_get();
4744 MonoArray *res;
4745 MonoClass *klass;
4746 int i, j, file_count = 0;
4747 MonoImage **modules;
4748 guint32 module_count, real_module_count;
4749 MonoTableInfo *table;
4750 guint32 cols [MONO_FILE_SIZE];
4751 MonoImage *image = assembly->assembly->image;
4753 g_assert (image != NULL);
4754 g_assert (!assembly->assembly->dynamic);
4756 table = &image->tables [MONO_TABLE_FILE];
4757 file_count = table->rows;
4759 modules = image->modules;
4760 module_count = image->module_count;
4762 real_module_count = 0;
4763 for (i = 0; i < module_count; ++i)
4764 if (modules [i])
4765 real_module_count ++;
4767 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4768 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4770 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4771 j = 1;
4772 for (i = 0; i < module_count; ++i)
4773 if (modules [i]) {
4774 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4775 ++j;
4778 for (i = 0; i < file_count; ++i, ++j) {
4779 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4780 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4781 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4782 else {
4783 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4784 if (!m) {
4785 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4786 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4788 mono_array_setref (res, j, mono_module_get_object (domain, m));
4792 return res;
4795 static MonoReflectionMethod*
4796 ves_icall_GetCurrentMethod (void)
4798 MonoMethod *m = mono_method_get_last_managed ();
4800 while (m->is_inflated)
4801 m = ((MonoMethodInflated*)m)->declaring;
4803 return mono_method_get_object (mono_domain_get (), m, NULL);
4807 static MonoMethod*
4808 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4810 int offset = -1, i;
4811 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4812 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4813 //method is inflated, we should inflate it on the other class
4814 MonoGenericContext ctx;
4815 ctx.method_inst = inflated->context.method_inst;
4816 ctx.class_inst = inflated->context.class_inst;
4817 if (klass->generic_class)
4818 ctx.class_inst = klass->generic_class->context.class_inst;
4819 else if (klass->generic_container)
4820 ctx.class_inst = klass->generic_container->context.class_inst;
4821 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4824 mono_class_setup_methods (method->klass);
4825 if (method->klass->exception_type)
4826 return NULL;
4827 for (i = 0; i < method->klass->method.count; ++i) {
4828 if (method->klass->methods [i] == method) {
4829 offset = i;
4830 break;
4833 mono_class_setup_methods (klass);
4834 if (klass->exception_type)
4835 return NULL;
4836 g_assert (offset >= 0 && offset < klass->method.count);
4837 return klass->methods [offset];
4840 static MonoReflectionMethod*
4841 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4843 MonoClass *klass;
4844 if (type) {
4845 klass = mono_class_from_mono_type (type);
4846 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4847 return NULL;
4848 if (method->klass != klass) {
4849 method = mono_method_get_equivalent_method (method, klass);
4850 if (!method)
4851 return NULL;
4853 } else
4854 klass = method->klass;
4855 return mono_method_get_object (mono_domain_get (), method, klass);
4858 static MonoReflectionMethod*
4859 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4861 return mono_method_get_object (mono_domain_get (), method, NULL);
4864 static MonoReflectionMethodBody*
4865 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4867 return mono_method_body_get_object (mono_domain_get (), method);
4870 static MonoReflectionAssembly*
4871 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4873 MonoMethod *dest = NULL;
4875 MONO_ARCH_SAVE_REGS;
4877 mono_stack_walk_no_il (get_executing, &dest);
4878 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4882 static MonoReflectionAssembly*
4883 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4885 MonoDomain* domain = mono_domain_get ();
4887 MONO_ARCH_SAVE_REGS;
4889 if (!domain->entry_assembly)
4890 return NULL;
4892 return mono_assembly_get_object (domain, domain->entry_assembly);
4895 static MonoReflectionAssembly*
4896 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4898 MonoMethod *m;
4899 MonoMethod *dest;
4901 MONO_ARCH_SAVE_REGS;
4903 dest = NULL;
4904 mono_stack_walk_no_il (get_executing, &dest);
4905 m = dest;
4906 mono_stack_walk_no_il (get_caller, &dest);
4907 if (!dest)
4908 dest = m;
4909 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4912 static MonoString *
4913 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4914 gboolean assembly_qualified)
4916 MonoDomain *domain = mono_object_domain (object);
4917 MonoTypeNameFormat format;
4918 MonoString *res;
4919 gchar *name;
4921 if (full_name)
4922 format = assembly_qualified ?
4923 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4924 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4925 else
4926 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4928 name = mono_type_get_name_full (object->type, format);
4929 if (!name)
4930 return NULL;
4932 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4933 g_free (name);
4934 return NULL;
4937 res = mono_string_new (domain, name);
4938 g_free (name);
4940 return res;
4943 static int
4944 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4946 MonoClass *klass = mono_class_from_mono_type (this->type);
4947 mono_class_init_or_throw (klass);
4948 return mono_security_core_clr_class_level (klass);
4951 static void
4952 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4954 static MonoMethod *create_culture = NULL;
4955 gpointer args [2];
4956 guint32 pkey_len;
4957 const char *pkey_ptr;
4958 gchar *codebase;
4959 MonoBoolean assembly_ref = 0;
4961 MONO_ARCH_SAVE_REGS;
4963 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4964 aname->major = name->major;
4965 aname->minor = name->minor;
4966 aname->build = name->build;
4967 aname->flags = name->flags;
4968 aname->revision = name->revision;
4969 aname->hashalg = name->hash_alg;
4970 aname->versioncompat = 1; /* SameMachine (default) */
4971 aname->processor_architecture = name->arch;
4973 if (by_default_version)
4974 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4976 codebase = NULL;
4977 if (absolute != NULL && *absolute != '\0') {
4978 const gchar *prepend = "file://";
4979 gchar *result;
4981 codebase = g_strdup (absolute);
4983 #if HOST_WIN32
4985 gint i;
4986 for (i = strlen (codebase) - 1; i >= 0; i--)
4987 if (codebase [i] == '\\')
4988 codebase [i] = '/';
4990 if (*codebase == '/' && *(codebase + 1) == '/') {
4991 prepend = "file:";
4992 } else {
4993 prepend = "file:///";
4996 #endif
4997 result = g_strconcat (prepend, codebase, NULL);
4998 g_free (codebase);
4999 codebase = result;
5002 if (codebase) {
5003 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5004 g_free (codebase);
5007 if (!create_culture) {
5008 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5009 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5010 g_assert (create_culture);
5011 mono_method_desc_free (desc);
5014 if (name->culture) {
5015 args [0] = mono_string_new (domain, name->culture);
5016 args [1] = &assembly_ref;
5017 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5020 if (name->public_key) {
5021 pkey_ptr = (char*)name->public_key;
5022 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5024 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5025 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5026 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5027 } else if (default_publickey) {
5028 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5029 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5032 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5033 if (name->public_key_token [0]) {
5034 int i, j;
5035 char *p;
5037 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5038 p = mono_array_addr (aname->keyToken, char, 0);
5040 for (i = 0, j = 0; i < 8; i++) {
5041 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5042 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5043 p++;
5045 } else if (default_token) {
5046 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5050 static MonoString *
5051 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5053 MonoDomain *domain = mono_object_domain (assembly);
5054 MonoAssembly *mass = assembly->assembly;
5055 MonoString *res;
5056 gchar *name;
5058 name = mono_stringify_assembly_name (&mass->aname);
5059 res = mono_string_new (domain, name);
5060 g_free (name);
5062 return res;
5065 static void
5066 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5068 gchar *absolute;
5069 MonoAssembly *mass = assembly->assembly;
5071 MONO_ARCH_SAVE_REGS;
5073 if (g_path_is_absolute (mass->image->name)) {
5074 fill_reflection_assembly_name (mono_object_domain (assembly),
5075 aname, &mass->aname, mass->image->name, TRUE,
5076 TRUE, TRUE);
5077 return;
5079 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5081 fill_reflection_assembly_name (mono_object_domain (assembly),
5082 aname, &mass->aname, absolute, TRUE, TRUE,
5083 TRUE);
5085 g_free (absolute);
5088 static void
5089 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5091 char *filename;
5092 MonoImageOpenStatus status = MONO_IMAGE_OK;
5093 gboolean res;
5094 MonoImage *image;
5095 MonoAssemblyName name;
5096 char *dirname
5098 MONO_ARCH_SAVE_REGS;
5100 filename = mono_string_to_utf8 (fname);
5102 dirname = g_path_get_dirname (filename);
5103 replace_shadow_path (mono_domain_get (), dirname, &filename);
5104 g_free (dirname);
5106 image = mono_image_open (filename, &status);
5108 if (!image){
5109 MonoException *exc;
5111 g_free (filename);
5112 if (status == MONO_IMAGE_IMAGE_INVALID)
5113 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5114 else
5115 exc = mono_get_exception_file_not_found2 (NULL, fname);
5116 mono_raise_exception (exc);
5119 res = mono_assembly_fill_assembly_name (image, &name);
5120 if (!res) {
5121 mono_image_close (image);
5122 g_free (filename);
5123 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5126 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5127 TRUE, FALSE, TRUE);
5129 g_free (filename);
5130 mono_image_close (image);
5133 static MonoBoolean
5134 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5135 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5137 MonoBoolean result = FALSE;
5138 MonoDeclSecurityEntry entry;
5140 /* SecurityAction.RequestMinimum */
5141 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5142 *minimum = entry.blob;
5143 *minLength = entry.size;
5144 result = TRUE;
5146 /* SecurityAction.RequestOptional */
5147 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5148 *optional = entry.blob;
5149 *optLength = entry.size;
5150 result = TRUE;
5152 /* SecurityAction.RequestRefuse */
5153 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5154 *refused = entry.blob;
5155 *refLength = entry.size;
5156 result = TRUE;
5159 return result;
5162 static MonoArray*
5163 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5165 MonoArray *res;
5166 MonoClass *klass;
5167 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5168 int i, count;
5169 guint32 attrs, visibility;
5171 /* we start the count from 1 because we skip the special type <Module> */
5172 if (exportedOnly) {
5173 count = 0;
5174 for (i = 1; i < tdef->rows; ++i) {
5175 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5176 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5177 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5178 count++;
5180 } else {
5181 count = tdef->rows - 1;
5183 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5184 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5185 count = 0;
5186 for (i = 1; i < tdef->rows; ++i) {
5187 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5188 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5189 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5190 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5191 if (klass) {
5192 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5193 } else {
5194 MonoLoaderError *error;
5195 MonoException *ex;
5197 error = mono_loader_get_last_error ();
5198 g_assert (error != NULL);
5200 ex = mono_loader_error_prepare_exception (error);
5201 mono_array_setref (*exceptions, count, ex);
5203 if (mono_loader_get_last_error ())
5204 mono_loader_clear_error ();
5205 count++;
5209 return res;
5212 static MonoArray*
5213 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5215 MonoArray *res = NULL;
5216 MonoArray *exceptions = NULL;
5217 MonoImage *image = NULL;
5218 MonoTableInfo *table = NULL;
5219 MonoDomain *domain;
5220 GList *list = NULL;
5221 int i, len, ex_count;
5223 MONO_ARCH_SAVE_REGS;
5225 domain = mono_object_domain (assembly);
5227 g_assert (!assembly->assembly->dynamic);
5228 image = assembly->assembly->image;
5229 table = &image->tables [MONO_TABLE_FILE];
5230 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5232 /* Append data from all modules in the assembly */
5233 for (i = 0; i < table->rows; ++i) {
5234 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5235 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5236 if (loaded_image) {
5237 MonoArray *ex2;
5238 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5239 /* Append the new types to the end of the array */
5240 if (mono_array_length (res2) > 0) {
5241 guint32 len1, len2;
5242 MonoArray *res3, *ex3;
5244 len1 = mono_array_length (res);
5245 len2 = mono_array_length (res2);
5247 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5248 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5249 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5250 res = res3;
5252 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5253 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5254 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5255 exceptions = ex3;
5261 /* the ReflectionTypeLoadException must have all the types (Types property),
5262 * NULL replacing types which throws an exception. The LoaderException must
5263 * contain all exceptions for NULL items.
5266 len = mono_array_length (res);
5268 ex_count = 0;
5269 for (i = 0; i < len; i++) {
5270 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5271 MonoClass *klass;
5273 if (t) {
5274 klass = mono_type_get_class (t->type);
5275 if ((klass != NULL) && klass->exception_type) {
5276 /* keep the class in the list */
5277 list = g_list_append (list, klass);
5278 /* and replace Type with NULL */
5279 mono_array_setref (res, i, NULL);
5281 } else {
5282 ex_count ++;
5286 if (list || ex_count) {
5287 GList *tmp = NULL;
5288 MonoException *exc = NULL;
5289 MonoArray *exl = NULL;
5290 int j, length = g_list_length (list) + ex_count;
5292 mono_loader_clear_error ();
5294 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5295 /* Types for which mono_class_get () succeeded */
5296 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5297 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5298 mono_array_setref (exl, i, exc);
5300 /* Types for which it don't */
5301 for (j = 0; j < mono_array_length (exceptions); ++j) {
5302 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5303 if (exc) {
5304 g_assert (i < length);
5305 mono_array_setref (exl, i, exc);
5306 i ++;
5309 g_list_free (list);
5310 list = NULL;
5312 exc = mono_get_exception_reflection_type_load (res, exl);
5313 mono_loader_clear_error ();
5314 mono_raise_exception (exc);
5317 return res;
5320 static gboolean
5321 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5323 MonoAssemblyName aname;
5324 MonoDomain *domain = mono_object_domain (name);
5325 char *val;
5326 gboolean is_version_defined;
5327 gboolean is_token_defined;
5329 aname.public_key = NULL;
5330 val = mono_string_to_utf8 (assname);
5331 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5332 g_free ((guint8*) aname.public_key);
5333 g_free (val);
5334 return FALSE;
5337 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5338 FALSE, is_token_defined);
5340 mono_assembly_name_free (&aname);
5341 g_free ((guint8*) aname.public_key);
5342 g_free (val);
5344 return TRUE;
5347 static MonoReflectionType*
5348 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5350 MonoDomain *domain = mono_object_domain (module);
5351 MonoClass *klass;
5353 MONO_ARCH_SAVE_REGS;
5355 g_assert (module->image);
5357 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5358 /* These images do not have a global type */
5359 return NULL;
5361 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5362 return mono_type_get_object (domain, &klass->byval_arg);
5365 static void
5366 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5368 /*if (module->image)
5369 mono_image_close (module->image);*/
5372 static MonoString*
5373 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5375 MonoDomain *domain = mono_object_domain (module);
5377 MONO_ARCH_SAVE_REGS;
5379 g_assert (module->image);
5380 return mono_string_new (domain, module->image->guid);
5383 static gpointer
5384 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5386 #ifdef HOST_WIN32
5387 if (module->image && module->image->is_module_handle)
5388 return module->image->raw_data;
5389 #endif
5391 return (gpointer) (-1);
5394 static void
5395 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5397 if (image->dynamic) {
5398 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5399 *pe_kind = dyn->pe_kind;
5400 *machine = dyn->machine;
5402 else {
5403 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5404 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5408 static gint32
5409 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5411 return (image->md_version_major << 16) | (image->md_version_minor);
5414 static MonoArray*
5415 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5417 MonoArray *exceptions;
5418 int i;
5420 MONO_ARCH_SAVE_REGS;
5422 if (!module->image)
5423 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5424 else {
5425 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5426 for (i = 0; i < mono_array_length (exceptions); ++i) {
5427 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5428 if (ex)
5429 mono_raise_exception (ex);
5431 return res;
5435 static gboolean
5436 mono_memberref_is_method (MonoImage *image, guint32 token)
5438 if (!image->dynamic) {
5439 guint32 cols [MONO_MEMBERREF_SIZE];
5440 const char *sig;
5441 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5442 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5443 mono_metadata_decode_blob_size (sig, &sig);
5444 return (*sig != 0x6);
5445 } else {
5446 MonoClass *handle_class;
5448 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5449 return FALSE;
5451 return mono_defaults.methodhandle_class == handle_class;
5455 static void
5456 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5458 if (type_args)
5459 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5460 mono_array_addr (type_args, MonoType*, 0));
5461 else
5462 context->class_inst = NULL;
5463 if (method_args)
5464 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5465 mono_array_addr (method_args, MonoType*, 0));
5466 else
5467 context->method_inst = NULL;
5470 static MonoType*
5471 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5473 MonoClass *klass;
5474 int table = mono_metadata_token_table (token);
5475 int index = mono_metadata_token_index (token);
5476 MonoGenericContext context;
5478 *error = ResolveTokenError_Other;
5480 /* Validate token */
5481 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5482 (table != MONO_TABLE_TYPESPEC)) {
5483 *error = ResolveTokenError_BadTable;
5484 return NULL;
5487 if (image->dynamic) {
5488 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5489 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5490 return klass ? &klass->byval_arg : NULL;
5493 init_generic_context_from_args (&context, type_args, method_args);
5494 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5495 return klass ? &klass->byval_arg : NULL;
5498 if ((index <= 0) || (index > image->tables [table].rows)) {
5499 *error = ResolveTokenError_OutOfRange;
5500 return NULL;
5503 init_generic_context_from_args (&context, type_args, method_args);
5504 klass = mono_class_get_full (image, token, &context);
5506 if (mono_loader_get_last_error ())
5507 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5509 if (klass)
5510 return &klass->byval_arg;
5511 else
5512 return NULL;
5515 static MonoMethod*
5516 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5518 int table = mono_metadata_token_table (token);
5519 int index = mono_metadata_token_index (token);
5520 MonoGenericContext context;
5521 MonoMethod *method;
5523 *error = ResolveTokenError_Other;
5525 /* Validate token */
5526 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5527 (table != MONO_TABLE_MEMBERREF)) {
5528 *error = ResolveTokenError_BadTable;
5529 return NULL;
5532 if (image->dynamic) {
5533 if (table == MONO_TABLE_METHOD)
5534 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5536 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5537 *error = ResolveTokenError_BadTable;
5538 return NULL;
5541 init_generic_context_from_args (&context, type_args, method_args);
5542 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5545 if ((index <= 0) || (index > image->tables [table].rows)) {
5546 *error = ResolveTokenError_OutOfRange;
5547 return NULL;
5549 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5550 *error = ResolveTokenError_BadTable;
5551 return NULL;
5554 init_generic_context_from_args (&context, type_args, method_args);
5555 method = mono_get_method_full (image, token, NULL, &context);
5557 if (mono_loader_get_last_error ())
5558 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5560 return method;
5563 static MonoString*
5564 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5566 int index = mono_metadata_token_index (token);
5568 *error = ResolveTokenError_Other;
5570 /* Validate token */
5571 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5572 *error = ResolveTokenError_BadTable;
5573 return NULL;
5576 if (image->dynamic)
5577 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5579 if ((index <= 0) || (index >= image->heap_us.size)) {
5580 *error = ResolveTokenError_OutOfRange;
5581 return NULL;
5584 /* FIXME: What to do if the index points into the middle of a string ? */
5586 return mono_ldstr (mono_domain_get (), image, index);
5589 static MonoClassField*
5590 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5592 MonoClass *klass;
5593 int table = mono_metadata_token_table (token);
5594 int index = mono_metadata_token_index (token);
5595 MonoGenericContext context;
5596 MonoClassField *field;
5598 *error = ResolveTokenError_Other;
5600 /* Validate token */
5601 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5602 *error = ResolveTokenError_BadTable;
5603 return NULL;
5606 if (image->dynamic) {
5607 if (table == MONO_TABLE_FIELD)
5608 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5610 if (mono_memberref_is_method (image, token)) {
5611 *error = ResolveTokenError_BadTable;
5612 return NULL;
5615 init_generic_context_from_args (&context, type_args, method_args);
5616 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5619 if ((index <= 0) || (index > image->tables [table].rows)) {
5620 *error = ResolveTokenError_OutOfRange;
5621 return NULL;
5623 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5624 *error = ResolveTokenError_BadTable;
5625 return NULL;
5628 init_generic_context_from_args (&context, type_args, method_args);
5629 field = mono_field_from_token (image, token, &klass, &context);
5631 if (mono_loader_get_last_error ())
5632 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5634 return field;
5638 static MonoObject*
5639 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5641 int table = mono_metadata_token_table (token);
5643 *error = ResolveTokenError_Other;
5645 switch (table) {
5646 case MONO_TABLE_TYPEDEF:
5647 case MONO_TABLE_TYPEREF:
5648 case MONO_TABLE_TYPESPEC: {
5649 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5650 if (t)
5651 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5652 else
5653 return NULL;
5655 case MONO_TABLE_METHOD:
5656 case MONO_TABLE_METHODSPEC: {
5657 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5658 if (m)
5659 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5660 else
5661 return NULL;
5663 case MONO_TABLE_FIELD: {
5664 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5665 if (f)
5666 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5667 else
5668 return NULL;
5670 case MONO_TABLE_MEMBERREF:
5671 if (mono_memberref_is_method (image, token)) {
5672 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5673 if (m)
5674 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5675 else
5676 return NULL;
5678 else {
5679 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5680 if (f)
5681 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5682 else
5683 return NULL;
5685 break;
5687 default:
5688 *error = ResolveTokenError_BadTable;
5691 return NULL;
5694 static MonoArray*
5695 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5697 int table = mono_metadata_token_table (token);
5698 int idx = mono_metadata_token_index (token);
5699 MonoTableInfo *tables = image->tables;
5700 guint32 sig, len;
5701 const char *ptr;
5702 MonoArray *res;
5704 *error = ResolveTokenError_OutOfRange;
5706 /* FIXME: Support other tables ? */
5707 if (table != MONO_TABLE_STANDALONESIG)
5708 return NULL;
5710 if (image->dynamic)
5711 return NULL;
5713 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5714 return NULL;
5716 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5718 ptr = mono_metadata_blob_heap (image, sig);
5719 len = mono_metadata_decode_blob_size (ptr, &ptr);
5721 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5722 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5723 return res;
5726 static MonoReflectionType*
5727 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5729 MonoClass *klass;
5730 int isbyref = 0, rank;
5731 char *str = mono_string_to_utf8 (smodifiers);
5732 char *p;
5734 MONO_ARCH_SAVE_REGS;
5736 klass = mono_class_from_mono_type (tb->type.type);
5737 p = str;
5738 /* logic taken from mono_reflection_parse_type(): keep in sync */
5739 while (*p) {
5740 switch (*p) {
5741 case '&':
5742 if (isbyref) { /* only one level allowed by the spec */
5743 g_free (str);
5744 return NULL;
5746 isbyref = 1;
5747 p++;
5748 g_free (str);
5749 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5750 break;
5751 case '*':
5752 klass = mono_ptr_class_get (&klass->byval_arg);
5753 mono_class_init (klass);
5754 p++;
5755 break;
5756 case '[':
5757 rank = 1;
5758 p++;
5759 while (*p) {
5760 if (*p == ']')
5761 break;
5762 if (*p == ',')
5763 rank++;
5764 else if (*p != '*') { /* '*' means unknown lower bound */
5765 g_free (str);
5766 return NULL;
5768 ++p;
5770 if (*p != ']') {
5771 g_free (str);
5772 return NULL;
5774 p++;
5775 klass = mono_array_class_get (klass, rank);
5776 mono_class_init (klass);
5777 break;
5778 default:
5779 break;
5782 g_free (str);
5783 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5786 static MonoBoolean
5787 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5789 MonoType *type;
5790 MonoBoolean res;
5792 MONO_ARCH_SAVE_REGS;
5794 type = t->type;
5795 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5797 return res;
5800 static void
5801 check_for_invalid_type (MonoClass *klass)
5803 char *name;
5804 MonoString *str;
5805 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5806 return;
5808 name = mono_type_get_full_name (klass);
5809 str = mono_string_new (mono_domain_get (), name);
5810 g_free (name);
5811 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5814 static MonoReflectionType *
5815 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5817 MonoClass *klass, *aklass;
5819 MONO_ARCH_SAVE_REGS;
5821 klass = mono_class_from_mono_type (type->type);
5822 check_for_invalid_type (klass);
5824 if (rank == 0) //single dimentional array
5825 aklass = mono_array_class_get (klass, 1);
5826 else
5827 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5829 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5832 static MonoReflectionType *
5833 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5835 MonoClass *klass;
5837 MONO_ARCH_SAVE_REGS;
5839 klass = mono_class_from_mono_type (type->type);
5840 mono_class_init_or_throw (klass);
5841 check_for_invalid_type (klass);
5843 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5846 static MonoReflectionType *
5847 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5849 MonoClass *klass, *pklass;
5851 klass = mono_class_from_mono_type (type->type);
5852 mono_class_init_or_throw (klass);
5853 check_for_invalid_type (klass);
5855 pklass = mono_ptr_class_get (type->type);
5857 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5860 static MonoObject *
5861 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5862 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5864 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5865 MonoObject *delegate;
5866 gpointer func;
5867 MonoMethod *method = info->method;
5869 MONO_ARCH_SAVE_REGS;
5871 mono_class_init_or_throw (delegate_class);
5873 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5875 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5876 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5877 return NULL;
5880 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5882 if (method->dynamic) {
5883 /* Creating a trampoline would leak memory */
5884 func = mono_compile_method (method);
5885 } else {
5886 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5887 method = mono_object_get_virtual_method (target, method);
5888 func = mono_create_ftnptr (mono_domain_get (),
5889 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5892 mono_delegate_ctor_with_method (delegate, target, func, method);
5894 return delegate;
5897 static void
5898 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5900 /* Reset the invoke impl to the default one */
5901 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5905 * Magic number to convert a time which is relative to
5906 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5908 #define EPOCH_ADJUST ((guint64)62135596800LL)
5911 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5913 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5915 #ifdef HOST_WIN32
5916 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5917 static void
5918 convert_to_absolute_date(SYSTEMTIME *date)
5920 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5921 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5922 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5923 /* from the calendar FAQ */
5924 int a = (14 - date->wMonth) / 12;
5925 int y = date->wYear - a;
5926 int m = date->wMonth + 12 * a - 2;
5927 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5929 /* d is now the day of the week for the first of the month (0 == Sunday) */
5931 int day_of_week = date->wDayOfWeek;
5933 /* set day_in_month to the first day in the month which falls on day_of_week */
5934 int day_in_month = 1 + (day_of_week - d);
5935 if (day_in_month <= 0)
5936 day_in_month += 7;
5938 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5939 date->wDay = day_in_month + (date->wDay - 1) * 7;
5940 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5941 date->wDay -= 7;
5943 #endif
5945 #ifndef HOST_WIN32
5947 * Return's the offset from GMT of a local time.
5949 * tm is a local time
5950 * t is the same local time as seconds.
5952 static int
5953 gmt_offset(struct tm *tm, time_t t)
5955 #if defined (HAVE_TM_GMTOFF)
5956 return tm->tm_gmtoff;
5957 #else
5958 struct tm g;
5959 time_t t2;
5960 g = *gmtime(&t);
5961 g.tm_isdst = tm->tm_isdst;
5962 t2 = mktime(&g);
5963 return (int)difftime(t, t2);
5964 #endif
5966 #endif
5968 * This is heavily based on zdump.c from glibc 2.2.
5970 * * data[0]: start of daylight saving time (in DateTime ticks).
5971 * * data[1]: end of daylight saving time (in DateTime ticks).
5972 * * data[2]: utcoffset (in TimeSpan ticks).
5973 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5974 * * name[0]: name of this timezone when not daylight saving.
5975 * * name[1]: name of this timezone when daylight saving.
5977 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5978 * the class library allows years between 1 and 9999.
5980 * Returns true on success and zero on failure.
5982 static guint32
5983 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5985 #ifndef HOST_WIN32
5986 MonoDomain *domain = mono_domain_get ();
5987 struct tm start, tt;
5988 time_t t;
5990 long int gmtoff;
5991 int is_daylight = 0, day;
5992 char tzone [64];
5994 MONO_ARCH_SAVE_REGS;
5996 MONO_CHECK_ARG_NULL (data);
5997 MONO_CHECK_ARG_NULL (names);
5999 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
6000 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
6003 * no info is better than crashing: we'll need our own tz data
6004 * to make this work properly, anyway. The range is probably
6005 * reduced to 1970 .. 2037 because that is what mktime is
6006 * guaranteed to support (we get into an infinite loop
6007 * otherwise).
6010 memset (&start, 0, sizeof (start));
6012 start.tm_mday = 1;
6013 start.tm_year = year-1900;
6015 t = mktime (&start);
6017 if ((year < 1970) || (year > 2037) || (t == -1)) {
6018 t = time (NULL);
6019 tt = *localtime (&t);
6020 strftime (tzone, sizeof (tzone), "%Z", &tt);
6021 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6022 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6023 return 1;
6026 gmtoff = gmt_offset (&start, t);
6028 /* For each day of the year, calculate the tm_gmtoff. */
6029 for (day = 0; day < 365; day++) {
6031 t += 3600*24;
6032 tt = *localtime (&t);
6034 /* Daylight saving starts or ends here. */
6035 if (gmt_offset (&tt, t) != gmtoff) {
6036 struct tm tt1;
6037 time_t t1;
6039 /* Try to find the exact hour when daylight saving starts/ends. */
6040 t1 = t;
6041 do {
6042 t1 -= 3600;
6043 tt1 = *localtime (&t1);
6044 } while (gmt_offset (&tt1, t1) != gmtoff);
6046 /* Try to find the exact minute when daylight saving starts/ends. */
6047 do {
6048 t1 += 60;
6049 tt1 = *localtime (&t1);
6050 } while (gmt_offset (&tt1, t1) == gmtoff);
6051 t1+=gmtoff;
6052 strftime (tzone, sizeof (tzone), "%Z", &tt);
6054 /* Write data, if we're already in daylight saving, we're done. */
6055 if (is_daylight) {
6056 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6057 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6058 return 1;
6059 } else {
6060 struct tm end;
6061 time_t te;
6063 memset (&end, 0, sizeof (end));
6064 end.tm_year = year-1900 + 1;
6065 end.tm_mday = 1;
6067 te = mktime (&end);
6069 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6070 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6071 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6072 mono_array_set ((*data), gint64, 1, ((gint64)te + EPOCH_ADJUST) * 10000000L);
6073 is_daylight = 1;
6076 /* This is only set once when we enter daylight saving. */
6077 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6078 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6080 gmtoff = gmt_offset (&tt, t);
6084 if (!is_daylight) {
6085 strftime (tzone, sizeof (tzone), "%Z", &tt);
6086 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6087 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6088 mono_array_set ((*data), gint64, 0, 0);
6089 mono_array_set ((*data), gint64, 1, 0);
6090 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6091 mono_array_set ((*data), gint64, 3, 0);
6094 return 1;
6095 #else
6096 MonoDomain *domain = mono_domain_get ();
6097 TIME_ZONE_INFORMATION tz_info;
6098 FILETIME ft;
6099 int i;
6100 int err, tz_id;
6102 tz_id = GetTimeZoneInformation (&tz_info);
6103 if (tz_id == TIME_ZONE_ID_INVALID)
6104 return 0;
6106 MONO_CHECK_ARG_NULL (data);
6107 MONO_CHECK_ARG_NULL (names);
6109 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6110 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6112 for (i = 0; i < 32; ++i)
6113 if (!tz_info.DaylightName [i])
6114 break;
6115 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6116 for (i = 0; i < 32; ++i)
6117 if (!tz_info.StandardName [i])
6118 break;
6119 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6121 if ((year <= 1601) || (year > 30827)) {
6123 * According to MSDN, the MS time functions can't handle dates outside
6124 * this interval.
6126 return 1;
6129 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6130 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6131 tz_info.StandardDate.wYear = year;
6132 convert_to_absolute_date(&tz_info.StandardDate);
6133 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6134 //g_assert(err);
6135 if (err == 0)
6136 return 0;
6138 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6139 tz_info.DaylightDate.wYear = year;
6140 convert_to_absolute_date(&tz_info.DaylightDate);
6141 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6142 //g_assert(err);
6143 if (err == 0)
6144 return 0;
6146 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6148 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6149 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6151 return 1;
6152 #endif
6155 static gpointer
6156 ves_icall_System_Object_obj_address (MonoObject *this)
6158 MONO_ARCH_SAVE_REGS;
6160 return this;
6163 /* System.Buffer */
6165 static inline gint32
6166 mono_array_get_byte_length (MonoArray *array)
6168 MonoClass *klass;
6169 int length;
6170 int i;
6172 klass = array->obj.vtable->klass;
6174 if (array->bounds == NULL)
6175 length = array->max_length;
6176 else {
6177 length = 1;
6178 for (i = 0; i < klass->rank; ++ i)
6179 length *= array->bounds [i].length;
6182 switch (klass->element_class->byval_arg.type) {
6183 case MONO_TYPE_I1:
6184 case MONO_TYPE_U1:
6185 case MONO_TYPE_BOOLEAN:
6186 return length;
6187 case MONO_TYPE_I2:
6188 case MONO_TYPE_U2:
6189 case MONO_TYPE_CHAR:
6190 return length << 1;
6191 case MONO_TYPE_I4:
6192 case MONO_TYPE_U4:
6193 case MONO_TYPE_R4:
6194 return length << 2;
6195 case MONO_TYPE_I:
6196 case MONO_TYPE_U:
6197 return length * sizeof (gpointer);
6198 case MONO_TYPE_I8:
6199 case MONO_TYPE_U8:
6200 case MONO_TYPE_R8:
6201 return length << 3;
6202 default:
6203 return -1;
6207 static gint32
6208 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6210 MONO_ARCH_SAVE_REGS;
6212 return mono_array_get_byte_length (array);
6215 static gint8
6216 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6218 MONO_ARCH_SAVE_REGS;
6220 return mono_array_get (array, gint8, idx);
6223 static void
6224 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6226 MONO_ARCH_SAVE_REGS;
6228 mono_array_set (array, gint8, idx, value);
6231 static MonoBoolean
6232 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6234 guint8 *src_buf, *dest_buf;
6236 MONO_ARCH_SAVE_REGS;
6238 /* This is called directly from the class libraries without going through the managed wrapper */
6239 MONO_CHECK_ARG_NULL (src);
6240 MONO_CHECK_ARG_NULL (dest);
6242 /* watch out for integer overflow */
6243 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6244 return FALSE;
6246 src_buf = (guint8 *)src->vector + src_offset;
6247 dest_buf = (guint8 *)dest->vector + dest_offset;
6249 if (src != dest)
6250 memcpy (dest_buf, src_buf, count);
6251 else
6252 mono_gc_memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6254 return TRUE;
6257 static MonoObject *
6258 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6260 MonoDomain *domain = mono_object_domain (this);
6261 MonoObject *res;
6262 MonoRealProxy *rp = ((MonoRealProxy *)this);
6263 MonoTransparentProxy *tp;
6264 MonoType *type;
6265 MonoClass *klass;
6267 MONO_ARCH_SAVE_REGS;
6269 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6270 tp = (MonoTransparentProxy*) res;
6272 MONO_OBJECT_SETREF (tp, rp, rp);
6273 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6274 klass = mono_class_from_mono_type (type);
6276 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6277 tp->remote_class = mono_remote_class (domain, class_name, klass);
6279 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6280 return res;
6283 static MonoReflectionType *
6284 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6286 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6289 /* System.Environment */
6291 MonoString*
6292 ves_icall_System_Environment_get_UserName (void)
6294 MONO_ARCH_SAVE_REGS;
6296 /* using glib is more portable */
6297 return mono_string_new (mono_domain_get (), g_get_user_name ());
6301 static MonoString *
6302 ves_icall_System_Environment_get_MachineName (void)
6304 #if defined (HOST_WIN32)
6305 gunichar2 *buf;
6306 guint32 len;
6307 MonoString *result;
6309 len = MAX_COMPUTERNAME_LENGTH + 1;
6310 buf = g_new (gunichar2, len);
6312 result = NULL;
6313 if (GetComputerName (buf, (PDWORD) &len))
6314 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6316 g_free (buf);
6317 return result;
6318 #elif !defined(DISABLE_SOCKETS)
6319 gchar buf [256];
6320 MonoString *result;
6322 if (gethostname (buf, sizeof (buf)) == 0)
6323 result = mono_string_new (mono_domain_get (), buf);
6324 else
6325 result = NULL;
6327 return result;
6328 #else
6329 return mono_string_new (mono_domain_get (), "mono");
6330 #endif
6333 static int
6334 ves_icall_System_Environment_get_Platform (void)
6336 #if defined (TARGET_WIN32)
6337 /* Win32NT */
6338 return 2;
6339 #elif defined(__MACH__)
6340 /* OSX */
6342 // Notice that the value is hidden from user code, and only exposed
6343 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6344 // define and making assumptions based on Unix/128/4 values before there
6345 // was a MacOS define. Lots of code would assume that not-Unix meant
6346 // Windows, but in this case, it would be OSX.
6348 return 6;
6349 #else
6350 /* Unix */
6351 return 4;
6352 #endif
6355 static MonoString *
6356 ves_icall_System_Environment_get_NewLine (void)
6358 MONO_ARCH_SAVE_REGS;
6360 #if defined (HOST_WIN32)
6361 return mono_string_new (mono_domain_get (), "\r\n");
6362 #else
6363 return mono_string_new (mono_domain_get (), "\n");
6364 #endif
6367 static MonoString *
6368 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6370 const gchar *value;
6371 gchar *utf8_name;
6373 MONO_ARCH_SAVE_REGS;
6375 if (name == NULL)
6376 return NULL;
6378 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6379 value = g_getenv (utf8_name);
6381 g_free (utf8_name);
6383 if (value == 0)
6384 return NULL;
6386 return mono_string_new (mono_domain_get (), value);
6390 * There is no standard way to get at environ.
6392 #ifndef _MSC_VER
6393 #ifndef __MINGW32_VERSION
6394 #if defined(__APPLE__) && !defined (__arm__)
6395 /* Apple defines this in crt_externs.h but doesn't provide that header for
6396 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6397 * in fact exist on all implementations (so far)
6399 gchar ***_NSGetEnviron(void);
6400 #define environ (*_NSGetEnviron())
6401 #else
6402 extern
6403 char **environ;
6404 #endif
6405 #endif
6406 #endif
6408 static MonoArray *
6409 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6411 #ifdef HOST_WIN32
6412 MonoArray *names;
6413 MonoDomain *domain;
6414 MonoString *str;
6415 WCHAR* env_strings;
6416 WCHAR* env_string;
6417 WCHAR* equal_str;
6418 int n = 0;
6420 env_strings = GetEnvironmentStrings();
6422 if (env_strings) {
6423 env_string = env_strings;
6424 while (*env_string != '\0') {
6425 /* weird case that MS seems to skip */
6426 if (*env_string != '=')
6427 n++;
6428 while (*env_string != '\0')
6429 env_string++;
6430 env_string++;
6434 domain = mono_domain_get ();
6435 names = mono_array_new (domain, mono_defaults.string_class, n);
6437 if (env_strings) {
6438 n = 0;
6439 env_string = env_strings;
6440 while (*env_string != '\0') {
6441 /* weird case that MS seems to skip */
6442 if (*env_string != '=') {
6443 equal_str = wcschr(env_string, '=');
6444 g_assert(equal_str);
6445 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6446 mono_array_setref (names, n, str);
6447 n++;
6449 while (*env_string != '\0')
6450 env_string++;
6451 env_string++;
6454 FreeEnvironmentStrings (env_strings);
6457 return names;
6459 #else
6460 MonoArray *names;
6461 MonoDomain *domain;
6462 MonoString *str;
6463 gchar **e, **parts;
6464 int n;
6466 MONO_ARCH_SAVE_REGS;
6468 n = 0;
6469 for (e = environ; *e != 0; ++ e)
6470 ++ n;
6472 domain = mono_domain_get ();
6473 names = mono_array_new (domain, mono_defaults.string_class, n);
6475 n = 0;
6476 for (e = environ; *e != 0; ++ e) {
6477 parts = g_strsplit (*e, "=", 2);
6478 if (*parts != 0) {
6479 str = mono_string_new (domain, *parts);
6480 mono_array_setref (names, n, str);
6483 g_strfreev (parts);
6485 ++ n;
6488 return names;
6489 #endif
6493 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6495 #if !GLIB_CHECK_VERSION(2,4,0)
6496 #define g_setenv(a,b,c) setenv(a,b,c)
6497 #define g_unsetenv(a) unsetenv(a)
6498 #endif
6500 static void
6501 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6503 MonoError error;
6504 #ifdef HOST_WIN32
6506 gunichar2 *utf16_name, *utf16_value;
6507 #else
6508 gchar *utf8_name, *utf8_value;
6509 #endif
6511 MONO_ARCH_SAVE_REGS;
6513 #ifdef HOST_WIN32
6514 utf16_name = mono_string_to_utf16 (name);
6515 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6516 SetEnvironmentVariable (utf16_name, NULL);
6517 g_free (utf16_name);
6518 return;
6521 utf16_value = mono_string_to_utf16 (value);
6523 SetEnvironmentVariable (utf16_name, utf16_value);
6525 g_free (utf16_name);
6526 g_free (utf16_value);
6527 #else
6528 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6530 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6531 g_unsetenv (utf8_name);
6532 g_free (utf8_name);
6533 return;
6536 utf8_value = mono_string_to_utf8_checked (value, &error);
6537 if (!mono_error_ok (&error)) {
6538 g_free (utf8_name);
6539 mono_error_raise_exception (&error);
6541 g_setenv (utf8_name, utf8_value, TRUE);
6543 g_free (utf8_name);
6544 g_free (utf8_value);
6545 #endif
6548 static void
6549 ves_icall_System_Environment_Exit (int result)
6551 MONO_ARCH_SAVE_REGS;
6553 mono_threads_set_shutting_down ();
6555 mono_runtime_set_shutting_down ();
6557 /* This will kill the tp threads which cannot be suspended */
6558 mono_thread_pool_cleanup ();
6560 /* Suspend all managed threads since the runtime is going away */
6561 mono_thread_suspend_all_other_threads ();
6563 mono_runtime_quit ();
6565 /* we may need to do some cleanup here... */
6566 exit (result);
6569 static MonoString*
6570 ves_icall_System_Environment_GetGacPath (void)
6572 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6575 static MonoString*
6576 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6578 #if defined (HOST_WIN32)
6579 #ifndef CSIDL_FLAG_CREATE
6580 #define CSIDL_FLAG_CREATE 0x8000
6581 #endif
6583 WCHAR path [MAX_PATH];
6584 /* Create directory if no existing */
6585 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6586 int len = 0;
6587 while (path [len])
6588 ++ len;
6589 return mono_string_new_utf16 (mono_domain_get (), path, len);
6591 #else
6592 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6593 #endif
6594 return mono_string_new (mono_domain_get (), "");
6597 static MonoArray *
6598 ves_icall_System_Environment_GetLogicalDrives (void)
6600 gunichar2 buf [256], *ptr, *dname;
6601 gunichar2 *u16;
6602 guint initial_size = 127, size = 128;
6603 gint ndrives;
6604 MonoArray *result;
6605 MonoString *drivestr;
6606 MonoDomain *domain = mono_domain_get ();
6607 gint len;
6609 MONO_ARCH_SAVE_REGS;
6611 buf [0] = '\0';
6612 ptr = buf;
6614 while (size > initial_size) {
6615 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6616 if (size > initial_size) {
6617 if (ptr != buf)
6618 g_free (ptr);
6619 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6620 initial_size = size;
6621 size++;
6625 /* Count strings */
6626 dname = ptr;
6627 ndrives = 0;
6628 do {
6629 while (*dname++);
6630 ndrives++;
6631 } while (*dname);
6633 dname = ptr;
6634 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6635 ndrives = 0;
6636 do {
6637 len = 0;
6638 u16 = dname;
6639 while (*u16) { u16++; len ++; }
6640 drivestr = mono_string_new_utf16 (domain, dname, len);
6641 mono_array_setref (result, ndrives++, drivestr);
6642 while (*dname++);
6643 } while (*dname);
6645 if (ptr != buf)
6646 g_free (ptr);
6648 return result;
6651 static MonoString *
6652 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6654 gunichar2 volume_name [MAX_PATH + 1];
6656 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6657 return NULL;
6658 /* Not sure using wcslen here is safe */
6659 return mono_string_from_utf16 (volume_name);
6662 static MonoString *
6663 ves_icall_System_Environment_InternalGetHome (void)
6665 MONO_ARCH_SAVE_REGS;
6667 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6670 static const char *encodings [] = {
6671 (char *) 1,
6672 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6673 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6674 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6675 (char *) 2,
6676 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6677 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6678 "x_unicode_2_0_utf_7",
6679 (char *) 3,
6680 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6681 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6682 (char *) 4,
6683 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6684 "iso_10646_ucs2",
6685 (char *) 5,
6686 "unicodefffe", "utf_16be",
6687 (char *) 6,
6688 "iso_8859_1",
6689 (char *) 0
6693 * Returns the internal codepage, if the value of "int_code_page" is
6694 * 1 at entry, and we can not compute a suitable code page number,
6695 * returns the code page as a string
6697 static MonoString*
6698 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6700 const char *cset;
6701 const char *p;
6702 char *c;
6703 char *codepage = NULL;
6704 int code;
6705 int want_name = *int_code_page;
6706 int i;
6708 *int_code_page = -1;
6709 MONO_ARCH_SAVE_REGS;
6711 g_get_charset (&cset);
6712 c = codepage = strdup (cset);
6713 for (c = codepage; *c; c++){
6714 if (isascii (*c) && isalpha (*c))
6715 *c = tolower (*c);
6716 if (*c == '-')
6717 *c = '_';
6719 /* g_print ("charset: %s\n", cset); */
6721 /* handle some common aliases */
6722 p = encodings [0];
6723 code = 0;
6724 for (i = 0; p != 0; ){
6725 if ((gssize) p < 7){
6726 code = (gssize) p;
6727 p = encodings [++i];
6728 continue;
6730 if (strcmp (p, codepage) == 0){
6731 *int_code_page = code;
6732 break;
6734 p = encodings [++i];
6737 if (strstr (codepage, "utf_8") != NULL)
6738 *int_code_page |= 0x10000000;
6739 free (codepage);
6741 if (want_name && *int_code_page == -1)
6742 return mono_string_new (mono_domain_get (), cset);
6743 else
6744 return NULL;
6747 static MonoBoolean
6748 ves_icall_System_Environment_get_HasShutdownStarted (void)
6750 if (mono_runtime_is_shutting_down ())
6751 return TRUE;
6753 if (mono_domain_is_unloading (mono_domain_get ()))
6754 return TRUE;
6756 return FALSE;
6759 static void
6760 ves_icall_System_Environment_BroadcastSettingChange (void)
6762 #ifdef HOST_WIN32
6763 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6764 #endif
6767 static void
6768 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6769 MonoReflectionMethod *method,
6770 MonoArray *out_args)
6772 MONO_ARCH_SAVE_REGS;
6774 mono_message_init (mono_object_domain (this), this, method, out_args);
6777 static MonoBoolean
6778 ves_icall_IsTransparentProxy (MonoObject *proxy)
6780 MONO_ARCH_SAVE_REGS;
6782 if (!proxy)
6783 return 0;
6785 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6786 return 1;
6788 return 0;
6791 static MonoReflectionMethod *
6792 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6793 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6795 MonoClass *klass;
6796 MonoMethod *method;
6797 MonoMethod **vtable;
6798 MonoMethod *res = NULL;
6800 MONO_CHECK_ARG_NULL (rtype);
6801 MONO_CHECK_ARG_NULL (rmethod);
6803 method = rmethod->method;
6804 klass = mono_class_from_mono_type (rtype->type);
6805 mono_class_init_or_throw (klass);
6807 if (MONO_CLASS_IS_INTERFACE (klass))
6808 return NULL;
6810 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6811 return NULL;
6813 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6814 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6815 return rmethod;
6816 else
6817 return NULL;
6820 mono_class_setup_vtable (klass);
6821 vtable = klass->vtable;
6823 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6824 gboolean variance_used = FALSE;
6825 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6826 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6827 if (offs >= 0)
6828 res = vtable [offs + method->slot];
6829 } else {
6830 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6831 return NULL;
6833 if (method->slot != -1)
6834 res = vtable [method->slot];
6837 if (!res)
6838 return NULL;
6840 return mono_method_get_object (mono_domain_get (), res, NULL);
6843 static void
6844 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6846 MonoClass *klass;
6847 MonoVTable* vtable;
6849 MONO_ARCH_SAVE_REGS;
6851 klass = mono_class_from_mono_type (type->type);
6852 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6854 if (enable) vtable->remote = 1;
6855 else vtable->remote = 0;
6858 static MonoObject *
6859 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6861 MonoClass *klass;
6862 MonoDomain *domain;
6864 MONO_ARCH_SAVE_REGS;
6866 domain = mono_object_domain (type);
6867 klass = mono_class_from_mono_type (type->type);
6868 mono_class_init_or_throw (klass);
6870 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6871 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6873 if (klass->rank >= 1) {
6874 g_assert (klass->rank == 1);
6875 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6876 } else {
6877 /* Bypass remoting object creation check */
6878 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6882 static MonoString *
6883 ves_icall_System_IO_get_temp_path (void)
6885 MONO_ARCH_SAVE_REGS;
6887 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6890 #ifndef PLATFORM_NO_DRIVEINFO
6891 static MonoBoolean
6892 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6893 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6894 gint32 *error)
6896 gboolean result;
6897 ULARGE_INTEGER wapi_free_bytes_avail;
6898 ULARGE_INTEGER wapi_total_number_of_bytes;
6899 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6901 MONO_ARCH_SAVE_REGS;
6903 *error = ERROR_SUCCESS;
6904 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6905 &wapi_total_number_of_free_bytes);
6907 if (result) {
6908 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6909 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6910 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6911 } else {
6912 *free_bytes_avail = 0;
6913 *total_number_of_bytes = 0;
6914 *total_number_of_free_bytes = 0;
6915 *error = GetLastError ();
6918 return result;
6921 static guint32
6922 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6924 MONO_ARCH_SAVE_REGS;
6926 return GetDriveType (mono_string_chars (root_path_name));
6928 #endif
6930 static gpointer
6931 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6933 MONO_ARCH_SAVE_REGS;
6935 return mono_compile_method (method);
6938 static MonoString *
6939 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6941 MonoString *mcpath;
6942 gchar *path;
6944 MONO_ARCH_SAVE_REGS;
6946 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6948 #if defined (HOST_WIN32)
6949 /* Avoid mixing '/' and '\\' */
6951 gint i;
6952 for (i = strlen (path) - 1; i >= 0; i--)
6953 if (path [i] == '/')
6954 path [i] = '\\';
6956 #endif
6957 mcpath = mono_string_new (mono_domain_get (), path);
6958 g_free (path);
6960 return mcpath;
6963 static MonoString *
6964 get_bundled_app_config (void)
6966 const gchar *app_config;
6967 MonoDomain *domain;
6968 MonoString *file;
6969 gchar *config_file_name, *config_file_path;
6970 gsize len;
6971 gchar *module;
6973 MONO_ARCH_SAVE_REGS;
6975 domain = mono_domain_get ();
6976 file = domain->setup->configuration_file;
6977 if (!file)
6978 return NULL;
6980 // Retrieve config file and remove the extension
6981 config_file_name = mono_string_to_utf8 (file);
6982 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6983 if (!config_file_path)
6984 config_file_path = config_file_name;
6985 len = strlen (config_file_path) - strlen (".config");
6986 module = g_malloc0 (len + 1);
6987 memcpy (module, config_file_path, len);
6988 // Get the config file from the module name
6989 app_config = mono_config_string_for_assembly_file (module);
6990 // Clean-up
6991 g_free (module);
6992 if (config_file_name != config_file_path)
6993 g_free (config_file_name);
6994 g_free (config_file_path);
6996 if (!app_config)
6997 return NULL;
6999 return mono_string_new (mono_domain_get (), app_config);
7002 static MonoString *
7003 get_bundled_machine_config (void)
7005 const gchar *machine_config;
7007 MONO_ARCH_SAVE_REGS;
7009 machine_config = mono_get_machine_config ();
7011 if (!machine_config)
7012 return NULL;
7014 return mono_string_new (mono_domain_get (), machine_config);
7017 static MonoString *
7018 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7020 MonoString *ipath;
7021 gchar *path;
7023 MONO_ARCH_SAVE_REGS;
7025 path = g_path_get_dirname (mono_get_config_dir ());
7027 #if defined (HOST_WIN32)
7028 /* Avoid mixing '/' and '\\' */
7030 gint i;
7031 for (i = strlen (path) - 1; i >= 0; i--)
7032 if (path [i] == '/')
7033 path [i] = '\\';
7035 #endif
7036 ipath = mono_string_new (mono_domain_get (), path);
7037 g_free (path);
7039 return ipath;
7042 static gboolean
7043 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7045 MonoPEResourceDataEntry *entry;
7046 MonoImage *image;
7048 MONO_ARCH_SAVE_REGS;
7050 if (!assembly || !result || !size)
7051 return FALSE;
7053 *result = NULL;
7054 *size = 0;
7055 image = assembly->assembly->image;
7056 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7057 if (!entry)
7058 return FALSE;
7060 *result = mono_image_rva_map (image, entry->rde_data_offset);
7061 if (!(*result)) {
7062 g_free (entry);
7063 return FALSE;
7065 *size = entry->rde_size;
7066 g_free (entry);
7067 return TRUE;
7070 static MonoBoolean
7071 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7073 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
7076 static void
7077 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7079 #if defined (HOST_WIN32)
7080 OutputDebugString (mono_string_chars (message));
7081 #else
7082 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7083 #endif
7086 /* Only used for value types */
7087 static MonoObject *
7088 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7090 MonoClass *klass;
7091 MonoDomain *domain;
7093 MONO_ARCH_SAVE_REGS;
7095 domain = mono_object_domain (type);
7096 klass = mono_class_from_mono_type (type->type);
7097 mono_class_init_or_throw (klass);
7099 if (mono_class_is_nullable (klass))
7100 /* No arguments -> null */
7101 return NULL;
7103 return mono_object_new (domain, klass);
7106 static MonoReflectionMethod *
7107 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7109 MonoClass *klass, *parent;
7110 MonoMethod *method = m->method;
7111 MonoMethod *result = NULL;
7112 int slot;
7114 MONO_ARCH_SAVE_REGS;
7116 if (method->klass == NULL)
7117 return m;
7119 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7120 MONO_CLASS_IS_INTERFACE (method->klass) ||
7121 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7122 return m;
7124 slot = mono_method_get_vtable_slot (method);
7125 if (slot == -1)
7126 return m;
7128 klass = method->klass;
7129 if (klass->generic_class)
7130 klass = klass->generic_class->container_class;
7132 if (definition) {
7133 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7134 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7135 mono_class_setup_vtable (parent);
7136 if (parent->vtable_size <= slot)
7137 break;
7138 klass = parent;
7140 } else {
7141 klass = klass->parent;
7142 if (!klass)
7143 return m;
7146 if (klass == method->klass)
7147 return m;
7149 /*This is possible if definition == FALSE.
7150 * Do it here to be really sure we don't read invalid memory.
7152 if (slot >= klass->vtable_size)
7153 return m;
7155 mono_class_setup_vtable (klass);
7157 result = klass->vtable [slot];
7158 if (result == NULL) {
7159 /* It is an abstract method */
7160 gpointer iter = NULL;
7161 while ((result = mono_class_get_methods (klass, &iter)))
7162 if (result->slot == slot)
7163 break;
7166 if (result == NULL)
7167 return m;
7169 return mono_method_get_object (mono_domain_get (), result, NULL);
7172 static MonoString*
7173 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7175 MonoMethod *method = m->method;
7177 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7178 return m->name;
7181 static void
7182 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7184 MONO_ARCH_SAVE_REGS;
7186 iter->sig = *(MonoMethodSignature**)argsp;
7188 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7189 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7191 iter->next_arg = 0;
7192 /* FIXME: it's not documented what start is exactly... */
7193 if (start) {
7194 iter->args = start;
7195 } else {
7196 iter->args = argsp + sizeof (gpointer);
7198 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7200 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7203 static MonoTypedRef
7204 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7206 guint32 i, arg_size;
7207 gint32 align;
7208 MonoTypedRef res;
7209 MONO_ARCH_SAVE_REGS;
7211 i = iter->sig->sentinelpos + iter->next_arg;
7213 g_assert (i < iter->sig->param_count);
7215 res.type = iter->sig->params [i];
7216 res.klass = mono_class_from_mono_type (res.type);
7217 res.value = iter->args;
7218 arg_size = mono_type_stack_size (res.type, &align);
7219 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7220 if (arg_size <= sizeof (gpointer)) {
7221 int dummy;
7222 int padding = arg_size - mono_type_size (res.type, &dummy);
7223 res.value = (guint8*)res.value + padding;
7225 #endif
7226 iter->args = (char*)iter->args + arg_size;
7227 iter->next_arg++;
7229 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7231 return res;
7234 static MonoTypedRef
7235 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7237 guint32 i, arg_size;
7238 gint32 align;
7239 MonoTypedRef res;
7240 MONO_ARCH_SAVE_REGS;
7242 i = iter->sig->sentinelpos + iter->next_arg;
7244 g_assert (i < iter->sig->param_count);
7246 while (i < iter->sig->param_count) {
7247 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7248 continue;
7249 res.type = iter->sig->params [i];
7250 res.klass = mono_class_from_mono_type (res.type);
7251 /* FIXME: endianess issue... */
7252 res.value = iter->args;
7253 arg_size = mono_type_stack_size (res.type, &align);
7254 iter->args = (char*)iter->args + arg_size;
7255 iter->next_arg++;
7256 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7257 return res;
7259 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7261 res.type = NULL;
7262 res.value = NULL;
7263 res.klass = NULL;
7264 return res;
7267 static MonoType*
7268 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7270 gint i;
7271 MONO_ARCH_SAVE_REGS;
7273 i = iter->sig->sentinelpos + iter->next_arg;
7275 g_assert (i < iter->sig->param_count);
7277 return iter->sig->params [i];
7280 static MonoObject*
7281 mono_TypedReference_ToObject (MonoTypedRef tref)
7283 MONO_ARCH_SAVE_REGS;
7285 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7286 MonoObject** objp = tref.value;
7287 return *objp;
7290 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7293 static MonoObject*
7294 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7296 MONO_ARCH_SAVE_REGS;
7298 if (MONO_TYPE_IS_REFERENCE (type)) {
7299 MonoObject** objp = value;
7300 return *objp;
7303 return mono_value_box (mono_domain_get (), klass, value);
7306 static void
7307 prelink_method (MonoMethod *method)
7309 const char *exc_class, *exc_arg;
7310 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7311 return;
7312 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7313 if (exc_class) {
7314 mono_raise_exception(
7315 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7317 /* create the wrapper, too? */
7320 static void
7321 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7323 MONO_ARCH_SAVE_REGS;
7324 prelink_method (method->method);
7327 static void
7328 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7330 MonoClass *klass = mono_class_from_mono_type (type->type);
7331 MonoMethod* m;
7332 gpointer iter = NULL;
7333 MONO_ARCH_SAVE_REGS;
7335 mono_class_init_or_throw (klass);
7337 while ((m = mono_class_get_methods (klass, &iter)))
7338 prelink_method (m);
7341 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7342 static void
7343 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7344 gint32 const **exponents,
7345 gunichar2 const **digitLowerTable,
7346 gunichar2 const **digitUpperTable,
7347 gint64 const **tenPowersList,
7348 gint32 const **decHexDigits)
7350 *mantissas = Formatter_MantissaBitsTable;
7351 *exponents = Formatter_TensExponentTable;
7352 *digitLowerTable = Formatter_DigitLowerTable;
7353 *digitUpperTable = Formatter_DigitUpperTable;
7354 *tenPowersList = Formatter_TenPowersList;
7355 *decHexDigits = Formatter_DecHexDigits;
7358 /* These parameters are "readonly" in corlib/System/Char.cs */
7359 static void
7360 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7361 guint8 const **numeric_data,
7362 gdouble const **numeric_data_values,
7363 guint16 const **to_lower_data_low,
7364 guint16 const **to_lower_data_high,
7365 guint16 const **to_upper_data_low,
7366 guint16 const **to_upper_data_high)
7368 *category_data = CategoryData;
7369 *numeric_data = NumericData;
7370 *numeric_data_values = NumericDataValues;
7371 *to_lower_data_low = ToLowerDataLow;
7372 *to_lower_data_high = ToLowerDataHigh;
7373 *to_upper_data_low = ToUpperDataLow;
7374 *to_upper_data_high = ToUpperDataHigh;
7377 static gint32
7378 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7380 return method->method->token;
7384 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7385 * and avoid useless allocations.
7387 static MonoArray*
7388 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7390 MonoArray *res;
7391 int i, count = 0;
7392 for (i = 0; i < type->num_mods; ++i) {
7393 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7394 count++;
7396 if (!count)
7397 return NULL;
7398 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7399 count = 0;
7400 for (i = 0; i < type->num_mods; ++i) {
7401 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7402 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7403 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7404 count++;
7407 return res;
7410 static MonoArray*
7411 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7413 MonoType *type = param->ClassImpl->type;
7414 MonoClass *member_class = mono_object_class (param->MemberImpl);
7415 MonoMethod *method = NULL;
7416 MonoImage *image;
7417 int pos;
7418 MonoMethodSignature *sig;
7420 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7421 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7422 method = rmethod->method;
7423 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7424 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7425 if (!(method = prop->property->get))
7426 method = prop->property->set;
7427 g_assert (method);
7428 } else {
7429 char *type_name = mono_type_get_full_name (member_class);
7430 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7431 MonoException *ex = mono_get_exception_not_supported (msg);
7432 g_free (type_name);
7433 g_free (msg);
7434 mono_raise_exception (ex);
7437 image = method->klass->image;
7438 pos = param->PositionImpl;
7439 sig = mono_method_signature (method);
7440 if (pos == -1)
7441 type = sig->ret;
7442 else
7443 type = sig->params [pos];
7445 return type_array_from_modifiers (image, type, optional);
7448 static MonoType*
7449 get_property_type (MonoProperty *prop)
7451 MonoMethodSignature *sig;
7452 if (prop->get) {
7453 sig = mono_method_signature (prop->get);
7454 return sig->ret;
7455 } else if (prop->set) {
7456 sig = mono_method_signature (prop->set);
7457 return sig->params [sig->param_count - 1];
7459 return NULL;
7462 static MonoArray*
7463 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7465 MonoType *type = get_property_type (property->property);
7466 MonoImage *image = property->klass->image;
7468 if (!type)
7469 return NULL;
7470 return type_array_from_modifiers (image, type, optional);
7474 *Construct a MonoType suited to be used to decode a constant blob object.
7476 * @type is the target type which will be constructed
7477 * @blob_type is the blob type, for example, that comes from the constant table
7478 * @real_type is the expected constructed type.
7480 static void
7481 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7483 type->type = blob_type;
7484 type->data.klass = NULL;
7485 if (blob_type == MONO_TYPE_CLASS)
7486 type->data.klass = mono_defaults.object_class;
7487 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7488 /* For enums, we need to use the base type */
7489 type->type = MONO_TYPE_VALUETYPE;
7490 type->data.klass = mono_class_from_mono_type (real_type);
7491 } else
7492 type->data.klass = mono_class_from_mono_type (real_type);
7495 static MonoObject*
7496 property_info_get_default_value (MonoReflectionProperty *property)
7498 MonoType blob_type;
7499 MonoProperty *prop = property->property;
7500 MonoType *type = get_property_type (prop);
7501 MonoDomain *domain = mono_object_domain (property);
7502 MonoTypeEnum def_type;
7503 const char *def_value;
7504 MonoObject *o;
7506 mono_class_init (prop->parent);
7508 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7509 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7511 def_value = mono_class_get_property_default_value (prop, &def_type);
7513 mono_type_from_blob_type (&blob_type, def_type, type);
7514 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7516 return o;
7519 static MonoBoolean
7520 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7522 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7523 MonoCustomAttrInfo *cinfo;
7524 gboolean found;
7526 mono_class_init_or_throw (attr_class);
7528 cinfo = mono_reflection_get_custom_attrs_info (obj);
7529 if (!cinfo)
7530 return FALSE;
7531 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7532 if (!cinfo->cached)
7533 mono_custom_attrs_free (cinfo);
7534 return found;
7537 static MonoArray*
7538 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7540 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7541 MonoArray *res;
7542 MonoError error;
7544 if (attr_class)
7545 mono_class_init_or_throw (attr_class);
7547 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7548 if (!mono_error_ok (&error))
7549 mono_error_raise_exception (&error);
7550 if (mono_loader_get_last_error ()) {
7551 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7552 g_assert_not_reached ();
7553 /* Not reached */
7554 return NULL;
7555 } else {
7556 return res;
7560 static MonoString*
7561 ves_icall_Mono_Runtime_GetDisplayName (void)
7563 char *info;
7564 MonoString *display_name;
7566 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7567 display_name = mono_string_new (mono_domain_get (), info);
7568 g_free (info);
7569 return display_name;
7572 static MonoString*
7573 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7575 MonoString *message;
7576 guint32 ret;
7577 gunichar2 buf[256];
7579 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7580 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7581 buf, 255, NULL);
7582 if (ret == 0) {
7583 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7584 } else {
7585 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7588 return message;
7591 const static guchar
7592 dbase64 [] = {
7593 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7594 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7595 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7596 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7597 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7598 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7599 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7600 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7603 static MonoArray *
7604 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7606 gint ignored;
7607 gint i;
7608 gunichar2 c;
7609 gunichar2 last, prev_last, prev2_last;
7610 gint olength;
7611 MonoArray *result;
7612 guchar *res_ptr;
7613 gint a [4], b [4];
7614 MonoException *exc;
7616 ignored = 0;
7617 last = prev_last = 0, prev2_last = 0;
7618 for (i = 0; i < ilength; i++) {
7619 c = start [i];
7620 if (c >= sizeof (dbase64)) {
7621 exc = mono_exception_from_name_msg (mono_get_corlib (),
7622 "System", "FormatException",
7623 "Invalid character found.");
7624 mono_raise_exception (exc);
7625 } else if (isspace (c)) {
7626 ignored++;
7627 } else {
7628 prev2_last = prev_last;
7629 prev_last = last;
7630 last = c;
7634 olength = ilength - ignored;
7636 if (allowWhitespaceOnly && olength == 0) {
7637 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7640 if ((olength & 3) != 0 || olength <= 0) {
7641 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7642 "FormatException", "Invalid length.");
7643 mono_raise_exception (exc);
7646 if (prev2_last == '=') {
7647 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7648 mono_raise_exception (exc);
7651 olength = (olength * 3) / 4;
7652 if (last == '=')
7653 olength--;
7655 if (prev_last == '=')
7656 olength--;
7658 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7659 res_ptr = mono_array_addr (result, guchar, 0);
7660 for (i = 0; i < ilength; ) {
7661 int k;
7663 for (k = 0; k < 4 && i < ilength;) {
7664 c = start [i++];
7665 if (isspace (c))
7666 continue;
7668 a [k] = (guchar) c;
7669 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7670 exc = mono_exception_from_name_msg (mono_get_corlib (),
7671 "System", "FormatException",
7672 "Invalid character found.");
7673 mono_raise_exception (exc);
7675 k++;
7678 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7679 if (a [2] != '=')
7680 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7681 if (a [3] != '=')
7682 *res_ptr++ = (b [2] << 6) | b [3];
7684 while (i < ilength && isspace (start [i]))
7685 i++;
7688 return result;
7691 static MonoArray *
7692 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7694 MONO_ARCH_SAVE_REGS;
7696 return base64_to_byte_array (mono_string_chars (str),
7697 mono_string_length (str), allowWhitespaceOnly);
7700 static MonoArray *
7701 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7703 MONO_ARCH_SAVE_REGS;
7705 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7706 length, FALSE);
7709 #define ICALL_TYPE(id,name,first)
7710 #define ICALL(id,name,func) Icall_ ## id,
7712 enum {
7713 #include "metadata/icall-def.h"
7714 Icall_last
7717 #undef ICALL_TYPE
7718 #undef ICALL
7719 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7720 #define ICALL(id,name,func)
7721 enum {
7722 #include "metadata/icall-def.h"
7723 Icall_type_num
7726 #undef ICALL_TYPE
7727 #undef ICALL
7728 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7729 #define ICALL(id,name,func)
7730 typedef struct {
7731 guint16 first_icall;
7732 } IcallTypeDesc;
7734 static const IcallTypeDesc
7735 icall_type_descs [] = {
7736 #include "metadata/icall-def.h"
7737 {Icall_last}
7740 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7742 #undef ICALL_TYPE
7743 #define ICALL_TYPE(id,name,first)
7744 #undef ICALL
7746 #ifdef HAVE_ARRAY_ELEM_INIT
7747 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7748 #define MSGSTRFIELD1(line) str##line
7750 static const struct msgstrtn_t {
7751 #define ICALL(id,name,func)
7752 #undef ICALL_TYPE
7753 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7754 #include "metadata/icall-def.h"
7755 #undef ICALL_TYPE
7756 } icall_type_names_str = {
7757 #define ICALL_TYPE(id,name,first) (name),
7758 #include "metadata/icall-def.h"
7759 #undef ICALL_TYPE
7761 static const guint16 icall_type_names_idx [] = {
7762 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7763 #include "metadata/icall-def.h"
7764 #undef ICALL_TYPE
7766 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7768 static const struct msgstr_t {
7769 #undef ICALL
7770 #define ICALL_TYPE(id,name,first)
7771 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7772 #include "metadata/icall-def.h"
7773 #undef ICALL
7774 } icall_names_str = {
7775 #define ICALL(id,name,func) (name),
7776 #include "metadata/icall-def.h"
7777 #undef ICALL
7779 static const guint16 icall_names_idx [] = {
7780 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7781 #include "metadata/icall-def.h"
7782 #undef ICALL
7784 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7786 #else
7788 #undef ICALL_TYPE
7789 #undef ICALL
7790 #define ICALL_TYPE(id,name,first) name,
7791 #define ICALL(id,name,func)
7792 static const char* const
7793 icall_type_names [] = {
7794 #include "metadata/icall-def.h"
7795 NULL
7798 #define icall_type_name_get(id) (icall_type_names [(id)])
7800 #undef ICALL_TYPE
7801 #undef ICALL
7802 #define ICALL_TYPE(id,name,first)
7803 #define ICALL(id,name,func) name,
7804 static const char* const
7805 icall_names [] = {
7806 #include "metadata/icall-def.h"
7807 NULL
7809 #define icall_name_get(id) icall_names [(id)]
7811 #endif /* !HAVE_ARRAY_ELEM_INIT */
7813 #undef ICALL_TYPE
7814 #undef ICALL
7815 #define ICALL_TYPE(id,name,first)
7816 #define ICALL(id,name,func) func,
7817 static const gconstpointer
7818 icall_functions [] = {
7819 #include "metadata/icall-def.h"
7820 NULL
7823 static GHashTable *icall_hash = NULL;
7824 static GHashTable *jit_icall_hash_name = NULL;
7825 static GHashTable *jit_icall_hash_addr = NULL;
7827 void
7828 mono_icall_init (void)
7830 int i = 0;
7832 /* check that tables are sorted: disable in release */
7833 if (TRUE) {
7834 int j;
7835 const char *prev_class = NULL;
7836 const char *prev_method;
7838 for (i = 0; i < Icall_type_num; ++i) {
7839 const IcallTypeDesc *desc;
7840 int num_icalls;
7841 prev_method = NULL;
7842 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7843 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7844 prev_class = icall_type_name_get (i);
7845 desc = &icall_type_descs [i];
7846 num_icalls = icall_desc_num_icalls (desc);
7847 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7848 for (j = 0; j < num_icalls; ++j) {
7849 const char *methodn = icall_name_get (desc->first_icall + j);
7850 if (prev_method && strcmp (prev_method, methodn) >= 0)
7851 g_print ("method %s should come before method %s\n", methodn, prev_method);
7852 prev_method = methodn;
7857 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7860 void
7861 mono_icall_cleanup (void)
7863 g_hash_table_destroy (icall_hash);
7864 g_hash_table_destroy (jit_icall_hash_name);
7865 g_hash_table_destroy (jit_icall_hash_addr);
7868 void
7869 mono_add_internal_call (const char *name, gconstpointer method)
7871 mono_loader_lock ();
7873 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7875 mono_loader_unlock ();
7878 #ifdef HAVE_ARRAY_ELEM_INIT
7879 static int
7880 compare_method_imap (const void *key, const void *elem)
7882 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7883 return strcmp (key, method_name);
7886 static gpointer
7887 find_method_icall (const IcallTypeDesc *imap, const char *name)
7889 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7890 if (!nameslot)
7891 return NULL;
7892 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7895 static int
7896 compare_class_imap (const void *key, const void *elem)
7898 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7899 return strcmp (key, class_name);
7902 static const IcallTypeDesc*
7903 find_class_icalls (const char *name)
7905 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7906 if (!nameslot)
7907 return NULL;
7908 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7911 #else
7912 static int
7913 compare_method_imap (const void *key, const void *elem)
7915 const char** method_name = (const char**)elem;
7916 return strcmp (key, *method_name);
7919 static gpointer
7920 find_method_icall (const IcallTypeDesc *imap, const char *name)
7922 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7923 if (!nameslot)
7924 return NULL;
7925 return (gpointer)icall_functions [(nameslot - icall_names)];
7928 static int
7929 compare_class_imap (const void *key, const void *elem)
7931 const char** class_name = (const char**)elem;
7932 return strcmp (key, *class_name);
7935 static const IcallTypeDesc*
7936 find_class_icalls (const char *name)
7938 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7939 if (!nameslot)
7940 return NULL;
7941 return &icall_type_descs [nameslot - icall_type_names];
7944 #endif
7947 * we should probably export this as an helper (handle nested types).
7948 * Returns the number of chars written in buf.
7950 static int
7951 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7953 int nspacelen, cnamelen;
7954 nspacelen = strlen (klass->name_space);
7955 cnamelen = strlen (klass->name);
7956 if (nspacelen + cnamelen + 2 > bufsize)
7957 return 0;
7958 if (nspacelen) {
7959 memcpy (buf, klass->name_space, nspacelen);
7960 buf [nspacelen ++] = '.';
7962 memcpy (buf + nspacelen, klass->name, cnamelen);
7963 buf [nspacelen + cnamelen] = 0;
7964 return nspacelen + cnamelen;
7967 gpointer
7968 mono_lookup_internal_call (MonoMethod *method)
7970 char *sigstart;
7971 char *tmpsig;
7972 char mname [2048];
7973 int typelen = 0, mlen, siglen;
7974 gpointer res;
7975 const IcallTypeDesc *imap;
7977 g_assert (method != NULL);
7979 if (method->is_inflated)
7980 method = ((MonoMethodInflated *) method)->declaring;
7982 if (method->klass->nested_in) {
7983 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7984 if (!pos)
7985 return NULL;
7987 mname [pos++] = '/';
7988 mname [pos] = 0;
7990 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7991 if (!typelen)
7992 return NULL;
7994 typelen += pos;
7995 } else {
7996 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7997 if (!typelen)
7998 return NULL;
8001 imap = find_class_icalls (mname);
8003 mname [typelen] = ':';
8004 mname [typelen + 1] = ':';
8006 mlen = strlen (method->name);
8007 memcpy (mname + typelen + 2, method->name, mlen);
8008 sigstart = mname + typelen + 2 + mlen;
8009 *sigstart = 0;
8011 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8012 siglen = strlen (tmpsig);
8013 if (typelen + mlen + siglen + 6 > sizeof (mname))
8014 return NULL;
8015 sigstart [0] = '(';
8016 memcpy (sigstart + 1, tmpsig, siglen);
8017 sigstart [siglen + 1] = ')';
8018 sigstart [siglen + 2] = 0;
8019 g_free (tmpsig);
8021 mono_loader_lock ();
8023 res = g_hash_table_lookup (icall_hash, mname);
8024 if (res) {
8025 mono_loader_unlock ();
8026 return res;
8028 /* try without signature */
8029 *sigstart = 0;
8030 res = g_hash_table_lookup (icall_hash, mname);
8031 if (res) {
8032 mono_loader_unlock ();
8033 return res;
8036 /* it wasn't found in the static call tables */
8037 if (!imap) {
8038 mono_loader_unlock ();
8039 return NULL;
8041 res = find_method_icall (imap, sigstart - mlen);
8042 if (res) {
8043 mono_loader_unlock ();
8044 return res;
8046 /* try _with_ signature */
8047 *sigstart = '(';
8048 res = find_method_icall (imap, sigstart - mlen);
8049 if (res) {
8050 mono_loader_unlock ();
8051 return res;
8054 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8055 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8056 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8057 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8058 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");
8059 g_print ("If you see other errors or faults after this message they are probably related\n");
8060 g_print ("and you need to fix your mono install first.\n");
8062 mono_loader_unlock ();
8064 return NULL;
8067 static MonoType*
8068 type_from_typename (char *typename)
8070 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8072 if (!strcmp (typename, "int"))
8073 klass = mono_defaults.int_class;
8074 else if (!strcmp (typename, "ptr"))
8075 klass = mono_defaults.int_class;
8076 else if (!strcmp (typename, "void"))
8077 klass = mono_defaults.void_class;
8078 else if (!strcmp (typename, "int32"))
8079 klass = mono_defaults.int32_class;
8080 else if (!strcmp (typename, "uint32"))
8081 klass = mono_defaults.uint32_class;
8082 else if (!strcmp (typename, "int8"))
8083 klass = mono_defaults.sbyte_class;
8084 else if (!strcmp (typename, "uint8"))
8085 klass = mono_defaults.byte_class;
8086 else if (!strcmp (typename, "int16"))
8087 klass = mono_defaults.int16_class;
8088 else if (!strcmp (typename, "uint16"))
8089 klass = mono_defaults.uint16_class;
8090 else if (!strcmp (typename, "long"))
8091 klass = mono_defaults.int64_class;
8092 else if (!strcmp (typename, "ulong"))
8093 klass = mono_defaults.uint64_class;
8094 else if (!strcmp (typename, "float"))
8095 klass = mono_defaults.single_class;
8096 else if (!strcmp (typename, "double"))
8097 klass = mono_defaults.double_class;
8098 else if (!strcmp (typename, "object"))
8099 klass = mono_defaults.object_class;
8100 else if (!strcmp (typename, "obj"))
8101 klass = mono_defaults.object_class;
8102 else if (!strcmp (typename, "string"))
8103 klass = mono_defaults.string_class;
8104 else if (!strcmp (typename, "bool"))
8105 klass = mono_defaults.boolean_class;
8106 else if (!strcmp (typename, "boolean"))
8107 klass = mono_defaults.boolean_class;
8108 else {
8109 g_error ("%s", typename);
8110 g_assert_not_reached ();
8112 return &klass->byval_arg;
8115 MonoMethodSignature*
8116 mono_create_icall_signature (const char *sigstr)
8118 gchar **parts;
8119 int i, len;
8120 gchar **tmp;
8121 MonoMethodSignature *res;
8123 mono_loader_lock ();
8124 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8125 if (res) {
8126 mono_loader_unlock ();
8127 return res;
8130 parts = g_strsplit (sigstr, " ", 256);
8132 tmp = parts;
8133 len = 0;
8134 while (*tmp) {
8135 len ++;
8136 tmp ++;
8139 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8140 res->pinvoke = 1;
8142 #ifdef HOST_WIN32
8144 * Under windows, the default pinvoke calling convention is STDCALL but
8145 * we need CDECL.
8147 res->call_convention = MONO_CALL_C;
8148 #endif
8150 res->ret = type_from_typename (parts [0]);
8151 for (i = 1; i < len; ++i) {
8152 res->params [i - 1] = type_from_typename (parts [i]);
8155 g_strfreev (parts);
8157 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8159 mono_loader_unlock ();
8161 return res;
8164 MonoJitICallInfo *
8165 mono_find_jit_icall_by_name (const char *name)
8167 MonoJitICallInfo *info;
8168 g_assert (jit_icall_hash_name);
8170 mono_loader_lock ();
8171 info = g_hash_table_lookup (jit_icall_hash_name, name);
8172 mono_loader_unlock ();
8173 return info;
8176 MonoJitICallInfo *
8177 mono_find_jit_icall_by_addr (gconstpointer addr)
8179 MonoJitICallInfo *info;
8180 g_assert (jit_icall_hash_addr);
8182 mono_loader_lock ();
8183 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8184 mono_loader_unlock ();
8186 return info;
8190 * mono_get_jit_icall_info:
8192 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8193 * caller should access it while holding the loader lock.
8195 GHashTable*
8196 mono_get_jit_icall_info (void)
8198 return jit_icall_hash_name;
8201 void
8202 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8204 mono_loader_lock ();
8205 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8206 mono_loader_unlock ();
8209 MonoJitICallInfo *
8210 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8212 MonoJitICallInfo *info;
8214 g_assert (func);
8215 g_assert (name);
8217 mono_loader_lock ();
8219 if (!jit_icall_hash_name) {
8220 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8221 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8224 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8225 g_warning ("jit icall already defined \"%s\"\n", name);
8226 g_assert_not_reached ();
8229 info = g_new0 (MonoJitICallInfo, 1);
8231 info->name = name;
8232 info->func = func;
8233 info->sig = sig;
8235 if (is_save) {
8236 info->wrapper = func;
8237 } else {
8238 info->wrapper = NULL;
8241 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8242 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8244 mono_loader_unlock ();
8245 return info;