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