Merge pull request #3896 from lambdageek/bug-46250
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: System.Type icalls and related reflection queries.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  * Copyright 2011 Rodrigo Kumpera
10  * Copyright 2016 Microsoft
11  *
12  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
13  */
14 #include <config.h>
15 #include "mono/utils/mono-membar.h"
16 #include "mono/metadata/reflection-internals.h"
17 #include "mono/metadata/tabledefs.h"
18 #include "mono/metadata/metadata-internals.h"
19 #include <mono/metadata/profiler-private.h>
20 #include "mono/metadata/class-internals.h"
21 #include "mono/metadata/gc-internals.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
29 #include <mono/metadata/reflection-cache.h>
30 #include <mono/metadata/sre-internals.h>
31 #include <stdio.h>
32 #include <glib.h>
33 #include <errno.h>
34 #include <time.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "image.h"
38 #include "cil-coff.h"
39 #include "mono-endian.h"
40 #include <mono/metadata/gc-internals.h>
41 #include <mono/metadata/mempool-internals.h>
42 #include <mono/metadata/security-core-clr.h>
43 #include <mono/metadata/debug-helpers.h>
44 #include <mono/metadata/verify-internals.h>
45 #include <mono/metadata/mono-ptr-array.h>
46 #include <mono/utils/mono-string.h>
47 #include <mono/utils/mono-error-internals.h>
48 #include <mono/utils/checked-build.h>
49 #include <mono/utils/mono-counters.h>
50
51 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
52 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error);
53
54 /* Class lazy loading functions */
55 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
56 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
57 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
58 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
59 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
60 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
61 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
62 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
63 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
64 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
65 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
66 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
67 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
68 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
69
70
71 static int class_ref_info_handle_count;
72
73 void
74 mono_reflection_init (void)
75 {
76         mono_reflection_emit_init ();
77
78         mono_counters_register ("MonoClass::ref_info_handle count",
79                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ref_info_handle_count);
80
81 }
82
83 /*
84  * mono_class_get_ref_info:
85  *
86  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
87  */
88 gpointer
89 mono_class_get_ref_info (MonoClass *klass)
90 {
91         MONO_REQ_GC_UNSAFE_MODE;
92
93         if (klass->ref_info_handle == 0)
94                 return NULL;
95         else
96                 return mono_gchandle_get_target (klass->ref_info_handle);
97 }
98
99 void
100 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
101 {
102         MONO_REQ_GC_UNSAFE_MODE;
103
104         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
105         ++class_ref_info_handle_count;
106         g_assert (klass->ref_info_handle != 0);
107 }
108
109 void
110 mono_class_free_ref_info (MonoClass *klass)
111 {
112         MONO_REQ_GC_NEUTRAL_MODE;
113
114         if (klass->ref_info_handle) {
115                 mono_gchandle_free (klass->ref_info_handle);
116                 klass->ref_info_handle = 0;
117         }
118 }
119
120
121 void
122 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
123 {
124         MONO_REQ_GC_NEUTRAL_MODE;
125
126         if (ainfo && !ainfo->cached)
127                 g_free (ainfo);
128 }
129
130
131 gboolean
132 reflected_equal (gconstpointer a, gconstpointer b)
133 {
134         const ReflectedEntry *ea = (const ReflectedEntry *)a;
135         const ReflectedEntry *eb = (const ReflectedEntry *)b;
136
137         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
138 }
139
140 guint
141 reflected_hash (gconstpointer a) {
142         const ReflectedEntry *ea = (const ReflectedEntry *)a;
143         return mono_aligned_addr_hash (ea->item);
144 }
145
146
147 static void
148 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
149 {
150         mono_domain_lock (domain);
151         if (domain->refobject_hash) {
152         ReflectedEntry pe;
153                 gpointer orig_pe, orig_value;
154
155                 pe.item = o;
156                 pe.refclass = klass;
157                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
158                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
159                         FREE_REFENTRY (orig_pe);
160                 }
161         }
162         mono_domain_unlock (domain);
163 }
164
165 #ifdef REFENTRY_REQUIRES_CLEANUP
166 static void
167 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
168 {
169         FREE_REFENTRY (key);
170 }
171 #endif
172
173 void
174 mono_reflection_cleanup_domain (MonoDomain *domain)
175 {
176         if (domain->refobject_hash) {
177 /*let's avoid scanning the whole hashtable if not needed*/
178 #ifdef REFENTRY_REQUIRES_CLEANUP
179                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
180 #endif
181                 mono_g_hash_table_destroy (domain->refobject_hash);
182                 domain->refobject_hash = NULL;
183         }
184 }
185
186
187 /*
188  * mono_assembly_get_object:
189  * @domain: an app domain
190  * @assembly: an assembly
191  *
192  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
193  */
194 MonoReflectionAssembly*
195 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
196 {
197         MonoError error;
198         MonoReflectionAssembly *result;
199         result = mono_assembly_get_object_checked (domain, assembly, &error);
200         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
201         return result;
202 }
203 /*
204  * mono_assembly_get_object_checked:
205  * @domain: an app domain
206  * @assembly: an assembly
207  *
208  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
209  */
210 MonoReflectionAssembly*
211 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
212 {
213         MonoReflectionAssembly *res;
214         
215         mono_error_init (error);
216
217         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
218         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
219         if (!res)
220                 return NULL;
221         res->assembly = assembly;
222
223         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
224 }
225
226
227
228 MonoReflectionModule*   
229 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
230 {
231         MonoError error;
232         MonoReflectionModule *result;
233         result = mono_module_get_object_checked (domain, image, &error);
234         mono_error_cleanup (&error);
235         return result;
236 }
237
238 MonoReflectionModule*
239 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
240 {
241         MonoReflectionModule *res;
242         char* basename;
243         
244         mono_error_init (error);
245         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
246         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
247         if (!res)
248                 return NULL;
249
250         res->image = image;
251         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
252         if (!assm_obj)
253                 return NULL;
254         MONO_OBJECT_SETREF (res, assembly, assm_obj);
255
256         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
257         basename = g_path_get_basename (image->name);
258         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
259         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
260         
261         g_free (basename);
262
263         if (image->assembly->image == image) {
264                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
265         } else {
266                 int i;
267                 res->token = 0;
268                 if (image->assembly->image->modules) {
269                         for (i = 0; i < image->assembly->image->module_count; i++) {
270                                 if (image->assembly->image->modules [i] == image)
271                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
272                         }
273                         g_assert (res->token);
274                 }
275         }
276
277         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
278 }
279
280 MonoReflectionModule*
281 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
282 {
283         MonoError error;
284         MonoReflectionModule *result;
285         result = mono_module_file_get_object_checked (domain, image, table_index, &error);
286         mono_error_cleanup (&error);
287         return result;
288 }
289
290 MonoReflectionModule*
291 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
292 {
293         MonoReflectionModule *res;
294         MonoTableInfo *table;
295         guint32 cols [MONO_FILE_SIZE];
296         const char *name;
297         guint32 i, name_idx;
298         const char *val;
299         
300         mono_error_init (error);
301
302         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
303         if (!res)
304                 return NULL;
305
306         table = &image->tables [MONO_TABLE_FILE];
307         g_assert (table_index < table->rows);
308         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
309
310         res->image = NULL;
311         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
312         if (!assm_obj)
313                 return NULL;
314         MONO_OBJECT_SETREF (res, assembly, assm_obj);
315         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
316
317         /* Check whenever the row has a corresponding row in the moduleref table */
318         table = &image->tables [MONO_TABLE_MODULEREF];
319         for (i = 0; i < table->rows; ++i) {
320                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
321                 val = mono_metadata_string_heap (image, name_idx);
322                 if (strcmp (val, name) == 0)
323                         res->image = image->modules [i];
324         }
325
326         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
327         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
328         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
329         res->is_resource = cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA;
330         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
331
332         return res;
333 }
334
335 static MonoType*
336 mono_type_normalize (MonoType *type)
337 {
338         int i;
339         MonoGenericClass *gclass;
340         MonoGenericInst *ginst;
341         MonoClass *gtd;
342         MonoGenericContainer *gcontainer;
343         MonoType **argv = NULL;
344         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
345
346         if (type->type != MONO_TYPE_GENERICINST)
347                 return type;
348
349         gclass = type->data.generic_class;
350         ginst = gclass->context.class_inst;
351         if (!ginst->is_open)
352                 return type;
353
354         gtd = gclass->container_class;
355         gcontainer = mono_class_get_generic_container (gtd);
356         argv = g_newa (MonoType*, ginst->type_argc);
357
358         for (i = 0; i < ginst->type_argc; ++i) {
359                 MonoType *t = ginst->type_argv [i], *norm;
360                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
361                         is_denorm_gtd = FALSE;
362                 norm = mono_type_normalize (t);
363                 argv [i] = norm;
364                 if (norm != t)
365                         requires_rebind = TRUE;
366         }
367
368         if (is_denorm_gtd)
369                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
370
371         if (requires_rebind) {
372                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
373                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
374         }
375
376         return type;
377 }
378 /*
379  * mono_type_get_object:
380  * @domain: an app domain
381  * @type: a type
382  *
383  * Return an System.MonoType object representing the type @type.
384  */
385 MonoReflectionType*
386 mono_type_get_object (MonoDomain *domain, MonoType *type)
387 {
388         MonoError error;
389         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
390         mono_error_cleanup (&error);
391
392         return ret;
393 }
394
395 MonoReflectionType*
396 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
397 {
398         MonoType *norm_type;
399         MonoReflectionType *res;
400         MonoClass *klass;
401
402         mono_error_init (error);
403
404         klass = mono_class_from_mono_type (type);
405
406         /*we must avoid using @type as it might have come
407          * from a mono_metadata_type_dup and the caller
408          * expects that is can be freed.
409          * Using the right type from 
410          */
411         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
412
413         /* void is very common */
414         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
415                 return (MonoReflectionType*)domain->typeof_void;
416
417         /*
418          * If the vtable of the given class was already created, we can use
419          * the MonoType from there and avoid all locking and hash table lookups.
420          * 
421          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
422          * that the resulting object is different.   
423          */
424         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
425                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
426                 if (vtable && vtable->type)
427                         return (MonoReflectionType *)vtable->type;
428         }
429
430         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
431         mono_domain_lock (domain);
432         if (!domain->type_hash)
433                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
434                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
435         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
436                 mono_domain_unlock (domain);
437                 mono_loader_unlock ();
438                 return res;
439         }
440
441         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
442          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
443          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
444          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
445          * artifact of how generics are encoded and should be transparent to managed code so we
446          * need to weed out this diference when retrieving managed System.Type objects.
447          */
448         norm_type = mono_type_normalize (type);
449         if (norm_type != type) {
450                 res = mono_type_get_object_checked (domain, norm_type, error);
451                 if (!mono_error_ok (error))
452                         return NULL;
453                 mono_g_hash_table_insert (domain->type_hash, type, res);
454                 mono_domain_unlock (domain);
455                 mono_loader_unlock ();
456                 return res;
457         }
458
459         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
460         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
461                 g_assert (0);
462
463         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder && !type->byref) {
464                 mono_domain_unlock (domain);
465                 mono_loader_unlock ();
466                 return (MonoReflectionType *)mono_class_get_ref_info (klass);
467         }
468         /* This is stored in vtables/JITted code so it has to be pinned */
469         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.runtimetype_class, error);
470         if (!mono_error_ok (error))
471                 return NULL;
472
473         res->type = type;
474         mono_g_hash_table_insert (domain->type_hash, type, res);
475
476         if (type->type == MONO_TYPE_VOID)
477                 domain->typeof_void = (MonoObject*)res;
478
479         mono_domain_unlock (domain);
480         mono_loader_unlock ();
481         return res;
482 }
483
484 /*
485  * mono_method_get_object:
486  * @domain: an app domain
487  * @method: a method
488  * @refclass: the reflected type (can be NULL)
489  *
490  * Return an System.Reflection.MonoMethod object representing the method @method.
491  */
492 MonoReflectionMethod*
493 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
494 {
495         MonoError error;
496         MonoReflectionMethod *ret = NULL;
497         ret = mono_method_get_object_checked (domain, method, refclass, &error);
498         mono_error_cleanup (&error);
499         return ret;
500 }
501
502 /*
503  * mono_method_get_object_checked:
504  * @domain: an app domain
505  * @method: a method
506  * @refclass: the reflected type (can be NULL)
507  * @error: set on error.
508  *
509  * Return an System.Reflection.MonoMethod object representing the method @method.
510  * Returns NULL and sets @error on error.
511  */
512 MonoReflectionMethod*
513 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
514 {
515         /*
516          * We use the same C representation for methods and constructors, but the type 
517          * name in C# is different.
518          */
519         MonoReflectionType *rt;
520         MonoClass *klass;
521         MonoReflectionMethod *ret;
522
523         mono_error_init (error);
524
525         if (!refclass)
526                 refclass = method->klass;
527
528         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
529         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
530                 klass = mono_class_get_mono_cmethod_class ();
531         }
532         else {
533                 klass = mono_class_get_mono_method_class ();
534         }
535         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
536         if (!mono_error_ok (error))
537                 goto leave;
538         ret->method = method;
539
540         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
541         if (!mono_error_ok (error))
542                 goto leave;
543
544         MONO_OBJECT_SETREF (ret, reftype, rt);
545
546         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
547
548 leave:
549         g_assert (!mono_error_ok (error));
550         return NULL;
551 }
552
553 /*
554  * mono_method_clear_object:
555  *
556  *   Clear the cached reflection objects for the dynamic method METHOD.
557  */
558 void
559 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
560 {
561         MonoClass *klass;
562         g_assert (method_is_dynamic (method));
563
564         klass = method->klass;
565         while (klass) {
566                 clear_cached_object (domain, method, klass);
567                 klass = klass->parent;
568         }
569         /* Added by mono_param_get_objects () */
570         clear_cached_object (domain, &(method->signature), NULL);
571         klass = method->klass;
572         while (klass) {
573                 clear_cached_object (domain, &(method->signature), klass);
574                 klass = klass->parent;
575         }
576 }
577
578 /*
579  * mono_field_get_object:
580  * @domain: an app domain
581  * @klass: a type
582  * @field: a field
583  *
584  * Return an System.Reflection.MonoField object representing the field @field
585  * in class @klass.
586  */
587 MonoReflectionField*
588 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
589 {
590         MonoError error;
591         MonoReflectionField *result;
592         result = mono_field_get_object_checked (domain, klass, field, &error);
593         mono_error_cleanup (&error);
594         return result;
595 }
596
597 /*
598  * mono_field_get_object_checked:
599  * @domain: an app domain
600  * @klass: a type
601  * @field: a field
602  * @error: set on error
603  *
604  * Return an System.Reflection.MonoField object representing the field @field
605  * in class @klass. On error, returns NULL and sets @error.
606  */
607 MonoReflectionField*
608 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
609 {
610         MonoReflectionType *rt;
611         MonoReflectionField *res;
612
613         mono_error_init (error);
614
615         CHECK_OBJECT (MonoReflectionField *, field, klass);
616         res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
617         if (!res)
618                 return NULL;
619         res->klass = klass;
620         res->field = field;
621         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
622
623         if (field->type) {
624                 rt = mono_type_get_object_checked (domain, field->type, error);
625                 if (!mono_error_ok (error))
626                         return NULL;
627
628                 MONO_OBJECT_SETREF (res, type, rt);
629         }
630         res->attrs = mono_field_get_flags (field);
631         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
632 }
633
634 /*
635  * mono_property_get_object:
636  * @domain: an app domain
637  * @klass: a type
638  * @property: a property
639  *
640  * Return an System.Reflection.MonoProperty object representing the property @property
641  * in class @klass.
642  */
643 MonoReflectionProperty*
644 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
645 {
646         MonoError error;
647         MonoReflectionProperty *result;
648         result = mono_property_get_object_checked (domain, klass, property, &error);
649         mono_error_cleanup (&error);
650         return result;
651 }
652
653 /**
654  * mono_property_get_object:
655  * @domain: an app domain
656  * @klass: a type
657  * @property: a property
658  * @error: set on error
659  *
660  * Return an System.Reflection.MonoProperty object representing the property @property
661  * in class @klass.  On error returns NULL and sets @error.
662  */
663 MonoReflectionProperty*
664 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
665 {
666         MonoReflectionProperty *res;
667
668         mono_error_init (error);
669
670         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
671         res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
672         if (!res)
673                 return NULL;
674         res->klass = klass;
675         res->property = property;
676         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
677 }
678
679 /*
680  * mono_event_get_object:
681  * @domain: an app domain
682  * @klass: a type
683  * @event: a event
684  *
685  * Return an System.Reflection.MonoEvent object representing the event @event
686  * in class @klass.
687  */
688 MonoReflectionEvent*
689 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
690 {
691         MonoError error;
692         MonoReflectionEvent *result;
693         result = mono_event_get_object_checked (domain, klass, event, &error);
694         mono_error_cleanup (&error);
695         return result;
696 }
697
698 /**
699  * mono_event_get_object_checked:
700  * @domain: an app domain
701  * @klass: a type
702  * @event: a event
703  * @error: set on error
704  *
705  * Return an System.Reflection.MonoEvent object representing the event @event
706  * in class @klass. On failure sets @error and returns NULL
707  */
708 MonoReflectionEvent*
709 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
710 {
711         MonoReflectionEvent *res;
712         MonoReflectionMonoEvent *mono_event;
713
714         mono_error_init (error);
715         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
716         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
717         if (!mono_event)
718                 return NULL;
719         mono_event->klass = klass;
720         mono_event->event = event;
721         res = (MonoReflectionEvent*)mono_event;
722         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
723 }
724
725 /**
726  * mono_get_reflection_missing_object:
727  * @domain: Domain where the object lives
728  *
729  * Returns the System.Reflection.Missing.Value singleton object
730  * (of type System.Reflection.Missing).
731  *
732  * Used as the value for ParameterInfo.DefaultValue when Optional
733  * is present
734  */
735 static MonoObject *
736 mono_get_reflection_missing_object (MonoDomain *domain)
737 {
738         MonoError error;
739         MonoObject *obj;
740         static MonoClassField *missing_value_field = NULL;
741         
742         if (!missing_value_field) {
743                 MonoClass *missing_klass;
744                 missing_klass = mono_class_get_missing_class ();
745                 mono_class_init (missing_klass);
746                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
747                 g_assert (missing_value_field);
748         }
749         obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
750         mono_error_assert_ok (&error);
751         return obj;
752 }
753
754 static MonoObject*
755 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
756 {
757         if (!*dbnull)
758                 *dbnull = mono_get_dbnull_object (domain);
759         return *dbnull;
760 }
761
762 static MonoObject*
763 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
764 {
765         if (!*reflection_missing)
766                 *reflection_missing = mono_get_reflection_missing_object (domain);
767         return *reflection_missing;
768 }
769
770 /*
771  * mono_param_get_objects:
772  * @domain: an app domain
773  * @method: a method
774  *
775  * Return an System.Reflection.ParameterInfo array object representing the parameters
776  * in the method @method.
777  */
778 MonoArray*
779 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
780 {
781         static MonoClass *System_Reflection_ParameterInfo;
782         static MonoClass *System_Reflection_ParameterInfo_array;
783         MonoArray *res = NULL;
784         MonoReflectionMethod *member = NULL;
785         MonoReflectionParameter *param = NULL;
786         char **names = NULL, **blobs = NULL;
787         guint32 *types = NULL;
788         MonoType *type = NULL;
789         MonoObject *dbnull = NULL;
790         MonoObject *missing = NULL;
791         MonoMarshalSpec **mspecs = NULL;
792         MonoMethodSignature *sig = NULL;
793         MonoVTable *pinfo_vtable;
794         MonoReflectionType *rt;
795         int i;
796
797         mono_error_init (error);
798         
799         if (!System_Reflection_ParameterInfo_array) {
800                 MonoClass *klass;
801
802                 klass = mono_class_get_mono_parameter_info_class ();
803
804                 mono_memory_barrier ();
805                 System_Reflection_ParameterInfo = klass; 
806
807         
808                 klass = mono_array_class_get (klass, 1);
809                 mono_memory_barrier ();
810                 System_Reflection_ParameterInfo_array = klass;
811         }
812
813         sig = mono_method_signature_checked (method, error);
814         if (!mono_error_ok (error))
815                 goto leave;
816
817         if (!sig->param_count) {
818                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
819                 if (!res)
820                         goto leave;
821
822                 return res;
823         }
824
825         /* Note: the cache is based on the address of the signature into the method
826          * since we already cache MethodInfos with the method as keys.
827          */
828         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
829
830         member = mono_method_get_object_checked (domain, method, refclass, error);
831         if (!member)
832                 goto leave;
833         names = g_new (char *, sig->param_count);
834         mono_method_get_param_names (method, (const char **) names);
835
836         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
837         mono_method_get_marshal_info (method, mspecs);
838
839         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
840         if (!res)
841                 goto leave;
842
843         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
844         for (i = 0; i < sig->param_count; ++i) {
845                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
846                 if (!param)
847                         goto leave;
848
849                 rt = mono_type_get_object_checked (domain, sig->params [i], error);
850                 if (!rt)
851                         goto leave;
852
853                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
854
855                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
856
857                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
858
859                 param->PositionImpl = i;
860                 param->AttrsImpl = sig->params [i]->attrs;
861
862                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
863                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
864                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
865                         else
866                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
867                 } else {
868
869                         if (!blobs) {
870                                 blobs = g_new0 (char *, sig->param_count);
871                                 types = g_new0 (guint32, sig->param_count);
872                                 get_default_param_value_blobs (method, blobs, types); 
873                         }
874
875                         /* Build MonoType for the type from the Constant Table */
876                         if (!type)
877                                 type = g_new0 (MonoType, 1);
878                         type->type = (MonoTypeEnum)types [i];
879                         type->data.klass = NULL;
880                         if (types [i] == MONO_TYPE_CLASS)
881                                 type->data.klass = mono_defaults.object_class;
882                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
883                                 /* For enums, types [i] contains the base type */
884
885                                         type->type = MONO_TYPE_VALUETYPE;
886                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
887                         } else
888                                 type->data.klass = mono_class_from_mono_type (type);
889
890                         MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
891                         if (!is_ok (error))
892                                 goto leave;
893                         MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
894
895                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
896                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
897                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
898                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
899                                 else
900                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
901                         }
902                         
903                 }
904
905                 if (mspecs [i + 1]) {
906                         MonoReflectionMarshalAsAttribute* mobj;
907                         mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
908                         if (!mobj)
909                                 goto leave;
910                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
911                 }
912                 
913                 mono_array_setref (res, i, param);
914         }
915
916 leave:
917         g_free (names);
918         g_free (blobs);
919         g_free (types);
920         g_free (type);
921
922         if (sig) {
923                 for (i = sig->param_count; i >= 0; i--) {
924                         if (mspecs [i])
925                                 mono_metadata_free_marshal_spec (mspecs [i]);
926                 }
927         }
928         g_free (mspecs);
929
930         if (!is_ok (error))
931                 return NULL;
932         
933         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
934 }
935
936 MonoArray*
937 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
938 {
939         MonoError error;
940         MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
941         mono_error_assert_ok (&error);
942         return result;
943 }
944
945 /*
946  * mono_method_body_get_object:
947  * @domain: an app domain
948  * @method: a method
949  *
950  * Return an System.Reflection.MethodBody object representing the method @method.
951  */
952 MonoReflectionMethodBody*
953 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
954 {
955         MonoError error;
956         MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
957         mono_error_cleanup (&error);
958         return result;
959 }
960
961 /**
962  * mono_method_body_get_object_checked:
963  * @domain: an app domain
964  * @method: a method
965  * @error: set on error
966  *
967  * Return an System.Reflection.MethodBody object representing the
968  * method @method.  On failure, returns NULL and sets @error.
969  */
970 MonoReflectionMethodBody*
971 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
972 {
973         MonoReflectionMethodBody *ret;
974         MonoMethodHeader *header;
975         MonoImage *image;
976         MonoReflectionType *rt;
977         guint32 method_rva, local_var_sig_token;
978         char *ptr;
979         unsigned char format, flags;
980         int i;
981
982         mono_error_init (error);
983
984         /* for compatibility with .net */
985         if (method_is_dynamic (method)) {
986                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
987                 return NULL;
988         }
989
990         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
991
992         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
993                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
994             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
995                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
996             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
997                 return NULL;
998
999         image = method->klass->image;
1000         header = mono_method_get_header_checked (method, error);
1001         return_val_if_nok (error, NULL);
1002
1003         if (!image_is_dynamic (image)) {
1004                 /* Obtain local vars signature token */
1005                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
1006                 ptr = mono_image_rva_map (image, method_rva);
1007                 flags = *(const unsigned char *) ptr;
1008                 format = flags & METHOD_HEADER_FORMAT_MASK;
1009                 switch (format){
1010                 case METHOD_HEADER_TINY_FORMAT:
1011                         local_var_sig_token = 0;
1012                         break;
1013                 case METHOD_HEADER_FAT_FORMAT:
1014                         ptr += 2;
1015                         ptr += 2;
1016                         ptr += 4;
1017                         local_var_sig_token = read32 (ptr);
1018                         break;
1019                 default:
1020                         g_assert_not_reached ();
1021                 }
1022         } else
1023                 local_var_sig_token = 0; //FIXME
1024
1025         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
1026         if (!is_ok (error))
1027                 goto fail;
1028
1029         ret->init_locals = header->init_locals;
1030         ret->max_stack = header->max_stack;
1031         ret->local_var_sig_token = local_var_sig_token;
1032         MonoArray *il_arr = mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size, error);
1033         if (!is_ok (error))
1034                 goto fail;
1035         MONO_OBJECT_SETREF (ret, il, il_arr);
1036         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
1037
1038         /* Locals */
1039         MonoArray *locals_arr = mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals, error);
1040         if (!is_ok (error))
1041                 goto fail;
1042         MONO_OBJECT_SETREF (ret, locals, locals_arr);
1043         for (i = 0; i < header->num_locals; ++i) {
1044                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
1045                 if (!is_ok (error))
1046                         goto fail;
1047
1048                 rt = mono_type_get_object_checked (domain, header->locals [i], error);
1049                 if (!is_ok (error))
1050                         goto fail;
1051
1052                 MONO_OBJECT_SETREF (info, local_type, rt);
1053
1054                 info->is_pinned = header->locals [i]->pinned;
1055                 info->local_index = i;
1056                 mono_array_setref (ret->locals, i, info);
1057         }
1058
1059         /* Exceptions */
1060         MonoArray *exn_clauses = mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses, error);
1061         if (!is_ok (error))
1062                 goto fail;
1063         MONO_OBJECT_SETREF (ret, clauses, exn_clauses);
1064         for (i = 0; i < header->num_clauses; ++i) {
1065                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
1066                 if (!is_ok (error))
1067                         goto fail;
1068                 MonoExceptionClause *clause = &header->clauses [i];
1069
1070                 info->flags = clause->flags;
1071                 info->try_offset = clause->try_offset;
1072                 info->try_length = clause->try_len;
1073                 info->handler_offset = clause->handler_offset;
1074                 info->handler_length = clause->handler_len;
1075                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
1076                         info->filter_offset = clause->data.filter_offset;
1077                 else if (clause->data.catch_class) {
1078                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
1079                         if (!is_ok (error))
1080                                 goto fail;
1081
1082                         MONO_OBJECT_SETREF (info, catch_type, rt);
1083                 }
1084
1085                 mono_array_setref (ret->clauses, i, info);
1086         }
1087
1088         mono_metadata_free_mh (header);
1089         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
1090         return ret;
1091
1092 fail:
1093         mono_metadata_free_mh (header);
1094         return NULL;
1095 }
1096
1097 /**
1098  * mono_get_dbnull_object:
1099  * @domain: Domain where the object lives
1100  *
1101  * Returns the System.DBNull.Value singleton object
1102  *
1103  * Used as the value for ParameterInfo.DefaultValue 
1104  */
1105 MonoObject *
1106 mono_get_dbnull_object (MonoDomain *domain)
1107 {
1108         MonoError error;
1109         MonoObject *obj;
1110         static MonoClassField *dbnull_value_field = NULL;
1111         
1112         if (!dbnull_value_field) {
1113                 MonoClass *dbnull_klass;
1114                 dbnull_klass = mono_class_get_dbnull_class ();
1115                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
1116                 g_assert (dbnull_value_field);
1117         }
1118         obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
1119         mono_error_assert_ok (&error);
1120         return obj;
1121 }
1122
1123 static void
1124 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
1125 {
1126         guint32 param_index, i, lastp, crow = 0;
1127         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
1128         gint32 idx;
1129
1130         MonoClass *klass = method->klass;
1131         MonoImage *image = klass->image;
1132         MonoMethodSignature *methodsig = mono_method_signature (method);
1133
1134         MonoTableInfo *constt;
1135         MonoTableInfo *methodt;
1136         MonoTableInfo *paramt;
1137
1138         if (!methodsig->param_count)
1139                 return;
1140
1141         mono_class_init (klass);
1142
1143         if (image_is_dynamic (klass->image)) {
1144                 MonoReflectionMethodAux *aux;
1145                 if (method->is_inflated)
1146                         method = ((MonoMethodInflated*)method)->declaring;
1147                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
1148                 if (aux && aux->param_defaults) {
1149                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
1150                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
1151                 }
1152                 return;
1153         }
1154
1155         methodt = &klass->image->tables [MONO_TABLE_METHOD];
1156         paramt = &klass->image->tables [MONO_TABLE_PARAM];
1157         constt = &image->tables [MONO_TABLE_CONSTANT];
1158
1159         idx = mono_method_get_index (method) - 1;
1160         g_assert (idx != -1);
1161
1162         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
1163         if (idx + 1 < methodt->rows)
1164                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
1165         else
1166                 lastp = paramt->rows + 1;
1167
1168         for (i = param_index; i < lastp; ++i) {
1169                 guint32 paramseq;
1170
1171                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
1172                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
1173
1174                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
1175                         continue;
1176
1177                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
1178                 if (!crow) {
1179                         continue;
1180                 }
1181         
1182                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
1183                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
1184                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
1185         }
1186
1187         return;
1188 }
1189
1190 MonoObject *
1191 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
1192 {
1193         void *retval;
1194         MonoClass *klass;
1195         MonoObject *object;
1196         MonoType *basetype = type;
1197
1198         mono_error_init (error);
1199
1200         if (!blob)
1201                 return NULL;
1202         
1203         klass = mono_class_from_mono_type (type);
1204         if (klass->valuetype) {
1205                 object = mono_object_new_checked (domain, klass, error);
1206                 return_val_if_nok (error, NULL);
1207                 retval = ((gchar *) object + sizeof (MonoObject));
1208                 if (klass->enumtype)
1209                         basetype = mono_class_enum_basetype (klass);
1210         } else {
1211                 retval = &object;
1212         }
1213                         
1214         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval, error))
1215                 return object;
1216         else
1217                 return NULL;
1218 }
1219
1220 static int
1221 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
1222         int found_sep;
1223         char *s;
1224         gboolean quoted = FALSE;
1225
1226         memset (assembly, 0, sizeof (MonoAssemblyName));
1227         assembly->culture = "";
1228         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
1229
1230         if (*p == '"') {
1231                 quoted = TRUE;
1232                 p++;
1233         }
1234         assembly->name = p;
1235         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
1236                 p++;
1237         if (quoted) {
1238                 if (*p != '"')
1239                         return 1;
1240                 *p = 0;
1241                 p++;
1242         }
1243         if (*p != ',')
1244                 return 1;
1245         *p = 0;
1246         /* Remove trailing whitespace */
1247         s = p - 1;
1248         while (*s && g_ascii_isspace (*s))
1249                 *s-- = 0;
1250         p ++;
1251         while (g_ascii_isspace (*p))
1252                 p++;
1253         while (*p) {
1254                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
1255                         p += 8;
1256                         assembly->major = strtoul (p, &s, 10);
1257                         if (s == p || *s != '.')
1258                                 return 1;
1259                         p = ++s;
1260                         assembly->minor = strtoul (p, &s, 10);
1261                         if (s == p || *s != '.')
1262                                 return 1;
1263                         p = ++s;
1264                         assembly->build = strtoul (p, &s, 10);
1265                         if (s == p || *s != '.')
1266                                 return 1;
1267                         p = ++s;
1268                         assembly->revision = strtoul (p, &s, 10);
1269                         if (s == p)
1270                                 return 1;
1271                         p = s;
1272                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
1273                         p += 8;
1274                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
1275                                 assembly->culture = "";
1276                                 p += 7;
1277                         } else {
1278                                 assembly->culture = p;
1279                                 while (*p && *p != ',') {
1280                                         p++;
1281                                 }
1282                         }
1283                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
1284                         p += 15;
1285                         if (strncmp (p, "null", 4) == 0) {
1286                                 p += 4;
1287                         } else {
1288                                 int len;
1289                                 gchar *start = p;
1290                                 while (*p && *p != ',') {
1291                                         p++;
1292                                 }
1293                                 len = (p - start + 1);
1294                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
1295                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
1296                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
1297                         }
1298                 } else {
1299                         while (*p && *p != ',')
1300                                 p++;
1301                 }
1302                 found_sep = 0;
1303                 while (g_ascii_isspace (*p) || *p == ',') {
1304                         *p++ = 0;
1305                         found_sep = 1;
1306                         continue;
1307                 }
1308                 /* failed */
1309                 if (!found_sep)
1310                         return 1;
1311         }
1312
1313         return 0;
1314 }
1315
1316 /*
1317  * mono_reflection_parse_type:
1318  * @name: type name
1319  *
1320  * Parse a type name as accepted by the GetType () method and output the info
1321  * extracted in the info structure.
1322  * the name param will be mangled, so, make a copy before passing it to this function.
1323  * The fields in info will be valid until the memory pointed to by name is valid.
1324  *
1325  * See also mono_type_get_name () below.
1326  *
1327  * Returns: 0 on parse error.
1328  */
1329 static int
1330 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
1331                              MonoTypeNameParse *info)
1332 {
1333         char *start, *p, *w, *last_point, *startn;
1334         int in_modifiers = 0;
1335         int isbyref = 0, rank = 0, isptr = 0;
1336
1337         start = p = w = name;
1338
1339         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
1340         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
1341         info->name = info->name_space = NULL;
1342         info->nested = NULL;
1343         info->modifiers = NULL;
1344         info->type_arguments = NULL;
1345
1346         /* last_point separates the namespace from the name */
1347         last_point = NULL;
1348         /* Skips spaces */
1349         while (*p == ' ') p++, start++, w++, name++;
1350
1351         while (*p) {
1352                 switch (*p) {
1353                 case '+':
1354                         *p = 0; /* NULL terminate the name */
1355                         startn = p + 1;
1356                         info->nested = g_list_append (info->nested, startn);
1357                         /* we have parsed the nesting namespace + name */
1358                         if (info->name)
1359                                 break;
1360                         if (last_point) {
1361                                 info->name_space = start;
1362                                 *last_point = 0;
1363                                 info->name = last_point + 1;
1364                         } else {
1365                                 info->name_space = (char *)"";
1366                                 info->name = start;
1367                         }
1368                         break;
1369                 case '.':
1370                         last_point = p;
1371                         break;
1372                 case '\\':
1373                         ++p;
1374                         break;
1375                 case '&':
1376                 case '*':
1377                 case '[':
1378                 case ',':
1379                 case ']':
1380                         in_modifiers = 1;
1381                         break;
1382                 default:
1383                         break;
1384                 }
1385                 if (in_modifiers)
1386                         break;
1387                 // *w++ = *p++;
1388                 p++;
1389         }
1390         
1391         if (!info->name) {
1392                 if (last_point) {
1393                         info->name_space = start;
1394                         *last_point = 0;
1395                         info->name = last_point + 1;
1396                 } else {
1397                         info->name_space = (char *)"";
1398                         info->name = start;
1399                 }
1400         }
1401         while (*p) {
1402                 switch (*p) {
1403                 case '&':
1404                         if (isbyref) /* only one level allowed by the spec */
1405                                 return 0;
1406                         isbyref = 1;
1407                         isptr = 0;
1408                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
1409                         *p++ = 0;
1410                         break;
1411                 case '*':
1412                         if (isbyref) /* pointer to ref not okay */
1413                                 return 0;
1414                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
1415                         isptr = 1;
1416                         *p++ = 0;
1417                         break;
1418                 case '[':
1419                         if (isbyref) /* array of ref and generic ref are not okay */
1420                                 return 0;
1421                         //Decide if it's an array of a generic argument list
1422                         *p++ = 0;
1423
1424                         if (!*p) //XXX test
1425                                 return 0;
1426                         if (*p  == ',' || *p == '*' || *p == ']') { //array
1427                                 isptr = 0;
1428                                 rank = 1;
1429                                 while (*p) {
1430                                         if (*p == ']')
1431                                                 break;
1432                                         if (*p == ',')
1433                                                 rank++;
1434                                         else if (*p == '*') /* '*' means unknown lower bound */
1435                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
1436                                         else
1437                                                 return 0;
1438                                         ++p;
1439                                 }
1440                                 if (*p++ != ']')
1441                                         return 0;
1442                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
1443                         } else {
1444                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
1445                                         return 0;
1446                                 isptr = 0;
1447                                 info->type_arguments = g_ptr_array_new ();
1448                                 while (*p) {
1449                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
1450                                         gboolean fqname = FALSE;
1451
1452                                         g_ptr_array_add (info->type_arguments, subinfo);
1453
1454                                         while (*p == ' ') p++;
1455                                         if (*p == '[') {
1456                                                 p++;
1457                                                 fqname = TRUE;
1458                                         }
1459
1460                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
1461                                                 return 0;
1462
1463                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
1464                                         if (fqname && (*p != ']')) {
1465                                                 char *aname;
1466
1467                                                 if (*p != ',')
1468                                                         return 0;
1469                                                 *p++ = 0;
1470
1471                                                 aname = p;
1472                                                 while (*p && (*p != ']'))
1473                                                         p++;
1474
1475                                                 if (*p != ']')
1476                                                         return 0;
1477
1478                                                 *p++ = 0;
1479                                                 while (*aname) {
1480                                                         if (g_ascii_isspace (*aname)) {
1481                                                                 ++aname;
1482                                                                 continue;
1483                                                         }
1484                                                         break;
1485                                                 }
1486                                                 if (!*aname ||
1487                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
1488                                                         return 0;
1489                                         } else if (fqname && (*p == ']')) {
1490                                                 *p++ = 0;
1491                                         }
1492                                         if (*p == ']') {
1493                                                 *p++ = 0;
1494                                                 break;
1495                                         } else if (!*p) {
1496                                                 return 0;
1497                                         }
1498                                         *p++ = 0;
1499                                 }
1500                         }
1501                         break;
1502                 case ']':
1503                         if (is_recursed)
1504                                 goto end;
1505                         return 0;
1506                 case ',':
1507                         if (is_recursed)
1508                                 goto end;
1509                         *p++ = 0;
1510                         while (*p) {
1511                                 if (g_ascii_isspace (*p)) {
1512                                         ++p;
1513                                         continue;
1514                                 }
1515                                 break;
1516                         }
1517                         if (!*p)
1518                                 return 0; /* missing assembly name */
1519                         if (!assembly_name_to_aname (&info->assembly, p))
1520                                 return 0;
1521                         break;
1522                 default:
1523                         return 0;
1524                 }
1525                 if (info->assembly.name)
1526                         break;
1527         }
1528         // *w = 0; /* terminate class name */
1529  end:
1530         if (!info->name || !*info->name)
1531                 return 0;
1532         if (endptr)
1533                 *endptr = p;
1534         /* add other consistency checks */
1535         return 1;
1536 }
1537
1538
1539 /**
1540  * mono_identifier_unescape_type_name_chars:
1541  * @identifier: the display name of a mono type
1542  *
1543  * Returns:
1544  *  The name in internal form, that is without escaping backslashes.
1545  *
1546  *  The string is modified in place!
1547  */
1548 char*
1549 mono_identifier_unescape_type_name_chars(char* identifier)
1550 {
1551         char *w, *r;
1552         if (!identifier)
1553                 return NULL;
1554         for (w = r = identifier; *r != 0; r++)
1555         {
1556                 char c = *r;
1557                 if (c == '\\') {
1558                         r++;
1559                         if (*r == 0)
1560                                 break;
1561                         c = *r;
1562                 }
1563                 *w = c;
1564                 w++;
1565         }
1566         if (w != r)
1567                 *w = 0;
1568         return identifier;
1569 }
1570
1571 void
1572 mono_identifier_unescape_info (MonoTypeNameParse* info);
1573
1574 static void
1575 unescape_each_type_argument(void* data, void* user_data)
1576 {
1577         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
1578         mono_identifier_unescape_info (info);
1579 }
1580
1581 static void
1582 unescape_each_nested_name (void* data, void* user_data)
1583 {
1584         char* nested_name = (char*) data;
1585         mono_identifier_unescape_type_name_chars(nested_name);
1586 }
1587
1588 /**
1589  * mono_identifier_unescape_info:
1590  *
1591  * @info: a parsed display form of an (optionally assembly qualified) full type name.
1592  *
1593  * Returns: nothing.
1594  *
1595  * Destructively updates the info by unescaping the identifiers that
1596  * comprise the type namespace, name, nested types (if any) and
1597  * generic type arguments (if any).
1598  *
1599  * The resulting info has the names in internal form.
1600  *
1601  */
1602 void
1603 mono_identifier_unescape_info (MonoTypeNameParse *info)
1604 {
1605         if (!info)
1606                 return;
1607         mono_identifier_unescape_type_name_chars(info->name_space);
1608         mono_identifier_unescape_type_name_chars(info->name);
1609         // but don't escape info->assembly
1610         if (info->type_arguments)
1611                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
1612         if (info->nested)
1613                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
1614 }
1615
1616 int
1617 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
1618 {
1619         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
1620         if (ok) {
1621                 mono_identifier_unescape_info (info);
1622         }
1623         return ok;
1624 }
1625
1626 static MonoType*
1627 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
1628 {
1629         gboolean type_resolve = FALSE;
1630         MonoType *type;
1631         MonoImage *rootimage = image;
1632
1633         mono_error_init (error);
1634
1635         if (info->assembly.name) {
1636                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
1637                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
1638                         /* 
1639                          * This could happen in the AOT compiler case when the search hook is not
1640                          * installed.
1641                          */
1642                         assembly = image->assembly;
1643                 if (!assembly) {
1644                         /* then we must load the assembly ourselve - see #60439 */
1645                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
1646                         if (!assembly)
1647                                 return NULL;
1648                 }
1649                 image = assembly->image;
1650         } else if (!image) {
1651                 image = mono_defaults.corlib;
1652         }
1653
1654         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
1655         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
1656                 /* ignore the error and try again */
1657                 mono_error_cleanup (error);
1658                 mono_error_init (error);
1659                 image = mono_defaults.corlib;
1660                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
1661         }
1662
1663         return type;
1664 }
1665
1666 /**
1667  * mono_reflection_get_type_internal:
1668  *
1669  * Returns: may return NULL on success, sets error on failure.
1670  */
1671 static MonoType*
1672 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
1673 {
1674         MonoClass *klass;
1675         GList *mod;
1676         int modval;
1677         gboolean bounded = FALSE;
1678         
1679         mono_error_init (error);
1680         if (!image)
1681                 image = mono_defaults.corlib;
1682
1683         if (!rootimage)
1684                 rootimage = mono_defaults.corlib;
1685
1686         if (ignorecase)
1687                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
1688         else
1689                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
1690
1691         if (!klass)
1692                 return NULL;
1693
1694         for (mod = info->nested; mod; mod = mod->next) {
1695                 gpointer iter = NULL;
1696                 MonoClass *parent;
1697
1698                 parent = klass;
1699                 mono_class_init (parent);
1700
1701                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
1702                         char *lastp;
1703                         char *nested_name, *nested_nspace;
1704                         gboolean match = TRUE;
1705
1706                         lastp = strrchr ((const char *)mod->data, '.');
1707                         if (lastp) {
1708                                 /* Nested classes can have namespaces */
1709                                 int nspace_len;
1710
1711                                 nested_name = g_strdup (lastp + 1);
1712                                 nspace_len = lastp - (char*)mod->data;
1713                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
1714                                 memcpy (nested_nspace, mod->data, nspace_len);
1715                                 nested_nspace [nspace_len] = '\0';
1716
1717                         } else {
1718                                 nested_name = (char *)mod->data;
1719                                 nested_nspace = NULL;
1720                         }
1721
1722                         if (nested_nspace) {
1723                                 if (ignorecase) {
1724                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
1725                                                 match = FALSE;
1726                                 } else {
1727                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
1728                                                 match = FALSE;
1729                                 }
1730                         }
1731                         if (match) {
1732                                 if (ignorecase) {
1733                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
1734                                                 match = FALSE;
1735                                 } else {
1736                                         if (strcmp (klass->name, nested_name) != 0)
1737                                                 match = FALSE;
1738                                 }
1739                         }
1740                         if (lastp) {
1741                                 g_free (nested_name);
1742                                 g_free (nested_nspace);
1743                         }
1744                         if (match)
1745                                 break;
1746                 }
1747
1748                 if (!klass)
1749                         break;
1750         }
1751         if (!klass)
1752                 return NULL;
1753
1754         if (info->type_arguments) {
1755                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
1756                 MonoReflectionType *the_type;
1757                 MonoType *instance;
1758                 int i;
1759
1760                 for (i = 0; i < info->type_arguments->len; i++) {
1761                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
1762
1763                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
1764                         if (!type_args [i]) {
1765                                 g_free (type_args);
1766                                 return NULL;
1767                         }
1768                 }
1769
1770                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
1771                 if (!the_type)
1772                         return NULL;
1773
1774                 instance = mono_reflection_bind_generic_parameters (
1775                         the_type, info->type_arguments->len, type_args, error);
1776
1777                 g_free (type_args);
1778                 if (!instance)
1779                         return NULL;
1780
1781                 klass = mono_class_from_mono_type (instance);
1782         }
1783
1784         for (mod = info->modifiers; mod; mod = mod->next) {
1785                 modval = GPOINTER_TO_UINT (mod->data);
1786                 if (!modval) { /* byref: must be last modifier */
1787                         return &klass->this_arg;
1788                 } else if (modval == -1) {
1789                         klass = mono_ptr_class_get (&klass->byval_arg);
1790                 } else if (modval == -2) {
1791                         bounded = TRUE;
1792                 } else { /* array rank */
1793                         klass = mono_bounded_array_class_get (klass, modval, bounded);
1794                 }
1795         }
1796
1797         return &klass->byval_arg;
1798 }
1799
1800 /*
1801  * mono_reflection_get_type:
1802  * @image: a metadata context
1803  * @info: type description structure
1804  * @ignorecase: flag for case-insensitive string compares
1805  * @type_resolve: whenever type resolve was already tried
1806  *
1807  * Build a MonoType from the type description in @info.
1808  * 
1809  */
1810
1811 MonoType*
1812 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
1813         MonoError error;
1814         MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
1815         mono_error_cleanup (&error);
1816         return result;
1817 }
1818
1819 /**
1820  * mono_reflection_get_type_checked:
1821  * @rootimage: the image of the currently active managed caller
1822  * @image: a metadata context
1823  * @info: type description structure
1824  * @ignorecase: flag for case-insensitive string compares
1825  * @type_resolve: whenever type resolve was already tried
1826  * @error: set on error.
1827  *
1828  * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
1829  *
1830  */
1831 MonoType*
1832 mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
1833         mono_error_init (error);
1834         return mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, type_resolve, error);
1835 }
1836
1837
1838 static MonoType*
1839 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
1840 {
1841         MonoReflectionAssemblyBuilder *abuilder;
1842         MonoType *type;
1843         int i;
1844
1845         mono_error_init (error);
1846         g_assert (assembly_is_dynamic (assembly));
1847         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
1848         if (!abuilder)
1849                 return NULL;
1850
1851         /* Enumerate all modules */
1852
1853         type = NULL;
1854         if (abuilder->modules) {
1855                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
1856                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
1857                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
1858                         if (type)
1859                                 break;
1860                         if (!mono_error_ok (error))
1861                                 return NULL;
1862                 }
1863         }
1864
1865         if (!type && abuilder->loaded_modules) {
1866                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
1867                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
1868                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
1869                         if (type)
1870                                 break;
1871                         if (!mono_error_ok (error))
1872                                 return NULL;
1873                 }
1874         }
1875
1876         return type;
1877 }
1878         
1879 MonoType*
1880 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
1881 {
1882         MonoType *type;
1883         MonoReflectionAssembly *assembly;
1884         GString *fullName;
1885         GList *mod;
1886
1887         mono_error_init (error);
1888
1889         if (image && image_is_dynamic (image))
1890                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
1891         else {
1892                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
1893         }
1894         return_val_if_nok (error, NULL);
1895
1896         if (type)
1897                 return type;
1898         if (!mono_domain_has_type_resolve (mono_domain_get ()))
1899                 return NULL;
1900
1901         if (type_resolve) {
1902                 if (*type_resolve) 
1903                         return NULL;
1904                 else
1905                         *type_resolve = TRUE;
1906         }
1907         
1908         /* Reconstruct the type name */
1909         fullName = g_string_new ("");
1910         if (info->name_space && (info->name_space [0] != '\0'))
1911                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
1912         else
1913                 g_string_printf (fullName, "%s", info->name);
1914         for (mod = info->nested; mod; mod = mod->next)
1915                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
1916
1917         assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
1918         if (!is_ok (error)) {
1919                 g_string_free (fullName, TRUE);
1920                 return NULL;
1921         }
1922
1923         if (assembly) {
1924                 if (assembly_is_dynamic (assembly->assembly))
1925                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
1926                                                                           info, ignorecase, error);
1927                 else
1928                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
1929                                                                   info, ignorecase, error);
1930         }
1931         g_string_free (fullName, TRUE);
1932         return_val_if_nok (error, NULL);
1933         return type;
1934 }
1935
1936 void
1937 mono_reflection_free_type_info (MonoTypeNameParse *info)
1938 {
1939         g_list_free (info->modifiers);
1940         g_list_free (info->nested);
1941
1942         if (info->type_arguments) {
1943                 int i;
1944
1945                 for (i = 0; i < info->type_arguments->len; i++) {
1946                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
1947
1948                         mono_reflection_free_type_info (subinfo);
1949                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
1950                         g_free (subinfo);
1951                 }
1952
1953                 g_ptr_array_free (info->type_arguments, TRUE);
1954         }
1955 }
1956
1957 /*
1958  * mono_reflection_type_from_name:
1959  * @name: type name.
1960  * @image: a metadata context (can be NULL).
1961  *
1962  * Retrieves a MonoType from its @name. If the name is not fully qualified,
1963  * it defaults to get the type from @image or, if @image is NULL or loading
1964  * from it fails, uses corlib.
1965  * 
1966  */
1967 MonoType*
1968 mono_reflection_type_from_name (char *name, MonoImage *image)
1969 {
1970         MonoError error;
1971         MonoType  *result = mono_reflection_type_from_name_checked (name, image, &error);
1972         mono_error_cleanup (&error);
1973         return result;
1974 }
1975
1976 /**
1977  * mono_reflection_type_from_name_checked:
1978  * @name: type name.
1979  * @image: a metadata context (can be NULL).
1980  * @error: set on errror.
1981  *
1982  * Retrieves a MonoType from its @name. If the name is not fully qualified,
1983  * it defaults to get the type from @image or, if @image is NULL or loading
1984  * from it fails, uses corlib.  On failure returns NULL and sets @error.
1985  * 
1986  */
1987 MonoType*
1988 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
1989 {
1990         MonoType *type = NULL;
1991         MonoTypeNameParse info;
1992         char *tmp;
1993
1994         mono_error_init (error);
1995         /* Make a copy since parse_type modifies its argument */
1996         tmp = g_strdup (name);
1997         
1998         /*g_print ("requested type %s\n", str);*/
1999         if (mono_reflection_parse_type (tmp, &info)) {
2000                 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
2001                 if (!is_ok (error)) {
2002                         g_free (tmp);
2003                         mono_reflection_free_type_info (&info);
2004                         return NULL;
2005                 }
2006         }
2007
2008         g_free (tmp);
2009         mono_reflection_free_type_info (&info);
2010         return type;
2011 }
2012
2013 /*
2014  * mono_reflection_get_token:
2015  *
2016  *   Return the metadata token of OBJ which should be an object
2017  * representing a metadata element.
2018  */
2019 guint32
2020 mono_reflection_get_token (MonoObject *obj)
2021 {
2022         MonoError error;
2023         guint32 result = mono_reflection_get_token_checked (obj, &error);
2024         mono_error_assert_ok (&error);
2025         return result;
2026 }
2027
2028 /**
2029  * mono_reflection_get_token_checked:
2030  * @obj: the object
2031  * @error: set on error
2032  *
2033  *   Return the metadata token of @obj which should be an object
2034  * representing a metadata element.  On failure sets @error.
2035  */
2036 guint32
2037 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
2038 {
2039         MonoClass *klass;
2040         guint32 token = 0;
2041
2042         mono_error_init (error);
2043
2044         klass = obj->vtable->klass;
2045
2046         if (strcmp (klass->name, "MethodBuilder") == 0) {
2047                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
2048
2049                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2050         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
2051                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
2052
2053                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2054         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
2055                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
2056
2057                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
2058         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
2059                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
2060                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
2061         } else if (strcmp (klass->name, "RuntimeType") == 0) {
2062                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
2063                 return_val_if_nok (error, 0);
2064                 MonoClass *mc = mono_class_from_mono_type (type);
2065                 if (!mono_class_init (mc)) {
2066                         mono_error_set_for_class_failure (error, mc);
2067                         return 0;
2068                 }
2069
2070                 token = mc->type_token;
2071         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
2072                            strcmp (klass->name, "MonoMethod") == 0) {
2073                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
2074                 if (m->method->is_inflated) {
2075                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
2076                         return inflated->declaring->token;
2077                 } else {
2078                         token = m->method->token;
2079                 }
2080         } else if (strcmp (klass->name, "MonoField") == 0) {
2081                 MonoReflectionField *f = (MonoReflectionField*)obj;
2082
2083                 token = mono_class_get_field_token (f->field);
2084         } else if (strcmp (klass->name, "MonoProperty") == 0) {
2085                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
2086
2087                 token = mono_class_get_property_token (p->property);
2088         } else if (strcmp (klass->name, "MonoEvent") == 0) {
2089                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
2090
2091                 token = mono_class_get_event_token (p->event);
2092         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
2093                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
2094                 MonoClass *member_class = mono_object_class (p->MemberImpl);
2095                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
2096
2097                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
2098         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
2099                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
2100
2101                 token = m->token;
2102         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
2103                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
2104         } else {
2105                 mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
2106                                                 klass->name_space, klass->name);
2107                 return 0;
2108         }
2109
2110         return token;
2111 }
2112
2113
2114 gboolean
2115 mono_reflection_is_usertype (MonoReflectionType *ref)
2116 {
2117         MonoClass *klass = mono_object_class (ref);
2118         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
2119 }
2120
2121 /**
2122  * mono_reflection_bind_generic_parameters:
2123  * @type: a managed type object (which should be some kind of generic (instance? definition?))
2124  * @type_args: the number of type arguments to bind
2125  * @types: array of type arguments
2126  * @error: set on error
2127  *
2128  * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
2129  * Returns the MonoType* for the resulting type instantiation.  On failure returns NULL and sets @error.
2130  */
2131 MonoType*
2132 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
2133 {
2134         MonoClass *klass;
2135         gboolean is_dynamic = FALSE;
2136         MonoClass *geninst;
2137
2138         mono_error_init (error);
2139         
2140         mono_loader_lock ();
2141
2142         if (mono_is_sre_type_builder (mono_object_class (type))) {
2143                 is_dynamic = TRUE;
2144         } else if (mono_is_sre_generic_instance (mono_object_class (type))) {
2145                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
2146                 MonoReflectionType *gtd = rgi->generic_type;
2147
2148                 if (mono_is_sre_type_builder (mono_object_class (gtd)))
2149                         is_dynamic = TRUE;
2150         }
2151
2152         MonoType *t = mono_reflection_type_get_handle (type, error);
2153         if (!is_ok (error)) {
2154                 mono_loader_unlock ();
2155                 return NULL;
2156         }
2157
2158         klass = mono_class_from_mono_type (t);
2159         if (!mono_class_is_gtd (klass)) {
2160                 mono_loader_unlock ();
2161                 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
2162                 return NULL;
2163         }
2164
2165         guint gtd_type_argc = mono_class_get_generic_container (klass)->type_argc;
2166         if (gtd_type_argc != type_argc) {
2167                 mono_loader_unlock ();
2168                 mono_error_set_argument (error, "types", "The generic type definition needs %d type arguments, but was instantiated with %d ", gtd_type_argc, type_argc);
2169                 return NULL;
2170         }
2171
2172
2173         if (klass->wastypebuilder)
2174                 is_dynamic = TRUE;
2175
2176         mono_loader_unlock ();
2177
2178         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
2179
2180         return &geninst->byval_arg;
2181 }
2182
2183 MonoClass*
2184 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
2185 {
2186         MonoGenericClass *gclass;
2187         MonoGenericInst *inst;
2188
2189         g_assert (mono_class_is_gtd (klass));
2190
2191         inst = mono_metadata_get_generic_inst (type_argc, types);
2192         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
2193
2194         return mono_generic_class_get_class (gclass);
2195 }
2196
2197 static MonoReflectionMethod*
2198 reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types, MonoError *error)
2199 {
2200         MonoClass *klass;
2201         MonoMethod *method, *inflated;
2202         MonoMethodInflated *imethod;
2203         MonoGenericContext tmp_context;
2204         MonoGenericInst *ginst;
2205         MonoType **type_argv;
2206         int count, i;
2207
2208         mono_error_init (error);
2209
2210         g_assert (strcmp (rmethod->object.vtable->klass->name, "MethodBuilder"));
2211
2212         method = rmethod->method;
2213
2214         klass = method->klass;
2215
2216         if (method->is_inflated)
2217                 method = ((MonoMethodInflated *) method)->declaring;
2218
2219         count = mono_method_signature (method)->generic_param_count;
2220         if (count != mono_array_length (types))
2221                 return NULL;
2222
2223         type_argv = g_new0 (MonoType *, count);
2224         for (i = 0; i < count; i++) {
2225                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
2226                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
2227                 if (!is_ok (error)) {
2228                         g_free (type_argv);
2229                         return NULL;
2230                 }
2231         }
2232         ginst = mono_metadata_get_generic_inst (count, type_argv);
2233         g_free (type_argv);
2234
2235         tmp_context.class_inst = mono_class_is_ginst (klass) ? mono_class_get_generic_class (klass)->context.class_inst : NULL;
2236         tmp_context.method_inst = ginst;
2237
2238         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
2239         mono_error_assert_ok (error);
2240         imethod = (MonoMethodInflated *) inflated;
2241
2242         /*FIXME but I think this is no longer necessary*/
2243         if (image_is_dynamic (method->klass->image)) {
2244                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
2245                 /*
2246                  * This table maps metadata structures representing inflated methods/fields
2247                  * to the reflection objects representing their generic definitions.
2248                  */
2249                 mono_image_lock ((MonoImage*)image);
2250                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
2251                 mono_image_unlock ((MonoImage*)image);
2252         }
2253
2254         if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) {
2255                 mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
2256                 return NULL;
2257         }
2258         
2259         return mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, error);
2260 }
2261
2262 MonoReflectionMethod*
2263 ves_icall_MonoMethod_MakeGenericMethod_impl (MonoReflectionMethod *rmethod, MonoArray *types)
2264 {
2265         MonoError error;
2266         MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
2267         mono_error_set_pending_exception (&error);
2268         return result;
2269 }
2270
2271
2272 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
2273 const static guint32 declsec_flags_map[] = {
2274         0x00000000,                                     /* empty */
2275         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
2276         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
2277         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
2278         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
2279         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
2280         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
2281         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
2282         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
2283         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
2284         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
2285         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
2286         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
2287         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
2288         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
2289         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
2290         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
2291         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
2292         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
2293 };
2294
2295 /*
2296  * Returns flags that includes all available security action associated to the handle.
2297  * @token: metadata token (either for a class or a method)
2298  * @image: image where resides the metadata.
2299  */
2300 static guint32
2301 mono_declsec_get_flags (MonoImage *image, guint32 token)
2302 {
2303         int index = mono_metadata_declsec_from_index (image, token);
2304         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
2305         guint32 result = 0;
2306         guint32 action;
2307         int i;
2308
2309         /* HasSecurity can be present for other, not specially encoded, attributes,
2310            e.g. SuppressUnmanagedCodeSecurityAttribute */
2311         if (index < 0)
2312                 return 0;
2313
2314         for (i = index; i < t->rows; i++) {
2315                 guint32 cols [MONO_DECL_SECURITY_SIZE];
2316
2317                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
2318                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
2319                         break;
2320
2321                 action = cols [MONO_DECL_SECURITY_ACTION];
2322                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
2323                         result |= declsec_flags_map [action];
2324                 } else {
2325                         g_assert_not_reached ();
2326                 }
2327         }
2328         return result;
2329 }
2330
2331 /*
2332  * Get the security actions (in the form of flags) associated with the specified method.
2333  *
2334  * @method: The method for which we want the declarative security flags.
2335  * Return the declarative security flags for the method (only).
2336  *
2337  * Note: To keep MonoMethod size down we do not cache the declarative security flags
2338  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
2339  */
2340 guint32
2341 mono_declsec_flags_from_method (MonoMethod *method)
2342 {
2343         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
2344                 /* FIXME: No cache (for the moment) */
2345                 guint32 idx = mono_method_get_index (method);
2346                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
2347                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
2348                 return mono_declsec_get_flags (method->klass->image, idx);
2349         }
2350         return 0;
2351 }
2352
2353 /*
2354  * Get the security actions (in the form of flags) associated with the specified class.
2355  *
2356  * @klass: The class for which we want the declarative security flags.
2357  * Return the declarative security flags for the class.
2358  *
2359  * Note: We cache the flags inside the MonoClass structure as this will get 
2360  *       called very often (at least for each method).
2361  */
2362 guint32
2363 mono_declsec_flags_from_class (MonoClass *klass)
2364 {
2365         if (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_HAS_SECURITY) {
2366                 if (!klass->ext || !klass->ext->declsec_flags) {
2367                         guint32 idx;
2368
2369                         idx = mono_metadata_token_index (klass->type_token);
2370                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
2371                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
2372                         mono_loader_lock ();
2373                         mono_class_alloc_ext (klass);
2374                         mono_loader_unlock ();
2375                         /* we cache the flags on classes */
2376                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
2377                 }
2378                 return klass->ext->declsec_flags;
2379         }
2380         return 0;
2381 }
2382
2383 /*
2384  * Get the security actions (in the form of flags) associated with the specified assembly.
2385  *
2386  * @assembly: The assembly for which we want the declarative security flags.
2387  * Return the declarative security flags for the assembly.
2388  */
2389 guint32
2390 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
2391 {
2392         guint32 idx = 1; /* there is only one assembly */
2393         idx <<= MONO_HAS_DECL_SECURITY_BITS;
2394         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
2395         return mono_declsec_get_flags (assembly->image, idx);
2396 }
2397
2398
2399 /*
2400  * Fill actions for the specific index (which may either be an encoded class token or
2401  * an encoded method token) from the metadata image.
2402  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
2403  */
2404 static MonoBoolean
2405 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
2406         guint32 id_std, guint32 id_noncas, guint32 id_choice)
2407 {
2408         MonoBoolean result = FALSE;
2409         MonoTableInfo *t;
2410         guint32 cols [MONO_DECL_SECURITY_SIZE];
2411         int index = mono_metadata_declsec_from_index (image, token);
2412         int i;
2413
2414         t  = &image->tables [MONO_TABLE_DECLSECURITY];
2415         for (i = index; i < t->rows; i++) {
2416                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
2417
2418                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
2419                         return result;
2420
2421                 /* if present only replace (class) permissions with method permissions */
2422                 /* if empty accept either class or method permissions */
2423                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
2424                         if (!actions->demand.blob) {
2425                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
2426                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
2427                                 actions->demand.blob = (char*) (blob + 2);
2428                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
2429                                 result = TRUE;
2430                         }
2431                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
2432                         if (!actions->noncasdemand.blob) {
2433                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
2434                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
2435                                 actions->noncasdemand.blob = (char*) (blob + 2);
2436                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
2437                                 result = TRUE;
2438                         }
2439                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
2440                         if (!actions->demandchoice.blob) {
2441                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
2442                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
2443                                 actions->demandchoice.blob = (char*) (blob + 2);
2444                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
2445                                 result = TRUE;
2446                         }
2447                 }
2448         }
2449
2450         return result;
2451 }
2452
2453 static MonoBoolean
2454 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
2455         guint32 id_std, guint32 id_noncas, guint32 id_choice)
2456 {
2457         guint32 idx = mono_metadata_token_index (klass->type_token);
2458         idx <<= MONO_HAS_DECL_SECURITY_BITS;
2459         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
2460         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
2461 }
2462
2463 static MonoBoolean
2464 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
2465         guint32 id_std, guint32 id_noncas, guint32 id_choice)
2466 {
2467         guint32 idx = mono_method_get_index (method);
2468         idx <<= MONO_HAS_DECL_SECURITY_BITS;
2469         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
2470         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
2471 }
2472
2473 /*
2474  * Collect all actions (that requires to generate code in mini) assigned for
2475  * the specified method.
2476  * Note: Don't use the content of actions if the function return FALSE.
2477  */
2478 MonoBoolean
2479 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
2480 {
2481         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
2482                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
2483         MonoBoolean result = FALSE;
2484         guint32 flags;
2485
2486         /* quick exit if no declarative security is present in the metadata */
2487         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
2488                 return FALSE;
2489
2490         /* we want the original as the wrapper is "free" of the security informations */
2491         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
2492                 method = mono_marshal_method_from_wrapper (method);
2493                 if (!method)
2494                         return FALSE;
2495         }
2496
2497         /* First we look for method-level attributes */
2498         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
2499                 mono_class_init (method->klass);
2500                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
2501
2502                 result = mono_declsec_get_method_demands_params (method, demands, 
2503                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
2504         }
2505
2506         /* Here we use (or create) the class declarative cache to look for demands */
2507         flags = mono_declsec_flags_from_class (method->klass);
2508         if (flags & mask) {
2509                 if (!result) {
2510                         mono_class_init (method->klass);
2511                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
2512                 }
2513                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
2514                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
2515         }
2516
2517         /* The boolean return value is used as a shortcut in case nothing needs to
2518            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
2519         return result;
2520 }
2521
2522
2523 /*
2524  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
2525  *
2526  * Note: Don't use the content of actions if the function return FALSE.
2527  */
2528 MonoBoolean
2529 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
2530 {
2531         MonoBoolean result = FALSE;
2532         guint32 flags;
2533
2534         /* quick exit if no declarative security is present in the metadata */
2535         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
2536                 return FALSE;
2537
2538         /* we want the original as the wrapper is "free" of the security informations */
2539         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
2540                 method = mono_marshal_method_from_wrapper (method);
2541                 if (!method)
2542                         return FALSE;
2543         }
2544
2545         /* results are independant - zeroize both */
2546         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
2547         memset (klass, 0, sizeof (MonoDeclSecurityActions));
2548
2549         /* First we look for method-level attributes */
2550         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
2551                 mono_class_init (method->klass);
2552
2553                 result = mono_declsec_get_method_demands_params (method, cmethod, 
2554                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
2555         }
2556
2557         /* Here we use (or create) the class declarative cache to look for demands */
2558         flags = mono_declsec_flags_from_class (method->klass);
2559         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
2560                 mono_class_init (method->klass);
2561
2562                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
2563                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
2564         }
2565
2566         return result;
2567 }
2568
2569 /*
2570  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
2571  *
2572  * @klass       The inherited class - this is the class that provides the security check (attributes)
2573  * @demans      
2574  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
2575  * 
2576  * Note: Don't use the content of actions if the function return FALSE.
2577  */
2578 MonoBoolean
2579 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
2580 {
2581         MonoBoolean result = FALSE;
2582         guint32 flags;
2583
2584         /* quick exit if no declarative security is present in the metadata */
2585         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
2586                 return FALSE;
2587
2588         /* Here we use (or create) the class declarative cache to look for demands */
2589         flags = mono_declsec_flags_from_class (klass);
2590         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
2591                 mono_class_init (klass);
2592                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
2593
2594                 result |= mono_declsec_get_class_demands_params (klass, demands, 
2595                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
2596         }
2597
2598         return result;
2599 }
2600
2601 /*
2602  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
2603  *
2604  * Note: Don't use the content of actions if the function return FALSE.
2605  */
2606 MonoBoolean
2607 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
2608 {
2609         /* quick exit if no declarative security is present in the metadata */
2610         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
2611                 return FALSE;
2612
2613         /* we want the original as the wrapper is "free" of the security informations */
2614         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
2615                 method = mono_marshal_method_from_wrapper (method);
2616                 if (!method)
2617                         return FALSE;
2618         }
2619
2620         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
2621                 mono_class_init (method->klass);
2622                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
2623
2624                 return mono_declsec_get_method_demands_params (method, demands, 
2625                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
2626         }
2627         return FALSE;
2628 }
2629
2630
2631 static MonoBoolean
2632 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
2633 {
2634         guint32 cols [MONO_DECL_SECURITY_SIZE];
2635         MonoTableInfo *t;
2636         int i;
2637
2638         int index = mono_metadata_declsec_from_index (image, token);
2639         if (index == -1)
2640                 return FALSE;
2641
2642         t =  &image->tables [MONO_TABLE_DECLSECURITY];
2643         for (i = index; i < t->rows; i++) {
2644                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
2645
2646                 /* shortcut - index are ordered */
2647                 if (token != cols [MONO_DECL_SECURITY_PARENT])
2648                         return FALSE;
2649
2650                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
2651                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
2652                         entry->blob = (char*) (metadata + 2);
2653                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
2654                         return TRUE;
2655                 }
2656         }
2657
2658         return FALSE;
2659 }
2660
2661 MonoBoolean
2662 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
2663 {
2664         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
2665                 guint32 idx = mono_method_get_index (method);
2666                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
2667                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
2668                 return get_declsec_action (method->klass->image, idx, action, entry);
2669         }
2670         return FALSE;
2671 }
2672
2673 MonoBoolean
2674 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
2675 {
2676         /* use cache */
2677         guint32 flags = mono_declsec_flags_from_class (klass);
2678         if (declsec_flags_map [action] & flags) {
2679                 guint32 idx = mono_metadata_token_index (klass->type_token);
2680                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
2681                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
2682                 return get_declsec_action (klass->image, idx, action, entry);
2683         }
2684         return FALSE;
2685 }
2686
2687 MonoBoolean
2688 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
2689 {
2690         guint32 idx = 1; /* there is only one assembly */
2691         idx <<= MONO_HAS_DECL_SECURITY_BITS;
2692         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
2693
2694         return get_declsec_action (assembly->image, idx, action, entry);
2695 }
2696
2697 gboolean
2698 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
2699 {
2700         MonoObject *res, *exc;
2701         void *params [1];
2702         static MonoMethod *method = NULL;
2703
2704         mono_error_init (error);
2705
2706         if (method == NULL) {
2707                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
2708                 g_assert (method);
2709         }
2710
2711         /* 
2712          * The result of mono_type_get_object_checked () might be a System.MonoType but we
2713          * need a TypeBuilder so use mono_class_get_ref_info (klass).
2714          */
2715         g_assert (mono_class_get_ref_info (klass));
2716         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
2717
2718         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
2719         return_val_if_nok (error, FALSE);
2720
2721         MonoError inner_error;
2722         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &inner_error);
2723
2724         if (exc || !is_ok (&inner_error)) {
2725                 mono_error_cleanup (&inner_error);
2726                 return FALSE;
2727         } else
2728                 return *(MonoBoolean*)mono_object_unbox (res);
2729 }
2730
2731 /**
2732  * mono_reflection_type_get_type:
2733  * @reftype: the System.Type object
2734  *
2735  * Returns the MonoType* associated with the C# System.Type object @reftype.
2736  */
2737 MonoType*
2738 mono_reflection_type_get_type (MonoReflectionType *reftype)
2739 {
2740         g_assert (reftype);
2741
2742         MonoError error;
2743         MonoType *result = mono_reflection_type_get_handle (reftype, &error);
2744         mono_error_assert_ok (&error);
2745         return result;
2746 }
2747
2748 /**
2749  * mono_reflection_assembly_get_assembly:
2750  * @refassembly: the System.Reflection.Assembly object
2751  *
2752  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
2753  */
2754 MonoAssembly*
2755 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
2756 {
2757         g_assert (refassembly);
2758
2759         return refassembly->assembly;
2760 }
2761
2762 /**
2763  * mono_class_from_mono_type_handle:
2764  * @reftype: the System.Type handle
2765  *
2766  * Returns the MonoClass* corresponding to the given type.
2767  */
2768 MonoClass*
2769 mono_class_from_mono_type_handle (MonoReflectionTypeHandle reftype)
2770 {
2771         return mono_class_from_mono_type (MONO_HANDLE_RAW (reftype)->type);
2772 }