2007-04-06 Andreas Faerber <andreas.faerber@web.de>
[mono.git] / mono / metadata / icall.c
blobdd3ada567236c752a92a9e0a9512b4b5820cb38b
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 * (C) 2001 Ximian, Inc.
12 #include <config.h>
13 #include <glib.h>
14 #include <stdarg.h>
15 #include <string.h>
16 #include <ctype.h>
17 #include <sys/time.h>
18 #include <unistd.h>
19 #if defined (PLATFORM_WIN32)
20 #include <stdlib.h>
21 #endif
23 #include <mono/metadata/object.h>
24 #include <mono/metadata/threads.h>
25 #include <mono/metadata/threads-types.h>
26 #include <mono/metadata/threadpool.h>
27 #include <mono/metadata/monitor.h>
28 #include <mono/metadata/reflection.h>
29 #include <mono/metadata/assembly.h>
30 #include <mono/metadata/tabledefs.h>
31 #include <mono/metadata/exception.h>
32 #include <mono/metadata/file-io.h>
33 #include <mono/metadata/console-io.h>
34 #include <mono/metadata/socket-io.h>
35 #include <mono/metadata/mono-endian.h>
36 #include <mono/metadata/tokentype.h>
37 #include <mono/metadata/domain-internals.h>
38 #include <mono/metadata/metadata-internals.h>
39 #include <mono/metadata/class-internals.h>
40 #include <mono/metadata/marshal.h>
41 #include <mono/metadata/gc-internal.h>
42 #include <mono/metadata/mono-gc.h>
43 #include <mono/metadata/rand.h>
44 #include <mono/metadata/sysmath.h>
45 #include <mono/metadata/string-icalls.h>
46 #include <mono/metadata/debug-helpers.h>
47 #include <mono/metadata/process.h>
48 #include <mono/metadata/environment.h>
49 #include <mono/metadata/profiler-private.h>
50 #include <mono/metadata/locales.h>
51 #include <mono/metadata/filewatcher.h>
52 #include <mono/metadata/char-conversions.h>
53 #include <mono/metadata/security.h>
54 #include <mono/metadata/mono-config.h>
55 #include <mono/metadata/cil-coff.h>
56 #include <mono/metadata/security-manager.h>
57 #include <mono/io-layer/io-layer.h>
58 #include <mono/utils/strtod.h>
59 #include <mono/utils/monobitset.h>
61 #if defined (PLATFORM_WIN32)
62 #include <windows.h>
63 #include <shlobj.h>
64 #endif
65 #include "decimal.h"
67 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
70 static inline MonoBoolean
71 is_generic_parameter (MonoType *type)
73 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
77 * We expect a pointer to a char, not a string
79 static gboolean
80 mono_double_ParseImpl (char *ptr, double *result)
82 gchar *endptr = NULL;
83 *result = 0.0;
85 MONO_ARCH_SAVE_REGS;
87 #ifdef __arm__
88 if (*ptr)
89 *result = strtod (ptr, &endptr);
90 #else
91 if (*ptr)
92 *result = bsd_strtod (ptr, &endptr);
93 #endif
95 if (!*ptr || (endptr && *endptr))
96 return FALSE;
98 return TRUE;
101 static MonoClass *
102 mono_class_get_throw (MonoImage *image, guint32 type_token)
104 MonoClass *class = mono_class_get (image, type_token);
105 MonoLoaderError *error;
106 MonoException *ex;
108 if (class != NULL)
109 return class;
111 error = mono_loader_get_last_error ();
112 g_assert (error != NULL);
114 ex = mono_loader_error_prepare_exception (error);
115 mono_raise_exception (ex);
116 return NULL;
119 static MonoObject *
120 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
122 MonoClass *ac;
123 MonoArray *ao;
124 gint32 esize;
125 gpointer *ea;
127 MONO_ARCH_SAVE_REGS;
129 ao = (MonoArray *)this;
130 ac = (MonoClass *)ao->obj.vtable->klass;
132 esize = mono_array_element_size (ac);
133 ea = (gpointer*)((char*)ao->vector + (pos * esize));
135 if (ac->element_class->valuetype)
136 return mono_value_box (this->vtable->domain, ac->element_class, ea);
137 else
138 return *ea;
141 static MonoObject *
142 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
144 MonoClass *ac, *ic;
145 MonoArray *ao, *io;
146 gint32 i, pos, *ind;
148 MONO_ARCH_SAVE_REGS;
150 MONO_CHECK_ARG_NULL (idxs);
152 io = (MonoArray *)idxs;
153 ic = (MonoClass *)io->obj.vtable->klass;
155 ao = (MonoArray *)this;
156 ac = (MonoClass *)ao->obj.vtable->klass;
158 g_assert (ic->rank == 1);
159 if (io->bounds != NULL || io->max_length != ac->rank)
160 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
162 ind = (gint32 *)io->vector;
164 if (ao->bounds == NULL) {
165 if (*ind < 0 || *ind >= ao->max_length)
166 mono_raise_exception (mono_get_exception_index_out_of_range ());
168 return ves_icall_System_Array_GetValueImpl (this, *ind);
171 for (i = 0; i < ac->rank; i++)
172 if ((ind [i] < ao->bounds [i].lower_bound) ||
173 (ind [i] >= ao->bounds [i].length + ao->bounds [i].lower_bound))
174 mono_raise_exception (mono_get_exception_index_out_of_range ());
176 pos = ind [0] - ao->bounds [0].lower_bound;
177 for (i = 1; i < ac->rank; i++)
178 pos = pos*ao->bounds [i].length + ind [i] -
179 ao->bounds [i].lower_bound;
181 return ves_icall_System_Array_GetValueImpl (this, pos);
184 static void
185 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
187 MonoClass *ac, *vc, *ec;
188 gint32 esize, vsize;
189 gpointer *ea, *va;
190 int et, vt;
192 guint64 u64 = 0;
193 gint64 i64 = 0;
194 gdouble r64 = 0;
196 MONO_ARCH_SAVE_REGS;
198 if (value)
199 vc = value->vtable->klass;
200 else
201 vc = NULL;
203 ac = this->obj.vtable->klass;
204 ec = ac->element_class;
206 esize = mono_array_element_size (ac);
207 ea = (gpointer*)((char*)this->vector + (pos * esize));
208 va = (gpointer*)((char*)value + sizeof (MonoObject));
210 if (!value) {
211 memset (ea, 0, esize);
212 return;
215 #define NO_WIDENING_CONVERSION G_STMT_START{\
216 mono_raise_exception (mono_get_exception_argument ( \
217 "value", "not a widening conversion")); \
218 }G_STMT_END
220 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
221 if (esize < vsize + (extra)) \
222 mono_raise_exception (mono_get_exception_argument ( \
223 "value", "not a widening conversion")); \
224 }G_STMT_END
226 #define INVALID_CAST G_STMT_START{\
227 mono_raise_exception (mono_get_exception_invalid_cast ()); \
228 }G_STMT_END
230 /* Check element (destination) type. */
231 switch (ec->byval_arg.type) {
232 case MONO_TYPE_STRING:
233 switch (vc->byval_arg.type) {
234 case MONO_TYPE_STRING:
235 break;
236 default:
237 INVALID_CAST;
239 break;
240 case MONO_TYPE_BOOLEAN:
241 switch (vc->byval_arg.type) {
242 case MONO_TYPE_BOOLEAN:
243 break;
244 case MONO_TYPE_CHAR:
245 case MONO_TYPE_U1:
246 case MONO_TYPE_U2:
247 case MONO_TYPE_U4:
248 case MONO_TYPE_U8:
249 case MONO_TYPE_I1:
250 case MONO_TYPE_I2:
251 case MONO_TYPE_I4:
252 case MONO_TYPE_I8:
253 case MONO_TYPE_R4:
254 case MONO_TYPE_R8:
255 NO_WIDENING_CONVERSION;
256 default:
257 INVALID_CAST;
259 break;
262 if (!ec->valuetype) {
263 if (!mono_object_isinst (value, ec))
264 INVALID_CAST;
265 *ea = (gpointer)value;
266 return;
269 if (mono_object_isinst (value, ec)) {
270 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
271 return;
274 if (!vc->valuetype)
275 INVALID_CAST;
277 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
279 et = ec->byval_arg.type;
280 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
281 et = ec->byval_arg.data.klass->enum_basetype->type;
283 vt = vc->byval_arg.type;
284 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
285 vt = vc->byval_arg.data.klass->enum_basetype->type;
287 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
288 switch (vt) { \
289 case MONO_TYPE_U1: \
290 case MONO_TYPE_U2: \
291 case MONO_TYPE_U4: \
292 case MONO_TYPE_U8: \
293 case MONO_TYPE_CHAR: \
294 CHECK_WIDENING_CONVERSION(0); \
295 *(etype *) ea = (etype) u64; \
296 return; \
297 /* You can't assign a signed value to an unsigned array. */ \
298 case MONO_TYPE_I1: \
299 case MONO_TYPE_I2: \
300 case MONO_TYPE_I4: \
301 case MONO_TYPE_I8: \
302 /* You can't assign a floating point number to an integer array. */ \
303 case MONO_TYPE_R4: \
304 case MONO_TYPE_R8: \
305 NO_WIDENING_CONVERSION; \
307 }G_STMT_END
309 #define ASSIGN_SIGNED(etype) G_STMT_START{\
310 switch (vt) { \
311 case MONO_TYPE_I1: \
312 case MONO_TYPE_I2: \
313 case MONO_TYPE_I4: \
314 case MONO_TYPE_I8: \
315 CHECK_WIDENING_CONVERSION(0); \
316 *(etype *) ea = (etype) i64; \
317 return; \
318 /* You can assign an unsigned value to a signed array if the array's */ \
319 /* element size is larger than the value size. */ \
320 case MONO_TYPE_U1: \
321 case MONO_TYPE_U2: \
322 case MONO_TYPE_U4: \
323 case MONO_TYPE_U8: \
324 case MONO_TYPE_CHAR: \
325 CHECK_WIDENING_CONVERSION(1); \
326 *(etype *) ea = (etype) u64; \
327 return; \
328 /* You can't assign a floating point number to an integer array. */ \
329 case MONO_TYPE_R4: \
330 case MONO_TYPE_R8: \
331 NO_WIDENING_CONVERSION; \
333 }G_STMT_END
335 #define ASSIGN_REAL(etype) G_STMT_START{\
336 switch (vt) { \
337 case MONO_TYPE_R4: \
338 case MONO_TYPE_R8: \
339 CHECK_WIDENING_CONVERSION(0); \
340 *(etype *) ea = (etype) r64; \
341 return; \
342 /* All integer values fit into a floating point array, so we don't */ \
343 /* need to CHECK_WIDENING_CONVERSION here. */ \
344 case MONO_TYPE_I1: \
345 case MONO_TYPE_I2: \
346 case MONO_TYPE_I4: \
347 case MONO_TYPE_I8: \
348 *(etype *) ea = (etype) i64; \
349 return; \
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 *(etype *) ea = (etype) u64; \
356 return; \
358 }G_STMT_END
360 switch (vt) {
361 case MONO_TYPE_U1:
362 u64 = *(guint8 *) va;
363 break;
364 case MONO_TYPE_U2:
365 u64 = *(guint16 *) va;
366 break;
367 case MONO_TYPE_U4:
368 u64 = *(guint32 *) va;
369 break;
370 case MONO_TYPE_U8:
371 u64 = *(guint64 *) va;
372 break;
373 case MONO_TYPE_I1:
374 i64 = *(gint8 *) va;
375 break;
376 case MONO_TYPE_I2:
377 i64 = *(gint16 *) va;
378 break;
379 case MONO_TYPE_I4:
380 i64 = *(gint32 *) va;
381 break;
382 case MONO_TYPE_I8:
383 i64 = *(gint64 *) va;
384 break;
385 case MONO_TYPE_R4:
386 r64 = *(gfloat *) va;
387 break;
388 case MONO_TYPE_R8:
389 r64 = *(gdouble *) va;
390 break;
391 case MONO_TYPE_CHAR:
392 u64 = *(guint16 *) va;
393 break;
394 case MONO_TYPE_BOOLEAN:
395 /* Boolean is only compatible with itself. */
396 switch (et) {
397 case MONO_TYPE_CHAR:
398 case MONO_TYPE_U1:
399 case MONO_TYPE_U2:
400 case MONO_TYPE_U4:
401 case MONO_TYPE_U8:
402 case MONO_TYPE_I1:
403 case MONO_TYPE_I2:
404 case MONO_TYPE_I4:
405 case MONO_TYPE_I8:
406 case MONO_TYPE_R4:
407 case MONO_TYPE_R8:
408 NO_WIDENING_CONVERSION;
409 default:
410 INVALID_CAST;
412 break;
415 /* If we can't do a direct copy, let's try a widening conversion. */
416 switch (et) {
417 case MONO_TYPE_CHAR:
418 ASSIGN_UNSIGNED (guint16);
419 case MONO_TYPE_U1:
420 ASSIGN_UNSIGNED (guint8);
421 case MONO_TYPE_U2:
422 ASSIGN_UNSIGNED (guint16);
423 case MONO_TYPE_U4:
424 ASSIGN_UNSIGNED (guint32);
425 case MONO_TYPE_U8:
426 ASSIGN_UNSIGNED (guint64);
427 case MONO_TYPE_I1:
428 ASSIGN_SIGNED (gint8);
429 case MONO_TYPE_I2:
430 ASSIGN_SIGNED (gint16);
431 case MONO_TYPE_I4:
432 ASSIGN_SIGNED (gint32);
433 case MONO_TYPE_I8:
434 ASSIGN_SIGNED (gint64);
435 case MONO_TYPE_R4:
436 ASSIGN_REAL (gfloat);
437 case MONO_TYPE_R8:
438 ASSIGN_REAL (gdouble);
441 INVALID_CAST;
442 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
443 return;
445 #undef INVALID_CAST
446 #undef NO_WIDENING_CONVERSION
447 #undef CHECK_WIDENING_CONVERSION
448 #undef ASSIGN_UNSIGNED
449 #undef ASSIGN_SIGNED
450 #undef ASSIGN_REAL
453 static void
454 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
455 MonoArray *idxs)
457 MonoClass *ac, *ic;
458 gint32 i, pos, *ind;
460 MONO_ARCH_SAVE_REGS;
462 MONO_CHECK_ARG_NULL (idxs);
464 ic = idxs->obj.vtable->klass;
465 ac = this->obj.vtable->klass;
467 g_assert (ic->rank == 1);
468 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
469 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
471 ind = (gint32 *)idxs->vector;
473 if (this->bounds == NULL) {
474 if (*ind < 0 || *ind >= this->max_length)
475 mono_raise_exception (mono_get_exception_index_out_of_range ());
477 ves_icall_System_Array_SetValueImpl (this, value, *ind);
478 return;
481 for (i = 0; i < ac->rank; i++)
482 if ((ind [i] < this->bounds [i].lower_bound) ||
483 (ind [i] >= this->bounds [i].length + this->bounds [i].lower_bound))
484 mono_raise_exception (mono_get_exception_index_out_of_range ());
486 pos = ind [0] - this->bounds [0].lower_bound;
487 for (i = 1; i < ac->rank; i++)
488 pos = pos * this->bounds [i].length + ind [i] -
489 this->bounds [i].lower_bound;
491 ves_icall_System_Array_SetValueImpl (this, value, pos);
494 static MonoArray *
495 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
497 MonoClass *aklass;
498 MonoArray *array;
499 guint32 *sizes, i;
500 gboolean bounded = FALSE;
502 MONO_ARCH_SAVE_REGS;
504 MONO_CHECK_ARG_NULL (type);
505 MONO_CHECK_ARG_NULL (lengths);
507 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
508 if (bounds)
509 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
511 for (i = 0; i < mono_array_length (lengths); i++)
512 if (mono_array_get (lengths, gint32, i) < 0)
513 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
515 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
516 /* vectors are not the same as one dimensional arrays with no-zero bounds */
517 bounded = TRUE;
518 else
519 bounded = FALSE;
521 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
523 sizes = alloca (aklass->rank * sizeof(guint32) * 2);
524 for (i = 0; i < aklass->rank; ++i) {
525 sizes [i] = mono_array_get (lengths, guint32, i);
526 if (bounds)
527 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
528 else
529 sizes [i + aklass->rank] = 0;
532 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
534 return array;
537 static gint32
538 ves_icall_System_Array_GetRank (MonoObject *this)
540 MONO_ARCH_SAVE_REGS;
542 return this->vtable->klass->rank;
545 static gint32
546 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
548 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
550 MONO_ARCH_SAVE_REGS;
552 if ((dimension < 0) || (dimension >= rank))
553 mono_raise_exception (mono_get_exception_index_out_of_range ());
555 if (this->bounds == NULL)
556 return this->max_length;
558 return this->bounds [dimension].length;
561 static gint32
562 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
564 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
566 MONO_ARCH_SAVE_REGS;
568 if ((dimension < 0) || (dimension >= rank))
569 mono_raise_exception (mono_get_exception_index_out_of_range ());
571 if (this->bounds == NULL)
572 return 0;
574 return this->bounds [dimension].lower_bound;
577 static void
578 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
580 int sz = mono_array_element_size (mono_object_class (arr));
581 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
584 static gboolean
585 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
587 int element_size;
588 void * dest_addr;
589 void * source_addr;
590 MonoClass *src_class;
591 MonoClass *dest_class;
592 int i;
594 MONO_ARCH_SAVE_REGS;
596 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
597 return FALSE;
599 if (source->bounds || dest->bounds)
600 return FALSE;
602 if ((dest_idx + length > mono_array_length (dest)) ||
603 (source_idx + length > mono_array_length (source)))
604 return FALSE;
606 src_class = source->obj.vtable->klass->element_class;
607 dest_class = dest->obj.vtable->klass->element_class;
610 * Handle common cases.
613 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
614 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
615 int has_refs = dest_class->has_references;
616 for (i = source_idx; i < source_idx + length; ++i) {
617 MonoObject *elem = mono_array_get (source, MonoObject*, i);
618 if (elem && !mono_object_isinst (elem, dest_class))
619 return FALSE;
622 element_size = mono_array_element_size (dest->obj.vtable->klass);
623 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
624 for (i = 0; i < length; ++i) {
625 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
626 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
627 if (!elem)
628 continue;
629 if (has_refs)
630 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
631 else
632 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
634 return TRUE;
637 /* Check if we're copying a char[] <==> (u)short[] */
638 if (src_class != dest_class) {
639 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
640 return FALSE;
642 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
644 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
645 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
646 for (i = source_idx; i < source_idx + length; ++i) {
647 MonoObject *elem = mono_array_get (source, MonoObject*, i);
648 if (elem && !mono_object_isinst (elem, dest_class))
649 return FALSE;
651 else
652 return FALSE;
655 if (dest_class->valuetype) {
656 element_size = mono_array_element_size (source->obj.vtable->klass);
657 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
658 if (dest_class->has_references) {
659 mono_value_copy_array (dest, dest_idx, source_addr, length);
660 } else {
661 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
662 memmove (dest_addr, source_addr, element_size * length);
664 } else {
665 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
668 return TRUE;
671 static void
672 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
674 MonoClass *ac;
675 MonoArray *ao;
676 gint32 esize;
677 gpointer *ea;
679 MONO_ARCH_SAVE_REGS;
681 ao = (MonoArray *)this;
682 ac = (MonoClass *)ao->obj.vtable->klass;
684 esize = mono_array_element_size (ac);
685 ea = (gpointer*)((char*)ao->vector + (pos * esize));
687 memcpy (value, ea, esize);
690 static void
691 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
693 MonoClass *klass = array->obj.vtable->klass;
694 guint32 size = mono_array_element_size (klass);
696 size *= array->max_length;
698 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
699 #define SWAP(n) {\
700 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
701 guint ## n *src = (guint ## n *) field_handle->data; \
702 guint ## n *end = (guint ## n *)((char*)src + size); \
704 for (; src < end; data++, src++) { \
705 *data = read ## n (src); \
709 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
711 switch (mono_type_get_underlying_type (&klass->element_class->byval_arg)->type) {
712 case MONO_TYPE_CHAR:
713 case MONO_TYPE_I2:
714 case MONO_TYPE_U2:
715 SWAP (16);
716 break;
717 case MONO_TYPE_I4:
718 case MONO_TYPE_U4:
719 case MONO_TYPE_R4:
720 SWAP (32);
721 break;
722 case MONO_TYPE_I8:
723 case MONO_TYPE_U8:
724 case MONO_TYPE_R8:
725 SWAP (64);
726 break;
727 default:
728 memcpy (mono_array_addr (array, char, 0), field_handle->data, size);
729 break;
731 #else
732 memcpy (mono_array_addr (array, char, 0), field_handle->data, size);
733 #ifdef ARM_FPU_FPA
734 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
735 gint i;
736 double tmp;
737 double *data = (double*)mono_array_addr (array, double, 0);
739 for (i = 0; i < size; i++, data++) {
740 readr8 (data, &tmp);
741 *data = tmp;
744 #endif
745 #endif
748 static gint
749 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
751 MONO_ARCH_SAVE_REGS;
753 return offsetof (MonoString, chars);
756 static MonoObject *
757 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
759 MONO_ARCH_SAVE_REGS;
761 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
762 return obj;
763 else
764 return mono_object_clone (obj);
767 static void
768 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
770 MonoClass *klass;
772 MONO_ARCH_SAVE_REGS;
774 MONO_CHECK_ARG_NULL (handle);
776 klass = mono_class_from_mono_type (handle);
777 MONO_CHECK_ARG (handle, klass);
779 /* This will call the type constructor */
780 if (! (klass->flags & TYPE_ATTRIBUTE_INTERFACE))
781 mono_runtime_class_init (mono_class_vtable (mono_domain_get (), klass));
784 static MonoObject *
785 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
787 MONO_ARCH_SAVE_REGS;
789 return mono_object_clone (this);
792 static gint32
793 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
795 MonoClass *klass;
796 MonoObject **values = NULL;
797 MonoObject *o;
798 int count = 0;
799 gint32 result = 0;
800 MonoClassField* field;
801 gpointer iter;
803 MONO_ARCH_SAVE_REGS;
805 klass = mono_object_class (this);
807 if (mono_class_num_fields (klass) == 0)
808 return mono_object_hash (this);
811 * Compute the starting value of the hashcode for fields of primitive
812 * types, and return the remaining fields in an array to the managed side.
813 * This way, we can avoid costly reflection operations in managed code.
815 iter = NULL;
816 while ((field = mono_class_get_fields (klass, &iter))) {
817 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
818 continue;
819 if (mono_field_is_deleted (field))
820 continue;
821 /* FIXME: Add more types */
822 switch (field->type->type) {
823 case MONO_TYPE_I4:
824 result ^= *(gint32*)((guint8*)this + field->offset);
825 break;
826 case MONO_TYPE_STRING: {
827 MonoString *s;
828 s = *(MonoString**)((guint8*)this + field->offset);
829 if (s != NULL)
830 result ^= mono_string_hash (s);
831 break;
833 default:
834 if (!values)
835 values = g_newa (MonoObject*, mono_class_num_fields (klass));
836 o = mono_field_get_value_object (mono_object_domain (this), field, this);
837 values [count++] = o;
841 if (values) {
842 int i;
843 *fields = mono_array_new (mono_domain_get (), mono_defaults.object_class, count);
844 for (i = 0; i < count; ++i)
845 mono_array_setref (*fields, i, values [i]);
846 } else {
847 *fields = NULL;
849 return result;
852 static MonoBoolean
853 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
855 MonoClass *klass;
856 MonoObject **values = NULL;
857 MonoObject *o;
858 MonoClassField* field;
859 gpointer iter;
860 int count = 0;
862 MONO_ARCH_SAVE_REGS;
864 MONO_CHECK_ARG_NULL (that);
866 if (this->vtable != that->vtable)
867 return FALSE;
869 klass = mono_object_class (this);
872 * Do the comparison for fields of primitive type and return a result if
873 * possible. Otherwise, return the remaining fields in an array to the
874 * managed side. This way, we can avoid costly reflection operations in
875 * managed code.
877 *fields = NULL;
878 iter = NULL;
879 while ((field = mono_class_get_fields (klass, &iter))) {
880 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
881 continue;
882 if (mono_field_is_deleted (field))
883 continue;
884 /* FIXME: Add more types */
885 switch (field->type->type) {
886 case MONO_TYPE_I4:
887 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
888 return FALSE;
889 break;
890 case MONO_TYPE_STRING: {
891 MonoString *s1, *s2;
892 guint32 s1len, s2len;
893 s1 = *(MonoString**)((guint8*)this + field->offset);
894 s2 = *(MonoString**)((guint8*)that + field->offset);
895 if (s1 == s2)
896 break;
897 if ((s1 == NULL) || (s2 == NULL))
898 return FALSE;
899 s1len = mono_string_length (s1);
900 s2len = mono_string_length (s2);
901 if (s1len != s2len)
902 return FALSE;
904 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
905 return FALSE;
906 break;
908 default:
909 if (!values)
910 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
911 o = mono_field_get_value_object (mono_object_domain (this), field, this);
912 values [count++] = o;
913 o = mono_field_get_value_object (mono_object_domain (this), field, that);
914 values [count++] = o;
918 if (values) {
919 int i;
920 *fields = mono_array_new (mono_domain_get (), mono_defaults.object_class, count);
921 for (i = 0; i < count; ++i)
922 mono_array_setref (*fields, i, values [i]);
923 return FALSE;
924 } else {
925 return TRUE;
929 static MonoReflectionType *
930 ves_icall_System_Object_GetType (MonoObject *obj)
932 MONO_ARCH_SAVE_REGS;
934 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
935 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
936 else
937 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
940 static void
941 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
943 MONO_ARCH_SAVE_REGS;
945 mtype->type = &obj->vtable->klass->byval_arg;
946 g_assert (mtype->type->type);
949 static gint32
950 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
952 MONO_ARCH_SAVE_REGS;
954 MONO_CHECK_ARG_NULL (obj);
956 return mono_image_create_token (mb->dynamic_image, obj, TRUE);
959 static gint32
960 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
961 MonoReflectionMethod *method,
962 MonoArray *opt_param_types)
964 MONO_ARCH_SAVE_REGS;
966 MONO_CHECK_ARG_NULL (method);
968 return mono_image_create_method_token (
969 mb->dynamic_image, (MonoObject *) method, opt_param_types);
972 static void
973 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
975 MONO_ARCH_SAVE_REGS;
977 mono_image_create_pefile (mb, file);
980 static void
981 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
983 MONO_ARCH_SAVE_REGS;
985 mono_image_build_metadata (mb);
988 static gboolean
989 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
991 MonoMethod **dest = data;
993 /* skip unmanaged frames */
994 if (!managed)
995 return FALSE;
997 if (m == *dest) {
998 *dest = NULL;
999 return FALSE;
1001 if (!(*dest)) {
1002 *dest = m;
1003 return TRUE;
1005 return FALSE;
1008 static MonoReflectionType *
1009 type_from_name (const char *str, MonoBoolean ignoreCase)
1011 MonoType *type = NULL;
1012 MonoAssembly *assembly = NULL;
1013 MonoTypeNameParse info;
1014 char *temp_str = g_strdup (str);
1015 gboolean type_resolve = FALSE;
1017 MONO_ARCH_SAVE_REGS;
1019 /* mono_reflection_parse_type() mangles the string */
1020 if (!mono_reflection_parse_type (temp_str, &info)) {
1021 g_list_free (info.modifiers);
1022 g_list_free (info.nested);
1023 g_free (temp_str);
1024 return NULL;
1027 if (info.assembly.name) {
1028 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1029 } else {
1030 MonoMethod *m = mono_method_get_last_managed ();
1031 MonoMethod *dest = m;
1033 mono_stack_walk_no_il (get_caller, &dest);
1034 if (!dest)
1035 dest = m;
1038 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1039 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1040 * to crash. This only seems to happen in some strange remoting
1041 * scenarios and I was unable to figure out what's happening there.
1042 * Dec 10, 2005 - Martin.
1045 if (dest)
1046 assembly = dest->klass->image->assembly;
1047 else {
1048 g_warning (G_STRLOC);
1052 if (assembly)
1053 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1055 if (!info.assembly.name && !type) /* try mscorlib */
1056 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1058 g_list_free (info.modifiers);
1059 g_list_free (info.nested);
1060 g_free (temp_str);
1062 if (!type)
1063 return NULL;
1065 return mono_type_get_object (mono_domain_get (), type);
1068 #ifdef UNUSED
1069 MonoReflectionType *
1070 mono_type_get (const char *str)
1072 char *copy = g_strdup (str);
1073 MonoReflectionType *type = type_from_name (copy, FALSE);
1075 g_free (copy);
1076 return type;
1078 #endif
1080 static MonoReflectionType*
1081 ves_icall_type_from_name (MonoString *name,
1082 MonoBoolean throwOnError,
1083 MonoBoolean ignoreCase)
1085 char *str = mono_string_to_utf8 (name);
1086 MonoReflectionType *type;
1088 type = type_from_name (str, ignoreCase);
1089 g_free (str);
1090 if (type == NULL){
1091 MonoException *e = NULL;
1093 if (throwOnError)
1094 e = mono_get_exception_type_load (name, NULL);
1096 mono_loader_clear_error ();
1097 if (e != NULL)
1098 mono_raise_exception (e);
1101 return type;
1105 static MonoReflectionType*
1106 ves_icall_type_from_handle (MonoType *handle)
1108 MonoDomain *domain = mono_domain_get ();
1109 MonoClass *klass = mono_class_from_mono_type (handle);
1111 MONO_ARCH_SAVE_REGS;
1113 mono_class_init (klass);
1114 return mono_type_get_object (domain, handle);
1117 static MonoBoolean
1118 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1120 MONO_ARCH_SAVE_REGS;
1122 if (c && type->type && c->type)
1123 return mono_metadata_type_equal (type->type, c->type);
1124 else
1125 return FALSE;
1128 /* System.TypeCode */
1129 typedef enum {
1130 TYPECODE_EMPTY,
1131 TYPECODE_OBJECT,
1132 TYPECODE_DBNULL,
1133 TYPECODE_BOOLEAN,
1134 TYPECODE_CHAR,
1135 TYPECODE_SBYTE,
1136 TYPECODE_BYTE,
1137 TYPECODE_INT16,
1138 TYPECODE_UINT16,
1139 TYPECODE_INT32,
1140 TYPECODE_UINT32,
1141 TYPECODE_INT64,
1142 TYPECODE_UINT64,
1143 TYPECODE_SINGLE,
1144 TYPECODE_DOUBLE,
1145 TYPECODE_DECIMAL,
1146 TYPECODE_DATETIME,
1147 TYPECODE_STRING = 18
1148 } TypeCode;
1150 static guint32
1151 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1153 int t = type->type->type;
1155 MONO_ARCH_SAVE_REGS;
1157 if (type->type->byref)
1158 return TYPECODE_OBJECT;
1160 handle_enum:
1161 switch (t) {
1162 case MONO_TYPE_VOID:
1163 return TYPECODE_OBJECT;
1164 case MONO_TYPE_BOOLEAN:
1165 return TYPECODE_BOOLEAN;
1166 case MONO_TYPE_U1:
1167 return TYPECODE_BYTE;
1168 case MONO_TYPE_I1:
1169 return TYPECODE_SBYTE;
1170 case MONO_TYPE_U2:
1171 return TYPECODE_UINT16;
1172 case MONO_TYPE_I2:
1173 return TYPECODE_INT16;
1174 case MONO_TYPE_CHAR:
1175 return TYPECODE_CHAR;
1176 case MONO_TYPE_PTR:
1177 case MONO_TYPE_U:
1178 case MONO_TYPE_I:
1179 return TYPECODE_OBJECT;
1180 case MONO_TYPE_U4:
1181 return TYPECODE_UINT32;
1182 case MONO_TYPE_I4:
1183 return TYPECODE_INT32;
1184 case MONO_TYPE_U8:
1185 return TYPECODE_UINT64;
1186 case MONO_TYPE_I8:
1187 return TYPECODE_INT64;
1188 case MONO_TYPE_R4:
1189 return TYPECODE_SINGLE;
1190 case MONO_TYPE_R8:
1191 return TYPECODE_DOUBLE;
1192 case MONO_TYPE_VALUETYPE:
1193 if (type->type->data.klass->enumtype) {
1194 t = type->type->data.klass->enum_basetype->type;
1195 goto handle_enum;
1196 } else {
1197 MonoClass *k = type->type->data.klass;
1198 if (strcmp (k->name_space, "System") == 0) {
1199 if (strcmp (k->name, "Decimal") == 0)
1200 return TYPECODE_DECIMAL;
1201 else if (strcmp (k->name, "DateTime") == 0)
1202 return TYPECODE_DATETIME;
1205 return TYPECODE_OBJECT;
1206 case MONO_TYPE_STRING:
1207 return TYPECODE_STRING;
1208 case MONO_TYPE_SZARRAY:
1209 case MONO_TYPE_ARRAY:
1210 case MONO_TYPE_OBJECT:
1211 case MONO_TYPE_VAR:
1212 case MONO_TYPE_MVAR:
1213 case MONO_TYPE_TYPEDBYREF:
1214 return TYPECODE_OBJECT;
1215 case MONO_TYPE_CLASS:
1217 MonoClass *k = type->type->data.klass;
1218 if (strcmp (k->name_space, "System") == 0) {
1219 if (strcmp (k->name, "DBNull") == 0)
1220 return TYPECODE_DBNULL;
1223 return TYPECODE_OBJECT;
1224 case MONO_TYPE_GENERICINST:
1225 return TYPECODE_OBJECT;
1226 default:
1227 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1229 return 0;
1232 static guint32
1233 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1235 MonoDomain *domain;
1236 MonoClass *klass;
1237 MonoClass *klassc;
1239 MONO_ARCH_SAVE_REGS;
1241 g_assert (type != NULL);
1243 domain = ((MonoObject *)type)->vtable->domain;
1245 if (!c) /* FIXME: dont know what do do here */
1246 return 0;
1248 klass = mono_class_from_mono_type (type->type);
1249 klassc = mono_class_from_mono_type (c->type);
1251 if (type->type->byref)
1252 return klassc == mono_defaults.object_class;
1254 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1257 static guint32
1258 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1260 MonoDomain *domain;
1261 MonoClass *klass;
1262 MonoClass *klassc;
1264 MONO_ARCH_SAVE_REGS;
1266 g_assert (type != NULL);
1268 domain = ((MonoObject *)type)->vtable->domain;
1270 klass = mono_class_from_mono_type (type->type);
1271 klassc = mono_class_from_mono_type (c->type);
1273 if (type->type->byref && !c->type->byref)
1274 return FALSE;
1276 return mono_class_is_assignable_from (klass, klassc);
1279 static guint32
1280 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1282 MonoClass *klass = mono_class_from_mono_type (type->type);
1283 return mono_object_isinst (obj, klass) != NULL;
1286 static guint32
1287 ves_icall_get_attributes (MonoReflectionType *type)
1289 MonoClass *klass = mono_class_from_mono_type (type->type);
1291 MONO_ARCH_SAVE_REGS;
1293 return klass->flags;
1296 static MonoReflectionMarshal*
1297 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1299 MonoClass *klass = field->field->parent;
1300 MonoMarshalType *info;
1301 int i;
1303 if (klass->generic_container ||
1304 (klass->generic_class && klass->generic_class->inst->is_open))
1305 return NULL;
1307 info = mono_marshal_load_type_info (klass);
1309 for (i = 0; i < info->num_fields; ++i) {
1310 if (info->fields [i].field == field->field) {
1311 if (!info->fields [i].mspec)
1312 return NULL;
1313 else
1314 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1318 return NULL;
1321 static MonoReflectionField*
1322 ves_icall_System_Reflection_FieldInfo_internal_from_handle (MonoClassField *handle)
1324 MONO_ARCH_SAVE_REGS;
1326 g_assert (handle);
1328 return mono_field_get_object (mono_domain_get (), handle->parent, handle);
1331 static void
1332 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1334 MonoDomain *domain = mono_domain_get ();
1335 MonoMethodSignature* sig;
1336 MONO_ARCH_SAVE_REGS;
1338 if (method->is_inflated)
1339 method = mono_get_inflated_method (method);
1341 sig = mono_method_signature (method);
1343 info->parent = mono_type_get_object (domain, &method->klass->byval_arg);
1344 info->ret = mono_type_get_object (domain, sig->ret);
1345 info->attrs = method->flags;
1346 info->implattrs = method->iflags;
1347 if (sig->call_convention == MONO_CALL_DEFAULT)
1348 info->callconv = 1;
1349 else {
1350 if (sig->call_convention == MONO_CALL_VARARG)
1351 info->callconv = 2;
1352 else
1353 info->callconv = 0;
1355 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1358 static MonoArray*
1359 ves_icall_get_parameter_info (MonoMethod *method)
1361 MonoDomain *domain = mono_domain_get ();
1363 MONO_ARCH_SAVE_REGS;
1365 if (method->is_inflated)
1366 method = mono_get_inflated_method (method);
1368 return mono_param_get_objects (domain, method);
1371 static MonoReflectionMarshal*
1372 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1374 MonoDomain *domain = mono_domain_get ();
1375 MonoReflectionMarshal* res = NULL;
1376 MonoMarshalSpec **mspecs;
1377 int i;
1379 MONO_ARCH_SAVE_REGS;
1381 if (method->is_inflated)
1382 method = mono_get_inflated_method (method);
1384 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1385 mono_method_get_marshal_info (method, mspecs);
1387 if (mspecs [0])
1388 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1390 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1391 if (mspecs [i])
1392 mono_metadata_free_marshal_spec (mspecs [i]);
1393 g_free (mspecs);
1395 return res;
1398 static gint32
1399 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1401 return field->field->offset - sizeof (MonoObject);
1404 static MonoReflectionType*
1405 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1407 MonoClass *parent;
1408 MONO_ARCH_SAVE_REGS;
1410 parent = declaring? field->field->parent: field->klass;
1412 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1415 static MonoObject *
1416 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1418 MonoObject *o;
1419 MonoClassField *cf = field->field;
1420 MonoClass *klass;
1421 MonoVTable *vtable;
1422 MonoType *t;
1423 MonoDomain *domain = mono_object_domain (field);
1424 gchar *v;
1425 gboolean is_static = FALSE;
1426 gboolean is_ref = FALSE;
1428 MONO_ARCH_SAVE_REGS;
1430 if (field->klass->image->assembly->ref_only)
1431 mono_raise_exception (mono_get_exception_invalid_operation (
1432 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1434 mono_class_init (field->klass);
1436 t = mono_type_get_underlying_type (cf->type);
1437 switch (t->type) {
1438 case MONO_TYPE_STRING:
1439 case MONO_TYPE_OBJECT:
1440 case MONO_TYPE_CLASS:
1441 case MONO_TYPE_ARRAY:
1442 case MONO_TYPE_SZARRAY:
1443 is_ref = TRUE;
1444 break;
1445 case MONO_TYPE_U1:
1446 case MONO_TYPE_I1:
1447 case MONO_TYPE_BOOLEAN:
1448 case MONO_TYPE_U2:
1449 case MONO_TYPE_I2:
1450 case MONO_TYPE_CHAR:
1451 case MONO_TYPE_U:
1452 case MONO_TYPE_I:
1453 case MONO_TYPE_U4:
1454 case MONO_TYPE_I4:
1455 case MONO_TYPE_R4:
1456 case MONO_TYPE_U8:
1457 case MONO_TYPE_I8:
1458 case MONO_TYPE_R8:
1459 case MONO_TYPE_VALUETYPE:
1460 is_ref = t->byref;
1461 break;
1462 case MONO_TYPE_GENERICINST:
1463 if (mono_type_generic_inst_is_valuetype (t)) {
1464 is_ref = t->byref;
1465 } else {
1466 is_ref = TRUE;
1468 break;
1469 default:
1470 g_error ("type 0x%x not handled in "
1471 "ves_icall_Monofield_GetValue", t->type);
1472 return NULL;
1475 vtable = NULL;
1476 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1477 is_static = TRUE;
1478 vtable = mono_class_vtable (domain, cf->parent);
1479 if (!vtable->initialized && !(cf->type->attrs & FIELD_ATTRIBUTE_LITERAL))
1480 mono_runtime_class_init (vtable);
1483 if (is_ref) {
1484 if (is_static) {
1485 mono_field_static_get_value (vtable, cf, &o);
1486 } else {
1487 mono_field_get_value (obj, cf, &o);
1489 return o;
1492 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1493 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1494 guint8 *buf;
1496 /* Convert the Nullable structure into a boxed vtype */
1497 if (is_static)
1498 buf = (guint8*)vtable->data + cf->offset;
1499 else
1500 buf = (guint8*)obj + cf->offset;
1502 return mono_nullable_box (buf, nklass);
1505 /* boxed value type */
1506 klass = mono_class_from_mono_type (cf->type);
1507 o = mono_object_new (domain, klass);
1508 v = ((gchar *) o) + sizeof (MonoObject);
1509 if (is_static) {
1510 mono_field_static_get_value (vtable, cf, v);
1511 } else {
1512 mono_field_get_value (obj, cf, v);
1515 return o;
1518 static void
1519 ves_icall_FieldInfo_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1521 MonoClassField *cf = field->field;
1522 gchar *v;
1524 MONO_ARCH_SAVE_REGS;
1526 if (field->klass->image->assembly->ref_only)
1527 mono_raise_exception (mono_get_exception_invalid_operation (
1528 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1530 v = (gchar *) value;
1531 if (!cf->type->byref) {
1532 switch (cf->type->type) {
1533 case MONO_TYPE_U1:
1534 case MONO_TYPE_I1:
1535 case MONO_TYPE_BOOLEAN:
1536 case MONO_TYPE_U2:
1537 case MONO_TYPE_I2:
1538 case MONO_TYPE_CHAR:
1539 case MONO_TYPE_U:
1540 case MONO_TYPE_I:
1541 case MONO_TYPE_U4:
1542 case MONO_TYPE_I4:
1543 case MONO_TYPE_R4:
1544 case MONO_TYPE_U8:
1545 case MONO_TYPE_I8:
1546 case MONO_TYPE_R8:
1547 case MONO_TYPE_VALUETYPE:
1548 if (v != NULL)
1549 v += sizeof (MonoObject);
1550 break;
1551 case MONO_TYPE_STRING:
1552 case MONO_TYPE_OBJECT:
1553 case MONO_TYPE_CLASS:
1554 case MONO_TYPE_ARRAY:
1555 case MONO_TYPE_SZARRAY:
1556 /* Do nothing */
1557 break;
1558 case MONO_TYPE_GENERICINST: {
1559 MonoGenericClass *gclass = cf->type->data.generic_class;
1560 g_assert (!gclass->inst->is_open);
1562 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1563 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1564 guint8 *buf;
1567 * Convert the boxed vtype into a Nullable structure.
1568 * This is complicated by the fact that Nullables have
1569 * a variable structure.
1571 /* Allocate using alloca so it gets GC tracking */
1572 buf = alloca (nklass->instance_size);
1574 mono_nullable_init (buf, value, nklass);
1576 v = (gchar*)buf;
1578 else
1579 if (gclass->container_class->valuetype && (v != NULL))
1580 v += sizeof (MonoObject);
1581 break;
1583 default:
1584 g_error ("type 0x%x not handled in "
1585 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1586 return;
1590 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1591 MonoVTable *vtable = mono_class_vtable (mono_object_domain (field), cf->parent);
1592 if (!vtable->initialized)
1593 mono_runtime_class_init (vtable);
1594 mono_field_static_set_value (vtable, cf, v);
1595 } else {
1596 mono_field_set_value (obj, cf, v);
1600 static MonoReflectionType*
1601 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1603 MonoMethod *method = mono_get_inflated_method (rmethod->method.method);
1605 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1608 /* From MonoProperty.cs */
1609 typedef enum {
1610 PInfo_Attributes = 1,
1611 PInfo_GetMethod = 1 << 1,
1612 PInfo_SetMethod = 1 << 2,
1613 PInfo_ReflectedType = 1 << 3,
1614 PInfo_DeclaringType = 1 << 4,
1615 PInfo_Name = 1 << 5
1616 } PInfo;
1618 static void
1619 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1621 MonoDomain *domain = mono_object_domain (property);
1623 MONO_ARCH_SAVE_REGS;
1625 if ((req_info & PInfo_ReflectedType) != 0)
1626 info->parent = mono_type_get_object (domain, &property->klass->byval_arg);
1627 else if ((req_info & PInfo_DeclaringType) != 0)
1628 info->parent = mono_type_get_object (domain, &property->property->parent->byval_arg);
1630 if ((req_info & PInfo_Name) != 0)
1631 info->name = mono_string_new (domain, property->property->name);
1633 if ((req_info & PInfo_Attributes) != 0)
1634 info->attrs = property->property->attrs;
1636 if ((req_info & PInfo_GetMethod) != 0)
1637 info->get = property->property->get ?
1638 mono_method_get_object (domain, property->property->get, NULL): NULL;
1640 if ((req_info & PInfo_SetMethod) != 0)
1641 info->set = property->property->set ?
1642 mono_method_get_object (domain, property->property->set, NULL): NULL;
1644 * There may be other methods defined for properties, though, it seems they are not exposed
1645 * in the reflection API
1649 static void
1650 ves_icall_get_event_info (MonoReflectionEvent *event, MonoEventInfo *info)
1652 MonoDomain *domain = mono_object_domain (event);
1654 MONO_ARCH_SAVE_REGS;
1656 info->reflected_type = mono_type_get_object (domain, &event->klass->byval_arg);
1657 info->declaring_type = mono_type_get_object (domain, &event->event->parent->byval_arg);
1659 info->name = mono_string_new (domain, event->event->name);
1660 info->attrs = event->event->attrs;
1661 info->add_method = event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL;
1662 info->remove_method = event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL;
1663 info->raise_method = event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL;
1665 if (event->event->other) {
1666 int i, n = 0;
1667 while (event->event->other [n])
1668 n++;
1669 info->other_methods = mono_array_new (domain, mono_defaults.method_info_class, n);
1671 for (i = 0; i < n; i++)
1672 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
1676 static MonoArray*
1677 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
1679 MonoDomain *domain = mono_object_domain (type);
1680 MonoArray *intf;
1681 GPtrArray *ifaces = NULL;
1682 int i;
1683 MonoClass *class = mono_class_from_mono_type (type->type);
1684 MonoClass *parent;
1685 MonoBitSet *slots;
1686 MonoGenericContext *context = NULL;
1688 MONO_ARCH_SAVE_REGS;
1690 /* open generic-instance classes can share their interface_id */
1691 if (class->generic_class && class->generic_class->inst->is_open) {
1692 context = mono_class_get_context (class);
1693 class = class->generic_class->container_class;
1696 mono_class_setup_vtable (class);
1698 slots = mono_bitset_new (class->max_interface_id + 1, 0);
1700 for (parent = class; parent; parent = parent->parent) {
1701 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent);
1702 if (tmp_ifaces) {
1703 for (i = 0; i < tmp_ifaces->len; ++i) {
1704 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
1706 if (mono_bitset_test (slots, ic->interface_id))
1707 continue;
1709 mono_bitset_set (slots, ic->interface_id);
1710 if (ifaces == NULL)
1711 ifaces = g_ptr_array_new ();
1712 g_ptr_array_add (ifaces, ic);
1714 g_ptr_array_free (tmp_ifaces, TRUE);
1717 mono_bitset_free (slots);
1719 if (!ifaces)
1720 return mono_array_new (domain, mono_defaults.monotype_class, 0);
1722 intf = mono_array_new (domain, mono_defaults.monotype_class, ifaces->len);
1723 for (i = 0; i < ifaces->len; ++i) {
1724 MonoClass *ic = g_ptr_array_index (ifaces, i);
1725 MonoType *ret = &ic->byval_arg;
1726 if (context && ic->generic_class && ic->generic_class->inst->is_open)
1727 ret = mono_class_inflate_generic_type (ret, context);
1729 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
1731 g_ptr_array_free (ifaces, TRUE);
1733 return intf;
1736 static void
1737 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
1739 MonoClass *class = mono_class_from_mono_type (type->type);
1740 MonoClass *iclass = mono_class_from_mono_type (iface->type);
1741 MonoReflectionMethod *member;
1742 MonoMethod* method;
1743 gpointer iter;
1744 int i = 0, len, ioffset;
1745 MonoDomain *domain;
1747 MONO_ARCH_SAVE_REGS;
1749 mono_class_setup_vtable (class);
1751 /* type doesn't implement iface: the exception is thrown in managed code */
1752 if ((iclass->interface_id > class->max_interface_id) || !class->interface_offsets [iclass->interface_id])
1753 return;
1755 len = mono_class_num_methods (iclass);
1756 ioffset = class->interface_offsets [iclass->interface_id];
1757 domain = mono_object_domain (type);
1758 *targets = mono_array_new (domain, mono_defaults.method_info_class, len);
1759 *methods = mono_array_new (domain, mono_defaults.method_info_class, len);
1760 iter = NULL;
1761 iter = NULL;
1762 while ((method = mono_class_get_methods (iclass, &iter))) {
1763 member = mono_method_get_object (domain, method, iclass);
1764 mono_array_setref (*methods, i, member);
1765 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
1766 mono_array_setref (*targets, i, member);
1768 i ++;
1772 static void
1773 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
1775 MonoClass *klass = mono_class_from_mono_type (type->type);
1777 g_assert (!klass->image->dynamic);
1779 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
1782 static MonoReflectionType*
1783 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
1785 MonoClass *class = mono_class_from_mono_type (type->type);
1787 MONO_ARCH_SAVE_REGS;
1789 // GelElementType should only return a type for:
1790 // Array Pointer PassedByRef
1791 if (type->type->byref)
1792 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
1793 if (class->enumtype && class->enum_basetype) /* types that are modifierd typebuilkders may not have enum_basetype set */
1794 return mono_type_get_object (mono_object_domain (type), class->enum_basetype);
1795 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
1796 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
1797 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
1798 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
1799 else
1800 return NULL;
1803 static MonoReflectionType*
1804 ves_icall_get_type_parent (MonoReflectionType *type)
1806 MonoClass *class = mono_class_from_mono_type (type->type);
1808 MONO_ARCH_SAVE_REGS;
1810 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
1813 static MonoBoolean
1814 ves_icall_type_ispointer (MonoReflectionType *type)
1816 MONO_ARCH_SAVE_REGS;
1818 return type->type->type == MONO_TYPE_PTR;
1821 static MonoBoolean
1822 ves_icall_type_isprimitive (MonoReflectionType *type)
1824 MONO_ARCH_SAVE_REGS;
1826 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)));
1829 static MonoBoolean
1830 ves_icall_type_isbyref (MonoReflectionType *type)
1832 MONO_ARCH_SAVE_REGS;
1834 return type->type->byref;
1837 static MonoBoolean
1838 ves_icall_type_iscomobject (MonoReflectionType *type)
1840 MonoClass *klass = mono_class_from_mono_type (type->type);
1841 MONO_ARCH_SAVE_REGS;
1843 return (klass && klass->is_com_object);
1846 static MonoReflectionModule*
1847 ves_icall_MonoType_get_Module (MonoReflectionType *type)
1849 MonoClass *class = mono_class_from_mono_type (type->type);
1851 MONO_ARCH_SAVE_REGS;
1853 return mono_module_get_object (mono_object_domain (type), class->image);
1856 static MonoReflectionAssembly*
1857 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
1859 MonoDomain *domain = mono_domain_get ();
1860 MonoClass *class = mono_class_from_mono_type (type->type);
1862 MONO_ARCH_SAVE_REGS;
1864 return mono_assembly_get_object (domain, class->image->assembly);
1867 static MonoReflectionType*
1868 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
1870 MonoDomain *domain = mono_domain_get ();
1871 MonoClass *class;
1873 MONO_ARCH_SAVE_REGS;
1875 if (type->type->byref)
1876 return NULL;
1877 if (type->type->type == MONO_TYPE_VAR)
1878 class = type->type->data.generic_param->owner->owner.klass;
1879 else if (type->type->type == MONO_TYPE_MVAR)
1880 class = type->type->data.generic_param->owner->owner.method->klass;
1881 else
1882 class = mono_class_from_mono_type (type->type)->nested_in;
1884 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
1887 static MonoReflectionType*
1888 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType *type)
1890 MonoDomain *domain = mono_domain_get ();
1891 MonoClass *class = mono_class_from_mono_type (type->type);
1893 MONO_ARCH_SAVE_REGS;
1895 if (class->enumtype && class->enum_basetype) /* types that are modified typebuilders may not have enum_basetype set */
1896 return mono_type_get_object (domain, class->enum_basetype);
1897 else if (class->element_class)
1898 return mono_type_get_object (domain, &class->element_class->byval_arg);
1899 else
1900 return NULL;
1903 static MonoString*
1904 ves_icall_MonoType_get_Name (MonoReflectionType *type)
1906 MonoDomain *domain = mono_domain_get ();
1907 MonoClass *class = mono_class_from_mono_type (type->type);
1909 MONO_ARCH_SAVE_REGS;
1911 if (type->type->byref) {
1912 char *n = g_strdup_printf ("%s&", class->name);
1913 MonoString *res = mono_string_new (domain, n);
1915 g_free (n);
1917 return res;
1918 } else {
1919 return mono_string_new (domain, class->name);
1923 static MonoString*
1924 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
1926 MonoDomain *domain = mono_domain_get ();
1927 MonoClass *class = mono_class_from_mono_type (type->type);
1929 MONO_ARCH_SAVE_REGS;
1931 while (class->nested_in)
1932 class = class->nested_in;
1934 if (class->name_space [0] == '\0')
1935 return NULL;
1936 else
1937 return mono_string_new (domain, class->name_space);
1940 static gint32
1941 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
1943 MonoClass *class = mono_class_from_mono_type (type->type);
1945 MONO_ARCH_SAVE_REGS;
1947 return class->rank;
1950 static MonoArray*
1951 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
1953 MonoArray *res;
1954 MonoClass *klass, *pklass;
1955 int i;
1956 MONO_ARCH_SAVE_REGS;
1958 klass = mono_class_from_mono_type (type->type);
1960 if (klass->generic_container) {
1961 MonoGenericContainer *container = klass->generic_container;
1962 res = mono_array_new (mono_object_domain (type), mono_defaults.monotype_class, container->type_argc);
1963 for (i = 0; i < container->type_argc; ++i) {
1964 pklass = mono_class_from_generic_parameter (&container->type_params [i], klass->image, FALSE);
1965 mono_array_setref (res, i, mono_type_get_object (mono_object_domain (type), &pklass->byval_arg));
1967 } else if (klass->generic_class) {
1968 MonoGenericInst *inst = klass->generic_class->inst;
1969 res = mono_array_new (mono_object_domain (type), mono_defaults.monotype_class, inst->type_argc);
1970 for (i = 0; i < inst->type_argc; ++i)
1971 mono_array_setref (res, i, mono_type_get_object (mono_object_domain (type), inst->type_argv [i]));
1972 } else {
1973 res = mono_array_new (mono_object_domain (type), mono_defaults.monotype_class, 0);
1975 return res;
1978 static gboolean
1979 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
1981 MonoClass *klass;
1982 MONO_ARCH_SAVE_REGS;
1984 if (type->type->byref)
1985 return FALSE;
1987 klass = mono_class_from_mono_type (type->type);
1989 return klass->generic_container != NULL;
1992 static MonoReflectionType*
1993 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
1995 MonoClass *klass;
1996 MONO_ARCH_SAVE_REGS;
1998 if (type->type->byref)
1999 return NULL;
2001 klass = mono_class_from_mono_type (type->type);
2002 if (klass->generic_container) {
2003 return type; /* check this one */
2005 if (klass->generic_class) {
2006 MonoClass *generic_class = klass->generic_class->container_class;
2008 if (generic_class->wastypebuilder && generic_class->reflection_info)
2009 return generic_class->reflection_info;
2010 else
2011 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2013 return NULL;
2016 static MonoReflectionType*
2017 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2019 MonoType *geninst, **types;
2020 int i, count;
2022 MONO_ARCH_SAVE_REGS;
2024 count = mono_array_length (type_array);
2025 types = g_new0 (MonoType *, count);
2027 for (i = 0; i < count; i++) {
2028 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2029 types [i] = t->type;
2032 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2033 g_free (types);
2034 if (!geninst)
2035 return NULL;
2037 return mono_type_get_object (mono_object_domain (type), geninst);
2040 static gboolean
2041 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2043 MonoClass *klass;
2044 MONO_ARCH_SAVE_REGS;
2046 if (type->type->byref)
2047 return FALSE;
2049 klass = mono_class_from_mono_type (type->type);
2050 return klass->generic_class != NULL;
2053 static gboolean
2054 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2056 MonoClass *klass;
2057 MONO_ARCH_SAVE_REGS;
2059 if (type->type->byref)
2060 return FALSE;
2062 klass = mono_class_from_mono_type (type->type);
2063 return klass->generic_class != NULL || klass->generic_container != NULL;
2066 static gint32
2067 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2069 MONO_ARCH_SAVE_REGS;
2071 if (is_generic_parameter (type->type))
2072 return type->type->data.generic_param->num;
2073 return -1;
2076 static GenericParameterAttributes
2077 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2079 MONO_ARCH_SAVE_REGS;
2080 g_assert (is_generic_parameter (type->type));
2081 return type->type->data.generic_param->flags;
2084 static MonoArray *
2085 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2087 MonoGenericParam *param;
2088 MonoDomain *domain;
2089 MonoClass **ptr;
2090 MonoArray *res;
2091 int i, count;
2093 MONO_ARCH_SAVE_REGS;
2095 domain = mono_object_domain (type);
2096 param = type->type->data.generic_param;
2097 for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
2100 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2101 for (i = 0; i < count; i++)
2102 mono_array_setref (res, i, mono_type_get_object (domain, &param->constraints [i]->byval_arg));
2105 return res;
2108 static MonoBoolean
2109 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2111 MONO_ARCH_SAVE_REGS;
2112 return is_generic_parameter (type->type);
2115 static MonoBoolean
2116 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2118 MONO_ARCH_SAVE_REGS;
2119 return is_generic_parameter (tb->type.type);
2122 static void
2123 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2124 MonoReflectionType *t)
2126 enumtype->type = t->type;
2129 static MonoReflectionType*
2130 ves_icall_MonoGenericClass_GetParentType (MonoReflectionGenericClass *type)
2132 MonoDynamicGenericClass *gclass;
2133 MonoReflectionType *parent = NULL;
2134 MonoDomain *domain;
2135 MonoType *inflated;
2136 MonoClass *klass;
2138 MONO_ARCH_SAVE_REGS;
2140 g_assert (type->type.type->data.generic_class->is_dynamic);
2141 gclass = (MonoDynamicGenericClass *) type->type.type->data.generic_class;
2143 domain = mono_object_domain (type);
2144 klass = mono_class_from_mono_type (type->generic_type->type);
2146 if (!klass->generic_class && !klass->generic_container)
2147 return NULL;
2149 if (!strcmp (type->generic_type->object.vtable->klass->name, "TypeBuilder")) {
2150 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *) type->generic_type;
2151 parent = tb->parent;
2152 } else if (klass->wastypebuilder) {
2153 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *) type->generic_type;
2154 parent = tb->parent;
2155 } else {
2156 MonoClass *pklass = klass->parent;
2157 if (pklass)
2158 parent = mono_type_get_object (domain, &pklass->byval_arg);
2161 if (!parent || (parent->type->type != MONO_TYPE_GENERICINST))
2162 return NULL;
2164 inflated = mono_class_inflate_generic_type (
2165 parent->type, mono_generic_class_get_context ((MonoGenericClass *) gclass));
2167 return mono_type_get_object (domain, inflated);
2170 static MonoArray*
2171 ves_icall_MonoGenericClass_GetInterfaces (MonoReflectionGenericClass *type)
2173 static MonoClass *System_Reflection_MonoGenericClass;
2174 MonoGenericClass *gclass;
2175 MonoReflectionTypeBuilder *tb = NULL;
2176 MonoClass *klass = NULL;
2177 MonoDomain *domain;
2178 MonoArray *res;
2179 int icount, i;
2181 MONO_ARCH_SAVE_REGS;
2183 if (!System_Reflection_MonoGenericClass) {
2184 System_Reflection_MonoGenericClass = mono_class_from_name (
2185 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
2186 g_assert (System_Reflection_MonoGenericClass);
2189 domain = mono_object_domain (type);
2191 gclass = type->type.type->data.generic_class;
2192 g_assert (gclass->is_dynamic);
2194 if (!strcmp (type->generic_type->object.vtable->klass->name, "TypeBuilder")) {
2195 tb = (MonoReflectionTypeBuilder *) type->generic_type;
2196 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
2197 } else {
2198 klass = gclass->container_class;
2199 mono_class_init (klass);
2200 icount = klass->interface_count;
2203 res = mono_array_new (domain, System_Reflection_MonoGenericClass, icount);
2205 for (i = 0; i < icount; i++) {
2206 MonoReflectionType *iface;
2207 MonoType *it;
2209 if (tb) {
2210 iface = mono_array_get (tb->interfaces, MonoReflectionType *, i);
2211 it = iface->type;
2212 } else
2213 it = &klass->interfaces [i]->byval_arg;
2215 it = mono_class_inflate_generic_type (it, mono_generic_class_get_context (gclass));
2217 iface = mono_type_get_object (domain, it);
2218 mono_array_setref (res, i, iface);
2221 return res;
2224 static MonoReflectionMethod*
2225 ves_icall_MonoGenericClass_GetCorrespondingInflatedMethod (MonoReflectionGenericClass *type,
2226 MonoReflectionMethod* generic)
2228 MonoGenericClass *gclass;
2229 MonoDynamicGenericClass *dgclass;
2230 MonoDomain *domain;
2231 int i;
2233 MONO_ARCH_SAVE_REGS;
2235 gclass = type->type.type->data.generic_class;
2236 g_assert (gclass->is_dynamic);
2238 dgclass = (MonoDynamicGenericClass *) gclass;
2240 domain = mono_object_domain (type);
2242 for (i = 0; i < dgclass->count_methods; i++)
2243 if (generic->method->token == dgclass->methods [i]->token)
2244 return mono_method_get_object (domain, dgclass->methods [i], NULL);
2246 return NULL;
2249 static MonoReflectionMethod*
2250 ves_icall_MonoGenericClass_GetCorrespondingInflatedConstructor (MonoReflectionGenericClass *type,
2251 MonoReflectionMethod* generic)
2253 MonoGenericClass *gclass;
2254 MonoDynamicGenericClass *dgclass;
2255 MonoDomain *domain;
2256 int i;
2258 MONO_ARCH_SAVE_REGS;
2260 gclass = type->type.type->data.generic_class;
2261 g_assert (gclass->is_dynamic);
2263 dgclass = (MonoDynamicGenericClass *) gclass;
2265 domain = mono_object_domain (type);
2267 for (i = 0; i < dgclass->count_ctors; i++)
2268 if (generic->method->token == dgclass->ctors [i]->token)
2269 return mono_method_get_object (domain, dgclass->ctors [i], NULL);
2271 return NULL;
2275 static MonoReflectionField*
2276 ves_icall_MonoGenericClass_GetCorrespondingInflatedField (MonoReflectionGenericClass *type,
2277 MonoString* generic_name)
2279 MonoGenericClass *gclass;
2280 MonoDynamicGenericClass *dgclass;
2281 MonoDomain *domain;
2282 MonoClass *refclass;
2283 char *utf8_name = mono_string_to_utf8 (generic_name);
2284 int i;
2286 MONO_ARCH_SAVE_REGS;
2288 gclass = type->type.type->data.generic_class;
2289 g_assert (gclass->is_dynamic);
2291 dgclass = (MonoDynamicGenericClass *) gclass;
2293 refclass = mono_class_from_mono_type (type->type.type);
2295 domain = mono_object_domain (type);
2297 for (i = 0; i < dgclass->count_fields; i++)
2298 if (strcmp (utf8_name, dgclass->fields [i].name) == 0) {
2299 g_free (utf8_name);
2300 return mono_field_get_object (domain, refclass, &dgclass->fields [i]);
2303 g_free (utf8_name);
2305 return NULL;
2309 static MonoReflectionMethod*
2310 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2311 MonoReflectionMethod* generic)
2313 MonoDomain *domain;
2314 MonoClass *klass;
2315 MonoMethod *method;
2316 gpointer iter;
2318 MONO_ARCH_SAVE_REGS;
2320 domain = ((MonoObject *)type)->vtable->domain;
2322 klass = mono_class_from_mono_type (type->type);
2324 iter = NULL;
2325 while ((method = mono_class_get_methods (klass, &iter))) {
2326 if (method->token == generic->method->token)
2327 return mono_method_get_object (domain, method, klass);
2330 return NULL;
2333 static MonoArray*
2334 ves_icall_MonoGenericClass_GetMethods (MonoReflectionGenericClass *type,
2335 MonoReflectionType *reflected_type)
2337 MonoGenericClass *gclass;
2338 MonoDynamicGenericClass *dgclass;
2339 MonoDomain *domain;
2340 MonoClass *refclass;
2341 MonoArray *res;
2342 int i;
2344 MONO_ARCH_SAVE_REGS;
2346 gclass = type->type.type->data.generic_class;
2347 g_assert (gclass->is_dynamic);
2348 dgclass = (MonoDynamicGenericClass *) gclass;
2350 refclass = mono_class_from_mono_type (reflected_type->type);
2352 domain = mono_object_domain (type);
2353 res = mono_array_new (domain, mono_defaults.method_info_class, dgclass->count_methods);
2355 for (i = 0; i < dgclass->count_methods; i++)
2356 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->methods [i], refclass));
2358 return res;
2361 static MonoArray*
2362 ves_icall_MonoGenericClass_GetConstructors (MonoReflectionGenericClass *type,
2363 MonoReflectionType *reflected_type)
2365 static MonoClass *System_Reflection_ConstructorInfo;
2366 MonoGenericClass *gclass;
2367 MonoDynamicGenericClass *dgclass;
2368 MonoDomain *domain;
2369 MonoClass *refclass;
2370 MonoArray *res;
2371 int i;
2373 MONO_ARCH_SAVE_REGS;
2375 if (!System_Reflection_ConstructorInfo)
2376 System_Reflection_ConstructorInfo = mono_class_from_name (
2377 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
2379 gclass = type->type.type->data.generic_class;
2380 g_assert (gclass->is_dynamic);
2381 dgclass = (MonoDynamicGenericClass *) gclass;
2383 refclass = mono_class_from_mono_type (reflected_type->type);
2385 domain = mono_object_domain (type);
2386 res = mono_array_new (domain, System_Reflection_ConstructorInfo, dgclass->count_ctors);
2388 for (i = 0; i < dgclass->count_ctors; i++)
2389 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->ctors [i], refclass));
2391 return res;
2394 static MonoArray*
2395 ves_icall_MonoGenericClass_GetFields (MonoReflectionGenericClass *type,
2396 MonoReflectionType *reflected_type)
2398 MonoGenericClass *gclass;
2399 MonoDynamicGenericClass *dgclass;
2400 MonoDomain *domain;
2401 MonoClass *refclass;
2402 MonoArray *res;
2403 int i;
2405 MONO_ARCH_SAVE_REGS;
2407 gclass = type->type.type->data.generic_class;
2408 g_assert (gclass->is_dynamic);
2409 dgclass = (MonoDynamicGenericClass *) gclass;
2411 refclass = mono_class_from_mono_type (reflected_type->type);
2413 domain = mono_object_domain (type);
2414 res = mono_array_new (domain, mono_defaults.field_info_class, dgclass->count_fields);
2416 for (i = 0; i < dgclass->count_fields; i++)
2417 mono_array_setref (res, i, mono_field_get_object (domain, refclass, &dgclass->fields [i]));
2419 return res;
2422 static MonoArray*
2423 ves_icall_MonoGenericClass_GetProperties (MonoReflectionGenericClass *type,
2424 MonoReflectionType *reflected_type)
2426 static MonoClass *System_Reflection_PropertyInfo;
2427 MonoGenericClass *gclass;
2428 MonoDynamicGenericClass *dgclass;
2429 MonoDomain *domain;
2430 MonoClass *refclass;
2431 MonoArray *res;
2432 int i;
2434 MONO_ARCH_SAVE_REGS;
2436 if (!System_Reflection_PropertyInfo)
2437 System_Reflection_PropertyInfo = mono_class_from_name (
2438 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
2440 gclass = type->type.type->data.generic_class;
2441 g_assert (gclass->is_dynamic);
2442 dgclass = (MonoDynamicGenericClass *) gclass;
2444 refclass = mono_class_from_mono_type (reflected_type->type);
2446 domain = mono_object_domain (type);
2447 res = mono_array_new (domain, System_Reflection_PropertyInfo, dgclass->count_properties);
2449 for (i = 0; i < dgclass->count_properties; i++)
2450 mono_array_setref (res, i, mono_property_get_object (domain, refclass, &dgclass->properties [i]));
2452 return res;
2455 static MonoArray*
2456 ves_icall_MonoGenericClass_GetEvents (MonoReflectionGenericClass *type,
2457 MonoReflectionType *reflected_type)
2459 static MonoClass *System_Reflection_EventInfo;
2460 MonoGenericClass *gclass;
2461 MonoDynamicGenericClass *dgclass;
2462 MonoDomain *domain;
2463 MonoClass *refclass;
2464 MonoArray *res;
2465 int i;
2467 MONO_ARCH_SAVE_REGS;
2469 if (!System_Reflection_EventInfo)
2470 System_Reflection_EventInfo = mono_class_from_name (
2471 mono_defaults.corlib, "System.Reflection", "EventInfo");
2473 gclass = type->type.type->data.generic_class;
2474 g_assert (gclass->is_dynamic);
2475 dgclass = (MonoDynamicGenericClass *) gclass;
2477 refclass = mono_class_from_mono_type (reflected_type->type);
2479 domain = mono_object_domain (type);
2480 res = mono_array_new (domain, System_Reflection_EventInfo, dgclass->count_events);
2482 for (i = 0; i < dgclass->count_events; i++)
2483 mono_array_setref (res, i, mono_event_get_object (domain, refclass, &dgclass->events [i]));
2485 return res;
2488 static MonoReflectionMethod *
2489 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *type)
2491 MonoMethod *method;
2492 MonoClass *klass;
2494 MONO_ARCH_SAVE_REGS;
2496 if (type->type->byref || type->type->type != MONO_TYPE_MVAR)
2497 return NULL;
2499 method = type->type->data.generic_param->owner->owner.method;
2500 g_assert (method);
2501 klass = mono_class_from_mono_type (type->type);
2502 return mono_method_get_object (mono_object_domain (type), method, klass);
2505 static MonoReflectionDllImportAttribute*
2506 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2508 static MonoClass *DllImportAttributeClass = NULL;
2509 MonoDomain *domain = mono_domain_get ();
2510 MonoReflectionDllImportAttribute *attr;
2511 MonoImage *image = method->klass->image;
2512 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2513 MonoTableInfo *tables = image->tables;
2514 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2515 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2516 guint32 im_cols [MONO_IMPLMAP_SIZE];
2517 guint32 scope_token;
2518 const char *import = NULL;
2519 const char *scope = NULL;
2520 guint32 flags;
2522 if (!method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2523 return NULL;
2525 if (!DllImportAttributeClass) {
2526 DllImportAttributeClass =
2527 mono_class_from_name (mono_defaults.corlib,
2528 "System.Runtime.InteropServices", "DllImportAttribute");
2529 g_assert (DllImportAttributeClass);
2532 if (method->klass->image->dynamic) {
2533 MonoReflectionMethodAux *method_aux =
2534 g_hash_table_lookup (
2535 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2536 if (method_aux) {
2537 import = method_aux->dllentry;
2538 scope = method_aux->dll;
2541 else {
2542 if (piinfo->implmap_idx) {
2543 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2545 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2546 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2547 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2548 scope = mono_metadata_string_heap (image, scope_token);
2551 flags = piinfo->piflags;
2553 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2555 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2556 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2557 attr->call_conv = (flags & 0x700) >> 8;
2558 attr->charset = ((flags & 0x6) >> 1) + 1;
2559 if (attr->charset == 1)
2560 attr->charset = 2;
2561 attr->exact_spelling = (flags & 0x1) != 0;
2562 attr->set_last_error = (flags & 0x40) != 0;
2563 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2564 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2565 attr->preserve_sig = FALSE;
2567 return attr;
2570 static MonoReflectionMethod *
2571 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2573 MonoGenericContext *context;
2574 MonoMethodInflated *imethod;
2576 MONO_ARCH_SAVE_REGS;
2578 if (!method->method->is_inflated) {
2579 if (mono_method_signature (method->method)->generic_param_count)
2580 return method;
2582 return NULL;
2585 imethod = (MonoMethodInflated *) method->method;
2587 /* FIXME: should reflection_info be part of imethod? */
2588 context = mono_method_get_context (method->method);
2589 if (context->gmethod && context->gmethod->reflection_info)
2590 return context->gmethod->reflection_info;
2591 else
2592 return mono_method_get_object (
2593 mono_object_domain (method), imethod->declaring, NULL);
2596 static gboolean
2597 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2599 MONO_ARCH_SAVE_REGS;
2601 return mono_method_signature (method->method)->generic_param_count != 0;
2604 static gboolean
2605 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2607 MONO_ARCH_SAVE_REGS;
2609 return !method->method->is_inflated &&
2610 (mono_method_signature (method->method)->generic_param_count != 0);
2613 static MonoArray*
2614 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2616 MonoArray *res;
2617 MonoDomain *domain;
2618 int count, i;
2619 MONO_ARCH_SAVE_REGS;
2621 domain = mono_object_domain (method);
2623 if (method->method->is_inflated) {
2624 MonoGenericMethod *gmethod = mono_method_get_context (method->method)->gmethod;
2626 if (gmethod) {
2627 count = gmethod->inst->type_argc;
2628 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2630 for (i = 0; i < count; i++)
2631 mono_array_setref (res, i, mono_type_get_object (domain, gmethod->inst->type_argv [i]));
2633 return res;
2637 count = mono_method_signature (method->method)->generic_param_count;
2638 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2640 for (i = 0; i < count; i++) {
2641 MonoGenericParam *param = &method->method->generic_container->type_params [i];
2642 MonoClass *pklass = mono_class_from_generic_parameter (
2643 param, method->method->klass->image, TRUE);
2644 mono_array_setref (res, i,
2645 mono_type_get_object (domain, &pklass->byval_arg));
2648 return res;
2651 static MonoObject *
2652 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params)
2655 * Invoke from reflection is supposed to always be a virtual call (the API
2656 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2657 * greater flexibility.
2659 MonoMethod *m = mono_get_inflated_method (method->method);
2660 int pcount;
2661 void *obj = this;
2663 MONO_ARCH_SAVE_REGS;
2665 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2666 if (this) {
2667 if (!mono_object_isinst (this, m->klass))
2668 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetException"));
2669 m = mono_object_get_virtual_method (this, m);
2670 /* must pass the pointer to the value for valuetype methods */
2671 if (m->klass->valuetype)
2672 obj = mono_object_unbox (this);
2673 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type)
2674 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetException"));
2677 pcount = params? mono_array_length (params): 0;
2678 if (pcount != mono_method_signature (m)->param_count)
2679 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2681 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor"))
2682 mono_raise_exception (mono_exception_from_name_msg (mono_defaults.corlib, "System", "MethodAccessException", "Cannot invoke constructor of an abstract class."));
2684 if (m->klass->image->assembly->ref_only)
2685 mono_raise_exception (mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
2687 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2688 int i;
2689 guint32 *lengths;
2690 guint32 *lower_bounds;
2691 pcount = mono_array_length (params);
2692 lengths = alloca (sizeof (guint32) * pcount);
2693 for (i = 0; i < pcount; ++i)
2694 lengths [i] = *(gint32*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2696 if (m->klass->rank == pcount) {
2697 /* Only lengths provided. */
2698 lower_bounds = NULL;
2699 } else {
2700 g_assert (pcount == (m->klass->rank * 2));
2701 /* lower bounds are first. */
2702 lower_bounds = lengths;
2703 lengths += m->klass->rank;
2706 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2708 return mono_runtime_invoke_array (m, obj, params, NULL);
2711 static MonoObject *
2712 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2714 MonoDomain *domain = mono_object_domain (method);
2715 MonoMethod *m = method->method;
2716 MonoMethodSignature *sig = mono_method_signature (m);
2717 MonoArray *out_args;
2718 MonoObject *result;
2719 int i, j, outarg_count = 0;
2721 MONO_ARCH_SAVE_REGS;
2723 if (m->klass == mono_defaults.object_class) {
2725 if (!strcmp (m->name, "FieldGetter")) {
2726 MonoClass *k = this->vtable->klass;
2727 MonoString *name;
2728 char *str;
2730 /* If this is a proxy, then it must be a CBO */
2731 if (k == mono_defaults.transparent_proxy_class) {
2732 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2733 this = tp->rp->unwrapped_server;
2734 g_assert (this);
2735 k = this->vtable->klass;
2738 name = mono_array_get (params, MonoString *, 1);
2739 str = mono_string_to_utf8 (name);
2741 do {
2742 MonoClassField* field = mono_class_get_field_from_name (k, str);
2743 if (field) {
2744 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2745 if (field_klass->valuetype)
2746 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2747 else
2748 result = *((gpointer *)((char *)this + field->offset));
2750 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2751 *outArgs = out_args;
2752 mono_array_setref (out_args, 0, result);
2753 g_free (str);
2754 return NULL;
2756 k = k->parent;
2757 } while (k);
2759 g_free (str);
2760 g_assert_not_reached ();
2762 } else if (!strcmp (m->name, "FieldSetter")) {
2763 MonoClass *k = this->vtable->klass;
2764 MonoString *name;
2765 guint32 size;
2766 gint32 align;
2767 char *str;
2769 /* If this is a proxy, then it must be a CBO */
2770 if (k == mono_defaults.transparent_proxy_class) {
2771 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2772 this = tp->rp->unwrapped_server;
2773 g_assert (this);
2774 k = this->vtable->klass;
2777 name = mono_array_get (params, MonoString *, 1);
2778 str = mono_string_to_utf8 (name);
2780 do {
2781 MonoClassField* field = mono_class_get_field_from_name (k, str);
2782 if (field) {
2783 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2784 MonoObject *val = mono_array_get (params, gpointer, 2);
2786 if (field_klass->valuetype) {
2787 size = mono_type_size (field->type, &align);
2788 memcpy ((char *)this + field->offset,
2789 ((char *)val) + sizeof (MonoObject), size);
2790 } else
2791 *(MonoObject**)((char *)this + field->offset) = val;
2793 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2794 *outArgs = out_args;
2796 g_free (str);
2797 return NULL;
2800 k = k->parent;
2801 } while (k);
2803 g_free (str);
2804 g_assert_not_reached ();
2809 for (i = 0; i < mono_array_length (params); i++) {
2810 if (sig->params [i]->byref)
2811 outarg_count++;
2814 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2816 /* handle constructors only for objects already allocated */
2817 if (!strcmp (method->method->name, ".ctor"))
2818 g_assert (this);
2820 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2821 g_assert (!method->method->klass->valuetype);
2822 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2824 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2825 if (sig->params [i]->byref) {
2826 gpointer arg;
2827 arg = mono_array_get (params, gpointer, i);
2828 mono_array_setref (out_args, j, arg);
2829 j++;
2833 *outArgs = out_args;
2835 return result;
2838 static guint64
2839 read_enum_value (char *mem, int type)
2841 switch (type) {
2842 case MONO_TYPE_U1:
2843 return *(guint8*)mem;
2844 case MONO_TYPE_I1:
2845 return *(gint8*)mem;
2846 case MONO_TYPE_U2:
2847 return *(guint16*)mem;
2848 case MONO_TYPE_I2:
2849 return *(gint16*)mem;
2850 case MONO_TYPE_U4:
2851 return *(guint32*)mem;
2852 case MONO_TYPE_I4:
2853 return *(gint32*)mem;
2854 case MONO_TYPE_U8:
2855 return *(guint64*)mem;
2856 case MONO_TYPE_I8:
2857 return *(gint64*)mem;
2858 default:
2859 g_assert_not_reached ();
2861 return 0;
2864 static void
2865 write_enum_value (char *mem, int type, guint64 value)
2867 switch (type) {
2868 case MONO_TYPE_U1:
2869 case MONO_TYPE_I1: {
2870 guint8 *p = (guint8*)mem;
2871 *p = value;
2872 break;
2874 case MONO_TYPE_U2:
2875 case MONO_TYPE_I2: {
2876 guint16 *p = (void*)mem;
2877 *p = value;
2878 break;
2880 case MONO_TYPE_U4:
2881 case MONO_TYPE_I4: {
2882 guint32 *p = (void*)mem;
2883 *p = value;
2884 break;
2886 case MONO_TYPE_U8:
2887 case MONO_TYPE_I8: {
2888 guint64 *p = (void*)mem;
2889 *p = value;
2890 break;
2892 default:
2893 g_assert_not_reached ();
2895 return;
2898 static MonoObject *
2899 ves_icall_System_Enum_ToObject (MonoReflectionType *type, MonoObject *obj)
2901 MonoDomain *domain;
2902 MonoClass *enumc, *objc;
2903 MonoObject *res;
2904 guint64 val;
2906 MONO_ARCH_SAVE_REGS;
2908 MONO_CHECK_ARG_NULL (type);
2909 MONO_CHECK_ARG_NULL (obj);
2911 domain = mono_object_domain (type);
2912 enumc = mono_class_from_mono_type (type->type);
2913 objc = obj->vtable->klass;
2915 if (!enumc->enumtype)
2916 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
2917 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
2918 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."));
2920 res = mono_object_new (domain, enumc);
2921 val = read_enum_value ((char *)obj + sizeof (MonoObject), objc->enumtype? objc->enum_basetype->type: objc->byval_arg.type);
2922 write_enum_value ((char *)res + sizeof (MonoObject), enumc->enum_basetype->type, val);
2924 return res;
2927 static MonoObject *
2928 ves_icall_System_Enum_get_value (MonoObject *this)
2930 MonoObject *res;
2931 MonoClass *enumc;
2932 gpointer dst;
2933 gpointer src;
2934 int size;
2936 MONO_ARCH_SAVE_REGS;
2938 if (!this)
2939 return NULL;
2941 g_assert (this->vtable->klass->enumtype);
2943 enumc = mono_class_from_mono_type (this->vtable->klass->enum_basetype);
2944 res = mono_object_new (mono_object_domain (this), enumc);
2945 dst = (char *)res + sizeof (MonoObject);
2946 src = (char *)this + sizeof (MonoObject);
2947 size = mono_class_value_size (enumc, NULL);
2949 memcpy (dst, src, size);
2951 return res;
2954 static void
2955 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
2957 MonoDomain *domain = mono_object_domain (type);
2958 MonoClass *enumc = mono_class_from_mono_type (type->type);
2959 guint j = 0, nvalues, crow;
2960 gpointer iter;
2961 MonoClassField *field;
2963 MONO_ARCH_SAVE_REGS;
2965 info->utype = mono_type_get_object (domain, enumc->enum_basetype);
2966 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
2967 info->names = mono_array_new (domain, mono_defaults.string_class, nvalues);
2968 info->values = mono_array_new (domain, enumc, nvalues);
2970 crow = -1;
2971 iter = NULL;
2972 while ((field = mono_class_get_fields (enumc, &iter))) {
2973 const char *p;
2974 int len;
2976 if (strcmp ("value__", field->name) == 0)
2977 continue;
2978 if (mono_field_is_deleted (field))
2979 continue;
2980 mono_array_setref (info->names, j, mono_string_new (domain, field->name));
2982 if (!field->data) {
2983 crow = mono_metadata_get_constant_index (enumc->image, mono_class_get_field_token (field), crow + 1);
2984 field->def_type = mono_metadata_decode_row_col (&enumc->image->tables [MONO_TABLE_CONSTANT], crow-1, MONO_CONSTANT_TYPE);
2985 crow = mono_metadata_decode_row_col (&enumc->image->tables [MONO_TABLE_CONSTANT], crow-1, MONO_CONSTANT_VALUE);
2986 field->data = (gpointer)mono_metadata_blob_heap (enumc->image, crow);
2989 p = field->data;
2990 len = mono_metadata_decode_blob_size (p, &p);
2991 switch (enumc->enum_basetype->type) {
2992 case MONO_TYPE_U1:
2993 case MONO_TYPE_I1:
2994 mono_array_set (info->values, gchar, j, *p);
2995 break;
2996 case MONO_TYPE_CHAR:
2997 case MONO_TYPE_U2:
2998 case MONO_TYPE_I2:
2999 mono_array_set (info->values, gint16, j, read16 (p));
3000 break;
3001 case MONO_TYPE_U4:
3002 case MONO_TYPE_I4:
3003 mono_array_set (info->values, gint32, j, read32 (p));
3004 break;
3005 case MONO_TYPE_U8:
3006 case MONO_TYPE_I8:
3007 mono_array_set (info->values, gint64, j, read64 (p));
3008 break;
3009 default:
3010 g_error ("Implement type 0x%02x in get_enum_info", enumc->enum_basetype->type);
3012 ++j;
3016 enum {
3017 BFLAGS_IgnoreCase = 1,
3018 BFLAGS_DeclaredOnly = 2,
3019 BFLAGS_Instance = 4,
3020 BFLAGS_Static = 8,
3021 BFLAGS_Public = 0x10,
3022 BFLAGS_NonPublic = 0x20,
3023 BFLAGS_FlattenHierarchy = 0x40,
3024 BFLAGS_InvokeMethod = 0x100,
3025 BFLAGS_CreateInstance = 0x200,
3026 BFLAGS_GetField = 0x400,
3027 BFLAGS_SetField = 0x800,
3028 BFLAGS_GetProperty = 0x1000,
3029 BFLAGS_SetProperty = 0x2000,
3030 BFLAGS_ExactBinding = 0x10000,
3031 BFLAGS_SuppressChangeType = 0x20000,
3032 BFLAGS_OptionalParamBinding = 0x40000
3035 static MonoReflectionField *
3036 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3038 MonoDomain *domain;
3039 MonoClass *startklass, *klass;
3040 int match;
3041 MonoClassField *field;
3042 gpointer iter;
3043 char *utf8_name;
3044 int (*compare_func) (const char *s1, const char *s2) = NULL;
3045 domain = ((MonoObject *)type)->vtable->domain;
3046 klass = startklass = mono_class_from_mono_type (type->type);
3048 MONO_ARCH_SAVE_REGS;
3050 if (!name)
3051 mono_raise_exception (mono_get_exception_argument_null ("name"));
3052 if (type->type->byref)
3053 return NULL;
3055 compare_func = (bflags & BFLAGS_IgnoreCase) ? g_strcasecmp : strcmp;
3057 handle_parent:
3058 iter = NULL;
3059 while ((field = mono_class_get_fields (klass, &iter))) {
3060 match = 0;
3061 if (mono_field_is_deleted (field))
3062 continue;
3063 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3064 if (bflags & BFLAGS_Public)
3065 match++;
3066 } else {
3067 if (bflags & BFLAGS_NonPublic)
3068 match++;
3070 if (!match)
3071 continue;
3072 match = 0;
3073 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3074 if (bflags & BFLAGS_Static)
3075 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3076 match++;
3077 } else {
3078 if (bflags & BFLAGS_Instance)
3079 match++;
3082 if (!match)
3083 continue;
3085 utf8_name = mono_string_to_utf8 (name);
3087 if (compare_func (field->name, utf8_name)) {
3088 g_free (utf8_name);
3089 continue;
3091 g_free (utf8_name);
3093 return mono_field_get_object (domain, klass, field);
3095 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3096 goto handle_parent;
3098 return NULL;
3101 static MonoArray*
3102 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3104 MonoDomain *domain;
3105 MonoClass *startklass, *klass, *refklass;
3106 MonoArray *res;
3107 MonoObject *member;
3108 int i, len, match;
3109 gpointer iter;
3110 MonoClassField *field;
3112 MONO_ARCH_SAVE_REGS;
3114 domain = ((MonoObject *)type)->vtable->domain;
3115 if (type->type->byref)
3116 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3117 klass = startklass = mono_class_from_mono_type (type->type);
3118 refklass = mono_class_from_mono_type (reftype->type);
3120 i = 0;
3121 len = 2;
3122 res = mono_array_new (domain, mono_defaults.field_info_class, len);
3123 handle_parent:
3124 iter = NULL;
3125 while ((field = mono_class_get_fields (klass, &iter))) {
3126 match = 0;
3127 if (mono_field_is_deleted (field))
3128 continue;
3129 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3130 if (bflags & BFLAGS_Public)
3131 match++;
3132 } else {
3133 if (bflags & BFLAGS_NonPublic) {
3134 /* Serialization currently depends on the old behavior.
3135 * if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE || startklass == klass)*/
3136 match++;
3139 if (!match)
3140 continue;
3141 match = 0;
3142 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3143 if (bflags & BFLAGS_Static)
3144 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3145 match++;
3146 } else {
3147 if (bflags & BFLAGS_Instance)
3148 match++;
3151 if (!match)
3152 continue;
3153 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3154 if (i >= len) {
3155 MonoArray *new_res = mono_array_new (domain, mono_defaults.field_info_class, len * 2);
3156 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3157 len *= 2;
3158 res = new_res;
3160 mono_array_setref (res, i, member);
3161 ++i;
3163 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3164 goto handle_parent;
3165 if (i != len) {
3166 MonoArray *new_res = mono_array_new (domain, mono_defaults.field_info_class, i);
3167 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3168 res = new_res;
3170 * Better solution for the new GC.
3171 * res->max_length = i;
3174 return res;
3177 static MonoArray*
3178 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3180 MonoDomain *domain;
3181 MonoClass *startklass, *klass, *refklass;
3182 MonoArray *res;
3183 MonoMethod *method;
3184 gpointer iter;
3185 MonoObject *member;
3186 int i, len, match, nslots;
3187 guint32 method_slots_default [8];
3188 guint32 *method_slots;
3189 gchar *mname = NULL;
3190 int (*compare_func) (const char *s1, const char *s2) = NULL;
3192 MONO_ARCH_SAVE_REGS;
3194 domain = ((MonoObject *)type)->vtable->domain;
3195 if (type->type->byref)
3196 return mono_array_new (domain, mono_defaults.method_info_class, 0);
3197 klass = startklass = mono_class_from_mono_type (type->type);
3198 refklass = mono_class_from_mono_type (reftype->type);
3199 len = 0;
3200 if (name != NULL) {
3201 mname = mono_string_to_utf8 (name);
3202 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3205 mono_class_setup_vtable (klass);
3207 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : klass->vtable_size;
3208 if (nslots >= sizeof (method_slots_default) * 8) {
3209 method_slots = g_new0 (guint32, nslots / 32 + 1);
3210 } else {
3211 method_slots = method_slots_default;
3212 memset (method_slots, 0, sizeof (method_slots_default));
3214 i = 0;
3215 len = 1;
3216 res = mono_array_new (domain, mono_defaults.method_info_class, len);
3217 handle_parent:
3218 mono_class_setup_vtable (klass);
3219 iter = NULL;
3220 while ((method = mono_class_get_methods (klass, &iter))) {
3221 match = 0;
3222 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3223 continue;
3224 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3225 if (bflags & BFLAGS_Public)
3226 match++;
3227 } else {
3228 if (bflags & BFLAGS_NonPublic)
3229 match++;
3231 if (!match)
3232 continue;
3233 match = 0;
3234 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3235 if (bflags & BFLAGS_Static)
3236 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3237 match++;
3238 } else {
3239 if (bflags & BFLAGS_Instance)
3240 match++;
3243 if (!match)
3244 continue;
3246 if (name != NULL) {
3247 if (compare_func (mname, method->name))
3248 continue;
3251 match = 0;
3252 if (method->slot != -1) {
3253 g_assert (method->slot < nslots);
3254 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3255 continue;
3256 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3259 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3261 if (i >= len) {
3262 MonoArray *new_res = mono_array_new (domain, mono_defaults.method_info_class, len * 2);
3263 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3264 len *= 2;
3265 res = new_res;
3267 mono_array_setref (res, i, member);
3268 ++i;
3270 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3271 goto handle_parent;
3273 g_free (mname);
3274 if (method_slots != method_slots_default)
3275 g_free (method_slots);
3276 if (i != len) {
3277 MonoArray *new_res = mono_array_new (domain, mono_defaults.method_info_class, i);
3278 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3279 res = new_res;
3281 * Better solution for the new GC.
3282 * res->max_length = i;
3285 return res;
3288 static MonoArray*
3289 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3291 MonoDomain *domain;
3292 static MonoClass *System_Reflection_ConstructorInfo;
3293 MonoClass *startklass, *klass, *refklass;
3294 MonoArray *res;
3295 MonoMethod *method;
3296 MonoObject *member;
3297 int i, len, match;
3298 gpointer iter = NULL;
3300 MONO_ARCH_SAVE_REGS;
3302 domain = ((MonoObject *)type)->vtable->domain;
3303 if (type->type->byref)
3304 return mono_array_new (domain, mono_defaults.method_info_class, 0);
3305 klass = startklass = mono_class_from_mono_type (type->type);
3306 refklass = mono_class_from_mono_type (reftype->type);
3308 if (!System_Reflection_ConstructorInfo)
3309 System_Reflection_ConstructorInfo = mono_class_from_name (
3310 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3312 i = 0;
3313 len = 2;
3314 res = mono_array_new (domain, System_Reflection_ConstructorInfo, len);
3315 iter = NULL;
3316 while ((method = mono_class_get_methods (klass, &iter))) {
3317 match = 0;
3318 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3319 continue;
3320 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3321 if (bflags & BFLAGS_Public)
3322 match++;
3323 } else {
3324 if (bflags & BFLAGS_NonPublic)
3325 match++;
3327 if (!match)
3328 continue;
3329 match = 0;
3330 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3331 if (bflags & BFLAGS_Static)
3332 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3333 match++;
3334 } else {
3335 if (bflags & BFLAGS_Instance)
3336 match++;
3339 if (!match)
3340 continue;
3341 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3343 if (i >= len) {
3344 MonoArray *new_res = mono_array_new (domain, System_Reflection_ConstructorInfo, len * 2);
3345 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3346 len *= 2;
3347 res = new_res;
3349 mono_array_setref (res, i, member);
3350 ++i;
3352 if (i != len) {
3353 MonoArray *new_res = mono_array_new (domain, System_Reflection_ConstructorInfo, i);
3354 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3355 res = new_res;
3357 * Better solution for the new GC.
3358 * res->max_length = i;
3361 return res;
3364 static MonoArray*
3365 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3367 MonoDomain *domain;
3368 static MonoClass *System_Reflection_PropertyInfo;
3369 MonoClass *startklass, *klass;
3370 MonoArray *res;
3371 MonoMethod *method;
3372 MonoProperty *prop;
3373 int i, match, nslots;
3374 int len = 0;
3375 guint32 flags;
3376 guint32 method_slots_default [8];
3377 guint32 *method_slots;
3378 gchar *propname = NULL;
3379 int (*compare_func) (const char *s1, const char *s2) = NULL;
3380 gpointer iter;
3382 MONO_ARCH_SAVE_REGS;
3384 if (!System_Reflection_PropertyInfo)
3385 System_Reflection_PropertyInfo = mono_class_from_name (
3386 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3388 domain = ((MonoObject *)type)->vtable->domain;
3389 if (type->type->byref)
3390 return mono_array_new (domain, System_Reflection_PropertyInfo, 0);
3391 klass = startklass = mono_class_from_mono_type (type->type);
3392 if (name != NULL) {
3393 propname = mono_string_to_utf8 (name);
3394 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3397 mono_class_setup_vtable (klass);
3399 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : klass->vtable_size;
3400 if (nslots >= sizeof (method_slots_default) * 8) {
3401 method_slots = g_new0 (guint32, nslots / 32 + 1);
3402 } else {
3403 method_slots = method_slots_default;
3404 memset (method_slots, 0, sizeof (method_slots_default));
3406 i = 0;
3407 len = 2;
3408 res = mono_array_new (domain, System_Reflection_PropertyInfo, len);
3409 handle_parent:
3410 mono_class_setup_vtable (klass);
3411 iter = NULL;
3412 while ((prop = mono_class_get_properties (klass, &iter))) {
3413 match = 0;
3414 method = prop->get;
3415 if (!method)
3416 method = prop->set;
3417 if (method)
3418 flags = method->flags;
3419 else
3420 flags = 0;
3421 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3422 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3423 if (bflags & BFLAGS_Public)
3424 match++;
3425 } else {
3426 if (bflags & BFLAGS_NonPublic)
3427 match++;
3429 if (!match)
3430 continue;
3431 match = 0;
3432 if (flags & METHOD_ATTRIBUTE_STATIC) {
3433 if (bflags & BFLAGS_Static)
3434 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3435 match++;
3436 } else {
3437 if (bflags & BFLAGS_Instance)
3438 match++;
3441 if (!match)
3442 continue;
3443 match = 0;
3445 if (name != NULL) {
3446 if (compare_func (propname, prop->name))
3447 continue;
3450 if (prop->get && prop->get->slot != -1) {
3451 if (method_slots [prop->get->slot >> 5] & (1 << (prop->get->slot & 0x1f)))
3452 continue;
3453 method_slots [prop->get->slot >> 5] |= 1 << (prop->get->slot & 0x1f);
3455 if (prop->set && prop->set->slot != -1) {
3456 if (method_slots [prop->set->slot >> 5] & (1 << (prop->set->slot & 0x1f)))
3457 continue;
3458 method_slots [prop->set->slot >> 5] |= 1 << (prop->set->slot & 0x1f);
3461 if (i >= len) {
3462 MonoArray *new_res = mono_array_new (domain, System_Reflection_PropertyInfo, len * 2);
3463 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3464 len *= 2;
3465 res = new_res;
3467 mono_array_setref (res, i, mono_property_get_object (domain, startklass, prop));
3468 ++i;
3470 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3471 goto handle_parent;
3473 g_free (propname);
3474 if (method_slots != method_slots_default)
3475 g_free (method_slots);
3476 if (i != len) {
3477 MonoArray *new_res = mono_array_new (domain, System_Reflection_PropertyInfo, i);
3478 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3479 res = new_res;
3481 * Better solution for the new GC.
3482 * res->max_length = i;
3485 return res;
3488 static MonoReflectionEvent *
3489 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3491 MonoDomain *domain;
3492 MonoClass *klass, *startklass;
3493 gpointer iter;
3494 MonoEvent *event;
3495 MonoMethod *method;
3496 gchar *event_name;
3498 MONO_ARCH_SAVE_REGS;
3500 event_name = mono_string_to_utf8 (name);
3501 if (type->type->byref)
3502 return NULL;
3503 klass = startklass = mono_class_from_mono_type (type->type);
3504 domain = mono_object_domain (type);
3506 handle_parent:
3507 iter = NULL;
3508 while ((event = mono_class_get_events (klass, &iter))) {
3509 if (strcmp (event->name, event_name))
3510 continue;
3512 method = event->add;
3513 if (!method)
3514 method = event->remove;
3515 if (!method)
3516 method = event->raise;
3517 if (method) {
3518 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3519 if (!(bflags & BFLAGS_Public))
3520 continue;
3521 } else {
3522 if (!(bflags & BFLAGS_NonPublic))
3523 continue;
3526 else
3527 if (!(bflags & BFLAGS_NonPublic))
3528 continue;
3530 g_free (event_name);
3531 return mono_event_get_object (domain, startklass, event);
3534 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3535 goto handle_parent;
3537 g_free (event_name);
3538 return NULL;
3541 static MonoArray*
3542 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3544 MonoDomain *domain;
3545 static MonoClass *System_Reflection_EventInfo;
3546 MonoClass *startklass, *klass;
3547 MonoArray *res;
3548 MonoMethod *method;
3549 MonoEvent *event;
3550 int i, len, match;
3551 gpointer iter;
3553 MONO_ARCH_SAVE_REGS;
3555 if (!System_Reflection_EventInfo)
3556 System_Reflection_EventInfo = mono_class_from_name (
3557 mono_defaults.corlib, "System.Reflection", "EventInfo");
3559 domain = mono_object_domain (type);
3560 if (type->type->byref)
3561 return mono_array_new (domain, System_Reflection_EventInfo, 0);
3562 klass = startklass = mono_class_from_mono_type (type->type);
3564 i = 0;
3565 len = 2;
3566 res = mono_array_new (domain, System_Reflection_EventInfo, len);
3567 handle_parent:
3568 iter = NULL;
3569 while ((event = mono_class_get_events (klass, &iter))) {
3570 match = 0;
3571 method = event->add;
3572 if (!method)
3573 method = event->remove;
3574 if (!method)
3575 method = event->raise;
3576 if (method) {
3577 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3578 if (bflags & BFLAGS_Public)
3579 match++;
3580 } else {
3581 if (bflags & BFLAGS_NonPublic)
3582 match++;
3585 else
3586 if (bflags & BFLAGS_NonPublic)
3587 match ++;
3588 if (!match)
3589 continue;
3590 match = 0;
3591 if (method) {
3592 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3593 if (bflags & BFLAGS_Static)
3594 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3595 match++;
3596 } else {
3597 if (bflags & BFLAGS_Instance)
3598 match++;
3601 else
3602 if (bflags & BFLAGS_Instance)
3603 match ++;
3604 if (!match)
3605 continue;
3606 match = 0;
3607 if (i >= len) {
3608 MonoArray *new_res = mono_array_new (domain, System_Reflection_EventInfo, len * 2);
3609 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3610 len *= 2;
3611 res = new_res;
3613 mono_array_setref (res, i, mono_event_get_object (domain, startklass, event));
3614 ++i;
3616 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3617 goto handle_parent;
3618 if (i != len) {
3619 MonoArray *new_res = mono_array_new (domain, System_Reflection_EventInfo, i);
3620 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3621 res = new_res;
3623 * Better solution for the new GC.
3624 * res->max_length = i;
3627 return res;
3630 static MonoReflectionType *
3631 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3633 MonoDomain *domain;
3634 MonoClass *klass;
3635 MonoClass *nested;
3636 GList *tmpn;
3637 char *str;
3639 MONO_ARCH_SAVE_REGS;
3641 domain = ((MonoObject *)type)->vtable->domain;
3642 if (type->type->byref)
3643 return NULL;
3644 klass = mono_class_from_mono_type (type->type);
3645 str = mono_string_to_utf8 (name);
3647 handle_parent:
3649 * If a nested type is generic, return its generic type definition.
3650 * Note that this means that the return value is essentially a
3651 * nested type of the generic type definition of @klass.
3653 * A note in MSDN claims that a generic type definition can have
3654 * nested types that aren't generic. In any case, the container of that
3655 * nested type would be the generic type definition.
3657 if (klass->generic_class)
3658 klass = klass->generic_class->container_class;
3660 for (tmpn = klass->nested_classes; tmpn; tmpn = tmpn->next) {
3661 int match = 0;
3662 nested = tmpn->data;
3663 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3664 if (bflags & BFLAGS_Public)
3665 match++;
3666 } else {
3667 if (bflags & BFLAGS_NonPublic)
3668 match++;
3670 if (!match)
3671 continue;
3672 if (strcmp (nested->name, str) == 0){
3673 g_free (str);
3674 return mono_type_get_object (domain, &nested->byval_arg);
3677 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3678 goto handle_parent;
3679 g_free (str);
3680 return NULL;
3683 static MonoArray*
3684 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
3686 MonoDomain *domain;
3687 GList *tmpn;
3688 MonoClass *klass;
3689 MonoArray *res;
3690 MonoObject *member;
3691 int i, len, match;
3692 MonoClass *nested;
3694 MONO_ARCH_SAVE_REGS;
3696 domain = ((MonoObject *)type)->vtable->domain;
3697 if (type->type->byref)
3698 return mono_array_new (domain, mono_defaults.monotype_class, 0);
3699 klass = mono_class_from_mono_type (type->type);
3702 * If a nested type is generic, return its generic type definition.
3703 * Note that this means that the return value is essentially the set
3704 * of nested types of the generic type definition of @klass.
3706 * A note in MSDN claims that a generic type definition can have
3707 * nested types that aren't generic. In any case, the container of that
3708 * nested type would be the generic type definition.
3710 if (klass->generic_class)
3711 klass = klass->generic_class->container_class;
3713 i = 0;
3714 len = 1;
3715 res = mono_array_new (domain, mono_defaults.monotype_class, len);
3716 for (tmpn = klass->nested_classes; tmpn; tmpn = tmpn->next) {
3717 match = 0;
3718 nested = tmpn->data;
3719 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3720 if (bflags & BFLAGS_Public)
3721 match++;
3722 } else {
3723 if (bflags & BFLAGS_NonPublic)
3724 match++;
3726 if (!match)
3727 continue;
3728 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
3729 if (i >= len) {
3730 MonoArray *new_res = mono_array_new (domain, mono_defaults.monotype_class, len * 2);
3731 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3732 len *= 2;
3733 res = new_res;
3735 mono_array_setref (res, i, member);
3736 ++i;
3738 if (i != len) {
3739 MonoArray *new_res = mono_array_new (domain, mono_defaults.monotype_class, i);
3740 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3741 res = new_res;
3743 * Better solution for the new GC.
3744 * res->max_length = i;
3747 return res;
3750 static MonoReflectionType*
3751 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
3753 gchar *str;
3754 MonoType *type = NULL;
3755 MonoTypeNameParse info;
3756 gboolean type_resolve;
3758 MONO_ARCH_SAVE_REGS;
3760 /* On MS.NET, this does not fire a TypeResolve event */
3761 type_resolve = TRUE;
3762 str = mono_string_to_utf8 (name);
3763 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
3764 if (!mono_reflection_parse_type (str, &info)) {
3765 g_free (str);
3766 g_list_free (info.modifiers);
3767 g_list_free (info.nested);
3768 if (throwOnError) /* uhm: this is a parse error, though... */
3769 mono_raise_exception (mono_get_exception_type_load (name, NULL));
3770 /*g_print ("failed parse\n");*/
3771 return NULL;
3774 if (module != NULL) {
3775 if (module->image)
3776 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
3777 else
3778 type = NULL;
3780 else
3781 if (assembly->assembly->dynamic) {
3782 /* Enumerate all modules */
3783 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
3784 int i;
3786 type = NULL;
3787 if (abuilder->modules) {
3788 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
3789 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
3790 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
3791 if (type)
3792 break;
3796 if (!type && abuilder->loaded_modules) {
3797 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
3798 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
3799 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
3800 if (type)
3801 break;
3805 else
3806 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
3807 g_free (str);
3808 g_list_free (info.modifiers);
3809 g_list_free (info.nested);
3810 if (!type) {
3811 MonoException *e = NULL;
3813 if (throwOnError)
3814 e = mono_get_exception_type_load (name, NULL);
3816 mono_loader_clear_error ();
3818 if (e != NULL)
3819 mono_raise_exception (e);
3821 return NULL;
3824 if (type->type == MONO_TYPE_CLASS) {
3825 MonoClass *klass = mono_type_get_class (type);
3826 /* need to report exceptions ? */
3827 if (throwOnError && klass->exception_type) {
3828 /* report SecurityException (or others) that occured when loading the assembly */
3829 MonoException *exc = mono_class_get_exception_for_failure (klass);
3830 mono_loader_clear_error ();
3831 mono_raise_exception (exc);
3832 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
3833 return NULL;
3837 /* g_print ("got it\n"); */
3838 return mono_type_get_object (mono_object_domain (assembly), type);
3841 static MonoString *
3842 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
3844 MonoDomain *domain = mono_object_domain (assembly);
3845 MonoAssembly *mass = assembly->assembly;
3846 MonoString *res = NULL;
3847 gchar *uri;
3848 gchar *absolute;
3850 MONO_ARCH_SAVE_REGS;
3852 if (g_path_is_absolute (mass->image->name))
3853 absolute = g_strdup (mass->image->name);
3854 else
3855 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
3856 #if PLATFORM_WIN32
3858 gint i;
3859 for (i = strlen (absolute) - 1; i >= 0; i--)
3860 if (absolute [i] == '\\')
3861 absolute [i] = '/';
3863 #endif
3864 if (escaped) {
3865 uri = g_filename_to_uri (absolute, NULL, NULL);
3866 } else {
3867 uri = g_strconcat ("file://", absolute, NULL);
3870 if (uri) {
3871 res = mono_string_new (domain, uri);
3872 g_free (uri);
3874 g_free (absolute);
3875 return res;
3878 static MonoBoolean
3879 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
3881 MonoAssembly *mass = assembly->assembly;
3883 MONO_ARCH_SAVE_REGS;
3885 return mass->in_gac;
3888 static MonoReflectionAssembly*
3889 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
3891 gchar *name;
3892 MonoAssembly *res;
3893 MonoImageOpenStatus status;
3895 MONO_ARCH_SAVE_REGS;
3897 name = mono_string_to_utf8 (mname);
3898 res = mono_assembly_load_with_partial_name (name, &status);
3900 g_free (name);
3902 if (res == NULL)
3903 return NULL;
3904 return mono_assembly_get_object (mono_domain_get (), res);
3907 static MonoString *
3908 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
3910 MonoDomain *domain = mono_object_domain (assembly);
3911 MonoString *res;
3913 MONO_ARCH_SAVE_REGS;
3915 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
3917 return res;
3920 static MonoBoolean
3921 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
3923 MONO_ARCH_SAVE_REGS;
3925 return assembly->assembly->ref_only;
3928 static MonoString *
3929 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
3931 MonoDomain *domain = mono_object_domain (assembly);
3933 MONO_ARCH_SAVE_REGS;
3935 return mono_string_new (domain, assembly->assembly->image->version);
3938 static MonoReflectionMethod*
3939 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
3941 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
3943 MONO_ARCH_SAVE_REGS;
3945 if (!token)
3946 return NULL;
3947 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
3950 static MonoReflectionModule*
3951 ves_icall_System_Reflection_Assembly_get_ManifestModule (MonoReflectionAssembly *assembly)
3953 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
3956 static MonoArray*
3957 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
3959 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
3960 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
3961 int i;
3962 const char *val;
3964 MONO_ARCH_SAVE_REGS;
3966 for (i = 0; i < table->rows; ++i) {
3967 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
3968 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
3970 return result;
3973 static MonoObject*
3974 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
3976 static MonoClass *System_Version = NULL;
3977 static MonoMethod *create_version = NULL;
3978 MonoObject *result;
3979 gpointer args [4];
3981 if (!System_Version) {
3982 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
3983 g_assert (System_Version);
3986 if (!create_version) {
3987 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
3988 create_version = mono_method_desc_search_in_class (desc, System_Version);
3989 g_assert (create_version);
3990 mono_method_desc_free (desc);
3993 args [0] = &major;
3994 args [1] = &minor;
3995 args [2] = &build;
3996 args [3] = &revision;
3997 result = mono_object_new (domain, System_Version);
3998 mono_runtime_invoke (create_version, result, args, NULL);
4000 return result;
4003 static MonoArray*
4004 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4006 static MonoClass *System_Reflection_AssemblyName;
4007 MonoArray *result;
4008 MonoDomain *domain = mono_object_domain (assembly);
4009 int i, count = 0;
4010 static MonoMethod *create_culture = NULL;
4011 MonoImage *image = assembly->assembly->image;
4012 MonoTableInfo *t;
4014 MONO_ARCH_SAVE_REGS;
4016 if (!System_Reflection_AssemblyName)
4017 System_Reflection_AssemblyName = mono_class_from_name (
4018 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4020 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4021 count = t->rows;
4023 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4025 if (count > 0) {
4026 MonoMethodDesc *desc = mono_method_desc_new (
4027 "System.Globalization.CultureInfo:CreateSpecificCulture(string)", TRUE);
4028 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4029 g_assert (create_culture);
4030 mono_method_desc_free (desc);
4033 for (i = 0; i < count; i++) {
4034 MonoReflectionAssemblyName *aname;
4035 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4037 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4039 aname = (MonoReflectionAssemblyName *) mono_object_new (
4040 domain, System_Reflection_AssemblyName);
4042 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4044 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4045 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4046 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4047 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4048 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4049 aname->versioncompat = 1; /* SameMachine (default) */
4050 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4051 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4053 if (create_culture) {
4054 gpointer args [1];
4055 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4056 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4059 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4060 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4061 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4063 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4064 /* public key token isn't copied - the class library will
4065 automatically generate it from the public key if required */
4066 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4067 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4068 } else {
4069 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4070 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4074 /* note: this function doesn't return the codebase on purpose (i.e. it can
4075 be used under partial trust as path information isn't present). */
4077 mono_array_setref (result, i, aname);
4079 return result;
4082 typedef struct {
4083 MonoArray *res;
4084 int idx;
4085 } NameSpaceInfo;
4087 static void
4088 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4090 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4092 mono_array_setref (info->res, info->idx, name);
4093 info->idx++;
4096 static MonoArray*
4097 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4099 MonoImage *img = assembly->assembly->image;
4100 MonoArray *res;
4101 NameSpaceInfo info;
4103 MONO_ARCH_SAVE_REGS;
4105 if (!img->name_cache)
4106 mono_image_init_name_cache (img);
4108 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, g_hash_table_size (img->name_cache));
4109 info.res = res;
4110 info.idx = 0;
4111 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4113 return res;
4116 /* move this in some file in mono/util/ */
4117 static char *
4118 g_concat_dir_and_file (const char *dir, const char *file)
4120 g_return_val_if_fail (dir != NULL, NULL);
4121 g_return_val_if_fail (file != NULL, NULL);
4124 * If the directory name doesn't have a / on the end, we need
4125 * to add one so we get a proper path to the file
4127 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4128 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4129 else
4130 return g_strconcat (dir, file, NULL);
4133 static void *
4134 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4136 char *n = mono_string_to_utf8 (name);
4137 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4138 guint32 i;
4139 guint32 cols [MONO_MANIFEST_SIZE];
4140 guint32 impl, file_idx;
4141 const char *val;
4142 MonoImage *module;
4144 MONO_ARCH_SAVE_REGS;
4146 for (i = 0; i < table->rows; ++i) {
4147 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4148 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4149 if (strcmp (val, n) == 0)
4150 break;
4152 g_free (n);
4153 if (i == table->rows)
4154 return NULL;
4155 /* FIXME */
4156 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4157 if (impl) {
4159 * this code should only be called after obtaining the
4160 * ResourceInfo and handling the other cases.
4162 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4163 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4165 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4166 if (!module)
4167 return NULL;
4169 else
4170 module = assembly->assembly->image;
4172 *ref_module = mono_module_get_object (mono_domain_get (), module);
4174 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4177 static gboolean
4178 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4180 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4181 int i;
4182 guint32 cols [MONO_MANIFEST_SIZE];
4183 guint32 file_cols [MONO_FILE_SIZE];
4184 const char *val;
4185 char *n;
4187 MONO_ARCH_SAVE_REGS;
4189 n = mono_string_to_utf8 (name);
4190 for (i = 0; i < table->rows; ++i) {
4191 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4192 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4193 if (strcmp (val, n) == 0)
4194 break;
4196 g_free (n);
4197 if (i == table->rows)
4198 return FALSE;
4200 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4201 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4203 else {
4204 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4205 case MONO_IMPLEMENTATION_FILE:
4206 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4207 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4208 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4209 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4210 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4211 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4212 info->location = 0;
4213 else
4214 info->location = RESOURCE_LOCATION_EMBEDDED;
4215 break;
4217 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4218 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4219 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4220 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4221 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4222 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4223 g_free (msg);
4224 mono_raise_exception (ex);
4226 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4228 /* Obtain info recursively */
4229 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4230 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4231 break;
4233 case MONO_IMPLEMENTATION_EXP_TYPE:
4234 g_assert_not_reached ();
4235 break;
4239 return TRUE;
4242 static MonoObject*
4243 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4245 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4246 MonoArray *result = NULL;
4247 int i, count;
4248 const char *val;
4249 char *n;
4251 MONO_ARCH_SAVE_REGS;
4253 /* check hash if needed */
4254 if (name) {
4255 n = mono_string_to_utf8 (name);
4256 for (i = 0; i < table->rows; ++i) {
4257 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4258 if (strcmp (val, n) == 0) {
4259 MonoString *fn;
4260 g_free (n);
4261 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4262 fn = mono_string_new (mono_object_domain (assembly), n);
4263 g_free (n);
4264 return (MonoObject*)fn;
4267 g_free (n);
4268 return NULL;
4271 count = 0;
4272 for (i = 0; i < table->rows; ++i) {
4273 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4274 count ++;
4277 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4279 count = 0;
4280 for (i = 0; i < table->rows; ++i) {
4281 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4282 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4283 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4284 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4285 g_free (n);
4286 count ++;
4289 return (MonoObject*)result;
4292 static MonoArray*
4293 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4295 MonoDomain *domain = mono_domain_get();
4296 MonoArray *res;
4297 MonoClass *klass;
4298 int i, j, file_count = 0;
4299 MonoImage **modules;
4300 guint32 module_count, real_module_count;
4301 MonoTableInfo *table;
4303 g_assert (assembly->assembly->image != NULL);
4305 if (assembly->assembly->dynamic) {
4306 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)assembly;
4308 if (assemblyb->modules)
4309 module_count = mono_array_length (assemblyb->modules);
4310 else
4311 module_count = 0;
4312 real_module_count = module_count;
4314 modules = g_new0 (MonoImage*, module_count);
4315 if (assemblyb->modules) {
4316 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4317 modules [i] =
4318 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i)->module.image;
4322 else {
4323 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4324 file_count = table->rows;
4326 modules = assembly->assembly->image->modules;
4327 module_count = assembly->assembly->image->module_count;
4329 real_module_count = 0;
4330 for (i = 0; i < module_count; ++i)
4331 if (modules [i])
4332 real_module_count ++;
4335 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4336 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4338 mono_array_setref (res, 0, mono_module_get_object (domain, assembly->assembly->image));
4339 j = 1;
4340 for (i = 0; i < module_count; ++i)
4341 if (modules [i]) {
4342 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4343 ++j;
4346 for (i = 0; i < file_count; ++i, ++j)
4347 mono_array_setref (res, j, mono_module_file_get_object (domain, assembly->assembly->image, i));
4349 if (assembly->assembly->dynamic)
4350 g_free (modules);
4352 return res;
4355 static MonoReflectionMethod*
4356 ves_icall_GetCurrentMethod (void)
4358 MonoMethod *m = mono_method_get_last_managed ();
4360 MONO_ARCH_SAVE_REGS;
4362 return mono_method_get_object (mono_domain_get (), m, NULL);
4365 static MonoReflectionMethod*
4366 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4368 return mono_method_get_object (mono_domain_get (), method, NULL);
4371 static MonoReflectionMethodBody*
4372 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4374 return mono_method_body_get_object (mono_domain_get (), method);
4377 static MonoReflectionAssembly*
4378 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4380 MonoMethod *m = mono_method_get_last_managed ();
4382 MONO_ARCH_SAVE_REGS;
4384 return mono_assembly_get_object (mono_domain_get (), m->klass->image->assembly);
4388 static MonoReflectionAssembly*
4389 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4391 MonoDomain* domain = mono_domain_get ();
4393 MONO_ARCH_SAVE_REGS;
4395 if (!domain->entry_assembly)
4396 return NULL;
4398 return mono_assembly_get_object (domain, domain->entry_assembly);
4401 static MonoReflectionAssembly*
4402 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4404 MonoMethod *m = mono_method_get_last_managed ();
4405 MonoMethod *dest = m;
4407 MONO_ARCH_SAVE_REGS;
4409 mono_stack_walk_no_il (get_caller, &dest);
4410 if (!dest)
4411 dest = m;
4412 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4415 static MonoString *
4416 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4417 gboolean assembly_qualified)
4419 MonoDomain *domain = mono_object_domain (object);
4420 MonoTypeNameFormat format;
4421 MonoString *res;
4422 gchar *name;
4424 MONO_ARCH_SAVE_REGS;
4425 if (full_name)
4426 format = assembly_qualified ?
4427 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4428 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4429 else
4430 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4432 name = mono_type_get_name_full (object->type, format);
4433 if (!name)
4434 return NULL;
4436 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR))
4437 return NULL;
4439 res = mono_string_new (domain, name);
4440 g_free (name);
4442 return res;
4445 static void
4446 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version)
4448 static MonoMethod *create_culture = NULL;
4449 gpointer args [1];
4450 guint32 pkey_len;
4451 const char *pkey_ptr;
4452 gchar *codebase;
4454 MONO_ARCH_SAVE_REGS;
4456 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4457 aname->major = name->major;
4458 aname->minor = name->minor;
4459 aname->build = name->build;
4460 aname->revision = name->revision;
4461 aname->hashalg = name->hash_alg;
4462 if (by_default_version)
4463 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4465 codebase = g_filename_to_uri (absolute, NULL, NULL);
4466 if (codebase) {
4467 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4468 g_free (codebase);
4471 if (!create_culture) {
4472 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateSpecificCulture(string)", TRUE);
4473 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4474 g_assert (create_culture);
4475 mono_method_desc_free (desc);
4478 if (name->culture) {
4479 args [0] = mono_string_new (domain, name->culture);
4480 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4483 if (name->public_key) {
4484 pkey_ptr = (char*)name->public_key;
4485 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4487 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4488 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4491 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4492 if (name->public_key_token [0]) {
4493 int i, j;
4494 char *p;
4496 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4497 p = mono_array_addr (aname->keyToken, char, 0);
4499 for (i = 0, j = 0; i < 8; i++) {
4500 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4501 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4502 p++;
4507 static void
4508 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
4510 gchar *absolute;
4511 MonoAssembly *mass = assembly->assembly;
4513 MONO_ARCH_SAVE_REGS;
4515 if (g_path_is_absolute (mass->image->name)) {
4516 fill_reflection_assembly_name (mono_object_domain (assembly),
4517 aname, &mass->aname, mass->image->name, TRUE);
4518 return;
4520 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4522 fill_reflection_assembly_name (mono_object_domain (assembly),
4523 aname, &mass->aname, absolute, TRUE);
4525 g_free (absolute);
4528 static void
4529 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
4531 char *filename;
4532 MonoImageOpenStatus status = MONO_IMAGE_OK;
4533 gboolean res;
4534 MonoImage *image;
4535 MonoAssemblyName name;
4537 MONO_ARCH_SAVE_REGS;
4539 filename = mono_string_to_utf8 (fname);
4541 image = mono_image_open (filename, &status);
4543 if (!image){
4544 MonoException *exc;
4546 g_free (filename);
4547 if (status == MONO_IMAGE_IMAGE_INVALID)
4548 exc = mono_get_exception_bad_image_format2 (NULL, fname);
4549 else
4550 exc = mono_get_exception_file_not_found2 (NULL, fname);
4551 mono_raise_exception (exc);
4554 res = mono_assembly_fill_assembly_name (image, &name);
4555 if (!res) {
4556 mono_image_close (image);
4557 g_free (filename);
4558 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
4561 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE);
4563 g_free (filename);
4564 mono_image_close (image);
4567 static MonoBoolean
4568 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
4569 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
4571 MonoBoolean result = FALSE;
4572 MonoDeclSecurityEntry entry;
4574 /* SecurityAction.RequestMinimum */
4575 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
4576 *minimum = entry.blob;
4577 *minLength = entry.size;
4578 result = TRUE;
4580 /* SecurityAction.RequestOptional */
4581 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
4582 *optional = entry.blob;
4583 *optLength = entry.size;
4584 result = TRUE;
4586 /* SecurityAction.RequestRefuse */
4587 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
4588 *refused = entry.blob;
4589 *refLength = entry.size;
4590 result = TRUE;
4593 return result;
4596 static MonoArray*
4597 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoBoolean exportedOnly)
4599 MonoArray *res;
4600 MonoClass *klass;
4601 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
4602 int i, count;
4603 guint32 attrs, visibility;
4605 /* we start the count from 1 because we skip the special type <Module> */
4606 if (exportedOnly) {
4607 count = 0;
4608 for (i = 1; i < tdef->rows; ++i) {
4609 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
4610 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4611 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
4612 count++;
4614 } else {
4615 count = tdef->rows - 1;
4617 res = mono_array_new (domain, mono_defaults.monotype_class, count);
4618 count = 0;
4619 for (i = 1; i < tdef->rows; ++i) {
4620 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
4621 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4622 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
4623 klass = mono_class_get_throw (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
4624 if (mono_loader_get_last_error ())
4625 mono_loader_clear_error ();
4626 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
4627 count++;
4631 return res;
4634 static MonoArray*
4635 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
4637 MonoArray *res = NULL;
4638 MonoImage *image = NULL;
4639 MonoTableInfo *table = NULL;
4640 MonoDomain *domain;
4641 GList *list = NULL;
4642 int i, len;
4644 MONO_ARCH_SAVE_REGS;
4646 domain = mono_object_domain (assembly);
4648 if (assembly->assembly->dynamic) {
4649 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4650 if (abuilder->modules) {
4651 for (i = 0; i < mono_array_length(abuilder->modules); i++) {
4652 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4653 MonoArray *append = mb->types;
4654 /* The types array might not be fully filled up */
4655 if (append && mb->num_types > 0) {
4656 guint32 len1, len2;
4657 MonoArray *new;
4658 len1 = res ? mono_array_length (res) : 0;
4659 len2 = mb->num_types;
4660 new = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
4661 if (res)
4662 mono_array_memcpy_refs (new, 0, res, 0, len1);
4663 mono_array_memcpy_refs (new, len1, append, 0, len2);
4664 res = new;
4669 * Replace TypeBuilders with the created types to be compatible
4670 * with MS.NET.
4672 if (res) {
4673 for (i = 0; i < mono_array_length (res); ++i) {
4674 MonoReflectionTypeBuilder *tb = mono_array_get (res, MonoReflectionTypeBuilder*, i);
4675 if (tb->created)
4676 mono_array_setref (res, i, tb->created);
4681 if (abuilder->loaded_modules)
4682 for (i = 0; i < mono_array_length(abuilder->loaded_modules); i++) {
4683 MonoReflectionModule *rm = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4684 MonoArray *append = mono_module_get_types (domain, rm->image, exportedOnly);
4685 if (append && mono_array_length (append) > 0) {
4686 guint32 len1, len2;
4687 MonoArray *new;
4688 len1 = res ? mono_array_length (res) : 0;
4689 len2 = mono_array_length (append);
4690 new = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
4691 if (res)
4692 mono_array_memcpy_refs (new, 0, res, 0, len1);
4693 mono_array_memcpy_refs (new, len1, append, 0, len2);
4694 res = new;
4697 if (res)
4698 return res;
4699 else
4700 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4702 image = assembly->assembly->image;
4703 table = &image->tables [MONO_TABLE_FILE];
4704 res = mono_module_get_types (domain, image, exportedOnly);
4706 /* Append data from all modules in the assembly */
4707 for (i = 0; i < table->rows; ++i) {
4708 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4709 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
4710 if (loaded_image) {
4711 MonoArray *res2 = mono_module_get_types (domain, loaded_image, exportedOnly);
4712 /* Append the new types to the end of the array */
4713 if (mono_array_length (res2) > 0) {
4714 guint32 len1, len2;
4715 MonoArray *res3;
4717 len1 = mono_array_length (res);
4718 len2 = mono_array_length (res2);
4719 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
4720 mono_array_memcpy_refs (res3, 0, res, 0, len1);
4721 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
4722 res = res3;
4728 /* the ReflectionTypeLoadException must have all the types (Types property),
4729 * NULL replacing types which throws an exception. The LoaderException must
4730 * contain all exceptions for NULL items.
4733 len = mono_array_length (res);
4735 for (i = 0; i < len; i++) {
4736 MonoReflectionType *t = mono_array_get (res, gpointer, i);
4737 MonoClass *klass = mono_type_get_class (t->type);
4738 if ((klass != NULL) && klass->exception_type) {
4739 /* keep the class in the list */
4740 list = g_list_append (list, klass);
4741 /* and replace Type with NULL */
4742 mono_array_setref (res, i, NULL);
4746 if (list) {
4747 GList *tmp = NULL;
4748 MonoException *exc = NULL;
4749 MonoArray *exl = NULL;
4750 int length = g_list_length (list);
4752 mono_loader_clear_error ();
4754 exl = mono_array_new (domain, mono_defaults.exception_class, length);
4755 for (i = 0, tmp = list; i < length; i++, tmp = tmp->next) {
4756 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
4757 mono_array_setref (exl, i, exc);
4759 g_list_free (list);
4760 list = NULL;
4762 exc = mono_get_exception_reflection_type_load (res, exl);
4763 mono_loader_clear_error ();
4764 mono_raise_exception (exc);
4767 return res;
4770 static gboolean
4771 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
4773 MonoAssemblyName aname;
4774 MonoDomain *domain = mono_object_domain (name);
4775 char *val;
4776 gboolean is_version_defined;
4778 val = mono_string_to_utf8 (assname);
4779 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined))
4780 return FALSE;
4782 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined);
4784 mono_assembly_name_free (&aname);
4785 g_free ((guint8*) aname.public_key);
4786 g_free (val);
4788 return TRUE;
4791 static MonoReflectionType*
4792 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
4794 MonoDomain *domain = mono_object_domain (module);
4795 MonoClass *klass;
4797 MONO_ARCH_SAVE_REGS;
4799 g_assert (module->image);
4801 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
4802 /* These images do not have a global type */
4803 return NULL;
4805 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
4806 return mono_type_get_object (domain, &klass->byval_arg);
4809 static void
4810 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
4812 /*if (module->image)
4813 mono_image_close (module->image);*/
4816 static MonoString*
4817 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
4819 MonoDomain *domain = mono_object_domain (module);
4821 MONO_ARCH_SAVE_REGS;
4823 g_assert (module->image);
4824 return mono_string_new (domain, module->image->guid);
4827 static void
4828 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
4830 if (image->dynamic) {
4831 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
4832 *pe_kind = dyn->pe_kind;
4833 *machine = dyn->machine;
4835 else {
4836 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
4837 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
4841 static gint32
4842 ves_icall_System_Reflection_Module_get_MDStreamVersion (MonoReflectionModule *module)
4844 MonoImage *image = module->image;
4846 if (!image)
4847 mono_raise_exception (mono_get_exception_not_supported (""));
4849 return (image->md_version_major << 16) | (image->md_version_minor);
4852 static MonoArray*
4853 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
4855 MONO_ARCH_SAVE_REGS;
4857 if (!module->image)
4858 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
4859 else
4860 return mono_module_get_types (mono_object_domain (module), module->image, FALSE);
4863 static gboolean
4864 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
4866 guint32 cols [MONO_MEMBERREF_SIZE];
4867 const char *sig;
4868 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
4869 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
4870 mono_metadata_decode_blob_size (sig, &sig);
4871 return (*sig != 0x6);
4874 static MonoType*
4875 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
4877 MonoClass *klass;
4878 int table = mono_metadata_token_table (token);
4879 int index = mono_metadata_token_index (token);
4881 *error = ResolveTokenError_Other;
4883 /* Validate token */
4884 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
4885 (table != MONO_TABLE_TYPESPEC)) {
4886 *error = ResolveTokenError_BadTable;
4887 return NULL;
4890 if (image->dynamic)
4891 return mono_lookup_dynamic_token (image, token);
4893 if ((index <= 0) || (index > image->tables [table].rows)) {
4894 *error = ResolveTokenError_OutOfRange;
4895 return NULL;
4898 klass = mono_class_get (image, token);
4899 if (klass)
4900 return &klass->byval_arg;
4901 else
4902 return NULL;
4905 static MonoMethod*
4906 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
4908 int table = mono_metadata_token_table (token);
4909 int index = mono_metadata_token_index (token);
4911 *error = ResolveTokenError_Other;
4913 /* Validate token */
4914 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
4915 (table != MONO_TABLE_MEMBERREF)) {
4916 *error = ResolveTokenError_BadTable;
4917 return NULL;
4920 if (image->dynamic)
4921 /* FIXME: validate memberref token type */
4922 return mono_lookup_dynamic_token (image, token);
4924 if ((index <= 0) || (index > image->tables [table].rows)) {
4925 *error = ResolveTokenError_OutOfRange;
4926 return NULL;
4928 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
4929 *error = ResolveTokenError_BadTable;
4930 return NULL;
4933 return mono_get_method (image, token, NULL);
4936 static MonoString*
4937 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
4939 int index = mono_metadata_token_index (token);
4941 *error = ResolveTokenError_Other;
4943 /* Validate token */
4944 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
4945 *error = ResolveTokenError_BadTable;
4946 return NULL;
4949 if (image->dynamic)
4950 return mono_lookup_dynamic_token (image, token);
4952 if ((index <= 0) || (index >= image->heap_us.size)) {
4953 *error = ResolveTokenError_OutOfRange;
4954 return NULL;
4957 /* FIXME: What to do if the index points into the middle of a string ? */
4959 return mono_ldstr (mono_domain_get (), image, index);
4962 static MonoClassField*
4963 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
4965 MonoClass *klass;
4966 int table = mono_metadata_token_table (token);
4967 int index = mono_metadata_token_index (token);
4969 *error = ResolveTokenError_Other;
4971 /* Validate token */
4972 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
4973 *error = ResolveTokenError_BadTable;
4974 return NULL;
4977 if (image->dynamic)
4978 /* FIXME: validate memberref token type */
4979 return mono_lookup_dynamic_token (image, token);
4981 if ((index <= 0) || (index > image->tables [table].rows)) {
4982 *error = ResolveTokenError_OutOfRange;
4983 return NULL;
4985 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
4986 *error = ResolveTokenError_BadTable;
4987 return NULL;
4990 return mono_field_from_token (image, token, &klass, NULL);
4994 static MonoObject*
4995 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
4997 int table = mono_metadata_token_table (token);
4999 *error = ResolveTokenError_Other;
5001 switch (table) {
5002 case MONO_TABLE_TYPEDEF:
5003 case MONO_TABLE_TYPEREF:
5004 case MONO_TABLE_TYPESPEC: {
5005 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, error);
5006 if (t)
5007 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5008 else
5009 return NULL;
5011 case MONO_TABLE_METHOD:
5012 case MONO_TABLE_METHODSPEC: {
5013 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, error);
5014 if (m)
5015 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5016 else
5017 return NULL;
5019 case MONO_TABLE_FIELD: {
5020 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, error);
5021 if (f)
5022 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5023 else
5024 return NULL;
5026 case MONO_TABLE_MEMBERREF:
5027 if (mono_metadata_memberref_is_method (image, token)) {
5028 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, error);
5029 if (m)
5030 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5031 else
5032 return NULL;
5034 else {
5035 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, error);
5036 if (f)
5037 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5038 else
5039 return NULL;
5041 break;
5043 default:
5044 *error = ResolveTokenError_BadTable;
5047 return NULL;
5050 static MonoReflectionType*
5051 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5053 MonoClass *klass;
5054 int isbyref = 0, rank;
5055 char *str = mono_string_to_utf8 (smodifiers);
5056 char *p;
5058 MONO_ARCH_SAVE_REGS;
5060 klass = mono_class_from_mono_type (tb->type.type);
5061 p = str;
5062 /* logic taken from mono_reflection_parse_type(): keep in sync */
5063 while (*p) {
5064 switch (*p) {
5065 case '&':
5066 if (isbyref) { /* only one level allowed by the spec */
5067 g_free (str);
5068 return NULL;
5070 isbyref = 1;
5071 p++;
5072 g_free (str);
5073 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5074 break;
5075 case '*':
5076 klass = mono_ptr_class_get (&klass->byval_arg);
5077 mono_class_init (klass);
5078 p++;
5079 break;
5080 case '[':
5081 rank = 1;
5082 p++;
5083 while (*p) {
5084 if (*p == ']')
5085 break;
5086 if (*p == ',')
5087 rank++;
5088 else if (*p != '*') { /* '*' means unknown lower bound */
5089 g_free (str);
5090 return NULL;
5092 ++p;
5094 if (*p != ']') {
5095 g_free (str);
5096 return NULL;
5098 p++;
5099 klass = mono_array_class_get (klass, rank);
5100 mono_class_init (klass);
5101 break;
5102 default:
5103 break;
5106 g_free (str);
5107 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5110 static MonoBoolean
5111 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5113 MonoType *type;
5114 MonoBoolean res;
5116 MONO_ARCH_SAVE_REGS;
5118 type = t->type;
5119 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5121 return res;
5124 static MonoReflectionType *
5125 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5127 MonoClass *klass, *aklass;
5129 MONO_ARCH_SAVE_REGS;
5131 klass = mono_class_from_mono_type (type->type);
5132 aklass = mono_array_class_get (klass, rank);
5134 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5137 static MonoReflectionType *
5138 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5140 MonoClass *klass;
5142 MONO_ARCH_SAVE_REGS;
5144 klass = mono_class_from_mono_type (type->type);
5146 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5149 static MonoReflectionType *
5150 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5152 MonoClass *pklass;
5154 MONO_ARCH_SAVE_REGS;
5156 pklass = mono_ptr_class_get (type->type);
5158 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5161 static MonoObject *
5162 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5163 MonoReflectionMethod *info)
5165 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5166 MonoObject *delegate;
5167 gpointer func;
5169 MONO_ARCH_SAVE_REGS;
5171 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5173 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5175 func = mono_compile_method (info->method);
5177 mono_delegate_ctor (delegate, target, func);
5179 return delegate;
5183 * Magic number to convert a time which is relative to
5184 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5186 #define EPOCH_ADJUST ((guint64)62135596800LL)
5189 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5191 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5194 * This returns Now in UTC
5196 static gint64
5197 ves_icall_System_DateTime_GetNow (void)
5199 #ifdef PLATFORM_WIN32
5200 SYSTEMTIME st;
5201 FILETIME ft;
5203 GetSystemTime (&st);
5204 SystemTimeToFileTime (&st, &ft);
5205 return (gint64) FILETIME_ADJUST + ((((gint64)ft.dwHighDateTime)<<32) | ft.dwLowDateTime);
5206 #else
5207 /* FIXME: put this in io-layer and call it GetLocalTime */
5208 struct timeval tv;
5209 gint64 res;
5211 MONO_ARCH_SAVE_REGS;
5213 if (gettimeofday (&tv, NULL) == 0) {
5214 res = (((gint64)tv.tv_sec + EPOCH_ADJUST)* 1000000 + tv.tv_usec)*10;
5215 return res;
5217 /* fixme: raise exception */
5218 return 0;
5219 #endif
5222 #ifdef PLATFORM_WIN32
5223 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5224 static void
5225 convert_to_absolute_date(SYSTEMTIME *date)
5227 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5228 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5229 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5230 /* from the calendar FAQ */
5231 int a = (14 - date->wMonth) / 12;
5232 int y = date->wYear - a;
5233 int m = date->wMonth + 12 * a - 2;
5234 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5236 /* d is now the day of the week for the first of the month (0 == Sunday) */
5238 int day_of_week = date->wDayOfWeek;
5240 /* set day_in_month to the first day in the month which falls on day_of_week */
5241 int day_in_month = 1 + (day_of_week - d);
5242 if (day_in_month <= 0)
5243 day_in_month += 7;
5245 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5246 date->wDay = day_in_month + (date->wDay - 1) * 7;
5247 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5248 date->wDay -= 7;
5250 #endif
5252 #ifndef PLATFORM_WIN32
5254 * Return's the offset from GMT of a local time.
5256 * tm is a local time
5257 * t is the same local time as seconds.
5259 static int
5260 gmt_offset(struct tm *tm, time_t t)
5262 #if defined (HAVE_TM_GMTOFF)
5263 return tm->tm_gmtoff;
5264 #else
5265 struct tm g;
5266 time_t t2;
5267 g = *gmtime(&t);
5268 g.tm_isdst = tm->tm_isdst;
5269 t2 = mktime(&g);
5270 return (int)difftime(t, t2);
5271 #endif
5273 #endif
5275 * This is heavily based on zdump.c from glibc 2.2.
5277 * * data[0]: start of daylight saving time (in DateTime ticks).
5278 * * data[1]: end of daylight saving time (in DateTime ticks).
5279 * * data[2]: utcoffset (in TimeSpan ticks).
5280 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5281 * * name[0]: name of this timezone when not daylight saving.
5282 * * name[1]: name of this timezone when daylight saving.
5284 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5285 * the class library allows years between 1 and 9999.
5287 * Returns true on success and zero on failure.
5289 static guint32
5290 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5292 #ifndef PLATFORM_WIN32
5293 MonoDomain *domain = mono_domain_get ();
5294 struct tm start, tt;
5295 time_t t;
5297 long int gmtoff;
5298 int is_daylight = 0, day;
5299 char tzone [64];
5301 MONO_ARCH_SAVE_REGS;
5303 MONO_CHECK_ARG_NULL (data);
5304 MONO_CHECK_ARG_NULL (names);
5306 (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
5307 (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
5310 * no info is better than crashing: we'll need our own tz data
5311 * to make this work properly, anyway. The range is probably
5312 * reduced to 1970 .. 2037 because that is what mktime is
5313 * guaranteed to support (we get into an infinite loop
5314 * otherwise).
5317 memset (&start, 0, sizeof (start));
5319 start.tm_mday = 1;
5320 start.tm_year = year-1900;
5322 t = mktime (&start);
5324 if ((year < 1970) || (year > 2037) || (t == -1)) {
5325 t = time (NULL);
5326 tt = *localtime (&t);
5327 strftime (tzone, sizeof (tzone), "%Z", &tt);
5328 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5329 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5330 return 1;
5333 gmtoff = gmt_offset (&start, t);
5335 /* For each day of the year, calculate the tm_gmtoff. */
5336 for (day = 0; day < 365; day++) {
5338 t += 3600*24;
5339 tt = *localtime (&t);
5341 /* Daylight saving starts or ends here. */
5342 if (gmt_offset (&tt, t) != gmtoff) {
5343 struct tm tt1;
5344 time_t t1;
5346 /* Try to find the exact hour when daylight saving starts/ends. */
5347 t1 = t;
5348 do {
5349 t1 -= 3600;
5350 tt1 = *localtime (&t1);
5351 } while (gmt_offset (&tt1, t1) != gmtoff);
5353 /* Try to find the exact minute when daylight saving starts/ends. */
5354 do {
5355 t1 += 60;
5356 tt1 = *localtime (&t1);
5357 } while (gmt_offset (&tt1, t1) == gmtoff);
5358 t1+=gmtoff;
5359 strftime (tzone, sizeof (tzone), "%Z", &tt);
5361 /* Write data, if we're already in daylight saving, we're done. */
5362 if (is_daylight) {
5363 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5364 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5365 return 1;
5366 } else {
5367 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5368 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5369 is_daylight = 1;
5372 /* This is only set once when we enter daylight saving. */
5373 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
5374 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
5376 gmtoff = gmt_offset (&tt, t);
5380 if (!is_daylight) {
5381 strftime (tzone, sizeof (tzone), "%Z", &tt);
5382 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5383 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5384 mono_array_set ((*data), gint64, 0, 0);
5385 mono_array_set ((*data), gint64, 1, 0);
5386 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
5387 mono_array_set ((*data), gint64, 3, 0);
5390 return 1;
5391 #else
5392 MonoDomain *domain = mono_domain_get ();
5393 TIME_ZONE_INFORMATION tz_info;
5394 FILETIME ft;
5395 int i;
5396 int err, tz_id;
5398 tz_id = GetTimeZoneInformation (&tz_info);
5399 if (tz_id == TIME_ZONE_ID_INVALID)
5400 return 0;
5402 MONO_CHECK_ARG_NULL (data);
5403 MONO_CHECK_ARG_NULL (names);
5405 (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
5406 (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
5408 for (i = 0; i < 32; ++i)
5409 if (!tz_info.DaylightName [i])
5410 break;
5411 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
5412 for (i = 0; i < 32; ++i)
5413 if (!tz_info.StandardName [i])
5414 break;
5415 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
5417 if ((year <= 1601) || (year > 30827)) {
5419 * According to MSDN, the MS time functions can't handle dates outside
5420 * this interval.
5422 return 1;
5425 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
5426 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
5427 tz_info.StandardDate.wYear = year;
5428 convert_to_absolute_date(&tz_info.StandardDate);
5429 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
5430 g_assert(err);
5431 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
5432 tz_info.DaylightDate.wYear = year;
5433 convert_to_absolute_date(&tz_info.DaylightDate);
5434 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
5435 g_assert(err);
5436 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
5438 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
5439 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
5441 return 1;
5442 #endif
5445 static gpointer
5446 ves_icall_System_Object_obj_address (MonoObject *this)
5448 MONO_ARCH_SAVE_REGS;
5450 return this;
5453 /* System.Buffer */
5455 static inline gint32
5456 mono_array_get_byte_length (MonoArray *array)
5458 MonoClass *klass;
5459 int length;
5460 int i;
5462 klass = array->obj.vtable->klass;
5464 if (array->bounds == NULL)
5465 length = array->max_length;
5466 else {
5467 length = 1;
5468 for (i = 0; i < klass->rank; ++ i)
5469 length *= array->bounds [i].length;
5472 switch (klass->element_class->byval_arg.type) {
5473 case MONO_TYPE_I1:
5474 case MONO_TYPE_U1:
5475 case MONO_TYPE_BOOLEAN:
5476 return length;
5477 case MONO_TYPE_I2:
5478 case MONO_TYPE_U2:
5479 case MONO_TYPE_CHAR:
5480 return length << 1;
5481 case MONO_TYPE_I4:
5482 case MONO_TYPE_U4:
5483 case MONO_TYPE_R4:
5484 return length << 2;
5485 case MONO_TYPE_I:
5486 case MONO_TYPE_U:
5487 return length * sizeof (gpointer);
5488 case MONO_TYPE_I8:
5489 case MONO_TYPE_U8:
5490 case MONO_TYPE_R8:
5491 return length << 3;
5492 default:
5493 return -1;
5497 static gint32
5498 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
5500 MONO_ARCH_SAVE_REGS;
5502 return mono_array_get_byte_length (array);
5505 static gint8
5506 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
5508 MONO_ARCH_SAVE_REGS;
5510 return mono_array_get (array, gint8, idx);
5513 static void
5514 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
5516 MONO_ARCH_SAVE_REGS;
5518 mono_array_set (array, gint8, idx, value);
5521 static MonoBoolean
5522 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
5524 guint8 *src_buf, *dest_buf;
5526 MONO_ARCH_SAVE_REGS;
5528 /* watch out for integer overflow */
5529 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
5530 return FALSE;
5532 src_buf = (guint8 *)src->vector + src_offset;
5533 dest_buf = (guint8 *)dest->vector + dest_offset;
5535 if (src != dest)
5536 memcpy (dest_buf, src_buf, count);
5537 else
5538 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
5540 return TRUE;
5543 static MonoObject *
5544 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
5546 MonoDomain *domain = mono_object_domain (this);
5547 MonoObject *res;
5548 MonoRealProxy *rp = ((MonoRealProxy *)this);
5549 MonoTransparentProxy *tp;
5550 MonoType *type;
5551 MonoClass *klass;
5553 MONO_ARCH_SAVE_REGS;
5555 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
5556 tp = (MonoTransparentProxy*) res;
5558 MONO_OBJECT_SETREF (tp, rp, rp);
5559 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
5560 klass = mono_class_from_mono_type (type);
5562 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
5563 tp->remote_class = mono_remote_class (domain, class_name, klass);
5565 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
5566 return res;
5569 static MonoReflectionType *
5570 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
5572 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
5575 /* System.Environment */
5577 static MonoString *
5578 ves_icall_System_Environment_get_MachineName (void)
5580 #if defined (PLATFORM_WIN32)
5581 gunichar2 *buf;
5582 guint32 len;
5583 MonoString *result;
5585 len = MAX_COMPUTERNAME_LENGTH + 1;
5586 buf = g_new (gunichar2, len);
5588 result = NULL;
5589 if (GetComputerName (buf, (PDWORD) &len))
5590 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
5592 g_free (buf);
5593 return result;
5594 #else
5595 gchar buf [256];
5596 MonoString *result;
5598 if (gethostname (buf, sizeof (buf)) == 0)
5599 result = mono_string_new (mono_domain_get (), buf);
5600 else
5601 result = NULL;
5603 return result;
5604 #endif
5607 static int
5608 ves_icall_System_Environment_get_Platform (void)
5610 MONO_ARCH_SAVE_REGS;
5612 #if defined (PLATFORM_WIN32)
5613 /* Win32NT */
5614 return 2;
5615 #else
5616 /* Unix */
5617 return 128;
5618 #endif
5621 static MonoString *
5622 ves_icall_System_Environment_get_NewLine (void)
5624 MONO_ARCH_SAVE_REGS;
5626 #if defined (PLATFORM_WIN32)
5627 return mono_string_new (mono_domain_get (), "\r\n");
5628 #else
5629 return mono_string_new (mono_domain_get (), "\n");
5630 #endif
5633 static MonoString *
5634 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
5636 const gchar *value;
5637 gchar *utf8_name;
5639 MONO_ARCH_SAVE_REGS;
5641 if (name == NULL)
5642 return NULL;
5644 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
5645 value = g_getenv (utf8_name);
5647 g_free (utf8_name);
5649 if (value == 0)
5650 return NULL;
5652 return mono_string_new (mono_domain_get (), value);
5656 * There is no standard way to get at environ.
5658 #ifndef _MSC_VER
5659 #ifndef __MINGW32_VERSION
5660 extern
5661 char **environ;
5662 #endif
5663 #endif
5665 static MonoArray *
5666 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
5668 MonoArray *names;
5669 MonoDomain *domain;
5670 MonoString *str;
5671 gchar **e, **parts;
5672 int n;
5674 MONO_ARCH_SAVE_REGS;
5676 n = 0;
5677 for (e = environ; *e != 0; ++ e)
5678 ++ n;
5680 domain = mono_domain_get ();
5681 names = mono_array_new (domain, mono_defaults.string_class, n);
5683 n = 0;
5684 for (e = environ; *e != 0; ++ e) {
5685 parts = g_strsplit (*e, "=", 2);
5686 if (*parts != 0) {
5687 str = mono_string_new (domain, *parts);
5688 mono_array_setref (names, n, str);
5691 g_strfreev (parts);
5693 ++ n;
5696 return names;
5700 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
5702 #if !GLIB_CHECK_VERSION(2,4,0)
5703 #define g_setenv(a,b,c) setenv(a,b,c)
5704 #define g_unsetenv(a) unsetenv(a)
5705 #endif
5707 static void
5708 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
5710 #ifdef PLATFORM_WIN32
5711 gunichar2 *utf16_name, *utf16_value;
5712 #else
5713 gchar *utf8_name, *utf8_value;
5714 #endif
5716 MONO_ARCH_SAVE_REGS;
5718 #ifdef PLATFORM_WIN32
5719 utf16_name = mono_string_to_utf16 (name);
5720 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
5721 SetEnvironmentVariable (utf16_name, NULL);
5722 g_free (utf16_name);
5723 return;
5726 utf16_value = mono_string_to_utf16 (value);
5728 SetEnvironmentVariable (utf16_name, utf16_value);
5730 g_free (utf16_name);
5731 g_free (utf16_value);
5732 #else
5733 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
5735 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
5736 g_unsetenv (utf8_name);
5737 g_free (utf8_name);
5738 return;
5741 utf8_value = mono_string_to_utf8 (value);
5742 g_setenv (utf8_name, utf8_value, TRUE);
5744 g_free (utf8_name);
5745 g_free (utf8_value);
5746 #endif
5750 * Returns: the number of milliseconds elapsed since the system started.
5752 static gint32
5753 ves_icall_System_Environment_get_TickCount (void)
5755 return GetTickCount ();
5759 static void
5760 ves_icall_System_Environment_Exit (int result)
5762 MONO_ARCH_SAVE_REGS;
5764 mono_runtime_set_shutting_down ();
5766 /* Suspend all managed threads since the runtime is going away */
5767 mono_thread_suspend_all_other_threads ();
5769 mono_runtime_quit ();
5771 /* we may need to do some cleanup here... */
5772 exit (result);
5775 static MonoString*
5776 ves_icall_System_Environment_GetGacPath (void)
5778 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
5781 static MonoString*
5782 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
5784 #if defined (PLATFORM_WIN32)
5785 #ifndef CSIDL_FLAG_CREATE
5786 #define CSIDL_FLAG_CREATE 0x8000
5787 #endif
5789 WCHAR path [MAX_PATH];
5790 /* Create directory if no existing */
5791 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
5792 int len = 0;
5793 while (path [len])
5794 ++ len;
5795 return mono_string_new_utf16 (mono_domain_get (), path, len);
5797 #else
5798 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
5799 #endif
5800 return mono_string_new (mono_domain_get (), "");
5803 static MonoArray *
5804 ves_icall_System_Environment_GetLogicalDrives (void)
5806 gunichar2 buf [128], *ptr, *dname;
5807 gunichar2 *u16;
5808 gint initial_size = 127, size = 128;
5809 gint ndrives;
5810 MonoArray *result;
5811 MonoString *drivestr;
5812 MonoDomain *domain = mono_domain_get ();
5813 gint len;
5815 MONO_ARCH_SAVE_REGS;
5817 buf [0] = '\0';
5818 ptr = buf;
5820 while (size > initial_size) {
5821 size = GetLogicalDriveStrings (initial_size, ptr);
5822 if (size > initial_size) {
5823 if (ptr != buf)
5824 g_free (ptr);
5825 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
5826 initial_size = size;
5827 size++;
5831 /* Count strings */
5832 dname = ptr;
5833 ndrives = 0;
5834 do {
5835 while (*dname++);
5836 ndrives++;
5837 } while (*dname);
5839 dname = ptr;
5840 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
5841 ndrives = 0;
5842 do {
5843 len = 0;
5844 u16 = dname;
5845 while (*u16) { u16++; len ++; }
5846 drivestr = mono_string_new_utf16 (domain, dname, len);
5847 mono_array_setref (result, ndrives++, drivestr);
5848 while (*dname++);
5849 } while (*dname);
5851 if (ptr != buf)
5852 g_free (ptr);
5854 return result;
5857 static MonoString *
5858 ves_icall_System_Environment_InternalGetHome (void)
5860 MONO_ARCH_SAVE_REGS;
5862 return mono_string_new (mono_domain_get (), g_get_home_dir ());
5865 static const char *encodings [] = {
5866 (char *) 1,
5867 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
5868 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
5869 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
5870 (char *) 2,
5871 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
5872 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
5873 "x_unicode_2_0_utf_7",
5874 (char *) 3,
5875 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
5876 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
5877 (char *) 4,
5878 "utf_16", "UTF_16LE", "ucs_2", "unicode",
5879 "iso_10646_ucs2",
5880 (char *) 5,
5881 "unicodefffe", "utf_16be",
5882 (char *) 6,
5883 "iso_8859_1",
5884 (char *) 0
5888 * Returns the internal codepage, if the value of "int_code_page" is
5889 * 1 at entry, and we can not compute a suitable code page number,
5890 * returns the code page as a string
5892 static MonoString*
5893 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
5895 const char *cset;
5896 const char *p;
5897 char *c;
5898 char *codepage = NULL;
5899 int code;
5900 int want_name = *int_code_page;
5901 int i;
5903 *int_code_page = -1;
5904 MONO_ARCH_SAVE_REGS;
5906 g_get_charset (&cset);
5907 c = codepage = strdup (cset);
5908 for (c = codepage; *c; c++){
5909 if (isascii (*c) && isalpha (*c))
5910 *c = tolower (*c);
5911 if (*c == '-')
5912 *c = '_';
5914 /* g_print ("charset: %s\n", cset); */
5916 /* handle some common aliases */
5917 p = encodings [0];
5918 code = 0;
5919 for (i = 0; p != 0; ){
5920 if ((gssize) p < 7){
5921 code = (gssize) p;
5922 p = encodings [++i];
5923 continue;
5925 if (strcmp (p, codepage) == 0){
5926 *int_code_page = code;
5927 break;
5929 p = encodings [++i];
5932 if (strstr (codepage, "utf_8") != NULL)
5933 *int_code_page |= 0x10000000;
5934 free (codepage);
5936 if (want_name && *int_code_page == -1)
5937 return mono_string_new (mono_domain_get (), cset);
5938 else
5939 return NULL;
5942 static MonoBoolean
5943 ves_icall_System_Environment_get_HasShutdownStarted (void)
5945 if (mono_runtime_is_shutting_down ())
5946 return TRUE;
5948 if (mono_domain_is_unloading (mono_domain_get ()))
5949 return TRUE;
5951 return FALSE;
5954 static void
5955 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
5956 MonoReflectionMethod *method,
5957 MonoArray *out_args)
5959 MONO_ARCH_SAVE_REGS;
5961 mono_message_init (mono_object_domain (this), this, method, out_args);
5964 static MonoBoolean
5965 ves_icall_IsTransparentProxy (MonoObject *proxy)
5967 MONO_ARCH_SAVE_REGS;
5969 if (!proxy)
5970 return 0;
5972 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
5973 return 1;
5975 return 0;
5978 static void
5979 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
5981 MonoClass *klass;
5982 MonoVTable* vtable;
5984 MONO_ARCH_SAVE_REGS;
5986 klass = mono_class_from_mono_type (type->type);
5987 vtable = mono_class_vtable (mono_domain_get (), klass);
5989 if (enable) vtable->remote = 1;
5990 else vtable->remote = 0;
5993 static MonoObject *
5994 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
5996 MonoClass *klass;
5997 MonoDomain *domain;
5999 MONO_ARCH_SAVE_REGS;
6001 domain = mono_object_domain (type);
6002 klass = mono_class_from_mono_type (type->type);
6004 if (klass->rank >= 1) {
6005 g_assert (klass->rank == 1);
6006 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6007 } else {
6008 /* Bypass remoting object creation check */
6009 return mono_object_new_alloc_specific (mono_class_vtable (domain, klass));
6013 static MonoString *
6014 ves_icall_System_IO_get_temp_path (void)
6016 MONO_ARCH_SAVE_REGS;
6018 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6021 static gpointer
6022 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6024 MONO_ARCH_SAVE_REGS;
6026 return mono_compile_method (method);
6029 static MonoString *
6030 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6032 MonoString *mcpath;
6033 gchar *path;
6035 MONO_ARCH_SAVE_REGS;
6037 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6039 #if defined (PLATFORM_WIN32)
6040 /* Avoid mixing '/' and '\\' */
6042 gint i;
6043 for (i = strlen (path) - 1; i >= 0; i--)
6044 if (path [i] == '/')
6045 path [i] = '\\';
6047 #endif
6048 mcpath = mono_string_new (mono_domain_get (), path);
6049 g_free (path);
6051 return mcpath;
6054 static MonoString *
6055 ves_icall_System_Configuration_DefaultConfig_get_bundled_machine_config (void)
6057 const gchar *machine_config;
6059 MONO_ARCH_SAVE_REGS;
6061 machine_config = mono_get_machine_config ();
6063 if (!machine_config)
6064 return NULL;
6066 return mono_string_new (mono_domain_get (), machine_config);
6069 static MonoString *
6070 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6072 MonoString *ipath;
6073 gchar *path;
6075 MONO_ARCH_SAVE_REGS;
6077 path = g_path_get_dirname (mono_get_config_dir ());
6079 #if defined (PLATFORM_WIN32)
6080 /* Avoid mixing '/' and '\\' */
6082 gint i;
6083 for (i = strlen (path) - 1; i >= 0; i--)
6084 if (path [i] == '/')
6085 path [i] = '\\';
6087 #endif
6088 ipath = mono_string_new (mono_domain_get (), path);
6089 g_free (path);
6091 return ipath;
6094 static void
6095 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6097 #if defined (PLATFORM_WIN32)
6098 OutputDebugString (mono_string_chars (message));
6099 #else
6100 g_warning ("WriteWindowsDebugString called and PLATFORM_WIN32 not defined!\n");
6101 #endif
6104 /* Only used for value types */
6105 static MonoObject *
6106 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6108 MonoClass *klass;
6109 MonoDomain *domain;
6111 MONO_ARCH_SAVE_REGS;
6113 domain = mono_object_domain (type);
6114 klass = mono_class_from_mono_type (type->type);
6116 if (mono_class_is_nullable (klass))
6117 /* No arguments -> null */
6118 return NULL;
6120 return mono_object_new (domain, klass);
6123 static MonoReflectionMethod *
6124 ves_icall_MonoMethod_get_base_definition (MonoReflectionMethod *m)
6126 MonoClass *klass, *parent;
6127 MonoMethod *method = m->method;
6128 MonoMethod *result = NULL;
6130 MONO_ARCH_SAVE_REGS;
6132 if (method->klass == NULL)
6133 return m;
6135 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6136 MONO_CLASS_IS_INTERFACE (method->klass) ||
6137 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6138 return m;
6140 klass = method->klass;
6141 if (klass->generic_class)
6142 klass = klass->generic_class->container_class;
6144 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6145 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6146 mono_class_setup_vtable (parent);
6147 if (parent->vtable_size <= method->slot)
6148 break;
6149 klass = parent;
6152 if (klass == method->klass)
6153 return m;
6155 result = klass->vtable [method->slot];
6156 if (result == NULL) {
6157 /* It is an abstract method */
6158 gpointer iter = NULL;
6159 while ((result = mono_class_get_methods (klass, &iter)))
6160 if (result->slot == method->slot)
6161 break;
6164 if (result == NULL)
6165 return m;
6167 return mono_method_get_object (mono_domain_get (), result, NULL);
6170 static void
6171 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
6173 MONO_ARCH_SAVE_REGS;
6175 iter->sig = *(MonoMethodSignature**)argsp;
6177 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
6178 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
6180 iter->next_arg = 0;
6181 /* FIXME: it's not documented what start is exactly... */
6182 if (start) {
6183 iter->args = start;
6184 } else {
6185 guint32 i, arg_size;
6186 gint32 align;
6187 iter->args = argsp + sizeof (gpointer);
6188 #ifndef MONO_ARCH_REGPARMS
6189 for (i = 0; i < iter->sig->sentinelpos; ++i) {
6190 arg_size = mono_type_stack_size (iter->sig->params [i], &align);
6191 iter->args = (char*)iter->args + arg_size;
6193 #endif
6195 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
6197 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
6200 static MonoTypedRef
6201 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
6203 guint32 i, arg_size;
6204 gint32 align;
6205 MonoTypedRef res;
6206 MONO_ARCH_SAVE_REGS;
6208 i = iter->sig->sentinelpos + iter->next_arg;
6210 g_assert (i < iter->sig->param_count);
6212 res.type = iter->sig->params [i];
6213 res.klass = mono_class_from_mono_type (res.type);
6214 /* FIXME: endianess issue... */
6215 res.value = iter->args;
6216 arg_size = mono_type_stack_size (res.type, &align);
6217 iter->args = (char*)iter->args + arg_size;
6218 iter->next_arg++;
6220 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6222 return res;
6225 static MonoTypedRef
6226 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
6228 guint32 i, arg_size;
6229 gint32 align;
6230 MonoTypedRef res;
6231 MONO_ARCH_SAVE_REGS;
6233 i = iter->sig->sentinelpos + iter->next_arg;
6235 g_assert (i < iter->sig->param_count);
6237 while (i < iter->sig->param_count) {
6238 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
6239 continue;
6240 res.type = iter->sig->params [i];
6241 res.klass = mono_class_from_mono_type (res.type);
6242 /* FIXME: endianess issue... */
6243 res.value = iter->args;
6244 arg_size = mono_type_stack_size (res.type, &align);
6245 iter->args = (char*)iter->args + arg_size;
6246 iter->next_arg++;
6247 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6248 return res;
6250 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
6252 res.type = NULL;
6253 res.value = NULL;
6254 res.klass = NULL;
6255 return res;
6258 static MonoType*
6259 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
6261 gint i;
6262 MONO_ARCH_SAVE_REGS;
6264 i = iter->sig->sentinelpos + iter->next_arg;
6266 g_assert (i < iter->sig->param_count);
6268 return iter->sig->params [i];
6271 static MonoObject*
6272 mono_TypedReference_ToObject (MonoTypedRef tref)
6274 MONO_ARCH_SAVE_REGS;
6276 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
6277 MonoObject** objp = tref.value;
6278 return *objp;
6281 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
6284 static MonoObject*
6285 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
6287 MONO_ARCH_SAVE_REGS;
6289 if (MONO_TYPE_IS_REFERENCE (type)) {
6290 MonoObject** objp = value;
6291 return *objp;
6294 return mono_value_box (mono_domain_get (), klass, value);
6297 static void
6298 prelink_method (MonoMethod *method)
6300 const char *exc_class, *exc_arg;
6301 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
6302 return;
6303 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
6304 if (exc_class) {
6305 mono_raise_exception(
6306 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
6308 /* create the wrapper, too? */
6311 static void
6312 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
6314 MONO_ARCH_SAVE_REGS;
6315 prelink_method (method->method);
6318 static void
6319 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
6321 MonoClass *klass = mono_class_from_mono_type (type->type);
6322 MonoMethod* m;
6323 gpointer iter = NULL;
6324 MONO_ARCH_SAVE_REGS;
6326 while ((m = mono_class_get_methods (klass, &iter)))
6327 prelink_method (m);
6330 /* These parameters are "readonly" in corlib/System/Char.cs */
6331 static void
6332 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
6333 guint8 const **numeric_data,
6334 gdouble const **numeric_data_values,
6335 guint16 const **to_lower_data_low,
6336 guint16 const **to_lower_data_high,
6337 guint16 const **to_upper_data_low,
6338 guint16 const **to_upper_data_high)
6340 *category_data = CategoryData;
6341 *numeric_data = NumericData;
6342 *numeric_data_values = NumericDataValues;
6343 *to_lower_data_low = ToLowerDataLow;
6344 *to_lower_data_high = ToLowerDataHigh;
6345 *to_upper_data_low = ToUpperDataLow;
6346 *to_upper_data_high = ToUpperDataHigh;
6349 static gint32
6350 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
6352 return method->method->token;
6356 * We eturn NULL for no modifiers so the corlib code can return Type.EmptyTypes
6357 * and avoid useless allocations.
6359 static MonoArray*
6360 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
6362 MonoArray *res;
6363 int i, count = 0;
6364 for (i = 0; i < type->num_mods; ++i) {
6365 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
6366 count++;
6368 if (!count)
6369 return NULL;
6370 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
6371 count = 0;
6372 for (i = 0; i < type->num_mods; ++i) {
6373 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
6374 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
6375 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
6376 count++;
6379 return res;
6382 static MonoArray*
6383 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
6385 MonoType *type = param->ClassImpl->type;
6386 MonoReflectionMethod *method = (MonoReflectionMethod*)param->MemberImpl;
6387 MonoImage *image = method->method->klass->image;
6388 int pos = param->PositionImpl;
6389 MonoMethodSignature *sig = mono_method_signature (method->method);
6390 if (pos == -1)
6391 type = sig->ret;
6392 else
6393 type = sig->params [pos];
6395 return type_array_from_modifiers (image, type, optional);
6398 static MonoType*
6399 get_property_type (MonoProperty *prop)
6401 MonoMethodSignature *sig;
6402 if (prop->get) {
6403 sig = mono_method_signature (prop->get);
6404 return sig->ret;
6405 } else if (prop->set) {
6406 sig = mono_method_signature (prop->set);
6407 return sig->params [sig->param_count - 1];
6409 return NULL;
6412 static MonoArray*
6413 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
6415 MonoType *type = get_property_type (property->property);
6416 MonoImage *image = property->klass->image;
6418 if (!type)
6419 return NULL;
6420 return type_array_from_modifiers (image, type, optional);
6423 static MonoBoolean
6424 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
6426 MonoCustomAttrInfo *cinfo;
6427 gboolean found;
6429 cinfo = mono_reflection_get_custom_attrs_info (obj);
6430 if (!cinfo)
6431 return FALSE;
6432 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
6433 if (!cinfo->cached)
6434 mono_custom_attrs_free (cinfo);
6435 return found;
6438 static MonoArray*
6439 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
6441 return mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
6444 static MonoBoolean
6445 GCHandle_CheckCurrentDomain (guint32 gchandle)
6447 return mono_gchandle_is_in_domain (gchandle, mono_domain_get ());
6450 static MonoString*
6451 ves_icall_Mono_Runtime_GetDisplayName (void)
6453 static const char display_name_str [] = "Mono " VERSION;
6454 MonoString *display_name = mono_string_new (mono_domain_get (), display_name_str);
6455 return display_name;
6458 const static guchar
6459 dbase64 [] = {
6460 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
6461 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
6462 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
6463 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
6464 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
6465 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
6466 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
6467 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
6470 static MonoArray *
6471 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
6473 gint ignored;
6474 gint i;
6475 gunichar2 c;
6476 gunichar2 last, prev_last;
6477 gint olength;
6478 MonoArray *result;
6479 guchar *res_ptr;
6480 gint a [4], b [4];
6481 MonoException *exc;
6483 ignored = 0;
6484 last = prev_last = 0;
6485 for (i = 0; i < ilength; i++) {
6486 c = start [i];
6487 if (c >= sizeof (dbase64)) {
6488 exc = mono_exception_from_name_msg (mono_get_corlib (),
6489 "System", "FormatException",
6490 "Invalid character found.");
6491 mono_raise_exception (exc);
6492 } else if (isspace (c)) {
6493 ignored++;
6494 } else {
6495 prev_last = last;
6496 last = c;
6500 olength = ilength - ignored;
6502 if (allowWhitespaceOnly && olength == 0) {
6503 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
6506 if ((olength & 3) != 0 || olength <= 0) {
6507 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
6508 "FormatException", "Invalid length.");
6509 mono_raise_exception (exc);
6512 olength = (olength * 3) / 4;
6513 if (last == '=')
6514 olength--;
6516 if (prev_last == '=')
6517 olength--;
6519 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
6520 res_ptr = mono_array_addr (result, guchar, 0);
6521 for (i = 0; i < ilength; ) {
6522 int k;
6524 for (k = 0; k < 4 && i < ilength;) {
6525 c = start [i++];
6526 if (isspace (c))
6527 continue;
6529 a [k] = (guchar) c;
6530 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
6531 exc = mono_exception_from_name_msg (mono_get_corlib (),
6532 "System", "FormatException",
6533 "Invalid character found.");
6534 mono_raise_exception (exc);
6536 k++;
6539 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
6540 if (a [2] != '=')
6541 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
6542 if (a [3] != '=')
6543 *res_ptr++ = (b [2] << 6) | b [3];
6545 while (i < ilength && isspace (start [i]))
6546 i++;
6549 return result;
6552 static MonoArray *
6553 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
6555 MONO_ARCH_SAVE_REGS;
6557 return base64_to_byte_array (mono_string_chars (str),
6558 mono_string_length (str), allowWhitespaceOnly);
6561 static MonoArray *
6562 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
6564 MONO_ARCH_SAVE_REGS;
6566 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
6567 length, FALSE);
6570 #define ICALL_TYPE(id,name,first)
6571 #define ICALL(id,name,func) Icall_ ## id,
6573 enum {
6574 #include "metadata/icall-def.h"
6575 Icall_last
6578 #undef ICALL_TYPE
6579 #undef ICALL
6580 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
6581 #define ICALL(id,name,func)
6582 enum {
6583 #include "metadata/icall-def.h"
6584 Icall_type_num
6587 #undef ICALL_TYPE
6588 #undef ICALL
6589 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
6590 #define ICALL(id,name,func)
6591 typedef struct {
6592 guint16 first_icall;
6593 } IcallTypeDesc;
6595 static const IcallTypeDesc
6596 icall_type_descs [] = {
6597 #include "metadata/icall-def.h"
6598 {Icall_last}
6601 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
6603 #undef ICALL_TYPE
6604 #define ICALL_TYPE(id,name,first)
6605 #undef ICALL
6607 #ifdef HAVE_ARRAY_ELEM_INIT
6608 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
6609 #define MSGSTRFIELD1(line) str##line
6611 static const struct msgstrtn_t {
6612 #define ICALL(id,name,func)
6613 #undef ICALL_TYPE
6614 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
6615 #include "metadata/icall-def.h"
6616 #undef ICALL_TYPE
6617 } icall_type_names_str = {
6618 #define ICALL_TYPE(id,name,first) (name),
6619 #include "metadata/icall-def.h"
6620 #undef ICALL_TYPE
6622 static const guint16 icall_type_names_idx [] = {
6623 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
6624 #include "metadata/icall-def.h"
6625 #undef ICALL_TYPE
6627 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
6629 static const struct msgstr_t {
6630 #undef ICALL
6631 #define ICALL_TYPE(id,name,first)
6632 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
6633 #include "metadata/icall-def.h"
6634 #undef ICALL
6635 } icall_names_str = {
6636 #define ICALL(id,name,func) (name),
6637 #include "metadata/icall-def.h"
6638 #undef ICALL
6640 static const guint16 icall_names_idx [] = {
6641 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
6642 #include "metadata/icall-def.h"
6643 #undef ICALL
6645 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
6647 #else
6649 #undef ICALL_TYPE
6650 #undef ICALL
6651 #define ICALL_TYPE(id,name,first) name,
6652 #define ICALL(id,name,func)
6653 static const char* const
6654 icall_type_names [] = {
6655 #include "metadata/icall-def.h"
6656 NULL
6659 #define icall_type_name_get(id) (icall_type_names [(id)])
6661 #undef ICALL_TYPE
6662 #undef ICALL
6663 #define ICALL_TYPE(id,name,first)
6664 #define ICALL(id,name,func) name,
6665 static const char* const
6666 icall_names [] = {
6667 #include "metadata/icall-def.h"
6668 NULL
6670 #define icall_name_get(id) icall_names [(id)]
6672 #endif /* !HAVE_ARRAY_ELEM_INIT */
6674 #undef ICALL_TYPE
6675 #undef ICALL
6676 #define ICALL_TYPE(id,name,first)
6677 #define ICALL(id,name,func) func,
6678 static const gconstpointer
6679 icall_functions [] = {
6680 #include "metadata/icall-def.h"
6681 NULL
6684 static GHashTable *icall_hash = NULL;
6685 static GHashTable *jit_icall_hash_name = NULL;
6686 static GHashTable *jit_icall_hash_addr = NULL;
6688 void
6689 mono_icall_init (void)
6691 int i = 0;
6693 /* check that tables are sorted: disable in release */
6694 if (TRUE) {
6695 int j;
6696 const char *prev_class = NULL;
6697 const char *prev_method;
6699 for (i = 0; i < Icall_type_num; ++i) {
6700 const IcallTypeDesc *desc;
6701 int num_icalls;
6702 prev_method = NULL;
6703 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
6704 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
6705 prev_class = icall_type_name_get (i);
6706 desc = &icall_type_descs [i];
6707 num_icalls = icall_desc_num_icalls (desc);
6708 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
6709 for (j = 0; j < num_icalls; ++j) {
6710 const char *methodn = icall_name_get (desc->first_icall + j);
6711 if (prev_method && strcmp (prev_method, methodn) >= 0)
6712 g_print ("method %s should come before method %s\n", methodn, prev_method);
6713 prev_method = methodn;
6718 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
6721 void
6722 mono_icall_cleanup (void)
6724 g_hash_table_destroy (icall_hash);
6725 g_hash_table_destroy (jit_icall_hash_name);
6726 g_hash_table_destroy (jit_icall_hash_addr);
6729 void
6730 mono_add_internal_call (const char *name, gconstpointer method)
6732 mono_loader_lock ();
6734 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
6736 mono_loader_unlock ();
6739 #ifdef HAVE_ARRAY_ELEM_INIT
6740 static int
6741 compare_method_imap (const void *key, const void *elem)
6743 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
6744 return strcmp (key, method_name);
6747 static gpointer
6748 find_method_icall (const IcallTypeDesc *imap, const char *name)
6750 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
6751 if (!nameslot)
6752 return NULL;
6753 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
6756 static int
6757 compare_class_imap (const void *key, const void *elem)
6759 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
6760 return strcmp (key, class_name);
6763 static const IcallTypeDesc*
6764 find_class_icalls (const char *name)
6766 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
6767 if (!nameslot)
6768 return NULL;
6769 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
6772 #else
6773 static int
6774 compare_method_imap (const void *key, const void *elem)
6776 const char** method_name = (const char**)elem;
6777 return strcmp (key, *method_name);
6780 static gpointer
6781 find_method_icall (const IcallTypeDesc *imap, const char *name)
6783 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
6784 if (!nameslot)
6785 return NULL;
6786 return (gpointer)icall_functions [(nameslot - icall_names)];
6789 static int
6790 compare_class_imap (const void *key, const void *elem)
6792 const char** class_name = (const char**)elem;
6793 return strcmp (key, *class_name);
6796 static const IcallTypeDesc*
6797 find_class_icalls (const char *name)
6799 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
6800 if (!nameslot)
6801 return NULL;
6802 return &icall_type_descs [nameslot - icall_type_names];
6805 #endif
6808 * we should probably export this as an helper (handle nested types).
6809 * Returns the number of chars written in buf.
6811 static int
6812 concat_class_name (char *buf, int bufsize, MonoClass *klass)
6814 int nspacelen, cnamelen;
6815 nspacelen = strlen (klass->name_space);
6816 cnamelen = strlen (klass->name);
6817 if (nspacelen + cnamelen + 2 > bufsize)
6818 return 0;
6819 if (nspacelen) {
6820 memcpy (buf, klass->name_space, nspacelen);
6821 buf [nspacelen ++] = '.';
6823 memcpy (buf + nspacelen, klass->name, cnamelen);
6824 buf [nspacelen + cnamelen] = 0;
6825 return nspacelen + cnamelen;
6828 gpointer
6829 mono_lookup_internal_call (MonoMethod *method)
6831 char *sigstart;
6832 char *tmpsig;
6833 char mname [2048];
6834 int typelen = 0, mlen, siglen;
6835 gpointer res;
6836 const IcallTypeDesc *imap;
6838 g_assert (method != NULL);
6840 if (method->is_inflated)
6841 method = ((MonoMethodInflated *) method)->declaring;
6843 if (method->klass->nested_in) {
6844 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
6845 if (!pos)
6846 return NULL;
6848 mname [pos++] = '/';
6849 mname [pos] = 0;
6851 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
6852 if (!typelen)
6853 return NULL;
6855 typelen += pos;
6856 } else {
6857 typelen = concat_class_name (mname, sizeof (mname), method->klass);
6858 if (!typelen)
6859 return NULL;
6862 imap = find_class_icalls (mname);
6864 mname [typelen] = ':';
6865 mname [typelen + 1] = ':';
6867 mlen = strlen (method->name);
6868 memcpy (mname + typelen + 2, method->name, mlen);
6869 sigstart = mname + typelen + 2 + mlen;
6870 *sigstart = 0;
6872 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
6873 siglen = strlen (tmpsig);
6874 if (typelen + mlen + siglen + 6 > sizeof (mname))
6875 return NULL;
6876 sigstart [0] = '(';
6877 memcpy (sigstart + 1, tmpsig, siglen);
6878 sigstart [siglen + 1] = ')';
6879 sigstart [siglen + 2] = 0;
6880 g_free (tmpsig);
6882 mono_loader_lock ();
6884 res = g_hash_table_lookup (icall_hash, mname);
6885 if (res) {
6886 mono_loader_unlock ();
6887 return res;
6889 /* try without signature */
6890 *sigstart = 0;
6891 res = g_hash_table_lookup (icall_hash, mname);
6892 if (res) {
6893 mono_loader_unlock ();
6894 return res;
6897 /* it wasn't found in the static call tables */
6898 if (!imap) {
6899 mono_loader_unlock ();
6900 return NULL;
6902 res = find_method_icall (imap, sigstart - mlen);
6903 if (res) {
6904 mono_loader_unlock ();
6905 return res;
6907 /* try _with_ signature */
6908 *sigstart = '(';
6909 res = find_method_icall (imap, sigstart - mlen);
6910 if (res) {
6911 mono_loader_unlock ();
6912 return res;
6915 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
6916 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
6917 g_print ("The out of sync library is: %s\n", method->klass->image->name);
6918 g_print ("\nWhen you update one from cvs you need to update, compile and install\nthe other too.\n");
6919 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");
6920 g_print ("If you see other errors or faults after this message they are probably related\n");
6921 g_print ("and you need to fix your mono install first.\n");
6923 mono_loader_unlock ();
6925 return NULL;
6928 static MonoType*
6929 type_from_typename (char *typename)
6931 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
6933 if (!strcmp (typename, "int"))
6934 klass = mono_defaults.int_class;
6935 else if (!strcmp (typename, "ptr"))
6936 klass = mono_defaults.int_class;
6937 else if (!strcmp (typename, "void"))
6938 klass = mono_defaults.void_class;
6939 else if (!strcmp (typename, "int32"))
6940 klass = mono_defaults.int32_class;
6941 else if (!strcmp (typename, "uint32"))
6942 klass = mono_defaults.uint32_class;
6943 else if (!strcmp (typename, "int8"))
6944 klass = mono_defaults.sbyte_class;
6945 else if (!strcmp (typename, "uint8"))
6946 klass = mono_defaults.byte_class;
6947 else if (!strcmp (typename, "int16"))
6948 klass = mono_defaults.int16_class;
6949 else if (!strcmp (typename, "uint16"))
6950 klass = mono_defaults.uint16_class;
6951 else if (!strcmp (typename, "long"))
6952 klass = mono_defaults.int64_class;
6953 else if (!strcmp (typename, "ulong"))
6954 klass = mono_defaults.uint64_class;
6955 else if (!strcmp (typename, "float"))
6956 klass = mono_defaults.single_class;
6957 else if (!strcmp (typename, "double"))
6958 klass = mono_defaults.double_class;
6959 else if (!strcmp (typename, "object"))
6960 klass = mono_defaults.object_class;
6961 else if (!strcmp (typename, "obj"))
6962 klass = mono_defaults.object_class;
6963 else {
6964 g_error (typename);
6965 g_assert_not_reached ();
6967 return &klass->byval_arg;
6970 MonoMethodSignature*
6971 mono_create_icall_signature (const char *sigstr)
6973 gchar **parts;
6974 int i, len;
6975 gchar **tmp;
6976 MonoMethodSignature *res;
6978 mono_loader_lock ();
6979 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
6980 if (res) {
6981 mono_loader_unlock ();
6982 return res;
6985 parts = g_strsplit (sigstr, " ", 256);
6987 tmp = parts;
6988 len = 0;
6989 while (*tmp) {
6990 len ++;
6991 tmp ++;
6994 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
6995 res->pinvoke = 1;
6997 #ifdef PLATFORM_WIN32
6999 * Under windows, the default pinvoke calling convention is STDCALL but
7000 * we need CDECL.
7002 res->call_convention = MONO_CALL_C;
7003 #endif
7005 res->ret = type_from_typename (parts [0]);
7006 for (i = 1; i < len; ++i) {
7007 res->params [i - 1] = type_from_typename (parts [i]);
7010 g_strfreev (parts);
7012 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
7014 mono_loader_unlock ();
7016 return res;
7019 MonoJitICallInfo *
7020 mono_find_jit_icall_by_name (const char *name)
7022 MonoJitICallInfo *info;
7023 g_assert (jit_icall_hash_name);
7025 mono_loader_lock ();
7026 info = g_hash_table_lookup (jit_icall_hash_name, name);
7027 mono_loader_unlock ();
7028 return info;
7031 MonoJitICallInfo *
7032 mono_find_jit_icall_by_addr (gconstpointer addr)
7034 MonoJitICallInfo *info;
7035 g_assert (jit_icall_hash_addr);
7037 mono_loader_lock ();
7038 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
7039 mono_loader_unlock ();
7041 return info;
7044 void
7045 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
7047 mono_loader_lock ();
7048 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
7049 mono_loader_unlock ();
7052 MonoJitICallInfo *
7053 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
7055 MonoJitICallInfo *info;
7057 g_assert (func);
7058 g_assert (name);
7060 mono_loader_lock ();
7062 if (!jit_icall_hash_name) {
7063 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
7064 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
7067 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
7068 g_warning ("jit icall already defined \"%s\"\n", name);
7069 g_assert_not_reached ();
7072 info = g_new0 (MonoJitICallInfo, 1);
7074 info->name = name;
7075 info->func = func;
7076 info->sig = sig;
7078 if (is_save) {
7079 info->wrapper = func;
7080 } else {
7081 info->wrapper = NULL;
7084 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
7085 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
7087 mono_loader_unlock ();
7088 return info;