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