[assembly] Add mono_assembly_open_predicate function
authorAleksey Kliger <aleksey@xamarin.com>
Mon, 27 Feb 2017 21:31:46 +0000 (16:31 -0500)
committerAleksey Kliger <aleksey@xamarin.com>
Tue, 14 Mar 2017 15:39:02 +0000 (11:39 -0400)
This is an extension of mono_assembly_open_full with a user-supplied predicate
that gets a chance to interrogate the candidate MonoAssembly before it is
consider successfully loaded.

mono/metadata/assembly-internals.h
mono/metadata/assembly.c

index c24e328f33083ff1c3beb8da8736aefe9be59bf7..e40603a388bc170711c858311e2512b978bee770 100644 (file)
@@ -5,10 +5,22 @@
 #ifndef __MONO_METADATA_ASSEMBLY_INTERNALS_H__
 #define __MONO_METADATA_ASSEMBLY_INTERNALS_H__
 
+#include <glib.h>
+
 #include <mono/metadata/assembly.h>
 
 MONO_API MonoImage*    mono_assembly_load_module_checked (MonoAssembly *assembly, uint32_t idx, MonoError *error);
 
 MonoAssembly * mono_assembly_open_a_lot (const char *filename, MonoImageOpenStatus *status, gboolean refonly, gboolean load_from_context);
 
+/* If predicate returns true assembly should be loaded, if false ignore it. */
+typedef gboolean (*MonoAssemblyOpenPredicate)(MonoAssembly *, gpointer);
+
+MonoAssembly*          mono_assembly_open_predicate (const char *filename,
+                                                    gboolean refonly,
+                                                    gboolean load_from_context,
+                                                    MonoAssemblyOpenPredicate pred,
+                                                    gpointer user_data,
+                                                    MonoImageOpenStatus *status);
+
 #endif /* __MONO_METADATA_ASSEMBLY_INTERNALS_H__ */
index 43cc6b44385899e3a842482446831c69c0d687d9..b19793ac2e1a8ad146dbd85042c284a2ece67c28 100644 (file)
@@ -1677,7 +1677,16 @@ mono_assembly_open_full (const char *filename, MonoImageOpenStatus *status, gboo
 MonoAssembly *
 mono_assembly_open_a_lot (const char *filename, MonoImageOpenStatus *status, gboolean refonly, gboolean load_from_context)
 {
+       return mono_assembly_open_predicate (filename, refonly, load_from_context, NULL, NULL, status);
+}
 
+MonoAssembly *
+mono_assembly_open_predicate (const char *filename, gboolean refonly,
+                             gboolean load_from_context,
+                             MonoAssemblyOpenPredicate predicate,
+                             gpointer user_data,
+                             MonoImageOpenStatus *status)
+{
        MonoImage *image;
        MonoAssembly *ass;
        MonoImageOpenStatus def_status;
@@ -1767,11 +1776,21 @@ mono_assembly_open_a_lot (const char *filename, MonoImageOpenStatus *status, gbo
                mono_assembly_invoke_load_hook (image->assembly);
                mono_image_close (image);
                g_free (fname);
-               return image->assembly;
+               if (!predicate || predicate (image->assembly, user_data)) {
+                       return image->assembly;
+               } else {
+                       *status = MONO_IMAGE_IMAGE_INVALID;
+                       return NULL;
+               }
        }
 
        ass = mono_assembly_load_from_full (image, fname, status, refonly);
 
+       if (ass && predicate && !predicate (ass, user_data)) {
+               *status = MONO_IMAGE_IMAGE_INVALID;
+               ass = NULL;
+       }
+
        if (ass) {
                if (!loaded_from_bundle)
                        mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY,
@@ -1948,7 +1967,7 @@ mono_assembly_has_reference_assembly_attribute (MonoAssembly *assembly, MonoErro
 MonoAssembly *
 mono_assembly_open (const char *filename, MonoImageOpenStatus *status)
 {
-       return mono_assembly_open_full (filename, status, FALSE);
+       return mono_assembly_open_predicate (filename, FALSE, FALSE, NULL, NULL, status);
 }
 
 /**