73c97e5c2ec2bccc5a61f3dbb52b60ee3558deed
[mono.git] / mono / metadata / icall.c
1 /*
2  * icall.c:
3  *
4  * Authors:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *   Paolo Molaro (lupus@ximian.com)
7  *       Patrik Torstensson (patrik.torstensson@labs2.com)
8  *
9  * (C) 2001 Ximian, Inc.
10  */
11
12 #include <config.h>
13 #include <glib.h>
14 #include <stdarg.h>
15 #include <string.h>
16 #include <ctype.h>
17 #ifdef HAVE_SYS_TIME_H
18 #include <sys/time.h>
19 #endif
20 #ifdef HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
23 #if defined (PLATFORM_WIN32)
24 #include <stdlib.h>
25 #endif
26
27 #include <mono/metadata/object.h>
28 #include <mono/metadata/threads.h>
29 #include <mono/metadata/threads-types.h>
30 #include <mono/metadata/threadpool.h>
31 #include <mono/metadata/monitor.h>
32 #include <mono/metadata/reflection.h>
33 #include <mono/metadata/assembly.h>
34 #include <mono/metadata/tabledefs.h>
35 #include <mono/metadata/exception.h>
36 #include <mono/metadata/file-io.h>
37 #include <mono/metadata/console-io.h>
38 #include <mono/metadata/socket-io.h>
39 #include <mono/metadata/mono-endian.h>
40 #include <mono/metadata/tokentype.h>
41 #include <mono/metadata/domain-internals.h>
42 #include <mono/metadata/metadata-internals.h>
43 #include <mono/metadata/class-internals.h>
44 #include <mono/metadata/marshal.h>
45 #include <mono/metadata/gc-internal.h>
46 #include <mono/metadata/mono-gc.h>
47 #include <mono/metadata/rand.h>
48 #include <mono/metadata/sysmath.h>
49 #include <mono/metadata/string-icalls.h>
50 #include <mono/metadata/debug-helpers.h>
51 #include <mono/metadata/process.h>
52 #include <mono/metadata/environment.h>
53 #include <mono/metadata/profiler-private.h>
54 #include <mono/metadata/locales.h>
55 #include <mono/metadata/filewatcher.h>
56 #include <mono/metadata/char-conversions.h>
57 #include <mono/metadata/security.h>
58 #include <mono/metadata/mono-config.h>
59 #include <mono/metadata/cil-coff.h>
60 #include <mono/metadata/number-formatter.h>
61 #include <mono/metadata/security-manager.h>
62 #include <mono/metadata/security-core-clr.h>
63 #include <mono/metadata/mono-perfcounters.h>
64 #include <mono/io-layer/io-layer.h>
65 #include <mono/utils/strtod.h>
66 #include <mono/utils/monobitset.h>
67 #include <mono/utils/mono-time.h>
68
69 #if defined (PLATFORM_WIN32)
70 #include <windows.h>
71 #include <shlobj.h>
72 #endif
73 #include "decimal.h"
74
75 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
76
77 static MonoArray*
78 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
79
80 static inline MonoBoolean
81 is_generic_parameter (MonoType *type)
82 {
83         return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
84 }
85
86 /*
87  * We expect a pointer to a char, not a string
88  */
89 static gboolean
90 mono_double_ParseImpl (char *ptr, double *result)
91 {
92         gchar *endptr = NULL;
93         *result = 0.0;
94
95         MONO_ARCH_SAVE_REGS;
96
97 #ifdef __arm__
98         if (*ptr)
99                 *result = strtod (ptr, &endptr);
100 #else
101         if (*ptr)
102                 *result = mono_strtod (ptr, &endptr);
103 #endif
104
105         if (!*ptr || (endptr && *endptr))
106                 return FALSE;
107         
108         return TRUE;
109 }
110
111 static MonoClass *
112 mono_class_get_throw (MonoImage *image, guint32 type_token)
113 {
114         MonoClass *class = mono_class_get (image, type_token);
115         MonoLoaderError *error;
116         MonoException *ex;
117         
118         if (class != NULL)
119                 return class;
120
121         error = mono_loader_get_last_error ();
122         g_assert (error != NULL);
123         
124         ex = mono_loader_error_prepare_exception (error);
125         mono_raise_exception (ex);
126         return NULL;
127 }
128
129 static MonoObject *
130 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
131 {
132         MonoClass *ac;
133         MonoArray *ao;
134         gint32 esize;
135         gpointer *ea;
136
137         MONO_ARCH_SAVE_REGS;
138
139         ao = (MonoArray *)this;
140         ac = (MonoClass *)ao->obj.vtable->klass;
141
142         esize = mono_array_element_size (ac);
143         ea = (gpointer*)((char*)ao->vector + (pos * esize));
144
145         if (ac->element_class->valuetype)
146                 return mono_value_box (this->vtable->domain, ac->element_class, ea);
147         else
148                 return *ea;
149 }
150
151 static MonoObject *
152 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
153 {
154         MonoClass *ac, *ic;
155         MonoArray *ao, *io;
156         gint32 i, pos, *ind;
157
158         MONO_ARCH_SAVE_REGS;
159
160         MONO_CHECK_ARG_NULL (idxs);
161
162         io = (MonoArray *)idxs;
163         ic = (MonoClass *)io->obj.vtable->klass;
164         
165         ao = (MonoArray *)this;
166         ac = (MonoClass *)ao->obj.vtable->klass;
167
168         g_assert (ic->rank == 1);
169         if (io->bounds != NULL || io->max_length !=  ac->rank)
170                 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
171
172         ind = (gint32 *)io->vector;
173
174         if (ao->bounds == NULL) {
175                 if (*ind < 0 || *ind >= ao->max_length)
176                         mono_raise_exception (mono_get_exception_index_out_of_range ());
177
178                 return ves_icall_System_Array_GetValueImpl (this, *ind);
179         }
180         
181         for (i = 0; i < ac->rank; i++)
182                 if ((ind [i] < ao->bounds [i].lower_bound) ||
183                     (ind [i] >= ao->bounds [i].length + ao->bounds [i].lower_bound))
184                         mono_raise_exception (mono_get_exception_index_out_of_range ());
185
186         pos = ind [0] - ao->bounds [0].lower_bound;
187         for (i = 1; i < ac->rank; i++)
188                 pos = pos*ao->bounds [i].length + ind [i] - 
189                         ao->bounds [i].lower_bound;
190
191         return ves_icall_System_Array_GetValueImpl (this, pos);
192 }
193
194 static void
195 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
196 {
197         MonoClass *ac, *vc, *ec;
198         gint32 esize, vsize;
199         gpointer *ea, *va;
200         int et, vt;
201
202         guint64 u64 = 0;
203         gint64 i64 = 0;
204         gdouble r64 = 0;
205
206         MONO_ARCH_SAVE_REGS;
207
208         if (value)
209                 vc = value->vtable->klass;
210         else
211                 vc = NULL;
212
213         ac = this->obj.vtable->klass;
214         ec = ac->element_class;
215
216         esize = mono_array_element_size (ac);
217         ea = (gpointer*)((char*)this->vector + (pos * esize));
218         va = (gpointer*)((char*)value + sizeof (MonoObject));
219
220         if (!value) {
221                 memset (ea, 0,  esize);
222                 return;
223         }
224
225 #define NO_WIDENING_CONVERSION G_STMT_START{\
226         mono_raise_exception (mono_get_exception_argument ( \
227                 "value", "not a widening conversion")); \
228 }G_STMT_END
229
230 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
231         if (esize < vsize + (extra)) \
232                 mono_raise_exception (mono_get_exception_argument ( \
233                         "value", "not a widening conversion")); \
234 }G_STMT_END
235
236 #define INVALID_CAST G_STMT_START{\
237         mono_raise_exception (mono_get_exception_invalid_cast ()); \
238 }G_STMT_END
239
240         /* Check element (destination) type. */
241         switch (ec->byval_arg.type) {
242         case MONO_TYPE_STRING:
243                 switch (vc->byval_arg.type) {
244                 case MONO_TYPE_STRING:
245                         break;
246                 default:
247                         INVALID_CAST;
248                 }
249                 break;
250         case MONO_TYPE_BOOLEAN:
251                 switch (vc->byval_arg.type) {
252                 case MONO_TYPE_BOOLEAN:
253                         break;
254                 case MONO_TYPE_CHAR:
255                 case MONO_TYPE_U1:
256                 case MONO_TYPE_U2:
257                 case MONO_TYPE_U4:
258                 case MONO_TYPE_U8:
259                 case MONO_TYPE_I1:
260                 case MONO_TYPE_I2:
261                 case MONO_TYPE_I4:
262                 case MONO_TYPE_I8:
263                 case MONO_TYPE_R4:
264                 case MONO_TYPE_R8:
265                         NO_WIDENING_CONVERSION;
266                 default:
267                         INVALID_CAST;
268                 }
269                 break;
270         }
271
272         if (!ec->valuetype) {
273                 if (!mono_object_isinst (value, ec))
274                         INVALID_CAST;
275                 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
276                 return;
277         }
278
279         if (mono_object_isinst (value, ec)) {
280                 if (ec->has_references)
281                         mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
282                 else
283                         memcpy (ea, (char *)value + sizeof (MonoObject), esize);
284                 return;
285         }
286
287         if (!vc->valuetype)
288                 INVALID_CAST;
289
290         vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
291
292         et = ec->byval_arg.type;
293         if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
294                 et = ec->byval_arg.data.klass->enum_basetype->type;
295
296         vt = vc->byval_arg.type;
297         if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
298                 vt = vc->byval_arg.data.klass->enum_basetype->type;
299
300 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
301         switch (vt) { \
302         case MONO_TYPE_U1: \
303         case MONO_TYPE_U2: \
304         case MONO_TYPE_U4: \
305         case MONO_TYPE_U8: \
306         case MONO_TYPE_CHAR: \
307                 CHECK_WIDENING_CONVERSION(0); \
308                 *(etype *) ea = (etype) u64; \
309                 return; \
310         /* You can't assign a signed value to an unsigned array. */ \
311         case MONO_TYPE_I1: \
312         case MONO_TYPE_I2: \
313         case MONO_TYPE_I4: \
314         case MONO_TYPE_I8: \
315         /* You can't assign a floating point number to an integer array. */ \
316         case MONO_TYPE_R4: \
317         case MONO_TYPE_R8: \
318                 NO_WIDENING_CONVERSION; \
319         } \
320 }G_STMT_END
321
322 #define ASSIGN_SIGNED(etype) G_STMT_START{\
323         switch (vt) { \
324         case MONO_TYPE_I1: \
325         case MONO_TYPE_I2: \
326         case MONO_TYPE_I4: \
327         case MONO_TYPE_I8: \
328                 CHECK_WIDENING_CONVERSION(0); \
329                 *(etype *) ea = (etype) i64; \
330                 return; \
331         /* You can assign an unsigned value to a signed array if the array's */ \
332         /* element size is larger than the value size. */ \
333         case MONO_TYPE_U1: \
334         case MONO_TYPE_U2: \
335         case MONO_TYPE_U4: \
336         case MONO_TYPE_U8: \
337         case MONO_TYPE_CHAR: \
338                 CHECK_WIDENING_CONVERSION(1); \
339                 *(etype *) ea = (etype) u64; \
340                 return; \
341         /* You can't assign a floating point number to an integer array. */ \
342         case MONO_TYPE_R4: \
343         case MONO_TYPE_R8: \
344                 NO_WIDENING_CONVERSION; \
345         } \
346 }G_STMT_END
347
348 #define ASSIGN_REAL(etype) G_STMT_START{\
349         switch (vt) { \
350         case MONO_TYPE_R4: \
351         case MONO_TYPE_R8: \
352                 CHECK_WIDENING_CONVERSION(0); \
353                 *(etype *) ea = (etype) r64; \
354                 return; \
355         /* All integer values fit into a floating point array, so we don't */ \
356         /* need to CHECK_WIDENING_CONVERSION here. */ \
357         case MONO_TYPE_I1: \
358         case MONO_TYPE_I2: \
359         case MONO_TYPE_I4: \
360         case MONO_TYPE_I8: \
361                 *(etype *) ea = (etype) i64; \
362                 return; \
363         case MONO_TYPE_U1: \
364         case MONO_TYPE_U2: \
365         case MONO_TYPE_U4: \
366         case MONO_TYPE_U8: \
367         case MONO_TYPE_CHAR: \
368                 *(etype *) ea = (etype) u64; \
369                 return; \
370         } \
371 }G_STMT_END
372
373         switch (vt) {
374         case MONO_TYPE_U1:
375                 u64 = *(guint8 *) va;
376                 break;
377         case MONO_TYPE_U2:
378                 u64 = *(guint16 *) va;
379                 break;
380         case MONO_TYPE_U4:
381                 u64 = *(guint32 *) va;
382                 break;
383         case MONO_TYPE_U8:
384                 u64 = *(guint64 *) va;
385                 break;
386         case MONO_TYPE_I1:
387                 i64 = *(gint8 *) va;
388                 break;
389         case MONO_TYPE_I2:
390                 i64 = *(gint16 *) va;
391                 break;
392         case MONO_TYPE_I4:
393                 i64 = *(gint32 *) va;
394                 break;
395         case MONO_TYPE_I8:
396                 i64 = *(gint64 *) va;
397                 break;
398         case MONO_TYPE_R4:
399                 r64 = *(gfloat *) va;
400                 break;
401         case MONO_TYPE_R8:
402                 r64 = *(gdouble *) va;
403                 break;
404         case MONO_TYPE_CHAR:
405                 u64 = *(guint16 *) va;
406                 break;
407         case MONO_TYPE_BOOLEAN:
408                 /* Boolean is only compatible with itself. */
409                 switch (et) {
410                 case MONO_TYPE_CHAR:
411                 case MONO_TYPE_U1:
412                 case MONO_TYPE_U2:
413                 case MONO_TYPE_U4:
414                 case MONO_TYPE_U8:
415                 case MONO_TYPE_I1:
416                 case MONO_TYPE_I2:
417                 case MONO_TYPE_I4:
418                 case MONO_TYPE_I8:
419                 case MONO_TYPE_R4:
420                 case MONO_TYPE_R8:
421                         NO_WIDENING_CONVERSION;
422                 default:
423                         INVALID_CAST;
424                 }
425                 break;
426         }
427
428         /* If we can't do a direct copy, let's try a widening conversion. */
429         switch (et) {
430         case MONO_TYPE_CHAR:
431                 ASSIGN_UNSIGNED (guint16);
432         case MONO_TYPE_U1:
433                 ASSIGN_UNSIGNED (guint8);
434         case MONO_TYPE_U2:
435                 ASSIGN_UNSIGNED (guint16);
436         case MONO_TYPE_U4:
437                 ASSIGN_UNSIGNED (guint32);
438         case MONO_TYPE_U8:
439                 ASSIGN_UNSIGNED (guint64);
440         case MONO_TYPE_I1:
441                 ASSIGN_SIGNED (gint8);
442         case MONO_TYPE_I2:
443                 ASSIGN_SIGNED (gint16);
444         case MONO_TYPE_I4:
445                 ASSIGN_SIGNED (gint32);
446         case MONO_TYPE_I8:
447                 ASSIGN_SIGNED (gint64);
448         case MONO_TYPE_R4:
449                 ASSIGN_REAL (gfloat);
450         case MONO_TYPE_R8:
451                 ASSIGN_REAL (gdouble);
452         }
453
454         INVALID_CAST;
455         /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
456         return;
457
458 #undef INVALID_CAST
459 #undef NO_WIDENING_CONVERSION
460 #undef CHECK_WIDENING_CONVERSION
461 #undef ASSIGN_UNSIGNED
462 #undef ASSIGN_SIGNED
463 #undef ASSIGN_REAL
464 }
465
466 static void 
467 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
468                                  MonoArray *idxs)
469 {
470         MonoClass *ac, *ic;
471         gint32 i, pos, *ind;
472
473         MONO_ARCH_SAVE_REGS;
474
475         MONO_CHECK_ARG_NULL (idxs);
476
477         ic = idxs->obj.vtable->klass;
478         ac = this->obj.vtable->klass;
479
480         g_assert (ic->rank == 1);
481         if (idxs->bounds != NULL || idxs->max_length != ac->rank)
482                 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
483
484         ind = (gint32 *)idxs->vector;
485
486         if (this->bounds == NULL) {
487                 if (*ind < 0 || *ind >= this->max_length)
488                         mono_raise_exception (mono_get_exception_index_out_of_range ());
489
490                 ves_icall_System_Array_SetValueImpl (this, value, *ind);
491                 return;
492         }
493         
494         for (i = 0; i < ac->rank; i++)
495                 if ((ind [i] < this->bounds [i].lower_bound) ||
496                     (ind [i] >= this->bounds [i].length + this->bounds [i].lower_bound))
497                         mono_raise_exception (mono_get_exception_index_out_of_range ());
498
499         pos = ind [0] - this->bounds [0].lower_bound;
500         for (i = 1; i < ac->rank; i++)
501                 pos = pos * this->bounds [i].length + ind [i] - 
502                         this->bounds [i].lower_bound;
503
504         ves_icall_System_Array_SetValueImpl (this, value, pos);
505 }
506
507 static MonoArray *
508 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
509 {
510         MonoClass *aklass;
511         MonoArray *array;
512         guint32 *sizes, i;
513         gboolean bounded = FALSE;
514
515         MONO_ARCH_SAVE_REGS;
516
517         MONO_CHECK_ARG_NULL (type);
518         MONO_CHECK_ARG_NULL (lengths);
519
520         MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
521         if (bounds)
522                 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
523
524         for (i = 0; i < mono_array_length (lengths); i++)
525                 if (mono_array_get (lengths, gint32, i) < 0)
526                         mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
527
528         if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
529                 /* vectors are not the same as one dimensional arrays with no-zero bounds */
530                 bounded = TRUE;
531         else
532                 bounded = FALSE;
533
534         aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
535
536         sizes = alloca (aklass->rank * sizeof(guint32) * 2);
537         for (i = 0; i < aklass->rank; ++i) {
538                 sizes [i] = mono_array_get (lengths, guint32, i);
539                 if (bounds)
540                         sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
541                 else
542                         sizes [i + aklass->rank] = 0;
543         }
544
545         array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
546
547         return array;
548 }
549
550 static gint32 
551 ves_icall_System_Array_GetRank (MonoObject *this)
552 {
553         MONO_ARCH_SAVE_REGS;
554
555         return this->vtable->klass->rank;
556 }
557
558 static gint32
559 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
560 {
561         gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
562
563         MONO_ARCH_SAVE_REGS;
564
565         if ((dimension < 0) || (dimension >= rank))
566                 mono_raise_exception (mono_get_exception_index_out_of_range ());
567         
568         if (this->bounds == NULL)
569                 return this->max_length;
570         
571         return this->bounds [dimension].length;
572 }
573
574 static gint32
575 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
576 {
577         gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
578
579         MONO_ARCH_SAVE_REGS;
580
581         if ((dimension < 0) || (dimension >= rank))
582                 mono_raise_exception (mono_get_exception_index_out_of_range ());
583         
584         if (this->bounds == NULL)
585                 return 0;
586         
587         return this->bounds [dimension].lower_bound;
588 }
589
590 static void
591 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
592 {
593         int sz = mono_array_element_size (mono_object_class (arr));
594         memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
595 }
596
597 static gboolean
598 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
599 {
600         int element_size;
601         void * dest_addr;
602         void * source_addr;
603         MonoClass *src_class;
604         MonoClass *dest_class;
605         int i;
606
607         MONO_ARCH_SAVE_REGS;
608
609         if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
610                 return FALSE;
611
612         if (source->bounds || dest->bounds)
613                 return FALSE;
614
615         if ((dest_idx + length > mono_array_length (dest)) ||
616                 (source_idx + length > mono_array_length (source)))
617                 return FALSE;
618
619         src_class = source->obj.vtable->klass->element_class;
620         dest_class = dest->obj.vtable->klass->element_class;
621
622         /*
623          * Handle common cases.
624          */
625
626         /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
627         if (src_class == mono_defaults.object_class && dest_class->valuetype) {
628                 int has_refs = dest_class->has_references;
629                 for (i = source_idx; i < source_idx + length; ++i) {
630                         MonoObject *elem = mono_array_get (source, MonoObject*, i);
631                         if (elem && !mono_object_isinst (elem, dest_class))
632                                 return FALSE;
633                 }
634
635                 element_size = mono_array_element_size (dest->obj.vtable->klass);
636                 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
637                 for (i = 0; i < length; ++i) {
638                         MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
639                         void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
640                         if (!elem)
641                                 continue;
642                         if (has_refs)
643                                 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
644                         else
645                                 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
646                 }
647                 return TRUE;
648         }
649
650         /* Check if we're copying a char[] <==> (u)short[] */
651         if (src_class != dest_class) {
652                 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
653                         return FALSE;
654
655                 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
656                         ;
657                 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
658                 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
659                         for (i = source_idx; i < source_idx + length; ++i) {
660                                 MonoObject *elem = mono_array_get (source, MonoObject*, i);
661                                 if (elem && !mono_object_isinst (elem, dest_class))
662                                         return FALSE;
663                         }
664                 else
665                         return FALSE;
666         }
667
668         if (dest_class->valuetype) {
669                 element_size = mono_array_element_size (source->obj.vtable->klass);
670                 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
671                 if (dest_class->has_references) {
672                         mono_value_copy_array (dest, dest_idx, source_addr, length);
673                 } else {
674                         dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
675                         memmove (dest_addr, source_addr, element_size * length);
676                 }
677         } else {
678                 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
679         }
680
681         return TRUE;
682 }
683
684 static void
685 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
686 {
687         MonoClass *ac;
688         MonoArray *ao;
689         gint32 esize;
690         gpointer *ea;
691
692         MONO_ARCH_SAVE_REGS;
693
694         ao = (MonoArray *)this;
695         ac = (MonoClass *)ao->obj.vtable->klass;
696
697         esize = mono_array_element_size (ac);
698         ea = (gpointer*)((char*)ao->vector + (pos * esize));
699
700         memcpy (value, ea, esize);
701 }
702
703 static void
704 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
705 {
706         MonoClass *ac;
707         MonoArray *ao;
708         gint32 esize;
709         gpointer *ea;
710
711         MONO_ARCH_SAVE_REGS;
712
713         ao = (MonoArray *)this;
714         ac = (MonoClass *)ao->obj.vtable->klass;
715
716         esize = mono_array_element_size (ac);
717         ea = (gpointer*)((char*)ao->vector + (pos * esize));
718
719         memcpy (ea, value, esize);
720 }
721
722 static void
723 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
724 {
725         MonoClass *klass = array->obj.vtable->klass;
726         guint32 size = mono_array_element_size (klass);
727         MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
728         int align;
729
730         if (MONO_TYPE_IS_REFERENCE (type) ||
731                         (type->type == MONO_TYPE_VALUETYPE &&
732                                 (!mono_type_get_class (type) ||
733                                 mono_type_get_class (type)->has_references))) {
734                 MonoException *exc = mono_get_exception_argument("array",
735                         "Cannot initialize array containing references");
736                 mono_raise_exception (exc);
737         }
738
739         if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
740                 MonoException *exc = mono_get_exception_argument("field_handle",
741                         "Field doesn't have an RVA");
742                 mono_raise_exception (exc);
743         }
744
745         size *= array->max_length;
746
747         if (size > mono_type_size (field_handle->type, &align)) {
748                 MonoException *exc = mono_get_exception_argument("field_handle",
749                         "Field not large enough to fill array");
750                 mono_raise_exception (exc);
751         }
752
753 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
754 #define SWAP(n) {\
755         guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
756         guint ## n *src = (guint ## n *) field_handle->data; \
757         guint ## n *end = (guint ## n *)((char*)src + size); \
758 \
759         for (; src < end; data++, src++) { \
760                 *data = read ## n (src); \
761         } \
762 }
763
764         /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
765
766         switch (type->type) {
767         case MONO_TYPE_CHAR:
768         case MONO_TYPE_I2:
769         case MONO_TYPE_U2:
770                 SWAP (16);
771                 break;
772         case MONO_TYPE_I4:
773         case MONO_TYPE_U4:
774         case MONO_TYPE_R4:
775                 SWAP (32);
776                 break;
777         case MONO_TYPE_I8:
778         case MONO_TYPE_U8:
779         case MONO_TYPE_R8:
780                 SWAP (64);
781                 break;
782         default:
783                 memcpy (mono_array_addr (array, char, 0), field_handle->data, size);
784                 break;
785         }
786 #else
787         memcpy (mono_array_addr (array, char, 0), field_handle->data, size);
788 #ifdef ARM_FPU_FPA
789         if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
790                 gint i;
791                 double tmp;
792                 double *data = (double*)mono_array_addr (array, double, 0);
793
794                 for (i = 0; i < size; i++, data++) {
795                         readr8 (data, &tmp);
796                         *data = tmp;
797                 }
798         }
799 #endif
800 #endif
801 }
802
803 static gint
804 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
805 {
806         MONO_ARCH_SAVE_REGS;
807
808         return offsetof (MonoString, chars);
809 }
810
811 static MonoObject *
812 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
813 {
814         MONO_ARCH_SAVE_REGS;
815
816         if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
817                 return obj;
818         else
819                 return mono_object_clone (obj);
820 }
821
822 static void
823 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
824 {
825         MonoClass *klass;
826
827         MONO_ARCH_SAVE_REGS;
828
829         MONO_CHECK_ARG_NULL (handle);
830
831         klass = mono_class_from_mono_type (handle);
832         MONO_CHECK_ARG (handle, klass);
833
834         /* This will call the type constructor */
835         mono_runtime_class_init (mono_class_vtable (mono_domain_get (), klass));
836 }
837
838 static void
839 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
840 {
841         MONO_ARCH_SAVE_REGS;
842
843         mono_image_check_for_module_cctor (image);
844         if (image->has_module_cctor) {
845                 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
846                 mono_runtime_class_init (mono_class_vtable (mono_domain_get (), module_klass));
847         }
848 }
849
850 static MonoObject *
851 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
852 {
853         MONO_ARCH_SAVE_REGS;
854
855         return mono_object_clone (this);
856 }
857
858 static gint32
859 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
860 {
861         MonoClass *klass;
862         MonoObject **values = NULL;
863         MonoObject *o;
864         int count = 0;
865         gint32 result = 0;
866         MonoClassField* field;
867         gpointer iter;
868
869         MONO_ARCH_SAVE_REGS;
870
871         klass = mono_object_class (this);
872
873         if (mono_class_num_fields (klass) == 0)
874                 return mono_object_hash (this);
875
876         /*
877          * Compute the starting value of the hashcode for fields of primitive
878          * types, and return the remaining fields in an array to the managed side.
879          * This way, we can avoid costly reflection operations in managed code.
880          */
881         iter = NULL;
882         while ((field = mono_class_get_fields (klass, &iter))) {
883                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
884                         continue;
885                 if (mono_field_is_deleted (field))
886                         continue;
887                 /* FIXME: Add more types */
888                 switch (field->type->type) {
889                 case MONO_TYPE_I4:
890                         result ^= *(gint32*)((guint8*)this + field->offset);
891                         break;
892                 case MONO_TYPE_STRING: {
893                         MonoString *s;
894                         s = *(MonoString**)((guint8*)this + field->offset);
895                         if (s != NULL)
896                                 result ^= mono_string_hash (s);
897                         break;
898                 }
899                 default:
900                         if (!values)
901                                 values = g_newa (MonoObject*, mono_class_num_fields (klass));
902                         o = mono_field_get_value_object (mono_object_domain (this), field, this);
903                         values [count++] = o;
904                 }
905         }
906
907         if (values) {
908                 int i;
909                 *fields = mono_array_new (mono_domain_get (), mono_defaults.object_class, count);
910                 for (i = 0; i < count; ++i)
911                         mono_array_setref (*fields, i, values [i]);
912         } else {
913                 *fields = NULL;
914         }
915         return result;
916 }
917
918 static MonoBoolean
919 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
920 {
921         MonoClass *klass;
922         MonoObject **values = NULL;
923         MonoObject *o;
924         MonoClassField* field;
925         gpointer iter;
926         int count = 0;
927
928         MONO_ARCH_SAVE_REGS;
929
930         MONO_CHECK_ARG_NULL (that);
931
932         if (this->vtable != that->vtable)
933                 return FALSE;
934
935         klass = mono_object_class (this);
936
937         /*
938          * Do the comparison for fields of primitive type and return a result if
939          * possible. Otherwise, return the remaining fields in an array to the 
940          * managed side. This way, we can avoid costly reflection operations in 
941          * managed code.
942          */
943         *fields = NULL;
944         iter = NULL;
945         while ((field = mono_class_get_fields (klass, &iter))) {
946                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
947                         continue;
948                 if (mono_field_is_deleted (field))
949                         continue;
950                 /* FIXME: Add more types */
951                 switch (field->type->type) {
952                 case MONO_TYPE_I4:
953                         if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
954                                 return FALSE;
955                         break;
956                 case MONO_TYPE_STRING: {
957                         MonoString *s1, *s2;
958                         guint32 s1len, s2len;
959                         s1 = *(MonoString**)((guint8*)this + field->offset);
960                         s2 = *(MonoString**)((guint8*)that + field->offset);
961                         if (s1 == s2)
962                                 break;
963                         if ((s1 == NULL) || (s2 == NULL))
964                                 return FALSE;
965                         s1len = mono_string_length (s1);
966                         s2len = mono_string_length (s2);
967                         if (s1len != s2len)
968                                 return FALSE;
969
970                         if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
971                                 return FALSE;
972                         break;
973                 }
974                 default:
975                         if (!values)
976                                 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
977                         o = mono_field_get_value_object (mono_object_domain (this), field, this);
978                         values [count++] = o;
979                         o = mono_field_get_value_object (mono_object_domain (this), field, that);
980                         values [count++] = o;
981                 }
982         }
983
984         if (values) {
985                 int i;
986                 *fields = mono_array_new (mono_domain_get (), mono_defaults.object_class, count);
987                 for (i = 0; i < count; ++i)
988                         mono_array_setref (*fields, i, values [i]);
989                 return FALSE;
990         } else {
991                 return TRUE;
992         }
993 }
994
995 static MonoReflectionType *
996 ves_icall_System_Object_GetType (MonoObject *obj)
997 {
998         MONO_ARCH_SAVE_REGS;
999
1000         if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1001                 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1002         else
1003                 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1004 }
1005
1006 static void
1007 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1008 {
1009         MONO_ARCH_SAVE_REGS;
1010
1011         mtype->type = &obj->vtable->klass->byval_arg;
1012         g_assert (mtype->type->type);
1013 }
1014
1015 static gint32
1016 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
1017 {
1018         MONO_ARCH_SAVE_REGS;
1019         
1020         MONO_CHECK_ARG_NULL (obj);
1021         
1022         return mono_image_create_token (mb->dynamic_image, obj, TRUE);
1023 }
1024
1025 static gint32
1026 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1027                                         MonoReflectionMethod *method,
1028                                         MonoArray *opt_param_types)
1029 {
1030         MONO_ARCH_SAVE_REGS;
1031
1032         MONO_CHECK_ARG_NULL (method);
1033         
1034         return mono_image_create_method_token (
1035                 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1036 }
1037
1038 static void
1039 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1040 {
1041         MONO_ARCH_SAVE_REGS;
1042
1043         mono_image_create_pefile (mb, file);
1044 }
1045
1046 static void
1047 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1048 {
1049         MONO_ARCH_SAVE_REGS;
1050
1051         mono_image_build_metadata (mb);
1052 }
1053
1054 static void
1055 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1056 {
1057         MONO_ARCH_SAVE_REGS;
1058
1059         mono_image_register_token (mb->dynamic_image, token, obj);
1060 }
1061
1062 static gboolean
1063 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1064 {
1065         MonoMethod **dest = data;
1066
1067         /* skip unmanaged frames */
1068         if (!managed)
1069                 return FALSE;
1070
1071         if (m == *dest) {
1072                 *dest = NULL;
1073                 return FALSE;
1074         }
1075         if (!(*dest)) {
1076                 *dest = m;
1077                 return TRUE;
1078         }
1079         return FALSE;
1080 }
1081
1082 static MonoReflectionType *
1083 type_from_name (const char *str, MonoBoolean ignoreCase)
1084 {
1085         MonoType *type = NULL;
1086         MonoAssembly *assembly = NULL;
1087         MonoTypeNameParse info;
1088         char *temp_str = g_strdup (str);
1089         gboolean type_resolve = FALSE;
1090
1091         MONO_ARCH_SAVE_REGS;
1092
1093         /* mono_reflection_parse_type() mangles the string */
1094         if (!mono_reflection_parse_type (temp_str, &info)) {
1095                 mono_reflection_free_type_info (&info);
1096                 g_free (temp_str);
1097                 return NULL;
1098         }
1099
1100         if (info.assembly.name) {
1101                 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1102         } else {
1103                 MonoMethod *m = mono_method_get_last_managed ();
1104                 MonoMethod *dest = m;
1105
1106                 mono_stack_walk_no_il (get_caller, &dest);
1107                 if (!dest)
1108                         dest = m;
1109
1110                 /*
1111                  * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1112                  *        causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1113                  *        to crash.  This only seems to happen in some strange remoting
1114                  *        scenarios and I was unable to figure out what's happening there.
1115                  *        Dec 10, 2005 - Martin.
1116                  */
1117
1118                 if (dest)
1119                         assembly = dest->klass->image->assembly;
1120                 else {
1121                         g_warning (G_STRLOC);
1122                 }
1123         }
1124
1125         if (assembly)
1126                 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1127         
1128         if (!info.assembly.name && !type) /* try mscorlib */
1129                 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1130
1131         mono_reflection_free_type_info (&info);
1132         g_free (temp_str);
1133
1134         if (!type) 
1135                 return NULL;
1136
1137         return mono_type_get_object (mono_domain_get (), type);
1138 }
1139
1140 #ifdef UNUSED
1141 MonoReflectionType *
1142 mono_type_get (const char *str)
1143 {
1144         char *copy = g_strdup (str);
1145         MonoReflectionType *type = type_from_name (copy, FALSE);
1146
1147         g_free (copy);
1148         return type;
1149 }
1150 #endif
1151
1152 static MonoReflectionType*
1153 ves_icall_type_from_name (MonoString *name,
1154                           MonoBoolean throwOnError,
1155                           MonoBoolean ignoreCase)
1156 {
1157         char *str = mono_string_to_utf8 (name);
1158         MonoReflectionType *type;
1159
1160         type = type_from_name (str, ignoreCase);
1161         g_free (str);
1162         if (type == NULL){
1163                 MonoException *e = NULL;
1164                 
1165                 if (throwOnError)
1166                         e = mono_get_exception_type_load (name, NULL);
1167
1168                 mono_loader_clear_error ();
1169                 if (e != NULL)
1170                         mono_raise_exception (e);
1171         }
1172         
1173         return type;
1174 }
1175
1176
1177 static MonoReflectionType*
1178 ves_icall_type_from_handle (MonoType *handle)
1179 {
1180         MonoDomain *domain = mono_domain_get (); 
1181         MonoClass *klass = mono_class_from_mono_type (handle);
1182
1183         MONO_ARCH_SAVE_REGS;
1184
1185         mono_class_init (klass);
1186         return mono_type_get_object (domain, handle);
1187 }
1188
1189 static MonoBoolean
1190 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1191 {
1192         MONO_ARCH_SAVE_REGS;
1193
1194         if (c && type->type && c->type)
1195                 return mono_metadata_type_equal (type->type, c->type);
1196         else
1197                 return FALSE;
1198 }
1199
1200 /* System.TypeCode */
1201 typedef enum {
1202         TYPECODE_EMPTY,
1203         TYPECODE_OBJECT,
1204         TYPECODE_DBNULL,
1205         TYPECODE_BOOLEAN,
1206         TYPECODE_CHAR,
1207         TYPECODE_SBYTE,
1208         TYPECODE_BYTE,
1209         TYPECODE_INT16,
1210         TYPECODE_UINT16,
1211         TYPECODE_INT32,
1212         TYPECODE_UINT32,
1213         TYPECODE_INT64,
1214         TYPECODE_UINT64,
1215         TYPECODE_SINGLE,
1216         TYPECODE_DOUBLE,
1217         TYPECODE_DECIMAL,
1218         TYPECODE_DATETIME,
1219         TYPECODE_STRING = 18
1220 } TypeCode;
1221
1222 static guint32
1223 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1224 {
1225         int t = type->type->type;
1226
1227         MONO_ARCH_SAVE_REGS;
1228
1229         if (type->type->byref)
1230                 return TYPECODE_OBJECT;
1231
1232 handle_enum:
1233         switch (t) {
1234         case MONO_TYPE_VOID:
1235                 return TYPECODE_OBJECT;
1236         case MONO_TYPE_BOOLEAN:
1237                 return TYPECODE_BOOLEAN;
1238         case MONO_TYPE_U1:
1239                 return TYPECODE_BYTE;
1240         case MONO_TYPE_I1:
1241                 return TYPECODE_SBYTE;
1242         case MONO_TYPE_U2:
1243                 return TYPECODE_UINT16;
1244         case MONO_TYPE_I2:
1245                 return TYPECODE_INT16;
1246         case MONO_TYPE_CHAR:
1247                 return TYPECODE_CHAR;
1248         case MONO_TYPE_PTR:
1249         case MONO_TYPE_U:
1250         case MONO_TYPE_I:
1251                 return TYPECODE_OBJECT;
1252         case MONO_TYPE_U4:
1253                 return TYPECODE_UINT32;
1254         case MONO_TYPE_I4:
1255                 return TYPECODE_INT32;
1256         case MONO_TYPE_U8:
1257                 return TYPECODE_UINT64;
1258         case MONO_TYPE_I8:
1259                 return TYPECODE_INT64;
1260         case MONO_TYPE_R4:
1261                 return TYPECODE_SINGLE;
1262         case MONO_TYPE_R8:
1263                 return TYPECODE_DOUBLE;
1264         case MONO_TYPE_VALUETYPE:
1265                 if (type->type->data.klass->enumtype) {
1266                         t = type->type->data.klass->enum_basetype->type;
1267                         goto handle_enum;
1268                 } else {
1269                         MonoClass *k =  type->type->data.klass;
1270                         if (strcmp (k->name_space, "System") == 0) {
1271                                 if (strcmp (k->name, "Decimal") == 0)
1272                                         return TYPECODE_DECIMAL;
1273                                 else if (strcmp (k->name, "DateTime") == 0)
1274                                         return TYPECODE_DATETIME;
1275                         }
1276                 }
1277                 return TYPECODE_OBJECT;
1278         case MONO_TYPE_STRING:
1279                 return TYPECODE_STRING;
1280         case MONO_TYPE_SZARRAY:
1281         case MONO_TYPE_ARRAY:
1282         case MONO_TYPE_OBJECT:
1283         case MONO_TYPE_VAR:
1284         case MONO_TYPE_MVAR:
1285         case MONO_TYPE_TYPEDBYREF:
1286                 return TYPECODE_OBJECT;
1287         case MONO_TYPE_CLASS:
1288                 {
1289                         MonoClass *k =  type->type->data.klass;
1290                         if (strcmp (k->name_space, "System") == 0) {
1291                                 if (strcmp (k->name, "DBNull") == 0)
1292                                         return TYPECODE_DBNULL;
1293                         }
1294                 }
1295                 return TYPECODE_OBJECT;
1296         case MONO_TYPE_GENERICINST:
1297                 return TYPECODE_OBJECT;
1298         default:
1299                 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1300         }
1301         return 0;
1302 }
1303
1304 static guint32
1305 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1306 {
1307         MonoDomain *domain; 
1308         MonoClass *klass;
1309         MonoClass *klassc;
1310
1311         MONO_ARCH_SAVE_REGS;
1312
1313         g_assert (type != NULL);
1314         
1315         domain = ((MonoObject *)type)->vtable->domain;
1316
1317         if (!c) /* FIXME: dont know what do do here */
1318                 return 0;
1319
1320         klass = mono_class_from_mono_type (type->type);
1321         klassc = mono_class_from_mono_type (c->type);
1322
1323         if (type->type->byref)
1324                 return klassc == mono_defaults.object_class;
1325
1326         return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1327 }
1328
1329 static guint32
1330 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1331 {
1332         MonoDomain *domain; 
1333         MonoClass *klass;
1334         MonoClass *klassc;
1335
1336         MONO_ARCH_SAVE_REGS;
1337
1338         g_assert (type != NULL);
1339         
1340         domain = ((MonoObject *)type)->vtable->domain;
1341
1342         klass = mono_class_from_mono_type (type->type);
1343         klassc = mono_class_from_mono_type (c->type);
1344
1345         if (type->type->byref && !c->type->byref)
1346                 return FALSE;
1347
1348         return mono_class_is_assignable_from (klass, klassc);
1349 }
1350
1351 static guint32
1352 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1353 {
1354         MonoClass *klass = mono_class_from_mono_type (type->type);
1355         return mono_object_isinst (obj, klass) != NULL;
1356 }
1357
1358 static guint32
1359 ves_icall_get_attributes (MonoReflectionType *type)
1360 {
1361         MonoClass *klass = mono_class_from_mono_type (type->type);
1362
1363         MONO_ARCH_SAVE_REGS;
1364
1365         return klass->flags;
1366 }
1367
1368 static MonoReflectionMarshal*
1369 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1370 {
1371         MonoClass *klass = field->field->parent;
1372         MonoMarshalType *info;
1373         int i;
1374
1375         if (klass->generic_container ||
1376             (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1377                 return NULL;
1378
1379         info = mono_marshal_load_type_info (klass);
1380
1381         for (i = 0; i < info->num_fields; ++i) {
1382                 if (info->fields [i].field == field->field) {
1383                         if (!info->fields [i].mspec)
1384                                 return NULL;
1385                         else
1386                                 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1387                 }
1388         }
1389
1390         return NULL;
1391 }
1392
1393 static MonoReflectionField*
1394 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoClass *klass)
1395 {
1396         g_assert (handle);
1397
1398         if (!klass)
1399                 klass = handle->parent;
1400
1401         /* FIXME: check that handle is a field of klass or of a parent: return null
1402          * and throw the exception in managed code.
1403          */
1404         return mono_field_get_object (mono_domain_get (), klass, handle);
1405 }
1406
1407 static MonoReflectionField*
1408 ves_icall_System_Reflection_FieldInfo_internal_from_handle (MonoClassField *handle)
1409 {
1410         MONO_ARCH_SAVE_REGS;
1411
1412         g_assert (handle);
1413
1414         return mono_field_get_object (mono_domain_get (), handle->parent, handle);
1415 }
1416
1417 static MonoArray*
1418 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1419 {
1420         MonoType *type = field->field->type;
1421
1422         return type_array_from_modifiers (field->field->parent->image, type, optional);
1423 }
1424
1425 static void
1426 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1427 {
1428         MonoDomain *domain = mono_domain_get ();
1429         MonoMethodSignature* sig;
1430         MONO_ARCH_SAVE_REGS;
1431
1432         sig = mono_method_signature (method);
1433         if (!sig) {
1434                 g_assert (mono_loader_get_last_error ());
1435                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1436         }
1437         
1438         info->parent = mono_type_get_object (domain, &method->klass->byval_arg);
1439         info->ret = mono_type_get_object (domain, sig->ret);
1440         info->attrs = method->flags;
1441         info->implattrs = method->iflags;
1442         if (sig->call_convention == MONO_CALL_DEFAULT)
1443                 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1444         else {
1445                 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1446                         info->callconv = 2;
1447                 else
1448                         info->callconv = 1;
1449         }
1450         info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6); 
1451 }
1452
1453 static MonoArray*
1454 ves_icall_get_parameter_info (MonoMethod *method)
1455 {
1456         MonoDomain *domain = mono_domain_get (); 
1457
1458         return mono_param_get_objects (domain, method);
1459 }
1460
1461 static MonoReflectionMarshal*
1462 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1463 {
1464         MonoDomain *domain = mono_domain_get (); 
1465         MonoReflectionMarshal* res = NULL;
1466         MonoMarshalSpec **mspecs;
1467         int i;
1468
1469         mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1470         mono_method_get_marshal_info (method, mspecs);
1471
1472         if (mspecs [0])
1473                 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1474                 
1475         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1476                 if (mspecs [i])
1477                         mono_metadata_free_marshal_spec (mspecs [i]);
1478         g_free (mspecs);
1479
1480         return res;
1481 }
1482
1483 static gint32
1484 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1485 {
1486         return field->field->offset - sizeof (MonoObject);
1487 }
1488
1489 static MonoReflectionType*
1490 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1491 {
1492         MonoClass *parent;
1493         MONO_ARCH_SAVE_REGS;
1494
1495         parent = declaring? field->field->parent: field->klass;
1496
1497         return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1498 }
1499
1500 static MonoObject *
1501 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1502 {       
1503         MonoObject *o;
1504         MonoClassField *cf = field->field;
1505         MonoClass *klass;
1506         MonoVTable *vtable;
1507         MonoType *t;
1508         MonoDomain *domain = mono_object_domain (field); 
1509         gchar *v;
1510         gboolean is_static = FALSE;
1511         gboolean is_ref = FALSE;
1512
1513         MONO_ARCH_SAVE_REGS;
1514
1515         if (field->klass->image->assembly->ref_only)
1516                 mono_raise_exception (mono_get_exception_invalid_operation (
1517                                         "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1518         
1519         mono_class_init (field->klass);
1520
1521         if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC)
1522                 is_static = TRUE;
1523
1524         if (obj && !is_static) {
1525                 /* Check that the field belongs to the object */
1526                 gboolean found = FALSE;
1527                 MonoClass *k;
1528
1529                 for (k = obj->vtable->klass; k; k = k->parent) {
1530                         if (k == cf->parent) {
1531                                 found = TRUE;
1532                                 break;
1533                         }
1534                 }
1535
1536                 if (!found) {
1537                         char *msg = g_strdup_printf ("Field '%s' defined on type '%s' is not a field on the target object which is of type '%s'.", cf->name, cf->parent->name, obj->vtable->klass->name);
1538                         MonoException *ex = mono_get_exception_argument (NULL, msg);
1539                         g_free (msg);
1540                         mono_raise_exception (ex);
1541                 }
1542         }
1543
1544         t = mono_type_get_underlying_type (cf->type);
1545         switch (t->type) {
1546         case MONO_TYPE_STRING:
1547         case MONO_TYPE_OBJECT:
1548         case MONO_TYPE_CLASS:
1549         case MONO_TYPE_ARRAY:
1550         case MONO_TYPE_SZARRAY:
1551                 is_ref = TRUE;
1552                 break;
1553         case MONO_TYPE_U1:
1554         case MONO_TYPE_I1:
1555         case MONO_TYPE_BOOLEAN:
1556         case MONO_TYPE_U2:
1557         case MONO_TYPE_I2:
1558         case MONO_TYPE_CHAR:
1559         case MONO_TYPE_U:
1560         case MONO_TYPE_I:
1561         case MONO_TYPE_U4:
1562         case MONO_TYPE_I4:
1563         case MONO_TYPE_R4:
1564         case MONO_TYPE_U8:
1565         case MONO_TYPE_I8:
1566         case MONO_TYPE_R8:
1567         case MONO_TYPE_VALUETYPE:
1568                 is_ref = t->byref;
1569                 break;
1570         case MONO_TYPE_GENERICINST:
1571                 if (mono_type_generic_inst_is_valuetype (t)) {
1572                         is_ref = t->byref;
1573                 } else {
1574                         is_ref = TRUE;
1575                 }
1576                 break;
1577         default:
1578                 g_error ("type 0x%x not handled in "
1579                          "ves_icall_Monofield_GetValue", t->type);
1580                 return NULL;
1581         }
1582
1583         vtable = NULL;
1584         if (is_static) {
1585                 vtable = mono_class_vtable (domain, cf->parent);
1586                 if (!vtable->initialized && !(cf->type->attrs & FIELD_ATTRIBUTE_LITERAL))
1587                         mono_runtime_class_init (vtable);
1588         }
1589         
1590         if (is_ref) {
1591                 if (is_static) {
1592                         mono_field_static_get_value (vtable, cf, &o);
1593                 } else {
1594                         mono_field_get_value (obj, cf, &o);
1595                 }
1596                 return o;
1597         }
1598
1599         if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1600                 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1601                 guint8 *buf;
1602
1603                 /* Convert the Nullable structure into a boxed vtype */
1604                 if (is_static)
1605                         buf = (guint8*)vtable->data + cf->offset;
1606                 else
1607                         buf = (guint8*)obj + cf->offset;
1608
1609                 return mono_nullable_box (buf, nklass);
1610         }
1611
1612         /* boxed value type */
1613         klass = mono_class_from_mono_type (cf->type);
1614         o = mono_object_new (domain, klass);
1615         v = ((gchar *) o) + sizeof (MonoObject);
1616         if (is_static) {
1617                 mono_field_static_get_value (vtable, cf, v);
1618         } else {
1619                 mono_field_get_value (obj, cf, v);
1620         }
1621
1622         return o;
1623 }
1624
1625 static void
1626 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1627 {
1628         MonoClassField *cf = field->field;
1629         gchar *v;
1630
1631         MONO_ARCH_SAVE_REGS;
1632
1633         if (field->klass->image->assembly->ref_only)
1634                 mono_raise_exception (mono_get_exception_invalid_operation (
1635                                         "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1636
1637         v = (gchar *) value;
1638         if (!cf->type->byref) {
1639                 switch (cf->type->type) {
1640                 case MONO_TYPE_U1:
1641                 case MONO_TYPE_I1:
1642                 case MONO_TYPE_BOOLEAN:
1643                 case MONO_TYPE_U2:
1644                 case MONO_TYPE_I2:
1645                 case MONO_TYPE_CHAR:
1646                 case MONO_TYPE_U:
1647                 case MONO_TYPE_I:
1648                 case MONO_TYPE_U4:
1649                 case MONO_TYPE_I4:
1650                 case MONO_TYPE_R4:
1651                 case MONO_TYPE_U8:
1652                 case MONO_TYPE_I8:
1653                 case MONO_TYPE_R8:
1654                 case MONO_TYPE_VALUETYPE:
1655                         if (v != NULL)
1656                                 v += sizeof (MonoObject);
1657                         break;
1658                 case MONO_TYPE_STRING:
1659                 case MONO_TYPE_OBJECT:
1660                 case MONO_TYPE_CLASS:
1661                 case MONO_TYPE_ARRAY:
1662                 case MONO_TYPE_SZARRAY:
1663                         /* Do nothing */
1664                         break;
1665                 case MONO_TYPE_GENERICINST: {
1666                         MonoGenericClass *gclass = cf->type->data.generic_class;
1667                         g_assert (!gclass->context.class_inst->is_open);
1668
1669                         if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1670                                 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1671                                 MonoObject *nullable;
1672
1673                                 /* 
1674                                  * Convert the boxed vtype into a Nullable structure.
1675                                  * This is complicated by the fact that Nullables have
1676                                  * a variable structure.
1677                                  */
1678                                 nullable = mono_object_new (mono_domain_get (), nklass);
1679
1680                                 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1681
1682                                 v = mono_object_unbox (nullable);
1683                         }
1684                         else 
1685                                 if (gclass->container_class->valuetype && (v != NULL))
1686                                         v += sizeof (MonoObject);
1687                         break;
1688                 }
1689                 default:
1690                         g_error ("type 0x%x not handled in "
1691                                  "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1692                         return;
1693                 }
1694         }
1695
1696         if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1697                 MonoVTable *vtable = mono_class_vtable (mono_object_domain (field), cf->parent);
1698                 if (!vtable->initialized)
1699                         mono_runtime_class_init (vtable);
1700                 mono_field_static_set_value (vtable, cf, v);
1701         } else {
1702                 mono_field_set_value (obj, cf, v);
1703         }
1704 }
1705
1706 static MonoObject *
1707 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1708 {       
1709         MonoObject *o = NULL;
1710         MonoClassField *field = this->field;
1711         MonoClass *klass;
1712         MonoDomain *domain = mono_object_domain (this); 
1713         gchar *v;
1714         MonoTypeEnum def_type;
1715         const char *def_value;
1716
1717         MONO_ARCH_SAVE_REGS;
1718         
1719         mono_class_init (field->parent);
1720
1721         if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1722                 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1723
1724         if (field->parent->image->dynamic) {
1725                 /* FIXME: */
1726                 g_assert_not_reached ();
1727         }
1728
1729         def_value = mono_class_get_field_default_value (field, &def_type);
1730
1731         switch (def_type) {
1732         case MONO_TYPE_U1:
1733         case MONO_TYPE_I1:
1734         case MONO_TYPE_BOOLEAN:
1735         case MONO_TYPE_U2:
1736         case MONO_TYPE_I2:
1737         case MONO_TYPE_CHAR:
1738         case MONO_TYPE_U:
1739         case MONO_TYPE_I:
1740         case MONO_TYPE_U4:
1741         case MONO_TYPE_I4:
1742         case MONO_TYPE_R4:
1743         case MONO_TYPE_U8:
1744         case MONO_TYPE_I8:
1745         case MONO_TYPE_R8: {
1746                 MonoType *t;
1747
1748                 /* boxed value type */
1749                 t = g_new0 (MonoType, 1);
1750                 t->type = def_type;
1751                 klass = mono_class_from_mono_type (t);
1752                 g_free (t);
1753                 o = mono_object_new (domain, klass);
1754                 v = ((gchar *) o) + sizeof (MonoObject);
1755                 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1756                 break;
1757         }
1758         case MONO_TYPE_STRING:
1759         case MONO_TYPE_CLASS:
1760                 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1761                 break;
1762         default:
1763                 g_assert_not_reached ();
1764         }
1765
1766         return o;
1767 }
1768
1769 static MonoReflectionType*
1770 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1771 {
1772         MonoMethod *method = rmethod->method.method;
1773
1774         return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1775 }
1776
1777 /* From MonoProperty.cs */
1778 typedef enum {
1779         PInfo_Attributes = 1,
1780         PInfo_GetMethod  = 1 << 1,
1781         PInfo_SetMethod  = 1 << 2,
1782         PInfo_ReflectedType = 1 << 3,
1783         PInfo_DeclaringType = 1 << 4,
1784         PInfo_Name = 1 << 5
1785 } PInfo;
1786
1787 static void
1788 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1789 {
1790         MonoDomain *domain = mono_object_domain (property); 
1791
1792         MONO_ARCH_SAVE_REGS;
1793
1794         if ((req_info & PInfo_ReflectedType) != 0)
1795                 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1796         else if ((req_info & PInfo_DeclaringType) != 0)
1797                 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
1798
1799         if ((req_info & PInfo_Name) != 0)
1800                 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1801
1802         if ((req_info & PInfo_Attributes) != 0)
1803                 info->attrs = property->property->attrs;
1804
1805         if ((req_info & PInfo_GetMethod) != 0)
1806                 MONO_STRUCT_SETREF (info, get, property->property->get ?
1807                                                         mono_method_get_object (domain, property->property->get, property->klass): NULL);
1808         
1809         if ((req_info & PInfo_SetMethod) != 0)
1810                 MONO_STRUCT_SETREF (info, set, property->property->set ?
1811                                                         mono_method_get_object (domain, property->property->set, property->klass): NULL);
1812         /* 
1813          * There may be other methods defined for properties, though, it seems they are not exposed 
1814          * in the reflection API 
1815          */
1816 }
1817
1818 static void
1819 ves_icall_get_event_info (MonoReflectionEvent *event, MonoEventInfo *info)
1820 {
1821         MonoDomain *domain = mono_object_domain (event); 
1822
1823         MONO_ARCH_SAVE_REGS;
1824
1825         info->reflected_type = mono_type_get_object (domain, &event->klass->byval_arg);
1826         info->declaring_type = mono_type_get_object (domain, &event->event->parent->byval_arg);
1827
1828         info->name = mono_string_new (domain, event->event->name);
1829         info->attrs = event->event->attrs;
1830         info->add_method = event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL;
1831         info->remove_method = event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL;
1832         info->raise_method = event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL;
1833
1834         if (event->event->other) {
1835                 int i, n = 0;
1836                 while (event->event->other [n])
1837                         n++;
1838                 info->other_methods = mono_array_new (domain, mono_defaults.method_info_class, n);
1839
1840                 for (i = 0; i < n; i++)
1841                         mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
1842         }               
1843 }
1844
1845 static MonoArray*
1846 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
1847 {
1848         MonoDomain *domain = mono_object_domain (type); 
1849         MonoArray *intf;
1850         GPtrArray *ifaces = NULL;
1851         int i;
1852         MonoClass *class = mono_class_from_mono_type (type->type);
1853         MonoClass *parent;
1854         MonoBitSet *slots;
1855         MonoGenericContext *context = NULL;
1856
1857         MONO_ARCH_SAVE_REGS;
1858
1859         if (class->generic_class && class->generic_class->context.class_inst->is_open) {
1860                 context = mono_class_get_context (class);
1861                 class = class->generic_class->container_class;
1862         }
1863
1864         mono_class_setup_vtable (class);
1865
1866         slots = mono_bitset_new (class->max_interface_id + 1, 0);
1867
1868         for (parent = class; parent; parent = parent->parent) {
1869                 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent);
1870                 if (tmp_ifaces) {
1871                         for (i = 0; i < tmp_ifaces->len; ++i) {
1872                                 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
1873
1874                                 if (mono_bitset_test (slots, ic->interface_id))
1875                                         continue;
1876
1877                                 mono_bitset_set (slots, ic->interface_id);
1878                                 if (ifaces == NULL)
1879                                         ifaces = g_ptr_array_new ();
1880                                 g_ptr_array_add (ifaces, ic);
1881                         }
1882                         g_ptr_array_free (tmp_ifaces, TRUE);
1883                 }
1884         }
1885         mono_bitset_free (slots);
1886
1887         if (!ifaces)
1888                 return mono_array_new (domain, mono_defaults.monotype_class, 0);
1889                 
1890         intf = mono_array_new (domain, mono_defaults.monotype_class, ifaces->len);
1891         for (i = 0; i < ifaces->len; ++i) {
1892                 MonoClass *ic = g_ptr_array_index (ifaces, i);
1893                 MonoType *ret = &ic->byval_arg;
1894                 if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open)
1895                         ret = mono_class_inflate_generic_type (ret, context);
1896                 
1897                 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
1898         }
1899         g_ptr_array_free (ifaces, TRUE);
1900
1901         return intf;
1902 }
1903
1904 static void
1905 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
1906 {
1907         MonoClass *class = mono_class_from_mono_type (type->type);
1908         MonoClass *iclass = mono_class_from_mono_type (iface->type);
1909         MonoReflectionMethod *member;
1910         MonoMethod* method;
1911         gpointer iter;
1912         int i = 0, len, ioffset;
1913         MonoDomain *domain;
1914
1915         MONO_ARCH_SAVE_REGS;
1916
1917         mono_class_setup_vtable (class);
1918
1919         /* type doesn't implement iface: the exception is thrown in managed code */
1920         if (! MONO_CLASS_IMPLEMENTS_INTERFACE (class, iclass->interface_id))
1921                         return;
1922
1923         len = mono_class_num_methods (iclass);
1924         ioffset = mono_class_interface_offset (class, iclass);
1925         domain = mono_object_domain (type);
1926         *targets = mono_array_new (domain, mono_defaults.method_info_class, len);
1927         *methods = mono_array_new (domain, mono_defaults.method_info_class, len);
1928         iter = NULL;
1929         iter = NULL;
1930         while ((method = mono_class_get_methods (iclass, &iter))) {
1931                 member = mono_method_get_object (domain, method, iclass);
1932                 mono_array_setref (*methods, i, member);
1933                 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
1934                 mono_array_setref (*targets, i, member);
1935                 
1936                 i ++;
1937         }
1938 }
1939
1940 static void
1941 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
1942 {
1943         MonoClass *klass = mono_class_from_mono_type (type->type);
1944
1945         if (klass->image->dynamic) {
1946                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
1947                 *packing = tb->packing_size;
1948                 *size = tb->class_size;
1949         } else {
1950                 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
1951         }
1952 }
1953
1954 static MonoReflectionType*
1955 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
1956 {
1957         MonoClass *class = mono_class_from_mono_type (type->type);
1958
1959         MONO_ARCH_SAVE_REGS;
1960
1961         // GetElementType should only return a type for:
1962         // Array Pointer PassedByRef
1963         if (type->type->byref)
1964                 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
1965         else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
1966                 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
1967         else if (class->element_class && type->type->type == MONO_TYPE_PTR)
1968                 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
1969         else
1970                 return NULL;
1971 }
1972
1973 static MonoReflectionType*
1974 ves_icall_get_type_parent (MonoReflectionType *type)
1975 {
1976         MonoClass *class = mono_class_from_mono_type (type->type);
1977
1978         MONO_ARCH_SAVE_REGS;
1979
1980         return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
1981 }
1982
1983 static MonoBoolean
1984 ves_icall_type_ispointer (MonoReflectionType *type)
1985 {
1986         MONO_ARCH_SAVE_REGS;
1987
1988         return type->type->type == MONO_TYPE_PTR;
1989 }
1990
1991 static MonoBoolean
1992 ves_icall_type_isprimitive (MonoReflectionType *type)
1993 {
1994         MONO_ARCH_SAVE_REGS;
1995
1996         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)));
1997 }
1998
1999 static MonoBoolean
2000 ves_icall_type_isbyref (MonoReflectionType *type)
2001 {
2002         MONO_ARCH_SAVE_REGS;
2003
2004         return type->type->byref;
2005 }
2006
2007 static MonoBoolean
2008 ves_icall_type_iscomobject (MonoReflectionType *type)
2009 {
2010         MonoClass *klass = mono_class_from_mono_type (type->type);
2011         MONO_ARCH_SAVE_REGS;
2012
2013         return (klass && klass->is_com_object);
2014 }
2015
2016 static MonoReflectionModule*
2017 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2018 {
2019         MonoClass *class = mono_class_from_mono_type (type->type);
2020
2021         MONO_ARCH_SAVE_REGS;
2022
2023         return mono_module_get_object (mono_object_domain (type), class->image);
2024 }
2025
2026 static MonoReflectionAssembly*
2027 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2028 {
2029         MonoDomain *domain = mono_domain_get (); 
2030         MonoClass *class = mono_class_from_mono_type (type->type);
2031
2032         MONO_ARCH_SAVE_REGS;
2033
2034         return mono_assembly_get_object (domain, class->image->assembly);
2035 }
2036
2037 static MonoReflectionType*
2038 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2039 {
2040         MonoDomain *domain = mono_domain_get ();
2041         MonoClass *class;
2042
2043         MONO_ARCH_SAVE_REGS;
2044
2045         if (type->type->byref)
2046                 return NULL;
2047         if (type->type->type == MONO_TYPE_VAR)
2048                 class = type->type->data.generic_param->owner->owner.klass;
2049         else if (type->type->type == MONO_TYPE_MVAR)
2050                 class = type->type->data.generic_param->owner->owner.method->klass;
2051         else
2052                 class = mono_class_from_mono_type (type->type)->nested_in;
2053
2054         return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2055 }
2056
2057 static MonoReflectionType*
2058 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType *type)
2059 {
2060         MonoDomain *domain = mono_domain_get (); 
2061         MonoClass *class = mono_class_from_mono_type (type->type);
2062
2063         MONO_ARCH_SAVE_REGS;
2064
2065         if (class->enumtype && class->enum_basetype) /* types that are modified typebuilders may not have enum_basetype set */
2066                 return mono_type_get_object (domain, class->enum_basetype);
2067         else if (class->element_class)
2068                 return mono_type_get_object (domain, &class->element_class->byval_arg);
2069         else
2070                 return NULL;
2071 }
2072
2073 static MonoString*
2074 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2075 {
2076         MonoDomain *domain = mono_domain_get (); 
2077         MonoClass *class = mono_class_from_mono_type (type->type);
2078
2079         MONO_ARCH_SAVE_REGS;
2080
2081         if (type->type->byref) {
2082                 char *n = g_strdup_printf ("%s&", class->name);
2083                 MonoString *res = mono_string_new (domain, n);
2084
2085                 g_free (n);
2086
2087                 return res;
2088         } else {
2089                 return mono_string_new (domain, class->name);
2090         }
2091 }
2092
2093 static MonoString*
2094 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2095 {
2096         MonoDomain *domain = mono_domain_get (); 
2097         MonoClass *class = mono_class_from_mono_type (type->type);
2098
2099         MONO_ARCH_SAVE_REGS;
2100
2101         while (class->nested_in)
2102                 class = class->nested_in;
2103
2104         if (class->name_space [0] == '\0')
2105                 return NULL;
2106         else
2107                 return mono_string_new (domain, class->name_space);
2108 }
2109
2110 static gint32
2111 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2112 {
2113         MonoClass *class = mono_class_from_mono_type (type->type);
2114
2115         MONO_ARCH_SAVE_REGS;
2116
2117         return class->rank;
2118 }
2119
2120 static MonoArray*
2121 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2122 {
2123         MonoArray *res;
2124         MonoClass *klass, *pklass;
2125         int i;
2126         MONO_ARCH_SAVE_REGS;
2127
2128         klass = mono_class_from_mono_type (type->type);
2129
2130         if (klass->generic_container) {
2131                 MonoGenericContainer *container = klass->generic_container;
2132                 res = mono_array_new (mono_object_domain (type), mono_defaults.systemtype_class, container->type_argc);
2133                 for (i = 0; i < container->type_argc; ++i) {
2134                         pklass = mono_class_from_generic_parameter (&container->type_params [i], klass->image, FALSE);
2135                         mono_array_setref (res, i, mono_type_get_object (mono_object_domain (type), &pklass->byval_arg));
2136                 }
2137         } else if (klass->generic_class) {
2138                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2139                 res = mono_array_new (mono_object_domain (type), mono_defaults.systemtype_class, inst->type_argc);
2140                 for (i = 0; i < inst->type_argc; ++i)
2141                         mono_array_setref (res, i, mono_type_get_object (mono_object_domain (type), inst->type_argv [i]));
2142         } else {
2143                 res = mono_array_new (mono_object_domain (type), mono_defaults.systemtype_class, 0);
2144         }
2145         return res;
2146 }
2147
2148 static gboolean
2149 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2150 {
2151         MonoClass *klass;
2152         MONO_ARCH_SAVE_REGS;
2153
2154         if (type->type->byref)
2155                 return FALSE;
2156
2157         klass = mono_class_from_mono_type (type->type);
2158
2159         return klass->generic_container != NULL;
2160 }
2161
2162 static MonoReflectionType*
2163 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2164 {
2165         MonoClass *klass;
2166         MONO_ARCH_SAVE_REGS;
2167
2168         if (type->type->byref)
2169                 return NULL;
2170
2171         klass = mono_class_from_mono_type (type->type);
2172         if (klass->generic_container) {
2173                 return type; /* check this one */
2174         }
2175         if (klass->generic_class) {
2176                 MonoClass *generic_class = klass->generic_class->container_class;
2177
2178                 if (generic_class->wastypebuilder && generic_class->reflection_info)
2179                         return generic_class->reflection_info;
2180                 else
2181                         return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2182         }
2183         return NULL;
2184 }
2185
2186 static MonoReflectionType*
2187 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2188 {
2189         MonoType *geninst, **types;
2190         int i, count;
2191
2192         MONO_ARCH_SAVE_REGS;
2193
2194         count = mono_array_length (type_array);
2195         types = g_new0 (MonoType *, count);
2196
2197         for (i = 0; i < count; i++) {
2198                 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2199                 types [i] = t->type;
2200         }
2201
2202         geninst = mono_reflection_bind_generic_parameters (type, count, types);
2203         g_free (types);
2204         if (!geninst)
2205                 return NULL;
2206
2207         return mono_type_get_object (mono_object_domain (type), geninst);
2208 }
2209
2210 static gboolean
2211 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2212 {
2213         MonoClass *klass;
2214         MONO_ARCH_SAVE_REGS;
2215
2216         if (type->type->byref)
2217                 return FALSE;
2218
2219         klass = mono_class_from_mono_type (type->type);
2220         return klass->generic_class != NULL;
2221 }
2222
2223 static gboolean
2224 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2225 {
2226         MonoClass *klass;
2227         MONO_ARCH_SAVE_REGS;
2228
2229         if (type->type->byref)
2230                 return FALSE;
2231
2232         klass = mono_class_from_mono_type (type->type);
2233         return klass->generic_class != NULL || klass->generic_container != NULL;
2234 }
2235
2236 static gint32
2237 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2238 {
2239         MONO_ARCH_SAVE_REGS;
2240
2241         if (is_generic_parameter (type->type))
2242                 return type->type->data.generic_param->num;
2243         return -1;
2244 }
2245
2246 static GenericParameterAttributes
2247 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2248 {
2249         MONO_ARCH_SAVE_REGS;
2250         g_assert (is_generic_parameter (type->type));
2251         return type->type->data.generic_param->flags;
2252 }
2253
2254 static MonoArray *
2255 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2256 {
2257         MonoGenericParam *param;
2258         MonoDomain *domain;
2259         MonoClass **ptr;
2260         MonoArray *res;
2261         int i, count;
2262
2263         MONO_ARCH_SAVE_REGS;
2264
2265         domain = mono_object_domain (type);
2266         param = type->type->data.generic_param;
2267         for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
2268                 ;
2269
2270         res = mono_array_new (domain, mono_defaults.monotype_class, count);
2271         for (i = 0; i < count; i++)
2272                 mono_array_setref (res, i, mono_type_get_object (domain, &param->constraints [i]->byval_arg));
2273
2274
2275         return res;
2276 }
2277
2278 static MonoBoolean
2279 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2280 {
2281         MONO_ARCH_SAVE_REGS;
2282         return is_generic_parameter (type->type);
2283 }
2284
2285 static MonoBoolean
2286 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2287 {
2288         MONO_ARCH_SAVE_REGS;
2289         return is_generic_parameter (tb->type.type);
2290 }
2291
2292 static void
2293 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2294                                                                            MonoReflectionType *t)
2295 {
2296         enumtype->type = t->type;
2297 }
2298
2299 static MonoReflectionType*
2300 ves_icall_MonoGenericClass_GetParentType (MonoReflectionGenericClass *type)
2301 {
2302         MonoDynamicGenericClass *gclass;
2303         MonoReflectionType *parent = NULL;
2304         MonoDomain *domain;
2305         MonoType *inflated;
2306         MonoClass *klass;
2307
2308         MONO_ARCH_SAVE_REGS;
2309
2310         g_assert (type->type.type->data.generic_class->is_dynamic);
2311         gclass = (MonoDynamicGenericClass *) type->type.type->data.generic_class;
2312
2313         domain = mono_object_domain (type);
2314         klass = mono_class_from_mono_type (type->generic_type->type.type);
2315
2316         if (!klass->generic_class && !klass->generic_container)
2317                 return NULL;
2318
2319         parent = type->generic_type->parent;
2320
2321         if (!parent || (parent->type->type != MONO_TYPE_GENERICINST))
2322                 return NULL;
2323
2324         inflated = mono_class_inflate_generic_type (
2325                 parent->type, mono_generic_class_get_context ((MonoGenericClass *) gclass));
2326
2327         return mono_type_get_object (domain, inflated);
2328 }
2329
2330 static MonoArray*
2331 ves_icall_MonoGenericClass_GetInterfaces (MonoReflectionGenericClass *type)
2332 {
2333         static MonoClass *System_Reflection_MonoGenericClass;
2334         MonoGenericClass *gclass;
2335         MonoReflectionTypeBuilder *tb = NULL;
2336         MonoClass *klass = NULL;
2337         MonoDomain *domain;
2338         MonoArray *res;
2339         int icount, i;
2340
2341         MONO_ARCH_SAVE_REGS;
2342
2343         if (!System_Reflection_MonoGenericClass) {
2344                 System_Reflection_MonoGenericClass = mono_class_from_name (
2345                         mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
2346                 g_assert (System_Reflection_MonoGenericClass);
2347         }
2348
2349         domain = mono_object_domain (type);
2350
2351         gclass = type->type.type->data.generic_class;
2352         g_assert (gclass->is_dynamic);
2353
2354         tb = type->generic_type;
2355         icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
2356
2357         res = mono_array_new (domain, System_Reflection_MonoGenericClass, icount);
2358
2359         for (i = 0; i < icount; i++) {
2360                 MonoReflectionType *iface;
2361                 MonoType *it;
2362
2363                 if (tb) {
2364                         iface = mono_array_get (tb->interfaces, MonoReflectionType *, i);
2365                         it = iface->type;
2366                 } else
2367                         it = &klass->interfaces [i]->byval_arg;
2368
2369                 it = mono_class_inflate_generic_type (it, mono_generic_class_get_context (gclass));
2370
2371                 iface = mono_type_get_object (domain, it);
2372                 mono_array_setref (res, i, iface);
2373         }
2374
2375         return res;
2376 }
2377
2378 static MonoReflectionMethod*
2379 ves_icall_MonoGenericClass_GetCorrespondingInflatedMethod (MonoReflectionGenericClass *type, 
2380                                                            MonoReflectionMethod* generic)
2381 {
2382         MonoGenericClass *gclass;
2383         MonoDynamicGenericClass *dgclass;
2384         MonoDomain *domain;
2385         int i;
2386
2387         MONO_ARCH_SAVE_REGS;
2388
2389         gclass = type->type.type->data.generic_class;
2390         g_assert (gclass->is_dynamic);
2391
2392         dgclass = (MonoDynamicGenericClass *) gclass;
2393
2394         domain = mono_object_domain (type);
2395
2396         for (i = 0; i < dgclass->count_methods; i++)
2397                 if (generic->method->token == dgclass->methods [i]->token)
2398                         return mono_method_get_object (domain, dgclass->methods [i], NULL);
2399
2400         return NULL;
2401 }
2402
2403 static MonoReflectionMethod*
2404 ves_icall_MonoGenericClass_GetCorrespondingInflatedConstructor (MonoReflectionGenericClass *type, 
2405                                                                 MonoReflectionMethod* generic)
2406 {
2407         MonoGenericClass *gclass;
2408         MonoDynamicGenericClass *dgclass;
2409         MonoDomain *domain;
2410         int i;
2411
2412         MONO_ARCH_SAVE_REGS;
2413
2414         gclass = type->type.type->data.generic_class;
2415         g_assert (gclass->is_dynamic);
2416
2417         dgclass = (MonoDynamicGenericClass *) gclass;
2418
2419         domain = mono_object_domain (type);
2420
2421         for (i = 0; i < dgclass->count_ctors; i++)
2422                 if (generic->method->token == dgclass->ctors [i]->token)
2423                         return mono_method_get_object (domain, dgclass->ctors [i], NULL);
2424
2425         return NULL;
2426 }
2427
2428
2429 static MonoReflectionField*
2430 ves_icall_MonoGenericClass_GetCorrespondingInflatedField (MonoReflectionGenericClass *type, 
2431                                                           MonoString* generic_name)
2432 {
2433         MonoGenericClass *gclass;
2434         MonoDynamicGenericClass *dgclass;
2435         MonoDomain *domain;
2436         MonoClass *refclass;
2437         char *utf8_name = mono_string_to_utf8 (generic_name);
2438         int i;
2439
2440         MONO_ARCH_SAVE_REGS;
2441
2442         gclass = type->type.type->data.generic_class;
2443         g_assert (gclass->is_dynamic);
2444
2445         dgclass = (MonoDynamicGenericClass *) gclass;
2446
2447         refclass = mono_class_from_mono_type (type->type.type);
2448
2449         domain = mono_object_domain (type);
2450
2451         for (i = 0; i < dgclass->count_fields; i++)
2452                 if (strcmp (utf8_name, dgclass->fields [i].name) == 0) {
2453                         g_free (utf8_name);
2454                         return mono_field_get_object (domain, refclass, &dgclass->fields [i]);
2455                 }
2456         
2457         g_free (utf8_name);
2458
2459         return NULL;
2460 }
2461
2462
2463 static MonoReflectionMethod*
2464 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type, 
2465                                                    MonoReflectionMethod* generic)
2466 {
2467         MonoDomain *domain; 
2468         MonoClass *klass;
2469         MonoMethod *method;
2470         gpointer iter;
2471                 
2472         MONO_ARCH_SAVE_REGS;
2473
2474         domain = ((MonoObject *)type)->vtable->domain;
2475
2476         klass = mono_class_from_mono_type (type->type);
2477
2478         iter = NULL;
2479         while ((method = mono_class_get_methods (klass, &iter))) {
2480                 if (method->token == generic->method->token)
2481                         return mono_method_get_object (domain, method, klass);
2482         }
2483
2484         return NULL;
2485 }
2486
2487 static MonoArray*
2488 ves_icall_MonoGenericClass_GetMethods (MonoReflectionGenericClass *type,
2489                                        MonoReflectionType *reflected_type)
2490 {
2491         MonoGenericClass *gclass;
2492         MonoDynamicGenericClass *dgclass;
2493         MonoDomain *domain;
2494         MonoClass *refclass;
2495         MonoArray *res;
2496         int i;
2497
2498         MONO_ARCH_SAVE_REGS;
2499
2500         gclass = type->type.type->data.generic_class;
2501         g_assert (gclass->is_dynamic);
2502         dgclass = (MonoDynamicGenericClass *) gclass;
2503
2504         refclass = mono_class_from_mono_type (reflected_type->type);
2505
2506         domain = mono_object_domain (type);
2507         res = mono_array_new (domain, mono_defaults.method_info_class, dgclass->count_methods);
2508
2509         for (i = 0; i < dgclass->count_methods; i++)
2510                 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->methods [i], refclass));
2511
2512         return res;
2513 }
2514
2515 static MonoArray*
2516 ves_icall_MonoGenericClass_GetConstructors (MonoReflectionGenericClass *type,
2517                                             MonoReflectionType *reflected_type)
2518 {
2519         static MonoClass *System_Reflection_ConstructorInfo;
2520         MonoGenericClass *gclass;
2521         MonoDynamicGenericClass *dgclass;
2522         MonoDomain *domain;
2523         MonoClass *refclass;
2524         MonoArray *res;
2525         int i;
2526
2527         MONO_ARCH_SAVE_REGS;
2528
2529         if (!System_Reflection_ConstructorInfo)
2530                 System_Reflection_ConstructorInfo = mono_class_from_name (
2531                         mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
2532
2533         gclass = type->type.type->data.generic_class;
2534         g_assert (gclass->is_dynamic);
2535         dgclass = (MonoDynamicGenericClass *) gclass;
2536
2537         refclass = mono_class_from_mono_type (reflected_type->type);
2538
2539         domain = mono_object_domain (type);
2540         res = mono_array_new (domain, System_Reflection_ConstructorInfo, dgclass->count_ctors);
2541
2542         for (i = 0; i < dgclass->count_ctors; i++)
2543                 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->ctors [i], refclass));
2544
2545         return res;
2546 }
2547
2548 static MonoArray*
2549 ves_icall_MonoGenericClass_GetFields (MonoReflectionGenericClass *type,
2550                                       MonoReflectionType *reflected_type)
2551 {
2552         MonoGenericClass *gclass;
2553         MonoDynamicGenericClass *dgclass;
2554         MonoDomain *domain;
2555         MonoClass *refclass;
2556         MonoArray *res;
2557         int i;
2558
2559         MONO_ARCH_SAVE_REGS;
2560
2561         gclass = type->type.type->data.generic_class;
2562         g_assert (gclass->is_dynamic);
2563         dgclass = (MonoDynamicGenericClass *) gclass;
2564
2565         refclass = mono_class_from_mono_type (reflected_type->type);
2566
2567         domain = mono_object_domain (type);
2568         res = mono_array_new (domain, mono_defaults.field_info_class, dgclass->count_fields);
2569
2570         for (i = 0; i < dgclass->count_fields; i++)
2571                 mono_array_setref (res, i, mono_field_get_object (domain, refclass, &dgclass->fields [i]));
2572
2573         return res;
2574 }
2575
2576 static MonoArray*
2577 ves_icall_MonoGenericClass_GetProperties (MonoReflectionGenericClass *type,
2578                                           MonoReflectionType *reflected_type)
2579 {
2580         static MonoClass *System_Reflection_PropertyInfo;
2581         MonoGenericClass *gclass;
2582         MonoDynamicGenericClass *dgclass;
2583         MonoDomain *domain;
2584         MonoClass *refclass;
2585         MonoArray *res;
2586         int i;
2587
2588         MONO_ARCH_SAVE_REGS;
2589
2590         if (!System_Reflection_PropertyInfo)
2591                 System_Reflection_PropertyInfo = mono_class_from_name (
2592                         mono_defaults.corlib, "System.Reflection", "PropertyInfo");
2593
2594         gclass = type->type.type->data.generic_class;
2595         g_assert (gclass->is_dynamic);
2596         dgclass = (MonoDynamicGenericClass *) gclass;
2597
2598         refclass = mono_class_from_mono_type (reflected_type->type);
2599
2600         domain = mono_object_domain (type);
2601         res = mono_array_new (domain, System_Reflection_PropertyInfo, dgclass->count_properties);
2602
2603         for (i = 0; i < dgclass->count_properties; i++)
2604                 mono_array_setref (res, i, mono_property_get_object (domain, refclass, &dgclass->properties [i]));
2605
2606         return res;
2607 }
2608
2609 static MonoArray*
2610 ves_icall_MonoGenericClass_GetEvents (MonoReflectionGenericClass *type,
2611                                       MonoReflectionType *reflected_type)
2612 {
2613         static MonoClass *System_Reflection_EventInfo;
2614         MonoGenericClass *gclass;
2615         MonoDynamicGenericClass *dgclass;
2616         MonoDomain *domain;
2617         MonoClass *refclass;
2618         MonoArray *res;
2619         int i;
2620
2621         MONO_ARCH_SAVE_REGS;
2622
2623         if (!System_Reflection_EventInfo)
2624                 System_Reflection_EventInfo = mono_class_from_name (
2625                         mono_defaults.corlib, "System.Reflection", "EventInfo");
2626
2627         gclass = type->type.type->data.generic_class;
2628         g_assert (gclass->is_dynamic);
2629         dgclass = (MonoDynamicGenericClass *) gclass;
2630
2631         refclass = mono_class_from_mono_type (reflected_type->type);
2632
2633         domain = mono_object_domain (type);
2634         res = mono_array_new (domain, System_Reflection_EventInfo, dgclass->count_events);
2635
2636         for (i = 0; i < dgclass->count_events; i++)
2637                 mono_array_setref (res, i, mono_event_get_object (domain, refclass, &dgclass->events [i]));
2638
2639         return res;
2640 }
2641
2642 static MonoReflectionMethod *
2643 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *type)
2644 {
2645         MonoMethod *method;
2646         MonoClass *klass;
2647
2648         MONO_ARCH_SAVE_REGS;
2649
2650         if (type->type->byref || type->type->type != MONO_TYPE_MVAR)
2651                 return NULL;
2652
2653         method = type->type->data.generic_param->owner->owner.method;
2654         g_assert (method);
2655         klass = mono_class_from_mono_type (type->type);
2656         return mono_method_get_object (mono_object_domain (type), method, klass);
2657 }
2658
2659 static MonoReflectionDllImportAttribute*
2660 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2661 {
2662         static MonoClass *DllImportAttributeClass = NULL;
2663         MonoDomain *domain = mono_domain_get ();
2664         MonoReflectionDllImportAttribute *attr;
2665         MonoImage *image = method->klass->image;
2666         MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2667         MonoTableInfo *tables = image->tables;
2668         MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2669         MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2670         guint32 im_cols [MONO_IMPLMAP_SIZE];
2671         guint32 scope_token;
2672         const char *import = NULL;
2673         const char *scope = NULL;
2674         guint32 flags;
2675
2676         if (!method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2677                 return NULL;
2678
2679         if (!DllImportAttributeClass) {
2680                 DllImportAttributeClass = 
2681                         mono_class_from_name (mono_defaults.corlib,
2682                                                                   "System.Runtime.InteropServices", "DllImportAttribute");
2683                 g_assert (DllImportAttributeClass);
2684         }
2685                                                                                                                 
2686         if (method->klass->image->dynamic) {
2687                 MonoReflectionMethodAux *method_aux = 
2688                         g_hash_table_lookup (
2689                                                                           ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2690                 if (method_aux) {
2691                         import = method_aux->dllentry;
2692                         scope = method_aux->dll;
2693                 }
2694         }
2695         else {
2696                 if (piinfo->implmap_idx) {
2697                         mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2698                         
2699                         piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2700                         import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2701                         scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2702                         scope = mono_metadata_string_heap (image, scope_token);
2703                 }
2704         }
2705         flags = piinfo->piflags;
2706         
2707         attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2708
2709         MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2710         MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2711         attr->call_conv = (flags & 0x700) >> 8;
2712         attr->charset = ((flags & 0x6) >> 1) + 1;
2713         if (attr->charset == 1)
2714                 attr->charset = 2;
2715         attr->exact_spelling = (flags & 0x1) != 0;
2716         attr->set_last_error = (flags & 0x40) != 0;
2717         attr->best_fit_mapping = (flags & 0x30) == 0x10;
2718         attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2719         attr->preserve_sig = FALSE;
2720
2721         return attr;
2722 }
2723
2724 static MonoReflectionMethod *
2725 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2726 {
2727         MonoMethodInflated *imethod;
2728         MonoMethod *result;
2729
2730         MONO_ARCH_SAVE_REGS;
2731
2732         if (method->method->generic_container)
2733                 return method;
2734
2735         if (!method->method->is_inflated)
2736                 return NULL;
2737
2738         imethod = (MonoMethodInflated *) method->method;
2739
2740         result = imethod->declaring;
2741         /* Not a generic method.  */
2742         if (!result->generic_container)
2743                 return NULL;
2744
2745         if (method->method->klass->image->dynamic) {
2746                 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2747                 MonoReflectionMethod *res;
2748
2749                 /*
2750                  * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2751                  * the dynamic case as well ?
2752                  */
2753                 mono_loader_lock ();
2754                 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2755                 mono_loader_unlock ();
2756
2757                 if (res)
2758                         return res;
2759         }
2760
2761         if (imethod->context.class_inst) {
2762                 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2763                 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2764         }
2765
2766         return mono_method_get_object (mono_object_domain (method), result, NULL);
2767 }
2768
2769 static gboolean
2770 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2771 {
2772         MONO_ARCH_SAVE_REGS;
2773
2774         return mono_method_signature (method->method)->generic_param_count != 0;
2775 }
2776
2777 static gboolean
2778 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2779 {
2780         MONO_ARCH_SAVE_REGS;
2781
2782         return method->method->generic_container != NULL;
2783 }
2784
2785 static MonoArray*
2786 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2787 {
2788         MonoArray *res;
2789         MonoDomain *domain;
2790         int count, i;
2791         MONO_ARCH_SAVE_REGS;
2792
2793         domain = mono_object_domain (method);
2794
2795         if (method->method->is_inflated) {
2796                 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2797
2798                 if (inst) {
2799                         count = inst->type_argc;
2800                         res = mono_array_new (domain, mono_defaults.monotype_class, count);
2801
2802                         for (i = 0; i < count; i++)
2803                                 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2804
2805                         return res;
2806                 }
2807         }
2808
2809         count = mono_method_signature (method->method)->generic_param_count;
2810         res = mono_array_new (domain, mono_defaults.monotype_class, count);
2811
2812         for (i = 0; i < count; i++) {
2813                 MonoGenericParam *param = &method->method->generic_container->type_params [i];
2814                 MonoClass *pklass = mono_class_from_generic_parameter (
2815                         param, method->method->klass->image, TRUE);
2816                 mono_array_setref (res, i,
2817                                 mono_type_get_object (domain, &pklass->byval_arg));
2818         }
2819
2820         return res;
2821 }
2822
2823 static void
2824 ensure_reflection_security (void)
2825 {
2826         MonoMethod *m = mono_method_get_last_managed ();
2827
2828         while (m) {
2829                 /*
2830                 g_print ("method %s.%s.%s in image %s\n",
2831                         m->klass->name_space, m->klass->name, m->name, m->klass->image->name);
2832                 */
2833
2834                 /* We stop at the first method which is not in
2835                    System.Reflection or which is not in a platform
2836                    image. */
2837                 if (strcmp (m->klass->name_space, "System.Reflection") != 0 ||
2838                                 !mono_security_core_clr_is_platform_image (m->klass->image)) {
2839                         /* If the method is transparent we throw an exception. */
2840                         if (mono_security_core_clr_method_level (m, TRUE) == MONO_SECURITY_CORE_CLR_TRANSPARENT ) {
2841                                 MonoException *ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MethodAccessException", "Reflection called from transparent code");
2842
2843                                 mono_raise_exception (ex);
2844                         }
2845                         return;
2846                 }
2847
2848                 mono_stack_walk_no_il (get_caller, &m);
2849         }
2850 }
2851
2852 static MonoObject *
2853 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params) 
2854 {
2855         /* 
2856          * Invoke from reflection is supposed to always be a virtual call (the API
2857          * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2858          * greater flexibility.
2859          */
2860         MonoMethod *m = method->method;
2861         int pcount;
2862         void *obj = this;
2863
2864         MONO_ARCH_SAVE_REGS;
2865
2866         if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR &&
2867                         mono_security_core_clr_method_level (m, TRUE) == MONO_SECURITY_CORE_CLR_CRITICAL)
2868                 ensure_reflection_security ();
2869
2870         if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2871                 if (this) {
2872                         if (!mono_object_isinst (this, m->klass))
2873                                 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetException"));
2874                         m = mono_object_get_virtual_method (this, m);
2875                         /* must pass the pointer to the value for valuetype methods */
2876                         if (m->klass->valuetype)
2877                                 obj = mono_object_unbox (this);
2878                 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type)
2879                         mono_raise_exception (mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetException"));
2880         }
2881
2882         pcount = params? mono_array_length (params): 0;
2883         if (pcount != mono_method_signature (m)->param_count)
2884                 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2885
2886         if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this)
2887                 mono_raise_exception (mono_exception_from_name_msg (mono_defaults.corlib, "System", "MethodAccessException", "Cannot invoke constructor of an abstract class."));
2888
2889         if (m->klass->image->assembly->ref_only)
2890                 mono_raise_exception (mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
2891         
2892         if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2893                 int i;
2894                 guint32 *lengths;
2895                 guint32 *lower_bounds;
2896                 pcount = mono_array_length (params);
2897                 lengths = alloca (sizeof (guint32) * pcount);
2898                 for (i = 0; i < pcount; ++i)
2899                         lengths [i] = *(gint32*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2900
2901                 if (m->klass->rank == pcount) {
2902                         /* Only lengths provided. */
2903                         lower_bounds = NULL;
2904                 } else {
2905                         g_assert (pcount == (m->klass->rank * 2));
2906                         /* lower bounds are first. */
2907                         lower_bounds = lengths;
2908                         lengths += m->klass->rank;
2909                 }
2910
2911                 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2912         }
2913         return mono_runtime_invoke_array (m, obj, params, NULL);
2914 }
2915
2916 static MonoObject *
2917 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs) 
2918 {
2919         MonoDomain *domain = mono_object_domain (method); 
2920         MonoMethod *m = method->method;
2921         MonoMethodSignature *sig = mono_method_signature (m);
2922         MonoArray *out_args;
2923         MonoObject *result;
2924         int i, j, outarg_count = 0;
2925
2926         MONO_ARCH_SAVE_REGS;
2927
2928         if (m->klass == mono_defaults.object_class) {
2929
2930                 if (!strcmp (m->name, "FieldGetter")) {
2931                         MonoClass *k = this->vtable->klass;
2932                         MonoString *name;
2933                         char *str;
2934                         
2935                         /* If this is a proxy, then it must be a CBO */
2936                         if (k == mono_defaults.transparent_proxy_class) {
2937                                 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2938                                 this = tp->rp->unwrapped_server;
2939                                 g_assert (this);
2940                                 k = this->vtable->klass;
2941                         }
2942                         
2943                         name = mono_array_get (params, MonoString *, 1);
2944                         str = mono_string_to_utf8 (name);
2945                 
2946                         do {
2947                                 MonoClassField* field = mono_class_get_field_from_name (k, str);
2948                                 if (field) {
2949                                         MonoClass *field_klass =  mono_class_from_mono_type (field->type);
2950                                         if (field_klass->valuetype)
2951                                                 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2952                                         else 
2953                                                 result = *((gpointer *)((char *)this + field->offset));
2954                                 
2955                                         out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2956                                         *outArgs = out_args;
2957                                         mono_array_setref (out_args, 0, result);
2958                                         g_free (str);
2959                                         return NULL;
2960                                 }
2961                                 k = k->parent;
2962                         } while (k);
2963
2964                         g_free (str);
2965                         g_assert_not_reached ();
2966
2967                 } else if (!strcmp (m->name, "FieldSetter")) {
2968                         MonoClass *k = this->vtable->klass;
2969                         MonoString *name;
2970                         guint32 size;
2971                         gint32 align;
2972                         char *str;
2973                         
2974                         /* If this is a proxy, then it must be a CBO */
2975                         if (k == mono_defaults.transparent_proxy_class) {
2976                                 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2977                                 this = tp->rp->unwrapped_server;
2978                                 g_assert (this);
2979                                 k = this->vtable->klass;
2980                         }
2981                         
2982                         name = mono_array_get (params, MonoString *, 1);
2983                         str = mono_string_to_utf8 (name);
2984                 
2985                         do {
2986                                 MonoClassField* field = mono_class_get_field_from_name (k, str);
2987                                 if (field) {
2988                                         MonoClass *field_klass =  mono_class_from_mono_type (field->type);
2989                                         MonoObject *val = mono_array_get (params, gpointer, 2);
2990
2991                                         if (field_klass->valuetype) {
2992                                                 size = mono_type_size (field->type, &align);
2993                                                 memcpy ((char *)this + field->offset, 
2994                                                         ((char *)val) + sizeof (MonoObject), size);
2995                                         } else 
2996                                                 *(MonoObject**)((char *)this + field->offset) = val;
2997                                 
2998                                         out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2999                                         *outArgs = out_args;
3000
3001                                         g_free (str);
3002                                         return NULL;
3003                                 }
3004                                 
3005                                 k = k->parent;
3006                         } while (k);
3007
3008                         g_free (str);
3009                         g_assert_not_reached ();
3010
3011                 }
3012         }
3013
3014         for (i = 0; i < mono_array_length (params); i++) {
3015                 if (sig->params [i]->byref) 
3016                         outarg_count++;
3017         }
3018
3019         out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3020         
3021         /* handle constructors only for objects already allocated */
3022         if (!strcmp (method->method->name, ".ctor"))
3023                 g_assert (this);
3024
3025         /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3026         g_assert (!method->method->klass->valuetype);
3027         result = mono_runtime_invoke_array (method->method, this, params, NULL);
3028
3029         for (i = 0, j = 0; i < mono_array_length (params); i++) {
3030                 if (sig->params [i]->byref) {
3031                         gpointer arg;
3032                         arg = mono_array_get (params, gpointer, i);
3033                         mono_array_setref (out_args, j, arg);
3034                         j++;
3035                 }
3036         }
3037
3038         *outArgs = out_args;
3039
3040         return result;
3041 }
3042
3043 static guint64
3044 read_enum_value (char *mem, int type)
3045 {
3046         switch (type) {
3047         case MONO_TYPE_U1:
3048                 return *(guint8*)mem;
3049         case MONO_TYPE_I1:
3050                 return *(gint8*)mem;
3051         case MONO_TYPE_U2:
3052                 return *(guint16*)mem;
3053         case MONO_TYPE_I2:
3054                 return *(gint16*)mem;
3055         case MONO_TYPE_U4:
3056                 return *(guint32*)mem;
3057         case MONO_TYPE_I4:
3058                 return *(gint32*)mem;
3059         case MONO_TYPE_U8:
3060                 return *(guint64*)mem;
3061         case MONO_TYPE_I8:
3062                 return *(gint64*)mem;
3063         default:
3064                 g_assert_not_reached ();
3065         }
3066         return 0;
3067 }
3068
3069 static void
3070 write_enum_value (char *mem, int type, guint64 value)
3071 {
3072         switch (type) {
3073         case MONO_TYPE_U1:
3074         case MONO_TYPE_I1: {
3075                 guint8 *p = (guint8*)mem;
3076                 *p = value;
3077                 break;
3078         }
3079         case MONO_TYPE_U2:
3080         case MONO_TYPE_I2: {
3081                 guint16 *p = (void*)mem;
3082                 *p = value;
3083                 break;
3084         }
3085         case MONO_TYPE_U4:
3086         case MONO_TYPE_I4: {
3087                 guint32 *p = (void*)mem;
3088                 *p = value;
3089                 break;
3090         }
3091         case MONO_TYPE_U8:
3092         case MONO_TYPE_I8: {
3093                 guint64 *p = (void*)mem;
3094                 *p = value;
3095                 break;
3096         }
3097         default:
3098                 g_assert_not_reached ();
3099         }
3100         return;
3101 }
3102
3103 static MonoObject *
3104 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3105 {
3106         MonoDomain *domain; 
3107         MonoClass *enumc, *objc;
3108         MonoObject *res;
3109         guint64 val;
3110         
3111         MONO_ARCH_SAVE_REGS;
3112
3113         MONO_CHECK_ARG_NULL (enumType);
3114         MONO_CHECK_ARG_NULL (value);
3115
3116         domain = mono_object_domain (enumType); 
3117         enumc = mono_class_from_mono_type (enumType->type);
3118         objc = value->vtable->klass;
3119
3120         if (!enumc->enumtype)
3121                 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3122         if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3123                 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."));
3124
3125         res = mono_object_new (domain, enumc);
3126         val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? objc->enum_basetype->type: objc->byval_arg.type);
3127         write_enum_value ((char *)res + sizeof (MonoObject), enumc->enum_basetype->type, val);
3128
3129         return res;
3130 }
3131
3132 static MonoObject *
3133 ves_icall_System_Enum_get_value (MonoObject *this)
3134 {
3135         MonoObject *res;
3136         MonoClass *enumc;
3137         gpointer dst;
3138         gpointer src;
3139         int size;
3140
3141         MONO_ARCH_SAVE_REGS;
3142
3143         if (!this)
3144                 return NULL;
3145
3146         g_assert (this->vtable->klass->enumtype);
3147         
3148         enumc = mono_class_from_mono_type (this->vtable->klass->enum_basetype);
3149         res = mono_object_new (mono_object_domain (this), enumc);
3150         dst = (char *)res + sizeof (MonoObject);
3151         src = (char *)this + sizeof (MonoObject);
3152         size = mono_class_value_size (enumc, NULL);
3153
3154         memcpy (dst, src, size);
3155
3156         return res;
3157 }
3158
3159 static void
3160 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3161 {
3162         MonoDomain *domain = mono_object_domain (type); 
3163         MonoClass *enumc = mono_class_from_mono_type (type->type);
3164         guint j = 0, nvalues, crow;
3165         gpointer iter;
3166         MonoClassField *field;
3167
3168         MONO_ARCH_SAVE_REGS;
3169
3170         info->utype = mono_type_get_object (domain, enumc->enum_basetype);
3171         nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3172         info->names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3173         info->values = mono_array_new (domain, enumc, nvalues);
3174         
3175         crow = -1;
3176         iter = NULL;
3177         while ((field = mono_class_get_fields (enumc, &iter))) {
3178                 const char *p;
3179                 int len;
3180                 
3181                 if (strcmp ("value__", field->name) == 0)
3182                         continue;
3183                 if (mono_field_is_deleted (field))
3184                         continue;
3185                 mono_array_setref (info->names, j, mono_string_new (domain, field->name));
3186
3187                 if (!field->data) {
3188                         crow = mono_metadata_get_constant_index (enumc->image, mono_class_get_field_token (field), crow + 1);
3189                         field->def_type = mono_metadata_decode_row_col (&enumc->image->tables [MONO_TABLE_CONSTANT], crow-1, MONO_CONSTANT_TYPE);
3190                         crow = mono_metadata_decode_row_col (&enumc->image->tables [MONO_TABLE_CONSTANT], crow-1, MONO_CONSTANT_VALUE);
3191                         field->data = (gpointer)mono_metadata_blob_heap (enumc->image, crow);
3192                 }
3193
3194                 p = field->data;
3195                 len = mono_metadata_decode_blob_size (p, &p);
3196                 switch (enumc->enum_basetype->type) {
3197                 case MONO_TYPE_U1:
3198                 case MONO_TYPE_I1:
3199                         mono_array_set (info->values, gchar, j, *p);
3200                         break;
3201                 case MONO_TYPE_CHAR:
3202                 case MONO_TYPE_U2:
3203                 case MONO_TYPE_I2:
3204                         mono_array_set (info->values, gint16, j, read16 (p));
3205                         break;
3206                 case MONO_TYPE_U4:
3207                 case MONO_TYPE_I4:
3208                         mono_array_set (info->values, gint32, j, read32 (p));
3209                         break;
3210                 case MONO_TYPE_U8:
3211                 case MONO_TYPE_I8:
3212                         mono_array_set (info->values, gint64, j, read64 (p));
3213                         break;
3214                 default:
3215                         g_error ("Implement type 0x%02x in get_enum_info", enumc->enum_basetype->type);
3216                 }
3217                 ++j;
3218         }
3219 }
3220
3221 enum {
3222         BFLAGS_IgnoreCase = 1,
3223         BFLAGS_DeclaredOnly = 2,
3224         BFLAGS_Instance = 4,
3225         BFLAGS_Static = 8,
3226         BFLAGS_Public = 0x10,
3227         BFLAGS_NonPublic = 0x20,
3228         BFLAGS_FlattenHierarchy = 0x40,
3229         BFLAGS_InvokeMethod = 0x100,
3230         BFLAGS_CreateInstance = 0x200,
3231         BFLAGS_GetField = 0x400,
3232         BFLAGS_SetField = 0x800,
3233         BFLAGS_GetProperty = 0x1000,
3234         BFLAGS_SetProperty = 0x2000,
3235         BFLAGS_ExactBinding = 0x10000,
3236         BFLAGS_SuppressChangeType = 0x20000,
3237         BFLAGS_OptionalParamBinding = 0x40000
3238 };
3239
3240 static MonoReflectionField *
3241 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3242 {
3243         MonoDomain *domain; 
3244         MonoClass *startklass, *klass;
3245         int match;
3246         MonoClassField *field;
3247         gpointer iter;
3248         char *utf8_name;
3249         int (*compare_func) (const char *s1, const char *s2) = NULL;
3250         domain = ((MonoObject *)type)->vtable->domain;
3251         klass = startklass = mono_class_from_mono_type (type->type);
3252
3253         MONO_ARCH_SAVE_REGS;
3254
3255         if (!name)
3256                 mono_raise_exception (mono_get_exception_argument_null ("name"));
3257         if (type->type->byref)
3258                 return NULL;
3259
3260         compare_func = (bflags & BFLAGS_IgnoreCase) ? g_strcasecmp : strcmp;
3261
3262 handle_parent:
3263         if (klass->exception_type != MONO_EXCEPTION_NONE)
3264                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3265
3266         iter = NULL;
3267         while ((field = mono_class_get_fields (klass, &iter))) {
3268                 match = 0;
3269
3270                 if (field->type == NULL)
3271                         continue;
3272                 if (mono_field_is_deleted (field))
3273                         continue;
3274                 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3275                         if (bflags & BFLAGS_Public)
3276                                 match++;
3277                 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3278                         if (bflags & BFLAGS_NonPublic) {
3279                                 match++;
3280                         }
3281                 }
3282                 if (!match)
3283                         continue;
3284                 match = 0;
3285                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3286                         if (bflags & BFLAGS_Static)
3287                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3288                                         match++;
3289                 } else {
3290                         if (bflags & BFLAGS_Instance)
3291                                 match++;
3292                 }
3293
3294                 if (!match)
3295                         continue;
3296                 
3297                 utf8_name = mono_string_to_utf8 (name);
3298
3299                 if (compare_func (field->name, utf8_name)) {
3300                         g_free (utf8_name);
3301                         continue;
3302                 }
3303                 g_free (utf8_name);
3304                 
3305                 return mono_field_get_object (domain, klass, field);
3306         }
3307         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3308                 goto handle_parent;
3309
3310         return NULL;
3311 }
3312
3313 static MonoArray*
3314 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3315 {
3316         MonoDomain *domain; 
3317         MonoClass *startklass, *klass, *refklass;
3318         MonoArray *res;
3319         MonoObject *member;
3320         int i, len, match;
3321         gpointer iter;
3322         MonoClassField *field;
3323
3324         MONO_ARCH_SAVE_REGS;
3325
3326         domain = ((MonoObject *)type)->vtable->domain;
3327         if (type->type->byref)
3328                 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3329         klass = startklass = mono_class_from_mono_type (type->type);
3330         refklass = mono_class_from_mono_type (reftype->type);
3331
3332         i = 0;
3333         len = 2;
3334         res = mono_array_new (domain, mono_defaults.field_info_class, len);
3335 handle_parent:  
3336         if (klass->exception_type != MONO_EXCEPTION_NONE)
3337                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3338
3339         iter = NULL;
3340         while ((field = mono_class_get_fields (klass, &iter))) {
3341                 match = 0;
3342                 if (mono_field_is_deleted (field))
3343                         continue;
3344                 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3345                         if (bflags & BFLAGS_Public)
3346                                 match++;
3347                 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3348                         if (bflags & BFLAGS_NonPublic) {
3349                                 match++;
3350                         }
3351                 }
3352                 if (!match)
3353                         continue;
3354                 match = 0;
3355                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3356                         if (bflags & BFLAGS_Static)
3357                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3358                                         match++;
3359                 } else {
3360                         if (bflags & BFLAGS_Instance)
3361                                 match++;
3362                 }
3363
3364                 if (!match)
3365                         continue;
3366                 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3367                 if (i >= len) {
3368                         MonoArray *new_res = mono_array_new (domain, mono_defaults.field_info_class, len * 2);
3369                         mono_array_memcpy_refs (new_res, 0, res, 0, len);
3370                         len *= 2;
3371                         res = new_res;
3372                 }
3373                 mono_array_setref (res, i, member);
3374                 ++i;
3375         }
3376         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3377                 goto handle_parent;
3378         if (i != len) {
3379                 MonoArray *new_res = mono_array_new (domain, mono_defaults.field_info_class, i);
3380                 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3381                 res = new_res;
3382                 /*
3383                  * Better solution for the new GC.
3384                  * res->max_length = i;
3385                  */
3386         }
3387         return res;
3388 }
3389
3390 static gboolean
3391 method_nonpublic (MonoMethod* method, gboolean start_klass)
3392 {
3393         switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3394                 case METHOD_ATTRIBUTE_ASSEM:
3395                         return (start_klass || mono_defaults.generic_ilist_class);
3396                 case METHOD_ATTRIBUTE_PRIVATE:
3397                         return start_klass;
3398                 case METHOD_ATTRIBUTE_PUBLIC:
3399                         return FALSE;
3400                 default:
3401                         return TRUE;
3402         }
3403 }
3404
3405 static MonoArray*
3406 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3407 {
3408         MonoDomain *domain; 
3409         MonoClass *startklass, *klass, *refklass;
3410         MonoArray *res;
3411         MonoMethod *method;
3412         gpointer iter;
3413         MonoObject *member;
3414         int i, len, match, nslots;
3415         guint32 method_slots_default [8];
3416         guint32 *method_slots;
3417         gchar *mname = NULL;
3418         int (*compare_func) (const char *s1, const char *s2) = NULL;
3419                 
3420         MONO_ARCH_SAVE_REGS;
3421
3422         domain = ((MonoObject *)type)->vtable->domain;
3423         if (type->type->byref)
3424                 return mono_array_new (domain, mono_defaults.method_info_class, 0);
3425         klass = startklass = mono_class_from_mono_type (type->type);
3426         refklass = mono_class_from_mono_type (reftype->type);
3427         len = 0;
3428         if (name != NULL) {
3429                 mname = mono_string_to_utf8 (name);
3430                 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3431         }
3432
3433         mono_class_setup_vtable (klass);
3434
3435         if (is_generic_parameter (type->type))
3436                 nslots = klass->parent->vtable_size;
3437         else
3438                 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : klass->vtable_size;
3439         if (nslots >= sizeof (method_slots_default) * 8) {
3440                 method_slots = g_new0 (guint32, nslots / 32 + 1);
3441         } else {
3442                 method_slots = method_slots_default;
3443                 memset (method_slots, 0, sizeof (method_slots_default));
3444         }
3445         i = 0;
3446         len = 1;
3447         res = mono_array_new (domain, mono_defaults.method_info_class, len);
3448 handle_parent:
3449         mono_class_setup_vtable (klass);
3450         if (klass->exception_type != MONO_EXCEPTION_NONE)
3451                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3452
3453         iter = NULL;
3454         while ((method = mono_class_get_methods (klass, &iter))) {
3455                 match = 0;
3456                 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3457                         continue;
3458                 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3459                         if (bflags & BFLAGS_Public)
3460                                 match++;
3461                 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3462                                 match++;
3463                 }
3464                 if (!match)
3465                         continue;
3466                 match = 0;
3467                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3468                         if (bflags & BFLAGS_Static)
3469                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3470                                         match++;
3471                 } else {
3472                         if (bflags & BFLAGS_Instance)
3473                                 match++;
3474                 }
3475
3476                 if (!match)
3477                         continue;
3478
3479                 if (name != NULL) {
3480                         if (compare_func (mname, method->name))
3481                                 continue;
3482                 }
3483                 
3484                 match = 0;
3485                 if (method->slot != -1) {
3486                         g_assert (method->slot < nslots);
3487                         if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3488                                 continue;
3489                         method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3490                 }
3491                 
3492                 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3493                 
3494                 if (i >= len) {
3495                         MonoArray *new_res = mono_array_new (domain, mono_defaults.method_info_class, len * 2);
3496                         mono_array_memcpy_refs (new_res, 0, res, 0, len);
3497                         len *= 2;
3498                         res = new_res;
3499                 }
3500                 mono_array_setref (res, i, member);
3501                 ++i;
3502         }
3503         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3504                 goto handle_parent;
3505
3506         g_free (mname);
3507         if (method_slots != method_slots_default)
3508                 g_free (method_slots);
3509         if (i != len) {
3510                 MonoArray *new_res = mono_array_new (domain, mono_defaults.method_info_class, i);
3511                 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3512                 res = new_res;
3513                 /*
3514                  * Better solution for the new GC.
3515                  * res->max_length = i;
3516                  */
3517         }
3518         return res;
3519 }
3520
3521 static MonoArray*
3522 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3523 {
3524         MonoDomain *domain; 
3525         static MonoClass *System_Reflection_ConstructorInfo;
3526         MonoClass *startklass, *klass, *refklass;
3527         MonoArray *res;
3528         MonoMethod *method;
3529         MonoObject *member;
3530         int i, len, match;
3531         gpointer iter = NULL;
3532         
3533         MONO_ARCH_SAVE_REGS;
3534
3535         domain = ((MonoObject *)type)->vtable->domain;
3536         if (type->type->byref)
3537                 return mono_array_new (domain, mono_defaults.method_info_class, 0);
3538         klass = startklass = mono_class_from_mono_type (type->type);
3539         refklass = mono_class_from_mono_type (reftype->type);
3540
3541         if (klass->exception_type != MONO_EXCEPTION_NONE)
3542                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3543
3544         if (!System_Reflection_ConstructorInfo)
3545                 System_Reflection_ConstructorInfo = mono_class_from_name (
3546                         mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3547
3548         i = 0;
3549         len = 2;
3550         res = mono_array_new (domain, System_Reflection_ConstructorInfo, len);
3551         iter = NULL;
3552         while ((method = mono_class_get_methods (klass, &iter))) {
3553                 match = 0;
3554                 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3555                         continue;
3556                 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3557                         if (bflags & BFLAGS_Public)
3558                                 match++;
3559                 } else {
3560                         if (bflags & BFLAGS_NonPublic)
3561                                 match++;
3562                 }
3563                 if (!match)
3564                         continue;
3565                 match = 0;
3566                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3567                         if (bflags & BFLAGS_Static)
3568                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3569                                         match++;
3570                 } else {
3571                         if (bflags & BFLAGS_Instance)
3572                                 match++;
3573                 }
3574
3575                 if (!match)
3576                         continue;
3577                 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3578
3579                 if (i >= len) {
3580                         MonoArray *new_res = mono_array_new (domain, System_Reflection_ConstructorInfo, len * 2);
3581                         mono_array_memcpy_refs (new_res, 0, res, 0, len);
3582                         len *= 2;
3583                         res = new_res;
3584                 }
3585                 mono_array_setref (res, i, member);
3586                 ++i;
3587         }
3588         if (i != len) {
3589                 MonoArray *new_res = mono_array_new (domain, System_Reflection_ConstructorInfo, i);
3590                 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3591                 res = new_res;
3592                 /*
3593                  * Better solution for the new GC.
3594                  * res->max_length = i;
3595                  */
3596         }
3597         return res;
3598 }
3599
3600 static guint
3601 property_hash (gconstpointer data)
3602 {
3603         MonoProperty *prop = (MonoProperty*)data;
3604
3605         return g_str_hash (prop->name);
3606 }
3607
3608 static gboolean
3609 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3610 {
3611         // Properties are hide-by-name-and-signature
3612         if (!g_str_equal (prop1->name, prop2->name))
3613                 return FALSE;
3614
3615         if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3616                 return FALSE;
3617         if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3618                 return FALSE;
3619         return TRUE;
3620 }
3621
3622 static gboolean
3623 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3624 {
3625         if (!accessor)
3626                 return FALSE;
3627
3628         return method_nonpublic (accessor, start_klass);
3629 }
3630
3631 static MonoArray*
3632 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3633 {
3634         MonoDomain *domain; 
3635         static MonoClass *System_Reflection_PropertyInfo;
3636         MonoClass *startklass, *klass;
3637         MonoArray *res;
3638         MonoMethod *method;
3639         MonoProperty *prop;
3640         int i, match;
3641         int len = 0;
3642         guint32 flags;
3643         gchar *propname = NULL;
3644         int (*compare_func) (const char *s1, const char *s2) = NULL;
3645         gpointer iter;
3646         GHashTable *properties;
3647
3648         MONO_ARCH_SAVE_REGS;
3649
3650         if (!System_Reflection_PropertyInfo)
3651                 System_Reflection_PropertyInfo = mono_class_from_name (
3652                         mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3653
3654         domain = ((MonoObject *)type)->vtable->domain;
3655         if (type->type->byref)
3656                 return mono_array_new (domain, System_Reflection_PropertyInfo, 0);
3657         klass = startklass = mono_class_from_mono_type (type->type);
3658         if (name != NULL) {
3659                 propname = mono_string_to_utf8 (name);
3660                 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3661         }
3662
3663         mono_class_setup_vtable (klass);
3664
3665         properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3666         i = 0;
3667         len = 2;
3668         res = mono_array_new (domain, System_Reflection_PropertyInfo, len);
3669 handle_parent:
3670         mono_class_setup_vtable (klass);
3671         if (klass->exception_type != MONO_EXCEPTION_NONE) {
3672                 g_hash_table_destroy (properties);
3673                 if (name != NULL)
3674                         g_free (propname);
3675                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3676         }
3677
3678         iter = NULL;
3679         while ((prop = mono_class_get_properties (klass, &iter))) {
3680                 match = 0;
3681                 method = prop->get;
3682                 if (!method)
3683                         method = prop->set;
3684                 if (method)
3685                         flags = method->flags;
3686                 else
3687                         flags = 0;
3688                 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3689                         (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3690                         if (bflags & BFLAGS_Public)
3691                                 match++;
3692                 } else if (bflags & BFLAGS_NonPublic) {
3693                         if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3694                                 property_accessor_nonpublic(prop->set, startklass == klass)) {
3695                                 match++;
3696                         }
3697                 }
3698                 if (!match)
3699                         continue;
3700                 match = 0;
3701                 if (flags & METHOD_ATTRIBUTE_STATIC) {
3702                         if (bflags & BFLAGS_Static)
3703                                 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3704                                         match++;
3705                 } else {
3706                         if (bflags & BFLAGS_Instance)
3707                                 match++;
3708                 }
3709
3710                 if (!match)
3711                         continue;
3712                 match = 0;
3713
3714                 if (name != NULL) {
3715                         if (compare_func (propname, prop->name))
3716                                 continue;
3717                 }
3718                 
3719                 if (g_hash_table_lookup (properties, prop))
3720                         continue;
3721
3722                 if (i >= len) {
3723                         MonoArray *new_res = mono_array_new (domain, System_Reflection_PropertyInfo, len * 2);
3724                         mono_array_memcpy_refs (new_res, 0, res, 0, len);
3725                         len *= 2;
3726                         res = new_res;
3727                 }
3728                 mono_array_setref (res, i, mono_property_get_object (domain, startklass, prop));
3729                 ++i;
3730                 
3731                 g_hash_table_insert (properties, prop, prop);
3732         }
3733         if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3734                 goto handle_parent;
3735
3736         g_hash_table_destroy (properties);
3737         g_free (propname);
3738         if (i != len) {
3739                 MonoArray *new_res = mono_array_new (domain, System_Reflection_PropertyInfo, i);
3740                 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3741                 res = new_res;
3742                 /*
3743                  * Better solution for the new GC.
3744                  * res->max_length = i;
3745                  */
3746         }
3747         return res;
3748 }
3749
3750 static MonoReflectionEvent *
3751 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3752 {
3753         MonoDomain *domain;
3754         MonoClass *klass, *startklass;
3755         gpointer iter;
3756         MonoEvent *event;
3757         MonoMethod *method;
3758         gchar *event_name;
3759
3760         MONO_ARCH_SAVE_REGS;
3761
3762         event_name = mono_string_to_utf8 (name);
3763         if (type->type->byref)
3764                 return NULL;
3765         klass = startklass = mono_class_from_mono_type (type->type);
3766         domain = mono_object_domain (type);
3767
3768 handle_parent:  
3769         if (klass->exception_type != MONO_EXCEPTION_NONE)
3770                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3771
3772         iter = NULL;
3773         while ((event = mono_class_get_events (klass, &iter))) {
3774                 if (strcmp (event->name, event_name))
3775                         continue;
3776
3777                 method = event->add;
3778                 if (!method)
3779                         method = event->remove;
3780                 if (!method)
3781                         method = event->raise;
3782                 if (method) {
3783                         if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3784                                 if (!(bflags & BFLAGS_Public))
3785                                         continue;
3786                         } else {
3787                                 if (!(bflags & BFLAGS_NonPublic))
3788                                         continue;
3789                                 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3790                                         continue;
3791                         }
3792                 }
3793                 else
3794                         if (!(bflags & BFLAGS_NonPublic))
3795                                 continue;
3796
3797                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3798                         if (!(bflags & BFLAGS_Static))
3799                                 continue;
3800                         if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3801                                 continue;
3802                 } else {
3803                         if (!(bflags & BFLAGS_Instance))
3804                                 continue;
3805                 }
3806
3807                 g_free (event_name);
3808                 return mono_event_get_object (domain, startklass, event);
3809         }
3810
3811         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3812                 goto handle_parent;
3813
3814         g_free (event_name);
3815         return NULL;
3816 }
3817
3818 static MonoArray*
3819 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3820 {
3821         MonoDomain *domain; 
3822         static MonoClass *System_Reflection_EventInfo;
3823         MonoClass *startklass, *klass;
3824         MonoArray *res;
3825         MonoMethod *method;
3826         MonoEvent *event;
3827         int i, len, match;
3828         gpointer iter;
3829
3830         MONO_ARCH_SAVE_REGS;
3831
3832         if (!System_Reflection_EventInfo)
3833                 System_Reflection_EventInfo = mono_class_from_name (
3834                         mono_defaults.corlib, "System.Reflection", "EventInfo");
3835
3836         domain = mono_object_domain (type);
3837         if (type->type->byref)
3838                 return mono_array_new (domain, System_Reflection_EventInfo, 0);
3839         klass = startklass = mono_class_from_mono_type (type->type);
3840
3841         i = 0;
3842         len = 2;
3843         res = mono_array_new (domain, System_Reflection_EventInfo, len);
3844 handle_parent:  
3845         if (klass->exception_type != MONO_EXCEPTION_NONE)
3846                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3847
3848         iter = NULL;
3849         while ((event = mono_class_get_events (klass, &iter))) {
3850                 match = 0;
3851                 method = event->add;
3852                 if (!method)
3853                         method = event->remove;
3854                 if (!method)
3855                         method = event->raise;
3856                 if (method) {
3857                         if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3858                                 if (bflags & BFLAGS_Public)
3859                                         match++;
3860                         } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3861                                 if (bflags & BFLAGS_NonPublic)
3862                                         match++;
3863                         }
3864                 }
3865                 else
3866                         if (bflags & BFLAGS_NonPublic)
3867                                 match ++;
3868                 if (!match)
3869                         continue;
3870                 match = 0;
3871                 if (method) {
3872                         if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3873                                 if (bflags & BFLAGS_Static)
3874                                         if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3875                                                 match++;
3876                         } else {
3877                                 if (bflags & BFLAGS_Instance)
3878                                         match++;
3879                         }
3880                 }
3881                 else
3882                         if (bflags & BFLAGS_Instance)
3883                                 match ++;
3884                 if (!match)
3885                         continue;
3886                 match = 0;
3887                 if (i >= len) {
3888                         MonoArray *new_res = mono_array_new (domain, System_Reflection_EventInfo, len * 2);
3889                         mono_array_memcpy_refs (new_res, 0, res, 0, len);
3890                         len *= 2;
3891                         res = new_res;
3892                 }
3893                 mono_array_setref (res, i, mono_event_get_object (domain, startklass, event));
3894                 ++i;
3895         }
3896         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3897                 goto handle_parent;
3898         if (i != len) {
3899                 MonoArray *new_res = mono_array_new (domain, System_Reflection_EventInfo, i);
3900                 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3901                 res = new_res;
3902                 /*
3903                  * Better solution for the new GC.
3904                  * res->max_length = i;
3905                  */
3906         }
3907         return res;
3908 }
3909
3910 static MonoReflectionType *
3911 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3912 {
3913         MonoDomain *domain; 
3914         MonoClass *klass;
3915         MonoClass *nested;
3916         GList *tmpn;
3917         char *str;
3918         
3919         MONO_ARCH_SAVE_REGS;
3920
3921         domain = ((MonoObject *)type)->vtable->domain;
3922         if (type->type->byref)
3923                 return NULL;
3924         klass = mono_class_from_mono_type (type->type);
3925         str = mono_string_to_utf8 (name);
3926
3927  handle_parent:
3928         if (klass->exception_type != MONO_EXCEPTION_NONE)
3929                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3930
3931         /*
3932          * If a nested type is generic, return its generic type definition.
3933          * Note that this means that the return value is essentially a
3934          * nested type of the generic type definition of @klass.
3935          *
3936          * A note in MSDN claims that a generic type definition can have
3937          * nested types that aren't generic.  In any case, the container of that
3938          * nested type would be the generic type definition.
3939          */
3940         if (klass->generic_class)
3941                 klass = klass->generic_class->container_class;
3942
3943         for (tmpn = klass->nested_classes; tmpn; tmpn = tmpn->next) {
3944                 int match = 0;
3945                 nested = tmpn->data;
3946                 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3947                         if (bflags & BFLAGS_Public)
3948                                 match++;
3949                 } else {
3950                         if (bflags & BFLAGS_NonPublic)
3951                                 match++;
3952                 }
3953                 if (!match)
3954                         continue;
3955                 if (strcmp (nested->name, str) == 0){
3956                         g_free (str);
3957                         return mono_type_get_object (domain, &nested->byval_arg);
3958                 }
3959         }
3960         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3961                 goto handle_parent;
3962         g_free (str);
3963         return NULL;
3964 }
3965
3966 static MonoArray*
3967 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
3968 {
3969         MonoDomain *domain; 
3970         GList *tmpn;
3971         MonoClass *klass;
3972         MonoArray *res;
3973         MonoObject *member;
3974         int i, len, match;
3975         MonoClass *nested;
3976
3977         MONO_ARCH_SAVE_REGS;
3978
3979         domain = ((MonoObject *)type)->vtable->domain;
3980         if (type->type->byref)
3981                 return mono_array_new (domain, mono_defaults.monotype_class, 0);
3982         klass = mono_class_from_mono_type (type->type);
3983         if (klass->exception_type != MONO_EXCEPTION_NONE)
3984                 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3985
3986         /*
3987          * If a nested type is generic, return its generic type definition.
3988          * Note that this means that the return value is essentially the set
3989          * of nested types of the generic type definition of @klass.
3990          *
3991          * A note in MSDN claims that a generic type definition can have
3992          * nested types that aren't generic.  In any case, the container of that
3993          * nested type would be the generic type definition.
3994          */
3995         if (klass->generic_class)
3996                 klass = klass->generic_class->container_class;
3997
3998         i = 0;
3999         len = 1;
4000         res = mono_array_new (domain, mono_defaults.monotype_class, len);
4001         for (tmpn = klass->nested_classes; tmpn; tmpn = tmpn->next) {
4002                 match = 0;
4003                 nested = tmpn->data;
4004                 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4005                         if (bflags & BFLAGS_Public)
4006                                 match++;
4007                 } else {
4008                         if (bflags & BFLAGS_NonPublic)
4009                                 match++;
4010                 }
4011                 if (!match)
4012                         continue;
4013                 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4014                 if (i >= len) {
4015                         MonoArray *new_res = mono_array_new (domain, mono_defaults.monotype_class, len * 2);
4016                         mono_array_memcpy_refs (new_res, 0, res, 0, len);
4017                         len *= 2;
4018                         res = new_res;
4019                 }
4020                 mono_array_setref (res, i, member);
4021                 ++i;
4022         }
4023         if (i != len) {
4024                 MonoArray *new_res = mono_array_new (domain, mono_defaults.monotype_class, i);
4025                 mono_array_memcpy_refs (new_res, 0, res, 0, i);
4026                 res = new_res;
4027                 /*
4028                  * Better solution for the new GC.
4029                  * res->max_length = i;
4030                  */
4031         }
4032         return res;
4033 }
4034
4035 static MonoReflectionType*
4036 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4037 {
4038         gchar *str;
4039         MonoType *type = NULL;
4040         MonoTypeNameParse info;
4041         gboolean type_resolve;
4042
4043         MONO_ARCH_SAVE_REGS;
4044
4045         /* On MS.NET, this does not fire a TypeResolve event */
4046         type_resolve = TRUE;
4047         str = mono_string_to_utf8 (name);
4048         /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4049         if (!mono_reflection_parse_type (str, &info)) {
4050                 g_free (str);
4051                 mono_reflection_free_type_info (&info);
4052                 if (throwOnError) /* uhm: this is a parse error, though... */
4053                         mono_raise_exception (mono_get_exception_type_load (name, NULL));
4054                 /*g_print ("failed parse\n");*/
4055                 return NULL;
4056         }
4057
4058         if (info.assembly.name) {
4059                 if (throwOnError) {
4060                         /* 1.0 and 2.0 throw different exceptions */
4061                         if (mono_defaults.generic_ilist_class)
4062                                 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4063                         else
4064                                 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4065                 }
4066                 return NULL;
4067         }
4068
4069         if (module != NULL) {
4070                 if (module->image)
4071                         type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4072                 else
4073                         type = NULL;
4074         }
4075         else
4076                 if (assembly->assembly->dynamic) {
4077                         /* Enumerate all modules */
4078                         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4079                         int i;
4080
4081                         type = NULL;
4082                         if (abuilder->modules) {
4083                                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4084                                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4085                                         type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4086                                         if (type)
4087                                                 break;
4088                                 }
4089                         }
4090
4091                         if (!type && abuilder->loaded_modules) {
4092                                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4093                                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4094                                         type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4095                                         if (type)
4096                                                 break;
4097                                 }
4098                         }
4099                 }
4100                 else
4101                         type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4102         g_free (str);
4103         mono_reflection_free_type_info (&info);
4104         if (!type) {
4105                 MonoException *e = NULL;
4106                 
4107                 if (throwOnError)
4108                         e = mono_get_exception_type_load (name, NULL);
4109
4110                 mono_loader_clear_error ();
4111
4112                 if (e != NULL)
4113                         mono_raise_exception (e);
4114
4115                 return NULL;
4116         }
4117
4118         if (type->type == MONO_TYPE_CLASS) {
4119                 MonoClass *klass = mono_type_get_class (type);
4120                 /* need to report exceptions ? */
4121                 if (throwOnError && klass->exception_type) {
4122                         /* report SecurityException (or others) that occured when loading the assembly */
4123                         MonoException *exc = mono_class_get_exception_for_failure (klass);
4124                         mono_loader_clear_error ();
4125                         mono_raise_exception (exc);
4126                 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4127                         return NULL;
4128                 }
4129         }
4130
4131         /* g_print ("got it\n"); */
4132         return mono_type_get_object (mono_object_domain (assembly), type);
4133 }
4134
4135 static MonoString *
4136 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4137 {
4138         MonoDomain *domain = mono_object_domain (assembly); 
4139         MonoAssembly *mass = assembly->assembly;
4140         MonoString *res = NULL;
4141         gchar *uri;
4142         gchar *absolute;
4143         
4144         MONO_ARCH_SAVE_REGS;
4145
4146         if (g_path_is_absolute (mass->image->name))
4147                 absolute = g_strdup (mass->image->name);
4148         else
4149                 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4150 #if PLATFORM_WIN32
4151         {
4152                 gint i;
4153                 for (i = strlen (absolute) - 1; i >= 0; i--)
4154                         if (absolute [i] == '\\')
4155                                 absolute [i] = '/';
4156         }
4157 #endif
4158         if (escaped) {
4159                 uri = g_filename_to_uri (absolute, NULL, NULL);
4160         } else {
4161                 uri = g_strconcat ("file://", absolute, NULL);
4162         }
4163
4164         if (uri) {
4165                 res = mono_string_new (domain, uri);
4166                 g_free (uri);
4167         }
4168         g_free (absolute);
4169         return res;
4170 }
4171
4172 static MonoBoolean
4173 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4174 {
4175         MonoAssembly *mass = assembly->assembly;
4176
4177         MONO_ARCH_SAVE_REGS;
4178
4179         return mass->in_gac;
4180 }
4181
4182 static MonoReflectionAssembly*
4183 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4184 {
4185         gchar *name;
4186         MonoAssembly *res;
4187         MonoImageOpenStatus status;
4188         
4189         MONO_ARCH_SAVE_REGS;
4190
4191         name = mono_string_to_utf8 (mname);
4192         res = mono_assembly_load_with_partial_name (name, &status);
4193
4194         g_free (name);
4195
4196         if (res == NULL)
4197                 return NULL;
4198         return mono_assembly_get_object (mono_domain_get (), res);
4199 }
4200
4201 static MonoString *
4202 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4203 {
4204         MonoDomain *domain = mono_object_domain (assembly); 
4205         MonoString *res;
4206
4207         MONO_ARCH_SAVE_REGS;
4208
4209         res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4210
4211         return res;
4212 }
4213
4214 static MonoBoolean
4215 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4216 {
4217         MONO_ARCH_SAVE_REGS;
4218
4219         return assembly->assembly->ref_only;
4220 }
4221
4222 static MonoString *
4223 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4224 {
4225         MonoDomain *domain = mono_object_domain (assembly); 
4226
4227         MONO_ARCH_SAVE_REGS;
4228
4229         return mono_string_new (domain, assembly->assembly->image->version);
4230 }
4231
4232 static MonoReflectionMethod*
4233 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly) 
4234 {
4235         guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4236
4237         MONO_ARCH_SAVE_REGS;
4238
4239         if (!token)
4240                 return NULL;
4241         return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4242 }
4243
4244 static MonoReflectionModule*
4245 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly) 
4246 {
4247         return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4248 }
4249
4250 static MonoArray*
4251 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly) 
4252 {
4253         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4254         MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4255         int i;
4256         const char *val;
4257
4258         MONO_ARCH_SAVE_REGS;
4259
4260         for (i = 0; i < table->rows; ++i) {
4261                 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4262                 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4263         }
4264         return result;
4265 }
4266
4267 static MonoObject*
4268 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4269 {
4270         static MonoClass *System_Version = NULL;
4271         static MonoMethod *create_version = NULL;
4272         MonoObject *result;
4273         gpointer args [4];
4274         
4275         if (!System_Version) {
4276                 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4277                 g_assert (System_Version);
4278         }
4279
4280         if (!create_version) {
4281                 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4282                 create_version = mono_method_desc_search_in_class (desc, System_Version);
4283                 g_assert (create_version);
4284                 mono_method_desc_free (desc);
4285         }
4286
4287         args [0] = &major;
4288         args [1] = &minor;
4289         args [2] = &build;
4290         args [3] = &revision;
4291         result = mono_object_new (domain, System_Version);
4292         mono_runtime_invoke (create_version, result, args, NULL);
4293
4294         return result;
4295 }
4296
4297 static MonoArray*
4298 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly) 
4299 {
4300         static MonoClass *System_Reflection_AssemblyName;
4301         MonoArray *result;
4302         MonoDomain *domain = mono_object_domain (assembly);
4303         int i, count = 0;
4304         static MonoMethod *create_culture = NULL;
4305         MonoImage *image = assembly->assembly->image;
4306         MonoTableInfo *t;
4307
4308         MONO_ARCH_SAVE_REGS;
4309
4310         if (!System_Reflection_AssemblyName)
4311                 System_Reflection_AssemblyName = mono_class_from_name (
4312                         mono_defaults.corlib, "System.Reflection", "AssemblyName");
4313
4314         t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4315         count = t->rows;
4316
4317         result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4318
4319         if (count > 0) {
4320                 MonoMethodDesc *desc = mono_method_desc_new (
4321                         "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4322                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4323                 g_assert (create_culture);
4324                 mono_method_desc_free (desc);
4325         }
4326
4327         for (i = 0; i < count; i++) {
4328                 MonoReflectionAssemblyName *aname;
4329                 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4330
4331                 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4332
4333                 aname = (MonoReflectionAssemblyName *) mono_object_new (
4334                         domain, System_Reflection_AssemblyName);
4335
4336                 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4337
4338                 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4339                 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4340                 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4341                 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4342                 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4343                 aname->versioncompat = 1; /* SameMachine (default) */
4344                 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4345                 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4346
4347                 if (create_culture) {
4348                         gpointer args [2];
4349                         gboolean assembly_ref = TRUE;
4350                         args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4351                         args [1] = &assembly_ref;
4352                         MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4353                 }
4354                 
4355                 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4356                         const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4357                         guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4358
4359                         if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4360                                 /* public key token isn't copied - the class library will 
4361                                 automatically generate it from the public key if required */
4362                                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4363                                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4364                         } else {
4365                                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4366                                 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4367                         }
4368                 } else {
4369                         MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4370                 }
4371                 
4372                 /* note: this function doesn't return the codebase on purpose (i.e. it can
4373                          be used under partial trust as path information isn't present). */
4374
4375                 mono_array_setref (result, i, aname);
4376         }
4377         return result;
4378 }
4379
4380 typedef struct {
4381         MonoArray *res;
4382         int idx;
4383 } NameSpaceInfo;
4384
4385 static void
4386 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4387 {
4388         MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4389
4390         mono_array_setref (info->res, info->idx, name);
4391         info->idx++;
4392 }
4393
4394 static MonoArray*
4395 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly) 
4396 {
4397         MonoImage *img = assembly->assembly->image;
4398         MonoArray *res;
4399         NameSpaceInfo info;
4400
4401         MONO_ARCH_SAVE_REGS;
4402
4403         if (!img->name_cache)
4404                 mono_image_init_name_cache (img);
4405
4406         res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, g_hash_table_size (img->name_cache));
4407         info.res = res;
4408         info.idx = 0;
4409         g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4410
4411         return res;
4412 }
4413
4414 /* move this in some file in mono/util/ */
4415 static char *
4416 g_concat_dir_and_file (const char *dir, const char *file)
4417 {
4418         g_return_val_if_fail (dir != NULL, NULL);
4419         g_return_val_if_fail (file != NULL, NULL);
4420
4421         /*
4422          * If the directory name doesn't have a / on the end, we need
4423          * to add one so we get a proper path to the file
4424          */
4425         if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4426                 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4427         else
4428                 return g_strconcat (dir, file, NULL);
4429 }
4430
4431 static void *
4432 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module) 
4433 {
4434         char *n = mono_string_to_utf8 (name);
4435         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4436         guint32 i;
4437         guint32 cols [MONO_MANIFEST_SIZE];
4438         guint32 impl, file_idx;
4439         const char *val;
4440         MonoImage *module;
4441
4442         MONO_ARCH_SAVE_REGS;
4443
4444         for (i = 0; i < table->rows; ++i) {
4445                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4446                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4447                 if (strcmp (val, n) == 0)
4448                         break;
4449         }
4450         g_free (n);
4451         if (i == table->rows)
4452                 return NULL;
4453         /* FIXME */
4454         impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4455         if (impl) {
4456                 /*
4457                  * this code should only be called after obtaining the 
4458                  * ResourceInfo and handling the other cases.
4459                  */
4460                 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4461                 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4462
4463                 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4464                 if (!module)
4465                         return NULL;
4466         }
4467         else
4468                 module = assembly->assembly->image;
4469
4470         *ref_module = mono_module_get_object (mono_domain_get (), module);
4471
4472         return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4473 }
4474
4475 static gboolean
4476 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4477 {
4478         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4479         int i;
4480         guint32 cols [MONO_MANIFEST_SIZE];
4481         guint32 file_cols [MONO_FILE_SIZE];
4482         const char *val;
4483         char *n;
4484
4485         MONO_ARCH_SAVE_REGS;
4486
4487         n = mono_string_to_utf8 (name);
4488         for (i = 0; i < table->rows; ++i) {
4489                 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4490                 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4491                 if (strcmp (val, n) == 0)
4492                         break;
4493         }
4494         g_free (n);
4495         if (i == table->rows)
4496                 return FALSE;
4497
4498         if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4499                 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4500         }
4501         else {
4502                 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4503                 case MONO_IMPLEMENTATION_FILE:
4504                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4505                         table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4506                         mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4507                         val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4508                         MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4509                         if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4510                                 info->location = 0;
4511                         else
4512                                 info->location = RESOURCE_LOCATION_EMBEDDED;
4513                         break;
4514
4515                 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4516                         i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4517                         mono_assembly_load_reference (assembly->assembly->image, i - 1);
4518                         if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4519                                 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4520                                 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4521                                 g_free (msg);
4522                                 mono_raise_exception (ex);
4523                         }
4524                         MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4525
4526                         /* Obtain info recursively */
4527                         ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4528                         info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4529                         break;
4530
4531                 case MONO_IMPLEMENTATION_EXP_TYPE:
4532                         g_assert_not_reached ();
4533                         break;
4534                 }
4535         }
4536
4537         return TRUE;
4538 }
4539
4540 static MonoObject*
4541 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules) 
4542 {
4543         MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4544         MonoArray *result = NULL;
4545         int i, count;
4546         const char *val;
4547         char *n;
4548
4549         MONO_ARCH_SAVE_REGS;
4550
4551         /* check hash if needed */
4552         if (name) {
4553                 n = mono_string_to_utf8 (name);
4554                 for (i = 0; i < table->rows; ++i) {
4555                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4556                         if (strcmp (val, n) == 0) {
4557                                 MonoString *fn;
4558                                 g_free (n);
4559                                 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4560                                 fn = mono_string_new (mono_object_domain (assembly), n);
4561                                 g_free (n);
4562                                 return (MonoObject*)fn;
4563                         }
4564                 }
4565                 g_free (n);
4566                 return NULL;
4567         }
4568
4569         count = 0;
4570         for (i = 0; i < table->rows; ++i) {
4571                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4572                         count ++;
4573         }
4574
4575         result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4576
4577         count = 0;
4578         for (i = 0; i < table->rows; ++i) {
4579                 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4580                         val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4581                         n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4582                         mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4583                         g_free (n);
4584                         count ++;
4585                 }
4586         }
4587         return (MonoObject*)result;
4588 }
4589
4590 static MonoArray*
4591 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4592 {
4593         MonoDomain *domain = mono_domain_get();
4594         MonoArray *res;
4595         MonoClass *klass;
4596         int i, j, file_count = 0;
4597         MonoImage **modules;
4598         guint32 module_count, real_module_count;
4599         MonoTableInfo *table;
4600         guint32 cols [MONO_FILE_SIZE];
4601         MonoImage *image = assembly->assembly->image;
4602
4603         g_assert (image != NULL);
4604         g_assert (!assembly->assembly->dynamic);
4605
4606         table = &image->tables [MONO_TABLE_FILE];
4607         file_count = table->rows;
4608
4609         modules = image->modules;
4610         module_count = image->module_count;
4611
4612         real_module_count = 0;
4613         for (i = 0; i < module_count; ++i)
4614                 if (modules [i])
4615                         real_module_count ++;
4616
4617         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4618         res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4619
4620         mono_array_setref (res, 0, mono_module_get_object (domain, image));
4621         j = 1;
4622         for (i = 0; i < module_count; ++i)
4623                 if (modules [i]) {
4624                         mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4625                         ++j;
4626                 }
4627
4628         for (i = 0; i < file_count; ++i, ++j) {
4629                 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4630                 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4631                         mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4632                 else {
4633                         MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4634                         if (!m) {
4635                                 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4636                                 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4637                         }
4638                         mono_array_setref (res, j, mono_module_get_object (domain, m));
4639                 }
4640         }
4641
4642         return res;
4643 }
4644
4645 static MonoReflectionMethod*
4646 ves_icall_GetCurrentMethod (void) 
4647 {
4648         MonoMethod *m = mono_method_get_last_managed ();
4649
4650         MONO_ARCH_SAVE_REGS;
4651
4652         return mono_method_get_object (mono_domain_get (), m, NULL);
4653 }
4654
4655 static MonoReflectionMethod*
4656 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4657 {
4658         /* FIXME check that method belongs to klass or a parent */
4659         MonoClass *klass;
4660         if (type)
4661                 klass = mono_class_from_mono_type (type);
4662         else
4663                 klass = method->klass;
4664         return mono_method_get_object (mono_domain_get (), method, klass);
4665 }
4666
4667 static MonoReflectionMethod*
4668 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4669 {
4670         return mono_method_get_object (mono_domain_get (), method, NULL);
4671 }
4672
4673 static MonoReflectionMethodBody*
4674 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4675 {
4676         return mono_method_body_get_object (mono_domain_get (), method);
4677 }
4678
4679 static MonoReflectionAssembly*
4680 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4681 {
4682         MonoMethod *m = mono_method_get_last_managed ();
4683
4684         MONO_ARCH_SAVE_REGS;
4685
4686         return mono_assembly_get_object (mono_domain_get (), m->klass->image->assembly);
4687 }
4688
4689
4690 static MonoReflectionAssembly*
4691 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4692 {
4693         MonoDomain* domain = mono_domain_get ();
4694
4695         MONO_ARCH_SAVE_REGS;
4696
4697         if (!domain->entry_assembly)
4698                 return NULL;
4699
4700         return mono_assembly_get_object (domain, domain->entry_assembly);
4701 }
4702
4703 static MonoReflectionAssembly*
4704 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4705 {
4706         MonoMethod *m = mono_method_get_last_managed ();
4707         MonoMethod *dest = m;
4708
4709         MONO_ARCH_SAVE_REGS;
4710
4711         mono_stack_walk_no_il (get_caller, &dest);
4712         if (!dest)
4713                 dest = m;
4714         return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4715 }
4716
4717 static MonoString *
4718 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4719                                        gboolean assembly_qualified)
4720 {
4721         MonoDomain *domain = mono_object_domain (object); 
4722         MonoTypeNameFormat format;
4723         MonoString *res;
4724         gchar *name;
4725
4726         MONO_ARCH_SAVE_REGS;
4727         if (full_name)
4728                 format = assembly_qualified ?
4729                         MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4730                         MONO_TYPE_NAME_FORMAT_FULL_NAME;
4731         else
4732                 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4733  
4734         name = mono_type_get_name_full (object->type, format);
4735         if (!name)
4736                 return NULL;
4737
4738         if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4739                 g_free (name);
4740                 return NULL;
4741         }
4742
4743         res = mono_string_new (domain, name);
4744         g_free (name);
4745
4746         return res;
4747 }
4748
4749 static void
4750 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4751 {
4752         static MonoMethod *create_culture = NULL;
4753         gpointer args [2];
4754         guint32 pkey_len;
4755         const char *pkey_ptr;
4756         gchar *codebase;
4757         gboolean assembly_ref = FALSE;
4758
4759         MONO_ARCH_SAVE_REGS;
4760
4761         MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4762         aname->major = name->major;
4763         aname->minor = name->minor;
4764         aname->build = name->build;
4765         aname->flags = name->flags;
4766         aname->revision = name->revision;
4767         aname->hashalg = name->hash_alg;
4768         aname->versioncompat = 1; /* SameMachine (default) */
4769
4770         if (by_default_version)
4771                 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4772         
4773         codebase = g_filename_to_uri (absolute, NULL, NULL);
4774         if (codebase) {
4775                 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4776                 g_free (codebase);
4777         }
4778
4779         if (!create_culture) {
4780                 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4781                 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4782                 g_assert (create_culture);
4783                 mono_method_desc_free (desc);
4784         }
4785
4786         if (name->culture) {
4787                 args [0] = mono_string_new (domain, name->culture);
4788                 args [1] = &assembly_ref;
4789                 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4790         }
4791
4792         if (name->public_key) {
4793                 pkey_ptr = (char*)name->public_key;
4794                 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4795
4796                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4797                 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4798                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4799         } else if (default_publickey) {
4800                 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4801                 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4802         }
4803
4804         /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4805         if (name->public_key_token [0]) {
4806                 int i, j;
4807                 char *p;
4808
4809                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4810                 p = mono_array_addr (aname->keyToken, char, 0);
4811
4812                 for (i = 0, j = 0; i < 8; i++) {
4813                         *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4814                         *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4815                         p++;
4816                 }
4817         } else if (default_token) {
4818                 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4819         }
4820 }
4821
4822 static MonoString *
4823 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
4824 {
4825         MonoDomain *domain = mono_object_domain (assembly); 
4826         MonoAssembly *mass = assembly->assembly;
4827         MonoString *res;
4828         gchar *name;
4829
4830         name = g_strdup_printf (
4831                 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
4832                 mass->aname.name,
4833                 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
4834                 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
4835                 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
4836                 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
4837
4838         res = mono_string_new (domain, name);
4839         g_free (name);
4840
4841         return res;
4842 }
4843
4844 static void
4845 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
4846 {
4847         gchar *absolute;
4848         MonoAssembly *mass = assembly->assembly;
4849
4850         MONO_ARCH_SAVE_REGS;
4851
4852         if (g_path_is_absolute (mass->image->name)) {
4853                 fill_reflection_assembly_name (mono_object_domain (assembly),
4854                         aname, &mass->aname, mass->image->name, TRUE,
4855                         TRUE, mono_get_runtime_info ()->framework_version [0] >= '2');
4856                 return;
4857         }
4858         absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4859
4860         fill_reflection_assembly_name (mono_object_domain (assembly),
4861                 aname, &mass->aname, absolute, TRUE, TRUE,
4862                 mono_get_runtime_info ()->framework_version [0] >= '2');
4863
4864         g_free (absolute);
4865 }
4866
4867 static void
4868 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
4869 {
4870         char *filename;
4871         MonoImageOpenStatus status = MONO_IMAGE_OK;
4872         gboolean res;
4873         MonoImage *image;
4874         MonoAssemblyName name;
4875
4876         MONO_ARCH_SAVE_REGS;
4877
4878         filename = mono_string_to_utf8 (fname);
4879
4880         image = mono_image_open (filename, &status);
4881
4882         if (!image){
4883                 MonoException *exc;
4884
4885                 g_free (filename);
4886                 if (status == MONO_IMAGE_IMAGE_INVALID)
4887                         exc = mono_get_exception_bad_image_format2 (NULL, fname);
4888                 else
4889                         exc = mono_get_exception_file_not_found2 (NULL, fname);
4890                 mono_raise_exception (exc);
4891         }
4892
4893         res = mono_assembly_fill_assembly_name (image, &name);
4894         if (!res) {
4895                 mono_image_close (image);
4896                 g_free (filename);
4897                 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
4898         }
4899
4900         fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
4901                 TRUE, mono_get_runtime_info ()->framework_version [0] == '1',
4902                 mono_get_runtime_info ()->framework_version [0] >= '2');
4903
4904         g_free (filename);
4905         mono_image_close (image);
4906 }
4907
4908 static MonoBoolean
4909 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
4910         char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
4911 {
4912         MonoBoolean result = FALSE;
4913         MonoDeclSecurityEntry entry;
4914
4915         /* SecurityAction.RequestMinimum */
4916         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
4917                 *minimum = entry.blob;
4918                 *minLength = entry.size;
4919                 result = TRUE;
4920         }
4921         /* SecurityAction.RequestOptional */
4922         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
4923                 *optional = entry.blob;
4924                 *optLength = entry.size;
4925                 result = TRUE;
4926         }
4927         /* SecurityAction.RequestRefuse */
4928         if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
4929                 *refused = entry.blob;
4930                 *refLength = entry.size;
4931                 result = TRUE;
4932         }
4933
4934         return result;  
4935 }
4936
4937 static MonoArray*
4938 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoBoolean exportedOnly)
4939 {
4940         MonoArray *res;
4941         MonoClass *klass;
4942         MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
4943         int i, count;
4944         guint32 attrs, visibility;
4945
4946         /* we start the count from 1 because we skip the special type <Module> */
4947         if (exportedOnly) {
4948                 count = 0;
4949                 for (i = 1; i < tdef->rows; ++i) {
4950                         attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
4951                         visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4952                         if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
4953                                 count++;
4954                 }
4955         } else {
4956                 count = tdef->rows - 1;
4957         }
4958         res = mono_array_new (domain, mono_defaults.monotype_class, count);
4959         count = 0;
4960         for (i = 1; i < tdef->rows; ++i) {
4961                 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
4962                 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4963                 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
4964                         klass = mono_class_get_throw (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
4965                         if (mono_loader_get_last_error ())
4966                                 mono_loader_clear_error ();
4967                         mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
4968                         count++;
4969                 }
4970         }
4971         
4972         return res;
4973 }
4974
4975 static MonoArray*
4976 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
4977 {
4978         MonoArray *res = NULL;
4979         MonoImage *image = NULL;
4980         MonoTableInfo *table = NULL;
4981         MonoDomain *domain;
4982         GList *list = NULL;
4983         int i, len;
4984
4985         MONO_ARCH_SAVE_REGS;
4986
4987         domain = mono_object_domain (assembly);
4988
4989         g_assert (!assembly->assembly->dynamic);
4990         image = assembly->assembly->image;
4991         table = &image->tables [MONO_TABLE_FILE];
4992         res = mono_module_get_types (domain, image, exportedOnly);
4993
4994         /* Append data from all modules in the assembly */
4995         for (i = 0; i < table->rows; ++i) {
4996                 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4997                         MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
4998                         if (loaded_image) {
4999                                 MonoArray *res2 = mono_module_get_types (domain, loaded_image, exportedOnly);
5000                                 /* Append the new types to the end of the array */
5001                                 if (mono_array_length (res2) > 0) {
5002                                         guint32 len1, len2;
5003                                         MonoArray *res3;
5004
5005                                         len1 = mono_array_length (res);
5006                                         len2 = mono_array_length (res2);
5007                                         res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5008                                         mono_array_memcpy_refs (res3, 0, res, 0, len1);
5009                                         mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5010                                         res = res3;
5011                                 }
5012                         }
5013                 }
5014         }
5015
5016         /* the ReflectionTypeLoadException must have all the types (Types property), 
5017          * NULL replacing types which throws an exception. The LoaderException must
5018          * contain all exceptions for NULL items.
5019          */
5020
5021         len = mono_array_length (res);
5022
5023         for (i = 0; i < len; i++) {
5024                 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5025                 MonoClass *klass = mono_type_get_class (t->type);
5026                 if ((klass != NULL) && klass->exception_type) {
5027                         /* keep the class in the list */
5028                         list = g_list_append (list, klass);
5029                         /* and replace Type with NULL */
5030                         mono_array_setref (res, i, NULL);
5031                 }
5032         }
5033
5034         if (list) {
5035                 GList *tmp = NULL;
5036                 MonoException *exc = NULL;
5037                 MonoArray *exl = NULL;
5038                 int length = g_list_length (list);
5039
5040                 mono_loader_clear_error ();
5041
5042                 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5043                 for (i = 0, tmp = list; i < length; i++, tmp = tmp->next) {
5044                         MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5045                         mono_array_setref (exl, i, exc);
5046                 }
5047                 g_list_free (list);
5048                 list = NULL;
5049
5050                 exc = mono_get_exception_reflection_type_load (res, exl);
5051                 mono_loader_clear_error ();
5052                 mono_raise_exception (exc);
5053         }
5054                 
5055         return res;
5056 }
5057
5058 static gboolean
5059 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5060 {
5061         MonoAssemblyName aname;
5062         MonoDomain *domain = mono_object_domain (name);
5063         char *val;
5064         gboolean is_version_defined;
5065         gboolean is_token_defined;
5066
5067         val = mono_string_to_utf8 (assname);
5068         if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined))
5069                 return FALSE;
5070         
5071         fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5072                 FALSE, is_token_defined);
5073
5074         mono_assembly_name_free (&aname);
5075         g_free ((guint8*) aname.public_key);
5076         g_free (val);
5077
5078         return TRUE;
5079 }
5080
5081 static MonoReflectionType*
5082 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5083 {
5084         MonoDomain *domain = mono_object_domain (module); 
5085         MonoClass *klass;
5086
5087         MONO_ARCH_SAVE_REGS;
5088
5089         g_assert (module->image);
5090
5091         if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5092                 /* These images do not have a global type */
5093                 return NULL;
5094
5095         klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5096         return mono_type_get_object (domain, &klass->byval_arg);
5097 }
5098
5099 static void
5100 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5101 {
5102         /*if (module->image)
5103                 mono_image_close (module->image);*/
5104 }
5105
5106 static MonoString*
5107 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5108 {
5109         MonoDomain *domain = mono_object_domain (module); 
5110
5111         MONO_ARCH_SAVE_REGS;
5112
5113         g_assert (module->image);
5114         return mono_string_new (domain, module->image->guid);
5115 }
5116
5117 static void
5118 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5119 {
5120         if (image->dynamic) {
5121                 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5122                 *pe_kind = dyn->pe_kind;
5123                 *machine = dyn->machine;
5124         }
5125         else {
5126                 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5127                 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5128         }
5129 }
5130
5131 static gint32
5132 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5133 {
5134         return (image->md_version_major << 16) | (image->md_version_minor);
5135 }
5136
5137 static MonoArray*
5138 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5139 {
5140         MONO_ARCH_SAVE_REGS;
5141
5142         if (!module->image)
5143                 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5144         else
5145                 return mono_module_get_types (mono_object_domain (module), module->image, FALSE);
5146 }
5147
5148 static gboolean
5149 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5150 {
5151         guint32 cols [MONO_MEMBERREF_SIZE];
5152         const char *sig;
5153         mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5154         sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5155         mono_metadata_decode_blob_size (sig, &sig);
5156         return (*sig != 0x6);
5157 }
5158
5159 static void
5160 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5161 {
5162         if (type_args)
5163                 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5164                                                                       mono_array_addr (type_args, MonoType*, 0));
5165         else
5166                 context->class_inst = NULL;
5167         if (method_args)
5168                 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5169                                                                        mono_array_addr (method_args, MonoType*, 0));
5170         else
5171                 context->method_inst = NULL;
5172 }
5173
5174 static MonoType*
5175 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5176 {
5177         MonoClass *klass;
5178         int table = mono_metadata_token_table (token);
5179         int index = mono_metadata_token_index (token);
5180         MonoGenericContext context;
5181
5182         *error = ResolveTokenError_Other;
5183
5184         /* Validate token */
5185         if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) && 
5186                 (table != MONO_TABLE_TYPESPEC)) {
5187                 *error = ResolveTokenError_BadTable;
5188                 return NULL;
5189         }
5190
5191         if (image->dynamic) {
5192                 if (type_args || method_args)
5193                         mono_raise_exception (mono_get_exception_not_implemented (NULL));
5194                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5195         }
5196
5197         if ((index <= 0) || (index > image->tables [table].rows)) {
5198                 *error = ResolveTokenError_OutOfRange;
5199                 return NULL;
5200         }
5201
5202         init_generic_context_from_args (&context, type_args, method_args);
5203         klass = mono_class_get_full (image, token, &context);
5204
5205         if (mono_loader_get_last_error ())
5206                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5207
5208         if (klass)
5209                 return &klass->byval_arg;
5210         else
5211                 return NULL;
5212 }
5213
5214 static MonoMethod*
5215 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5216 {
5217         int table = mono_metadata_token_table (token);
5218         int index = mono_metadata_token_index (token);
5219         MonoGenericContext context;
5220         MonoMethod *method;
5221
5222         *error = ResolveTokenError_Other;
5223
5224         /* Validate token */
5225         if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) && 
5226                 (table != MONO_TABLE_MEMBERREF)) {
5227                 *error = ResolveTokenError_BadTable;
5228                 return NULL;
5229         }
5230
5231         if (image->dynamic) {
5232                 if (type_args || method_args)
5233                         mono_raise_exception (mono_get_exception_not_implemented (NULL));
5234                 /* FIXME: validate memberref token type */
5235                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5236         }
5237
5238         if ((index <= 0) || (index > image->tables [table].rows)) {
5239                 *error = ResolveTokenError_OutOfRange;
5240                 return NULL;
5241         }
5242         if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5243                 *error = ResolveTokenError_BadTable;
5244                 return NULL;
5245         }
5246
5247         init_generic_context_from_args (&context, type_args, method_args);
5248         method = mono_get_method_full (image, token, NULL, &context);
5249
5250         if (mono_loader_get_last_error ())
5251                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5252
5253         return method;
5254 }
5255
5256 static MonoString*
5257 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5258 {
5259         int index = mono_metadata_token_index (token);
5260
5261         *error = ResolveTokenError_Other;
5262
5263         /* Validate token */
5264         if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5265                 *error = ResolveTokenError_BadTable;
5266                 return NULL;
5267         }
5268
5269         if (image->dynamic)
5270                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5271
5272         if ((index <= 0) || (index >= image->heap_us.size)) {
5273                 *error = ResolveTokenError_OutOfRange;
5274                 return NULL;
5275         }
5276
5277         /* FIXME: What to do if the index points into the middle of a string ? */
5278
5279         return mono_ldstr (mono_domain_get (), image, index);
5280 }
5281
5282 static MonoClassField*
5283 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5284 {
5285         MonoClass *klass;
5286         int table = mono_metadata_token_table (token);
5287         int index = mono_metadata_token_index (token);
5288         MonoGenericContext context;
5289         MonoClassField *field;
5290
5291         *error = ResolveTokenError_Other;
5292
5293         /* Validate token */
5294         if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5295                 *error = ResolveTokenError_BadTable;
5296                 return NULL;
5297         }
5298
5299         if (image->dynamic) {
5300                 if (type_args || method_args)
5301                         mono_raise_exception (mono_get_exception_not_implemented (NULL));
5302                 /* FIXME: validate memberref token type */
5303                 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5304         }
5305
5306         if ((index <= 0) || (index > image->tables [table].rows)) {
5307                 *error = ResolveTokenError_OutOfRange;
5308                 return NULL;
5309         }
5310         if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5311                 *error = ResolveTokenError_BadTable;
5312                 return NULL;
5313         }
5314
5315         init_generic_context_from_args (&context, type_args, method_args);
5316         field = mono_field_from_token (image, token, &klass, &context);
5317
5318         if (mono_loader_get_last_error ())
5319                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5320         
5321         return field;
5322 }
5323
5324
5325 static MonoObject*
5326 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5327 {
5328         int table = mono_metadata_token_table (token);
5329
5330         *error = ResolveTokenError_Other;
5331
5332         switch (table) {
5333         case MONO_TABLE_TYPEDEF:
5334         case MONO_TABLE_TYPEREF:
5335         case MONO_TABLE_TYPESPEC: {
5336                 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5337                 if (t)
5338                         return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5339                 else
5340                         return NULL;
5341         }
5342         case MONO_TABLE_METHOD:
5343         case MONO_TABLE_METHODSPEC: {
5344                 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5345                 if (m)
5346                         return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5347                 else
5348                         return NULL;
5349         }               
5350         case MONO_TABLE_FIELD: {
5351                 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5352                 if (f)
5353                         return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5354                 else
5355                         return NULL;
5356         }
5357         case MONO_TABLE_MEMBERREF:
5358                 if (mono_metadata_memberref_is_method (image, token)) {
5359                         MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5360                         if (m)
5361                                 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5362                         else
5363                                 return NULL;
5364                 }
5365                 else {
5366                         MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5367                         if (f)
5368                                 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5369                         else
5370                                 return NULL;
5371                 }
5372                 break;
5373
5374         default:
5375                 *error = ResolveTokenError_BadTable;
5376         }
5377
5378         return NULL;
5379 }
5380
5381 static MonoArray*
5382 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5383 {
5384         int table = mono_metadata_token_table (token);
5385         int idx = mono_metadata_token_index (token);
5386         MonoTableInfo *tables = image->tables;
5387         guint32 sig, len;
5388         const char *ptr;
5389         MonoArray *res;
5390
5391         *error = ResolveTokenError_OutOfRange;
5392
5393         /* FIXME: Support other tables ? */
5394         if (table != MONO_TABLE_STANDALONESIG)
5395                 return NULL;
5396
5397         if (image->dynamic)
5398                 return NULL;
5399
5400         if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5401                 return NULL;
5402
5403         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5404
5405         ptr = mono_metadata_blob_heap (image, sig);
5406         len = mono_metadata_decode_blob_size (ptr, &ptr);
5407
5408         res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5409         memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5410         return res;
5411 }
5412
5413 static MonoReflectionType*
5414 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5415 {
5416         MonoClass *klass;
5417         int isbyref = 0, rank;
5418         char *str = mono_string_to_utf8 (smodifiers);
5419         char *p;
5420
5421         MONO_ARCH_SAVE_REGS;
5422
5423         klass = mono_class_from_mono_type (tb->type.type);
5424         p = str;
5425         /* logic taken from mono_reflection_parse_type(): keep in sync */
5426         while (*p) {
5427                 switch (*p) {
5428                 case '&':
5429                         if (isbyref) { /* only one level allowed by the spec */
5430                                 g_free (str);
5431                                 return NULL;
5432                         }
5433                         isbyref = 1;
5434                         p++;
5435                         g_free (str);
5436                         return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5437                         break;
5438                 case '*':
5439                         klass = mono_ptr_class_get (&klass->byval_arg);
5440                         mono_class_init (klass);
5441                         p++;
5442                         break;
5443                 case '[':
5444                         rank = 1;
5445                         p++;
5446                         while (*p) {
5447                                 if (*p == ']')
5448                                         break;
5449                                 if (*p == ',')
5450                                         rank++;
5451                                 else if (*p != '*') { /* '*' means unknown lower bound */
5452                                         g_free (str);
5453                                         return NULL;
5454                                 }
5455                                 ++p;
5456                         }
5457                         if (*p != ']') {
5458                                 g_free (str);
5459                                 return NULL;
5460                         }
5461                         p++;
5462                         klass = mono_array_class_get (klass, rank);
5463                         mono_class_init (klass);
5464                         break;
5465                 default:
5466                         break;
5467                 }
5468         }
5469         g_free (str);
5470         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5471 }
5472
5473 static MonoBoolean
5474 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5475 {
5476         MonoType *type;
5477         MonoBoolean res;
5478
5479         MONO_ARCH_SAVE_REGS;
5480
5481         type = t->type;
5482         res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5483
5484         return res;
5485 }
5486
5487 static MonoReflectionType *
5488 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5489 {
5490         MonoClass *klass, *aklass;
5491
5492         MONO_ARCH_SAVE_REGS;
5493
5494         klass = mono_class_from_mono_type (type->type);
5495         aklass = mono_array_class_get (klass, rank);
5496
5497         return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5498 }
5499
5500 static MonoReflectionType *
5501 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5502 {
5503         MonoClass *klass;
5504
5505         MONO_ARCH_SAVE_REGS;
5506
5507         klass = mono_class_from_mono_type (type->type);
5508
5509         return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5510 }
5511
5512 static MonoReflectionType *
5513 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5514 {
5515         MonoClass *pklass;
5516
5517         MONO_ARCH_SAVE_REGS;
5518
5519         pklass = mono_ptr_class_get (type->type);
5520
5521         return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5522 }
5523
5524 static MonoObject *
5525 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5526                                                    MonoReflectionMethod *info)
5527 {
5528         MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5529         MonoObject *delegate;
5530         gpointer func;
5531
5532         MONO_ARCH_SAVE_REGS;
5533
5534         mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5535
5536         delegate = mono_object_new (mono_object_domain (type), delegate_class);
5537
5538         if (info->method->dynamic)
5539                 /* Creating a trampoline would leak memory */
5540                 func = mono_compile_method (info->method);
5541         else
5542                 func = mono_create_ftnptr (mono_domain_get (), mono_runtime_create_jump_trampoline (mono_domain_get (), info->method, TRUE));
5543
5544         mono_delegate_ctor (delegate, target, func);
5545
5546         return delegate;
5547 }
5548
5549 static void
5550 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5551 {
5552         /* Reset the invoke impl to the default one */
5553         this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5554 }
5555
5556 /*
5557  * Magic number to convert a time which is relative to
5558  * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5559  */
5560 #define EPOCH_ADJUST    ((guint64)62135596800LL)
5561
5562 /*
5563  * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5564  */
5565 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5566
5567 #ifdef PLATFORM_WIN32
5568 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5569 static void
5570 convert_to_absolute_date(SYSTEMTIME *date)
5571 {
5572 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5573         static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5574         static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5575         /* from the calendar FAQ */
5576         int a = (14 - date->wMonth) / 12;
5577         int y = date->wYear - a;
5578         int m = date->wMonth + 12 * a - 2;
5579         int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5580
5581         /* d is now the day of the week for the first of the month (0 == Sunday) */
5582
5583         int day_of_week = date->wDayOfWeek;
5584
5585         /* set day_in_month to the first day in the month which falls on day_of_week */    
5586         int day_in_month = 1 + (day_of_week - d);
5587         if (day_in_month <= 0)
5588                 day_in_month += 7;
5589
5590         /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5591         date->wDay = day_in_month + (date->wDay - 1) * 7;
5592         if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5593                 date->wDay -= 7;
5594 }
5595 #endif
5596
5597 #ifndef PLATFORM_WIN32
5598 /*
5599  * Return's the offset from GMT of a local time.
5600  * 
5601  *  tm is a local time
5602  *  t  is the same local time as seconds.
5603  */
5604 static int 
5605 gmt_offset(struct tm *tm, time_t t)
5606 {
5607 #if defined (HAVE_TM_GMTOFF)
5608         return tm->tm_gmtoff;
5609 #else
5610         struct tm g;
5611         time_t t2;
5612         g = *gmtime(&t);
5613         g.tm_isdst = tm->tm_isdst;
5614         t2 = mktime(&g);
5615         return (int)difftime(t, t2);
5616 #endif
5617 }
5618 #endif
5619 /*
5620  * This is heavily based on zdump.c from glibc 2.2.
5621  *
5622  *  * data[0]:  start of daylight saving time (in DateTime ticks).
5623  *  * data[1]:  end of daylight saving time (in DateTime ticks).
5624  *  * data[2]:  utcoffset (in TimeSpan ticks).
5625  *  * data[3]:  additional offset when daylight saving (in TimeSpan ticks).
5626  *  * name[0]:  name of this timezone when not daylight saving.
5627  *  * name[1]:  name of this timezone when daylight saving.
5628  *
5629  *  FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5630  *         the class library allows years between 1 and 9999.
5631  *
5632  *  Returns true on success and zero on failure.
5633  */
5634 static guint32
5635 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5636 {
5637 #ifndef PLATFORM_WIN32
5638         MonoDomain *domain = mono_domain_get ();
5639         struct tm start, tt;
5640         time_t t;
5641
5642         long int gmtoff;
5643         int is_daylight = 0, day;
5644         char tzone [64];
5645
5646         MONO_ARCH_SAVE_REGS;
5647
5648         MONO_CHECK_ARG_NULL (data);
5649         MONO_CHECK_ARG_NULL (names);
5650
5651         (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
5652         (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
5653
5654         /* 
5655          * no info is better than crashing: we'll need our own tz data
5656          * to make this work properly, anyway. The range is probably
5657          * reduced to 1970 .. 2037 because that is what mktime is
5658          * guaranteed to support (we get into an infinite loop
5659          * otherwise).
5660          */
5661
5662         memset (&start, 0, sizeof (start));
5663
5664         start.tm_mday = 1;
5665         start.tm_year = year-1900;
5666
5667         t = mktime (&start);
5668
5669         if ((year < 1970) || (year > 2037) || (t == -1)) {
5670                 t = time (NULL);
5671                 tt = *localtime (&t);
5672                 strftime (tzone, sizeof (tzone), "%Z", &tt);
5673                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5674                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5675                 return 1;
5676         }
5677
5678         gmtoff = gmt_offset (&start, t);
5679
5680         /* For each day of the year, calculate the tm_gmtoff. */
5681         for (day = 0; day < 365; day++) {
5682
5683                 t += 3600*24;
5684                 tt = *localtime (&t);
5685
5686                 /* Daylight saving starts or ends here. */
5687                 if (gmt_offset (&tt, t) != gmtoff) {
5688                         struct tm tt1;
5689                         time_t t1;
5690
5691                         /* Try to find the exact hour when daylight saving starts/ends. */
5692                         t1 = t;
5693                         do {
5694                                 t1 -= 3600;
5695                                 tt1 = *localtime (&t1);
5696                         } while (gmt_offset (&tt1, t1) != gmtoff);
5697
5698                         /* Try to find the exact minute when daylight saving starts/ends. */
5699                         do {
5700                                 t1 += 60;
5701                                 tt1 = *localtime (&t1);
5702                         } while (gmt_offset (&tt1, t1) == gmtoff);
5703                         t1+=gmtoff;
5704                         strftime (tzone, sizeof (tzone), "%Z", &tt);
5705                         
5706                         /* Write data, if we're already in daylight saving, we're done. */
5707                         if (is_daylight) {
5708                                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5709                                 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5710                                 return 1;
5711                         } else {
5712                                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5713                                 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5714                                 is_daylight = 1;
5715                         }
5716
5717                         /* This is only set once when we enter daylight saving. */
5718                         mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
5719                         mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
5720
5721                         gmtoff = gmt_offset (&tt, t);
5722                 }
5723         }
5724
5725         if (!is_daylight) {
5726                 strftime (tzone, sizeof (tzone), "%Z", &tt);
5727                 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5728                 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5729                 mono_array_set ((*data), gint64, 0, 0);
5730                 mono_array_set ((*data), gint64, 1, 0);
5731                 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
5732                 mono_array_set ((*data), gint64, 3, 0);
5733         }
5734
5735         return 1;
5736 #else
5737         MonoDomain *domain = mono_domain_get ();
5738         TIME_ZONE_INFORMATION tz_info;
5739         FILETIME ft;
5740         int i;
5741         int err, tz_id;
5742
5743         tz_id = GetTimeZoneInformation (&tz_info);
5744         if (tz_id == TIME_ZONE_ID_INVALID)
5745                 return 0;
5746
5747         MONO_CHECK_ARG_NULL (data);
5748         MONO_CHECK_ARG_NULL (names);
5749
5750         (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
5751         (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
5752
5753         for (i = 0; i < 32; ++i)
5754                 if (!tz_info.DaylightName [i])
5755                         break;
5756         mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
5757         for (i = 0; i < 32; ++i)
5758                 if (!tz_info.StandardName [i])
5759                         break;
5760         mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
5761
5762         if ((year <= 1601) || (year > 30827)) {
5763                 /*
5764                  * According to MSDN, the MS time functions can't handle dates outside
5765                  * this interval.
5766                  */
5767                 return 1;
5768         }
5769
5770         /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
5771         if (tz_id != TIME_ZONE_ID_UNKNOWN) {
5772                 tz_info.StandardDate.wYear = year;
5773                 convert_to_absolute_date(&tz_info.StandardDate);
5774                 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
5775                 //g_assert(err);
5776                 if (err == 0)
5777                         return 0;
5778                 
5779                 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
5780                 tz_info.DaylightDate.wYear = year;
5781                 convert_to_absolute_date(&tz_info.DaylightDate);
5782                 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
5783                 //g_assert(err);
5784                 if (err == 0)
5785                         return 0;
5786                 
5787                 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
5788         }
5789         mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
5790         mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
5791
5792         return 1;
5793 #endif
5794 }
5795
5796 static gpointer
5797 ves_icall_System_Object_obj_address (MonoObject *this) 
5798 {
5799         MONO_ARCH_SAVE_REGS;
5800
5801         return this;
5802 }
5803
5804 /* System.Buffer */
5805
5806 static inline gint32 
5807 mono_array_get_byte_length (MonoArray *array)
5808 {
5809         MonoClass *klass;
5810         int length;
5811         int i;
5812
5813         klass = array->obj.vtable->klass;
5814
5815         if (array->bounds == NULL)
5816                 length = array->max_length;
5817         else {
5818                 length = 1;
5819                 for (i = 0; i < klass->rank; ++ i)
5820                         length *= array->bounds [i].length;
5821         }
5822
5823         switch (klass->element_class->byval_arg.type) {
5824         case MONO_TYPE_I1:
5825         case MONO_TYPE_U1:
5826         case MONO_TYPE_BOOLEAN:
5827                 return length;
5828         case MONO_TYPE_I2:
5829         case MONO_TYPE_U2:
5830         case MONO_TYPE_CHAR:
5831                 return length << 1;
5832         case MONO_TYPE_I4:
5833         case MONO_TYPE_U4:
5834         case MONO_TYPE_R4:
5835                 return length << 2;
5836         case MONO_TYPE_I:
5837         case MONO_TYPE_U:
5838                 return length * sizeof (gpointer);
5839         case MONO_TYPE_I8:
5840         case MONO_TYPE_U8:
5841         case MONO_TYPE_R8:
5842                 return length << 3;
5843         default:
5844                 return -1;
5845         }
5846 }
5847
5848 static gint32 
5849 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array) 
5850 {
5851         MONO_ARCH_SAVE_REGS;
5852
5853         return mono_array_get_byte_length (array);
5854 }
5855
5856 static gint8 
5857 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx) 
5858 {
5859         MONO_ARCH_SAVE_REGS;
5860
5861         return mono_array_get (array, gint8, idx);
5862 }
5863
5864 static void 
5865 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value) 
5866 {
5867         MONO_ARCH_SAVE_REGS;
5868
5869         mono_array_set (array, gint8, idx, value);
5870 }
5871
5872 static MonoBoolean
5873 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count) 
5874 {
5875         guint8 *src_buf, *dest_buf;
5876
5877         MONO_ARCH_SAVE_REGS;
5878
5879         /* watch out for integer overflow */
5880         if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
5881                 return FALSE;
5882
5883         src_buf = (guint8 *)src->vector + src_offset;
5884         dest_buf = (guint8 *)dest->vector + dest_offset;
5885
5886         if (src != dest)
5887                 memcpy (dest_buf, src_buf, count);
5888         else
5889                 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
5890
5891         return TRUE;
5892 }
5893
5894 static MonoObject *
5895 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
5896 {
5897         MonoDomain *domain = mono_object_domain (this); 
5898         MonoObject *res;
5899         MonoRealProxy *rp = ((MonoRealProxy *)this);
5900         MonoTransparentProxy *tp;
5901         MonoType *type;
5902         MonoClass *klass;
5903
5904         MONO_ARCH_SAVE_REGS;
5905
5906         res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
5907         tp = (MonoTransparentProxy*) res;
5908         
5909         MONO_OBJECT_SETREF (tp, rp, rp);
5910         type = ((MonoReflectionType *)rp->class_to_proxy)->type;
5911         klass = mono_class_from_mono_type (type);
5912
5913         tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
5914         tp->remote_class = mono_remote_class (domain, class_name, klass);
5915
5916         res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
5917         return res;
5918 }
5919
5920 static MonoReflectionType *
5921 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
5922 {
5923         return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
5924 }
5925
5926 /* System.Environment */
5927
5928 static MonoString *
5929 ves_icall_System_Environment_get_MachineName (void)
5930 {
5931 #if defined (PLATFORM_WIN32)
5932         gunichar2 *buf;
5933         guint32 len;
5934         MonoString *result;
5935
5936         len = MAX_COMPUTERNAME_LENGTH + 1;
5937         buf = g_new (gunichar2, len);
5938
5939         result = NULL;
5940         if (GetComputerName (buf, (PDWORD) &len))
5941                 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
5942
5943         g_free (buf);
5944         return result;
5945 #else
5946         gchar buf [256];
5947         MonoString *result;
5948
5949         if (gethostname (buf, sizeof (buf)) == 0)
5950                 result = mono_string_new (mono_domain_get (), buf);
5951         else
5952                 result = NULL;
5953         
5954         return result;
5955 #endif
5956 }
5957
5958 static int
5959 ves_icall_System_Environment_get_Platform (void)
5960 {
5961         MONO_ARCH_SAVE_REGS;
5962
5963 #if defined (PLATFORM_WIN32)
5964         /* Win32NT */
5965         return 2;
5966 #else
5967         /* Unix */
5968         return 128;
5969 #endif
5970 }
5971
5972 static MonoString *
5973 ves_icall_System_Environment_get_NewLine (void)
5974 {
5975         MONO_ARCH_SAVE_REGS;
5976
5977 #if defined (PLATFORM_WIN32)
5978         return mono_string_new (mono_domain_get (), "\r\n");
5979 #else
5980         return mono_string_new (mono_domain_get (), "\n");
5981 #endif
5982 }
5983
5984 static MonoString *
5985 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
5986 {
5987         const gchar *value;
5988         gchar *utf8_name;
5989
5990         MONO_ARCH_SAVE_REGS;
5991
5992         if (name == NULL)
5993                 return NULL;
5994
5995         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
5996         value = g_getenv (utf8_name);
5997
5998         g_free (utf8_name);
5999
6000         if (value == 0)
6001                 return NULL;
6002         
6003         return mono_string_new (mono_domain_get (), value);
6004 }
6005
6006 /*
6007  * There is no standard way to get at environ.
6008  */
6009 #ifndef _MSC_VER
6010 #ifndef __MINGW32_VERSION
6011 extern
6012 char **environ;
6013 #endif
6014 #endif
6015
6016 static MonoArray *
6017 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6018 {
6019 #ifdef PLATFORM_WIN32
6020         MonoArray *names;
6021         MonoDomain *domain;
6022         MonoString *str;
6023         WCHAR* env_strings;
6024         WCHAR* env_string;
6025         WCHAR* equal_str;
6026         int n = 0;
6027
6028         env_strings = GetEnvironmentStrings();
6029
6030         if (env_strings) {
6031                 env_string = env_strings;
6032                 while (*env_string != '\0') {
6033                 /* weird case that MS seems to skip */
6034                         if (*env_string != '=')
6035                                 n++;
6036                         while (*env_string != '\0')
6037                                 env_string++;
6038                         env_string++;
6039                 }
6040         }
6041
6042         domain = mono_domain_get ();
6043         names = mono_array_new (domain, mono_defaults.string_class, n);
6044
6045         if (env_strings) {
6046                 n = 0;
6047                 env_string = env_strings;
6048                 while (*env_string != '\0') {
6049                         /* weird case that MS seems to skip */
6050                         if (*env_string != '=') {
6051                                 equal_str = wcschr(env_string, '=');
6052                                 g_assert(equal_str);
6053                                 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6054                                 mono_array_setref (names, n, str);
6055                                 n++;
6056                         }
6057                         while (*env_string != '\0')
6058                                 env_string++;
6059                         env_string++;
6060                 }
6061
6062                 FreeEnvironmentStrings (env_strings);
6063         }
6064
6065         return names;
6066
6067 #else
6068         MonoArray *names;
6069         MonoDomain *domain;
6070         MonoString *str;
6071         gchar **e, **parts;
6072         int n;
6073
6074         MONO_ARCH_SAVE_REGS;
6075
6076         n = 0;
6077         for (e = environ; *e != 0; ++ e)
6078                 ++ n;
6079
6080         domain = mono_domain_get ();
6081         names = mono_array_new (domain, mono_defaults.string_class, n);
6082
6083         n = 0;
6084         for (e = environ; *e != 0; ++ e) {
6085                 parts = g_strsplit (*e, "=", 2);
6086                 if (*parts != 0) {
6087                         str = mono_string_new (domain, *parts);
6088                         mono_array_setref (names, n, str);
6089                 }
6090
6091                 g_strfreev (parts);
6092
6093                 ++ n;
6094         }
6095
6096         return names;
6097 #endif
6098 }
6099
6100 /*
6101  * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6102  */
6103 #if !GLIB_CHECK_VERSION(2,4,0)
6104 #define g_setenv(a,b,c)   setenv(a,b,c)
6105 #define g_unsetenv(a) unsetenv(a)
6106 #endif
6107
6108 static void
6109 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6110 {
6111 #ifdef PLATFORM_WIN32
6112         gunichar2 *utf16_name, *utf16_value;
6113 #else
6114         gchar *utf8_name, *utf8_value;
6115 #endif
6116
6117         MONO_ARCH_SAVE_REGS;
6118         
6119 #ifdef PLATFORM_WIN32
6120         utf16_name = mono_string_to_utf16 (name);
6121         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6122                 SetEnvironmentVariable (utf16_name, NULL);
6123                 g_free (utf16_name);
6124                 return;
6125         }
6126
6127         utf16_value = mono_string_to_utf16 (value);
6128
6129         SetEnvironmentVariable (utf16_name, utf16_value);
6130
6131         g_free (utf16_name);
6132         g_free (utf16_value);
6133 #else
6134         utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6135
6136         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6137                 g_unsetenv (utf8_name);
6138                 g_free (utf8_name);
6139                 return;
6140         }
6141
6142         utf8_value = mono_string_to_utf8 (value);
6143         g_setenv (utf8_name, utf8_value, TRUE);
6144
6145         g_free (utf8_name);
6146         g_free (utf8_value);
6147 #endif
6148 }
6149
6150 static void
6151 ves_icall_System_Environment_Exit (int result)
6152 {
6153         MONO_ARCH_SAVE_REGS;
6154
6155         if (!mono_threads_set_shutting_down ())
6156                 return;
6157
6158         mono_runtime_set_shutting_down ();
6159
6160         /* Suspend all managed threads since the runtime is going away */
6161         mono_thread_suspend_all_other_threads ();
6162
6163         mono_runtime_quit ();
6164
6165         /* we may need to do some cleanup here... */
6166         exit (result);
6167 }
6168
6169 static MonoString*
6170 ves_icall_System_Environment_GetGacPath (void)
6171 {
6172         return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6173 }
6174
6175 static MonoString*
6176 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6177 {
6178 #if defined (PLATFORM_WIN32)
6179         #ifndef CSIDL_FLAG_CREATE
6180                 #define CSIDL_FLAG_CREATE       0x8000
6181         #endif
6182
6183         WCHAR path [MAX_PATH];
6184         /* Create directory if no existing */
6185         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6186                 int len = 0;
6187                 while (path [len])
6188                         ++ len;
6189                 return mono_string_new_utf16 (mono_domain_get (), path, len);
6190         }
6191 #else
6192         g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6193 #endif
6194         return mono_string_new (mono_domain_get (), "");
6195 }
6196
6197 static MonoArray *
6198 ves_icall_System_Environment_GetLogicalDrives (void)
6199 {
6200         gunichar2 buf [128], *ptr, *dname;
6201         gunichar2 *u16;
6202         gint initial_size = 127, size = 128;
6203         gint ndrives;
6204         MonoArray *result;
6205         MonoString *drivestr;
6206         MonoDomain *domain = mono_domain_get ();
6207         gint len;
6208
6209         MONO_ARCH_SAVE_REGS;
6210
6211         buf [0] = '\0';
6212         ptr = buf;
6213
6214         while (size > initial_size) {
6215                 size = GetLogicalDriveStrings (initial_size, ptr);
6216                 if (size > initial_size) {
6217                         if (ptr != buf)
6218                                 g_free (ptr);
6219                         ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6220                         initial_size = size;
6221                         size++;
6222                 }
6223         }
6224
6225         /* Count strings */
6226         dname = ptr;
6227         ndrives = 0;
6228         do {
6229                 while (*dname++);
6230                 ndrives++;
6231         } while (*dname);
6232
6233         dname = ptr;
6234         result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6235         ndrives = 0;
6236         do {
6237                 len = 0;
6238                 u16 = dname;
6239                 while (*u16) { u16++; len ++; }
6240                 drivestr = mono_string_new_utf16 (domain, dname, len);
6241                 mono_array_setref (result, ndrives++, drivestr);
6242                 while (*dname++);
6243         } while (*dname);
6244
6245         if (ptr != buf)
6246                 g_free (ptr);
6247
6248         return result;
6249 }
6250
6251 static MonoString *
6252 ves_icall_System_Environment_InternalGetHome (void)
6253 {
6254         MONO_ARCH_SAVE_REGS;
6255
6256         return mono_string_new (mono_domain_get (), g_get_home_dir ());
6257 }
6258
6259 static const char *encodings [] = {
6260         (char *) 1,
6261                 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6262                 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6263                 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6264         (char *) 2,
6265                 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6266                 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6267                 "x_unicode_2_0_utf_7",
6268         (char *) 3,
6269                 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6270                 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6271         (char *) 4,
6272                 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6273                 "iso_10646_ucs2",
6274         (char *) 5,
6275                 "unicodefffe", "utf_16be",
6276         (char *) 6,
6277                 "iso_8859_1",
6278         (char *) 0
6279 };
6280
6281 /*
6282  * Returns the internal codepage, if the value of "int_code_page" is
6283  * 1 at entry, and we can not compute a suitable code page number,
6284  * returns the code page as a string
6285  */
6286 static MonoString*
6287 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page) 
6288 {
6289         const char *cset;
6290         const char *p;
6291         char *c;
6292         char *codepage = NULL;
6293         int code;
6294         int want_name = *int_code_page;
6295         int i;
6296         
6297         *int_code_page = -1;
6298         MONO_ARCH_SAVE_REGS;
6299
6300         g_get_charset (&cset);
6301         c = codepage = strdup (cset);
6302         for (c = codepage; *c; c++){
6303                 if (isascii (*c) && isalpha (*c))
6304                         *c = tolower (*c);
6305                 if (*c == '-')
6306                         *c = '_';
6307         }
6308         /* g_print ("charset: %s\n", cset); */
6309         
6310         /* handle some common aliases */
6311         p = encodings [0];
6312         code = 0;
6313         for (i = 0; p != 0; ){
6314                 if ((gssize) p < 7){
6315                         code = (gssize) p;
6316                         p = encodings [++i];
6317                         continue;
6318                 }
6319                 if (strcmp (p, codepage) == 0){
6320                         *int_code_page = code;
6321                         break;
6322                 }
6323                 p = encodings [++i];
6324         }
6325         
6326         if (strstr (codepage, "utf_8") != NULL)
6327                 *int_code_page |= 0x10000000;
6328         free (codepage);
6329         
6330         if (want_name && *int_code_page == -1)
6331                 return mono_string_new (mono_domain_get (), cset);
6332         else
6333                 return NULL;
6334 }
6335
6336 static MonoBoolean
6337 ves_icall_System_Environment_get_HasShutdownStarted (void)
6338 {
6339         if (mono_runtime_is_shutting_down ())
6340                 return TRUE;
6341
6342         if (mono_domain_is_unloading (mono_domain_get ()))
6343                 return TRUE;
6344
6345         return FALSE;
6346 }
6347
6348 static void
6349 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this, 
6350                                          MonoReflectionMethod *method,
6351                                          MonoArray *out_args)
6352 {
6353         MONO_ARCH_SAVE_REGS;
6354
6355         mono_message_init (mono_object_domain (this), this, method, out_args);
6356 }
6357
6358 static MonoBoolean
6359 ves_icall_IsTransparentProxy (MonoObject *proxy)
6360 {
6361         MONO_ARCH_SAVE_REGS;
6362
6363         if (!proxy)
6364                 return 0;
6365
6366         if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6367                 return 1;
6368
6369         return 0;
6370 }
6371
6372 static MonoReflectionMethod *
6373 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6374         MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6375 {
6376         MonoClass *klass;
6377         MonoMethod *method;
6378         MonoMethod **vtable;
6379         MonoMethod *res = NULL;
6380
6381         MONO_CHECK_ARG_NULL (rtype);
6382         MONO_CHECK_ARG_NULL (rmethod);
6383
6384         method = rmethod->method;
6385         klass = mono_class_from_mono_type (rtype->type);
6386
6387         if (MONO_CLASS_IS_INTERFACE (klass))
6388                 return NULL;
6389
6390         if (method->flags & METHOD_ATTRIBUTE_STATIC)
6391                 return NULL;
6392
6393         if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6394                 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6395                         return rmethod;
6396                 else
6397                         return NULL;
6398         }
6399
6400         mono_class_setup_vtable (klass);
6401         vtable = klass->vtable;
6402
6403         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6404                 int offs = mono_class_interface_offset (klass, method->klass);
6405                 if (offs >= 0)
6406                         res = vtable [offs + method->slot];
6407         } else {
6408                 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6409                         return NULL;
6410
6411                 if (method->slot != -1)
6412                         res = vtable [method->slot];
6413         }
6414
6415         if (!res)
6416                 return NULL;
6417
6418         return mono_method_get_object (mono_domain_get (), res, NULL);
6419 }
6420
6421 static void
6422 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6423 {
6424         MonoClass *klass;
6425         MonoVTable* vtable;
6426
6427         MONO_ARCH_SAVE_REGS;
6428
6429         klass = mono_class_from_mono_type (type->type);
6430         vtable = mono_class_vtable (mono_domain_get (), klass);
6431
6432         if (enable) vtable->remote = 1;
6433         else vtable->remote = 0;
6434 }
6435
6436 static MonoObject *
6437 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6438 {
6439         MonoClass *klass;
6440         MonoDomain *domain;
6441         
6442         MONO_ARCH_SAVE_REGS;
6443
6444         domain = mono_object_domain (type);
6445         klass = mono_class_from_mono_type (type->type);
6446
6447         if (klass->rank >= 1) {
6448                 g_assert (klass->rank == 1);
6449                 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6450         } else {
6451                 /* Bypass remoting object creation check */
6452                 return mono_object_new_alloc_specific (mono_class_vtable (domain, klass));
6453         }
6454 }
6455
6456 static MonoString *
6457 ves_icall_System_IO_get_temp_path (void)
6458 {
6459         MONO_ARCH_SAVE_REGS;
6460
6461         return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6462 }
6463
6464 static gpointer
6465 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6466 {
6467         MONO_ARCH_SAVE_REGS;
6468
6469         return mono_compile_method (method);
6470 }
6471
6472 static MonoString *
6473 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6474 {
6475         MonoString *mcpath;
6476         gchar *path;
6477
6478         MONO_ARCH_SAVE_REGS;
6479
6480         path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6481
6482 #if defined (PLATFORM_WIN32)
6483         /* Avoid mixing '/' and '\\' */
6484         {
6485                 gint i;
6486                 for (i = strlen (path) - 1; i >= 0; i--)
6487                         if (path [i] == '/')
6488                                 path [i] = '\\';
6489         }
6490 #endif
6491         mcpath = mono_string_new (mono_domain_get (), path);
6492         g_free (path);
6493
6494         return mcpath;
6495 }
6496
6497 static MonoString *
6498 get_bundled_machine_config (void)
6499 {
6500         const gchar *machine_config;
6501
6502         MONO_ARCH_SAVE_REGS;
6503
6504         machine_config = mono_get_machine_config ();
6505
6506         if (!machine_config)
6507                 return NULL;
6508
6509         return mono_string_new (mono_domain_get (), machine_config);
6510 }
6511
6512 static MonoString *
6513 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6514 {
6515         MonoString *ipath;
6516         gchar *path;
6517
6518         MONO_ARCH_SAVE_REGS;
6519
6520         path = g_path_get_dirname (mono_get_config_dir ());
6521
6522 #if defined (PLATFORM_WIN32)
6523         /* Avoid mixing '/' and '\\' */
6524         {
6525                 gint i;
6526                 for (i = strlen (path) - 1; i >= 0; i--)
6527                         if (path [i] == '/')
6528                                 path [i] = '\\';
6529         }
6530 #endif
6531         ipath = mono_string_new (mono_domain_get (), path);
6532         g_free (path);
6533
6534         return ipath;
6535 }
6536
6537 static void
6538 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6539 {
6540 #if defined (PLATFORM_WIN32)
6541         OutputDebugString (mono_string_chars (message));
6542 #else
6543         g_warning ("WriteWindowsDebugString called and PLATFORM_WIN32 not defined!\n");
6544 #endif
6545 }
6546
6547 /* Only used for value types */
6548 static MonoObject *
6549 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6550 {
6551         MonoClass *klass;
6552         MonoDomain *domain;
6553         
6554         MONO_ARCH_SAVE_REGS;
6555
6556         domain = mono_object_domain (type);
6557         klass = mono_class_from_mono_type (type->type);
6558
6559         if (mono_class_is_nullable (klass))
6560                 /* No arguments -> null */
6561                 return NULL;
6562
6563         return mono_object_new (domain, klass);
6564 }
6565
6566 static MonoReflectionMethod *
6567 ves_icall_MonoMethod_get_base_definition (MonoReflectionMethod *m)
6568 {
6569         MonoClass *klass, *parent;
6570         MonoMethod *method = m->method;
6571         MonoMethod *result = NULL;
6572
6573         MONO_ARCH_SAVE_REGS;
6574
6575         if (method->klass == NULL)
6576                 return m;
6577
6578         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6579             MONO_CLASS_IS_INTERFACE (method->klass) ||
6580             method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6581                 return m;
6582
6583         klass = method->klass;
6584         if (klass->generic_class)
6585                 klass = klass->generic_class->container_class;
6586
6587         /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6588         for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6589                 mono_class_setup_vtable (parent);
6590                 if (parent->vtable_size <= method->slot)
6591                         break;
6592                 klass = parent;
6593         }               
6594
6595         if (klass == method->klass)
6596                 return m;
6597
6598         result = klass->vtable [method->slot];
6599         if (result == NULL) {
6600                 /* It is an abstract method */
6601                 gpointer iter = NULL;
6602                 while ((result = mono_class_get_methods (klass, &iter)))
6603                         if (result->slot == method->slot)
6604                                 break;
6605         }
6606
6607         if (result == NULL)
6608                 return m;
6609
6610         return mono_method_get_object (mono_domain_get (), result, NULL);
6611 }
6612
6613 static MonoString*
6614 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
6615 {
6616         MonoMethod *method = m->method;
6617
6618         MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
6619         return m->name;
6620 }
6621
6622 static void
6623 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
6624 {
6625         MONO_ARCH_SAVE_REGS;
6626
6627         iter->sig = *(MonoMethodSignature**)argsp;
6628         
6629         g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
6630         g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
6631
6632         iter->next_arg = 0;
6633         /* FIXME: it's not documented what start is exactly... */
6634         if (start) {
6635                 iter->args = start;
6636         } else {
6637                 guint32 i, arg_size;
6638                 gint32 align;
6639                 iter->args = argsp + sizeof (gpointer);
6640 #ifndef MONO_ARCH_REGPARMS
6641                 for (i = 0; i < iter->sig->sentinelpos; ++i) {
6642                         arg_size = mono_type_stack_size (iter->sig->params [i], &align);
6643                         iter->args = (char*)iter->args + arg_size;
6644                 }
6645 #endif
6646         }
6647         iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
6648
6649         /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
6650 }
6651
6652 static MonoTypedRef
6653 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
6654 {
6655         guint32 i, arg_size;
6656         gint32 align;
6657         MonoTypedRef res;
6658         MONO_ARCH_SAVE_REGS;
6659
6660         i = iter->sig->sentinelpos + iter->next_arg;
6661
6662         g_assert (i < iter->sig->param_count);
6663
6664         res.type = iter->sig->params [i];
6665         res.klass = mono_class_from_mono_type (res.type);
6666         /* FIXME: endianess issue... */
6667         res.value = iter->args;
6668         arg_size = mono_type_stack_size (res.type, &align);
6669         iter->args = (char*)iter->args + arg_size;
6670         iter->next_arg++;
6671
6672         /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6673
6674         return res;
6675 }
6676
6677 static MonoTypedRef
6678 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
6679 {
6680         guint32 i, arg_size;
6681         gint32 align;
6682         MonoTypedRef res;
6683         MONO_ARCH_SAVE_REGS;
6684
6685         i = iter->sig->sentinelpos + iter->next_arg;
6686
6687         g_assert (i < iter->sig->param_count);
6688
6689         while (i < iter->sig->param_count) {
6690                 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
6691                         continue;
6692                 res.type = iter->sig->params [i];
6693                 res.klass = mono_class_from_mono_type (res.type);
6694                 /* FIXME: endianess issue... */
6695                 res.value = iter->args;
6696                 arg_size = mono_type_stack_size (res.type, &align);
6697                 iter->args = (char*)iter->args + arg_size;
6698                 iter->next_arg++;
6699                 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6700                 return res;
6701         }
6702         /* g_print ("arg type 0x%02x not found\n", res.type->type); */
6703
6704         res.type = NULL;
6705         res.value = NULL;
6706         res.klass = NULL;
6707         return res;
6708 }
6709
6710 static MonoType*
6711 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
6712 {
6713         gint i;
6714         MONO_ARCH_SAVE_REGS;
6715         
6716         i = iter->sig->sentinelpos + iter->next_arg;
6717
6718         g_assert (i < iter->sig->param_count);
6719
6720         return iter->sig->params [i];
6721 }
6722
6723 static MonoObject*
6724 mono_TypedReference_ToObject (MonoTypedRef tref)
6725 {
6726         MONO_ARCH_SAVE_REGS;
6727
6728         if (MONO_TYPE_IS_REFERENCE (tref.type)) {
6729                 MonoObject** objp = tref.value;
6730                 return *objp;
6731         }
6732
6733         return mono_value_box (mono_domain_get (), tref.klass, tref.value);
6734 }
6735
6736 static MonoObject*
6737 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
6738 {
6739         MONO_ARCH_SAVE_REGS;
6740
6741         if (MONO_TYPE_IS_REFERENCE (type)) {
6742                 MonoObject** objp = value;
6743                 return *objp;
6744         }
6745
6746         return mono_value_box (mono_domain_get (), klass, value);
6747 }
6748
6749 static void
6750 prelink_method (MonoMethod *method)
6751 {
6752         const char *exc_class, *exc_arg;
6753         if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
6754                 return;
6755         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
6756         if (exc_class) {
6757                 mono_raise_exception( 
6758                         mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
6759         }
6760         /* create the wrapper, too? */
6761 }
6762
6763 static void
6764 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
6765 {
6766         MONO_ARCH_SAVE_REGS;
6767         prelink_method (method->method);
6768 }
6769
6770 static void
6771 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
6772 {
6773         MonoClass *klass = mono_class_from_mono_type (type->type);
6774         MonoMethod* m;
6775         gpointer iter = NULL;
6776         MONO_ARCH_SAVE_REGS;
6777
6778         while ((m = mono_class_get_methods (klass, &iter)))
6779                 prelink_method (m);
6780 }
6781
6782 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
6783 static void
6784 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
6785                                             gint32 const **exponents,
6786                                             gunichar2 const **digitLowerTable,
6787                                             gunichar2 const **digitUpperTable,
6788                                             gint64 const **tenPowersList,
6789                                             gint32 const **decHexDigits)
6790 {
6791         *mantissas = Formatter_MantissaBitsTable;
6792         *exponents = Formatter_TensExponentTable;
6793         *digitLowerTable = Formatter_DigitLowerTable;
6794         *digitUpperTable = Formatter_DigitUpperTable;
6795         *tenPowersList = Formatter_TenPowersList;
6796         *decHexDigits = Formatter_DecHexDigits;
6797 }
6798
6799 /* These parameters are "readonly" in corlib/System/Char.cs */
6800 static void
6801 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
6802                                             guint8 const **numeric_data,
6803                                             gdouble const **numeric_data_values,
6804                                             guint16 const **to_lower_data_low,
6805                                             guint16 const **to_lower_data_high,
6806                                             guint16 const **to_upper_data_low,
6807                                             guint16 const **to_upper_data_high)
6808 {
6809         *category_data = CategoryData;
6810         *numeric_data = NumericData;
6811         *numeric_data_values = NumericDataValues;
6812         *to_lower_data_low = ToLowerDataLow;
6813         *to_lower_data_high = ToLowerDataHigh;
6814         *to_upper_data_low = ToUpperDataLow;
6815         *to_upper_data_high = ToUpperDataHigh;
6816 }
6817
6818 static gint32
6819 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
6820 {
6821         return method->method->token;
6822 }
6823
6824 /*
6825  * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
6826  * and avoid useless allocations.
6827  */
6828 static MonoArray*
6829 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
6830 {
6831         MonoArray *res;
6832         int i, count = 0;
6833         for (i = 0; i < type->num_mods; ++i) {
6834                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
6835                         count++;
6836         }
6837         if (!count)
6838                 return NULL;
6839         res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
6840         count = 0;
6841         for (i = 0; i < type->num_mods; ++i) {
6842                 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
6843                         MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
6844                         mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
6845                         count++;
6846                 }
6847         }
6848         return res;
6849 }
6850
6851 static MonoArray*
6852 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
6853 {
6854         MonoType *type = param->ClassImpl->type;
6855         MonoReflectionMethod *method = (MonoReflectionMethod*)param->MemberImpl;
6856         MonoImage *image = method->method->klass->image;
6857         int pos = param->PositionImpl;
6858         MonoMethodSignature *sig = mono_method_signature (method->method);
6859         if (pos == -1)
6860                 type = sig->ret;
6861         else
6862                 type = sig->params [pos];
6863
6864         return type_array_from_modifiers (image, type, optional);
6865 }
6866
6867 static MonoType*
6868 get_property_type (MonoProperty *prop)
6869 {
6870         MonoMethodSignature *sig;
6871         if (prop->get) {
6872                 sig = mono_method_signature (prop->get);
6873                 return sig->ret;
6874         } else if (prop->set) {
6875                 sig = mono_method_signature (prop->set);
6876                 return sig->params [sig->param_count - 1];
6877         }
6878         return NULL;
6879 }
6880
6881 static MonoArray*
6882 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
6883 {
6884         MonoType *type = get_property_type (property->property);
6885         MonoImage *image = property->klass->image;
6886
6887         if (!type)
6888                 return NULL;
6889         return type_array_from_modifiers (image, type, optional);
6890 }
6891
6892 static MonoBoolean
6893 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
6894 {
6895         MonoCustomAttrInfo *cinfo;
6896         gboolean found;
6897
6898         cinfo = mono_reflection_get_custom_attrs_info (obj);
6899         if (!cinfo)
6900                 return FALSE;
6901         found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
6902         if (!cinfo->cached)
6903                 mono_custom_attrs_free (cinfo);
6904         return found;
6905 }
6906
6907 static MonoArray*
6908 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
6909 {
6910         MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
6911
6912         if (mono_loader_get_last_error ()) {
6913                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
6914                 g_assert_not_reached ();
6915         } else {
6916                 return res;
6917         }
6918 }
6919
6920 static MonoBoolean
6921 GCHandle_CheckCurrentDomain (guint32 gchandle)
6922 {
6923         return mono_gchandle_is_in_domain (gchandle, mono_domain_get ());
6924 }
6925
6926 static MonoString*
6927 ves_icall_Mono_Runtime_GetDisplayName (void)
6928 {
6929         static const char display_name_str [] = "Mono " VERSION;
6930         MonoString *display_name = mono_string_new (mono_domain_get (), display_name_str);
6931         return display_name;
6932 }
6933
6934 const static guchar
6935 dbase64 [] = {
6936         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
6937         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
6938         128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
6939         52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
6940         128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
6941         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
6942         128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
6943         41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
6944 };
6945
6946 static MonoArray *
6947 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
6948 {
6949         gint ignored;
6950         gint i;
6951         gunichar2 c;
6952         gunichar2 last, prev_last;
6953         gint olength;
6954         MonoArray *result;
6955         guchar *res_ptr;
6956         gint a [4], b [4];
6957         MonoException *exc;
6958
6959         ignored = 0;
6960         last = prev_last = 0;
6961         for (i = 0; i < ilength; i++) {
6962                 c = start [i];
6963                 if (c >= sizeof (dbase64)) {
6964                         exc = mono_exception_from_name_msg (mono_get_corlib (),
6965                                 "System", "FormatException",
6966                                 "Invalid character found.");
6967                         mono_raise_exception (exc);
6968                 } else if (isspace (c)) {
6969                         ignored++;
6970                 } else {
6971                         prev_last = last;
6972                         last = c;
6973                 }
6974         }
6975
6976         olength = ilength - ignored;
6977
6978         if (allowWhitespaceOnly && olength == 0) {
6979                 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
6980         }
6981
6982         if ((olength & 3) != 0 || olength <= 0) {
6983                 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
6984                                         "FormatException", "Invalid length.");
6985                 mono_raise_exception (exc);
6986         }
6987
6988         olength = (olength * 3) / 4;
6989         if (last == '=')
6990                 olength--;
6991
6992         if (prev_last == '=')
6993                 olength--;
6994
6995         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
6996         res_ptr = mono_array_addr (result, guchar, 0);
6997         for (i = 0; i < ilength; ) {
6998                 int k;
6999
7000                 for (k = 0; k < 4 && i < ilength;) {
7001                         c = start [i++];
7002                         if (isspace (c))
7003                                 continue;
7004
7005                         a [k] = (guchar) c;
7006                         if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7007                                 exc = mono_exception_from_name_msg (mono_get_corlib (),
7008                                         "System", "FormatException",
7009                                         "Invalid character found.");
7010                                 mono_raise_exception (exc);
7011                         }
7012                         k++;
7013                 }
7014
7015                 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7016                 if (a [2] != '=')
7017                         *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7018                 if (a [3] != '=')
7019                         *res_ptr++ = (b [2] << 6) | b [3];
7020
7021                 while (i < ilength && isspace (start [i]))
7022                         i++;
7023         }
7024
7025         return result;
7026 }
7027
7028 static MonoArray *
7029 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7030 {
7031         MONO_ARCH_SAVE_REGS;
7032
7033         return base64_to_byte_array (mono_string_chars (str), 
7034                 mono_string_length (str), allowWhitespaceOnly);
7035 }
7036
7037 static MonoArray *
7038 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7039 {
7040         MONO_ARCH_SAVE_REGS;
7041
7042         return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7043                 length, FALSE);
7044 }
7045
7046 #define ICALL_TYPE(id,name,first)
7047 #define ICALL(id,name,func) Icall_ ## id,
7048
7049 enum {
7050 #include "metadata/icall-def.h"
7051         Icall_last
7052 };
7053
7054 #undef ICALL_TYPE
7055 #undef ICALL
7056 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7057 #define ICALL(id,name,func)
7058 enum {
7059 #include "metadata/icall-def.h"
7060         Icall_type_num
7061 };
7062
7063 #undef ICALL_TYPE
7064 #undef ICALL
7065 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7066 #define ICALL(id,name,func)
7067 typedef struct {
7068         guint16 first_icall;
7069 } IcallTypeDesc;
7070
7071 static const IcallTypeDesc
7072 icall_type_descs [] = {
7073 #include "metadata/icall-def.h"
7074         {Icall_last}
7075 };
7076
7077 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7078
7079 #undef ICALL_TYPE
7080 #define ICALL_TYPE(id,name,first)
7081 #undef ICALL
7082
7083 #ifdef HAVE_ARRAY_ELEM_INIT
7084 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7085 #define MSGSTRFIELD1(line) str##line
7086
7087 static const struct msgstrtn_t {
7088 #define ICALL(id,name,func)
7089 #undef ICALL_TYPE
7090 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7091 #include "metadata/icall-def.h"
7092 #undef ICALL_TYPE
7093 } icall_type_names_str = {
7094 #define ICALL_TYPE(id,name,first) (name),
7095 #include "metadata/icall-def.h"
7096 #undef ICALL_TYPE
7097 };
7098 static const guint16 icall_type_names_idx [] = {
7099 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7100 #include "metadata/icall-def.h"
7101 #undef ICALL_TYPE
7102 };
7103 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7104
7105 static const struct msgstr_t {
7106 #undef ICALL
7107 #define ICALL_TYPE(id,name,first)
7108 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7109 #include "metadata/icall-def.h"
7110 #undef ICALL
7111 } icall_names_str = {
7112 #define ICALL(id,name,func) (name),
7113 #include "metadata/icall-def.h"
7114 #undef ICALL
7115 };
7116 static const guint16 icall_names_idx [] = {
7117 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7118 #include "metadata/icall-def.h"
7119 #undef ICALL
7120 };
7121 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7122
7123 #else
7124
7125 #undef ICALL_TYPE
7126 #undef ICALL
7127 #define ICALL_TYPE(id,name,first) name,
7128 #define ICALL(id,name,func)
7129 static const char* const
7130 icall_type_names [] = {
7131 #include "metadata/icall-def.h"
7132         NULL
7133 };
7134
7135 #define icall_type_name_get(id) (icall_type_names [(id)])
7136
7137 #undef ICALL_TYPE
7138 #undef ICALL
7139 #define ICALL_TYPE(id,name,first)
7140 #define ICALL(id,name,func) name,
7141 static const char* const
7142 icall_names [] = {
7143 #include "metadata/icall-def.h"
7144         NULL
7145 };
7146 #define icall_name_get(id) icall_names [(id)]
7147
7148 #endif /* !HAVE_ARRAY_ELEM_INIT */
7149
7150 #undef ICALL_TYPE
7151 #undef ICALL
7152 #define ICALL_TYPE(id,name,first)
7153 #define ICALL(id,name,func) func,
7154 static const gconstpointer
7155 icall_functions [] = {
7156 #include "metadata/icall-def.h"
7157         NULL
7158 };
7159
7160 static GHashTable *icall_hash = NULL;
7161 static GHashTable *jit_icall_hash_name = NULL;
7162 static GHashTable *jit_icall_hash_addr = NULL;
7163
7164 void
7165 mono_icall_init (void)
7166 {
7167         int i = 0;
7168
7169         /* check that tables are sorted: disable in release */
7170         if (TRUE) {
7171                 int j;
7172                 const char *prev_class = NULL;
7173                 const char *prev_method;
7174                 
7175                 for (i = 0; i < Icall_type_num; ++i) {
7176                         const IcallTypeDesc *desc;
7177                         int num_icalls;
7178                         prev_method = NULL;
7179                         if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7180                                 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7181                         prev_class = icall_type_name_get (i);
7182                         desc = &icall_type_descs [i];
7183                         num_icalls = icall_desc_num_icalls (desc);
7184                         /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7185                         for (j = 0; j < num_icalls; ++j) {
7186                                 const char *methodn = icall_name_get (desc->first_icall + j);
7187                                 if (prev_method && strcmp (prev_method, methodn) >= 0)
7188                                         g_print ("method %s should come before method %s\n", methodn, prev_method);
7189                                 prev_method = methodn;
7190                         }
7191                 }
7192         }
7193
7194         icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7195 }
7196
7197 void
7198 mono_icall_cleanup (void)
7199 {
7200         g_hash_table_destroy (icall_hash);
7201         g_hash_table_destroy (jit_icall_hash_name);
7202         g_hash_table_destroy (jit_icall_hash_addr);
7203 }
7204
7205 void
7206 mono_add_internal_call (const char *name, gconstpointer method)
7207 {
7208         mono_loader_lock ();
7209
7210         g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7211
7212         mono_loader_unlock ();
7213 }
7214
7215 #ifdef HAVE_ARRAY_ELEM_INIT
7216 static int
7217 compare_method_imap (const void *key, const void *elem)
7218 {
7219         const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7220         return strcmp (key, method_name);
7221 }
7222
7223 static gpointer
7224 find_method_icall (const IcallTypeDesc *imap, const char *name)
7225 {
7226         const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7227         if (!nameslot)
7228                 return NULL;
7229         return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7230 }
7231
7232 static int
7233 compare_class_imap (const void *key, const void *elem)
7234 {
7235         const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7236         return strcmp (key, class_name);
7237 }
7238
7239 static const IcallTypeDesc*
7240 find_class_icalls (const char *name)
7241 {
7242         const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7243         if (!nameslot)
7244                 return NULL;
7245         return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7246 }
7247
7248 #else
7249 static int
7250 compare_method_imap (const void *key, const void *elem)
7251 {
7252         const char** method_name = (const char**)elem;
7253         return strcmp (key, *method_name);
7254 }
7255
7256 static gpointer
7257 find_method_icall (const IcallTypeDesc *imap, const char *name)
7258 {
7259         const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7260         if (!nameslot)
7261                 return NULL;
7262         return (gpointer)icall_functions [(nameslot - icall_names)];
7263 }
7264
7265 static int
7266 compare_class_imap (const void *key, const void *elem)
7267 {
7268         const char** class_name = (const char**)elem;
7269         return strcmp (key, *class_name);
7270 }
7271
7272 static const IcallTypeDesc*
7273 find_class_icalls (const char *name)
7274 {
7275         const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7276         if (!nameslot)
7277                 return NULL;
7278         return &icall_type_descs [nameslot - icall_type_names];
7279 }
7280
7281 #endif
7282
7283 /* 
7284  * we should probably export this as an helper (handle nested types).
7285  * Returns the number of chars written in buf.
7286  */
7287 static int
7288 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7289 {
7290         int nspacelen, cnamelen;
7291         nspacelen = strlen (klass->name_space);
7292         cnamelen = strlen (klass->name);
7293         if (nspacelen + cnamelen + 2 > bufsize)
7294                 return 0;
7295         if (nspacelen) {
7296                 memcpy (buf, klass->name_space, nspacelen);
7297                 buf [nspacelen ++] = '.';
7298         }
7299         memcpy (buf + nspacelen, klass->name, cnamelen);
7300         buf [nspacelen + cnamelen] = 0;
7301         return nspacelen + cnamelen;
7302 }
7303
7304 gpointer
7305 mono_lookup_internal_call (MonoMethod *method)
7306 {
7307         char *sigstart;
7308         char *tmpsig;
7309         char mname [2048];
7310         int typelen = 0, mlen, siglen;
7311         gpointer res;
7312         const IcallTypeDesc *imap;
7313
7314         g_assert (method != NULL);
7315
7316         if (method->is_inflated)
7317                 method = ((MonoMethodInflated *) method)->declaring;
7318
7319         if (method->klass->nested_in) {
7320                 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7321                 if (!pos)
7322                         return NULL;
7323
7324                 mname [pos++] = '/';
7325                 mname [pos] = 0;
7326
7327                 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7328                 if (!typelen)
7329                         return NULL;
7330
7331                 typelen += pos;
7332         } else {
7333                 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7334                 if (!typelen)
7335                         return NULL;
7336         }
7337
7338         imap = find_class_icalls (mname);
7339
7340         mname [typelen] = ':';
7341         mname [typelen + 1] = ':';
7342
7343         mlen = strlen (method->name);
7344         memcpy (mname + typelen + 2, method->name, mlen);
7345         sigstart = mname + typelen + 2 + mlen;
7346         *sigstart = 0;
7347
7348         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7349         siglen = strlen (tmpsig);
7350         if (typelen + mlen + siglen + 6 > sizeof (mname))
7351                 return NULL;
7352         sigstart [0] = '(';
7353         memcpy (sigstart + 1, tmpsig, siglen);
7354         sigstart [siglen + 1] = ')';
7355         sigstart [siglen + 2] = 0;
7356         g_free (tmpsig);
7357         
7358         mono_loader_lock ();
7359
7360         res = g_hash_table_lookup (icall_hash, mname);
7361         if (res) {
7362                 mono_loader_unlock ();
7363                 return res;
7364         }
7365         /* try without signature */
7366         *sigstart = 0;
7367         res = g_hash_table_lookup (icall_hash, mname);
7368         if (res) {
7369                 mono_loader_unlock ();
7370                 return res;
7371         }
7372
7373         /* it wasn't found in the static call tables */
7374         if (!imap) {
7375                 mono_loader_unlock ();
7376                 return NULL;
7377         }
7378         res = find_method_icall (imap, sigstart - mlen);
7379         if (res) {
7380                 mono_loader_unlock ();
7381                 return res;
7382         }
7383         /* try _with_ signature */
7384         *sigstart = '(';
7385         res = find_method_icall (imap, sigstart - mlen);
7386         if (res) {
7387                 mono_loader_unlock ();
7388                 return res;
7389         }
7390
7391         g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7392         g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7393         g_print ("The out of sync library is: %s\n", method->klass->image->name);
7394         g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7395         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");
7396         g_print ("If you see other errors or faults after this message they are probably related\n");
7397         g_print ("and you need to fix your mono install first.\n");
7398
7399         mono_loader_unlock ();
7400
7401         return NULL;
7402 }
7403
7404 static MonoType*
7405 type_from_typename (char *typename)
7406 {
7407         MonoClass *klass = NULL;        /* assignment to shut GCC warning up */
7408
7409         if (!strcmp (typename, "int"))
7410                 klass = mono_defaults.int_class;
7411         else if (!strcmp (typename, "ptr"))
7412                 klass = mono_defaults.int_class;
7413         else if (!strcmp (typename, "void"))
7414                 klass = mono_defaults.void_class;
7415         else if (!strcmp (typename, "int32"))
7416                 klass = mono_defaults.int32_class;
7417         else if (!strcmp (typename, "uint32"))
7418                 klass = mono_defaults.uint32_class;
7419         else if (!strcmp (typename, "int8"))
7420                 klass = mono_defaults.sbyte_class;
7421         else if (!strcmp (typename, "uint8"))
7422                 klass = mono_defaults.byte_class;
7423         else if (!strcmp (typename, "int16"))
7424                 klass = mono_defaults.int16_class;
7425         else if (!strcmp (typename, "uint16"))
7426                 klass = mono_defaults.uint16_class;
7427         else if (!strcmp (typename, "long"))
7428                 klass = mono_defaults.int64_class;
7429         else if (!strcmp (typename, "ulong"))
7430                 klass = mono_defaults.uint64_class;
7431         else if (!strcmp (typename, "float"))
7432                 klass = mono_defaults.single_class;
7433         else if (!strcmp (typename, "double"))
7434                 klass = mono_defaults.double_class;
7435         else if (!strcmp (typename, "object"))
7436                 klass = mono_defaults.object_class;
7437         else if (!strcmp (typename, "obj"))
7438                 klass = mono_defaults.object_class;
7439         else {
7440                 g_error (typename);
7441                 g_assert_not_reached ();
7442         }
7443         return &klass->byval_arg;
7444 }
7445
7446 MonoMethodSignature*
7447 mono_create_icall_signature (const char *sigstr)
7448 {
7449         gchar **parts;
7450         int i, len;
7451         gchar **tmp;
7452         MonoMethodSignature *res;
7453
7454         mono_loader_lock ();
7455         res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7456         if (res) {
7457                 mono_loader_unlock ();
7458                 return res;
7459         }
7460
7461         parts = g_strsplit (sigstr, " ", 256);
7462
7463         tmp = parts;
7464         len = 0;
7465         while (*tmp) {
7466                 len ++;
7467                 tmp ++;
7468         }
7469
7470         res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
7471         res->pinvoke = 1;
7472
7473 #ifdef PLATFORM_WIN32
7474         /* 
7475          * Under windows, the default pinvoke calling convention is STDCALL but
7476          * we need CDECL.
7477          */
7478         res->call_convention = MONO_CALL_C;
7479 #endif
7480
7481         res->ret = type_from_typename (parts [0]);
7482         for (i = 1; i < len; ++i) {
7483                 res->params [i - 1] = type_from_typename (parts [i]);
7484         }
7485
7486         g_strfreev (parts);
7487
7488         g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
7489
7490         mono_loader_unlock ();
7491
7492         return res;
7493 }
7494
7495 MonoJitICallInfo *
7496 mono_find_jit_icall_by_name (const char *name)
7497 {
7498         MonoJitICallInfo *info;
7499         g_assert (jit_icall_hash_name);
7500
7501         mono_loader_lock ();
7502         info = g_hash_table_lookup (jit_icall_hash_name, name);
7503         mono_loader_unlock ();
7504         return info;
7505 }
7506
7507 MonoJitICallInfo *
7508 mono_find_jit_icall_by_addr (gconstpointer addr)
7509 {
7510         MonoJitICallInfo *info;
7511         g_assert (jit_icall_hash_addr);
7512
7513         mono_loader_lock ();
7514         info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
7515         mono_loader_unlock ();
7516
7517         return info;
7518 }
7519
7520 void
7521 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
7522 {
7523         mono_loader_lock ();
7524         g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
7525         mono_loader_unlock ();
7526 }
7527
7528 MonoJitICallInfo *
7529 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
7530 {
7531         MonoJitICallInfo *info;
7532         
7533         g_assert (func);
7534         g_assert (name);
7535
7536         mono_loader_lock ();
7537
7538         if (!jit_icall_hash_name) {
7539                 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
7540                 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
7541         }
7542
7543         if (g_hash_table_lookup (jit_icall_hash_name, name)) {
7544                 g_warning ("jit icall already defined \"%s\"\n", name);
7545                 g_assert_not_reached ();
7546         }
7547
7548         info = g_new0 (MonoJitICallInfo, 1);
7549         
7550         info->name = name;
7551         info->func = func;
7552         info->sig = sig;
7553
7554         if (is_save) {
7555                 info->wrapper = func;
7556         } else {
7557                 info->wrapper = NULL;
7558         }
7559
7560         g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
7561         g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
7562
7563         mono_loader_unlock ();
7564         return info;
7565 }